Release bumped to "gts4".
[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
48 #include "tac_plus.h"
49
50 #ifdef DB
51
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55
56 #include "db.h"
57 #include "report.h"
58 #include "do_acct.h"
59 #include "main.h"
60 #include "do_author.h"                  /* for "struct identity" */
61 #include "utils.h"
62
63
64 #ifdef DB_MYSQL
65 #include "db_mysql.h"
66 #endif
67 #ifdef DB_NULL
68 #include "db_null.h"
69 #endif
70 #ifdef DB_PGSQL
71 #include "db_pgsql.h"
72 #endif
73
74
75 static int check_db_type TAC_ARGS((char *db_type));
76
77
78 /* The databases  recognized by this function */
79 #define DEFINED_DB {"null","mysql","pgsql"}
80
81 int db_verify TAC_ARGS((const char *user, const char *users_passwd, const char *str_conn));
82
83 int
84 db_verify(user, users_passwd, str_conn)
85 const char *user;                       /* username ... */
86 const char *users_passwd;               /* ... and given password */
87 const char *str_conn;                   /* string connection to database */
88 {
89     char *buffer;
90     char *db_pref, *db_user, *db_password;
91     char *db_hostname, *db_table,*db_name,*dbfield_name, *dbfield_passwd;
92     int ret;
93
94     if (debug & DEBUG_PASSWD_FLAG)
95         report(LOG_DEBUG, "verify %s by database at %s", user, str_conn);
96
97     buffer = db_pref = (char *) tac_malloc( strlen(str_conn) + 1 );
98
99     strcpy( buffer, str_conn );
100
101     db_user = (char *)strstr( db_pref, "://" );
102     if( db_user == NULL ){
103         if (debug & DEBUG_PASSWD_FLAG)
104             report(LOG_DEBUG, "Error parse db_user");
105             free(buffer);
106             return(0);
107     }
108     *db_user = '\0';
109
110         /* For recognize db authentication database */
111
112     if (check_db_type(db_pref)) {
113         report(LOG_DEBUG, "%s DB authentication scheme didn't recognize by tac_plus",db_pref);
114         free(buffer);
115         return(0);
116     }
117
118     db_user += 3;
119
120     db_password = (char *)strstr( db_user, ":" );
121     if( db_password == NULL ){
122         if (debug & DEBUG_PASSWD_FLAG)
123              report(LOG_DEBUG, "Error parse db_password");
124         free(buffer);
125         return(0);
126     }
127     *db_password = '\0';
128     db_password++;
129
130     db_hostname = (char *)strstr( db_password, "@" );
131     if( db_hostname == NULL ){
132         if (debug & DEBUG_PASSWD_FLAG)
133             report(LOG_DEBUG, "Error parse db_hostname");
134         free(buffer);
135         return(0);
136     }
137     *db_hostname = '\0';
138     db_hostname++;
139
140     db_name = (char *)strstr( db_hostname, "/" );
141     if( db_name == NULL ){
142         if (debug & DEBUG_PASSWD_FLAG)
143             report(LOG_DEBUG, "Error parse db_name");
144         free(buffer);
145         return(0);
146     }
147     *db_name = '\0';
148     db_name++;
149
150     db_table = (char *)strstr( db_name, "/" );
151     if( db_table == NULL ){
152         if (debug & DEBUG_PASSWD_FLAG)
153             report(LOG_DEBUG, "Error parse db_table");
154         free(buffer);
155         return(0);
156     }
157     *db_table = '\0';
158     db_table++;
159
160     dbfield_name = (char *)strstr( db_table, "?" );
161     if( dbfield_name == NULL){
162         if (debug & DEBUG_PASSWD_FLAG)
163             report(LOG_DEBUG, "Error parse dbfield_name");
164         free(buffer);
165         return(0);
166     }
167     *dbfield_name = '\0';
168     dbfield_name++;
169
170
171     dbfield_passwd = (char *)strstr( dbfield_name, "&" );
172     if( dbfield_passwd == NULL){
173         if (debug & DEBUG_PASSWD_FLAG)
174             report(LOG_DEBUG, "Error parse dbfield_passwd");
175         free(buffer);
176         return(0);
177     }
178     *dbfield_passwd = '\0';
179     dbfield_passwd++;
180
181
182     /* Parse database connection string */
183         if (debug & DEBUG_PASSWD_FLAG)
184             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);
185
186     /* Check for empty passwords */
187    if (users_passwd == NULL || *users_passwd == '\0' ||
188         db_password == NULL || *db_password == '\0' ) {
189         if (debug & DEBUG_PASSWD_FLAG)
190            report(LOG_DEBUG, "One from passwords is empty");
191         free(buffer);
192         return (0);
193     }
194
195     ret = 0;
196
197     /* Run database depend function */
198 #if defined(DB_ORACLE)
199     if (!strcmp(db_pref, "oracle")) {
200         ret = oracle_db_verify(
201             user, users_passwd,
202             db_user, db_password, db_hostname, db_table,
203             dbfield_name, dbfield_passwd);
204     }
205 #endif
206
207 #if defined(DB_MYSQL)
208     if (!strcmp(db_pref, "mysql")) {
209         ret = mysql_db_verify(
210             user, users_passwd,
211             db_user, db_password, db_hostname, db_name, db_table,
212             dbfield_name, dbfield_passwd);
213     }
214 #endif
215
216 #if defined(DB_PGSQL)
217     if (!strcmp(db_pref, "pgsql")) {
218         ret = pgsql_db_verify(
219             user, users_passwd,
220             db_user, db_password, db_hostname,db_name, db_table,
221             dbfield_name, dbfield_passwd);
222     }
223 #endif
224
225 #if defined(DB_NULL)
226     if (!strcmp(db_pref, "null")) {
227         ret = null_db_verify(
228             user, users_passwd,
229             db_user, db_password, db_hostname ,db_table,
230             dbfield_name, dbfield_passwd);
231     }
232 #endif
233
234 #if defined(DB_GDBM)
235     if (!strcmp(db_pref, "gdbm")) {
236         gdb_db_verify();
237     }
238 #endif
239     free(buffer); /* Free unused memory */
240     return (ret); /* error */
241 }
242
243
244 int db_acct TAC_ARGS((struct acct_rec *rec));
245
246 /* Db accounting routine */
247 int
248 db_acct(rec)
249 struct acct_rec *rec;
250 {
251     char *buffer;
252     char *db_pref, *db_user, *db_password;
253     char *db_hostname, *db_name,*db_table;
254     char *a_username,*s_name,*c_name,*elapsed_time,*bytes_in,*bytes_out;
255     int ret;
256
257     buffer = db_pref = (char *) tac_malloc( strlen(session.db_acct) + 1 );
258
259     strcpy( buffer, session.db_acct);
260
261     db_user = (char *)strstr( db_pref, "://" );
262     if( db_user == NULL ){
263         if (debug & DEBUG_PASSWD_FLAG)
264             report(LOG_DEBUG, "Error parse db_user");
265         free(buffer);
266         return(0);
267     }
268     *db_user = '\0';
269
270         /* For recognize db accouting database */
271
272     if( check_db_type(db_pref) ) {
273         report(LOG_DEBUG, "%s DB accounting scheme didn't recognize by tac_plus",db_pref);
274         free(buffer);
275         return(0);
276     }
277
278     db_user += 3;
279
280     db_password = (char *)strstr( db_user, ":" );
281     if( db_password == NULL ){
282         if (debug & DEBUG_PASSWD_FLAG)
283             report(LOG_DEBUG, "Error parse db_password");
284         free(buffer);
285         return(0);
286     }
287     *db_password = '\0';
288     db_password++;
289
290     db_hostname = (char *)strstr( db_password, "@" );
291     if( db_hostname == NULL ){
292         if (debug & DEBUG_PASSWD_FLAG)
293             report(LOG_DEBUG, "Error parse db_hostname");
294         free(buffer);
295         return(0);
296     }
297     *db_hostname = '\0';
298     db_hostname++;
299
300     db_name = (char *)strstr( db_hostname, "/" );
301     if( db_name == NULL ){
302         if (debug & DEBUG_PASSWD_FLAG)
303             report(LOG_DEBUG, "Error parse db_name");
304         free(buffer);
305         return(0);
306     }
307     *db_name = '\0';
308     db_name++;
309
310     db_table = (char *)strstr( db_name, "/" );
311     if( db_table == NULL ){
312         if (debug & DEBUG_PASSWD_FLAG)
313             report(LOG_DEBUG, "Error parse db_table");
314         free(buffer);
315         return(0);
316     }
317     *db_table = '\0';
318     db_table++;
319
320 /* Find some attributes  for accounting */
321     a_username=rec->identity->username;
322         if (a_username==NULL ) {
323                 if (debug & DEBUG_PASSWD_FLAG)
324                         report(LOG_DEBUG,"db_acct: Can't find username!");
325                         free(buffer);
326                         return(0);
327         }
328     s_name=rec->identity->NAS_name;
329         if (s_name==NULL) {
330                 if (debug & DEBUG_PASSWD_FLAG)
331                         report(LOG_DEBUG,"db_acct: Can't find NAS name!");
332                         free(buffer);
333                         return(0);
334         }
335     c_name=find_attr_value("addr", rec->args, rec->num_args);
336         if (c_name==NULL) {
337                 if (debug & DEBUG_PASSWD_FLAG)
338                         report(LOG_DEBUG,"db_acct: Can't find client adress!");
339         /* Can't find client adress so give NAC_address attribute value */
340                 c_name=rec->identity->NAC_address;
341         }
342     elapsed_time=find_attr_value("elapsed_time", rec->args, rec->num_args);
343         if (elapsed_time==NULL) {
344                 if (debug & DEBUG_PASSWD_FLAG)
345                         report(LOG_DEBUG,"db_acct: Can't get elapsed time!");
346                         free(buffer);
347                         return(0);
348         }
349     bytes_in=find_attr_value("bytes_in", rec->args, rec->num_args);
350         if (bytes_in==NULL) bytes_in="0";
351     bytes_out=find_attr_value("bytes_out", rec->args, rec->num_args);
352         if (bytes_out==NULL) bytes_out="0";
353
354
355     /* Parse database connection string */
356         if (debug & DEBUG_PASSWD_FLAG)
357             report(LOG_DEBUG, "db_verify: db_pref=%s, db_user=%s,db_password=%s , db_hostname=%s, db_name=%s ,db_table=%s ",
358                 db_pref, db_user, db_password,
359                 db_hostname, db_name,db_table );
360
361     /* Check for empty passwords */
362    if (db_user == NULL || db_password == '\0' ) {
363         if (debug & DEBUG_PASSWD_FLAG)
364            report(LOG_DEBUG, "One from passwords is empty");
365         free(buffer);
366         return (0);
367     }
368
369     ret = 0;
370     /* Run database depend function */
371 #if defined(DB_ORACLE)
372     if (!strcmp(db_pref, "oracle")) {
373         ret = oracle_db_acct(
374             db_user, db_password, db_hostname, db_name, db_table);
375     }
376 #endif
377
378 #if defined(DB_MYSQL)
379     if (!strcmp(db_pref, "mysql")) {
380         ret = mysql_db_acct(
381             db_user, db_password, db_hostname, db_name, db_table,s_name,c_name,a_username,elapsed_time,bytes_in,bytes_out);
382     }
383 #endif
384
385 #if defined(DB_PGSQL)
386     if (!strcmp(db_pref, "pgsql")) {
387         ret = pgsql_db_acct(
388             db_user, db_password, db_hostname, db_name, db_table,s_name,c_name,a_username,elapsed_time,bytes_in,bytes_out);
389     }
390 #endif
391
392 #if defined(DB_NULL)
393     if (!strcmp(db_pref, "null")) {
394         ret = null_db_acct(
395             db_user, db_password, db_hostname, db_name, db_table,s_name,c_name,a_username,elapsed_time,bytes_in,bytes_out);
396     }
397 #endif
398 #if defined(DB_GDBM)
399     if (!strcmp(db_pref, "gdbm")) {
400         gdb_db_acct();
401     }
402 #endif
403
404     free(buffer); /* Free unused memory */
405     return (ret); /* error */
406
407 }
408
409 static int check_db_type TAC_ARGS((char *db_type));
410
411 /* For checking DB type */
412 static int
413 check_db_type(db_type)
414 char *db_type;
415 {
416 char *dbp[]=DEFINED_DB;
417 int ret=1,i;
418
419 for (i=0; dbp[i] ; i++ ) {
420         if(!strcmp(db_type,dbp[i])) {
421                 ret=0;
422                 break;
423         }
424 }
425 return ret;
426 }
427
428 #else /* DB */
429
430 TAC_SOURCEFILE_EMPTY
431
432 #endif /* DB */