OSDN Git Service

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