OSDN Git Service

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