OSDN Git Service

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