1 /**************************************************
2 OpengateM - MAC address authentication system
3 module for getting parameters from conf file in XML form
4 ezxml library(by Aaron Voisine) is used for handling XML
6 Copyright (C) 2006 Opengate Project Team
7 Written by Yoshiaki Watanabe
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 Email: watanaby@is.saga-u.ac.jp
25 Programmed by Yoshiaki WATANABE
27 **************************************************/
28 #include "opengatemmng.h"
29 #include "../ezxml/ezxml.h"
31 #define CONFIG_VERSION "0.7.5" /* compared to the value in conf file */
32 #define SEPARATOR "/" /* separator used in XML tree description */
35 static ezxml_t xmlRoot=NULL;
36 static ezxml_t xmlExtraSet=NULL;
37 static ezxml_t xmlAuthServer=NULL;
38 static ezxml_t xml=NULL;
39 static ezxml_t xmlSave=NULL;
41 char *getConfValueExtra(char *name);
42 char *getConfValue(char *name);
43 char *convertToFacilityRaw(char *pValue);
44 int selectNextAuthServer(void);
45 char *GetConfAuthServer(char *name);
47 /**************************************************/
48 /* Prepare Conf file to use */
49 /* this is called before syslog setup */
50 /**************************************************/
51 int openConfFile(void){
56 /* parse file and make tree */
57 if((xmlRoot = ezxml_parse_file(CONFIGFILE))==NULL){
59 /* as the syslog is not prepared, error is send to web*/
60 strlcpy(buff, "<H3>Error: Opengate configuration file ",BUFFMAXLN);
61 strlcat(buff, CONFIGFILE,BUFFMAXLN);
62 strlcat(buff, " is not found. Call the administrator.</H3><BR>",BUFFMAXLN);
63 PutMessageToClient(buff);
68 /* to check error, convert to xml */
69 s=ezxml_toxml(xmlRoot); free(s);
71 /* if failed, show error message */
72 errMsg=(char *)ezxml_error(xmlRoot);
75 /* as the syslog is not prepared, error is send to web*/
76 strlcpy(buff, "<H3>Error: Opengate configuration file ",BUFFMAXLN);
77 strlcat(buff, CONFIGFILE,BUFFMAXLN);
78 strlcat(buff, " is illegal. Call the administrator.</H3><HR>",BUFFMAXLN);
79 strlcat(buff, "XML parser message: ", BUFFMAXLN);
80 strlcat(buff, errMsg, BUFFMAXLN);
81 strlcat(buff, "<HR>", BUFFMAXLN);
82 PutMessageToClient(buff);
87 /* check compatibility between conf file and this program (compare version number) */
88 if(isNull(ezxml_attr(xmlRoot, "ConfigVersion"))||
89 (strcmp(CONFIG_VERSION, ezxml_attr(xmlRoot, "ConfigVersion"))!=0)){
90 strlcpy(buff, "<H3>Error: Opengate configuration file ",BUFFMAXLN);
91 strlcat(buff, CONFIGFILE, BUFFMAXLN);
92 strlcat(buff, " has mismatch version.<br> Please update it with ",BUFFMAXLN);
93 strlcat(buff, CONFIGFILE, BUFFMAXLN);
94 strlcat(buff, ".sample.",BUFFMAXLN);
95 PutMessageToClient(buff);
100 /* check the syslog setting */
101 if(atoi(GetConfValue("Syslog/Enable")) &&
102 atoi(GetConfValue("Syslog/Facility"))==0){
104 /* as the syslog is not prepared, error is send to web*/
105 strlcpy(buff, "<H3>Error: correct SYSLOG setting(local0-local7) is not found in Opengate configuration file ",BUFFMAXLN);
106 strlcat(buff, CONFIGFILE,BUFFMAXLN);
107 strlcat(buff, ". Call the administrator.</H3><BR>",BUFFMAXLN);
108 PutMessageToClient(buff);
116 /**************************************************/
117 /* initialize the Config */
118 /**************************************************/
121 /* as debug flag is used many times, put it in static variable */
122 debug=atoi(getConfValue("Debug"));
125 /**************************************************/
126 /* Finish Config file usage */
127 /**************************************************/
128 void closeConfFile(void){
129 if(xmlRoot!=NULL)ezxml_free(xmlRoot);
132 /**************************************************/
133 /* Setup pointer to the matched ExtraSet */
134 /**************************************************/
135 void setupConfExtra(char *userId, char *extraId){
137 char useridfull[USERMAXLN]; /* userid@extraid */
139 /* setup long userid (userid@extraid) */
140 ConcatUserId(useridfull, userId, extraId);
142 /* init as non-ExtraSet */
145 /* search the matching extra set (first match is employed) */
146 for(xml=ezxml_child(xmlRoot, "ExtraSet"); xml; xml=xml->next){
148 /* if ExtraId is exist, check it */
149 if(!isNull(ezxml_attr(xml, "ExtraId"))){
151 /* if not match, go to next ExtraSet */
152 /* ('default' indicated in conf matchs to Null-extraId) */
154 if(strcmp("default", ezxml_attr(xml, "ExtraId"))!=0)continue;
156 if(strcmp(extraId, ezxml_attr(xml, "ExtraId"))!=0)continue;
160 /* if userID pattern is exist, check it */
161 if(!isNull(ezxml_attr(xml, "UserIdPattern"))){
163 /* if not matched, go to next ExtraSet. last-arg 0 means ingore-case */
164 if(RegExMatch(userId,ezxml_attr(xml,"UserIdPattern"),0)==FALSE){
169 /* if UserExtraPattern is exist, check it */
170 /* UserExtraPattern = REGEX pattern matching to "userid@extraid" */
171 if(!isNull(ezxml_attr(xml, "UserExtraPattern"))){
173 /* if not matched, go to next ExtraSet. last-arg 0 means ingore-case */
174 if(RegExMatch(useridfull,ezxml_attr(xml,"UserExtraPattern"),0)==FALSE){
179 /* if UserExtraPtternNot is exist, check it */
180 /* UserExtraPatternNot = REGEX pattern NOT matching to "userid@extraid" */
181 if(!isNull(ezxml_attr(xml, "UserExtraPatternNot"))){
183 /* if matched, go to next ExtraSet. last-arg 0 means ingore-case */
184 if(RegExMatch(useridfull,ezxml_attr(xml,"UserExtraPatternNot"),0)==TRUE){
189 /* found matched ExtraSet */
193 /* if found a matched ExtraSet, save the pointer */
194 if(xml!=NULL) xmlExtraSet=xml;
196 /* change syslog setting */
197 errToSyslog(atoi(GetConfValue("Syslog/Enable")));
198 progName=getProgramName();
199 openlog(progName, LOG_PID, atoi(GetConfValue("Syslog/Facility")));
201 /* reset config setting */
205 /****************************************************/
206 /* regular expression matching */
207 /* inStr : (in) string to match */
208 /* regEx : (in) regular expression */
209 /* caseSensitive : (in) 0=ignore case, 1=sensitive */
210 /* return value : TRUE=match, FALSE=unmatch */
211 /****************************************************/
212 int regExMatch(const char *inStr, const char *regEx, int caseSensitive){
216 char errbuff[WORDMAXLN];
220 errcode=regcomp(®, regEx, REG_NOSUB|REG_EXTENDED);
222 errcode=regcomp(®, regEx, REG_NOSUB|REG_EXTENDED|REG_ICASE);
225 /* if error, return false */
227 regerror(errcode, ®, errbuff, WORDMAXLN);
228 err_msg("ERR at %s#%d: regex message=%s",__FILE__,__LINE__,errbuff);
232 /* if compile is success, check the input string */
234 if(regexec(®, inStr, (size_t)0, NULL, 0)==0) match=TRUE;
238 /* free memory for the compiled regex */
244 /**************************************************/
245 /* get a value for name from Conf file */
246 /* the name[aa/bb/cc] means the path in xml */
247 /* extraSet value is overlayed, if exists */
248 /**************************************************/
249 char *getConfValue(char *name){
253 char buff[BUFFMAXLN];
255 /* AuthServer setting is done in other routine */
256 if(strstr(name,"AuthServer/")==name) return GetConfAuthServer(name);
258 /* copy name to work area */
259 strlcpy(buff,name,BUFFMAXLN);
261 /* get first token */
262 pStr=strtok(buff, SEPARATOR);
264 /* set search start to root of tree */
267 /* search the tree node for the name */
269 xml=ezxml_child(xml, pStr);
270 pStr=strtok(NULL, SEPARATOR);
273 /* get the node value */
274 pValue= ezxml_txt(xml);
276 /* if not get, write error message */
278 err_msg("ERR at %s#%d: cannot get %s from conf file",__FILE__,__LINE__,name);
281 /* get value in extra set matched to name */
282 /* if name is matched in first level, reset all child setting */
283 /*****************************************************************
284 in the following, <CmdPath> and <Timing> for 'user1' is NOT defined
286 <CmdPath>/bin/rmail</CmdPath>
287 <Content>/etc/opengate/warningmail</Content>
288 <Timing>date(now())=date(........)</Timing>
290 <ExtraSet ExtraId="default" UserIdPattern="^user1$|^user2$">
292 <Content>/etc/opengate/warningmail-special</Content>
295 *****************************************************************/
296 if(!isNull(pValueExtra=getConfValueExtra(name))){
300 /* if syslog facility, the id is converted to raw value */
301 if(strcmp(name,"Syslog/Facility")==0){
302 pValue=convertToFacilityRaw(pValue);
305 /* return found value */
309 /************************************************/
310 /* get the value in extra set matched to name */
311 /************************************************/
312 char *getConfValueExtra(char *name){
314 char buff[BUFFMAXLN];
317 if(xmlExtraSet==NULL) return "";
319 /* extract first token in name */
320 strlcpy(buff,name,BUFFMAXLN);
321 pStr=strtok(buff, SEPARATOR);
323 /* get a first level matched node in extra set */
324 /* the first level is not included in the following loop */
325 /* as to prevent partial overlay of sub level value */
326 /* (see 40-lines above) */
327 xml=ezxml_child(xmlExtraSet, pStr);
328 if(xml==NULL) return "";
330 /* search the node matched to name */
331 pStr=strtok(NULL, SEPARATOR);
333 xml=ezxml_child(xml, pStr);
334 pStr=strtok(NULL, SEPARATOR);
337 /* return the found value */
338 return ezxml_txt(xml);
342 /***************************************************/
343 /* get a value for AuthServer param from Conf file*/
344 /* the name[AuthServer/bb/cc] means the xml path */
345 /***************************************************/
346 char *getConfAuthServer(char *name)
350 char buff[BUFFMAXLN];
353 /* copy name to work area */
354 strlcpy(buff,name,BUFFMAXLN);
356 /* get first token */
357 pStr=strtok(buff, SEPARATOR);
359 /* it must be AuthServer. if not return */
360 if(strcmp(pStr, "AuthServer")!=0)return NULL;
362 /* if authserver pointer is not set, set it */
363 if(xmlAuthServer==NULL){
364 if(!selectNextAuthServer()) return NULL;
367 /* set search start to the saved pointer */
370 /* search the tree node for the name */
371 pStr=strtok(NULL, SEPARATOR);
373 xml=ezxml_child(xml, pStr);
374 pStr=strtok(NULL, SEPARATOR);
377 /* get the node value */
378 pValue= ezxml_txt(xml);
380 /* if not get Protocol, write error message */
382 && (strcmp(name,"AuthServer/Protocol")==0) ){
383 err_msg("ERR at %s#%d: cannot get %s from conf file",__FILE__,__LINE__,name);
386 /* return found value */
390 /*****************************************************************/
391 /* select next authserver setting */
392 /* at first call, this selects the first server setting */
393 /* and form second call, this selects the next server setting */
394 /* ResetAuthServerPointer() returns the pointer to first setting */
395 /*****************************************************************/
396 int selectNextAuthServer(void){
398 ezxml_t xmlTmp; /* temporary variable */
400 /* first call (initialize) */
401 /* xmlAuthPointer is the static variable to save authserver pointer */
402 if(xmlAuthServer==NULL){
404 /* if not set, search the first authserver pointer */
405 xmlAuthServer=ezxml_child(xmlRoot, "AuthServer");
407 /* if authserver is found in extra set, pointer is moved to it */
408 if(xmlExtraSet!=NULL){
409 xmlTmp=ezxml_child(xmlExtraSet, "AuthServer");
411 xmlAuthServer=xmlTmp;
416 /* successive calls */
417 /* pointer is moved to next */
419 xmlAuthServer=ezxml_next(xmlAuthServer);
422 /* if not found return False */
423 if(xmlAuthServer==NULL){
430 /*********************************************/
431 /* reset pointer for auth server list */
432 /*********************************************/
433 void resetAuthServerPointer(void){
437 /************************************************************/
438 /* Convart the syslog facility id(string) to raw value(int) */
439 /************************************************************/
440 char *convertToFacilityRaw(char *pValue){
441 static char facility[WORDMAXLN];
444 if (strcmp(pValue, "local0")==0) rawValue=LOG_LOCAL0;
445 else if(strcmp(pValue, "local1")==0) rawValue=LOG_LOCAL1;
446 else if(strcmp(pValue, "local2")==0) rawValue=LOG_LOCAL2;
447 else if(strcmp(pValue, "local3")==0) rawValue=LOG_LOCAL3;
448 else if(strcmp(pValue, "local4")==0) rawValue=LOG_LOCAL4;
449 else if(strcmp(pValue, "local5")==0) rawValue=LOG_LOCAL5;
450 else if(strcmp(pValue, "local6")==0) rawValue=LOG_LOCAL6;
451 else if(strcmp(pValue, "local7")==0) rawValue=LOG_LOCAL7;
454 snprintf(facility, WORDMAXLN, "%d", rawValue);
459 /**************************************************/
460 /* get the first value matched to name */
461 /* (first node of matched lowest level of tree) */
462 /**************************************************/
463 char *getFirstConfValue(char* name){
465 pValue=GetConfValue(name);
467 /* save the pointer now */
470 /* return found value */
474 /**************************************************/
475 /* get the value in sibling of previous get */
476 /* (next node of the lowest level of tree) */
477 /**************************************************/
478 char *getNextConfValue(void){
481 /* recover previous pointer */
485 if(xml==NULL) return "";
486 xml = ezxml_next(xml);
488 /* save for next call */
491 /* get the node value */
492 pValue= ezxml_txt(xml);
494 /* if not get, write error message */
495 if(pValue==NULL) return "";
497 /* return found value */
502 /***********************************************/
503 /***********************************************/
504 int OpenConfFile(void){
506 if(debug>1) err_msg("DEBUG:=>openConfFile( )");
507 ret = openConfFile();
508 if(debug>1) err_msg("DEBUG:(%d)<=openConfFile( )",ret);
512 void CloseConfFile(void){
513 if(debug>1) err_msg("DEBUG:=>closeConfFile( )");
515 if(debug>1) err_msg("DEBUG:<=closeConfFile( )");
518 void SetupConfExtra(char *userId, char *extraId){
519 if(debug>1) err_msg("DEBUG:=>setupConfExtra(%s,%s)",userId, extraId);
520 setupConfExtra(userId, extraId);
521 if(debug>1) err_msg("DEBUG:<=setupConfExtra( )");
524 char *GetConfValue(char *name){
526 if(debug>1) err_msg("DEBUG:=>getConfValue(%s)",name);
527 ret=getConfValue(name);
528 if(debug>1) err_msg("DEBUG:(%s)<=getConfValue( )",ret);
532 char *GetConfValueExtra(char *name){
534 if(debug>1) err_msg("DEBUG:=>getConfValueExtra(%s)",name);
535 ret=getConfValueExtra(name);
536 if(debug>1) err_msg("DEBUG:(%s)<=getConfValueExtra( )",ret);
540 char *GetConfAuthServer(char *name){
542 if(debug>1) err_msg("DEBUG:=>getConfAuthServer(%s)",name);
543 ret=getConfAuthServer(name);
544 if(debug>1) err_msg("DEBUG:(%s)<=getConfAuthServer( )",ret);
548 int SelectNextAuthServer(void){
550 if(debug>1) err_msg("DEBUG:=>selectNextAuthServer( )");
551 ret=selectNextAuthServer();
552 if(debug>1) err_msg("DEBUG:(%d)<=selectNextAuthServer( )",ret);
557 if(debug>1) err_msg("DEBUG:=>initConf( )");
559 if(debug>1) err_msg("DEBUG:<=initConf( )");
562 int RegExMatch(const char *inStr, const char *regEx, int caseSensitive){
564 if(debug>1) err_msg("DEBUG:=>regExMatch(%s,%s)",inStr,regEx,caseSensitive);
565 ret=regExMatch(inStr, regEx,caseSensitive);
566 if(debug>1) err_msg("DEBUG:(%d)<=regExMatch( )",ret);
570 void ResetAuthServerPointer(void){
571 if(debug>1) err_msg("DEBUG:=>resetAuthServerPointer( )");
572 resetAuthServerPointer();
573 if(debug>1) err_msg("DEBUG:<=resetAuthServerPointer( )");
576 char *GetFirstConfValue(char* name){
578 if(debug>1) err_msg("DEBUG:=>getFirstConfValue( )");
579 ret=getFirstConfValue(name);
580 if(debug>1) err_msg("DEBUG:(%s)<=getFirstConfValue( )",ret);
584 char *GetNextConfValue(){
586 if(debug>1) err_msg("DEBUG:=>getNextConfValue( )");
587 ret=getNextConfValue();
588 if(debug>1) err_msg("DEBUG:(%s)<=getNextConfValue( )",ret);