Release bumped to "gts4".
[tac_plus.git] / acct.c
1 /*
2    Copyright (c) 1995-1998 by Cisco systems, Inc.
3
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.
12
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.
18 */
19
20
21 #include "tac_plus.h"
22
23 #include <stdlib.h>
24 #include <netinet/in.h>         /* for ntohl() */
25
26 #include "acct.h"
27 #include "report.h"
28 #include "packet.h"
29 #include "utils.h"
30 #include "do_acct.h"
31 #include "main.h"
32 #include "do_author.h"                  /* for "struct identity" */
33 #include "cfgfile.h"
34
35 #ifdef MAXSESS
36 #include "maxsess.h"
37 #endif
38 #ifdef DB
39 #include "db.h"
40 #endif
41
42
43 static void account TAC_ARGS((u_char *pak));
44
45
46 /*
47  *  Come here when we receive an Start Accounting packet
48  */
49
50 void accounting TAC_ARGS((u_char *pak));
51
52 void
53 accounting(pak)
54 u_char *pak;
55 {
56     struct acct *acct_pak;
57     u_char *p;
58     HDR *hdr;
59     int i;
60     unsigned long len;
61
62     if (debug & DEBUG_ACCT_FLAG)
63         report(LOG_DEBUG, "Start accounting request");
64
65     hdr = (HDR *) pak;
66     acct_pak = (struct acct *) (pak + TAC_PLUS_HDR_SIZE);
67
68     /* Do some sanity checking on the packet */
69
70     /* arg counts start here */
71     p = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REQ_FIXED_FIELDS_SIZE;
72
73     /* Length checks */
74     len = TAC_ACCT_REQ_FIXED_FIELDS_SIZE;
75     len += acct_pak->user_len + acct_pak->port_len +
76         acct_pak->rem_addr_len + acct_pak->arg_cnt;
77     for (i = 0; i < (int)acct_pak->arg_cnt; i++) {
78         len += p[i];
79     }
80
81     if (len != (unsigned long) ntohl(hdr->datalength)) {
82         send_error_reply(TAC_PLUS_ACCT, NULL);
83         return;
84     }
85
86     account(pak);
87
88     free(pak);
89 }
90
91 static void account TAC_ARGS((u_char *pak));
92
93 static void
94 account(pak)
95 u_char *pak;
96 {
97     struct acct *acct_pak;
98     u_char *p, *argsizep;
99     struct acct_rec rec;
100     struct identity identity;
101     char **cmd_argp;
102     int i, errors, status;
103
104     acct_pak = (struct acct *) (pak + TAC_PLUS_HDR_SIZE);
105
106     /* Fill out accounting record structure */
107     bzero(&rec, sizeof(struct acct_rec));
108
109     if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_WATCHDOG)
110         rec.acct_type = ACCT_TYPE_UPDATE;
111     if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_START)
112         rec.acct_type = ACCT_TYPE_START;
113     if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_STOP)
114         rec.acct_type = ACCT_TYPE_STOP;
115
116     rec.authen_method  = acct_pak->authen_method;
117     rec.authen_type    = acct_pak->authen_type;
118     rec.authen_service = acct_pak->authen_service;
119
120     /* start of variable length data is here */
121     p = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REQ_FIXED_FIELDS_SIZE;
122
123     /* skip arg cnts */
124     p += acct_pak->arg_cnt;
125
126     /* zero out identity struct */
127     bzero(&identity, sizeof(struct identity));
128
129     identity.username = tac_make_string(p, (int)acct_pak->user_len);
130     p += acct_pak->user_len;
131
132     identity.NAS_name = tac_strdup(session.peer);
133
134     identity.NAS_port = tac_make_string(p, (int)acct_pak->port_len);
135     p += acct_pak->port_len;
136     if (acct_pak->port_len <= 0) {
137         strcpy(session.port, "unknown-port");
138     } else {
139         strcpy(session.port, identity.NAS_port);
140     }
141
142     identity.NAC_address = tac_make_string(p, (int)acct_pak->rem_addr_len);
143     p += acct_pak->rem_addr_len;
144
145     identity.priv_lvl = acct_pak->priv_lvl;
146
147     cfg_request_identity(&identity);
148
149     rec.identity = &identity;
150
151     /* Now process cmd args */
152     argsizep = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REQ_FIXED_FIELDS_SIZE;
153
154     cmd_argp = (char **) tac_malloc(acct_pak->arg_cnt * sizeof(char *));
155
156     for (i = 0; i < (int)acct_pak->arg_cnt; i++) {
157         cmd_argp[i] = tac_make_string(p, *argsizep);
158         p += *argsizep++;
159     }
160
161     rec.args = cmd_argp;
162     rec.num_args = acct_pak->arg_cnt;
163
164 #ifdef MAXSESS
165     /*
166      * Tally for MAXSESS counting
167      */
168     loguser(&rec);
169 #endif
170
171     /*
172      * Do accounting.
173      */
174     if (wtmpfile) {
175         errors = do_wtmp(&rec);
176     } else {
177         errors = do_acct(&rec);
178 #ifdef DB
179     if (session.db_acct && rec.acct_type==ACCT_TYPE_STOP )
180         db_acct(&rec);
181 #endif
182         }
183
184     if (errors) {
185         status = TAC_PLUS_ACCT_STATUS_ERROR;
186     } else {
187         status = TAC_PLUS_ACCT_STATUS_SUCCESS;
188     }
189     send_acct_reply(status, rec.msg, rec.admin_msg);
190
191     free(identity.username);
192     free(identity.NAS_name);
193     free(identity.NAS_port);
194     free(identity.NAC_address);
195
196     for (i = 0; i < (int)acct_pak->arg_cnt; i++) {
197         free(cmd_argp[i]);
198     }
199     free(cmd_argp);
200
201     if (rec.msg)
202         free(rec.msg);
203     if (rec.admin_msg)
204         free(rec.admin_msg);
205 }