root/src/router/httpd/httpd.c

Revision 12435, 42.5 kB (checked in by BrainSlayer, 5 months ago)

disable cross site detection for this file if authentication is disabled

Line 
1 /* milli_httpd - pretty small HTTP server
2 ** A combination of
3 ** micro_httpd - really small HTTP server
4 ** and
5 ** mini_httpd - small HTTP server
6 **
7 ** Copyright  1999,2000 by Jef Poskanzer <jef@acme.com>.
8 ** All rights reserved.
9 **
10 ** Redistribution and use in source and binary forms, with or without
11 ** modification, are permitted provided that the following conditions
12 ** are met:
13 ** 1. Redistributions of source code must retain the above copyright
14 **    notice, this list of conditions and the following disclaimer.
15 ** 2. Redistributions in binary form must reproduce the above copyright
16 **    notice, this list of conditions and the following disclaimer in the
17 **    documentation and/or other materials provided with the distribution.
18 **
19 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 ** SUCH DAMAGE.
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <time.h>
38 #include <unistd.h>
39 #include <netinet/in.h>
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <sys/stat.h>
43 #include <arpa/inet.h>
44 #include <getopt.h>
45 #include <stdarg.h>
46 #include <syslog.h>
47 #include <cy_conf.h>
48 #include "httpd.h"
49 #include <bcmnvram.h>
50 #include <code_pattern.h>
51 #include <utils.h>
52 #include <shutils.h>
53 #include <md5.h>
54 #include <sys/time.h>
55
56 #ifdef HAVE_OPENSSL
57 #include <openssl/ssl.h>
58 #endif
59
60 #ifdef HAVE_MATRIXSSL
61 # include <matrixSsl.h>
62 # include <matrixssl_xface.h>
63 #endif
64
65 #ifdef HAVE_XYSSL
66 #include <xyssl/havege.h>
67 #include <xyssl/certs.h>
68 #include <xyssl/x509.h>
69 #include <xyssl/ssl.h>
70 #include <xyssl/net.h>
71 //#include <xyssl_xface.h>
72 #endif
73
74 #ifdef HAVE_VFS
75 #include <vfs.h>
76 #endif
77
78 #include <error.h>
79 #include <sys/signal.h>
80
81 #define SERVER_NAME "httpd"
82 //#define SERVER_PORT 80
83 #define PROTOCOL "HTTP/1.0"
84 #define RFC1123FMT "%a, %d %b %Y %H:%M:%S GMT"
85 #define TIMEOUT 15
86
87 /* A multi-family sockaddr. */
88 typedef union {
89         struct sockaddr sa;
90         struct sockaddr_in sa_in;
91 } usockaddr;
92
93 /* Globals. */
94 #ifdef HAVE_OPENSSL
95 static SSL *ssl;
96 #endif
97
98 #ifdef FILTER_DEBUG
99 FILE *debout;
100 #endif
101
102 #if defined(HAVE_OPENSSL) || defined(HAVE_MATRIXSSL) || defined(HAVE_XYSSL)
103
104 #define DEFAULT_HTTPS_PORT 443
105 #define CERT_FILE "/etc/cert.pem"
106 #define KEY_FILE "/etc/key.pem"
107 #endif
108
109 #ifdef HAVE_MATRIXSSL
110 extern ssl_t *ssl;
111 extern sslKeys_t *keys;
112 #endif
113
114 #ifdef HAVE_XYSSL
115 ssl_context ssl;
116 int my_ciphers[] = {
117         TLS1_EDH_RSA_AES_256_SHA,
118         SSL3_EDH_RSA_DES_168_SHA,
119         TLS1_RSA_AES_256_SHA,
120         SSL3_RSA_DES_168_SHA,
121         SSL3_RSA_RC4_128_SHA,
122         SSL3_RSA_RC4_128_MD5,
123         0
124 };
125
126 char *dhm_P =
127     "E4004C1F94182000103D883A448B3F80"
128     "2CE4B44A83301270002C20D0321CFD00"
129     "11CCEF784C26A400F43DFB901BCA7538"
130     "F2C6B176001CF5A0FD16D2C48B1D0C1C"
131     "F6AC8E1DA6BCC3B4E1F96B0564965300"
132     "FFA1D0B601EB2800F489AA512C4B248C"
133     "01F76949A60BB7F00A40B1EAB64BDD48" "E8A700D60B7F1200FA8E77B0A979DABF";
134
135 char *dhm_G = "4";
136 unsigned char session_table[SSL_SESSION_TBL_LEN];
137 #endif
138
139 #define DEFAULT_HTTP_PORT 80
140 int server_port;
141 char pid_file[80];
142 char *server_dir = NULL;
143
144 #ifdef HAVE_HTTPS
145 int do_ssl = 0;
146 #endif
147 #ifdef SAMBA_SUPPORT
148 extern int smb_getlock;
149 extern int httpd_fork;
150 void smb_handler()
151 {
152         printf("============child exit=====waitting ...====\n");
153         smb_getlock = 0;
154         wait(NULL);
155         printf("wait finish \n");
156 }
157 #endif
158
159 //static FILE *conn_fp;
160 static webs_t conn_fp = NULL;   // jimmy, https, 8/4/2003
161 static char auth_userid[AUTH_MAX];
162 static char auth_passwd[AUTH_MAX];
163 char auth_realm[AUTH_MAX];
164
165 //#ifdef GET_POST_SUPPORT
166 int post;
167
168 //#endif
169 int auth_fail = 0;
170 int httpd_level;
171
172 char http_client_ip[20];
173 extern char *get_mac_from_ip(char *ip);
174
175 /* Forwards. */
176 static int initialize_listen_socket(usockaddr * usaP);
177 static int auth_check(char *user, char *pass, char *dirname,
178                       char *authorization);
179 static void send_error(int status, char *title, char *extra_header, char *text);
180 static void send_headers(int status, char *title, char *extra_header,
181                          char *mime_type, long length, char *attach_file);
182 static int b64_decode(const char *str, unsigned char *space, int size);
183 static int match(const char *pattern, const char *string);
184 static int match_one(const char *pattern, int patternlen, const char *string);
185 static void handle_request(void);
186
187 static int initialize_listen_socket(usockaddr * usaP)
188 {
189         int listen_fd;
190         int i;
191
192         memset(usaP, 0, sizeof(usockaddr));
193         usaP->sa.sa_family = AF_INET;
194         usaP->sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
195         usaP->sa_in.sin_port = htons(server_port);
196
197         listen_fd = socket(usaP->sa.sa_family, SOCK_STREAM, 0);
198         if (listen_fd < 0) {
199                 perror("socket");
200                 return -1;
201         }
202         (void)fcntl(listen_fd, F_SETFD, 1);
203         i = 1;
204         if (setsockopt
205             (listen_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(i)) < 0) {
206                 perror("setsockopt");
207                 return -1;
208         }
209         if (bind(listen_fd, &usaP->sa, sizeof(struct sockaddr_in)) < 0) {
210                 perror("bind");
211                 return -1;
212         }
213         if (listen(listen_fd, 1024) < 0) {
214                 perror("listen");
215                 return -1;
216         }
217         return listen_fd;
218 }
219
220 static int auth_check(char *user, char *pass, char *dirname,
221                       char *authorization)
222 {
223         unsigned char authinfo[500];
224         unsigned char *authpass;
225         int l;
226
227         /* Is this directory unprotected? */
228         if (!strlen(pass))
229                 /* Yes, let the request go through. */
230                 return 1;
231
232         /* Basic authorization info? */
233         if (!authorization || strncmp(authorization, "Basic ", 6) != 0) {
234                 //send_authenticate( dirname );
235                 ct_syslog(LOG_INFO, httpd_level, "Authentication fail");
236                 return 0;
237         }
238
239         /* Decode it. */
240         l = b64_decode(&(authorization[6]), authinfo, sizeof(authinfo));
241         authinfo[l] = '\0';
242         /* Split into user and password. */
243         authpass = strchr((char *)authinfo, ':');
244         if (authpass == (unsigned char *)0) {
245                 /* No colon?  Bogus auth info. */
246                 //send_authenticate( dirname );
247                 return 0;
248         }
249         *authpass++ = '\0';
250
251         char *crypt(const char *, const char *);
252
253         /* Is this the right user and password? */
254 //#ifdef DDM_SUPPORT
255         char buf1[36];
256         char buf2[36];
257         char *enc1;
258         char *enc2;
259
260         if (user[0] == '$' && user[1] == '1' && user[2] == '$')
261                 enc1 = md5_crypt(buf1, authinfo, (unsigned char *)user);
262         else
263                 enc1 = crypt(authinfo, (unsigned char *)user);
264
265         if (strcmp(enc1, user)) {
266                 return 0;
267         }
268
269         if (pass[0] == '$' && pass[1] == '1' && pass[2] == '$')
270                 enc2 = md5_crypt(buf2, authpass, (unsigned char *)pass);
271         else
272                 enc2 = crypt(authpass, (unsigned char *)pass);
273         if (strcmp(enc2, pass)) {
274                 return 0;
275         }
276
277         if (strcmp(enc1, user) == 0 && strcmp(enc2, pass) == 0) {
278                 return 1;
279         }
280 //#else
281 //  if (strcmp (auth_passwd, authpass) == 0)
282 //    return 1;
283 //#endif
284         //send_authenticate( dirname );
285         return 1;
286 }
287
288 void send_authenticate(char *realm)
289 {
290         char header[10000];
291
292         (void)snprintf(header, sizeof(header),
293                        "WWW-Authenticate: Basic realm=\"%s\"", realm);
294         send_error(401, "Unauthorized", header,
295                    "Authorization required. please note that the default username is \"root\" in all newer releases");
296 }
297
298 static void send_error(int status, char *title, char *extra_header, char *text)
299 {
300
301         // jimmy, https, 8/4/2003, fprintf -> wfprintf, fflush -> wfflush
302         send_headers(status, title, extra_header, "text/html", 0, NULL);
303         (void)wfprintf(conn_fp,
304                        "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n<BODY BGCOLOR=\"#cc9999\"><H4>%d %s</H4>\n",
305                        status, title, status, title);
306         (void)wfprintf(conn_fp, "%s\n", text);
307         (void)wfprintf(conn_fp, "</BODY></HTML>\n");
308         (void)wfflush(conn_fp);
309 }
310
311 static void
312 send_headers(int status, char *title, char *extra_header, char *mime_type,
313              long length, char *attach_file)
314 {
315         time_t now;
316         char timebuf[100];
317
318         wfprintf(conn_fp, "%s %d %s\r\n", PROTOCOL, status, title);
319         if (mime_type != (char *)0)
320                 wfprintf(conn_fp, "Content-Type: %s\r\n", mime_type);
321
322         wfprintf(conn_fp, "Server: %s\r\n", SERVER_NAME);
323         now = time((time_t *) 0);
324         strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now));
325         wfprintf(conn_fp, "Date: %s\r\n", timebuf);
326         wfprintf(conn_fp, "Connection: close\r\n");
327         wfprintf(conn_fp,
328                  "Cache-Control: no-store, no-cache, must-revalidate\r\n");
329         wfprintf(conn_fp, "Cache-Control: post-check=0, pre-check=0\r\n");
330         wfprintf(conn_fp, "Pragma: no-cache\r\n");
331         if (attach_file)
332                 wfprintf(conn_fp,
333                          "Content-Disposition: attachment; filename=%s\r\n",
334                          attach_file);
335         if (extra_header != (char *)0 && *extra_header)
336                 wfprintf(conn_fp, "%s\r\n", extra_header);
337         if (length != 0)
338                 wfprintf(conn_fp, "Content-Length: %ld\r\n", length);
339         wfprintf(conn_fp, "\r\n");
340 }
341
342 /* Base-64 decoding.  This represents binary data as printable ASCII
343 ** characters.  Three 8-bit binary bytes are turned into four 6-bit
344 ** values, like so:
345 **
346 **   [11111111]  [22222222]  [33333333]
347 **
348 **   [111111] [112222] [222233] [333333]
349 **
350 ** Then the 6-bit values are represented using the characters "A-Za-z0-9+/".
351 */
352
353 static int b64_decode_table[256] = {
354         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00-0F */
355         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10-1F */
356         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 20-2F */
357         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 30-3F */
358         -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,   /* 40-4F */
359         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 50-5F */
360         -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 60-6F */
361         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 70-7F */
362         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80-8F */
363         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90-9F */
364         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0-AF */
365         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0-BF */
366         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0-CF */
367         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0-DF */
368         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0-EF */
369         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1  /* F0-FF */
370 };
371
372 /* Do base-64 decoding on a string.  Ignore any non-base64 bytes.
373 ** Return the actual number of bytes generated.  The decoded size will
374 ** be at most 3/4 the size of the encoded, and may be smaller if there
375 ** are padding characters (blanks, newlines).
376 */
377 static int b64_decode(const char *str, unsigned char *space, int size)
378 {
379         const char *cp;
380         int space_idx, phase;
381         int d, prev_d = 0;
382         unsigned char c;
383
384         space_idx = 0;
385         phase = 0;
386         for (cp = str; *cp != '\0'; ++cp) {
387                 d = b64_decode_table[(int)*cp];
388                 if (d != -1) {
389                         switch (phase) {
390                         case 0:
391                                 ++phase;
392                                 break;
393                         case 1:
394                                 c = ((prev_d << 2) | ((d & 0x30) >> 4));
395                                 if (space_idx < size)
396                                         space[space_idx++] = c;
397                                 ++phase;
398                                 break;
399                         case 2:
400                                 c = (((prev_d & 0xf) << 4) | ((d & 0x3c) >> 2));
401                                 if (space_idx < size)
402                                         space[space_idx++] = c;
403                                 ++phase;
404                                 break;
405                         case 3:
406                                 c = (((prev_d & 0x03) << 6) | d);
407                                 if (space_idx < size)
408                                         space[space_idx++] = c;
409                                 phase = 0;
410                                 break;
411                         }
412                         prev_d = d;
413                 }
414         }
415         return space_idx;
416 }
417
418 /* Simple shell-style filename matcher.  Only does ? * and **, and multiple
419 ** patterns separated by |.  Returns 1 or 0.
420 */
421 int match(const char *pattern, const char *string)
422 {
423         const char *or;
424
425         for (;;) {
426                 or = strchr(pattern, '|');
427                 if (or == (char *)0)
428                         return match_one(pattern, strlen(pattern), string);
429                 if (match_one(pattern, or - pattern, string))
430                         return 1;
431                 pattern = or + 1;
432         }
433 }
434
435 static int match_one(const char *pattern, int patternlen, const char *string)
436 {
437         const char *p;
438
439         for (p = pattern; p - pattern < patternlen; ++p, ++string) {
440                 if (*p == '?' && *string != '\0')
441                         continue;
442                 if (*p == '*') {
443                         int i, pl;
444
445                         ++p;
446                         if (*p == '*') {
447                                 /* Double-wildcard matches anything. */
448                                 ++p;
449                                 i = strlen(string);
450                         } else
451                                 /* Single-wildcard matches anything but slash. */
452                                 i = strcspn(string, "/");
453                         pl = patternlen - (p - pattern);
454                         for (; i >= 0; --i)
455                                 if (match_one(p, pl, &(string[i])))
456                                         return 1;
457                         return 0;
458                 }
459                 if (*p != *string)
460                         return 0;
461         }
462         if (*string == '\0')
463                 return 1;
464         return 0;
465 }
466
467 static void
468 //do_file(char *path, FILE *stream)
469 do_file_2(struct mime_handler *handler, char *path, webs_t stream, char *query, char *attach)   //jimmy, https, 8/4/2003
470 {
471
472 #ifdef HAVE_VFS
473         int c;
474         entry *e;
475
476         e = vfsopen(path, "r");
477         if (e == NULL) {
478                 FILE *fp;
479
480                 if (!(fp = fopen(path, "rb")))
481                         return;
482                 while ((c = getc(fp)) != EOF)
483                         //fputc(c, stream);
484                         wfputc(c, stream);      // jimmy, https, 8/4/2003
485                 fclose(fp);
486         } else {
487
488                 while ((c = vfsgetc(e)) != EOF)
489                         //fputc(c, stream);
490                         wfputc(c, stream);      // jimmy, https, 8/4/2003
491                 vfsclose(e);
492         }
493 #else
494         FILE *web = getWebsFile(path);
495
496         if (web == NULL) {
497                 FILE *fp;
498                 int c;
499
500                 if (!(fp = fopen(path, "rb")))
501                         return;
502                 fseek(fp, 0, SEEK_END);
503                 if (!handler->send_headers)
504                         send_headers(200, "Ok", handler->extra_header,
505                                      handler->mime_type, ftell(fp), attach);
506                 fseek(fp, 0, SEEK_SET);
507                 while ((c = getc(fp)) != EOF)
508                         wfputc(c, stream);      // jimmy, https, 8/4/2003
509                 fclose(fp);
510         } else {
511                 int len = getWebsFileLen(path);
512
513                 if (!handler->send_headers)
514                         send_headers(200, "Ok", handler->extra_header,
515                                      handler->mime_type, len, attach);
516                 int a;
517                 char buf[128];
518                 int tot = 0;
519
520                 for (a = 0; a < len / 128; a++) {
521                         tot += fread(buf, 1, 128, web);
522                         wfwrite(buf, 128, 1, stream);
523                 }
524                 len = fread(buf, 1, (len % 128), web);
525                 tot += len;
526                 wfwrite(buf, len, 1, stream);
527                 fclose(web);
528         }
529 #endif
530 }
531
532 void
533 //do_file(char *path, FILE *stream)
534 do_file(struct mime_handler *handler, char *path, webs_t stream, char *query)   //jimmy, https, 8/4/2003
535 {
536
537         do_file_2(handler, path, stream, query, NULL);
538 }
539
540 void
541 //do_file(char *path, FILE *stream)
542 do_file_attach(struct mime_handler *handler, char *path, webs_t stream, char *query, char *attachment)  //jimmy, https, 8/4/2003
543 {
544
545         do_file_2(handler, path, stream, query, attachment);
546 }
547
548 #ifdef HSIAB_SUPPORT
549 static char *                   // add by jimmy 2003-5-13
550 get_aaa_url(int inout_mode, char *client_ip)
551 {
552         static char line[MAX_BUF_LEN];
553         char cmd[MAX_BUF_LEN];
554
555         strcpy(line, "");
556         if (inout_mode == 0)
557                 snprintf(cmd, sizeof(cmd), "GET aaa_login_url %s", client_ip);
558         else
559                 snprintf(cmd, sizeof(cmd), "GET aaa_logout_url %s", client_ip);
560
561         send_command(cmd, line);
562
563         return line;
564 }
565
566 char *                          // add by honor 2003-04-16, modify by jimmy 2003-05-13
567 get_client_ip(int conn_fp)
568 {
569         struct sockaddr_in sa;
570         int len = sizeof(struct sockaddr_in);
571         static char ip[20];
572
573         getpeername(conn_fp, (struct sockaddr *)&sa, &len);
574         char client[32];
575         char *peer = inet_ntop(AF_INET, &sa.sin_addr, client, 16);
576
577         strcpy(ip, peer);
578         return (ip);
579 }
580 #endif
581
582 static int check_connect_type(void)
583 {
584         struct wl_assoc_mac *wlmac = NULL;
585         int count_wl = 0;
586         int i, j, ret = 0;
587         char temp[32];
588         int c = get_wl_instances();
589
590         for (j = 0; j < c; j++) {
591                 sprintf(temp, "wl%d_web_filter", j);
592                 if (nvram_invmatch(temp, "1"))
593                         continue;
594
595                 wlmac = get_wl_assoc_mac(j, &count_wl);
596
597                 for (i = 0; i < count_wl; i++) {
598                         if (!strcmp
599                             (wlmac[i].mac, nvram_safe_get("http_client_mac"))) {
600                                 cprintf("Can't accept wireless access\n");
601                                 ret = -1;
602                         }
603                 }
604                 free(wlmac);
605         }
606
607         return ret;
608 }
609
610 /*static void addEnv(const char *name_before_underline,
611                         const char *name_after_underline, const char *value)
612 {
613   char *s = NULL;
614   const char *underline;
615
616   if (!value)
617         value = "";
618   underline = *name_after_underline ? "_" : "";
619   asprintf(&s, "%s%s%s=%s", name_before_underline, underline,
620                                         name_after_underline, value);
621   if(s) {
622     putenv(s);
623   }
624 }*/
625 int containsstring(char *source, char *cmp)
626 {
627         if (cmp == NULL || source == NULL)
628                 return 0;
629         int slen = strlen(source);
630         int clen = strlen(cmp);
631
632         if (slen < clen)
633                 return 0;
634         int i;
635
636         for (i = 0; i < slen - clen; i++) {
637                 int a;
638                 int r = 0;
639
640                 for (a = 0; a < clen; a++)
641                         if (source[i + a] != cmp[a])
642                                 r++;
643                 if (!r)
644                         return 1;
645         }
646         return 0;
647 }
648
649 static char *last_log_ip = NULL;
650 static int registered = -1;
651 static int registered_real = -1;
652
653 #define LINE_LEN 10000
654 static void handle_request(void)
655 {
656         char *query;
657         char *cur;
658         char *method, *path, *protocol, *authorization, *boundary, *referer,
659             *host;
660         char *cp;
661         char *file;
662         FILE *exec;
663         int len;
664         struct mime_handler *handler;
665         int cl = 0, count, flags;
666         char line[LINE_LEN];
667
668         //   line =(char*)malloc(LINE_LEN);
669         /* Initialize the request variables. */
670         authorization = referer = boundary = host = NULL;
671         bzero(line, sizeof line);
672
673         memset(line, 0, LINE_LEN);
674
675         /* Parse the first line of the request. */
676         if (wfgets(line, LINE_LEN, conn_fp) == (char *)0) {     //jimmy,https,8/4/2003
677                 send_error(400, "Bad Request", (char *)0, "No request found.");
678 //          free(line);
679                 return;
680         }
681
682         /* To prevent http receive https packets, cause http crash (by honor 2003/09/02) */
683         if (strncasecmp(line, "GET", 3) && strncasecmp(line, "POST", 4)) {
684 //      free(line);
685                 return;
686         }
687         method = path = line;
688         strsep(&path, " ");
689         if (!path) {            // Avoid http server crash, added by honor 2003-12-08
690                 send_error(400, "Bad Request", (char *)0,
691                            "Can't parse request.");
692 //      free(line);
693                 return;
694         }
695         while (*path == ' ')
696                 path++;
697         protocol = path;
698         strsep(&protocol, " ");
699         if (!protocol) {        // Avoid http server crash, added by honor 2003-12-08
700                 send_error(400, "Bad Request", (char *)0,
701                            "Can't parse request.");
702 //      free(line);
703                 return;
704         }
705         while (*protocol == ' ')
706                 protocol++;
707         cp = protocol;
708         strsep(&cp, " ");
709         cur = protocol + strlen(protocol) + 1;
710         /* Parse the rest of the request headers. */
711         //while ( fgets( cur, line + sizeof(line) - cur, conn_fp ) != (char*) 0 )
712         //exec=fopen("/tmp/logweb.tmp","wb");
713
714         while (wfgets(cur, line + LINE_LEN - cur, conn_fp) != 0)        //jimmy,https,8/4/2003
715         {
716                 //    fwrite(cur,1,line + LINE_LEN - cur,exec);
717 //      fprintf(stderr,"%s\n",cur);
718                 if (strcmp(cur, "\n") == 0 || strcmp(cur, "\r\n") == 0) {
719                         break;
720                 } else if (strncasecmp(cur, "Authorization:", 14) == 0) {
721                         cp = &cur[14];
722                         cp += strspn(cp, " \t");
723                         authorization = cp;
724                         cur = cp + strlen(cp) + 1;
725                 } else if (strncasecmp(cur, "Referer:", 8) == 0) {
726                         cp = &cur[8];
727                         cp += strspn(cp, " \t");
728                         referer = cp;
729                         cur = cp + strlen(cp) + 1;
730                 } else if (strncasecmp(cur, "Host:", 5) == 0) {
731                         cp = &cur[5];
732                         cp += strspn(cp, " \t");
733                         host = cp;
734                         cur = cp + strlen(cp) + 1;
735                 } else if (strncasecmp(cur, "Content-Length:", 15) == 0) {
736                         cp = &cur[15];
737                         cp += strspn(cp, " \t");
738                         cl = strtoul(cp, NULL, 0);
739
740                 } else if ((cp = strstr(cur, "boundary="))) {
741                         boundary = &cp[9];
742                         for (cp = cp + 9; *cp && *cp != '\r' && *cp != '\n';
743                              cp++) ;
744                         *cp = '\0';
745                         cur = ++cp;
746                 }
747
748         }
749         //fclose(exec);
750
751         if (strcasecmp(method, "get") != 0 && strcasecmp(method, "post") != 0) {
752                 send_error(501, "Not Implemented", (char *)0,
753                            "That method is not implemented.");
754 //      free(line);
755                 return;
756         }
757         if (path[0] != '/') {
758                 send_error(400, "Bad Request", (char *)0, "Bad filename.");
759 //      free(line);
760                 return;
761         }
762         file = &(path[1]);
763         len = strlen(file);
764         if (file[0] == '/' || strcmp(file, "..") == 0
765             || strncmp(file, "../", 3) == 0
766             || strstr(file, "/../") != (char *)0
767             || strcmp(&(file[len - 3]), "/..") == 0) {
768                 send_error(400, "Bad Request", (char *)0, "Illegal filename.");
769 //      free(line);
770                 return;
771         }
772         int nodetect=0;
773         if (nvram_match("status_auth", "0") && endswith(file,"Info.htm"))
774                 nodetect=1;
775
776         if (referer && host && nodetect==0) {
777                 int i;
778                 int hlen = strlen(host);
779                 int rlen = strlen(referer);
780                 int slashs = 0;
781
782                 for (i = 0; i < rlen; i++) {
783                         if (referer[i] == '/')
784                                 slashs++;
785                         if (slashs == 2) {
786                                 i++;
787                                 break;
788                         }
789                 }
790                 if (slashs == 2) {
791                         int a;
792                         int c = 0;
793
794                         for (a = 0; a < hlen; a++)
795                                 if (host[a] == ' ' || host[a] == '\r'
796                                     || host[a] == '\n' || host[a] == '\t')
797                                         host[a] = 0;
798                         hlen = strlen(host);
799                         for (a = i; a < rlen; a++) {
800                                 if (referer[a] == '/') {
801                                         send_error(400, "Bad Request",
802                                                    (char *)0,
803                                                    "Cross Site Action detected!");
804                                         return;
805                                 }
806                                 if (host[c++] != referer[a]) {
807                                         send_error(400, "Bad Request",
808                                                    (char *)0,
809                                                    "Cross Site Action detected!");
810                                         return;
811                                 }
812                                 if (c == hlen) {
813                                         a++;
814                                         break;
815                                 }
816                         }
817                         if (c != hlen || referer[a] != '/') {
818                                 send_error(400, "Bad Request", (char *)0,
819                                            "Cross Site Action detected!");
820                                 return;
821                         }
822                 }
823
824         }
825         // seg change for status site
826 #ifdef HAVE_REGISTER
827         if (registered_real == -1) {
828                 registered_real = isregistered_real();
829         }
830         if (!registered_real)
831                 registered = isregistered();
832         else
833                 registered = registered_real;
834 #endif
835
836 #ifdef HAVE_SKYTRON
837         if (file[0] == '\0' || file[len - 1] == '/') {
838                 file = "setupindex.asp";
839         }
840 #else
841         if (file[0] == '\0' || file[len - 1] == '/') {
842
843                 {
844                         if (server_dir != NULL && strcmp(server_dir, "/www"))   // to allow to use router as a WEB server
845                         {
846                                 file = "index.htm";
847                         } else {
848                                 if (nvram_invmatch("status_auth", "0"))
849                                         file = "Info.htm";
850                                 else
851                                         file = "index.asp";
852                         }
853                 }
854         } else {
855                 {
856                         if (nvram_invmatch("status_auth", "1"))
857                                 if (strcmp(file, "Info.htm") == 0)
858                                         file = "index.asp";
859                 }
860         }
861 #endif
862
863         if (containsstring(file, "cgi-bin")) {
864
865                 auth_fail = 0;
866                 if (!do_auth
867                     (conn_fp, auth_userid, auth_passwd, auth_realm,
868                      authorization, auth_check))
869                         auth_fail = 1;
870                 query = NULL;
871                 if (strcasecmp(method, "post") == 0) {
872                         query = malloc(10000);
873                         if ((count = wfread(query, 1, cl, conn_fp))) {
874                                 query[count] = '\0';;
875                                 cl -= strlen(query);
876                         } else {
877                                 free(query);
878                                 query = NULL;
879                         }
880 #if defined(linux)
881 #ifdef HAVE_HTTPS
882                         if (!do_ssl
883                             && (flags =
884                                 fcntl(fileno(conn_fp->fp), F_GETFL)) != -1
885                             && fcntl(fileno(conn_fp->fp), F_SETFL,
886                                      flags | O_NONBLOCK) != -1) {
887                                 /* Read up to two more characters */
888                                 if (fgetc(conn_fp->fp) != EOF)
889                                         (void)fgetc(conn_fp->fp);
890                                 fcntl(fileno(conn_fp->fp), F_SETFL, flags);
891                         }
892 #else
893                         if ((flags = fcntl(fileno(conn_fp->fp), F_GETFL)) != -1
894                             && fcntl(fileno(conn_fp->fp), F_SETFL,
895                                      flags | O_NONBLOCK) != -1) {
896                                 /* Read up to two more characters */
897                                 if (fgetc(conn_fp->fp) != EOF)
898                                         (void)fgetc(conn_fp->fp);
899                                 fcntl(fileno(conn_fp->fp), F_SETFL, flags);
900                         }
901 #endif
902 #endif
903
904                 }
905                 exec = fopen("/tmp/exec.tmp", "wb");
906                 fprintf(exec, "export REQUEST_METHOD=\"%s\"\n", method);
907                 if (query)
908                         fprintf(exec, "/bin/sh %s/%s</tmp/exec.query\n",
909                                 server_dir != NULL ? server_dir : "/www", file);
910                 else
911                         fprintf(exec, "/%s/%s\n",
912                                 server_dir != NULL ? server_dir : "/www", file);
913                 fclose(exec);
914
915                 if (query) {
916                         exec = fopen("/tmp/exec.query", "wb");
917                         fprintf(exec, "%s\n", query);
918                         free(query);
919                         fclose(exec);
920                 }
921
922                 system2("chmod 700 /tmp/exec.tmp");
923                 system2("/tmp/exec.tmp>/tmp/shellout.asp");
924                 if (check_connect_type() < 0) {
925                         send_error(401, "Bad Request", (char *)0,
926                                    "Can't use wireless interface to access GUI.");
927 //          free(line);
928                         return;
929                 }
930                 if (auth_fail == 1) {
931                         send_authenticate(auth_realm);
932                         auth_fail = 0;
933 //          free(line);
934                         return;
935                 }
936
937                 do_ej(NULL, "/tmp/shellout.asp", conn_fp, "");
938                 unlink("/tmp/shellout.asp");
939                 unlink("/tmp/exec.tmp");
940                 unlink("/tmp/exec.query");
941
942         } else {
943                 /* extract url args if present */
944                 query = strchr(file, '?');
945                 if (query) {
946                         *query++ = 0;
947                 }
948                 int changepassword = 0;
949
950 #ifdef HAVE_REGISTER
951                 if (!registered_real) {
952                         if (endswith(file, "About.htm"))
953                                 file = "register.asp";
954                 }
955                 if (!registered) {
956                         if (endswith(file, ".asp"))
957                                 file = "register.asp";
958                         else if (endswith(file, ".htm"))
959                                 file = "register.asp";
960                         else if (endswith(file, ".html"))
961                                 file = "register.asp";
962                 } else
963 #endif
964                 {
965                         if (((nvram_match("http_username", DEFAULT_USER)
966                              && nvram_match("http_passwd", DEFAULT_PASS))
967                             || nvram_match("http_username", "")
968                             || nvram_match("http_passwd", "admin")) && !endswith(file, "About.htm")){
969                                 changepassword = 1;
970                                 if (endswith(file, ".asp"))
971                                         file = "changepass.asp";
972                                 else if (endswith(file, ".htm")
973                                          && !endswith(file, "About.htm"))
974                                         file = "changepass.asp";
975                                 else if (endswith(file, ".html"))
976                                         file = "changepass.asp";
977                         } else {
978                                 if (endswith(file, "changepass.asp")) {
979                                         if (nvram_invmatch("status_auth", "0"))
980                                                 file = "Info.htm";
981                                         else
982                                                 file = "index.asp";
983                                 }
984                         }
985                 }
986                 for (handler = &mime_handlers[0]; handler->pattern; handler++) {
987                         if (match(handler->pattern, file)) {
988 #ifdef HAVE_REGISTER
989                                 if (registered)
990 #endif
991                                         if (!changepassword && handler->auth) {
992                                                 int result =
993                                                     handler->auth(conn_fp,
994                                                                   auth_userid,
995                                                                   auth_passwd,
996                                                                   auth_realm,
997                                                                   authorization,
998                                                                   auth_check);
999
1000                                                 if (!result) {
1001                                                         auth_fail = 0;
1002                                                         send_authenticate
1003                                                             (auth_realm);
1004                                                         return;
1005                                                 }
1006                                         }
1007                                 post = 0;
1008                                 if (strcasecmp(method, "post") == 0) {
1009                                         post = 1;
1010                                 }
1011                                 if (handler->input)
1012                                         handler->input(file, conn_fp, cl,
1013                                                        boundary);
1014 #if defined(linux)
1015 #ifdef HAVE_HTTPS
1016                                 if (!do_ssl
1017                                     && (flags =
1018                                         fcntl(fileno(conn_fp->fp),
1019                                               F_GETFL)) != -1
1020                                     && fcntl(fileno(conn_fp->fp), F_SETFL,
1021                                              flags | O_NONBLOCK) != -1) {
1022                                         /* Read up to two more characters */
1023                                         if (fgetc(conn_fp->fp) != EOF)
1024                                                 (void)fgetc(conn_fp->fp);
1025                                         fcntl(fileno(conn_fp->fp), F_SETFL,
1026                                               flags);
1027                                 }
1028 #else
1029                                 if ((flags =
1030                                      fcntl(fileno(conn_fp->fp), F_GETFL)) != -1
1031                                     && fcntl(fileno(conn_fp->fp), F_SETFL,
1032                                              flags | O_NONBLOCK) != -1) {
1033                                         /* Read up to two more characters */
1034                                         if (fgetc(conn_fp->fp) != EOF)
1035                                                 (void)fgetc(conn_fp->fp);
1036                                         fcntl(fileno(conn_fp->fp), F_SETFL,
1037                                               flags);
1038                                 }
1039 #endif
1040 #endif
1041                                 if (check_connect_type() < 0) {
1042                                         send_error(401, "Bad Request",
1043                                                    (char *)0,
1044                                                    "Can't use wireless interface to access GUI.");
1045 //                          free(line);
1046                                         return;
1047                                 }
1048
1049                                 if (auth_fail == 1) {
1050                                         send_authenticate(auth_realm);
1051                                         auth_fail = 0;
1052 //                          free(line);
1053                                         return;
1054                                 } else {
1055                                         if (handler->send_headers)
1056                                                 send_headers(200, "Ok",
1057                                                              handler->extra_header,
1058                                                              handler->mime_type,
1059                                                              0, NULL);
1060                                 }
1061                                 if (handler->output) {
1062                                         handler->output(handler, file, conn_fp,
1063                                                         query);
1064                                 }
1065                                 break;
1066                         }
1067
1068                         if (!handler->pattern)
1069                                 send_error(404, "Not Found", (char *)0,
1070                                            "File not found.");
1071                 }
1072
1073         }
1074 //    free(line);
1075 }
1076
1077 void                            // add by honor 2003-04-16
1078 get_client_ip_mac(int conn_fp)
1079 {
1080         struct sockaddr_in sa;
1081         unsigned int len = sizeof(struct sockaddr_in);
1082         char *m;
1083
1084         getpeername(conn_fp, (struct sockaddr *)&sa, &len);
1085         char client[32];
1086         char *peer = (char *)inet_ntop(AF_INET, &sa.sin_addr, client, 16);
1087
1088         nvram_set("http_client_ip", peer);
1089         m = get_mac_from_ip(peer);
1090         nvram_set("http_client_mac", m);
1091 }
1092
1093 static void handle_server_sig_int(int sig)
1094 {
1095 #ifdef HAVE_HTTPS
1096         ct_syslog(LOG_INFO, httpd_level, "httpd server %sshutdown",
1097                   do_ssl ? "(ssl support) " : "");
1098 #else
1099         ct_syslog(LOG_INFO, httpd_level, "httpd server shutdown");
1100 #endif
1101         exit(0);
1102 }
1103
1104 void settimeouts(int sock, int secs)
1105 {
1106         struct timeval tv;
1107
1108         tv.tv_sec = secs;
1109         tv.tv_usec = 0;
1110         if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
1111                 perror("setsockopt(SO_SNDTIMEO)");
1112         if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
1113                 perror("setsockopt(SO_RCVTIMEO)");
1114 }
1115
1116 /****************************************************************************
1117  *
1118  > $Function: decodeString()
1119  *
1120  * $Description: Given a URL encoded string, convert it to plain ascii.
1121  *   Since decoding always makes strings smaller, the decode is done in-place.
1122  *   Thus, callers should strdup() the argument if they do not want the
1123  *   argument modified.  The return is the original pointer, allowing this
1124  *   function to be easily used as arguments to other functions.
1125  *
1126  * $Parameters:
1127  *      (char *) string . . . The first string to decode.
1128  *      (int)    flag   . . . 1 if require decode '+' as ' ' for CGI
1129  *
1130  * $Return: (char *)  . . . . A pointer to the decoded string (same as input).
1131  *
1132  * $Errors: None
1133  *
1134  ****************************************************************************/
1135 static char *decodeString(char *orig, int flag_plus_to_space)
1136 {
1137         /* note that decoded string is always shorter than original */
1138         char *string = orig;
1139         char *ptr = string;
1140
1141         while (*ptr) {
1142                 if (*ptr == '+' && flag_plus_to_space) {
1143                         *string++ = ' ';
1144                         ptr++;
1145                 } else if (*ptr != '%')
1146                         *string++ = *ptr++;
1147                 else {
1148                         unsigned int value;
1149
1150                         sscanf(ptr + 1, "%2X", &value);
1151                         *string++ = value;
1152                         ptr += 3;
1153                 }
1154         }
1155         *string = '\0';
1156         return orig;
1157 }
1158
1159 /****************************************************************************
1160  *
1161  > $Function: encodeString()
1162  *
1163  * $Description: Given a string, html encode special characters.
1164  *   This is used for the -e command line option to provide an easy way
1165  *   for scripts to encode result data without confusing browsers.  The
1166  *   returned string pointer is memory allocated by malloc().
1167  *
1168  * $Parameters:
1169  *      (const char *) string . . The first string to encode.
1170  *
1171  * $Return: (char *) . . . .. . . A pointer to the encoded string.
1172  *
1173  * $Errors: Returns a null string ("") if memory is not available.
1174  *
1175  ****************************************************************************/
1176 static char *encodeString(const char *string)
1177 {
1178         /* take the simple route and encode everything */
1179         /* could possibly scan once to get length.     */
1180         int len = strlen(string);
1181         char *out = malloc(len * 5 + 1);
1182         char *p = out;
1183         char ch;
1184
1185         if (!out)
1186                 return "";
1187         while ((ch = *string++)) {
1188                 // very simple check for what to encode
1189
1190                 if (ch > '0' - 1 && ch < '9' + 1)
1191                         *p++ = ch;
1192                 else if (ch > 'a' - 1 && ch < 'z' + 1)
1193                         *p++ = ch;
1194                 else if (ch > 'A' - 1 && ch < 'Z' + 1)
1195                         *p++ = ch;
1196                 else
1197                         p += sprintf(p, "&#%d;", (unsigned char)ch);
1198         }
1199         *p = 0;
1200         return out;
1201 }
1202
1203 int main(int argc, char **argv)
1204 {
1205         usockaddr usa;
1206         int listen_fd;
1207         int conn_fd;
1208         socklen_t sz = sizeof(usa);
1209         int c;
1210         int timeout = TIMEOUT;
1211         struct stat stat_dir;
1212
1213         nvram_set("gozila_action", "0");
1214
1215 #ifdef FILTER_DEBUG
1216         debout = fopen("/tmp/filterdebug.log", "wb");
1217 #endif
1218         cprintf("init nvram tab\n");
1219 /* SEG addition */
1220         Initnvramtab();
1221         cprintf("done()\n");
1222 #ifdef HAVE_OPENSSL
1223         BIO *sbio;
1224         SSL_CTX *ctx = NULL;
1225         int r;
1226         BIO *ssl_bio;
1227 #endif
1228 #ifdef HAVE_XYSSL
1229         int ret, len;
1230         x509_cert srvcert;
1231         rsa_context rsa;
1232         havege_state hs;
1233 #endif
1234
1235         strcpy(pid_file, "/var/run/httpd.pid");
1236         server_port = DEFAULT_HTTP_PORT;
1237
1238         while ((c = getopt(argc, argv, "Sih:p:d:t:s:g:e:")) != -1)
1239                 switch (c) {
1240 #ifdef HAVE_HTTPS
1241                 case 'S':
1242 #if defined(HAVE_OPENSSL) || defined(HAVE_MATRIXSSL) || defined(HAVE_XYSSL)
1243                         do_ssl = 1;
1244                         server_port = DEFAULT_HTTPS_PORT;
1245                         strcpy(pid_file, "/var/run/httpsd.pid");
1246 #else
1247                         fprintf(stderr, "No SSL support available\n");
1248                         exit(0);
1249 #endif
1250                         break;
1251 #endif
1252                 case 'h':
1253                         server_dir = optarg;
1254                         break;
1255                 case 'p':
1256                         server_port = atoi(optarg);
1257                         break;
1258                 case 't':
1259                         timeout = atoi(optarg);
1260                         break;
1261 #ifdef DEBUG_CIPHER
1262                 case 's':
1263                         set_ciphers = optarg;
1264                         break;
1265                 case 'g':
1266                         get_ciphers = 1;
1267                         break;
1268 #endif
1269                 case 'e':
1270                         printf("%s", encodeString(optarg));
1271                         exit(0);
1272                         break;
1273                 case 'd':
1274                         printf("%s", decodeString(optarg, 1));
1275                         exit(0);
1276                         break;
1277                 case 'i':
1278                         fprintf(stderr, "Usage: %s [-S] [-p port]\n"
1279 #ifdef HAVE_HTTPS
1280                                 "       -S : Support https (port 443)\n"
1281 #endif
1282                                 "       -p port : Which port to listen?\n"
1283                                 "       -t secs : How many seconds to wait before timing out?\n"
1284                                 "       -s ciphers: set cipher lists\n"
1285                                 "       -g: get cipher lists\n"
1286                                 "       -h: home directory: use directory\n"
1287                                 "       -d: decode string\n"
1288                                 "       -e: encode string\n", argv[0]);
1289                         exit(0);
1290                         break;
1291                 default:
1292                         break;
1293                 }
1294
1295         httpd_level =
1296             ct_openlog("httpd", LOG_PID | LOG_NDELAY, LOG_DAEMON, "LOG_HTTPD");
1297 #ifdef HAVE_HTTPS
1298         ct_syslog(LOG_INFO, httpd_level, "httpd server %sstarted at port %d\n",
1299                   do_ssl ? "(ssl support) " : "", server_port);
1300 #else
1301         ct_syslog(LOG_INFO, httpd_level, "httpd server started at port %d\n",
1302                   server_port);
1303 #endif
1304         /* Ignore broken pipes */
1305         signal(SIGPIPE, SIG_IGN);
1306         signal(SIGTERM, handle_server_sig_int); // kill
1307
1308         if (server_dir && stat(server_dir, &stat_dir) == 0)
1309                 chdir(server_dir);
1310
1311         /* Build our SSL context */
1312 #ifdef HAVE_HTTPS
1313         if (do_ssl) {
1314 #ifdef HAVE_OPENSSL
1315                 SSLeay_add_ssl_algorithms();
1316                 SSL_load_error_strings();
1317                 ctx = SSL_CTX_new(SSLv23_server_method());
1318                 if (SSL_CTX_use_certificate_file
1319                     (ctx, CERT_FILE, SSL_FILETYPE_PEM)
1320                     == 0) {
1321                         cprintf("Can't read %s\n", CERT_FILE);
1322                         ERR_print_errors_fp(stderr);
1323                         exit(1);
1324
1325                 }
1326                 if (SSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, SSL_FILETYPE_PEM)
1327                     == 0) {
1328                         cprintf("Can't read %s\n", KEY_FILE);
1329                         ERR_print_errors_fp(stderr);
1330                         exit(1);
1331
1332                 }
1333                 if (SSL_CTX_check_private_key(ctx) == 0) {
1334                         cprintf("Check private key fail\n");
1335                         ERR_print_errors_fp(stderr);
1336                         exit(1);
1337                 }
1338 #endif
1339 #ifdef HAVE_XYSSL
1340                 memset(&ssl, 0, sizeof(ssl));
1341                 memset(&srvcert, 0, sizeof(x509_cert));
1342                 ret = x509_read_crtfile(&srvcert, CERT_FILE);
1343                 if (ret != 0) {
1344                         printf("x509_read_crtfile failed\n");
1345                         exit(0);
1346                 }
1347                 ret = x509_read_keyfile(&rsa, KEY_FILE, NULL);
1348                 if (ret != 0) {
1349                         printf("x509_read_keyfile failed\n");
1350                         exit(0);
1351                 }
1352 //              if (0 != xysslReadKeys(CERT_FILE, KEY_FILE)) {
1353 //                      fprintf(stderr, "Error reading or parsing %s.\n",KEY_FILE);
1354 //                      exit(0);
1355 //              }
1356 #endif
1357
1358 #ifdef HAVE_MATRIXSSL
1359                 matrixssl_init();
1360                 if (0 !=
1361                     matrixSslReadKeys(&keys, CERT_FILE, KEY_FILE, NULL, NULL)) {
1362                         fprintf(stderr, "Error reading or parsing %s.\n",
1363                                 KEY_FILE);
1364                         exit(0);
1365                 }
1366 #endif
1367         }
1368 #endif
1369
1370         /* Initialize listen socket */
1371         if ((listen_fd = initialize_listen_socket(&usa)) < 0) {
1372                 ct_syslog(LOG_ERR, httpd_level, "Can't bind to any address");
1373                 exit(errno);
1374         }
1375 #if !defined(DEBUG)
1376         {
1377                 FILE *pid_fp;
1378
1379                 /* Daemonize and log PID */
1380                 if (daemon(1, 1) == -1) {
1381                         perror("daemon");
1382                         exit(errno);
1383                 }
1384                 if (!(pid_fp = fopen(pid_file, "w"))) {
1385                         perror(pid_file);
1386                         return errno;
1387                 }
1388                 fprintf(pid_fp, "%d", getpid());
1389                 fclose(pid_fp);
1390         }
1391 #endif
1392
1393         /* Loop forever handling requests */
1394         for (;;) {
1395                 if ((conn_fd = accept(listen_fd, &usa.sa, &sz)) < 0) {
1396                         perror("accept");
1397                         return errno;
1398                 }
1399
1400                 /* Make sure we don't linger a long time if the other end disappears */
1401                 settimeouts(conn_fd, timeout);
1402
1403                 if (check_action() == ACT_TFTP_UPGRADE ||       // We don't want user to use web during tftp upgrade.
1404                     check_action() == ACT_SW_RESTORE ||
1405                     check_action() == ACT_HW_RESTORE) {
1406                         fprintf(stderr, "http(s)d: nothing to do...\n");
1407                         return -1;
1408                 }
1409 #ifdef HAVE_HTTPS
1410                 if (do_ssl) {
1411                         if (check_action() == ACT_WEB_UPGRADE) {        // We don't want user to use web (https) during web (http) upgrade.
1412                                 fprintf(stderr, "httpsd: nothing to do...\n");
1413                                 return -1;
1414                         }
1415 #ifdef HAVE_OPENSSL
1416                         sbio = BIO_new_socket(conn_fd, BIO_NOCLOSE);
1417                         ssl = SSL_new(ctx);
1418
1419 //#ifdef DEBUG_CIPHER
1420 //              check_cipher();
1421 //#endif
1422                         SSL_set_bio(ssl, sbio, sbio);
1423
1424                         if ((r = SSL_accept(ssl) <= 0)) {
1425                                 //berr_exit("SSL accept error");
1426                                 ct_syslog(LOG_ERR, httpd_level,
1427                                           "SSL accept error");
1428                                 close(conn_fd);
1429                                 continue;
1430                         }
1431
1432                         conn_fp = (webs_t)BIO_new(BIO_f_buffer());
1433                         ssl_bio = BIO_new(BIO_f_ssl());
1434                         BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE);
1435                         BIO_push((BIO *) conn_fp, ssl_bio);
1436 #elif defined(HAVE_MATRIXSSL)
1437                         matrixssl_new_session(conn_fd);
1438                         if (!conn_fp)
1439                                 conn_fp = malloc(sizeof(webs));
1440                         conn_fp->fp = (FILE *) conn_fd;
1441 #endif
1442 #ifdef HAVE_XYSSL
1443                         ssl_free(&ssl);
1444                         havege_init(&hs);
1445                         if ((ret = ssl_init(&ssl, 0)) != 0) {
1446                                 printf("ssl_init failed\n");
1447                                 close(conn_fd);
1448                                 continue;
1449                         }
1450 //              ret = xyssl_new_session(conn_fd);
1451                         ssl_set_endpoint(&ssl, SSL_IS_SERVER);
1452                         ssl_set_authmode(&ssl, SSL_VERIFY_NONE);
1453                         ssl_set_rng_func(&ssl, havege_rand, &hs);
1454                         ssl_set_io_files(&ssl, conn_fd, conn_fd);
1455                         ssl_set_ciphlist(&ssl, my_ciphers);
1456                         ssl_set_ca_chain(&ssl, srvcert.next, NULL);
1457                         ssl_set_rsa_cert(&ssl, &srvcert, &rsa);
1458                         ssl_set_sidtable(&ssl, session_table);
1459                         ssl_set_dhm_vals(&ssl, dhm_P, dhm_G);
1460
1461                         ret = ssl_server_start(&ssl);
1462                         if (ret != 0) {
1463                                 printf("ssl_server_start failed\n");
1464                                 close(conn_fd);
1465                                 continue;
1466                         }
1467 //              conn_fp = (FILE *)conn_fd;
1468                         conn_fp = (webs_t)(&ssl);
1469 #endif
1470                 } else
1471 #endif
1472                 {
1473 #ifdef HAVE_HTTPS
1474                         if (check_action() == ACT_WEBS_UPGRADE) {       // We don't want user to use web (http) during web (https) upgrade.
1475                                 fprintf(stderr, "httpd: nothing to do...\n");
1476                                 return -1;
1477                         }
1478 #endif
1479                         if (!conn_fp)
1480                                 conn_fp = malloc(sizeof(webs));
1481                         if (!(conn_fp->fp = fdopen(conn_fd, "r+"))) {
1482                                 perror("fdopen");
1483                                 return errno;
1484                         }
1485                 }
1486                 get_client_ip_mac(conn_fd);
1487                 handle_request();
1488                 wfflush(conn_fp);       // jimmy, https, 8/4/2003
1489 #ifdef HAVE_HTTPS
1490 #ifdef XYSSL_SUPPORT
1491                 ssl_close_notify(&ssl);
1492 #endif
1493 #endif
1494                 wfclose(conn_fp);       // jimmy, https, 8/4/2003
1495                 close(conn_fd);
1496         }
1497
1498         shutdown(listen_fd, 2);
1499         close(listen_fd);
1500
1501         return 0;
1502 }
1503
1504 char *wfgets(char *buf, int len, webs_t wp)
1505 {
1506         FILE *fp = wp->fp;
1507 #ifdef HAVE_HTTPS
1508 #ifdef HAVE_OPENSSL
1509         if (do_ssl)
1510                 return (char *)BIO_gets((BIO *) fp, buf, len);
1511         else
1512 #elif defined(HAVE_MATRIXSSL)
1513         if (do_ssl)
1514                 return (char *)matrixssl_gets(fp, buf, len);
1515         else
1516 #elif defined(HAVE_XYSSL)
1517         if (do_ssl)
1518                 return (char *)ssl_read_line((ssl_context *) fp,
1519                                              (unsigned char *)buf, &len);
1520         else
1521 #endif
1522 #endif
1523                 return fgets(buf, len, fp);
1524 }
1525
1526 int wfputc(char c, webs_t wp)
1527 {
1528         FILE *fp = wp->fp;
1529 #ifdef HAVE_HTTPS
1530 #ifdef HAVE_OPENSSL
1531         if (do_ssl)
1532                 return BIO_printf((BIO *) fp, "%c", c);
1533         else
1534 #elif defined(HAVE_MATRIXSSL)
1535         if (do_ssl)
1536                 return matrixssl_putc(fp, c);
1537         else
1538 #elif defined(HAVE_XYSSL)
1539         if (do_ssl)
1540                 return ssl_write((ssl_context *) fp, (unsigned char *)&c, 1);
1541         else
1542 #endif
1543 #endif
1544                 return fputc(c, fp);
1545 }
1546
1547 int wfputs(char *buf, webs_t wp)
1548 {
1549         FILE *fp = wp->fp;
1550
1551 #ifdef HAVE_HTTPS
1552 #ifdef HAVE_OPENSSL
1553         if (do_ssl)
1554                 return BIO_puts((BIO *) fp, buf);
1555         else
1556 #elif defined(HAVE_MATRIXSSL)
1557         if (do_ssl)
1558                 return matrixssl_puts(fp, buf);
1559         else
1560 #elif defined(HAVE_XYSSL)
1561         if (do_ssl)
1562                 return ssl_write((ssl_context *) fp, (unsigned char *)buf,
1563                                  strlen(buf));
1564         else
1565 #endif
1566 #endif
1567                 return fputs(buf, fp);
1568 }
1569
1570 int wfprintf(webs_t wp, char *fmt, ...)
1571 {
1572         FILE *fp = wp->fp;
1573
1574         va_list args;
1575         char buf[1024];
1576         int ret;
1577
1578         //buf = (char*)malloc(1024);
1579         va_start(args, fmt);
1580         vsnprintf(buf, sizeof(buf), fmt, args);
1581 #ifdef HAVE_HTTPS
1582 #ifdef HAVE_OPENSSL
1583         if (do_ssl)
1584                 ret = BIO_printf((BIO *) fp, "%s", buf);
1585         else
1586 #elif defined(HAVE_MATRIXSSL)
1587         if (do_ssl)
1588                 ret = matrixssl_printf(fp, "%s", buf);
1589         else
1590 #elif defined(HAVE_XYSSL)
1591         if (do_ssl)
1592                 ret = ssl_printf((ssl_context *) fp, "%s", buf);
1593         else
1594 #endif
1595 #endif
1596                 ret = fprintf(fp, "%s", buf);
1597         va_end(args);
1598         //free(buf);
1599         return ret;
1600 }
1601
1602 int websWrite(webs_t wp, char *fmt, ...)
1603 {
1604         va_list args;
1605         char buf[2048];
1606         int ret;
1607         FILE *fp = wp->fp;
1608
1609         if (!wp || !fmt)
1610                 return -1;
1611         //buf = (char*)malloc(1024);
1612         va_start(args, fmt);
1613         vsnprintf(buf, sizeof(buf), fmt, args);
1614 #ifdef HAVE_HTTPS
1615 #ifdef HAVE_OPENSSL
1616         if (do_ssl)
1617                 ret = BIO_printf((BIO *) fp, "%s", buf);
1618         else
1619 #elif defined(HAVE_MATRIXSSL)
1620         if (do_ssl)
1621                 ret = matrixssl_printf(fp, "%s", buf);
1622         else
1623 #elif defined(HAVE_XYSSL)
1624         if (do_ssl)
1625                 ret = ssl_printf((ssl_context *) fp, "%s", buf);
1626         else
1627 #endif
1628 #endif
1629                 ret = fprintf(fp, "%s", buf);
1630         va_end(args);
1631         wfflush(wp);
1632         return ret;
1633 }
1634
1635 size_t wfwrite(char *buf, int size, int n, webs_t wp)
1636 {
1637         FILE *fp = wp->fp;
1638 #ifdef HAVE_HTTPS
1639 #ifdef HAVE_OPENSSL
1640         if (do_ssl)
1641                 return BIO_write((BIO *) fp, buf, n * size);
1642         else
1643 #elif defined(HAVE_MATRIXSSL)
1644         if (do_ssl)
1645                 return matrixssl_write(fp, (unsigned char *)buf, n * size);
1646         else
1647 #elif defined(HAVE_XYSSL)
1648         if (do_ssl)
1649                 return ssl_write((ssl_context *) fp, (unsigned char *)buf,
1650                                  n * size);
1651         else
1652 #endif
1653 #endif
1654                 return fwrite(buf, size, n, fp);
1655 }
1656
1657 size_t wfread(char *buf, int size, int n, webs_t wp)
1658 {
1659         FILE *fp = wp->fp;
1660
1661 #ifdef HAVE_HTTPS
1662 #ifdef HAVE_OPENSSL
1663         if (do_ssl)
1664                 return BIO_read((BIO *) fp, buf, n * size);
1665         else
1666 #elif defined(HAVE_MATRIXSSL)
1667         if (do_ssl) {
1668                 //do it in chains
1669                 int cnt = (size * n) / 0x4000;
1670                 int i;
1671                 int len = 0;
1672
1673                 for (i = 0; i < cnt; i++) {
1674                         len += matrixssl_read(fp, buf, 0x4000);
1675                         *buf += 0x4000;
1676                 }
1677                 len += matrixssl_read(fp, buf, (size * n) % 0x4000);
1678
1679                 return len;
1680         } else
1681 #elif defined(HAVE_XYSSL)
1682         if (do_ssl) {
1683                 int len = n * size;
1684
1685                 return ssl_read((ssl_context *) fp, (unsigned char *)buf, &len);
1686         } else
1687 #endif
1688 #endif
1689                 return fread(buf, size, n, fp);
1690 }
1691
1692 int wfflush(webs_t wp)
1693 {
1694         FILE *fp = wp->fp;
1695 #ifdef HAVE_HTTPS
1696 #ifdef HAVE_OPENSSL
1697         if (do_ssl) {
1698                 BIO_flush((BIO *) fp);
1699                 return 1;
1700         } else
1701 #elif defined(HAVE_MATRIXSSL)
1702         if (do_ssl)
1703                 return matrixssl_flush(fp);
1704         else
1705 #elif defined(HAVE_XYSSL)
1706         if (do_ssl) {
1707                 ssl_flush((ssl_context *) fp);
1708                 return 1;
1709         } else
1710 #endif
1711 #endif
1712                 return fflush(fp);
1713 }
1714
1715 int wfclose(webs_t wp)
1716 {
1717         FILE *fp = wp->fp;
1718
1719 #ifdef HAVE_HTTPS
1720 #ifdef HAVE_OPENSSL
1721         if (do_ssl) {
1722                 BIO_free_all((BIO *) fp);
1723                 return 1;
1724         } else
1725 #elif defined(HAVE_MATRIXSSL)
1726         if (do_ssl)
1727                 return matrixssl_free_session(fp);
1728         else
1729 #elif defined(HAVE_XYSSL)
1730         if (do_ssl) {
1731                 ssl_free((ssl_context *) fp);
1732                 return 1;
1733         } else
1734 #endif
1735 #endif
1736                 return fclose(fp);
1737 }
1738
1739 #ifdef DEBUG_CIPHER
1740 void check_cipher(void)
1741 {
1742         STACK_OF(SSL_CIPHER) * sk;
1743         char buf[512];
1744         BIO *STDout = NULL;
1745         int i;
1746         static BIO *bio_stdout = NULL;
1747         X509 *peer;
1748         static BIO *bio_s_out = NULL;
1749         SSL_CIPHER *ciph;
1750
1751         if (set_ciphers) {
1752                 /* Set supported cipher lists */
1753                 SSL_set_cipher_list(ssl, set_ciphers);
1754         }
1755         if (get_ciphers) {
1756                 /* Show supported cipher lists */
1757                 sk = SSL_get_ciphers(ssl);
1758
1759                 for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
1760                         BIO_puts(STDout,
1761                                  SSL_CIPHER_description(sk_SSL_CIPHER_value
1762                                                         (sk, i), buf, 512));
1763                         printf("%d: %s", i, buf);
1764                 }
1765                 if (STDout != NULL)
1766                         BIO_free_all(STDout);
1767         }
1768         peer = SSL_get_peer_certificate(ssl);
1769         if (peer != NULL) {
1770                 BIO_printf(bio_s_out, "Client certificate\n");
1771                 PEM_write_bio_X509(bio_s_out, peer);
1772                 X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof buf);
1773                 BIO_printf(bio_s_out, "subject=%s\n", buf);
1774                 X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof buf);
1775                 BIO_printf(bio_s_out, "issuer=%s\n", buf);
1776                 X509_free(peer);
1777         }
1778
1779         if (SSL_get_shared_ciphers(ssl, buf, sizeof buf) != NULL)
1780                 BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf);
1781
1782         bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
1783         ciph = SSL_get_current_cipher(ssl);
1784         BIO_printf(bio_stdout, "%s%s, cipher %s %s\n",
1785                    "",
1786                    SSL_get_version(ssl),
1787                    SSL_CIPHER_get_version(ciph), SSL_CIPHER_get_name(ciph));
1788 }
1789 #endif
Note: See TracBrowser for help on using the browser.