OSDN Git Service

Ver1.5.28 Changed to deny duplicated open, added udp send and ohters.
[opengate/opengate.git] / opengate / opengatesrv / utilities.c
1 /**************************************************
2 opengate server
3  utility routines
4
5 Copyright (C) 1999 Opengate Project Team
6 Written by Yoshiaki Watanabe
7 Modified Katsuhiko Eguchi, 2005 
8
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.
13
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.
18
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.
22
23 Email: watanaby@is.saga-u.ac.jp
24 **************************************************/
25
26 #include "opengatesrv.h"
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 /******************************/
158 /* lock functions using fcntl */
159 /******************************/
160 int lock(int fd)
161 {
162   struct flock lck;
163   
164   lck.l_type=F_WRLCK;
165   lck.l_whence=SEEK_SET;
166   lck.l_start=0;
167   lck.l_len=0;
168   return fcntl(fd, F_SETLKW, &lck);
169 }
170   
171 /********************************/
172 /* unlock functions using fcntl */
173 /********************************/
174 int unlock(int fd)
175 {
176   struct flock lck;
177
178   lck.l_type=F_UNLCK;
179   lck.l_whence=SEEK_SET;
180   lck.l_start=0;
181   lck.l_len=0;
182   return fcntl(fd, F_SETLK, &lck);
183 }
184
185 /**************************************/
186 /* check NULL or point to null string */
187 /**************************************/
188 int isNull(const char *pStr)
189 {
190   if(pStr==NULL) return TRUE;
191   if(*pStr=='\0') return TRUE;
192   return FALSE;
193 }
194
195
196
197 /**************************************************/
198 /* popen with argument list                       */
199 /* rootPriv: if 1, run command as root user       */
200 /* type : open type "r" or "w"                    */
201 /* path : command path to fork/exec               */
202 /* ... : command arguments. last must be (char*)0 */
203 /*  DO NOT SET user entered string in args        */
204 /**************************************************/
205 FILE *Popenl(int rootPriv, const char *type, const char *path, ...)
206 {
207   char  commandLine[BUFFMAXLN];
208   va_list     ap;
209   char *pStr;
210   FILE *file;
211
212   /* insert command path */
213   strncpy(commandLine, path, BUFFMAXLN);
214
215   /* insert command arguments */
216   va_start(ap, path);
217   
218   while((pStr=va_arg(ap, char *))!=(char *)0){
219     strcat(commandLine, " ");
220     strncat(commandLine, pStr, BUFFMAXLN);
221   }
222
223   va_end(ap);
224
225   /* if desired, add root privilege */
226   if(rootPriv==1){
227     if(seteuid(0)!=0){
228       err_msg("ERR at %s#%d: cannot add root privilege ",
229               __FILE__,__LINE__);
230     } 
231   }
232
233   /* open the pipe to the program  */
234   if(debug>1) err_msg("DEBUG:=>popen(%s, %s)", commandLine, type);
235   file=popen(commandLine, type);
236   if(debug>1) err_msg("DEBUG:(%x)<=popen( )",file);  
237
238   /* remove root privilege */
239   seteuid(getuid()); 
240
241   return file;
242 }
243
244
245 /**************************************************/
246 /* system with argument list                      */
247 /* rootPriv: if 1, run command as root user       */
248 /* path : command path to fork/exec               */
249 /* ... : command arguments. last must be (char*)0 */
250 /*  DO NOT SET user entered string in args        */
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
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
288   return ret;
289 }
290
291 /*******************************************/
292 /* get port number string in /etc/services */
293 /*******************************************/
294 char *getServicePortStr(char *servName)
295 {
296   struct servent *pServEnt;
297   static char portStr[WORDMAXLN];
298
299   /* get service info from service name */
300   pServEnt = getservbyname(servName, NULL);
301
302   if(pServEnt==NULL){
303     err_msg("ERR at %s#%d: cannot find /etc/services entry for %s",
304             __FILE__,__LINE__,servName);
305     return "";
306   }
307
308   /* convert service port number to string form */
309   snprintf(portStr, sizeof(portStr),"%d",ntohs(pServEnt->s_port));
310
311   return portStr;
312 }
313
314 /*******************************************/
315 /* create random session id                */
316 /*  simple but might be overlapped         */
317 /*  change logic, if you need identical id */ 
318 /*******************************************/
319 void createSessionId(char *sessionId)
320 {
321   srandom(getpid()+time(NULL));
322   snprintf(sessionId, SIDMAXLN, "%ld", random() );
323 }
324
325 /*************************************************/
326 /* calc MD5 in hex form                          */
327 /*  str: plain text to convert                   */
328 /*  hexdigest: converted hex string              */
329 /*      prepare buff more or equal to 33chars    */
330 /*  len: length of hexdigest buffer              */
331 /*************************************************/
332 char *md5hex(char *hexdigest, int len, char *str)
333 {
334   char unsigned digest[16];
335   char hexcode[16]="0123456789abcdef";
336   int i;
337   
338   /* if not enough buffer, exit */
339   if(len<33){
340     *hexdigest='\0';
341     return hexdigest;
342   }
343
344   /* calc MD5 digest */
345   MD5((unsigned char*)str, strlen(str), digest);
346
347   /* convert to HEX string */
348   for(i=0;i<16;i++){
349     hexdigest[2*i]=hexcode[digest[i]/16];
350     hexdigest[2*i+1]=hexcode[digest[i]%16];
351   }
352   hexdigest[2*16]='\0';
353
354   return hexdigest;
355 }
356
357 /*******************************************/
358 /* create random session cookie            */
359 /*******************************************/
360 void createCookie(char *cookie)
361 {
362   char str[BUFFMAXLN];
363
364   /* make Http-cookie from pid&time */
365   snprintf(str, BUFFMAXLN, "%d%d", getpid(),time(NULL));
366   md5hex(cookie, SIDMAXLN, str);
367 }
368
369 /****************************************************/
370 /* getenv for multiple variables                    */
371 /*             after replacing '-' with '_'         */
372 /*                                                  */
373 /* if env = "ab cd-ef-gh ijk"                       */
374 /*  repeat getenv until getting non-null value      */
375 /*  getnev("ab"),getenv("cd_ef_gh"),getenv("ijk")   */
376 /* if pre=TRUE convert '-' to '_' in env-var name   */
377 /* if post=TRUE convert ' '|'@' to '_' in get-str   */
378 /****************************************************/
379 char* getenvEx(char* env, int pre, int post){
380   char work[BUFFMAXLN];
381   char* envValue="";
382   char* p=NULL;
383   char* thisVar=NULL;
384   char* nextVar=NULL;
385   int found=FALSE;
386
387   /* copy string not to destroy it */
388   strncpy(work, env, BUFFMAXLN);
389
390   /* repeat for variables */
391   thisVar=nextVar=work;
392
393   while(!isNull(thisVar)){
394
395     /* skip preceeding space in string */
396     for(p=thisVar; *p==' '; p++);
397     thisVar=p;
398
399     /* search space (end of this variable) */
400     for(p=thisVar; (*p!=' ' && *p!='\0'); p++);
401
402     /* prepare next variable */
403     if(*p=='\0') nextVar=p; /* end of env string */
404     else{                   /* some variales follows */
405       *p='\0';                /* set end of this variable */
406       nextVar=p+1;            /* and start of next variable */
407     }
408
409     /* replace '-' in string with '_' */
410     if(pre){
411       for(p=thisVar; *p!='\0'; p++){
412         if(*p=='-') *p='_';
413       }
414     }
415
416     /* exeute getenv. if success, exit loop */
417     envValue = getenv(thisVar);
418     if(!isNull(envValue)){
419       found=TRUE;
420       break;
421     }
422
423     /* try next variable */
424     thisVar=nextVar;
425   }
426
427   /* getting no data */
428   if(!found) return NULL;
429
430   /* convert ' ' and '@' to '_' */
431   if(post){
432     for(p=envValue; *p!='\0'; p++){
433       if(*p==' ') *p='_';
434       if(*p=='@') *p='_';
435     }
436   }
437
438   return envValue;
439 }
440
441 /****************************************/
442 /* routine for debug output             */
443 /****************************************/
444 int Pclose(FILE *stream)
445 {
446   int ret;
447   if(debug>1) err_msg("DEBUG:=>pclose( )");
448   ret = pclose(stream);
449   if(debug>1) err_msg("DEBUG:<=pclose( )");  
450   return ret;
451 }
452
453 char *GetServicePortStr(char *servName)
454 {
455   char *ret;
456   if(debug>1) err_msg("DEBUG:=>getServicePortStr(%s)", servName);
457   ret = getServicePortStr(servName);
458   if(debug>1) err_msg("DEBUG:(%s)<=getServicePortStr( )", ret);  
459   return ret;
460 }
461
462 ssize_t Readln(int fd, void *ptr, size_t maxlen)
463 {
464   ssize_t               n;
465   if(debug>1) err_msg("DEBUG:=>readln( )");
466   if ( (n = readln(fd, ptr, maxlen)) < 0){
467     err_msg("ERR at %s#%d: readln error",__FILE__,__LINE__);
468   }
469   if(debug>1) err_msg("DEBUG:(%d)<=readln( )",n);
470   return(n);
471 }
472
473 int Lock(int fd)
474 {
475   int ret;
476   if(debug>1) err_msg("DEBUG:=>lock( )");
477   ret=lock(fd);
478   if(debug>1) err_msg("DEBUG:(%d)<=lock( )",ret);
479   return ret;
480 }
481
482 int Unlock(int fd)
483 {
484   int ret;
485   if(debug>1) err_msg("DEBUG:=>unlock( )");
486   ret=unlock(fd);
487   if(debug>1) err_msg("DEBUG:(%d)<=unlock( )",ret);
488   return ret;
489 }
490
491 void CreateSessionId(char *sessionId){
492   if(debug>1) err_msg("DEBUG:=>createSessionId( )");
493   createSessionId(sessionId);
494   if(debug>1) err_msg("DEBUG:<=createSessionId(%s)",sessionId);
495 }
496 void CreateCookie(char *cookie){
497   if(debug>1) err_msg("DEBUG:=>createCookie( )");
498   createCookie(cookie);
499   if(debug>1) err_msg("DEBUG:<=createCookie(%s)",cookie);
500 }