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.
22 static int acctfd = 0;
24 /* Make a acct entry into the accounting file for accounting.
31 if (write(acctfd, string, strlen(string)) != strlen(string)) {
32 report(LOG_ERR, "%s: couldn't write acct file %s %s",
34 session.acctfile, sys_errlist[errno]);
38 if (debug & DEBUG_ACCT_FLAG)
39 report(LOG_DEBUG, "'%s'", string);
44 /* Write a string or "unknown" into the accounting file.
47 acct_write_field(string)
50 if (string && string[0]) {
51 if (acct_write(string))
54 if (acct_write("unknown"))
65 time_t t = time(NULL);
71 acctfd = open(session.acctfile, O_CREAT | O_WRONLY | O_APPEND,0640);
73 report(LOG_ERR, "Can't open acct file %s -- %s",
74 session.acctfile, sys_errlist[errno]);
79 if (!tac_lockfd(session.acctfile, acctfd)) {
80 rec->admin_msg = tac_strdup("Cannot lock log file");
81 report(LOG_ERR, "%s: Cannot lock %s",
82 session.peer, session.acctfile);
88 errors += acct_write(ct);
89 errors += acct_write("\t");
91 errors += acct_write_field(rec->identity->NAS_name);
92 errors += acct_write("\t");
94 errors += acct_write_field(rec->identity->username);
95 errors += acct_write("\t");
97 errors += acct_write_field(rec->identity->NAS_port);
98 errors += acct_write("\t");
100 errors += acct_write_field(rec->identity->NAC_address);
101 errors += acct_write("\t");
103 switch(rec->acct_type) {
104 case ACCT_TYPE_UPDATE:
105 errors += acct_write("update\t");
107 case ACCT_TYPE_START:
108 errors += acct_write("start\t");
111 errors += acct_write("stop\t");
114 errors += acct_write("unknown\t");
118 for (i=0; i < rec->num_args; i++) {
119 errors += acct_write(rec->args[i]);
120 if (i < (rec->num_args-1))
121 errors += acct_write("\t");
123 errors += acct_write("\n");
135 wtmp_entry (line, name, host, utime)
136 char *line, *name, *host;
145 bzero(&entry, sizeof entry);
147 if (strlen(line) < sizeof entry.ut_line)
148 strcpy(entry.ut_line, line);
149 else bcopy(line, entry.ut_line, sizeof entry.ut_line);
151 if (strlen(name) < sizeof entry.ut_name)
152 strcpy(entry.ut_name, name);
153 else bcopy(name, entry.ut_name, sizeof entry.ut_name);
156 if (strlen(host) < sizeof entry.ut_host)
157 strcpy(entry.ut_host, host);
158 else bcopy(host, entry.ut_host, sizeof entry.ut_host);
160 entry.ut_time = utime;
162 wtmpfd = open(wtmpfile, O_CREAT | O_WRONLY | O_APPEND | O_SYNC, 0644);
164 report(LOG_ERR, "Can't open wtmp file %s -- %s",
165 wtmpfile, sys_errlist[errno]);
169 if (!tac_lockfd(wtmpfile, wtmpfd)) {
170 report(LOG_ERR, "%s: Cannot lock %s", session.peer, wtmpfile);
174 if (write(wtmpfd, &entry, sizeof entry) != (sizeof entry)) {
175 report(LOG_ERR, "%s: couldn't write wtmp file %s %s",
176 session.peer, wtmpfile, sys_errlist[errno]);
182 if (debug & DEBUG_ACCT_FLAG) {
183 report(LOG_DEBUG, "wtmp: %s, %s %s %d", line, name, host, utime);
190 find_attr_value (attr, args, cnt)
196 for (i=0; i < cnt; i++) {
197 if (!strncmp(attr, args[i], strlen(attr))) {
200 for (ptr = args[i]; ptr && *ptr; ptr++) {
201 if ((*ptr == '*') || (*ptr == '=')) {
213 struct acct_rec *rec;
215 time_t now = time(NULL);
217 char *elapsed_time, *start_time;
218 time_t start_utime = 0, stop_utime = 0, elapsed_utime = 0;
221 switch(rec->acct_type) {
222 case ACCT_TYPE_START:
226 case ACCT_TYPE_UPDATE:
231 service = find_attr_value("service", rec->args, rec->num_args);
238 if (STREQ(service, "system")) {
239 if (rec->acct_type == ACCT_TYPE_START) {
241 wtmp_entry("~", "", session.peer, now);
246 if (rec->acct_type != ACCT_TYPE_STOP) {
251 * Since xtacacs logged start records containing the peer address
252 * for a connection, we have to generate them from T+ stop records.
253 * Might as well do this for exec records too.
256 elapsed_time = find_attr_value("elapsed_time", rec->args, rec->num_args);
259 elapsed_utime = strtol(elapsed_time, NULL, 10);
262 start_time = find_attr_value("start_time", rec->args, rec->num_args);
265 * Use the start_time if there is one. If not (e.g. the NAS may
266 * not know the time), assume the stop time is now, and calculate
271 start_utime = strtol(start_time, NULL, 10);
272 stop_utime = start_utime + elapsed_utime;
274 start_utime = now - elapsed_utime;
278 if (STREQ(service, "slip") || STREQ(service, "ppp")) {
279 char *dest_addr = find_attr_value("addr", rec->args, rec->num_args);
281 /* The start record */
282 wtmp_entry(rec->identity->NAS_port,
283 rec->identity->username,
287 /* The stop record */
288 wtmp_entry(rec->identity->NAS_port,
295 if (STREQ(service, "shell")) {
297 wtmp_entry(rec->identity->NAS_port,
298 rec->identity->username,
303 wtmp_entry(rec->identity->NAS_port,