OSDN Git Service

modified code to prevent DB inflation
[opengatem/opengatem.git] / mngsrc / util.c
1 /**************************************************
2 OpengateM - MAC address authentication system 
3  module for misc routines
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
25 #include "opengatemmng.h"
26
27
28 /*************************************************/
29 /* formated write                                */
30 /* fd : file descriptor                          */
31 /* fmt : format to write                         */
32 /* ... : terms to write                          */
33 /* usage is same as fprintf                      */
34 /*************************************************/
35 void Writefmt(int fd, const char *fmt, ...){
36   char  buff[BUFFMAXLN];
37   va_list     ap;
38   int nchar, nwrt;
39
40   va_start(ap, fmt);
41   vsnprintf(buff, BUFFMAXLN, fmt, ap);  
42   va_end(ap);
43
44   nchar=strlen(buff);
45   nwrt=write(fd, buff, nchar);
46
47   return;
48 }
49
50 /***********************************************/
51 /* SSL version of WriteFmt                     */
52 /***********************************************/
53 void WritefmtSSL(SSL *fd, const char *fmt, ...){
54   char  buff[BUFFMAXLN];
55   va_list     ap;
56   int nchar, nwrt;
57
58   va_start(ap, fmt);
59   vsnprintf(buff, BUFFMAXLN, fmt, ap);  
60   va_end(ap);
61
62   nchar=strlen(buff);
63   nwrt=SSL_write(fd, buff, nchar);
64
65   return;
66 }
67
68
69 /******************************************************/
70 /* Read one line                                      */
71 /*   fd: file descriptor                              */
72 /*   vptr: input buffer pointer                       */
73 /*   maxlen: buffer length                            */
74 /*                                                    */
75 /* read the string terminated with EOL or EOF         */
76 /* # this function assumes two EOL chars [CR LF]      */ 
77 /*  CRLF is not stored into buffer and is skipped     */
78 /* [abcdCRLFefghCRLF] => store[abcd],remain[efghCRLF] */
79 /*                                                    */
80 /* return value                                       */
81 /*    plus value means the count of read-in chars     */
82 /*    value 0 means NULL line (no-chars & CRLF)       */
83 /*    value -1 means error (errno is set)             */
84 /*    value -2 means EOF (no-chars & EOF)             */ 
85 /******************************************************/
86 ssize_t readln(int fd, void *vptr, size_t maxlen){
87   ssize_t       n, rc;
88   char  *ptr,c;
89
90   ptr=vptr;
91
92   /* pre read */
93   rc = read(fd, &c, 1);
94   if(rc==0) return(-2); /* EOF */
95   if(rc<0) return(-1);  /* ERR */
96
97   /* get char loop */
98   n=0;
99   while(n < maxlen-1) {
100     if ( rc == 1) {      /* get some char */
101       if (iscntrl(c)){         /* get control char (means EOL) */
102         rc = read(fd, &c, 1);  /* skip second EOL char */
103         break;
104       }
105       *ptr++ = c;
106       n++;
107     }else if (rc == 0) { /* EOF (but some chars are read already) */
108       break;
109     } else {             /* ERR */
110       return(-1);
111     }
112     rc = read(fd, &c, 1);
113   }
114   /* null terminate string */  
115   *ptr++ = 0;
116   return(n);
117 }
118
119 /***********************************************/
120 /* SSL version of readIn                       */
121 /***********************************************/
122 ssize_t readlnSSL(SSL *fd, void *vptr, size_t maxlen){
123   ssize_t       n, rc;
124   char  *ptr,c;
125
126   ptr=vptr;
127
128   /* pre read */
129   rc = SSL_read(fd, &c, 1);
130   if(rc==0) return(-2); /* EOF */
131   if(rc<0) return(-1);  /* ERR */
132
133   /* get char loop */
134   n=0;
135   while(n < maxlen-1) {
136     if ( rc == 1) {      /* get some char */
137       if (iscntrl(c)){      /* get control char (means EOL) */
138           rc = SSL_read(fd, &c, 1); /* skip second EOL char */
139           break;
140       }
141       *ptr++ = c;
142       n++;
143     }else if (rc == 0) { /* EOF (but some char are read already */
144       break;
145     } else {             /* ERR */
146       return(-1);
147     }
148     rc = SSL_read(fd, &c, 1);
149   }
150   /* null terminate string */  
151   *ptr++ = 0;
152   return(n);
153 }
154
155 /******************************/
156 /* lock function using fcntl  */
157 /******************************/
158 int lock(int fd){
159   struct flock lck;
160   
161   lck.l_type=F_WRLCK;
162   lck.l_whence=SEEK_SET;
163   lck.l_start=0;
164   lck.l_len=0;
165   return fcntl(fd, F_SETLKW, &lck);
166 }
167   
168 /********************************/
169 /* unlock function using fcntl  */
170 /********************************/
171 int unlock(int fd){
172   struct flock lck;
173
174   lck.l_type=F_UNLCK;
175   lck.l_whence=SEEK_SET;
176   lck.l_start=0;
177   lck.l_len=0;
178   return fcntl(fd, F_SETLK, &lck);
179 }
180
181 /**********************************************/
182 /* return true, if the pointer value is NULL  */
183 /* or pointer points to null(length=0) string */
184 /**********************************************/
185 int isNull(const char *pStr){
186   if(pStr==NULL) return TRUE;
187   if(*pStr=='\0') return TRUE;
188   return FALSE;
189 }
190
191 /**************************************************/
192 /* popen with argument list                       */
193 /* rootPriv: if 1, run command as root user       */
194 /* type : open type "r" or "w"                    */
195 /* path : path of command executing fork/exec     */
196 /* ... : command arguments. last must be (char*)0 */
197 /*  If you use [user entered string] in arguments */
198 /*  sanitize the string to prevent hacking.       */
199 /**************************************************/
200 FILE *Popenl(int rootPriv, const char *type, const char *path, ...){
201   char  commandLine[BUFFMAXLN];
202   va_list     ap;
203   char *pStr;
204   FILE *file;
205
206   /* insert command path */
207   strlcpy(commandLine, path, BUFFMAXLN);
208
209   /* insert command arguments */
210   va_start(ap, path);
211   
212   while((pStr=va_arg(ap, char *))!=(char *)0){
213     strcat(commandLine, " ");
214     strlcat(commandLine, pStr, BUFFMAXLN);
215   }
216   free(pStr);
217   va_end(ap);
218
219   /* if desired, add root privilege */
220   if(rootPriv==1){
221     if(seteuid(0)!=0){
222       err_msg("ERR at %s#%d: cannot add root privilege ",
223               __FILE__,__LINE__);
224     } 
225   }
226
227   /* open the pipe to the program  */
228   if(debug>1) err_msg("DEBUG:=>popen(%s, %s)", commandLine, type);
229   file=popen(commandLine, type);
230   if(debug>1) err_msg("DEBUG:(%x)<=popen( )",file);  
231
232   /* remove root privilege */
233   seteuid(getuid()); 
234
235   return file;
236 }
237
238
239 /**************************************************/
240 /* system with argument list                      */
241 /* rootPriv: if 1, run command as root user       */
242 /* path : command path to fork/exec               */
243 /* ... : command arguments. last must be (char*)0 */
244 /*  If you use [user entered string] in arguments */
245 /*  sanitize the string to prevent hacking.       */
246 /**************************************************/
247 int Systeml(int rootPriv, const char *path, ...){
248   char  commandLine[BUFFMAXLN];
249   va_list     ap;
250   char *pStr;
251   int ret;
252
253   /* insert command path */
254   strlcpy(commandLine, path, BUFFMAXLN);
255
256   /* insert command arguments */
257   va_start(ap, path);
258   
259   while((pStr=va_arg(ap, char *))!=(char *)0){
260     strcat(commandLine, " ");
261     strlcat(commandLine, pStr, BUFFMAXLN);
262   }
263   free(pStr);
264   va_end(ap);
265
266   /* if desired, add root privilege */
267   if(rootPriv==1){
268     if(seteuid(0)!=0){
269       err_msg("ERR at %s#%d: cannot add root privilege ",
270               __FILE__,__LINE__);
271     } 
272   }
273
274   /* execute shell  */
275   if(debug>1) err_msg("DEBUG:=>system(%s)", commandLine);
276   ret=system(commandLine);
277   if(debug>1) err_msg("DEBUG:<=system()");
278
279   /* remove root privilege */
280   seteuid(getuid()); 
281   return ret;
282 }
283
284 /*************************************************/
285 /* calc MD5 and return in hex form               */
286 /*  str: (input)plain text to convert            */
287 /*  hexdigest: (output) converted hex string     */
288 /*      prepare buff more or equal to 33chars    */
289 /*  len: (input) length of hexdigest buffer      */
290 /*************************************************/
291 char *md5hex(char *hexdigest, int len, char *str){
292   char unsigned digest[16];
293   char hexcode[16]="0123456789abcdef";
294   int i;
295   
296   /* if not enough buffer, exit */
297   if(len<33){
298     *hexdigest='\0';
299     return hexdigest;
300   }
301
302   /* calc MD5 digest */
303   MD5((unsigned char*)str, strlen(str), digest);
304
305   /* convert to HEX string */
306   for(i=0;i<16;i++){
307     hexdigest[2*i]=hexcode[digest[i]/16];
308     hexdigest[2*i+1]=hexcode[digest[i]%16];
309   }
310   hexdigest[2*16]='\0';
311
312   return hexdigest;
313 }
314
315 /*******************************************/
316 /* create random session cookie            */
317 /* as md5hex(processId.TimeNow)            */
318 /*******************************************/
319 void createCookie(char *cookie)
320 {
321   char str[BUFFMAXLN];
322
323   /* make Http-cookie from pid&time */
324   snprintf(str, BUFFMAXLN, "%d%ld", getpid(),time(NULL));
325   md5hex(cookie, SIDMAXLN, str);
326 }
327
328 /********************************************/
329 /* get port number defined in /etc/services */
330 /* return as string form                    */
331 /********************************************/
332 char *getServicePortStr(char *servName){
333   struct servent *pServEnt;
334   static char portStr[WORDMAXLN];
335
336   /* get service info from service name */
337   pServEnt = getservbyname(servName, NULL);
338
339   if(pServEnt==NULL){
340     err_msg("ERR at %s#%d: cannot find /etc/services entry for %s",
341             __FILE__,__LINE__,servName);
342     return "";
343   }
344
345   /* convert service port number to string form */
346   snprintf(portStr, sizeof(portStr),"%d",ntohs(pServEnt->s_port));
347
348   return portStr;
349 }
350
351 /**************************************************************/
352 /* get env value from string including multiple env-var       */
353 /*                                                            */
354 /* if string(env) = "ab cd-ef-gh ijk"                         */
355 /*  repert the search of env-var having non-null value        */
356 /*  getenv("ab"),getenv("cd_ef_gh"),getenv("ijk")             */
357 /* if pre=TRUE convert '-' to '_' in env-var before search    */
358 /* if post=TRUE convert ' '|'@' to '_' in get-str after search*/
359 /**************************************************************/
360 char* getenvEx(char* env, int pre, int post){
361   char work[BUFFMAXLN];
362   char* envValue="";
363   char* p=NULL;
364   char* thisVar=NULL;
365   char* nextVar=NULL;
366   int found=FALSE;
367
368   /* copy string to work area */
369   strlcpy(work, env, BUFFMAXLN);
370
371   /* repeat from the head to the tail of the work area */
372   thisVar=nextVar=work;
373   while(!isNull(thisVar)){
374
375     /* skip preceeding spaces in string, and points the head of vairable */
376     for(p=thisVar; *p==' '; p++);
377     thisVar=p;
378
379     /* search space (=the end of this variable) */
380     for(p=thisVar; (*p!=' ' && *p!='\0'); p++);
381
382     /* points the next variable */
383     if(*p=='\0') nextVar=p; /* end of string */
384     else{                   /* some string follows */
385       *p='\0';                /* set termination char of this variable */
386       nextVar=p+1;            /* set the next search point */
387     }
388
389     /* if PRE is true, replace '-' in string with '_' */
390     if(pre){
391       for(p=thisVar; *p!='\0'; p++){
392         if(*p=='-') *p='_';
393       }
394     }
395
396     /* exeute getenv. if success, exit loop */
397     envValue = getenv(thisVar);
398     if(!isNull(envValue)){
399       found=TRUE;
400       break;
401     }
402
403     /* try next variable */
404     thisVar=nextVar;
405   }
406
407   /* getting no data */
408   if(!found) return NULL;
409
410   /* if POST is true, convert ' ' and '@' to '_' */
411   if(post){
412     for(p=envValue; *p!='\0'; p++){
413       if(*p==' ') *p='_';
414       if(*p=='@') *p='_';
415     }
416   }
417
418   return envValue;
419 }
420
421 /*********************************************************/
422 /* TCP Connection routine                                 */
423 /*  from UNIX NETWORK PROGRAMMING,Vol.1,Second Edition,   */
424 /*      By W. Richard Stevens, Published By Prentice Hall */
425 /*       ftp://ftp.kohala.com/pub/rstevens/unpv12e.tar.gz */
426 /**********************************************************/
427 int tcp_connect(const char *host, const char *serv){
428         int                             sockfd, n;
429         struct addrinfo hints, *res, *ressave;
430
431         bzero(&hints, sizeof(struct addrinfo));
432         hints.ai_family = AF_UNSPEC;
433         hints.ai_socktype = SOCK_STREAM;
434
435         if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0){
436                 err_msg("tcp_connect error for %s, %s: %s",
437                                  host, serv, gai_strerror(n));
438                 return -1;
439         }
440         ressave = res;
441
442         do {
443                 sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
444                 if (sockfd < 0)
445                         continue;       /* ignore this one */
446
447                 if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
448                         break;          /* success */
449
450                 Close(sockfd);  /* ignore this one */
451         } while ( (res = res->ai_next) != NULL);
452
453         if (res == NULL){       /* errno set from final connect() */
454                 err_msg("tcp_connect error for %s, %s", host, serv);
455                 return -1;
456         }
457
458         freeaddrinfo(ressave);
459
460         return(sockfd);
461 }
462
463 /****************************************/
464 /****************************************/
465 void CreateCookie(char *cookie){
466   if(debug>1) err_msg("DEBUG:=>createCookie( )");
467   createCookie(cookie);
468   if(debug>1) err_msg("DEBUG:<=createCookie(%s)", cookie);  
469 }
470
471 char *GetServicePortStr(char *servName){
472   char *ret;
473   if(debug>1) err_msg("DEBUG:=>getServicePortStr(%s)", servName);
474   ret = getServicePortStr(servName);
475   if(debug>1) err_msg("DEBUG:(%s)<=getServicePortStr( )", ret);  
476   return ret;
477 }
478
479 int Pclose(FILE *stream){
480   int ret;
481
482   if(debug>1) err_msg("DEBUG:=>pclose( )");
483   ret = pclose(stream);
484   if(debug>1) err_msg("DEBUG:<=pclose( )");  
485
486   return ret;
487 }
488
489 int Lock(int fd){
490   int ret;
491
492   if(debug>1) err_msg("DEBUG:=>lock( )");
493   ret=lock(fd);
494   if(debug>1) err_msg("DEBUG:(%d)<=lock( )",ret);
495
496   return ret;
497 }
498
499 int Unlock(int fd){
500   int ret;
501
502   if(debug>1) err_msg("DEBUG:=>unlock( )");
503   ret=unlock(fd);
504   if(debug>1) err_msg("DEBUG:(%d)<=unlock( )",ret);
505
506   return ret;
507 }
508
509 int Open(const char *pathname, int oflag, mode_t mode){
510         int             fd;
511
512         if ( (fd = open(pathname, oflag, mode)) == -1)
513                 err_msg("open error for %s", pathname);
514         return(fd);
515 }
516
517 int Close(int fd){
518   int ret;
519
520   /*if( (ret=close(fd)) == -1)
521    *  err_msg("close error");
522    */
523
524   ret=close(fd);
525
526   return ret;
527 }
528
529 pid_t Fork(void){
530         pid_t   pid;
531
532         if ( (pid = fork()) == -1)
533                 err_msg("fork error");
534         return(pid);
535 }
536
537 int Pipe(int *fds){
538   int ret;
539         if ((ret=pipe(fds)) < 0)
540                 err_msg("pipe error");
541
542         return ret;
543 }
544
545 void *Malloc(size_t size){
546         void    *ptr;
547
548         if ( (ptr = malloc(size)) == NULL)
549                 err_msg("malloc error");
550         return(ptr);
551 }
552
553 int Tcp_connect(const char *host, const char *serv){
554         return(tcp_connect(host, serv));
555 }
556