Import of tac_plus.v8.tar.gz: 173206 bytes, md5:
[tac_plus.git] / db.c
1 /*
2      Verify that this user/password is valid per a database.
3      Return 1 if verified, 0 otherwise.
4      
5      Format of connection string (look like internet URL):
6
7        db://user:password@hostname/table?name&passwd
8
9      Example connect to Oracle RDBMS at user 'roger' with password
10      'tiger', to 'host.domain.com' database server, fields name in
11      table is 'name' and 'passwd' in 'oshadow' table:
12
13        oracle://roger:tiger@host.domain.com/oshadow?name&passwd
14
15      DONE:
16      12-nov-1998 Created
17                  Add DB support to 'login = db <string>'
18      14-nov-1998 Change Tacacs+ version from 0.95 to 3.0.9
19      18-nov-1998 Added code for Oracle [version 8.0.5]
20      27-nov-1998 Tested with 30'000 usernames Oracle database
21                  Added DB support to global configuration
22                  'default authentication = db <string>'
23      28-nov-1998 Added code for NULL database %)
24      14-dec-1999 Add code for MySQL and also more check
25      
26      FUTURE:
27      Make *_db_verify() the functions is reenterable
28      More security for connection to database
29      GDBM support
30      Separate debug logging
31      Perfomance testing on 10000 records in Oracle database
32      (in guide sayd about 3 auth/sec on Ultra 2 - hmm)
33      
34      -------------------------------------------------------
35      fil@artelecom.ru                   http://twister.pp.ru
36  
37  ****************************************************************************
38                                     PART II
39
40    I am added some extra extension. Like MySQL and PostgreSQL database support
41    And change most of lines for use dynamic memory allocation. db_accounting 
42    added by me.
43   
44    devrim(devrim@gazi.edu.tr)
45 */
46
47 #if defined(DB)
48 #include <stdio.h>
49 #include "tac_plus.h"
50 /* The databases  recognized by this function */
51 #define DEFINED_DB {"null","mysql","pgsql"}
52
53 char *find_attr_value(); 
54
55 int
56 db_verify(user, users_passwd, str_conn)
57 char *user, *users_passwd;      /* Username and gived password   */
58 char *str_conn;                 /* String connection to database */
59 {
60     char *buffer;
61     char *db_pref, *db_user, *db_password;
62     char *db_hostname, *db_table,*db_name,*dbfield_name, *dbfield_passwd;
63     int ret;
64
65     if (debug & DEBUG_PASSWD_FLAG)
66         report(LOG_DEBUG, "verify %s by database at %s", user, str_conn);
67
68     buffer = db_pref = (char *)malloc( strlen(str_conn) + 1 );
69     if( buffer == NULL ){
70         report(LOG_DEBUG, "Error allocation memory");
71         return(0);
72     }
73
74     strcpy( buffer, str_conn );
75
76     db_user = (char *)strstr( db_pref, "://" );
77     if( db_user == NULL ){
78         if (debug & DEBUG_PASSWD_FLAG)
79             report(LOG_DEBUG, "Error parse db_user");
80             free(buffer);
81             return(0);
82     }
83     *db_user = '\0'; 
84
85         /* For recognize db authentication database */
86     
87     if (check_db_type(db_pref)) {
88         report(LOG_DEBUG, "%s DB authentication scheme didn't recognize by tac_plus",db_pref);
89         free(buffer);
90         return(0);
91     }
92
93     db_user += 3;
94
95     db_password = (char *)strstr( db_user, ":" );
96     if( db_password == NULL ){
97         if (debug & DEBUG_PASSWD_FLAG)
98              report(LOG_DEBUG, "Error parse db_password");
99         free(buffer);
100         return(0);
101     }
102     *db_password = '\0';
103     db_password++;
104     
105     db_hostname = (char *)strstr( db_password, "@" );
106     if( db_hostname == NULL ){
107         if (debug & DEBUG_PASSWD_FLAG)
108             report(LOG_DEBUG, "Error parse db_hostname");
109         free(buffer);
110         return(0);
111     }
112     *db_hostname = '\0';
113     db_hostname++;
114     
115     db_name = (char *)strstr( db_hostname, "/" );
116     if( db_name == NULL ){
117         if (debug & DEBUG_PASSWD_FLAG)
118             report(LOG_DEBUG, "Error parse db_name");
119         free(buffer);
120         return(0);
121     } 
122     *db_name = '\0';
123     db_name++;
124     
125     db_table = (char *)strstr( db_name, "/" );
126     if( db_table == NULL ){
127         if (debug & DEBUG_PASSWD_FLAG)
128             report(LOG_DEBUG, "Error parse db_table");
129         free(buffer);
130         return(0);
131     } 
132     *db_table = '\0';
133     db_table++;
134     
135     dbfield_name = (char *)strstr( db_table, "?" );
136     if( dbfield_name == NULL){
137         if (debug & DEBUG_PASSWD_FLAG)
138             report(LOG_DEBUG, "Error parse dbfield_name");
139         free(buffer);
140         return(0);
141     }
142     *dbfield_name = '\0';
143     dbfield_name++;
144
145
146     dbfield_passwd = (char *)strstr( dbfield_name, "&" );
147     if( dbfield_passwd == NULL){
148         if (debug & DEBUG_PASSWD_FLAG)
149             report(LOG_DEBUG, "Error parse dbfield_passwd");
150         free(buffer);
151         return(0);
152     }
153     *dbfield_passwd = '\0';
154     dbfield_passwd++;
155     
156
157     /* Parse database connection string */
158         if (debug & DEBUG_PASSWD_FLAG)
159             report(LOG_DEBUG, "db_verify: db_pref=%s, db_user=%s, db_password=%s db_hostname=%s, db_name=%s ,db_table=%s, dbfield_name=%s, dbfield_passwd=%s", db_pref, db_user, db_password, db_hostname, db_name,db_table, dbfield_name, dbfield_passwd);
160
161     /* Check for empty passwords */
162    if (users_passwd == NULL || *users_passwd == '\0' ||
163         db_password == NULL || *db_password == '\0' ) {
164         if (debug & DEBUG_PASSWD_FLAG)
165            report(LOG_DEBUG, "One from passwords is empty");
166         free(buffer);
167         return (0);
168     }
169
170     ret = 0;
171
172     /* Run database depend function */
173 #if defined(DB_ORACLE)
174     if (!strcmp(db_pref, "oracle")) {
175         ret = oracle_db_verify(
176             user, users_passwd,
177             db_user, db_password, db_hostname, db_table,
178             dbfield_name, dbfield_passwd);
179     }
180 #endif
181
182 #if defined(DB_MYSQL)
183     if (!strcmp(db_pref, "mysql")) {
184         ret = mysql_db_verify(
185             user, users_passwd,
186             db_user, db_password, db_hostname, db_name, db_table,
187             dbfield_name, dbfield_passwd);
188     }
189 #endif
190
191 #if defined(DB_PGSQL)
192     if (!strcmp(db_pref, "pgsql")) {
193         ret = pgsql_db_verify(
194             user, users_passwd,
195             db_user, db_password, db_hostname,db_name, db_table,
196             dbfield_name, dbfield_passwd);
197     }
198 #endif
199
200 #if defined(DB_NULL)
201     if (!strcmp(db_pref, "null")) {
202         ret = null_db_verify(
203             user, users_passwd,
204             db_user, db_password, db_hostname ,db_table,
205             dbfield_name, dbfield_passwd);
206     }
207 #endif
208
209 #if defined(DB_GDBM)
210     if (!strcmp(db_pref, "gdbm")) {
211         gdb_db_verify();
212     }
213 #endif
214     free(buffer); /* Free unused memory */
215     return (ret); /* error */
216 }
217
218
219 /* Db accounting routine */
220 int
221 db_acct(rec)
222 struct acct_rec *rec;
223 {
224     char *buffer;
225     char *db_pref, *db_user, *db_password;
226     char *db_hostname, *db_name,*db_table;
227     char *a_username,*s_name,*c_name,*elapsed_time,*bytes_in,*bytes_out;
228     int ret;
229
230     buffer = db_pref = (char *)malloc( strlen(session.db_acct) + 1 );
231         
232     if( buffer == NULL ){
233         report(LOG_DEBUG, "Error allocation memory");
234         return(0);
235     }
236
237     strcpy( buffer, session.db_acct);
238
239     db_user = (char *)strstr( db_pref, "://" );
240     if( db_user == NULL ){
241         if (debug & DEBUG_PASSWD_FLAG)
242             report(LOG_DEBUG, "Error parse db_user");
243         free(buffer);
244         return(0);
245     }
246     *db_user = '\0'; 
247
248         /* For recognize db accouting database */
249     
250     if( check_db_type(db_pref) ) {
251         report(LOG_DEBUG, "%s DB accounting scheme didn't recognize by tac_plus",db_pref);
252         free(buffer);
253         return(0);
254     }
255
256     db_user += 3;
257
258     db_password = (char *)strstr( db_user, ":" );
259     if( db_password == NULL ){
260         if (debug & DEBUG_PASSWD_FLAG)
261             report(LOG_DEBUG, "Error parse db_password");
262         free(buffer);
263         return(0);
264     }
265     *db_password = '\0';
266     db_password++;
267     
268     db_hostname = (char *)strstr( db_password, "@" );
269     if( db_hostname == NULL ){
270         if (debug & DEBUG_PASSWD_FLAG)
271             report(LOG_DEBUG, "Error parse db_hostname");
272         free(buffer);
273         return(0);
274     }
275     *db_hostname = '\0';
276     db_hostname++;
277     
278     db_name = (char *)strstr( db_hostname, "/" );
279     if( db_name == NULL ){
280         if (debug & DEBUG_PASSWD_FLAG)
281             report(LOG_DEBUG, "Error parse db_name");
282         free(buffer);
283         return(0);
284     } 
285     *db_name = '\0';
286     db_name++;
287     
288     db_table = (char *)strstr( db_name, "/" );
289     if( db_table == NULL ){
290         if (debug & DEBUG_PASSWD_FLAG)
291             report(LOG_DEBUG, "Error parse db_table");
292         free(buffer);
293         return(0);
294     } 
295     *db_table = '\0';
296     db_table++;
297
298 /* Find some attributes  for accounting */
299     a_username=rec->identity->username;
300         if (a_username==NULL ) {
301                 if (debug & DEBUG_PASSWD_FLAG) 
302                         report(LOG_DEBUG,"db_acct: Can't find username!");
303                         free(buffer);
304                         return(0);
305         }
306     s_name=rec->identity->NAS_name;
307         if (s_name==NULL) {
308                 if (debug & DEBUG_PASSWD_FLAG) 
309                         report(LOG_DEBUG,"db_acct: Can't find NAS name!");
310                         free(buffer);
311                         return(0);
312         }
313     c_name=find_attr_value("addr", rec->args, rec->num_args);
314         if (c_name==NULL) {
315                 if (debug & DEBUG_PASSWD_FLAG) 
316                         report(LOG_DEBUG,"db_acct: Can't find client adress!");
317         /* Can't find client adress so give NAC_address attribute value */ 
318                 c_name=rec->identity->NAC_address;
319         }
320     elapsed_time=find_attr_value("elapsed_time", rec->args, rec->num_args);
321         if (elapsed_time==NULL) {
322                 if (debug & DEBUG_PASSWD_FLAG) 
323                         report(LOG_DEBUG,"db_acct: Can't get elapsed time!");
324                         free(buffer);
325                         return(0);
326         }
327     bytes_in=find_attr_value("bytes_in", rec->args, rec->num_args);
328         if (bytes_in==NULL) bytes_in="0";
329     bytes_out=find_attr_value("bytes_out", rec->args, rec->num_args);
330         if (bytes_out==NULL) bytes_out="0";
331
332
333     /* Parse database connection string */
334         if (debug & DEBUG_PASSWD_FLAG)
335             report(LOG_DEBUG, "db_verify: db_pref=%s, db_user=%s,db_password=%s , db_hostname=%s, db_name=%s ,db_table=%s ",
336                 db_pref, db_user, db_password,
337                 db_hostname, db_name,db_table );
338
339     /* Check for empty passwords */
340    if (db_user == NULL || db_password == '\0' ) {
341         if (debug & DEBUG_PASSWD_FLAG)
342            report(LOG_DEBUG, "One from passwords is empty");
343         free(buffer);
344         return (0);
345     }
346
347     ret = 0;
348     /* Run database depend function */
349 #if defined(DB_ORACLE)
350     if (!strcmp(db_pref, "oracle")) {
351         ret = oracle_db_acct(
352             db_user, db_password, db_hostname, db_name, db_table);
353     }
354 #endif
355
356 #if defined(DB_MYSQL)
357     if (!strcmp(db_pref, "mysql")) {
358         ret = mysql_db_acct(
359             db_user, db_password, db_hostname, db_name, db_table,s_name,c_name,a_username,elapsed_time,bytes_in,bytes_out);
360     }
361 #endif
362
363 #if defined(DB_PGSQL)
364     if (!strcmp(db_pref, "pgsql")) {
365         ret = pgsql_db_acct(
366             db_user, db_password, db_hostname, db_name, db_table,s_name,c_name,a_username,elapsed_time,bytes_in,bytes_out);
367     }
368 #endif
369
370 #if defined(DB_NULL)
371     if (!strcmp(db_pref, "null")) {
372         ret = null_db_acct(
373             db_user, db_password, db_hostname, db_name, db_table,s_name,c_name,a_username,elapsed_time,bytes_in,bytes_out);
374     }
375 #endif
376 #if defined(DB_GDBM)
377     if (!strcmp(db_pref, "gdbm")) {
378         gdb_db_acct();
379     }
380 #endif
381
382     free(buffer); /* Free unused memory */
383     return (ret); /* error */
384
385 }
386
387 /* For checking DB type */
388 int 
389 check_db_type(db_type)
390 char *db_type;
391 {
392 char *dbp[]=DEFINED_DB;
393 int ret=1,i;
394
395 for (i=0; dbp[i] ; i++ ) {
396         if(!strcmp(db_type,dbp[i])) {
397                 ret=0;
398                 break;
399         }
400 }
401 return ret;
402 }
403 #endif /* DB */