source: src/router/httpd/httpd.c @ 10225

Last change on this file since 10225 was 10225, checked in by BrainSlayer, 5 years ago

another try to get around the crash problem (could be stack related)

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