OSDN Git Service

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