OSDN Git Service

6b48f97c979caf9248e759e076db856bc836803b
[opengatem/opengatem.git] / mdsrc / session.c
1 /**************************************************
2 OpengateM - a MAC address authentication system
3    module for Controlling sessions 
4
5 Copyright (C) 2011 Opengate Project Team
6 Written by Yoshiaki Watanabe
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21
22 Email: watanaby@is.saga-u.ac.jp
23 **************************************************/
24 #include "opengatemd.h"
25
26 /*******************************
27 add session for the mac address
28 add ipfw-rule and table-entry, write db and log 
29 *******************************/
30 int addSession(char* macAddress, char* userId, char* extraId){
31   int ruleNumber;
32   static int nSerialError=0; /* number of serial errors for addition */
33   int failToAdd=FALSE;
34   int openTime;
35   int checkTime;
36   int ruleNumberInDb;
37
38   /* open firewall */
39   ruleNumber=OpenClientGate(macAddress, userId, extraId);
40
41   /* check error */
42   if(-2<=ruleNumber && ruleNumber<=2) failToAdd=TRUE;
43
44   /* if mac is already registered in ipfw rule */
45   if(ruleNumber < -2){
46     
47     /* if mac is active session in work db, do nothing */
48     if(GetSessionFromWorkDb(macAddress, userId, extraId, &openTime,
49                             &checkTime, &ruleNumberInDb)){ 
50       return FALSE;
51     }
52     /* if not active session in work db, invert sign and goto write db */
53     else{
54       ruleNumber=-ruleNumber;
55     }
56   }
57
58   /* if addtion is failed, retry on next packet (clear cache for checking) */
59   /* as to prevent error loop, retry count is limitted */ 
60   if( failToAdd || !IsMacAddressFoundInIpfw(macAddress) ){
61     nSerialError++;
62     if(nSerialError<1) DelCacheItem(macAddress,"");
63     err_msg("ERR at %s#%d: ipfw rule addition is failed(%d-%d)",
64               __FILE__,__LINE__, failToAdd, nSerialError);
65     return FALSE;
66   }
67   nSerialError=0;
68
69   /* write to session db */
70   InsertSessionToWorkDb(macAddress, userId, extraId, ruleNumber);
71
72   /* write open log to syslog */
73   WriteOpenToSyslog(userId, extraId, macAddress);
74
75   /* write log to management db */
76   PutOpenToMngDb(macAddress);
77   return TRUE;
78 }
79
80 /*******************************
81 delete session for the mac address
82 (del ipfw-rule and table-entry, write db and log) 
83 *******************************/
84 void delSession(char* macAddress){
85   char userId[USERMAXLN]="";
86   char extraId[USERMAXLN]="";
87   int openTime=0;
88   int ruleNumber=0;
89   int checkTime=0;
90   int success;
91
92   /* get information from session table in work db */
93   success=GetSessionFromWorkDb(macAddress, userId, extraId, &openTime, 
94                                  &checkTime, &ruleNumber);
95
96   /* close firewall and refresh the cache */
97   if(success) CloseClientGate(ruleNumber);
98
99   /* del from cache */
100   DelCacheItem(macAddress,"");
101   
102   /* del from session from session table in work db */
103   DelSessionFromWorkDb(macAddress);
104
105   /* write close log to syslog */
106   WriteCloseToSyslog(userId, extraId, macAddress, openTime);
107   if(debug>0) WriteSessionInfoToSyslog(userId, extraId, 
108                                        macAddress, ruleNumber);
109
110   /* write close log to management db */
111   PutCloseToMngDb(macAddress);
112
113   /* reset the memory of MAC IP pair */
114   ResetMacIpPairs(macAddress);
115 }
116
117 /*******************************
118 renew session for the ip address
119 (renew time in table entry) 
120 *******************************/
121 void renewSession(char* macAddress){
122
123   /* renew the check time */
124   UpdateCheckTimeInWorkDb(macAddress);
125 }
126
127 /*******************************
128 search db to find ip that is not used for a long time
129 del ipfw rule, del table entry, write db/log 
130 *******************************/
131 void delUselessSessions(void){
132
133   /* scan db to remove old sessions */
134   DelUselessSessionsInWorkDb(TRUE);
135
136   /* scan ipfw rule to close unmatched db row */
137   CloseUnmatchSessions();
138 }
139
140 /**********************************
141 CALLBACK FUNCTION
142 called back from sqlite3_exec 
143 in sessiondb.c/delUselessSessionsInDb & delAllSessionsInDb
144 **********************************/
145 int closeSession(void* pParam, int argc, char *argv[], char* colName[]){
146
147   int ruleNumber;
148   char* userId;
149   char* extraId;
150   char* macAddress;
151   int openTime;
152
153   if(argc < 5) return 1; /* SQLITE_ERROR */
154   
155   ruleNumber=atoi(argv[0]);
156   userId=argv[1];
157   extraId=argv[2];
158   macAddress=argv[3];
159   openTime=atoi(argv[4]);
160
161   /* close firewall */
162   CloseClientGate(ruleNumber);
163   DelCacheItem(macAddress,"");
164
165   /* write close log to syslog */
166   WriteCloseToSyslog(userId, extraId,  macAddress, openTime);
167   if(debug>0) WriteSessionInfoToSyslog(userId, extraId, macAddress, ruleNumber);
168
169   /* write close log to management db */
170   PutCloseToMngDb(macAddress);
171
172   /* reset the memory of MAC IP pair */
173   ResetMacIpPairs(macAddress);
174
175   return 0; /* SQLITE_OK */
176 }
177
178 /*******************************
179 search db to find all ip
180 del ipfw rule, del table entry, write db/log 
181 *******************************/
182 void delAllSessions(void){
183
184   /* scan db to remove all sessions. argument indicates delayed flag */
185   DelUselessSessionsInWorkDb(FALSE);
186
187   /* scan ipfw rule to close unmatched db row */
188   CloseUnmatchSessions();
189 }
190
191 /**********************************************
192 is the mac session found 
193 **********************************************/
194 int isMatchedSessionFound(char* macAddress){
195   char userId[USERMAXLN];
196   char extraId[USERMAXLN];
197   int openTime;
198   int checkTime;
199   int ruleNumber;
200
201   /* get info for the macAddress */
202   return GetSessionFromWorkDb(macAddress, userId, extraId, 
203                          &openTime, &checkTime, &ruleNumber);
204 }
205
206 /************************************
207 debug routine for hash table
208 ************************************/
209 void dumpTable(DB* table){
210   DBT hashKey;
211   DBT hashVal;
212   int ruleNumber=0;
213   char macAddress[ADDRMAXLN]="?";
214   int ret;
215
216   memset(&hashKey, 0, sizeof(DBT));
217   memset(&hashVal, 0, sizeof(DBT));
218   ret=table->seq(table, &hashKey, &hashVal, R_FIRST);
219   while(ret==0){
220
221     ruleNumber=*(int*)(hashVal.data);
222     strlcpy(macAddress, (char*)hashKey.data, ADDRMAXLN);
223     err_msg("%d:%s", ruleNumber, macAddress);
224
225     /* get next entry */
226     ret=table->seq(table, &hashKey, &hashVal, R_NEXT);
227   }
228 }
229
230 /************************************************
231  close sessions that lost ipfw rule or database entry
232  load rules from ipfw and database, then compare
233   sessionTable        ruleTable
234 form opengatemd.db    from ipfw
235    key=macAddr         macAddr
236    val=0               ipfwRule
237       ^                 ^  
238       |-----------------|  
239 entry in ruleTable adn sessionTable should be matched.
240 if exists in ruleTable and not in sessionTable, remove rule
241 if exists in sessionTable and not in ruleTable, remove session
242 *************************************************/
243 void closeUnmatchSessions(void){
244   DB* ruleTable;
245   DB* sessionTable;
246
247   /* prepare hash table for active sessions */
248   if((sessionTable = dbopen(NULL, O_CREAT | O_RDWR, 0644, DB_HASH, NULL)) == NULL) {
249     err_msg("ERR at %s#%d: fail to open hash table",__FILE__,__LINE__);
250     terminateProg(0);
251   }
252
253   /* prepare hash table for rule numbers */
254   if((ruleTable = dbopen(NULL, O_CREAT | O_RDWR, 0644, DB_HASH, NULL)) == NULL) {
255     err_msg("ERR at %s#%d: fail to open hash table",__FILE__,__LINE__);
256     terminateProg(0);
257   }
258
259   /* get rule numbers from ipfw */
260   GetRuleTableFromIpfw(ruleTable);
261
262   /* get active sessions from work db */
263   GetSessionTableFromWorkDb(sessionTable);
264
265   /****debug print
266   err_msg("Rule");
267   dumpTable(ruleTable);
268   err_msg("Session");
269   dumpTable(sessionTable);
270   ****/
271
272   /* remove unmatched entry */
273   RemoveSessionUnmatchedToIpfwRule(ruleTable, sessionTable);
274   RemoveIpfwRuleUnmatchedToSession(ruleTable, sessionTable);
275
276   /* erase table area */
277   sessionTable->close(sessionTable);
278   ruleTable->close(ruleTable);
279 }
280
281 /*******************************
282 remove session in db unmatched to ipfw active rule
283  (db entry exists but no ipfw rule is found)
284 *******************************/
285 void removeSessionUnmatchedToIpfwRule(DB* ruleTable, DB* sessionTable){
286   DBT hashKey;
287   DBT hashVal;
288   int retRuleTbl;
289   int retSesTbl;
290   int ruleNumber;
291   char userId[USERMAXLN];
292   char extraId[USERMAXLN];
293   char macAddress[ADDRMAXLN];
294   int openTime;
295   int checkTime;
296
297   /* scan session table to find entry unmatched to rule table */
298   /* get first entry of session table */
299   memset(&hashKey, 0, sizeof(DBT));
300   memset(&hashVal, 0, sizeof(DBT));
301   retSesTbl=sessionTable->seq(sessionTable, &hashKey, &hashVal, R_FIRST);
302   while(retSesTbl==0){
303
304     /* (get-function returns 0 on success) */
305     /* if found a session, save the data */
306     strlcpy(macAddress, (char*)hashKey.data, ADDRMAXLN);
307
308     /* get entry having same key in rule table */
309     hashKey.data = macAddress;
310     hashKey.size = strlen(macAddress)+1;
311     memset(&hashVal, 0, sizeof(DBT));
312     retRuleTbl=ruleTable->get(ruleTable, &hashKey, &hashVal, 0);
313
314     /* (get-function returns 0 on success) */
315     /*** rule for the session exists */
316     if(retRuleTbl==0){
317       ; /* do nothing */
318     }
319
320     /*** rule for the session does not exist */
321     else{
322       /* write log and close session */
323       if(!GetSessionFromWorkDb(macAddress, userId, extraId, 
324                               &openTime, &checkTime, &ruleNumber)){
325         err_msg("ERR at %s#%d: fail to get session info",__FILE__,__LINE__);
326       }else{
327         WriteCloseToSyslog(userId, extraId, macAddress, openTime);
328         PutCloseToMngDb(macAddress);
329         DelSessionFromWorkDb(macAddress);
330       }
331
332       /* write session info to syslog */
333       if(debug>0) WriteSessionInfoToSyslog(userId, extraId, 
334                                            macAddress, ruleNumber);
335     }
336
337     /* get next rule entry */
338     retSesTbl=sessionTable->seq(sessionTable, &hashKey, &hashVal, R_NEXT);
339   }
340 }
341
342 /***********************************
343 remove active ipfw rule unmatched to session in db
344  (ipfw rule exists but no db entry is found)
345 ***********************************/
346 void  removeIpfwRuleUnmatchedToSession(DB* ruleTable, DB* sessionTable){
347   DBT hashKey;
348   DBT hashVal;
349   int retRuleTbl;
350   int retSesTbl;
351   int ruleNumber;
352   char macAddress[ADDRMAXLN];
353
354   /* scan ipfw rule table to find entry unmatched to session table */
355   /* get first entry of ipfw rule table */
356   memset(&hashKey, 0, sizeof(DBT));
357   memset(&hashVal, 0, sizeof(DBT));
358   retRuleTbl=ruleTable->seq(ruleTable, &hashKey, &hashVal, R_FIRST);
359   while(retRuleTbl==0){
360
361     /* if found in rule table, save data */
362     ruleNumber=*(int*)(hashVal.data);
363     strlcpy(macAddress, (char*)hashKey.data, ADDRMAXLN);
364
365     /* get entry having same key in session table */
366     hashKey.data = macAddress;
367     hashKey.size = strlen(macAddress)+1;
368     memset(&hashVal, 0, sizeof(DBT));
369     retSesTbl=sessionTable->get(sessionTable, &hashKey, &hashVal, 0);
370
371     /* (get-function returns 0 on success) */
372     /*** session for the rule exists */
373     if(retSesTbl==0){
374       ; /* do nothing */
375     }
376
377     /*** session for the rule does not exist */
378     else{
379
380       /* remove entry in ipfw rule */
381       CloseClientGate(ruleNumber);
382       DelCacheItem(macAddress,"");
383
384       /* write log */
385       WriteCloseToSyslog("?", "", macAddress, time(NULL));
386       PutCloseToMngDb(macAddress);
387       
388       /* write session info to syslog */
389       if(debug>0) WriteSessionInfoToSyslog("?","", macAddress, ruleNumber);
390     }
391
392     /* get next rule entry */
393     retRuleTbl=ruleTable->seq(ruleTable, &hashKey, &hashVal, R_NEXT);
394   }
395 }
396
397
398 /******************************************
399 write open message to syslog
400 ******************************************/
401 void writeOpenToSyslog(char* userId, char* extraId, char* macAddress){
402
403   if(extraId[0]=='\0'){
404     err_msg("OPEN: user %s at %s", 
405             userId, macAddress);
406   }else{
407     err_msg("OPEN: user %s%s%s at %s", 
408             userId, GetConfValue("UserIdSeparator"), extraId, macAddress);
409   }
410 }
411
412 /******************************************
413 write close message to syslog
414 ******************************************/
415 void writeCloseToSyslog(char* userId, char* extraId, char* macAddress, int openTime){
416
417   double time_l;
418   int hour, min, sec;
419
420   time_l=difftime((int)time(NULL), openTime);
421   hour=time_l/60/60;
422   min=(time_l-hour*60*60)/60;
423   sec=(time_l-hour*60*60-min*60);
424
425   if(extraId[0]=='\0'){
426     err_msg("CLOS: user %s at %s ( %02d:%02d:%02d )", 
427             userId, macAddress, hour,min,sec);
428   }else{
429     err_msg("CLOS: user %s%s%s at %s ( %02d:%02d:%02d )", 
430             userId, GetConfValue("UserIdSeparator"), extraId, 
431             macAddress, hour,min,sec);
432   }
433 }
434
435 /******************************************
436 write session info message to syslog
437 ******************************************/
438 void writeSessionInfoToSyslog(char* userId, char* extraId, char* macAddress, int ruleNumber){
439
440   char detectTimeStr[WORDMAXLN];
441   int ttl;
442
443   /* get client info from macinfo table in workdb */
444   GetMacInfoFromWorkDb(macAddress, detectTimeStr, &ttl);
445
446   if(extraId[0]=='\0'){
447     err_msg("INFO: user=%s macaddr=%s "
448             "ipfwrule=%d ttl=%d lastcheck=%s", 
449             userId, macAddress, ruleNumber, ttl, detectTimeStr);
450   }else{
451     err_msg("INFO: user=%s%s%s macaddr=%s "
452             "ipfwrule=%d ttl=%d lastcheck=%s", 
453             userId, GetConfValue("UserIdSeparator"), extraId, 
454             macAddress, ruleNumber, ttl, detectTimeStr);
455   }
456 }
457
458 /**********************************************
459 Memorize the MAC&IP address pair to DB and log
460 **********************************************/
461 void setMacIpPair(char* macAddress, char* ipAddress, char* userId, char* extraId){
462   
463   /* if the pair is not found in work db, record it */ 
464   if(!IsFoundMacIpPairInWorkDb(macAddress, ipAddress)){
465     PutMacIpPairToWorkDb(macAddress, ipAddress);
466
467     /* record the pair to management db */
468     PutMacIpPairToMngDb(macAddress, ipAddress);
469
470     /* write to syslog */
471     if(isNull(extraId)){
472       err_msg("FIND: user %s from %s at %s", userId, ipAddress, macAddress);
473     }else{
474       err_msg("FIND: user %s%s%s from %s at %s", 
475               userId, GetConfValue("UserIdSeparator"), extraId, 
476               ipAddress, macAddress);
477     }
478   }
479 }
480
481 /**********************************
482 Reset the MAC&IP address pair in DB
483 ***********************************/
484 void resetMacIpPairs(char* macAddress){
485
486   /* remove the all-pairs having the MAC from work db */
487   DelMacIpPairsInWorkDb(macAddress);
488 }
489
490
491 /**************************************************
492  routines for debugging output
493  *************************************************/
494
495 int AddSession(char* macAddress, char* userId, char* extraId){
496   int ret;
497   if(debug>1) err_msg("DEBUG:=>addSession(%s,%s,%s)",
498                       macAddress, userId, extraId);
499   ret = addSession(macAddress, userId, extraId);
500   if(debug>1) err_msg("DEBUG:(%d)<=addSession( )",ret);
501   return ret;
502 }
503 void DelSession(char* macAddress){
504   if(debug>1) err_msg("DEBUG:=>delSession(%s)",macAddress);
505   delSession(macAddress);
506   if(debug>1) err_msg("DEBUG:<=delSession( )");
507 }
508 void RenewSession(char* macAddress){
509   if(debug>1) err_msg("DEBUG:=>renewSession(%s)",macAddress);
510   renewSession(macAddress);
511   if(debug>1) err_msg("DEBUG:<=renewSession( )");
512 }
513 void DelUselessSessions(void){
514   if(debug>1) err_msg("DEBUG:=>delUselessSessions()");
515   delUselessSessions();
516   if(debug>1) err_msg("DEBUG:<=delUselessSessions( )");
517 }
518 void DelAllSessions(void){
519   if(debug>1) err_msg("DEBUG:=>delAllSessions()");
520   delAllSessions();
521   if(debug>1) err_msg("DEBUG:<=delAllSessions( )");
522 }
523 int CloseSession(void* pParam, int argc, char *argv[], char* colName[]){
524   int ret;
525   if(debug>1) err_msg("DEBUG:=>closeSession()");
526   ret = closeSession(pParam, argc, argv, colName);
527   if(debug>1) err_msg("DEBUG:(%d)<=closeSession( )",ret);
528   return ret;
529 }
530 int IsMatchedSessionFound(char* macAddress){
531   int ret;
532   if(debug>1) err_msg("DEBUG:=>isMatchedSessionFound(%s)",
533                       macAddress);
534   ret = isMatchedSessionFound(macAddress);
535   if(debug>1) err_msg("DEBUG:(%d)<=isMatchedSessionFound( )",ret);
536   return ret;
537 }
538
539 void CloseUnmatchSessions(void){
540   if(debug>1) err_msg("DEBUG:=>closeUnmatchSessions( )");
541   closeUnmatchSessions();
542   if(debug>1) err_msg("DEBUG:<=closeUnmatchSessions( )");
543 }
544
545 void WriteOpenToSyslog(char* userId, char* extraId, char* macAddress){
546   if(debug>1) err_msg("DEBUG:=>writeOpenToSyslog(%s,%s,%s)", userId, extraId, macAddress);
547   writeOpenToSyslog(userId, extraId, macAddress);
548   if(debug>1) err_msg("DEBUG:<=writeOpenToSyslog( )");
549 }
550
551 void WriteCloseToSyslog(char* userId, char* extraId, char* macAddress, int openTime){
552   if(debug>1) err_msg("DEBUG:=>writeCloseToSyslog(%s,%s,%s,%d)", userId, extraId, macAddress, openTime);
553   writeCloseToSyslog(userId, extraId, macAddress, openTime);
554   if(debug>1) err_msg("DEBUG:<=writeCloseToSyslog( )");
555 }
556
557 void WriteSessionInfoToSyslog(char* userId, char* extraId, char* macAddress, int ruleNumber){
558   if(debug>1) err_msg("DEBUG:=>writeSessionInfoToSyslog(%s,%s,%s,%d)", userId, extraId, macAddress, ruleNumber);
559   writeSessionInfoToSyslog(userId, extraId, macAddress, ruleNumber);
560   if(debug>1) err_msg("DEBUG:<=writeSessionInfoToSyslog( )");
561 }
562
563
564 void RemoveSessionUnmatchedToIpfwRule(DB* ruleTable, DB* sessionTable){
565   if(debug>1) err_msg("DEBUG:=>removeSessionUnmatchedToIpfwRule()");
566   removeSessionUnmatchedToIpfwRule(ruleTable, sessionTable);
567   if(debug>1) err_msg("DEBUG:<=removeSessionUnmatchedToIpfwRule()");
568 }
569
570 void RemoveIpfwRuleUnmatchedToSession(DB* ruleTable, DB* sessionTable){
571   if(debug>1) err_msg("DEBUG:=>removeIpfwRuleUnmatchedToSession()");
572   removeIpfwRuleUnmatchedToSession(ruleTable, sessionTable);
573   if(debug>1) err_msg("DEBUG:<=removeIpfwRuleUnmatchedToSession()");
574
575 }
576
577 void SetMacIpPair(char* macAddress, char* ipAddress, char* userId, char* extraId){
578   if(debug>1) err_msg("DEBUG:=>setMacIpPair(%s,%s,%s,%s)",
579                       macAddress, ipAddress, userId, extraId);
580   setMacIpPair(macAddress, ipAddress, userId, extraId);
581   if(debug>1) err_msg("DEBUG:<=setMacIpPair( )");
582 }
583
584 void ResetMacIpPairs(char* macAddress){
585   if(debug>1) err_msg("DEBUG:=>resetMacIpPairs(%s)", macAddress);
586   resetMacIpPairs(macAddress);
587   if(debug>1) err_msg("DEBUG:<=resetMacIpPairs( )");
588 }
589
590 /********************testmain********************
591 void testmain(){
592
593   char* ipAddress="192.168.0.120";
594   char* macAddress="00:01:02:03:04:05";
595   char* userId="watanaby";
596   char* extraId="";
597
598   addSession(ipAddress, macAddress, userId, extraId);
599   sleep(10);
600   renewSession(ipAddress);
601   sleep(10);
602   delUselessSessions();
603   sleep(10);
604   delUselessSessions();
605   delSession(ipAddress);
606 }
607 ************************************************/