root/src/router/httpd/httpd.c

Revision 12235, 42.3 kB (checked in by BrainSlayer, 6 months ago)

auto formated source

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         if (referer && host) {
773                 int i;
774                 int hlen = strlen(host);
775                 int rlen = strlen(referer);
776                 int slashs = 0;
777
778                 for (i = 0; i < rlen; i++) {
779                         if (referer[i] == '/')
780                                 slashs++;
781                         if (slashs == 2) {
782                                 i++;
783                                 break;
784                         }
785                 }
786                 if (slashs == 2) {
787                         int a;
788                         int c = 0;
789
790                         for (a = 0; a < hlen; a++)
791                                 if (host[a] == ' ' || host[a] == '\r'
792                                     || host[a] == '\n' || host[a] == '\t')
793                                         host[a] = 0;
794                         hlen = strlen(host);
795                         for (a = i; a < rlen; a++) {
796                                 if (referer[a] == '/') {
797                                         send_error(400, "Bad Request",
798                                                    (char *)0,
799                                                    "Cross Site Action detected!");
800                                         return;
801                                 }
802                                 if (host[c++] != referer[a]) {
803                                         send_error(400, "Bad Request",
804                                                    (char *)0,
805                                                    "Cross Site Action detected!");
806                                         return;
807                                 }
808                                 if (c == hlen) {
809                                         a++;
810                                         break;
811                                 }
812                         }
813                         if (c != hlen || referer[a] != '/') {
814                                 send_error(400, "Bad Request", (char *)0,
815                                            "Cross Site Action detected!");
816                                 return;
817                         }
818                 }
819
820         }
821         // seg change for status site
822 #ifdef HAVE_REGISTER
823         if (registered_real == -1) {
824                 registered_real = isregistered_real();
825         }
826         if (!registered_real)
827                 registered = isregistered();
828         else
829                 registered = registered_real;
830 #endif
831
832 #ifdef HAVE_SKYTRON
833         if (file[0] == '\0' || file[len - 1] == '/') {
834                 file = "setupindex.asp";
835         }
836 #else
837         if (file[0] == '\0' || file[len - 1] == '/') {
838
839                 {
840                         if (server_dir != NULL && strcmp(server_dir, "/www"))   // to allow to use router as a WEB server
841                         {
842                                 file = "index.htm";
843                         } else {
844                                 if (nvram_invmatch("status_auth", "0"))
845                                         file = "Info.htm";
846                                 else
847                                         file = "index.asp";
848                         }
849                 }
850         } else {
851                 {
852                         if (nvram_invmatch("status_auth", "1"))
853                                 if (strcmp(file, "Info.htm") == 0)
854                                         file = "index.asp";
855                 }
856         }
857 #endif
858
859         if (containsstring(file, "cgi-bin")) {
860
861                 auth_fail = 0;
862                 if (!do_auth
863                     (conn_fp, auth_userid, auth_passwd, auth_realm,
864                      authorization, auth_check))
865                         auth_fail = 1;
866                 query = NULL;
867                 if (strcasecmp(method, "post") == 0) {
868                         query = malloc(10000);
869                         if ((count = wfread(query, 1, cl, conn_fp))) {
870                                 query[count] = '\0';;
871                                 cl -= strlen(query);
872                         } else {
873                                 free(query);
874                                 query = NULL;
875                         }
876 #if defined(linux)
877 #ifdef HAVE_HTTPS
878                         if (!do_ssl
879                             && (flags =
880                                 fcntl(fileno(conn_fp->fp), F_GETFL)) != -1
881                             && fcntl(fileno(conn_fp->fp), F_SETFL,
882                                      flags | O_NONBLOCK) != -1) {
883                                 /* Read up to two more characters */
884                                 if (fgetc(conn_fp->fp) != EOF)
885                                         (void)fgetc(conn_fp->fp);
886                                 fcntl(fileno(conn_fp->fp), F_SETFL, flags);
887                         }
888 #else
889                         if ((flags = fcntl(fileno(conn_fp->fp), F_GETFL)) != -1
890                             && fcntl(fileno(conn_fp->fp), F_SETFL,
891                                      flags | O_NONBLOCK) != -1) {
892                                 /* Read up to two more characters */
893                                 if (fgetc(conn_fp->fp) != EOF)
894                                         (void)fgetc(conn_fp->fp);
895                                 fcntl(fileno(conn_fp->fp), F_SETFL, flags);
896                         }
897 #endif
898 #endif
899
900                 }
901                 exec = fopen("/tmp/exec.tmp", "wb");
902                 fprintf(exec, "export REQUEST_METHOD=\"%s\"\n", method);
903                 if (query)
904                         fprintf(exec, "/bin/sh %s/%s</tmp/exec.query\n",
905                                 server_dir != NULL ? server_dir : "/www", file);
906                 else
907                         fprintf(exec, "/%s/%s\n",
908                                 server_dir != NULL ? server_dir : "/www", file);
909                 fclose(exec);
910
911                 if (query) {
912                         exec = fopen("/tmp/exec.query", "wb");
913                         fprintf(exec, "%s\n", query);
914                         free(query);
915                         fclose(exec);
916                 }
917
918                 system2("chmod 700 /tmp/exec.tmp");
919                 system2("/tmp/exec.tmp>/tmp/shellout.asp");
920                 if (check_connect_type() < 0) {
921                         send_error(401, "Bad Request", (char *)0,
922                                    "Can't use wireless interface to access GUI.");
923 //          free(line);
924                         return;
925                 }
926                 if (auth_fail == 1) {
927                         send_authenticate(auth_realm);
928                         auth_fail = 0;
929 //          free(line);
930                         return;
931                 }
932
933                 do_ej(NULL, "/tmp/shellout.asp", conn_fp, "");
934                 unlink("/tmp/shellout.asp");
935                 unlink("/tmp/exec.tmp");
936                 unlink("/tmp/exec.query");
937
938         } else {
939                 /* extract url args if present */
940                 query = strchr(file, '?');
941                 if (query) {
942                         *query++ = 0;
943                 }
944                 int changepassword = 0;
945
946 #ifdef HAVE_REGISTER
947                 if (!registered_real) {
948                         if (endswith(file, "About.htm"))
949                                 file = "register.asp";
950                 }
951                 if (!registered) {
952                         if (endswith(file, ".asp"))
953                                 file = "register.asp";
954                         else if (endswith(file, ".htm"))
955                                 file = "register.asp";
956                         else if (endswith(file, ".html"))
957                                 file = "register.asp";
958                 } else
959 #endif
960                 {
961                         if ((nvram_match("http_username", DEFAULT_USER)
962                              && nvram_match("http_passwd", DEFAULT_PASS))
963                             || nvram_match("http_username", "")
964                             || nvram_match("http_passwd", "admin")) {
965                                 changepassword = 1;
966                                 if (endswith(file, ".asp"))
967                                         file = "changepass.asp";
968                                 else if (endswith(file, ".htm")
969                                          && !endswith(file, "About.htm"))
970                                         file = "changepass.asp";
971                                 else if (endswith(file, ".html"))
972                                         file = "changepass.asp";
973                         } else {
974                                 if (endswith(file, "changepass.asp")) {
975                                         if (nvram_invmatch("status_auth", "0"))
976                                                 file = "Info.htm";
977                                         else
978                                                 file = "index.asp";
979                                 }
980                         }
981                 }
982                 for (handler = &mime_handlers[0]; handler->pattern; handler++) {
983                         if (match(handler->pattern, file)) {
984 #ifdef HAVE_REGISTER
985                                 if (registered)
986 #endif
987                                         if (!changepassword && handler->auth) {
988                                                 int result =
989                                                     handler->auth(conn_fp,
990                                                                   auth_userid,
991                                                                   auth_passwd,
992                                                                   auth_realm,
993                                                                   authorization,
994                                                                   auth_check);
995
996                                                 if (!result) {
997                                                         auth_fail = 0;
998                                                         send_authenticate
999                                                             (auth_realm);
1000                                                         return;
1001                                                 }
1002                                         }
1003                                 post = 0;
1004                                 if (strcasecmp(method, "post") == 0) {
1005                                         post = 1;
1006                                 }
1007                                 if (handler->input)
1008                                         handler->input(file, conn_fp, cl,
1009                                                        boundary);
1010 #if defined(linux)
1011 #ifdef HAVE_HTTPS
1012                                 if (!do_ssl
1013                                     && (flags =
1014                                         fcntl(fileno(conn_fp->fp),
1015                                               F_GETFL)) != -1
1016                                     && fcntl(fileno(conn_fp->fp), F_SETFL,
1017                                              flags | O_NONBLOCK) != -1) {
1018                                         /* Read up to two more characters */
1019                                         if (fgetc(conn_fp->fp) != EOF)
1020                                                 (void)fgetc(conn_fp->fp);
1021                                         fcntl(fileno(conn_fp->fp), F_SETFL,
1022                                               flags);
1023                                 }
1024 #else
1025                                 if ((flags =
1026                                      fcntl(fileno(conn_fp->fp), F_GETFL)) != -1
1027                                     && fcntl(fileno(conn_fp->fp), F_SETFL,
1028                                              flags | O_NONBLOCK) != -1) {
1029                                         /* Read up to two more characters */
1030                                         if (fgetc(conn_fp->fp) != EOF)
1031                                                 (void)fgetc(conn_fp->fp);
1032                                         fcntl(fileno(conn_fp->fp), F_SETFL,
1033                                               flags);
1034                                 }
1035 #endif
1036 #endif
1037                                 if (check_connect_type() < 0) {
1038                                         send_error(401, "Bad Request",
1039                                                    (char *)0,
1040                                                    "Can't use wireless interface to access GUI.");
1041 //                          free(line);
1042                                         return;
1043                                 }
1044
1045                                 if (auth_fail == 1) {
1046                                         send_authenticate(auth_realm);
1047                                         auth_fail = 0;
1048 //                          free(line);
1049                                         return;
1050                                 } else {
1051                                         if (handler->send_headers)
1052                                                 send_headers(200, "Ok",
1053                                                              handler->extra_header,
1054                                                              handler->mime_type,
1055                                                              0, NULL);
1056                                 }
1057                                 if (handler->output) {
1058                                         handler->output(handler, file, conn_fp,
1059                                                         query);
1060                                 }
1061                                 break;
1062                         }
1063
1064                         if (!handler->pattern)
1065                                 send_error(404, "Not Found", (char *)0,
1066                                            "File not found.");
1067                 }
1068
1069         }
1070 //    free(line);
1071 }
1072
1073 void                            // add by honor 2003-04-16
1074 get_client_ip_mac(int conn_fp)
1075 {
1076         struct sockaddr_in sa;
1077         unsigned int len = sizeof(struct sockaddr_in);
1078         char *m;
1079
1080         getpeername(conn_fp, (struct sockaddr *)&sa, &len);
1081         char client[32];
1082         char *peer = (char *)inet_ntop(AF_INET, &sa.sin_addr, client, 16);
1083
1084         nvram_set("http_client_ip", peer);
1085         m = get_mac_from_ip(peer);
1086         nvram_set("http_client_mac", m);
1087 }
1088
1089 static void handle_server_sig_int(int sig)
1090 {
1091 #ifdef HAVE_HTTPS
1092         ct_syslog(LOG_INFO, httpd_level, "httpd server %sshutdown",
1093                   do_ssl ? "(ssl support) " : "");
1094 #else
1095         ct_syslog(LOG_INFO, httpd_level, "httpd server shutdown");
1096 #endif
1097         exit(0);
1098 }
1099
1100 void settimeouts(int sock, int secs)
1101 {
1102         struct timeval tv;
1103
1104         tv.tv_sec = secs;
1105         tv.tv_usec = 0;
1106         if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
1107                 perror("setsockopt(SO_SNDTIMEO)");
1108         if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
1109                 perror("setsockopt(SO_RCVTIMEO)");
1110 }
1111
1112 /****************************************************************************
1113  *
1114  > $Function: decodeString()
1115  *
1116  * $Description: Given a URL encoded string, convert it to plain ascii.
1117  *   Since decoding always makes strings smaller, the decode is done in-place.
1118  *   Thus, callers should strdup() the argument if they do not want the
1119  *   argument modified.  The return is the original pointer, allowing this
1120  *   function to be easily used as arguments to other functions.
1121  *
1122  * $Parameters:
1123  *      (char *) string . . . The first string to decode.
1124  *      (int)    flag   . . . 1 if require decode '+' as ' ' for CGI
1125  *
1126  * $Return: (char *)  . . . . A pointer to the decoded string (same as input).
1127  *
1128  * $Errors: None
1129  *
1130  ****************************************************************************/
1131 static char *decodeString(char *orig, int flag_plus_to_space)
1132 {
1133         /* note that decoded string is always shorter than original */
1134         char *string = orig;
1135         char *ptr = string;
1136
1137         while (*ptr) {
1138                 if (*ptr == '+' && flag_plus_to_space) {
1139                         *string++ = ' ';
1140                         ptr++;
1141                 } else if (*ptr != '%')
1142                         *string++ = *ptr++;
1143                 else {
1144                         unsigned int value;
1145
1146                         sscanf(ptr + 1, "%2X", &value);
1147                         *string++ = value;
1148                         ptr += 3;
1149                 }
1150         }
1151         *string = '\0';
1152         return orig;
1153 }
1154
1155 /****************************************************************************
1156  *
1157  > $Function: encodeString()
1158  *
1159  * $Description: Given a string, html encode special characters.
1160  *   This is used for the -e command line option to provide an easy way
1161  *   for scripts to encode result data without confusing browsers.  The
1162  *   returned string pointer is memory allocated by malloc().
1163  *
1164  * $Parameters:
1165  *      (const char *) string . . The first string to encode.
1166  *
1167  * $Return: (char *) . . . .. . . A pointer to the encoded string.
1168  *
1169  * $Errors: Returns a null string ("") if memory is not available.
1170  *
1171  ****************************************************************************/
1172 static char *encodeString(const char *string)
1173 {
1174         /* take the simple route and encode everything */
1175         /* could possibly scan once to get length.     */
1176         int len = strlen(string);
1177         char *out = malloc(len * 5 + 1);
1178         char *p = out;
1179         char ch;
1180
1181         if (!out)
1182                 return "";
1183         while ((ch = *string++)) {
1184                 // very simple check for what to encode
1185
1186                 if (ch > '0' - 1 && ch < '9' + 1)
1187                         *p++ = ch;
1188                 else if (ch > 'a' - 1 && ch < 'z' + 1)
1189                         *p++ = ch;
1190                 else if (ch > 'A' - 1 && ch < 'Z' + 1)
1191                         *p++ = ch;
1192                 else
1193                         p += sprintf(p, "&#%d;", (unsigned char)ch);
1194         }
1195         *p = 0;
1196         return out;
1197 }
1198
1199 int main(int argc, char **argv)
1200 {
1201         usockaddr usa;
1202         int listen_fd;
1203         int conn_fd;
1204         socklen_t sz = sizeof(usa);
1205         int c;
1206         int timeout = TIMEOUT;
1207         struct stat stat_dir;
1208
1209         nvram_set("gozila_action", "0");
1210
1211 #ifdef FILTER_DEBUG
1212         debout = fopen("/tmp/filterdebug.log", "wb");
1213 #endif
1214         cprintf("init nvram tab\n");
1215 /* SEG addition */
1216         Initnvramtab();
1217         cprintf("done()\n");
1218 #ifdef HAVE_OPENSSL
1219         BIO *sbio;
1220         SSL_CTX *ctx = NULL;
1221         int r;
1222         BIO *ssl_bio;
1223 #endif
1224 #ifdef HAVE_XYSSL
1225         int ret, len;
1226         x509_cert srvcert;
1227         rsa_context rsa;
1228         havege_state hs;
1229 #endif
1230
1231         strcpy(pid_file, "/var/run/httpd.pid");
1232         server_port = DEFAULT_HTTP_PORT;
1233
1234         while ((c = getopt(argc, argv, "Sih:p:d:t:s:g:e:")) != -1)
1235                 switch (c) {
1236 #ifdef HAVE_HTTPS
1237                 case 'S':
1238 #if defined(HAVE_OPENSSL) || defined(HAVE_MATRIXSSL) || defined(HAVE_XYSSL)
1239                         do_ssl = 1;
1240                         server_port = DEFAULT_HTTPS_PORT;
1241                         strcpy(pid_file, "/var/run/httpsd.pid");
1242 #else
1243                         fprintf(stderr, "No SSL support available\n");
1244                         exit(0);
1245 #endif
1246                         break;
1247 #endif
1248                 case 'h':
1249                         server_dir = optarg;
1250                         break;
1251                 case 'p':
1252                         server_port = atoi(optarg);
1253                         break;
1254                 case 't':
1255                         timeout = atoi(optarg);
1256                         break;
1257 #ifdef DEBUG_CIPHER
1258                 case 's':
1259                         set_ciphers = optarg;
1260                         break;
1261                 case 'g':
1262                         get_ciphers = 1;
1263                         break;
1264 #endif
1265                 case 'e':
1266                         printf("%s", encodeString(optarg));
1267                         exit(0);
1268                         break;
1269                 case 'd':
1270                         printf("%s", decodeString(optarg, 1));
1271                         exit(0);
1272                         break;
1273                 case 'i':
1274                         fprintf(stderr, "Usage: %s [-S] [-p port]\n"
1275 #ifdef HAVE_HTTPS
1276                                 "       -S : Support https (port 443)\n"
1277 #endif
1278                                 "       -p port : Which port to listen?\n"
1279                                 "       -t secs : How many seconds to wait before timing out?\n"
1280                                 "       -s ciphers: set cipher lists\n"
1281                                 "       -g: get cipher lists\n"
1282                                 "       -h: home directory: use directory\n"
1283                                 "       -d: decode string\n"
1284                                 "       -e: encode string\n", argv[0]);
1285                         exit(0);
1286                         break;
1287                 default:
1288                         break;
1289                 }
1290
1291         httpd_level =
1292             ct_openlog("httpd", LOG_PID | LOG_NDELAY, LOG_DAEMON, "LOG_HTTPD");
1293 #ifdef HAVE_HTTPS
1294         ct_syslog(LOG_INFO, httpd_level, "httpd server %sstarted at port %d\n",
1295                   do_ssl ? "(ssl support) " : "", server_port);
1296 #else
1297         ct_syslog(LOG_INFO, httpd_level, "httpd server started at port %d\n",
1298                   server_port);
1299 #endif
1300         /* Ignore broken pipes */
1301         signal(SIGPIPE, SIG_IGN);
1302         signal(SIGTERM, handle_server_sig_int); // kill
1303
1304         if (server_dir && stat(server_dir, &stat_dir) == 0)
1305                 chdir(server_dir);
1306
1307         /* Build our SSL context */
1308 #ifdef HAVE_HTTPS
1309         if (do_ssl) {
1310 #ifdef HAVE_OPENSSL
1311                 SSLeay_add_ssl_algorithms();
1312                 SSL_load_error_strings();
1313                 ctx = SSL_CTX_new(SSLv23_server_method());
1314                 if (SSL_CTX_use_certificate_file
1315                     (ctx, CERT_FILE, SSL_FILETYPE_PEM)
1316                     == 0) {
1317                         cprintf("Can't read %s\n", CERT_FILE);
1318                         ERR_print_errors_fp(stderr);
1319                         exit(1);
1320
1321                 }
1322                 if (SSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, SSL_FILETYPE_PEM)
1323                     == 0) {
1324                         cprintf("Can't read %s\n", KEY_FILE);
1325                         ERR_print_errors_fp(stderr);
1326                         exit(1);
1327
1328                 }
1329                 if (SSL_CTX_check_private_key(ctx) == 0) {
1330                         cprintf("Check private key fail\n");
1331                         ERR_print_errors_fp(stderr);
1332                         exit(1);
1333                 }
1334 #endif
1335 #ifdef HAVE_XYSSL
1336                 memset(&ssl, 0, sizeof(ssl));
1337                 memset(&srvcert, 0, sizeof(x509_cert));
1338                 ret = x509_read_crtfile(&srvcert, CERT_FILE);
1339                 if (ret != 0) {
1340                         printf("x509_read_crtfile failed\n");
1341                         exit(0);
1342                 }
1343                 ret = x509_read_keyfile(&rsa, KEY_FILE, NULL);
1344                 if (ret != 0) {
1345                         printf("x509_read_keyfile failed\n");
1346                         exit(0);
1347                 }
1348 //              if (0 != xysslReadKeys(CERT_FILE, KEY_FILE)) {
1349 //                      fprintf(stderr, "Error reading or parsing %s.\n",KEY_FILE);
1350 //                      exit(0);
1351 //              }
1352 #endif
1353
1354 #ifdef HAVE_MATRIXSSL
1355                 matrixssl_init();
1356                 if (0 !=
1357                     matrixSslReadKeys(&keys, CERT_FILE, KEY_FILE, NULL, NULL)) {
1358                         fprintf(stderr, "Error reading or parsing %s.\n",
1359                                 KEY_FILE);
1360                         exit(0);
1361                 }
1362 #endif
1363         }
1364 #endif
1365
1366         /* Initialize listen socket */
1367         if ((listen_fd = initialize_listen_socket(&usa)) < 0) {
1368                 ct_syslog(LOG_ERR, httpd_level, "Can't bind to any address");
1369                 exit(errno);
1370         }
1371 #if !defined(DEBUG)
1372         {
1373                 FILE *pid_fp;
1374
1375                 /* Daemonize and log PID */
1376                 if (daemon(1, 1) == -1) {
1377                         perror("daemon");
1378                         exit(errno);
1379                 }
1380                 if (!(pid_fp = fopen(pid_file, "w"))) {
1381                         perror(pid_file);
1382                         return errno;
1383                 }
1384                 fprintf(pid_fp, "%d", getpid());
1385                 fclose(pid_fp);
1386         }
1387 #endif
1388
1389         /* Loop forever handling requests */
1390         for (;;) {
1391                 if ((conn_fd = accept(listen_fd, &usa.sa, &sz)) < 0) {
1392                         perror("accept");
1393                         return errno;
1394                 }
1395
1396                 /* Make sure we don't linger a long time if the other end disappears */
1397                 settimeouts(conn_fd, timeout);
1398
1399                 if (check_action() == ACT_TFTP_UPGRADE ||       // We don't want user to use web during tftp upgrade.
1400                     check_action() == ACT_SW_RESTORE ||
1401                     check_action() == ACT_HW_RESTORE) {
1402                         fprintf(stderr, "http(s)d: nothing to do...\n");
1403                         return -1;
1404                 }
1405 #ifdef HAVE_HTTPS
1406                 if (do_ssl) {
1407                         if (check_action() == ACT_WEB_UPGRADE) {        // We don't want user to use web (https) during web (http) upgrade.
1408                                 fprintf(stderr, "httpsd: nothing to do...\n");
1409                                 return -1;
1410                         }
1411 #ifdef HAVE_OPENSSL
1412                         sbio = BIO_new_socket(conn_fd, BIO_NOCLOSE);
1413                         ssl = SSL_new(ctx);
1414
1415 //#ifdef DEBUG_CIPHER
1416 //              check_cipher();
1417 //#endif
1418                         SSL_set_bio(ssl, sbio, sbio);
1419
1420                         if ((r = SSL_accept(ssl) <= 0)) {
1421                                 //berr_exit("SSL accept error");
1422                                 ct_syslog(LOG_ERR, httpd_level,
1423                                           "SSL accept error");
1424                                 close(conn_fd);
1425                                 continue;
1426                         }
1427
1428                         conn_fp = (webs_t)BIO_new(BIO_f_buffer());
1429                         ssl_bio = BIO_new(BIO_f_ssl());
1430                         BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE);
1431                         BIO_push((BIO *) conn_fp, ssl_bio);
1432 #elif defined(HAVE_MATRIXSSL)
1433                         matrixssl_new_session(conn_fd);
1434                         if (!conn_fp)
1435                                 conn_fp = malloc(sizeof(webs));
1436                         conn_fp->fp = (FILE *) conn_fd;
1437 #endif
1438 #ifdef HAVE_XYSSL
1439                         ssl_free(&ssl);
1440                         havege_init(&hs);
1441                         if ((ret = ssl_init(&ssl, 0)) != 0) {
1442                                 printf("ssl_init failed\n");
1443                                 close(conn_fd);
1444                                 continue;
1445                         }
1446 //              ret = xyssl_new_session(conn_fd);
1447                         ssl_set_endpoint(&ssl, SSL_IS_SERVER);
1448                         ssl_set_authmode(&ssl, SSL_VERIFY_NONE);
1449                         ssl_set_rng_func(&ssl, havege_rand, &hs);
1450                         ssl_set_io_files(&ssl, conn_fd, conn_fd);
1451                         ssl_set_ciphlist(&ssl, my_ciphers);
1452                         ssl_set_ca_chain(&ssl, srvcert.next, NULL);
1453                         ssl_set_rsa_cert(&ssl, &srvcert, &rsa);
1454                         ssl_set_sidtable(&ssl, session_table);
1455                         ssl_set_dhm_vals(&ssl, dhm_P, dhm_G);
1456
1457                         ret = ssl_server_start(&ssl);
1458                         if (ret != 0) {
1459                                 printf("ssl_server_start failed\n");
1460                                 close(conn_fd);
1461                                 continue;
1462                         }
1463 //              conn_fp = (FILE *)conn_fd;
1464                         conn_fp = (webs_t)(&ssl);
1465 #endif
1466                 } else
1467 #endif
1468                 {
1469 #ifdef HAVE_HTTPS
1470                         if (check_action() == ACT_WEBS_UPGRADE) {       // We don't want user to use web (http) during web (https) upgrade.
1471                                 fprintf(stderr, "httpd: nothing to do...\n");
1472                                 return -1;
1473                         }
1474 #endif
1475                         if (!conn_fp)
1476                                 conn_fp = malloc(sizeof(webs));
1477                         if (!(conn_fp->fp = fdopen(conn_fd, "r+"))) {
1478                                 perror("fdopen");
1479                                 return errno;
1480                         }
1481                 }
1482                 get_client_ip_mac(conn_fd);
1483                 handle_request();
1484                 wfflush(conn_fp);       // jimmy, https, 8/4/2003
1485 #ifdef HAVE_HTTPS
1486 #ifdef XYSSL_SUPPORT
1487                 ssl_close_notify(&ssl);
1488 #endif
1489 #endif
1490                 wfclose(conn_fp);       // jimmy, https, 8/4/2003
1491                 close(conn_fd);
1492         }
1493
1494         shutdown(listen_fd, 2);
1495         close(listen_fd);
1496
1497         return 0;
1498 }
1499
1500 char *wfgets(char *buf, int len, webs_t wp)
1501 {
1502         FILE *fp = wp->fp;
1503 #ifdef HAVE_HTTPS
1504 #ifdef HAVE_OPENSSL
1505         if (do_ssl)
1506                 return (char *)BIO_gets((BIO *) fp, buf, len);
1507         else
1508 #elif defined(HAVE_MATRIXSSL)
1509         if (do_ssl)
1510                 return (char *)matrixssl_gets(fp, buf, len);
1511         else
1512 #elif defined(HAVE_XYSSL)
1513         if (do_ssl)
1514                 return (char *)ssl_read_line((ssl_context *) fp,
1515                                              (unsigned char *)buf, &len);
1516         else
1517 #endif
1518 #endif
1519                 return fgets(buf, len, fp);
1520 }
1521
1522 int wfputc(char c, webs_t wp)
1523 {
1524         FILE *fp = wp->fp;
1525 #ifdef HAVE_HTTPS
1526 #ifdef HAVE_OPENSSL
1527         if (do_ssl)
1528                 return BIO_printf((BIO *) fp, "%c", c);
1529         else
1530 #elif defined(HAVE_MATRIXSSL)
1531         if (do_ssl)
1532                 return matrixssl_putc(fp, c);
1533         else
1534 #elif defined(HAVE_XYSSL)
1535         if (do_ssl)
1536                 return ssl_write((ssl_context *) fp, (unsigned char *)&c, 1);
1537         else
1538 #endif
1539 #endif
1540                 return fputc(c, fp);
1541 }
1542
1543 int wfputs(char *buf, webs_t wp)
1544 {
1545         FILE *fp = wp->fp;
1546
1547 #ifdef HAVE_HTTPS
1548 #ifdef HAVE_OPENSSL
1549         if (do_ssl)
1550                 return BIO_puts((BIO *) fp, buf);
1551         else
1552 #elif defined(HAVE_MATRIXSSL)
1553         if (do_ssl)
1554                 return matrixssl_puts(fp, buf);
1555         else
1556 #elif defined(HAVE_XYSSL)
1557         if (do_ssl)
1558                 return ssl_write((ssl_context *) fp, (unsigned char *)buf,
1559                                  strlen(buf));
1560         else
1561 #endif
1562 #endif
1563                 return fputs(buf, fp);
1564 }
1565
1566 int wfprintf(webs_t wp, char *fmt, ...)
1567 {
1568         FILE *fp = wp->fp;
1569
1570         va_list args;
1571         char buf[1024];
1572         int ret;
1573
1574         //buf = (char*)malloc(1024);
1575         va_start(args, fmt);
1576         vsnprintf(buf, sizeof(buf), fmt, args);
1577 #ifdef HAVE_HTTPS
1578 #ifdef HAVE_OPENSSL
1579         if (do_ssl)
1580                 ret = BIO_printf((BIO *) fp, "%s", buf);
1581         else
1582 #elif defined(HAVE_MATRIXSSL)
1583         if (do_ssl)
1584                 ret = matrixssl_printf(fp, "%s", buf);
1585         else
1586 #elif defined(HAVE_XYSSL)
1587         if (do_ssl)
1588                 ret = ssl_printf((ssl_context *) fp, "%s", buf);
1589         else
1590 #endif
1591 #endif
1592                 ret = fprintf(fp, "%s", buf);
1593         va_end(args);
1594         //free(buf);
1595         return ret;
1596 }
1597
1598 int websWrite(webs_t wp, char *fmt, ...)
1599 {
1600         va_list args;
1601         char buf[2048];
1602         int ret;
1603         FILE *fp = wp->fp;
1604
1605         if (!wp || !fmt)
1606                 return -1;
1607         //buf = (char*)malloc(1024);
1608         va_start(args, fmt);
1609         vsnprintf(buf, sizeof(buf), fmt, args);
1610 #ifdef HAVE_HTTPS
1611 #ifdef HAVE_OPENSSL
1612         if (do_ssl)
1613                 ret = BIO_printf((BIO *) fp, "%s", buf);
1614         else
1615 #elif defined(HAVE_MATRIXSSL)
1616         if (do_ssl)
1617                 ret = matrixssl_printf(fp, "%s", buf);
1618         else
1619 #elif defined(HAVE_XYSSL)
1620         if (do_ssl)
1621                 ret = ssl_printf((ssl_context *) fp, "%s", buf);
1622         else
1623 #endif
1624 #endif
1625                 ret = fprintf(fp, "%s", buf);
1626         va_end(args);
1627         wfflush(wp);
1628         return ret;
1629 }
1630
1631 size_t wfwrite(char *buf, int size, int n, webs_t wp)
1632 {
1633         FILE *fp = wp->fp;
1634 #ifdef HAVE_HTTPS
1635 #ifdef HAVE_OPENSSL
1636         if (do_ssl)
1637                 return BIO_write((BIO *) fp, buf, n * size);
1638         else
1639 #elif defined(HAVE_MATRIXSSL)
1640         if (do_ssl)
1641                 return matrixssl_write(fp, (unsigned char *)buf, n * size);
1642         else
1643 #elif defined(HAVE_XYSSL)
1644         if (do_ssl)
1645                 return ssl_write((ssl_context *) fp, (unsigned char *)buf,
1646                                  n * size);
1647         else
1648 #endif
1649 #endif
1650                 return fwrite(buf, size, n, fp);
1651 }
1652
1653 size_t wfread(char *buf, int size, int n, webs_t wp)
1654 {
1655         FILE *fp = wp->fp;
1656
1657 #ifdef HAVE_HTTPS
1658 #ifdef HAVE_OPENSSL
1659         if (do_ssl)
1660                 return BIO_read((BIO *) fp, buf, n * size);
1661         else
1662 #elif defined(HAVE_MATRIXSSL)
1663         if (do_ssl) {
1664                 //do it in chains
1665                 int cnt = (size * n) / 0x4000;
1666                 int i;
1667                 int len = 0;
1668
1669                 for (i = 0; i < cnt; i++) {
1670                         len += matrixssl_read(fp, buf, 0x4000);
1671                         *buf += 0x4000;
1672                 }
1673                 len += matrixssl_read(fp, buf, (size * n) % 0x4000);
1674
1675                 return len;
1676         } else
1677 #elif defined(HAVE_XYSSL)
1678         if (do_ssl) {
1679                 int len = n * size;
1680
1681                 return ssl_read((ssl_context *) fp, (unsigned char *)buf, &len);
1682         } else
1683 #endif
1684 #endif
1685                 return fread(buf, size, n, fp);
1686 }
1687
1688 int wfflush(webs_t wp)
1689 {
1690         FILE *fp = wp->fp;
1691 #ifdef HAVE_HTTPS
1692 #ifdef HAVE_OPENSSL
1693         if (do_ssl) {
1694                 BIO_flush((BIO *) fp);
1695                 return 1;
1696         } else
1697 #elif defined(HAVE_MATRIXSSL)
1698         if (do_ssl)
1699                 return matrixssl_flush(fp);
1700         else
1701 #elif defined(HAVE_XYSSL)
1702         if (do_ssl) {
1703                 ssl_flush((ssl_context *) fp);
1704                 return 1;
1705         } else
1706 #endif
1707 #endif
1708                 return fflush(fp);
1709 }
1710
1711 int wfclose(webs_t wp)
1712 {
1713         FILE *fp = wp->fp;
1714
1715 #ifdef HAVE_HTTPS
1716 #ifdef HAVE_OPENSSL
1717         if (do_ssl) {
1718                 BIO_free_all((BIO *) fp);
1719                 return 1;
1720         } else
1721 #elif defined(HAVE_MATRIXSSL)
1722         if (do_ssl)
1723                 return matrixssl_free_session(fp);
1724         else
1725 #elif defined(HAVE_XYSSL)
1726         if (do_ssl) {
1727                 ssl_free((ssl_context *) fp);
1728                 return 1;
1729         } else
1730 #endif
1731 #endif
1732                 return fclose(fp);
1733 }
1734
1735 #ifdef DEBUG_CIPHER
1736 void check_cipher(void)
1737 {
1738         STACK_OF(SSL_CIPHER) * sk;
1739         char buf[512];
1740         BIO *STDout = NULL;
1741         int i;
1742         static BIO *bio_stdout = NULL;
1743         X509 *peer;
1744         static BIO *bio_s_out = NULL;
1745         SSL_CIPHER *ciph;
1746
1747         if (set_ciphers) {
1748                 /* Set supported cipher lists */
1749                 SSL_set_cipher_list(ssl, set_ciphers);
1750         }
1751         if (get_ciphers) {
1752                 /* Show supported cipher lists */
1753                 sk = SSL_get_ciphers(ssl);
1754
1755                 for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
1756                         BIO_puts(STDout,
1757                                  SSL_CIPHER_description(sk_SSL_CIPHER_value
1758                                                         (sk, i), buf, 512));
1759                         printf("%d: %s", i, buf);
1760                 }
1761                 if (STDout != NULL)
1762                         BIO_free_all(STDout);
1763         }
1764         peer = SSL_get_peer_certificate(ssl);
1765         if (peer != NULL) {
1766                 BIO_printf(bio_s_out, "Client certificate\n");
1767                 PEM_write_bio_X509(bio_s_out, peer);
1768                 X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof buf);
1769                 BIO_printf(bio_s_out, "subject=%s\n", buf);
1770                 X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof buf);
1771                 BIO_printf(bio_s_out, "issuer=%s\n", buf);
1772                 X509_free(peer);
1773         }
1774
1775         if (SSL_get_shared_ciphers(ssl, buf, sizeof buf) != NULL)
1776                 BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf);
1777
1778         bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
1779         ciph = SSL_get_current_cipher(ssl);
1780         BIO_printf(bio_stdout, "%s%s, cipher %s %s\n",
1781                    "",
1782                    SSL_get_version(ssl),
1783                    SSL_CIPHER_get_version(ciph), SSL_CIPHER_get_name(ciph));
1784 }
1785 #endif
Note: See TracBrowser for help on using the browser.