OSDN Git Service

Ver.1.4.7: Fix bugs. Add proc time measurement code.
[opengate/opengate.git] / opengate / opengatesrv / comm-cgi.c
1 /**************************************************
2 Opengate server
3  module for Communication through CGI 
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 Programmed by Yoshiaki WATANABE
26 Modified by Shin-ichi TADAKI
27 Modified by Katsuhiko Eguchi
28 **************************************************/
29
30 #include        "opengatesrv.h"
31
32 /* convert two-char-hex "aa" to one-number 0Xaa */ 
33 #define hex2num(x)  ((x)>='A' ? ((x) & 0XDF) - 'A' +10 : ((x) - '0'))
34
35 int isHttpWatchEnableClient(void);
36 int isJavaWatchEnableClient(void);
37 void split(char content[], char *name[], char *value[], char *next[]);
38 void decode(char *string);
39
40 char language[WORDMAXLN]; /* message language in java applet */
41
42 /*******************************/
43 /* get the client addr         */
44 /*******************************/
45 void getClientAddr(char *clientAddr)
46 {
47   strncpy(clientAddr, getenv("REMOTE_ADDR"), ADDRMAXLN);
48 }
49
50 /********************************************/
51 /* get Post data from the client  */
52 /********************************************/
53 int getPostData(char *userid, char *password, char *clientAddr4, int *durationPtr, char *watchMode)
54 {
55   int contentLen;
56   char content[BUFFMAXLN];
57   char *name[1];
58   char *value[1];
59   char *next[1];
60   char *ptr;
61   char durationStr[WORDMAXLN];
62   char langList[BUFFMAXLN];
63   char encodeAddr4[ADDRMAXLN];
64   char accessAddr[ADDRMAXLN];
65
66   /* get content sent from web input */
67   if(getenv("CONTENT_LENGTH")==NULL){
68     err_msg("ERR at %s#%d: CONTENT_LENGTH is not defined",__FILE__,__LINE__);
69     return FALSE;
70   }
71
72   contentLen=atoi(getenv("CONTENT_LENGTH"));
73   if(contentLen==0){
74     err_msg("ERR at %s#%d: CONTENT_LENGTH is zero",__FILE__,__LINE__);
75     return FALSE;
76   }
77
78   contentLen++; /* for terminate ch */
79   if(contentLen > BUFFMAXLN) contentLen=BUFFMAXLN;
80   if(fgets(content, contentLen, stdin) == NULL){
81     content[0]='\0';
82   }
83
84   /* get items from string */
85   userid[0]='\0';
86   password[0]='\0';
87   encodeAddr4[0]='\0';
88   language[0]='\0';
89   durationStr[0]='\0';
90
91   ptr=content;
92
93   while(ptr!=NULL){
94     split(ptr, name, value, next);
95
96     if(strstr(name[0], "userid")!=NULL){
97       strncpy(userid, value[0], USERMAXLN);
98     }else if(strstr(name[0], "password")!=NULL){
99       strncpy(password, value[0], PASSMAXLN);
100     }else if(strstr(name[0],"remote_addr")!=NULL){
101       strncpy(encodeAddr4,value[0],ADDRMAXLN);
102     }else if(strstr(name[0], "language")!=NULL){
103       strncpy(language, value[0], WORDMAXLN);
104     }else if(strstr(name[0], "duration")!=NULL){
105       strncpy(durationStr, value[0], WORDMAXLN);
106     }else if(strstr(name[0], "watchmode")!=NULL){
107       strncpy(watchMode, value[0], WORDMAXLN);
108     }
109     ptr=next[0];
110   }
111
112   /* decode the HTTP encoding */
113   decode(userid);
114   decode(password);
115   decode(encodeAddr4);
116   decode(language);
117   decode(durationStr);
118   decode(watchMode);
119
120  /* if not available language, use first lang */
121   strncpy(langList, GetConfValue("HtmlLangs"), BUFFMAXLN);  /* list of available languages */
122   if(strstr(langList,language)==NULL){
123     sscanf(langList,"%s",language);
124   }
125   
126   /* convert duration string to interger and minutes to seconds */
127   *durationPtr = atoi(durationStr)*60;
128
129   /* usage duration is restricted to permitted range */
130   if(*durationPtr <= 0){
131     *durationPtr=atoi(GetConfValue("Duration/Default"));
132   }else{
133     int durmax=atoi(GetConfValue("Duration/Max"));
134     if(*durationPtr > durmax) *durationPtr=durmax;
135   }
136
137   /* encoded address starting as "0-0-0" means no addr info */
138   /* it indicates needless to get dual stack addresses */
139   /* and only use getenv("REMOTE_ADDR") address */
140   if(strnstr(encodeAddr4, "0-0-0", ADDRMAXLN)==encodeAddr4){
141     clientAddr4[0]='\0';
142   }
143       
144   /* decode client address to dot separated form */
145   else if(AddrDecode(clientAddr4, encodeAddr4)==1){
146     /* if can't decode, retry */
147     err_msg("ERR at %s#%d: Cannot decode client address",__FILE__,__LINE__);
148     return FALSE;
149   }
150
151   /* if the decoded IPv4 addr is not same as access IPv4 addr, use later */
152   strncpy(accessAddr, getenv("REMOTE_ADDR"), ADDRMAXLN);
153   if((strnstr(accessAddr, ".", ADDRMAXLN)!=NULL)   /* access is IPv4 */
154      && strncmp(accessAddr, clientAddr4, ADDRMAXLN)!=0){  /* and not same */
155     strncpy(clientAddr4, accessAddr, ADDRMAXLN);
156   }
157   return TRUE;
158 }
159
160
161 /*********************************************/
162 /* deny message to the client            */
163 /*********************************************/
164 void putClientDeny(char *clientAddr4)
165 {
166   char denydoc[BUFFMAXLN];
167   char authCgiUrl[BUFFMAXLN];
168   char encodeAddr[ADDRMAXLN];
169
170   /* keyword pairs */
171   /*  the left key is replaced by the right value */
172   struct html_key keys[]=
173     {
174       {"%%AUTHCGIURL%%", authCgiUrl},
175       {"%%ADDR4%%", encodeAddr},
176       {"",""}  /* DON'T REMOVE THIS LINE */
177     };
178  
179   /* create authcgi URL string */
180   snprintf(authCgiUrl, BUFFMAXLN, "%s%s%s/%s",
181            GetConfValue("OpengateServerName"),
182            GetConfValue("CgiDir"),
183            GetConfValue("OpengateDir"),
184            GetConfValue("AuthCgi"));
185
186   /* create encoded addr4 */
187   if(AddrEncode(encodeAddr, clientAddr4)==1){
188     encodeAddr[0]='\0';
189   }
190
191   /* make path to the denydoc for ssl or non-ssl */
192   if(strcmp(getenv("SERVER_PORT"),GetServicePortStr("https"))==0){
193     snprintf(denydoc, BUFFMAXLN, "%s%s/%s/%s",GetConfValue("DocumentRoot"),
194             GetConfValue("OpengateDir"),language,GetConfValue("DenyDocSsl"));
195   }else{
196     snprintf(denydoc, BUFFMAXLN, "%s%s/%s/%s",GetConfValue("DocumentRoot"),
197             GetConfValue("OpengateDir"),language,GetConfValue("DenyDoc"));
198   }
199
200   /* replace keyword and send out the file */
201   printf("Content-type: text/html\r\n\r\n\r\n");
202   HtmlTemplate(denydoc, keys);
203
204   return;
205 }
206 /*********************************************/
207 /* deny message to the client            */
208 /*********************************************/
209 void putClientRetry(char *lang)
210 {
211   char retrydoc[BUFFMAXLN];
212   char externalUrl[BUFFMAXLN];
213   char authCgiUrl[BUFFMAXLN];
214
215   /* keyword pairs */
216   /*  the left key is replaced by the right value */
217   struct html_key keys[]=
218     {
219       {"%%EXTERNALURL%%", externalUrl},
220       {"%%AUTHCGIURL%%", authCgiUrl},
221       {"",""}  /* DON'T REMOVE THIS LINE */
222     };
223  
224   /* create external URL string */
225   strncpy(externalUrl, GetConfValue("ExternalUrl"), BUFFMAXLN);
226
227   /* create authcgi URL string */
228   snprintf(authCgiUrl, BUFFMAXLN, "%s%s%s/%s",
229            GetConfValue("OpengateServerName"),
230            GetConfValue("CgiDir"),
231            GetConfValue("OpengateDir"),
232            GetConfValue("AuthCgi"));
233
234   /* make read in path to the retry document */
235   snprintf(retrydoc, BUFFMAXLN, "%s%s/%s/%s",GetConfValue("DocumentRoot"),
236           GetConfValue("OpengateDir"),lang,GetConfValue("RetryDoc"));
237
238   /* replace keyword and send out the file */
239   printf("Content-type: text/html\r\n\r\n\r\n");
240   HtmlTemplate(retrydoc, keys);
241
242   return;
243 }
244
245 /*********************************************/
246 /* put some message to the client            */
247 /*********************************************/
248 void putClientMsg(char *message)
249 {
250   printf("Content-type: text/html\r\n\r\n\r\n");
251   printf("<HTML><HEAD><TITLE>OpengateMsg</TITLE></HEAD> \r\n");
252   printf("<BODY>         \r\n");
253   printf("%s\r\n",     message);
254   printf("</BODY></HTML> \r\n\r\n");
255
256 }
257
258 /*********************************************/
259 /* put accept message and java to the client */
260 /*********************************************/
261 void putClientAccept(char *userid, char *sessionId, int port, int pid, char *clientAddr4, char *clientAddr6, int ipStatus, int duration, char *watchMode)
262 {
263   FILE *fp;
264   char buff[BUFFMAXLN];
265   char acceptdoc[BUFFMAXLN];
266   char acceptdoc2url[BUFFMAXLN];
267   char terminateurl[BUFFMAXLN];
268   char httpkeepUrl[BUFFMAXLN];
269   char portStr[WORDMAXLN];
270   char durationStr[WORDMAXLN];
271   char *acceptDoc;
272
273   char *startPageUrl=GetConfValue("StartPage/Url");
274   int startPageType=atoi(GetConfValue("StartPage/Type"));
275   char *opengateDir=GetConfValue("OpengateDir");
276
277   /* select proper accept doc */
278   switch(watchMode[0]){
279
280     /* HTTP watch mode */
281   case 'H':
282     if(isHttpWatchEnableClient()){
283       acceptDoc=GetConfValue("AcceptDocHttp");
284     }else if(isJavaWatchEnableClient()){
285       acceptDoc=GetConfValue("AcceptDocJava");
286     }else{
287       acceptDoc=GetConfValue("AcceptDocTime");
288     }
289     break;
290
291     /* JAVA watch mode */
292   case 'J':
293     if(isJavaWatchEnableClient()){
294       acceptDoc=GetConfValue("AcceptDocJava");
295     }else if(isHttpWatchEnableClient()){
296       acceptDoc=GetConfValue("AcceptDocHttp");
297     }else{
298       acceptDoc=GetConfValue("AcceptDocTime");
299     }
300     break;
301
302     /* TIMEOUT watch mode */
303   case 'T':
304     acceptDoc=GetConfValue("AcceptDocTime");
305     break;
306
307   default:
308     err_msg("ERR at %s#%d: Unknown watch mode [%s]",__FILE__,__LINE__,watchMode); 
309     acceptDoc=GetConfValue("AcceptDocJava");
310   }
311
312   /* create path to acceptdoc */
313   snprintf(acceptdoc, BUFFMAXLN, "%s%s/%s/%s",GetConfValue("DocumentRoot"),
314          GetConfValue("OpengateDir"),language,acceptDoc);
315
316
317   snprintf(acceptdoc2url, BUFFMAXLN, 
318           "http://%s%s/%s/%s",GetConfValue("OpengateServerName"),
319           GetConfValue("OpengateDir"),language,GetConfValue("AcceptDoc2"));
320
321   /* create terminate url [http://<servaddr>:<port>/terminate-<pid>] */
322   snprintf(terminateurl, BUFFMAXLN, "http://%s:%d/terminate-%d", 
323           GetConfValue("OpengateServerName"), port, getpid());
324
325   /* create httpkeep page url
326      ['http://<servaddr>:<port>/httpkeep-<userid>'] */
327   snprintf(httpkeepUrl, BUFFMAXLN,
328            "'http://%s:%d/httpkeep-%s-%s'", 
329           GetConfValue("OpengateServerName"), port, userid,sessionId);
330
331   /* create port string */
332   snprintf(portStr, WORDMAXLN, "%d", port);
333
334   /* create duration string (duration=sec, display value=min) */
335   snprintf(durationStr, WORDMAXLN, "%d", duration/60);
336
337   /* open acceptdoc */
338   if((fp=fopen(acceptdoc, "r"))==NULL){
339     err_msg("ERR at %s#%d: cannot open %s",__FILE__,__LINE__,acceptdoc);
340     PutClientMsg("Cannot find html document");
341     return;
342   }
343
344   /* read html document from file and send to web */
345   printf("Content-type: text/html\r\n\r\n\r\n");
346   while(fgets(buff, BUFFMAXLN, fp)!=NULL){
347
348     /* length check */
349     if(strlen(buff)>=BUFFMAXLN-1){
350       err_msg("ERR at %s#%d: too long line in %s",__FILE__,__LINE__,acceptdoc);
351     }
352
353     /* replace mark */
354     htmlReplace(buff, "%%OPENGATEDIR%%", opengateDir);
355     htmlReplace(buff, "%%OPENGATEPORT%%", portStr);
356     htmlReplace(buff, "%%DURATION%%", durationStr);
357     htmlReplace(buff, "%%USERID%%", userid);
358     htmlReplace(buff, "%%SESSIONID%%", sessionId);
359     htmlReplace(buff, "%%LANGUAGE%%", language);
360     
361     htmlReplace(buff, "%%TERMINATEURL%%", terminateurl);
362     htmlReplace(buff, "%%HTTPKEEPURL%%", httpkeepUrl);
363     
364     /* replace information url mark */
365     if( startPageType==1 ){
366       htmlReplace(buff, "%%STARTURL%%", startPageUrl);
367     }else{
368       htmlReplace(buff, "%%STARTURL%%", acceptdoc2url);
369     }
370     
371     /* write out */
372     printf("%s",buff);
373   }
374   /* write end */
375   fputs("\r\n\r\n",stdout);
376   fclose(fp);
377
378   return;
379 }
380
381 /*****************************************************/
382 /* is the client enable to keep long http connection */
383 /*****************************************************/
384 int isHttpWatchEnableClient(void)
385 {
386   /* HTTP Keep-Alive is not standard in http/1.0 */
387   if(strcmp(getenv("SERVER_PROTOCOL"),"HTTP/1.0")==0) return FALSE;
388
389   /* some user agent does not support long HTTP Keep-Alive */
390   if(RegExMatch(getenv("HTTP_USER_AGENT"),
391                  GetConfValue("HttpWatch/SkipAgentPattern"))) return FALSE;
392
393   return TRUE;
394 }
395
396 /********************************************/
397 /* is the client enable to load Java Applet */
398 /********************************************/
399 int isJavaWatchEnableClient(void)
400 {
401   /* some user agent does not support Java Applet */
402   if(RegExMatch(getenv("HTTP_USER_AGENT"),
403                  GetConfValue("JavaWatch/SkipAgentPattern"))) return FALSE;
404
405   return TRUE;
406 }
407
408 /************************************/
409 /* split value for indicated name   */
410 /* in content  "name=value&..."     */
411 /************************************/
412 void split(char content[], char *name[], char *value[], char *next[])
413 {
414   char *pstr;
415   
416   /* set default */
417   name[0]=content;
418   value[0]=content+strlen(content);
419   next[0]=value[0];
420
421   /* set name end */
422   if((pstr=strchr(name[0],(int)'='))==NULL){
423     next[0]=NULL;
424     return;
425   }
426   *pstr='\0';
427   
428   /* set value start */
429   pstr++;
430   value[0]=pstr;
431   
432   /* set value end */
433   if((pstr=strchr(value[0],'&'))==NULL){
434     next[0]=NULL;
435     return;
436   }
437   *pstr='\0';
438
439   /* set next start */
440   pstr++;
441   next[0]=pstr;
442
443   return;
444 }
445
446 /**********************************/
447 /* decode text coding in web post */
448 /**********************************/
449 void decode(char *string)
450 {
451   char *pcheck, *pinsert;
452
453   pcheck=pinsert=string;
454   while(*pcheck != '\0'){
455     if(*pcheck == '+'){
456       *pinsert = ' ';
457     }else if(*pcheck == '%'){
458       *pinsert=(char)(hex2num(*(pcheck+1))*16 + hex2num(*(pcheck+2)));
459       pcheck+=2;
460     }else{
461       *pinsert=*pcheck;
462     }
463     pcheck++;
464     pinsert++;
465   }
466   *pinsert=*pcheck;
467 }
468
469 /***************************************/
470 /* get HTTP_REFERER and check true url */
471 /***************************************/
472 int checkReferer(void)
473 {
474   char url[BUFFMAXLN]="";
475   if(getenv("HTTP_REFERER")!=NULL){
476     strncpy(url,getenv("HTTP_REFERER"),BUFFMAXLN);
477     if(strstr(url,GetConfValue("OpengateServerName"))==NULL){
478       return FALSE;
479     }
480   }
481   return TRUE;
482 }
483
484 /*******************************/
485 /*******************************/
486 void GetClientAddr(char *clientAddr)
487 {
488   if(debug>1) err_msg("DEBUG:=>getClientAddr( )");
489   getClientAddr(clientAddr);
490   if(debug>1) err_msg("DEBUG:<=getClientAddr(%s)",clientAddr);
491 }
492
493
494 int GetPostData(char *userid, char *password, char *clientAddr4, int *durationPtr, char *watchMode)
495 {
496   int ret;
497
498   if(debug>1) err_msg("DEBUG:=>getPostData( )");
499   ret=getPostData(userid,password,clientAddr4,durationPtr, watchMode);
500   if(debug>1) err_msg("DEBUG:%d<=getPostData(%s,passwd,%s,%d,%s)",ret,userid,clientAddr4,*durationPtr,watchMode);
501   return ret;
502 }
503
504 void PutClientAccept(char *userid, char *sessionId, int port, int pid, char *clientAddr4, char *clientAddr6, int ipStatus, int duration, char *watchMode)
505 {
506   if(debug>1) err_msg("DEBUG:=>putClientAccept(%s,%s,%d,%d,%s,%s,%d,%d,%s)",userid,sessionId,port,pid,clientAddr4,clientAddr6,ipStatus, duration, watchMode);
507   putClientAccept(userid,sessionId,port,pid,clientAddr4,clientAddr6,ipStatus,duration,watchMode);
508   if(debug>1) err_msg("DEBUG:<=putClientAccept( )");
509 }
510
511 void PutClientDeny(char *clientAddr4)
512 {
513   if(debug>1) err_msg("DEBUG:=>putClientDeny(&s)",clientAddr4);
514   putClientDeny(clientAddr4);
515   if(debug>1) err_msg("DEBUG:<=putClientDeny( )");
516 }
517
518 void PutClientRetry(char *lang)
519 {
520   if(debug>1) err_msg("DEBUG:=>putClientRetry(%s)",lang);
521   putClientRetry(lang);
522   if(debug>1) err_msg("DEBUG:<=putClientRetry( )");
523 }
524
525 void PutClientMsg(char *message)
526 {
527   if(debug>1) err_msg("DEBUG:=>putClientMsg( %s )",message);
528   putClientMsg(message);
529   if(debug>1) err_msg("DEBUG:<=putClientMsg( )");
530 }
531
532 int CheckReferer(void)
533 {
534   int ret;
535   if(debug>1) err_msg("DEBUG:=>checkReferer( )");
536   ret = checkReferer();
537   if(debug>1) err_msg("DEBUG:(%d)<=checkReferer( )",ret);
538   return ret;
539 }