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* ipAddress, char* userId, char* extraId){
32 static int nSerialError=0; /* number of serial errors for addition */
34 char ipAddressInDb[ADDRMAXLN];
40 ruleNumber=OpenClientGate(macAddress, userId, extraId);
43 if(-2<=ruleNumber && ruleNumber<=2) failToAdd=TRUE;
45 /* if mac is already registered in ipfw rule */
48 /* if mac is active session in work db, do nothing */
49 if(GetSessionFromWorkDb(macAddress, userId, extraId, &openTime,
50 &checkTime, ipAddressInDb, &ruleNumberInDb)){
53 /* if not active session in work db, invert sign and goto write db */
55 ruleNumber=-ruleNumber;
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) ){
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);
70 /* write to session db */
71 InsertSessionToWorkDb(macAddress, userId, extraId, ipAddress, ruleNumber);
73 /* write open log to syslog */
74 WriteOpenToSyslog(userId, extraId, ipAddress, macAddress);
76 /* write log to management db */
77 PutOpenToMngDb(macAddress, ipAddress);
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]="";
94 /* get information from session table in work db */
95 success=GetSessionFromWorkDb(macAddress, userId, extraId, &openTime,
96 &checkTime, ipAddress, &ruleNumber);
98 /* close firewall and refresh the cache */
99 if(success) CloseClientGate(ruleNumber);
102 DelCacheItem(macAddress);
104 /* del from session from session table in work db */
105 DelSessionFromWorkDb(macAddress);
107 /* write close log to syslog */
108 WriteCloseToSyslog(userId, extraId, ipAddress, macAddress, openTime);
109 if(debug>0) WriteSessionInfoToSyslog(userId, extraId, ipAddress,
110 macAddress, ruleNumber);
112 /* write close log to management db */
113 PutCloseToMngDb(macAddress);
116 /*******************************
117 renew session for the ip address
118 (renew time in table entry)
119 *******************************/
120 void renewSession(char* macAddress){
122 /* renew the check time */
123 UpdateCheckTimeInWorkDb(macAddress);
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){
132 /* scan db to remove old sessions */
133 DelUselessSessionsInWorkDb(TRUE);
135 /* scan ipfw rule to close unmatched db row */
136 CloseUnmatchSessions();
139 /**********************************
141 called back from sqlite3_exec
142 in sessiondb.c/delUselessSessionsInDb & delAllSessionsInDb
143 **********************************/
144 int closeSession(void* pParam, int argc, char *argv[], char* colName[]){
153 if(argc < 5) return 1; /* SQLITE_ERROR */
155 ruleNumber=atoi(argv[0]);
160 openTime=atoi(argv[5]);
163 CloseClientGate(ruleNumber);
164 DelCacheItem(macAddress);
166 /* write close log to syslog */
167 WriteCloseToSyslog(userId, extraId, ipAddress, macAddress, openTime);
168 if(debug>0) WriteSessionInfoToSyslog(userId, extraId, ipAddress,
169 macAddress, ruleNumber);
171 /* write close log to management db */
172 PutCloseToMngDb(macAddress);
174 return 0; /* SQLITE_OK */
177 /*******************************
178 search db to find all ip
179 del ipfw rule, del table entry, write db/log
180 *******************************/
181 void delAllSessions(void){
183 /* scan db to remove all sessions. argument indicates delayed flag */
184 DelUselessSessionsInWorkDb(FALSE);
186 /* scan ipfw rule to close unmatched db row */
187 CloseUnmatchSessions();
190 /**********************************************
191 is the mac session found
192 **********************************************/
193 int isMatchedSessionFound(char* macAddress){
194 char userId[USERMAXLN];
195 char extraId[USERMAXLN];
198 char ipAddress[ADDRMAXLN];
201 /* get info for the macAddress */
202 return GetSessionFromWorkDb(macAddress, userId, extraId,
203 &openTime, &checkTime, ipAddress,
207 /************************************
208 debug routine for hash table
209 ************************************/
210 void dumpTable(DB* table){
214 char macAddress[ADDRMAXLN]="?";
217 memset(&hashKey, 0, sizeof(DBT));
218 memset(&hashVal, 0, sizeof(DBT));
219 ret=table->seq(table, &hashKey, &hashVal, R_FIRST);
222 ruleNumber=*(int*)(hashVal.data);
223 strncpy(macAddress, (char*)hashKey.data, ADDRMAXLN);
224 err_msg("%d:%s", ruleNumber, macAddress);
227 ret=table->seq(table, &hashKey, &hashVal, R_NEXT);
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
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){
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__);
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__);
260 /* get rule numbers from ipfw */
261 GetRuleTableFromIpfw(ruleTable);
263 /* get active sessions from work db */
264 GetSessionTableFromWorkDb(sessionTable);
268 dumpTable(ruleTable);
270 dumpTable(sessionTable);
273 /* remove unmatched entry */
274 RemoveSessionUnmatchedToIpfwRule(ruleTable, sessionTable);
275 RemoveIpfwRuleUnmatchedToSession(ruleTable, sessionTable);
277 /* erase table area */
278 sessionTable->close(sessionTable);
279 ruleTable->close(ruleTable);
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){
292 char ipAddress[ADDRMAXLN];
293 char userId[USERMAXLN];
294 char extraId[USERMAXLN];
295 char macAddress[ADDRMAXLN];
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);
306 /* (get-function returns 0 on success) */
307 /* if found a session, save the data */
308 strncpy(macAddress, (char*)hashKey.data, ADDRMAXLN);
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);
316 /* (get-function returns 0 on success) */
317 /*** rule for the session exists */
322 /*** rule for the session does not exist */
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__);
329 WriteCloseToSyslog(userId, extraId, ipAddress, macAddress, openTime);
330 PutCloseToMngDb(macAddress);
331 DelSessionFromWorkDb(macAddress);
334 /* write session info to syslog */
335 if(debug>0) WriteSessionInfoToSyslog(userId, extraId, ipAddress,
336 macAddress, ruleNumber);
339 /* get next rule entry */
340 retSesTbl=sessionTable->seq(sessionTable, &hashKey, &hashVal, R_NEXT);
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){
354 char macAddress[ADDRMAXLN];
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){
363 /* if found in rule table, save data */
364 ruleNumber=*(int*)(hashVal.data);
365 strncpy(macAddress, (char*)hashKey.data, ADDRMAXLN);
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);
373 /* (get-function returns 0 on success) */
374 /*** session for the rule exists */
379 /*** session for the rule does not exist */
382 /* remove entry in ipfw rule */
383 CloseClientGate(ruleNumber);
384 DelCacheItem(macAddress);
387 WriteCloseToSyslog("?", "", "?", macAddress, time(NULL));
388 PutCloseToMngDb(macAddress);
390 /* write session info to syslog */
391 if(debug>0) WriteSessionInfoToSyslog("?","","?",macAddress, ruleNumber);
394 /* get next rule entry */
395 retRuleTbl=ruleTable->seq(ruleTable, &hashKey, &hashVal, R_NEXT);
400 /******************************************
401 write open message to syslog
402 ******************************************/
403 void writeOpenToSyslog(char* userId, char* extraId, char* ipAddress, char* macAddress){
405 if(extraId[0]=='\0'){
406 err_msg("OPEN: user %s from %s at %s",
407 userId, ipAddress, macAddress);
409 err_msg("OPEN: user %s%s%s from %s at %s",
410 userId, GetConfValue("UserIdSeparator"), extraId,
411 ipAddress, macAddress);
415 /******************************************
416 write close message to syslog
417 ******************************************/
418 void writeCloseToSyslog(char* userId, char* extraId, char* ipAddress, char* macAddress, int openTime){
423 time_l=difftime((int)time(NULL), openTime);
425 min=(time_l-hour*60*60)/60;
426 sec=(time_l-hour*60*60-min*60);
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);
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);
438 /******************************************
439 write session info message to syslog
440 ******************************************/
441 void writeSessionInfoToSyslog(char* userId, char* extraId, char* ipAddress, char* macAddress, int ruleNumber){
443 char detectTimeStr[WORDMAXLN];
446 /* get client info from macinfo table in workdb */
447 GetMacInfoFromWorkDb(macAddress, detectTimeStr, &ttl);
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);
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);
462 /**************************************************
463 routines for debugging output
464 *************************************************/
466 int AddSession(char* macAddress, char* ipAddress, char* userId, char* extraId){
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);
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( )");
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( )");
484 void DelUselessSessions(void){
485 if(debug>1) err_msg("DEBUG:=>delUselessSessions()");
486 delUselessSessions();
487 if(debug>1) err_msg("DEBUG:<=delUselessSessions( )");
489 void DelAllSessions(void){
490 if(debug>1) err_msg("DEBUG:=>delAllSessions()");
492 if(debug>1) err_msg("DEBUG:<=delAllSessions( )");
494 int CloseSession(void* pParam, int argc, char *argv[], char* colName[]){
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);
501 int IsMatchedSessionFound(char* macAddress){
503 if(debug>1) err_msg("DEBUG:=>isMatchedSessionFound(%s)",
505 ret = isMatchedSessionFound(macAddress);
506 if(debug>1) err_msg("DEBUG:(%d)<=isMatchedSessionFound( )",ret);
510 void CloseUnmatchSessions(void){
511 if(debug>1) err_msg("DEBUG:=>closeUnmatchSessions( )");
512 closeUnmatchSessions();
513 if(debug>1) err_msg("DEBUG:<=closeUnmatchSessions( )");
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( )");
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( )");
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( )");
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()");
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()");
549 /********************testmain********************
552 char* ipAddress="192.168.0.120";
553 char* macAddress="00:01:02:03:04:05";
554 char* userId="watanaby";
557 addSession(ipAddress, macAddress, userId, extraId);
559 renewSession(ipAddress);
561 delUselessSessions();
563 delUselessSessions();
564 delSession(ipAddress);
566 ************************************************/