1 /**************************************************
2 OpengateM - a MAC address authentication system
3 module for Controlling sessions
5 Copyright (C) 2011 Opengate Project Team
6 Written by Yoshiaki Watanabe
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.
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.
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.
22 Email: watanaby@is.saga-u.ac.jp
23 **************************************************/
24 #include "opengatemd.h"
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){
32 static int nSerialError=0; /* number of serial errors for addition */
39 ruleNumber=OpenClientGate(macAddress, userId, extraId);
42 if(-2<=ruleNumber && ruleNumber<=2) failToAdd=TRUE;
44 /* if mac is already registered in ipfw rule */
47 /* if mac is active session in work db, do nothing */
48 if(GetSessionFromWorkDb(macAddress, userId, extraId, &openTime,
49 &checkTime, &ruleNumberInDb)){
52 /* if not active session in work db, invert sign and goto write db */
54 ruleNumber=-ruleNumber;
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) ){
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);
69 /* write to session db */
70 InsertSessionToWorkDb(macAddress, userId, extraId, ruleNumber);
72 /* write open log to syslog */
73 WriteOpenToSyslog(userId, extraId, macAddress);
75 /* write log to management db */
76 PutOpenToMngDb(macAddress);
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]="";
92 /* get information from session table in work db */
93 success=GetSessionFromWorkDb(macAddress, userId, extraId, &openTime,
94 &checkTime, &ruleNumber);
96 /* close firewall and refresh the cache */
97 if(success) CloseClientGate(ruleNumber);
100 DelCacheItem(macAddress,"");
102 /* del from session from session table in work db */
103 DelSessionFromWorkDb(macAddress);
105 /* write close log to syslog */
106 WriteCloseToSyslog(userId, extraId, macAddress, openTime);
107 if(debug>0) WriteSessionInfoToSyslog(userId, extraId,
108 macAddress, ruleNumber);
110 /* write close log to management db */
111 PutCloseToMngDb(macAddress);
113 /* reset the memory of MAC IP pair */
114 ResetMacIpPairs(macAddress);
117 /*******************************
118 renew session for the ip address
119 (renew time in table entry)
120 *******************************/
121 void renewSession(char* macAddress){
123 /* renew the check time */
124 UpdateCheckTimeInWorkDb(macAddress);
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){
133 /* scan db to remove old sessions */
134 DelUselessSessionsInWorkDb(TRUE);
136 /* scan ipfw rule to close unmatched db row */
137 CloseUnmatchSessions();
140 /**********************************
142 called back from sqlite3_exec
143 in sessiondb.c/delUselessSessionsInDb & delAllSessionsInDb
144 **********************************/
145 int closeSession(void* pParam, int argc, char *argv[], char* colName[]){
153 if(argc < 5) return 1; /* SQLITE_ERROR */
155 ruleNumber=atoi(argv[0]);
159 openTime=atoi(argv[4]);
162 CloseClientGate(ruleNumber);
163 DelCacheItem(macAddress,"");
165 /* write close log to syslog */
166 WriteCloseToSyslog(userId, extraId, macAddress, openTime);
167 if(debug>0) WriteSessionInfoToSyslog(userId, extraId, macAddress, ruleNumber);
169 /* write close log to management db */
170 PutCloseToMngDb(macAddress);
172 /* reset the memory of MAC IP pair */
173 ResetMacIpPairs(macAddress);
175 return 0; /* SQLITE_OK */
178 /*******************************
179 search db to find all ip
180 del ipfw rule, del table entry, write db/log
181 *******************************/
182 void delAllSessions(void){
184 /* scan db to remove all sessions. argument indicates delayed flag */
185 DelUselessSessionsInWorkDb(FALSE);
187 /* scan ipfw rule to close unmatched db row */
188 CloseUnmatchSessions();
191 /**********************************************
192 is the mac session found
193 **********************************************/
194 int isMatchedSessionFound(char* macAddress){
195 char userId[USERMAXLN];
196 char extraId[USERMAXLN];
201 /* get info for the macAddress */
202 return GetSessionFromWorkDb(macAddress, userId, extraId,
203 &openTime, &checkTime, &ruleNumber);
206 /************************************
207 debug routine for hash table
208 ************************************/
209 void dumpTable(DB* table){
213 char macAddress[ADDRMAXLN]="?";
216 memset(&hashKey, 0, sizeof(DBT));
217 memset(&hashVal, 0, sizeof(DBT));
218 ret=table->seq(table, &hashKey, &hashVal, R_FIRST);
221 ruleNumber=*(int*)(hashVal.data);
222 strlcpy(macAddress, (char*)hashKey.data, ADDRMAXLN);
223 err_msg("%d:%s", ruleNumber, macAddress);
226 ret=table->seq(table, &hashKey, &hashVal, R_NEXT);
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
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){
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__);
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__);
259 /* get rule numbers from ipfw */
260 GetRuleTableFromIpfw(ruleTable);
262 /* get active sessions from work db */
263 GetSessionTableFromWorkDb(sessionTable);
267 dumpTable(ruleTable);
269 dumpTable(sessionTable);
272 /* remove unmatched entry */
273 RemoveSessionUnmatchedToIpfwRule(ruleTable, sessionTable);
274 RemoveIpfwRuleUnmatchedToSession(ruleTable, sessionTable);
276 /* erase table area */
277 sessionTable->close(sessionTable);
278 ruleTable->close(ruleTable);
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){
291 char userId[USERMAXLN];
292 char extraId[USERMAXLN];
293 char macAddress[ADDRMAXLN];
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);
304 /* (get-function returns 0 on success) */
305 /* if found a session, save the data */
306 strlcpy(macAddress, (char*)hashKey.data, ADDRMAXLN);
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);
314 /* (get-function returns 0 on success) */
315 /*** rule for the session exists */
320 /*** rule for the session does not exist */
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__);
327 WriteCloseToSyslog(userId, extraId, macAddress, openTime);
328 PutCloseToMngDb(macAddress);
329 DelSessionFromWorkDb(macAddress);
332 /* write session info to syslog */
333 if(debug>0) WriteSessionInfoToSyslog(userId, extraId,
334 macAddress, ruleNumber);
337 /* get next rule entry */
338 retSesTbl=sessionTable->seq(sessionTable, &hashKey, &hashVal, R_NEXT);
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){
352 char macAddress[ADDRMAXLN];
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){
361 /* if found in rule table, save data */
362 ruleNumber=*(int*)(hashVal.data);
363 strlcpy(macAddress, (char*)hashKey.data, ADDRMAXLN);
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);
371 /* (get-function returns 0 on success) */
372 /*** session for the rule exists */
377 /*** session for the rule does not exist */
380 /* remove entry in ipfw rule */
381 CloseClientGate(ruleNumber);
382 DelCacheItem(macAddress,"");
385 WriteCloseToSyslog("?", "", macAddress, time(NULL));
386 PutCloseToMngDb(macAddress);
388 /* write session info to syslog */
389 if(debug>0) WriteSessionInfoToSyslog("?","", macAddress, ruleNumber);
392 /* get next rule entry */
393 retRuleTbl=ruleTable->seq(ruleTable, &hashKey, &hashVal, R_NEXT);
398 /******************************************
399 write open message to syslog
400 ******************************************/
401 void writeOpenToSyslog(char* userId, char* extraId, char* macAddress){
403 if(extraId[0]=='\0'){
404 err_msg("OPEN: user %s at %s",
407 err_msg("OPEN: user %s%s%s at %s",
408 userId, GetConfValue("UserIdSeparator"), extraId, macAddress);
412 /******************************************
413 write close message to syslog
414 ******************************************/
415 void writeCloseToSyslog(char* userId, char* extraId, char* macAddress, int openTime){
420 time_l=difftime((int)time(NULL), openTime);
422 min=(time_l-hour*60*60)/60;
423 sec=(time_l-hour*60*60-min*60);
425 if(extraId[0]=='\0'){
426 err_msg("CLOS: user %s at %s ( %02d:%02d:%02d )",
427 userId, macAddress, hour,min,sec);
429 err_msg("CLOS: user %s%s%s at %s ( %02d:%02d:%02d )",
430 userId, GetConfValue("UserIdSeparator"), extraId,
431 macAddress, hour,min,sec);
435 /******************************************
436 write session info message to syslog
437 ******************************************/
438 void writeSessionInfoToSyslog(char* userId, char* extraId, char* macAddress, int ruleNumber){
440 char detectTimeStr[WORDMAXLN];
443 /* get client info from macinfo table in workdb */
444 GetMacInfoFromWorkDb(macAddress, detectTimeStr, &ttl);
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);
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);
458 /**********************************************
459 Memorize the MAC&IP address pair to DB and log
460 **********************************************/
461 void setMacIpPair(char* macAddress, char* ipAddress, char* userId, char* extraId){
463 /* if the pair is not found in work db, record it */
464 if(!IsFoundMacIpPairInWorkDb(macAddress, ipAddress)){
465 PutMacIpPairToWorkDb(macAddress, ipAddress);
467 /* record the pair to management db */
468 PutMacIpPairToMngDb(macAddress, ipAddress);
470 /* write to syslog */
472 err_msg("FIND: user %s from %s at %s", userId, ipAddress, macAddress);
474 err_msg("FIND: user %s%s%s from %s at %s",
475 userId, GetConfValue("UserIdSeparator"), extraId,
476 ipAddress, macAddress);
481 /**********************************
482 Reset the MAC&IP address pair in DB
483 ***********************************/
484 void resetMacIpPairs(char* macAddress){
486 /* remove the all-pairs having the MAC from work db */
487 DelMacIpPairsInWorkDb(macAddress);
491 /**************************************************
492 routines for debugging output
493 *************************************************/
495 int AddSession(char* macAddress, char* userId, char* extraId){
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);
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( )");
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( )");
513 void DelUselessSessions(void){
514 if(debug>1) err_msg("DEBUG:=>delUselessSessions()");
515 delUselessSessions();
516 if(debug>1) err_msg("DEBUG:<=delUselessSessions( )");
518 void DelAllSessions(void){
519 if(debug>1) err_msg("DEBUG:=>delAllSessions()");
521 if(debug>1) err_msg("DEBUG:<=delAllSessions( )");
523 int CloseSession(void* pParam, int argc, char *argv[], char* colName[]){
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);
530 int IsMatchedSessionFound(char* macAddress){
532 if(debug>1) err_msg("DEBUG:=>isMatchedSessionFound(%s)",
534 ret = isMatchedSessionFound(macAddress);
535 if(debug>1) err_msg("DEBUG:(%d)<=isMatchedSessionFound( )",ret);
539 void CloseUnmatchSessions(void){
540 if(debug>1) err_msg("DEBUG:=>closeUnmatchSessions( )");
541 closeUnmatchSessions();
542 if(debug>1) err_msg("DEBUG:<=closeUnmatchSessions( )");
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( )");
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( )");
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( )");
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()");
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()");
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( )");
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( )");
590 /********************testmain********************
593 char* ipAddress="192.168.0.120";
594 char* macAddress="00:01:02:03:04:05";
595 char* userId="watanaby";
598 addSession(ipAddress, macAddress, userId, extraId);
600 renewSession(ipAddress);
602 delUselessSessions();
604 delUselessSessions();
605 delSession(ipAddress);
607 ************************************************/