2 Copyright (c) 1995-1998 by Cisco systems, Inc.
4 Permission to use, copy, modify, and distribute this software for
5 any purpose and without fee is hereby granted, provided that this
6 copyright and permission notice appear on all copies of the
7 software and supporting documentation, the name of Cisco Systems,
8 Inc. not be used in advertising or publicity pertaining to
9 distribution of the program without specific prior permission, and
10 notice be given in supporting documentation that modification,
11 copying and distribution is by permission of Cisco Systems, Inc.
13 Cisco Systems, Inc. makes no representations about the suitability
14 of this software for any purpose. THIS SOFTWARE IS PROVIDED ``AS
15 IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
16 WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS FOR A PARTICULAR PURPOSE.
26 #include <sys/types.h>
41 #include "do_author.h" /* for "struct identity" */
44 char *wtmpfile = NULL; /* for wtmp file logging */
47 static int wtmpfd = 0;
48 static int acctfd = 0;
50 /* Make a acct entry into the accounting file for accounting.
53 static int acct_write TAC_ARGS((char *string));
59 if ((unsigned long)write(acctfd, string, strlen(string)) != strlen(string)) {
60 report(LOG_ERR, "%s: couldn't write acct file %s %s",
62 session.acctfile, sys_errlist[errno]);
66 if (debug & DEBUG_ACCT_FLAG)
67 report(LOG_DEBUG, "'%s'", string);
72 static int acct_write_field TAC_ARGS((char *string));
74 /* Write a string or "unknown" into the accounting file.
77 acct_write_field(string)
80 if (string && string[0]) {
81 if (acct_write(string))
84 if (acct_write("unknown"))
90 int do_acct TAC_ARGS((struct acct_rec *rec));
97 time_t t = time(NULL);
103 acctfd = open(session.acctfile, O_CREAT | O_WRONLY | O_APPEND,0640);
105 report(LOG_ERR, "Can't open acct file %s -- %s",
106 session.acctfile, sys_errlist[errno]);
111 if (!tac_lockfd(session.acctfile, acctfd)) {
112 rec->admin_msg = tac_strdup("Cannot lock log file");
113 report(LOG_ERR, "%s: Cannot lock %s",
114 session.peer, session.acctfile);
120 errors += acct_write(ct);
121 errors += acct_write("\t");
123 errors += acct_write_field(rec->identity->NAS_name);
124 errors += acct_write("\t");
126 errors += acct_write_field(rec->identity->username);
127 errors += acct_write("\t");
129 errors += acct_write_field(rec->identity->NAS_port);
130 errors += acct_write("\t");
132 errors += acct_write_field(rec->identity->NAC_address);
133 errors += acct_write("\t");
135 switch(rec->acct_type) {
136 case ACCT_TYPE_UPDATE:
137 errors += acct_write("update\t");
139 case ACCT_TYPE_START:
140 errors += acct_write("start\t");
143 errors += acct_write("stop\t");
146 errors += acct_write("unknown\t");
150 for (i=0; i < rec->num_args; i++) {
151 errors += acct_write(rec->args[i]);
152 if (i < (rec->num_args-1))
153 errors += acct_write("\t");
155 errors += acct_write("\n");
166 static int wtmp_entry TAC_ARGS((char *line, char *name, char *host, time_t utime));
169 wtmp_entry (line, name, host, utime)
170 char *line, *name, *host;
179 bzero(&entry, sizeof entry);
181 if (strlen(line) < sizeof entry.ut_line)
182 strcpy(entry.ut_line, line);
183 else bcopy(line, entry.ut_line, sizeof entry.ut_line);
185 if (strlen(name) < sizeof entry.ut_name)
186 strcpy(entry.ut_name, name);
187 else bcopy(name, entry.ut_name, sizeof entry.ut_name);
189 #ifdef HAVE_UTMP_UT_HOST
190 if (strlen(host) < sizeof entry.ut_host)
191 strcpy(entry.ut_host, host);
192 else bcopy(host, entry.ut_host, sizeof entry.ut_host);
194 entry.ut_time = utime;
196 wtmpfd = open(wtmpfile, O_CREAT | O_WRONLY | O_APPEND | O_SYNC, 0644);
198 report(LOG_ERR, "Can't open wtmp file %s -- %s",
199 wtmpfile, sys_errlist[errno]);
203 if (!tac_lockfd(wtmpfile, wtmpfd)) {
204 report(LOG_ERR, "%s: Cannot lock %s", session.peer, wtmpfile);
208 if (write(wtmpfd, &entry, sizeof entry) != (sizeof entry)) {
209 report(LOG_ERR, "%s: couldn't write wtmp file %s %s",
210 session.peer, wtmpfile, sys_errlist[errno]);
216 if (debug & DEBUG_ACCT_FLAG) {
217 report(LOG_DEBUG, "wtmp: %s, %s %s %ld", line, name, host, (long)utime);
223 char *find_attr_value TAC_ARGS((char *attr, char **args, int cnt));
226 find_attr_value (attr, args, cnt)
232 for (i=0; i < cnt; i++) {
233 if (!strncmp(attr, args[i], strlen(attr))) {
236 for (ptr = args[i]; ptr && *ptr; ptr++) {
237 if ((*ptr == '*') || (*ptr == '=')) {
247 int do_wtmp TAC_ARGS((struct acct_rec *rec));
251 struct acct_rec *rec;
253 time_t now = time(NULL);
255 char *elapsed_time, *start_time;
256 time_t start_utime = 0, stop_utime = 0, elapsed_utime = 0;
259 switch(rec->acct_type) {
260 case ACCT_TYPE_START:
264 case ACCT_TYPE_UPDATE:
269 service = find_attr_value("service", rec->args, rec->num_args);
276 if (STREQ(service, "system")) {
277 if (rec->acct_type == ACCT_TYPE_START) {
279 wtmp_entry("~", "", session.peer, now);
284 if (rec->acct_type != ACCT_TYPE_STOP) {
289 * Since xtacacs logged start records containing the peer address
290 * for a connection, we have to generate them from T+ stop records.
291 * Might as well do this for exec records too.
294 elapsed_time = find_attr_value("elapsed_time", rec->args, rec->num_args);
297 elapsed_utime = strtol(elapsed_time, NULL, 10);
300 start_time = find_attr_value("start_time", rec->args, rec->num_args);
303 * Use the start_time if there is one. If not (e.g. the NAS may
304 * not know the time), assume the stop time is now, and calculate
309 start_utime = strtol(start_time, NULL, 10);
310 stop_utime = start_utime + elapsed_utime;
312 start_utime = now - elapsed_utime;
316 if (STREQ(service, "slip") || STREQ(service, "ppp")) {
317 char *dest_addr = find_attr_value("addr", rec->args, rec->num_args);
319 /* The start record */
320 wtmp_entry(rec->identity->NAS_port,
321 rec->identity->username,
325 /* The stop record */
326 wtmp_entry(rec->identity->NAS_port,
333 if (STREQ(service, "shell")) {
335 wtmp_entry(rec->identity->NAS_port,
336 rec->identity->username,
341 wtmp_entry(rec->identity->NAS_port,