OSDN Git Service

Ver1.3.2: Change config file to XML form and others.
[opengate/opengate.git] / opengate / opengatesrv / main.c
1 /**************************************************
2 opengate server main
3
4 Copyright (C) 1999 Opengate Project Team
5 Written by Yoshiaki Watanabe
6 Modified Katsuhiko Eguchi, 2005 
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        "opengatesrv.h"
26
27 int ipStatus;              /* flag for IPv4 or IPv6 */
28
29 extern char ruleNumber4[WORDMAXLN];  /* ipfw rule number in string form  */
30 extern char ruleNumber6[WORDMAXLN];  /* ip6fw rule number in string form */
31
32 char clientAddr4[ADDRMAXLN]="";  /* client addr (nnn.nnn.nnn.nnn) */
33 char clientAddr6[ADDRMAXLN]="";  /* client addr (nnnn:nnnn:xxxx::xxxx) 128bit */
34
35 struct clientAddr *pClientAddr = NULL;
36
37 char macAddr4[ADDRMAXLN]="?";    /* client MAC address (format for arp) */
38 char macAddr6[ADDRMAXLN]="?";    /* client MAC address (format for ndp) */
39
40 char userid[USERMAXLN];
41 char useridshort[USERMAXLN];/* userID before @ mark(cut off serverID) */
42 char serverid[USERMAXLN];
43 char userProperty[BUFFMAXLN];
44 time_t timeIn, timeOut;
45
46 void PutCloseMsg(time_t timeOut, time_t timeIn);
47 void ReFormatMacAddr(char* macAddr4, char* macAddr6);
48 void GetMacAddr(void);
49 void CheckIpVersions(void);
50 void closeExit(int signo);
51
52 /***************************************************/
53 /*  main routine called as cgi from Web server     */
54 /***************************************************/
55 int  main(int argc, char **argv)
56 {
57   char password[PASSMAXLN];
58   int port;
59   int dummyfd[2];
60   int pid;
61   int duration;     /* requested usage duration */
62
63   /* prepare config file */
64   OpenConfFile();
65
66   /* start log */
67   errToSyslog(atoi(GetConfValue("Syslog/Enable")));
68   openlog(argv[0], LOG_PID, atoi(GetConfValue("Syslog/Facility")));
69
70   /* check referer */
71   if(CheckReferer()==FALSE){
72     return 0;
73   }
74
75   /* get POST data */
76   if(GetPostData(userid, password, clientAddr4, &duration)==FALSE){
77     return 0;
78   }
79
80   /* split user@server to user and server */
81   SplitId(userid, useridshort, serverid);
82
83   /* setup ID for config file */
84   SetupConfId(serverid);
85
86   /* get address of client from getenv. it might be IPv4 or IPv6. */
87   GetClientAddr(clientAddr6);
88
89   /* check enable IP versions */
90   CheckIpVersions();
91
92   /* get MAC address from arp and ndp */
93   GetMacAddr();
94
95   /* authenticate the user with authentication server */
96   if(!AuthenticateUser(useridshort, password)){
97     /* if not authenticate, send deny */
98     PutClientDeny(clientAddr4);
99     err_msg("DENY: user %s from %s at %s", userid, clientAddr4, macAddr4);
100     return 0;
101   }
102
103   /* clear password */
104   bzero(password, PASSMAXLN);
105
106   /* get user property from user database (if you edit comm-userdb.c) */
107   if(!GetUserProperty(userid, userProperty)){
108     PutClientMsg("Error: You are denied.");
109     err_msg("DENY: user %s from %s at %s (ill-property)",
110             userid, clientAddr4, macAddr4);
111     return 0;
112   }
113
114   /* usage duration is restricted to permitted range */
115   if(duration <= 0){
116     duration=atoi(GetConfValue("Duration/Default"));
117   }else{
118     int durmax=atoi(GetConfValue("Duration/Max"));
119     if(duration > durmax){
120       duration=durmax;
121     }
122   }
123   /* set terminate signal handler */
124   Signal(SIGTERM, closeExit);
125
126   /* open firewall for the client */
127   if(OpenClientGate()==FALSE) return 0;
128   timeIn=time(NULL);
129
130   /* set (ruleNumber,userid,clientAddr) in process title */
131   if(ipStatus==IPV46DUAL){
132     setproctitle("%s(useIPv6),[%s(%s)],[%s(%s)]", useridshort, clientAddr4, ruleNumber4, clientAddr6, ruleNumber6);
133   }else if(ipStatus==IPV4ONLY){
134     setproctitle("%s,[%s(%s)],",useridshort, clientAddr4, ruleNumber4);
135   }else if(ipStatus==IPV6ONLY){
136     setproctitle("%s(useIPv6),,[%s(%s)]",useridshort, clientAddr6, ruleNumber6);
137   }
138   
139   /* get temporary port for server-listen */
140   port=GetListenPort();
141   if(port<0){
142     err_msg("ERR in main: cannot get unused listen port");
143     PutClientMsg("Error: Please contact to the administrator");
144     closeExit(1);
145   }
146
147   if((pid=Fork())!=0){
148     /** parent process **/
149     /* send java */
150     PutJavaApplet(userid, port, pid, clientAddr4, clientAddr6, ipStatus);
151
152     /* detach from Web server */
153     return 0;
154   }
155   /** child process **/
156
157   /* detach from Web server */
158   Close(0);Close(1);  /* detach stdin and out pipe connected to Web */
159   Close(2);           /* detach stderr */
160   Pipe(dummyfd);      /* connect dummy pipe for stdin and out */
161
162   /* wait connection from the java applet */
163   /* if no connection, close gate when duration is passed */
164   /* or ipaddr for the macAddr4 is changed */
165   if(WaitAppletConnect(userid, clientAddr4, clientAddr6, duration, macAddr4, ipStatus, pClientAddr)==1){
166
167     /* wait until the user quit */
168     /* close gate when no reply to temporal hello or end of TCP connection */
169     /* macAddr6 is used for NDP to search addition ipaddr */
170     WaitClientClose(pClientAddr, userid, userProperty, macAddr6, ipStatus);
171   }
172   /* close firewall and exit */
173   closeExit(1);
174
175   return 0;
176 }
177
178
179
180 /**************************************/
181 /* Open client gate for IPv4 and IPv6 */
182 /**************************************/
183 int openClientGate(void)
184 {
185   int ret;
186   struct clientAddr *pLastClientAddr = NULL;
187
188   /**** if client have IPv6 & IPv4 addresses, do below */
189   if(ipStatus == IPV46DUAL){
190
191     /* open firewall for clientAddr4 */
192     //err_msg("START: user %s use IPv6 and IPv4 at %s", userid, macAddr4);
193     if((ret=OpenClientGate4(clientAddr4, userid, macAddr4, userProperty))<0){
194
195       /* overlapped rules or other */
196       PutClientMsg("Error: Please End Web and Retry");
197       return FALSE;
198
199     }else if(ret>0){
200       /* system error raise */
201       PutClientMsg("Error: Please contact to the administrator");
202       return FALSE;
203     }
204
205     /* open ipv4 success. write message */
206     err_msg("OPEN: user %s from %s at %s", userid, clientAddr4, macAddr4);
207
208     /* create new address list. head and tail pointer point the same item. */
209     pClientAddr = CreateAddrListItem(clientAddr4,ruleNumber4,IPV4);
210     pLastClientAddr = pClientAddr;
211
212     /* open firewall for clientAddr6 */
213     if((ret=OpenClientGate6(clientAddr6, userid, macAddr6, userProperty))<0){
214
215       /* overlapped rules or other */
216       PutClientMsg("Error: Please End Web and Retry");
217
218       /* remove registered ipv4 rule from list */ 
219       if(pClientAddr!=NULL){
220         if(pClientAddr->ipType==IPV4){
221           CloseClientGate4(pClientAddr,userid,macAddr4);
222           free(pClientAddr);
223           pClientAddr=NULL;
224         }
225       }
226       return FALSE;
227
228     }else if(ret>0){
229
230       /* system error raise */
231       PutClientMsg("Error: Please contact to the administrator");
232       return FALSE;
233     }
234
235     /* open ipv6 success, write message */
236     err_msg("OPEN: user %s from %s at %s", userid, clientAddr6, macAddr6);
237
238     /* add the address info to list */
239     pLastClientAddr->next = CreateAddrListItem(clientAddr6,ruleNumber6,IPV6);
240     
241
242   /***** if client have IPv4 only, do below */
243   }else if(ipStatus==IPV4ONLY){
244     //err_msg("START: user %s use IPv4 at %s", userid, macAddr4);
245
246     if((ret=OpenClientGate4(clientAddr4, userid, macAddr4, userProperty))<0){
247       PutClientMsg("Error: Please End Web and Retry");
248       return FALSE;
249
250     }else if(ret>0){
251       PutClientMsg("Error: Please contact to the administrator");
252       return FALSE;
253     }
254     err_msg("OPEN: user %s from %s at %s", userid, clientAddr4, macAddr4);
255
256     /* create new address list. head and tail pointer point the same item. */
257     pClientAddr = CreateAddrListItem(clientAddr4,ruleNumber4,IPV4);
258     pLastClientAddr = pClientAddr;
259   
260   /***** if client have IPv6 only, do below */
261   }else if(ipStatus==IPV6ONLY){
262     //err_msg("START: user %s use IPv6 at %s", userid, macAddr6);
263
264     if((ret=OpenClientGate6(clientAddr6, userid, macAddr6, userProperty))<0){
265       PutClientMsg("Error: Please End Web and Retry");
266       return FALSE;
267
268     }else if(ret>0){
269       PutClientMsg("Error: Please contact to the administrator");
270       return FALSE;
271     }
272
273     err_msg("OPEN: user %s from %s at %s", userid, clientAddr6, macAddr6);
274
275     /* create new address list. head and tail pointer point the same item. */
276     pClientAddr = CreateAddrListItem(clientAddr4,ruleNumber4,IPV4);
277     pLastClientAddr = pClientAddr;
278   }
279   return TRUE;
280 }
281
282 /*******************************************/
283 /* calc connection duration and put it out */
284 /*******************************************/
285 void putCloseMsg(time_t timeOut, time_t timeIn)
286 {
287   double time;
288   int hour,min,sec;
289
290   time=difftime(timeOut,timeIn);
291   hour=time/60/60;
292   min=(time-hour*60*60)/60;
293   sec=(time-hour*60*60-min*60);
294   //err_msg("STOP: user %s at %s ( %02d:%02d:%02d )", userid, macAddr4, hour,min,sec);
295   return;
296 }
297
298 /*****************************/
299 /* Check enable IP versions  */
300 /*****************************/
301
302 void checkIpVersions(void){
303
304   if(strstr(clientAddr4,".")!=NULL){
305     if(strstr(clientAddr6,":")!=NULL){
306       ipStatus = IPV46DUAL;
307     }else{
308       ipStatus = IPV4ONLY;
309     }
310   }else{
311     if(strstr(clientAddr6,":")!=NULL){
312       ipStatus = IPV6ONLY;
313     }else{
314       err_msg("ERR in main: Can not get IP for user %s v4:%s v6:%s", userid,clientAddr4,clientAddr6);
315       PutClientMsg("Error: Please contact to the administrator");
316       exit(1);
317     }
318   }
319 }
320
321 /********************/
322 /* Get Mac Address  */
323 /********************/
324 void getMacAddr(void)
325 {
326
327   if(ipStatus==IPV46DUAL){
328     GetMacAddrFromArp(clientAddr4, macAddr4);
329     GetMacAddrFromNdp(clientAddr6,macAddr6);
330     
331   }else if(ipStatus==IPV4ONLY){
332     GetMacAddrFromArp(clientAddr4, macAddr4);
333     ReFormatMacAddr(macAddr4,macAddr6);
334     
335   }else{
336     GetMacAddrFromNdp(clientAddr6, macAddr6);
337   }
338   
339   return;
340 }
341
342 /*********************************/
343 /* format macAddr for ndp or arp */
344 /*********************************/
345 void reFormatMacAddr(char* macAddr4, char* macAddr6)
346 {
347   char *strp = NULL;
348   char delims[] = ":";
349   char buf[ADDRMAXLN] = "";
350   char nullstr[ADDRMAXLN] = "";
351
352   strcpy(macAddr6,nullstr);
353   strcpy(buf,macAddr4);
354   strp=strtok(buf,delims);
355   
356   if(strncmp(strp,"0",1)==0){
357     strp++;
358     strcat(macAddr6,strp);
359   }else{
360     strcat(macAddr6,strp);
361   }
362   strp=strtok(NULL,delims);
363   while(strp!=NULL){
364     strcat(macAddr6,delims);
365     if(strncmp(strp,"0",1)==0){
366       strp++;
367       strcat(macAddr6,strp);
368     }else{
369       strcat(macAddr6,strp);
370     }
371     strp=strtok(NULL,delims);
372   }
373 }
374
375 /*****************************/
376 /* At termination, call this */
377 /*****************************/
378 void closeExit(int signo)
379 {
380   /* signal is disabled */
381   Signal(SIGTERM, SIG_DFL);
382
383   /* send quit message to client java */
384   SendQuitClient();
385
386   /* close firewalls */
387   while(pClientAddr!=NULL){
388     if(pClientAddr->ipType==IPV4){
389       CloseClientGate4(pClientAddr,useridshort,macAddr4);
390     }else{
391       CloseClientGate6(pClientAddr,useridshort,macAddr6);
392       DeleteNdpEntry(pClientAddr->ipAddr);
393     }
394     pClientAddr = pClientAddr->next;
395   }
396
397   /* put out time */
398   timeOut=time(NULL);
399   PutCloseMsg(timeOut,timeIn);
400   if(debug) err_msg("DEBUG:terminated");
401
402   /* release the conf file area */
403   CloseConfFile();
404
405   exit(1);
406 }
407
408 /*****************************/
409 /*****************************/
410 int OpenClientGate(void)
411 {
412   int ret;
413   if(debug) err_msg("DEBUG:=>openClientGate( )");
414   ret = openClientGate();
415   if(debug) err_msg("DEBUG:(%d)<=openClientGate()",ret);
416   return ret;
417 }
418
419 void PutCloseMsg(time_t timeOut, time_t timeIn)
420 {
421   if(debug) err_msg("DEBUG:=>putCloseMsg( )");
422   putCloseMsg(timeOut,timeIn);
423   if(debug) err_msg("DEBUG:<=putCloseMsg( )");
424 }
425
426 void ReFormatMacAddr(char* macAddr4, char* macAddr6)
427 {
428   if(debug) err_msg("DEBUG:=>reFormatMacAddr(%s)", macAddr4);
429   reFormatMacAddr(macAddr4, macAddr6);
430   if(debug) err_msg("DEBUG:<=reFormatMacAddr(%s)", macAddr6);
431 }
432
433 void GetMacAddr(void)
434 {
435   if(debug) err_msg("DEBUG:=>getMacAddr( )");
436   getMacAddr();
437   if(debug) err_msg("DEBUG:<=getMacAddr( )");
438 }
439
440 void CheckIpVersions(void)
441 {
442   if(debug) err_msg("DEBUG:=>checkIpVersions( )");
443   checkIpVersions();
444   if(debug) err_msg("DEBUG:<=checkIpversions( )");
445 }
446