1/* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License as 4 * published by the Free Software Foundation; either version 2 of 5 * the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 15 * MA 02111-1307 USA 16 */ 17/* milli_httpd - pretty small HTTP server 18** A combination of 19** micro_httpd - really small HTTP server 20** and 21** mini_httpd - small HTTP server 22** 23** Copyright ?1999,2000 by Jef Poskanzer <jef@acme.com>. 24** All rights reserved. 25** 26** Redistribution and use in source and binary forms, with or without 27** modification, are permitted provided that the following conditions 28** are met: 29** 1. Redistributions of source code must retain the above copyright 30** notice, this list of conditions and the following disclaimer. 31** 2. Redistributions in binary form must reproduce the above copyright 32** notice, this list of conditions and the following disclaimer in the 33** documentation and/or other materials provided with the distribution. 34** 35** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 36** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 38** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 39** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 40** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 41** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 43** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 45** SUCH DAMAGE. 46*/ 47 48#include <stdio.h> 49#include <stdlib.h> 50#include <string.h> 51#include <errno.h> 52#include <fcntl.h> 53#include <time.h> 54#include <unistd.h> 55#include <netinet/in.h> 56#include <sys/types.h> 57#include <sys/socket.h> 58#include <sys/time.h> 59//#include <sys/stat.h> 60#include <assert.h> 61#include <sys/ioctl.h> 62#include <ctype.h> 63 64typedef unsigned int __u32; // 1225 ham 65 66#include <httpd.h> 67//2008.08 magic{ 68#include <bcmnvram.h> //2008.08 magic 69#include <arpa/inet.h> //2008.08 magic 70 71#include <error.h> 72#include <sys/signal.h> 73#include <sys/wait.h> 74#include <shared.h> 75#include <shutils.h> 76 77#define ETCPHYRD 14 78#define SIOCGETCPHYRD 0x89FE 79//#include "etioctl.h" 80 81#ifdef RTCONFIG_HTTPS 82#include <syslog.h> 83#include <mssl.h> 84#include <shutils.h> 85#define SERVER_PORT_SSL 443 86#endif 87#include "bcmnvram_f.h" 88 89/* A multi-family sockaddr. */ 90typedef union { 91 struct sockaddr sa; 92 struct sockaddr_in sa_in; 93} usockaddr; 94 95#include "queue.h" 96#define MAX_CONN_ACCEPT 64 97#define MAX_CONN_TIMEOUT 60 98 99#ifdef RTCONFIG_IFTTT 100#define IFTTTUSERAGENT "asusrouter-Windows-IFTTT-1.0" 101#define GETIFTTTCGI "get_IFTTTPincode.cgi" 102#endif 103 104typedef struct conn_item { 105 TAILQ_ENTRY(conn_item) entry; 106 int fd; 107 usockaddr usa; 108} conn_item_t; 109 110typedef struct conn_list { 111 TAILQ_HEAD(, conn_item) head; 112 int count; 113} conn_list_t; 114 115/* Globals. */ 116static FILE *conn_fp; 117static char auth_userid[AUTH_MAX]; 118static char auth_passwd[AUTH_MAX]; 119static char auth_realm[AUTH_MAX]; 120char host_name[64]; 121char referer_host[64]; 122char user_agent[1024]; 123char gen_token[32]={0}; 124 125#ifdef TRANSLATE_ON_FLY 126char Accept_Language[16]; 127 128struct language_table language_tables[] = { 129 {"br", "BR"}, 130 {"pt-BR", "BR"}, 131 {"zh-cn", "CN"}, 132 {"zh-Hans-CN", "CN"}, 133 {"cs", "CZ"}, 134 {"cs-cz", "CZ"}, 135 {"da", "DA"}, 136 {"da-DK", "DA"}, 137 {"de", "DE"}, 138 {"de-at", "DE"}, 139 {"de-ch", "DE"}, 140 {"de-de", "DE"}, 141 {"de-li", "DE"}, 142 {"de-lu", "DE"}, 143 {"en", "EN"}, 144 {"en-us", "EN"}, 145 {"es", "ES"}, 146 {"es-ec", "ES"}, 147 {"es-py", "ES"}, 148 {"es-pa", "ES"}, 149 {"es-ni", "ES"}, 150 {"es-gt", "ES"}, 151 {"es-do", "ES"}, 152 {"es-es", "ES"}, 153 {"es-hn", "ES"}, 154 {"es-ve", "ES"}, 155 {"es-pr", "ES"}, 156 {"es-ar", "ES"}, 157 {"es-bo", "ES"}, 158 {"es-us", "ES"}, 159 {"es-co", "ES"}, 160 {"es-cr", "ES"}, 161 {"es-uy", "ES"}, 162 {"es-pe", "ES"}, 163 {"es-cl", "ES"}, 164 {"es-mx", "ES"}, 165 {"es-sv", "ES"}, 166 {"fi", "FI"}, 167 {"fi-FI", "FI"}, 168 {"fr", "FR"}, 169 {"fr-fr", "FR"}, 170 {"fr-BE", "FR"}, 171 {"fr-CA", "FR"}, 172 {"fr-CH", "FR"}, 173 {"fr-MC", "FR"}, 174 {"fr-LU", "FR"}, 175 {"hu-hu", "HU"}, 176 {"hu", "HU"}, 177 {"it", "IT"}, 178 {"it-it", "IT"}, 179 {"it-ch", "IT"}, 180 {"ja", "JP"}, 181 {"ja-JP", "JP"}, 182 {"ko", "KR"}, 183 {"ko-kr", "KR"}, 184 {"ms", "MS"}, 185 {"ms-MY", "MS"}, 186 {"ms-BN", "MS"}, 187 {"no", "NO"}, 188 {"nb", "NO"}, 189 {"nn", "NO"}, 190 {"nb-NO", "NO"}, 191 {"nn-NO", "NO"}, 192 {"pl-pl", "PL"}, 193 {"pl", "PL"}, 194 {"ru", "RU"}, 195 {"ru-ru", "RU"}, 196 {"ro", "RO"}, 197 {"ro-ro", "RO"}, 198 {"sv", "SV"}, 199 {"sv-FI", "SV"}, 200 {"sv-SE", "SV"}, 201 {"th", "TH"}, 202 {"th-TH", "TH"}, 203 {"th-TH-TH", "TH"}, 204 {"tr", "TR"}, 205 {"tr-TR", "TR"}, 206 {"zh", "TW"}, 207 {"zh-tw", "TW"}, 208 {"zh-Hant-TW", "TW"}, 209 {"zh-hk", "TW"}, 210 {"uk", "UK"}, 211 {NULL, NULL} 212}; 213 214#endif //TRANSLATE_ON_FLY 215 216/* Forwards. */ 217static int initialize_listen_socket(usockaddr* usa, const char *ifname); 218static int auth_check( char* dirname, char* authorization, char* url, char* cookies, int fromapp_flag); 219static int referer_check(char* referer, int fromapp_flag); 220char *generate_token(void); 221static void send_error( int status, char* title, char* extra_header, char* text ); 222//#ifdef RTCONFIG_CLOUDSYNC 223static void send_page( int status, char* title, char* extra_header, char* text , int fromapp); 224//#endif 225static void send_headers( int status, char* title, char* extra_header, char* mime_type, int fromapp); 226static void send_token_headers( int status, char* title, char* extra_header, char* mime_type, int fromapp); 227static int match( const char* pattern, const char* string ); 228static int match_one( const char* pattern, int patternlen, const char* string ); 229static void handle_request(void); 230void send_login_page(int fromapp_flag, int error_status, char* url, int lock_time); 231void __send_login_page(int fromapp_flag, int error_status, char* url, int lock_time); 232int check_user_agent(char* user_agent); 233#ifdef RTCONFIG_IFTTT 234void add_ifttt_flag(void); 235#endif 236 237/* added by Joey */ 238//2008.08 magic{ 239//int redirect = 1; 240int redirect = 0; 241int change_passwd = 0; 242int reget_passwd = 0; 243int x_Setting = 0; 244int skip_auth = 0; 245char url[128]; 246int http_port = SERVER_PORT; 247char *http_ifname = NULL; 248 249/* Added by Joey for handle one people at the same time */ 250unsigned int login_ip=0; // the logined ip 251time_t login_timestamp=0; // the timestamp of the logined ip 252time_t login_timestamp_tmp=0; // the timestamp of the current session. 253time_t last_login_timestamp=0; // the timestamp of the current session. 254unsigned int login_ip_tmp=0; // the ip of the current session. 255unsigned int login_try=0; 256unsigned int last_login_ip = 0; // the last logined ip 2008.08 magic 257/* limit login IP addr; 2012.03 Yau */ 258struct { 259 struct in_addr ip; 260 struct in_addr netmask; 261} access_ip[4]; 262unsigned int MAX_login; 263int lock_flag = 0; 264 265// 2008.08 magic { 266time_t request_timestamp = 0; 267time_t turn_off_auth_timestamp = 0; 268int temp_turn_off_auth = 0; // for QISxxx.htm pages 269 270/* Const vars */ 271const int int_1 = 1; 272 273void http_login(unsigned int ip, char *url); 274void http_login_timeout(unsigned int ip, char *cookies, int fromapp_flag); 275void http_logout(unsigned int ip, char *cookies, int fromapp_flag); 276int http_login_check(void); 277asus_token_t* search_token_in_list(char* token, asus_token_t **prev); 278 279#if 0 280static int check_if_inviteCode(const char *dirpath){ 281 return 1; 282} 283#endif 284void sethost(char *host) 285{ 286 char *cp; 287 288 if(!host) return; 289 290 memset(host_name, 0, sizeof(host_name)); 291 strncpy(host_name, host, sizeof(host_name)-1); 292 293 cp = host_name; 294 for ( cp = cp + 7; *cp && *cp != '\r' && *cp != '\n'; cp++ ); 295 *cp = '\0'; 296} 297 298char *gethost(void) 299{ 300 if(strlen(host_name)) { 301 return host_name; 302 } 303 else return(nvram_safe_get("lan_ipaddr")); 304} 305 306#include <sys/sysinfo.h> 307long uptime(void) 308{ 309 struct sysinfo info; 310 sysinfo(&info); 311 312 return info.uptime; 313} 314 315static int 316initialize_listen_socket(usockaddr* usa, const char *ifname) 317{ 318 struct ifreq ifr; 319 int fd; 320 321 memset(usa, 0, sizeof(usockaddr)); 322 usa->sa.sa_family = AF_INET; 323 usa->sa_in.sin_addr.s_addr = htonl(INADDR_ANY); 324 usa->sa_in.sin_port = htons(http_port); 325 326 fd = socket(usa->sa.sa_family, SOCK_STREAM, 0); 327 if (fd < 0) { 328 perror("socket"); 329 return -1; 330 } 331 332 if (ifname) { 333 memset(&ifr, 0, sizeof(ifr)); 334 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 335 if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) { 336 perror("ioctl"); 337 goto error; 338 } 339 usa->sa_in.sin_addr.s_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr; 340 } 341 342 fcntl(fd, F_SETFD, FD_CLOEXEC); 343 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &int_1, sizeof(int_1)) < 0) { 344 perror("setsockopt"); 345 goto error; 346 } 347 if (bind(fd, &usa->sa, sizeof(struct sockaddr_in)) < 0) { 348 perror("bind"); 349 goto error; 350 } 351 if (listen(fd, 1024) < 0) { 352 perror( "listen" ); 353 goto error; 354 } 355 356 return fd; 357 358error: 359 close(fd); 360 return -1; 361} 362 363void 364send_login_page(int fromapp_flag, int error_status, char* url, int lock_time) 365{ 366 char inviteCode[256]={0}; 367 char url_tmp[64]={0}; 368 369 if(url == NULL) 370 strncpy(url_tmp, "index.asp", sizeof(url_tmp)); 371 else 372 strncpy(url_tmp, url, sizeof(url_tmp)); 373 374 if(fromapp_flag == 0){ 375 snprintf(inviteCode, sizeof(inviteCode), "<script>top.location.href='/Main_Login.asp?error_status=%d&page=%s&lock_time=%d';</script>",error_status, url_tmp, lock_time); 376 }else{ 377 snprintf(inviteCode, sizeof(inviteCode), "\"error_status\":\"%d\"", error_status); 378 } 379 send_page( 200, "OK", (char*) 0, inviteCode, fromapp_flag); 380} 381 382void 383__send_login_page(int fromapp_flag, int error_status, char* url, int lock_time) 384{ 385 login_try++; 386 last_login_timestamp = login_timestamp_tmp; 387 388 send_login_page(fromapp_flag, error_status, url, lock_time); 389} 390 391static int 392referer_check(char* referer, int fromapp_flag) 393{ 394 395 char *auth_referer=NULL; 396 char *cp1=NULL, *cp2=NULL, *location_cp1=NULL; 397 398 if(fromapp_flag != 0) 399 return 0; 400 if(!referer){ 401 send_login_page(fromapp_flag, NOREFERER, NULL, 0); 402 return NOREFERER; 403 }else{ 404 location_cp1 = strstr(referer,"//"); 405 if(location_cp1 != (char*) 0){ 406 cp1 = &location_cp1[2]; 407 if(strstr(cp1,"/") != (char*) 0){ 408 cp2 = strtok(cp1, "/"); 409 auth_referer = cp2; 410 }else 411 auth_referer = cp1; 412 }else 413 auth_referer = referer; 414 415 } 416 if(referer_host[0] == 0){ 417 send_login_page(fromapp_flag, WEB_NOREFERER, NULL, 0); 418 return WEB_NOREFERER; 419 } 420 if(strncmp(DUT_DOMAIN_NAME, auth_referer, strlen(DUT_DOMAIN_NAME))==0){ 421 strcpy(auth_referer, nvram_safe_get("lan_ipaddr")); 422 } 423 /* form based referer info? */ 424 if(strncmp( auth_referer, referer_host, strlen(referer_host) ) == 0){ 425 //_dprintf("asus token referer_check: the right user and password\n"); 426 return 0; 427 }else{ 428 //_dprintf("asus token referer_check: the wrong user and password\n"); 429 send_login_page(fromapp_flag, REFERERFAIL, NULL, 0); 430 return REFERERFAIL; 431 } 432 send_login_page(fromapp_flag, REFERERFAIL, NULL, 0); 433 return REFERERFAIL; 434} 435 436#define HEAD_HTTP_LOGIN "HTTP login" // copy from push_log/push_log.h 437 438static int 439auth_check( char* dirname, char* authorization ,char* url, char* cookies, int fromapp_flag) 440{ 441 struct in_addr temp_ip_addr; 442 char *temp_ip_str; 443 time_t dt; 444 char asustoken[32]; 445 char *cp=NULL, *location_cp; 446 447 memset(asustoken,0,sizeof(asustoken)); 448 449 login_timestamp_tmp = uptime(); 450 dt = login_timestamp_tmp - last_login_timestamp; 451 if(last_login_timestamp != 0 && dt > 60){ 452 login_try = 0; 453 last_login_timestamp = 0; 454 lock_flag = 0; 455 } 456 if (MAX_login <= DEFAULT_LOGIN_MAX_NUM) 457 MAX_login = DEFAULT_LOGIN_MAX_NUM; 458 if(login_try >= MAX_login){ 459 lock_flag = 1; 460 temp_ip_addr.s_addr = login_ip_tmp; 461 temp_ip_str = inet_ntoa(temp_ip_addr); 462 463 if(login_try%MAX_login == 0) 464 logmessage(HEAD_HTTP_LOGIN, "Detect abnormal logins at %d times. The newest one was from %s.", login_try, temp_ip_str); 465 466//#ifdef LOGIN_LOCK 467 send_login_page(fromapp_flag, LOGINLOCK, url, dt); 468 return LOGINLOCK; 469//#endif 470 } 471 472 /* Is this directory unprotected? */ 473 if ( !strlen(auth_passwd) ){ 474 /* Yes, let the request go through. */ 475 return 0; 476 } 477 478 if(!cookies){ 479 send_login_page(fromapp_flag, NOTOKEN, url, 0); 480 return NOTOKEN; 481 }else{ 482 location_cp = strstr(cookies,"asus_token"); 483 if(location_cp != NULL){ 484 cp = &location_cp[11]; 485 cp += strspn( cp, " \t" ); 486 snprintf(asustoken, sizeof(asustoken), "%s", cp); 487 }else{ 488 send_login_page(fromapp_flag, NOTOKEN, url, 0); 489 return NOTOKEN; 490 } 491 } 492 /* form based authorization info? */ 493 494 if(search_token_in_list(asustoken, NULL) != NULL){ 495 //_dprintf("asus token auth_check: the right user and password\n"); 496#ifdef RTCONFIG_IFTTT 497 if(strncmp(url, GETIFTTTCGI, strlen(GETIFTTTCGI))==0) add_ifttt_flag(); 498#endif 499 login_try = 0; 500 last_login_timestamp = 0; 501 lock_flag = 0; 502 return 0; 503 }else{ 504 //_dprintf("asus token auth_check: the wrong user and password\n"); 505 send_login_page(fromapp_flag, AUTHFAIL, url, 0); 506 return AUTHFAIL; 507 } 508 509 send_login_page(fromapp_flag, AUTHFAIL, url, 0); 510 return AUTHFAIL; 511} 512 513char *generate_token(void){ 514 515 int a=0, b=0, c=0, d=0; 516 //char create_token[32]={0}; 517 518 memset(gen_token,0,sizeof(gen_token)); 519 srand (time(NULL)); 520 a=rand(); 521 b=rand(); 522 c=rand(); 523 d=rand(); 524 snprintf(gen_token, sizeof(gen_token),"%d%d%d%d", a, b, c, d); 525 526 return gen_token; 527} 528 529static void 530send_error( int status, char* title, char* extra_header, char* text ) 531{ 532 send_headers( status, title, extra_header, "text/html", 0); 533 (void) fprintf( conn_fp, "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n<BODY BGCOLOR=\"#cc9999\"><H4>%d %s</H4>\n", status, title, status, title ); 534 (void) fprintf( conn_fp, "%s\n", text ); 535 (void) fprintf( conn_fp, "</BODY></HTML>\n" ); 536 (void) fflush( conn_fp ); 537} 538 539//#ifdef RTCONFIG_CLOUDSYNC 540static void 541send_page( int status, char* title, char* extra_header, char* text , int fromapp){ 542 if(fromapp == 0){ 543 send_headers( status, title, extra_header, "text/html", fromapp); 544 (void) fprintf( conn_fp, "<HTML><HEAD>"); 545 (void) fprintf( conn_fp, "%s\n", text ); 546 (void) fprintf( conn_fp, "</HEAD></HTML>\n" ); 547 }else{ 548 send_headers( status, title, extra_header, "application/json;charset=UTF-8", fromapp ); 549 (void) fprintf( conn_fp, "{\n"); 550 (void) fprintf( conn_fp, "%s\n", text ); 551 (void) fprintf( conn_fp, "}\n" ); 552 } 553 (void) fflush( conn_fp ); 554} 555//#endif 556 557static void 558send_headers( int status, char* title, char* extra_header, char* mime_type, int fromapp) 559{ 560 time_t now; 561 char timebuf[100]; 562 (void) fprintf( conn_fp, "%s %d %s\r\n", PROTOCOL, status, title ); 563 (void) fprintf( conn_fp, "Server: %s\r\n", SERVER_NAME ); 564 if (fromapp != 0){ 565 (void) fprintf( conn_fp, "Cache-Control: no-store\r\n"); 566 (void) fprintf( conn_fp, "Pragma: no-cache\r\n"); 567 if(fromapp == FROM_DUTUtil){ 568 (void) fprintf( conn_fp, "AiHOMEAPILevel: %d\r\n", EXTEND_AIHOME_API_LEVEL ); 569 (void) fprintf( conn_fp, "Httpd_AiHome_Ver: %d\r\n", EXTEND_HTTPD_AIHOME_VER ); 570 (void) fprintf( conn_fp, "Model_Name: %s\r\n", get_productid() ); 571 }else if(fromapp == FROM_ASSIA){ 572 (void) fprintf( conn_fp, "ASSIA_API_Level: %d\r\n", EXTEND_ASSIA_API_LEVEL ); 573 } 574 } 575 now = time( (time_t*) 0 ); 576 (void) strftime( timebuf, sizeof(timebuf), RFC1123FMT, gmtime( &now ) ); 577 (void) fprintf( conn_fp, "Date: %s\r\n", timebuf ); 578 if ( extra_header != (char*) 0 ) 579 (void) fprintf( conn_fp, "%s\r\n", extra_header ); 580 if ( mime_type != (char*) 0 ){ 581 if(fromapp != 0) 582 (void) fprintf( conn_fp, "Content-Type: %s\r\n", "application/json;charset=UTF-8" ); 583 else 584 (void) fprintf( conn_fp, "Content-Type: %s\r\n", mime_type ); 585 } 586 587 (void) fprintf( conn_fp, "Connection: close\r\n" ); 588 (void) fprintf( conn_fp, "\r\n" ); 589} 590 591static void 592send_token_headers( int status, char* title, char* extra_header, char* mime_type, int fromapp) 593{ 594 time_t now; 595 char timebuf[100]; 596 char asus_token[32]={0}; 597 memset(asus_token,0,sizeof(asus_token)); 598 599 if(nvram_match("x_Setting", "0") && strcmp( gen_token, "") != 0){ 600 strncpy(asus_token, gen_token, sizeof(asus_token)); 601 }else{ 602 strncpy(asus_token, generate_token(), sizeof(asus_token)); 603 add_asus_token(asus_token); 604 } 605 606 (void) fprintf( conn_fp, "%s %d %s\r\n", PROTOCOL, status, title ); 607 (void) fprintf( conn_fp, "Server: %s\r\n", SERVER_NAME ); 608 if(fromapp == FROM_DUTUtil){ 609 (void) fprintf( conn_fp, "AiHOMEAPILevel: %d\r\n", EXTEND_AIHOME_API_LEVEL ); 610 (void) fprintf( conn_fp, "Httpd_AiHome_Ver: %d\r\n", EXTEND_HTTPD_AIHOME_VER ); 611 (void) fprintf( conn_fp, "Model_Name: %s\r\n", get_productid() ); 612 }else if(fromapp == FROM_ASSIA){ 613 (void) fprintf( conn_fp, "ASSIA_API_Level: %d\r\n", EXTEND_ASSIA_API_LEVEL ); 614 } 615 now = time( (time_t*) 0 ); 616 (void) strftime( timebuf, sizeof(timebuf), RFC1123FMT, gmtime( &now ) ); 617 (void) fprintf( conn_fp, "Date: %s\r\n", timebuf ); 618 if ( extra_header != (char*) 0 ) 619 (void) fprintf( conn_fp, "%s\r\n", extra_header ); 620 if ( mime_type != (char*) 0 ) 621 (void) fprintf( conn_fp, "Content-Type: %s\r\n", mime_type ); 622 623 (void) fprintf( conn_fp, "Set-Cookie: asus_token=%s; HttpOnly;\r\n",asus_token ); 624 625 (void) fprintf( conn_fp, "Connection: close\r\n" ); 626 (void) fprintf( conn_fp, "\r\n" ); 627} 628 629/* Simple shell-style filename matcher. Only does ? * and **, and multiple 630** patterns separated by |. Returns 1 or 0. 631*/ 632int 633match( const char* pattern, const char* string ) 634 { 635 const char* or; 636 637 for (;;) 638 { 639 or = strchr( pattern, '|' ); 640 if ( or == (char*) 0 ) 641 return match_one( pattern, strlen( pattern ), string ); 642 if ( match_one( pattern, or - pattern, string ) ) 643 return 1; 644 pattern = or + 1; 645 } 646 } 647 648 649static int 650match_one( const char* pattern, int patternlen, const char* string ) 651 { 652 const char* p; 653 654 for ( p = pattern; p - pattern < patternlen; ++p, ++string ) 655 { 656 if ( *p == '?' && *string != '\0' ) 657 continue; 658 if ( *p == '*' ) 659 { 660 int i, pl; 661 ++p; 662 if ( *p == '*' ) 663 { 664 /* Double-wildcard matches anything. */ 665 ++p; 666 i = strlen( string ); 667 } 668 else 669 /* Single-wildcard matches anything but slash. */ 670 i = strcspn( string, "/" ); 671 pl = patternlen - ( p - pattern ); 672 for ( ; i >= 0; --i ) 673 if ( match_one( p, pl, &(string[i]) ) ) 674 return 1; 675 return 0; 676 } 677 if ( *p != *string ) 678 return 0; 679 } 680 if ( *string == '\0' ) 681 return 1; 682 return 0; 683} 684 685int web_write(const char *buffer, int len, FILE *stream) 686{ 687 int n = len; 688 int r = 0; 689 690 while (n > 0) { 691 r = fwrite(buffer, 1, n, stream); 692 if (( r == 0) && (errno != EINTR)) return -1; 693 buffer += r; 694 n -= r; 695 } 696 return r; 697} 698 699int check_user_agent(char* user_agent){ 700 701 int fromapp = 0; 702 703 if(user_agent != NULL){ 704 char *cp1=NULL, *app_router=NULL, *app_platform=NULL, *app_framework=NULL, *app_verison=NULL; 705 cp1 = strdup(user_agent); 706 707 vstrsep(cp1, "-", &app_router, &app_platform, &app_framework, &app_verison); 708 709 if(app_router != NULL && app_framework != NULL && strcmp( app_router, "asusrouter") == 0){ 710 fromapp=FROM_ASUSROUTER; 711 if(strcmp( app_framework, "DUTUtil") == 0) 712 fromapp=FROM_DUTUtil; 713 else if(strcmp( app_framework, "ASSIA") == 0) 714 fromapp=FROM_ASSIA; 715 else if(strcmp( app_framework, "IFTTT") == 0) 716 fromapp=FROM_IFTTT; 717 } 718 if(cp1) free(cp1); 719 } 720 return fromapp; 721} 722 723#ifdef RTCONFIG_IFTTT 724void add_ifttt_flag(void){ 725 726 memset(user_agent, 0, sizeof(user_agent)); 727 sprintf(user_agent, "%s",IFTTTUSERAGENT); 728 return; 729} 730#endif 731 732#if 0 733void 734do_file(char *path, FILE *stream) 735{ 736 FILE *fp; 737 char buf[1024]; 738 int nr; 739 740 if (!(fp = fopen(path, "r"))) 741 return; 742 while ((nr = fread(buf, 1, sizeof(buf), fp)) > 0) { 743 web_write(buf, nr, stream); 744 } 745 fclose(fp); 746} 747#else 748int do_fwrite(const char *buffer, int len, FILE *stream) 749{ 750 int n = len; 751 int r = 0; 752 753 while (n > 0) { 754 r = fwrite(buffer, 1, n, stream); 755 if ((r == 0) && (errno != EINTR)) return -1; 756 buffer += r; 757 n -= r; 758 } 759 760 return r; 761} 762 763void do_file(char *path, FILE *stream) 764{ 765 FILE *fp; 766 char buf[1024]; 767 int nr; 768 769 if ((fp = fopen(path, "r")) != NULL) { 770 while ((nr = fread(buf, 1, sizeof(buf), fp)) > 0) 771 do_fwrite(buf, nr, stream); 772 fclose(fp); 773 } 774} 775 776#endif 777int is_firsttime(void); 778 779time_t detect_timestamp, detect_timestamp_old, signal_timestamp; 780char detect_timestampstr[32]; 781 782 783#define APPLYAPPSTR "applyapp.cgi" 784#define GETAPPSTR "getapp" 785#define APPGETCGI "appGet.cgi" 786 787#ifdef RTCONFIG_ROG 788#define APPLYROGSTR "api.asp" 789#endif 790 791 792static void 793handle_request(void) 794{ 795 char line[10000], *cur; 796 char *method, *path, *protocol, *authorization, *boundary, *alang, *cookies, *referer, *useragent; 797 char *cp; 798 char *file; 799 int len; 800 struct mime_handler *handler; 801 struct except_mime_handler *exhandler; 802 struct mime_referer *doreferer; 803 int mime_exception, do_referer, login_state = -1; 804 int fromapp=0; 805 int cl = 0, flags; 806 int auth_result = 1; 807 int referer_result = 1; 808#ifdef RTCONFIG_FINDASUS 809 int i, isDeviceDiscovery=0; 810 char id_local[32],prouduct_id[32]; 811#endif 812 813 /* Initialize the request variables. */ 814 authorization = boundary = cookies = referer = useragent = NULL; 815 host_name[0] = 0; 816 bzero( line, sizeof line ); 817 818 /* Parse the first line of the request. */ 819 if ( fgets( line, sizeof(line), conn_fp ) == (char*) 0 ) { 820 send_error( 400, "Bad Request", (char*) 0, "No request found." ); 821 return; 822 } 823 824 method = path = line; 825 strsep(&path, " "); 826 //while (*path == ' ') path++; 827 while (path && *path == ' ') path++; // oleg patch 828 protocol = path; 829 strsep(&protocol, " "); 830 //while (*protocol == ' ') protocol++; 831 while (protocol && *protocol == ' ') protocol++; // oleg pat 832 cp = protocol; 833 strsep(&cp, " "); 834 if ( !method || !path || !protocol ) { 835 send_error( 400, "Bad Request", (char*) 0, "Can't parse request." ); 836 return; 837 } 838 cur = protocol + strlen(protocol) + 1; 839 840#ifdef TRANSLATE_ON_FLY 841 memset(Accept_Language, 0, sizeof(Accept_Language)); 842#endif 843 844 /* Parse the rest of the request headers. */ 845 while ( fgets( cur, line + sizeof(line) - cur, conn_fp ) != (char*) 0 ) 846 { 847 //_dprintf("handle_request:cur = %s\n",cur); 848 if ( strcmp( cur, "\n" ) == 0 || strcmp( cur, "\r\n" ) == 0 ) { 849 break; 850 } 851#ifdef TRANSLATE_ON_FLY 852 else if ( strncasecmp( cur, "Accept-Language:",16) ==0) { 853 char *p; 854 struct language_table *pLang; 855 char lang_buf[256]; 856 memset(lang_buf, 0, sizeof(lang_buf)); 857 alang = &cur[16]; 858 strncpy(lang_buf, alang, sizeof(lang_buf)-1); 859 p = lang_buf; 860 while (p != NULL) 861 { 862 p = strtok (p, "\r\n ,;"); 863 if (p == NULL) break; 864 //2008.11 magic{ 865 int i, len=strlen(p); 866 867 for (i=0;i<len;++i) 868 if (isupper(p[i])) { 869 p[i]=tolower(p[i]); 870 } 871 872 //2008.11 magic} 873 for (pLang = language_tables; pLang->Lang != NULL; ++pLang) 874 { 875 if (strcasecmp(p, pLang->Lang)==0) 876 { 877 char dictname[32]; 878 879 if (!check_lang_support(pLang->Target_Lang)) 880 continue; 881 snprintf(dictname,sizeof(dictname),"%s.dict", pLang->Target_Lang); 882 if(!check_if_file_exist(dictname)) 883 { 884 //_dprintf("language(%s) is not supported!!\n", pLang->Target_Lang); 885 continue; 886 } 887 snprintf(Accept_Language,sizeof(Accept_Language),"%s",pLang->Target_Lang); 888 if (is_firsttime() && nvram_match("ui_Setting", "0")) { 889 _dprintf("%s", Accept_Language); 890 nvram_set("ui_Setting", "1"); 891 nvram_set("preferred_lang", Accept_Language); 892 893 #ifdef RTCONFIG_DSL_TCLINUX 894 if(!strcmp(Accept_Language, "CZ") || !strcmp(Accept_Language, "DE")) { 895 int do_restart = 0; 896 if( nvram_match("dslx_annex", "4") 897 && nvram_match("dsltmp_adslsyncsts", "down") 898 ){ 899 _dprintf("DSL: auto switch to annex b/j\n"); 900 nvram_set("dslx_annex", "6"); 901 do_restart = 1; 902 } 903 if(!strcmp(Accept_Language, "DE") 904 && nvram_match("dslx_vdsl_profile", "0")) { 905 _dprintf("DSL: auto switch to 17a multi mode\n"); 906 nvram_set("dslx_vdsl_profile", "1"); 907 do_restart = 1; 908 } 909 if (do_restart) 910 notify_rc("restart_dsl_setting"); 911 } 912 #endif 913 } 914 915 break; 916 } 917 } 918 919 if (Accept_Language[0] != 0) { 920 break; 921 } 922 p+=strlen(p)+1; 923 } 924 925 if (Accept_Language[0] == 0) { 926 // If all language setting of user's browser are not supported, use English. 927 //printf ("Auto detect language failed. Use English.\n"); 928 strcpy (Accept_Language, "EN"); 929 930 // 2008.10 magic { 931 if (is_firsttime()) 932 nvram_set("preferred_lang", "EN"); 933 // 2008.10 magic } 934 } 935 } 936#endif 937 else if ( strncasecmp( cur, "Authorization:", 14 ) == 0 ) 938 { 939 cp = &cur[14]; 940 cp += strspn( cp, " \t" ); 941 authorization = cp; 942 cur = cp + strlen(cp) + 1; 943 } 944 else if ( strncasecmp( cur, "User-Agent:", 11 ) == 0 ) 945 { 946 cp = &cur[11]; 947 cp += strspn( cp, " \t" ); 948 useragent = cp; 949 cur = cp + strlen(cp) + 1; 950 } 951 else if ( strncasecmp( cur, "Cookie:", 7 ) == 0 ) 952 { 953 cp = &cur[7]; 954 cp += strspn( cp, " \t" ); 955 cookies = cp; 956 cur = cp + strlen(cp) + 1; 957 } 958 else if ( strncasecmp( cur, "Referer:", 8 ) == 0 ) 959 { 960 cp = &cur[8]; 961 cp += strspn( cp, " \t" ); 962 referer = cp; 963 cur = cp + strlen(cp) + 1; 964 //_dprintf("httpd referer = %s\n", referer); 965 } 966 else if ( strncasecmp( cur, "Host:", 5 ) == 0 ) 967 { 968 cp = &cur[5]; 969 cp += strspn( cp, " \t" ); 970 sethost(cp); 971 cur = cp + strlen(cp) + 1; 972#ifdef RTCONFIG_FINDASUS 973 sprintf(prouduct_id, "%s",get_productid()); 974 for(i = 0 ; i < strlen(prouduct_id) ; i++ ){ 975 prouduct_id[i] = tolower(prouduct_id[i]) ; 976 } 977 sprintf(id_local, "%s.local",prouduct_id); 978 if(!strncmp(cp, "findasus", 8) || !strncmp(cp, id_local,strlen(id_local))) 979 isDeviceDiscovery = 1; 980 else 981 isDeviceDiscovery = 0; 982#endif 983 } 984 else if (strncasecmp( cur, "Content-Length:", 15 ) == 0) { 985 cp = &cur[15]; 986 cp += strspn( cp, " \t" ); 987 cl = strtoul( cp, NULL, 0 ); 988 } 989 else if ((cp = strstr( cur, "boundary=" ))) { 990 boundary = &cp[9]; 991 for ( cp = cp + 9; *cp && *cp != '\r' && *cp != '\n'; cp++ ); 992 *cp = '\0'; 993 cur = ++cp; 994 } 995 } 996 997 if ( strcasecmp( method, "get" ) != 0 && strcasecmp(method, "post") != 0 && strcasecmp(method, "head") != 0 ) { 998 send_error( 501, "Not Implemented", (char*) 0, "That method is not implemented." ); 999 return; 1000 } 1001 1002 if ( path[0] != '/' ) { 1003 send_error( 400, "Bad Request", (char*) 0, "Bad filename." ); 1004 return; 1005 } 1006 file = &(path[1]); 1007 len = strlen( file ); 1008 if ( file[0] == '/' || strcmp( file, ".." ) == 0 || strncmp( file, "../", 3 ) == 0 || strstr( file, "/../" ) != (char*) 0 || strcmp( &(file[len-3]), "/.." ) == 0 ) { 1009 send_error( 400, "Bad Request", (char*) 0, "Illegal filename." ); 1010 return; 1011 } 1012 1013//2008.08 magic{ 1014 if (file[0] == '\0' || file[len-1] == '/'){ 1015 if (is_firsttime() 1016#ifdef RTCONFIG_FINDASUS 1017 && !isDeviceDiscovery 1018#endif 1019 ) 1020 //file = "QIS_wizard.htm"; 1021 file = "QIS_default.cgi"; 1022#ifdef RTCONFIG_FINDASUS 1023 else if(isDeviceDiscovery == 1) 1024 file = "find_device.asp"; 1025#endif 1026 else 1027 file = "index.asp"; 1028 } 1029 1030// 2007.11 James. { 1031 char *query; 1032 int file_len; 1033 1034 memset(url, 0, 128); 1035 if ((query = index(file, '?')) != NULL) { 1036 file_len = strlen(file)-strlen(query); 1037 1038 if(file_len > sizeof(url)) 1039 file_len = sizeof(url); 1040 1041 strncpy(url, file, file_len); 1042 } 1043 else 1044 { 1045 strncpy(url, file, sizeof(url)-1); 1046 } 1047// 2007.11 James. } 1048 1049 if(strncmp(url, APPLYAPPSTR, strlen(APPLYAPPSTR))==0 1050#ifdef RTCONFIG_ROG 1051 || strncmp(url, APPLYROGSTR, strlen(APPLYROGSTR))==0 1052#endif 1053 ) 1054 fromapp=1; 1055 else if(strncmp(url, GETAPPSTR, strlen(GETAPPSTR))==0) { 1056 fromapp=1; 1057 strcpy(url, url+strlen(GETAPPSTR)); 1058 file += strlen(GETAPPSTR); 1059 } 1060 1061 memset(user_agent, 0, sizeof(user_agent)); 1062 if(useragent != NULL) 1063 strncpy(user_agent, useragent, sizeof(user_agent)-1); 1064 else 1065 strcpy(user_agent, ""); 1066 1067 fromapp = check_user_agent(useragent); 1068 1069 //printf("httpd url: %s file: %s\n", url, file); 1070 //_dprintf("httpd url: %s file: %s\n", url, file); 1071 mime_exception = 0; 1072 do_referer = 0; 1073 1074 if(!fromapp) { 1075 if(lock_flag == 1){ 1076 time_t dt_t; 1077 login_timestamp_tmp = uptime(); 1078 dt_t = login_timestamp_tmp - last_login_timestamp; 1079 if(last_login_timestamp != 0 && dt_t > 60){ 1080 login_try = 0; 1081 last_login_timestamp = 0; 1082 lock_flag = 0; 1083 }else{ 1084 if(strncmp(file, "Main_Login.asp?error_status=7", 29)==0 || strstr(url, ".png")){ 1085 }else{ 1086 send_login_page(fromapp, LOGINLOCK, url, dt_t); 1087 return; 1088 } 1089 } 1090 } 1091 http_login_timeout(login_ip_tmp, cookies, fromapp); // 2008.07 James. 1092 login_state = http_login_check(); 1093 // for each page, mime_exception is defined to do exception handler 1094 1095 mime_exception = 0; 1096 1097 // check exception first 1098 for (exhandler = &except_mime_handlers[0]; exhandler->pattern; exhandler++) { 1099 if(match(exhandler->pattern, url)) 1100 { 1101 mime_exception = exhandler->flag; 1102 break; 1103 } 1104 } 1105 1106 do_referer = 0; 1107 1108 // check doreferer first 1109 for (doreferer = &mime_referers[0]; doreferer->pattern; doreferer++) { 1110 if(match(doreferer->pattern, url)) 1111 { 1112 do_referer = doreferer->flag; 1113 break; 1114 } 1115 } 1116 1117 x_Setting = nvram_get_int("x_Setting"); 1118 } 1119 else { // Jerry5 fix AiCloud login issue. 20120815 1120 x_Setting = nvram_get_int("x_Setting"); 1121 //skip_auth = 0; 1122 } 1123 for (handler = &mime_handlers[0]; handler->pattern; handler++) { 1124 if (match(handler->pattern, url)) 1125 { 1126 nvram_set("httpd_handle_request", url); 1127 nvram_set_int("httpd_handle_request_fromapp", fromapp); 1128 if(login_state==3 && !fromapp) { // few pages can be shown even someone else login 1129 if(!(mime_exception&MIME_EXCEPTION_MAINPAGE || strncmp(file, "Main_Login.asp?error_status=9", 29)==0 || ((!handler->auth) && strncmp(file, "Main_Login.asp", 14) != 0))) { 1130 if(strcasecmp(method, "post") == 0){ 1131 if (handler->input) { 1132 handler->input(file, conn_fp, cl, boundary); 1133 } 1134 } 1135 send_login_page(fromapp, NOLOGIN, NULL, 0); 1136 return; 1137 } 1138 } 1139 if (handler->auth) { 1140 if ((mime_exception&MIME_EXCEPTION_NOAUTH_FIRST)&&!x_Setting) { 1141 //skip_auth=1; 1142 } 1143 else if((mime_exception&MIME_EXCEPTION_NOAUTH_ALL)) { 1144 } 1145 else { 1146 if(do_referer&CHECK_REFERER){ 1147 referer_result = referer_check(referer, fromapp); 1148 if(referer_result != 0){ 1149 if(strcasecmp(method, "post") == 0){ 1150 if (handler->input) { 1151 handler->input(file, conn_fp, cl, boundary); 1152 } 1153 send_login_page(fromapp, referer_result, NULL, 0); 1154 } 1155 //if(!fromapp) http_logout(login_ip_tmp, cookies); 1156 return; 1157 } 1158 } 1159 handler->auth(auth_userid, auth_passwd, auth_realm); 1160 auth_result = auth_check(auth_realm, authorization, url, cookies, fromapp); 1161 if (auth_result != 0) 1162 { 1163 if(strcasecmp(method, "post") == 0){ 1164 if (handler->input) { 1165 handler->input(file, conn_fp, cl, boundary); 1166 } 1167 send_login_page(fromapp, auth_result, NULL, 0); 1168 } 1169 //if(!fromapp) http_logout(login_ip_tmp, cookies); 1170 return; 1171 } 1172 } 1173 1174 if(!fromapp) { 1175 if ( !strstr(url, "QIS_") 1176 && !strstr(url, ".js") 1177 && !strstr(url, ".css") 1178 && !strstr(url, ".gif") 1179 && !strstr(url, ".png")) 1180 http_login(login_ip_tmp, url); 1181 } 1182 }else{ 1183 } 1184 1185 if(!strcmp(file, "Logout.asp")){ 1186 http_logout(login_ip_tmp, cookies, fromapp); 1187 send_login_page(fromapp, ISLOGOUT, NULL, 0); 1188 return; 1189 } 1190 if (strcasecmp(method, "post") == 0 && !handler->input) { 1191 send_error(501, "Not Implemented", NULL, "That method is not implemented."); 1192 return; 1193 } 1194// 2007.11 James. for QISxxx.htm pages } 1195 if (handler->input) { 1196 handler->input(file, conn_fp, cl, boundary); 1197#if defined(linux) 1198 if ((flags = fcntl(fileno(conn_fp), F_GETFL)) != -1 && 1199 fcntl(fileno(conn_fp), F_SETFL, flags | O_NONBLOCK) != -1) { 1200 /* Read up to two more characters */ 1201 if (fgetc(conn_fp) != EOF) 1202 (void)fgetc(conn_fp); 1203 1204 fcntl(fileno(conn_fp), F_SETFL, flags); 1205 } 1206#elif defined(vxworks) 1207 flags = 1; 1208 if (ioctl(fileno(conn_fp), FIONBIO, (int) &flags) != -1) { 1209 /* Read up to two more characters */ 1210 if (fgetc(conn_fp) != EOF) 1211 (void)fgetc(conn_fp); 1212 flags = 0; 1213 ioctl(fileno(conn_fp), FIONBIO, (int) &flags); 1214 } 1215#endif 1216 } 1217 if(!strstr(file, ".cgi") && !strstr(file, "syslog.txt") && !(strstr(file,"uploadIconFile.tar")) && !(strstr(file,"networkmap.tar")) && !(strstr(file,".CFG")) && !(strstr(file,".log")) && !check_if_file_exist(file) 1218#ifdef RTCONFIG_USB_MODEM 1219 && !strstr(file, "modemlog.txt") 1220#endif 1221#ifdef RTCONFIG_DSL_TCLINUX 1222 && !strstr(file, "TCC.log") 1223#endif 1224 ){ 1225 send_error( 404, "Not Found", (char*) 0, "File not found." ); 1226 return; 1227 } 1228 if(strncmp(url, "QIS_default.cgi", strlen(url))==0 && nvram_match("x_Setting", "0")){ 1229 memset(referer_host, 0, sizeof(referer_host)); 1230 if(strncmp(DUT_DOMAIN_NAME, host_name, strlen(DUT_DOMAIN_NAME))==0){ 1231 strcpy(referer_host, nvram_safe_get("lan_ipaddr")); 1232 }else 1233 snprintf(referer_host,sizeof(host_name),"%s",host_name); 1234 1235 send_token_headers( 200, "Ok", handler->extra_header, handler->mime_type, fromapp); 1236 1237 }else if(strncmp(url, "login.cgi", strlen(url))!=0){ 1238 send_headers( 200, "Ok", handler->extra_header, handler->mime_type, fromapp); 1239 } 1240 1241 if (strcasecmp(method, "head") != 0 && handler->output) { 1242 handler->output(file, conn_fp); 1243 } 1244 1245 break; 1246 } 1247 } 1248 1249 if (!handler->pattern){ 1250 if(strlen(file) > 50 && !(strstr(file, "findasus"))){ 1251 char inviteCode[256]; 1252 snprintf(inviteCode, sizeof(inviteCode), "<script>location.href='/cloud_sync.asp?flag=%s';</script>", file); 1253 send_page( 200, "OK", (char*) 0, inviteCode, 0); 1254 } 1255 else 1256 send_error( 404, "Not Found", (char*) 0, "File not found." ); 1257 } 1258 nvram_unset("httpd_handle_request"); 1259 nvram_unset("httpd_handle_request_fromapp"); 1260} 1261 1262asus_token_t* search_token_in_list(char* token, asus_token_t **prev) 1263{ 1264 asus_token_t *ptr = head; 1265 asus_token_t *tmp = NULL; 1266 int found = 0; 1267 char *cp=NULL; 1268 1269 while(ptr != NULL) 1270 { 1271 if(!strncmp(token, ptr->token, 32)) 1272 { 1273 found = 1; 1274 break; 1275 } 1276 else if(strncmp(token, "cgi_logout", 10) == 0){ 1277 cp = strtok(ptr->useragent, "-"); 1278 1279 if(strcmp( cp, "asusrouter") != 0){ 1280 found = 1; 1281 break; 1282 } 1283 } 1284 else 1285 { 1286 tmp = ptr; 1287 ptr = ptr->next; 1288 } 1289 } 1290 if(found == 1) 1291 { 1292 if(prev) 1293 *prev = tmp; 1294 return ptr; 1295 } 1296 else 1297 { 1298 return NULL; 1299 } 1300} 1301 1302int delete_logout_from_list(char *cookies) 1303{ 1304 asus_token_t *prev = NULL; 1305 asus_token_t *del = NULL; 1306 1307 char asustoken[32]; 1308 char *cp=NULL, *location_cp; 1309 1310 memset(asustoken,0,sizeof(asustoken)); 1311 1312 //int fromapp_flag=0; 1313 1314 if(!cookies || nvram_match("x_Setting", "0")){ 1315 //send_login_page(fromapp_flag, NOTOKEN); 1316 return 0; 1317 1318 }else{ 1319 if(strncmp(cookies, "cgi_logout", 10) == 0){ 1320 strncpy(asustoken, cookies, sizeof(asustoken)); 1321 }else{ 1322 location_cp = strstr(cookies,"asus_token"); 1323 if(location_cp != NULL){ 1324 cp = &location_cp[11]; 1325 cp += strspn( cp, " \t" ); 1326 snprintf(asustoken, sizeof(asustoken), "%s", cp); 1327 }else{ 1328 //send_login_page(fromapp_flag, NOTOKEN); 1329 return 0; 1330 } 1331 } 1332 } 1333 1334 del = search_token_in_list(asustoken,&prev); 1335 if(del == NULL) 1336 { 1337 return -1; 1338 } 1339 else 1340 { 1341 if(prev != NULL){ 1342 prev->next = del->next; 1343 } 1344 if(del == curr) 1345 { 1346 curr = prev; 1347 } 1348 if(del == head) 1349 { 1350 head = del->next; 1351 } 1352 } 1353 1354 free(del); 1355 del = NULL; 1356 1357 return 0; 1358} 1359 1360//2008 magic{ 1361void http_login_cache(usockaddr *u) { 1362 struct in_addr temp_ip_addr; 1363 char *temp_ip_str; 1364 1365 login_ip_tmp = (unsigned int)(u->sa_in.sin_addr.s_addr); 1366 temp_ip_addr.s_addr = login_ip_tmp; 1367 temp_ip_str = inet_ntoa(temp_ip_addr); 1368} 1369 1370void http_get_access_ip(void) 1371{ 1372 struct in_addr addr4; 1373 char *nv, *nvp, *b, *ip; 1374 int i, size; 1375 1376 memset(&access_ip, 0, sizeof(access_ip)); 1377 1378 nv = nvp = strdup(nvram_safe_get("http_clientlist")); 1379 i = 0; 1380 while (nv && (b = strsep(&nvp, "<")) != NULL && i < ARRAY_SIZE(access_ip)) { 1381 ip = strsep(&b, "/"); 1382 size = (b && *b) ? strtoul(b, NULL, 10) : 32; 1383 if (inet_pton(AF_INET, ip, &addr4) > 0) { 1384 if (size > 32) 1385 size = 32; 1386 access_ip[i].ip.s_addr = addr4.s_addr; 1387 access_ip[i].netmask.s_addr = htonl(0xffffffffUL << (32 - size)); 1388 i++; 1389 } 1390 } 1391 free(nv); 1392} 1393 1394void http_login(unsigned int ip, char *url) { 1395 if(strncmp(url, "Main_Login.asp", strlen(url))==0) 1396 return; 1397 struct in_addr login_ip_addr; 1398 char *login_ip_str; 1399 char login_ipstr[32], login_timestampstr[32]; 1400 1401 if ((http_port != SERVER_PORT 1402/* && http_port != nvram_get_int("http_lanport")*/ 1403#ifdef RTCONFIG_HTTPS 1404 && http_port != SERVER_PORT_SSL 1405 && http_port != nvram_get_int("https_lanport") 1406#endif 1407 ) || ip == 0x100007f) 1408 return; 1409 1410 login_ip = ip; 1411 last_login_ip = 0; 1412 1413 login_ip_addr.s_addr = login_ip; 1414 login_ip_str = inet_ntoa(login_ip_addr); 1415 nvram_set("login_ip_str", login_ip_str); 1416 1417 login_timestamp = uptime(); 1418 1419 memset(login_ipstr, 0, 32); 1420 sprintf(login_ipstr, "%u", login_ip); 1421 nvram_set("login_ip", login_ipstr); 1422 1423 memset(login_timestampstr, 0, 32); 1424 sprintf(login_timestampstr, "%lu", login_timestamp); 1425 nvram_set("login_timestamp", login_timestampstr); 1426} 1427 1428int http_client_ip_check(void) 1429{ 1430 int i = 0; 1431 1432 if (nvram_match("http_client", "1")) { 1433 for (i = 0; i < ARRAY_SIZE(access_ip); i++) { 1434 if (access_ip[i].ip.s_addr == INADDR_ANY) 1435 continue; 1436 if ((login_ip_tmp & access_ip[i].netmask.s_addr) == 1437 (access_ip[i].ip.s_addr & access_ip[i].netmask.s_addr)) 1438 return 1; 1439 } 1440 return 0; 1441 } 1442 1443 return 1; 1444} 1445 1446// 0: can not login, 1: can login, 2: loginer, 3: not loginer 1447int http_login_check(void) 1448{ 1449 if ((http_port != SERVER_PORT 1450/* && http_port != nvram_get_int("http_lanport")*/ 1451#ifdef RTCONFIG_HTTPS 1452 && http_port != SERVER_PORT_SSL 1453 && http_port != nvram_get_int("https_lanport") 1454#endif 1455 ) || login_ip_tmp == 0x100007f) 1456 //return 1; 1457 return 0; // 2008.01 James. 1458 1459 if (login_ip == 0) 1460 return 1; 1461 else if (login_ip == login_ip_tmp) 1462 return 2; 1463 1464 return 3; 1465} 1466 1467void http_login_timeout(unsigned int ip, char *cookies, int fromapp_flag) 1468{ 1469 time_t now, login_ts; 1470 1471// time(&now); 1472 now = uptime(); 1473 login_ts = atol(nvram_safe_get("login_timestamp")); 1474 1475// 2007.10 James. for really logout. { 1476 //if (login_ip!=ip && (unsigned long)(now-login_timestamp) > 60) //one minitues 1477 if ((login_ip != 0 && login_ip != ip) && ((unsigned long)(now-login_ts) > 60)) //one minitues 1478// 2007.10 James } 1479 { 1480 http_logout(login_ip, cookies, fromapp_flag); 1481 } 1482} 1483 1484void http_logout(unsigned int ip, char *cookies, int fromapp_flag) 1485{ 1486 if ((ip == login_ip || ip == 0 ) && fromapp_flag == 0) { 1487 last_login_ip = login_ip; 1488 login_ip = 0; 1489 login_timestamp = 0; 1490 1491 nvram_set("login_ip", ""); 1492 nvram_set("login_timestamp", ""); 1493 memset(referer_host, 0, sizeof(referer_host)); 1494 delete_logout_from_list(cookies); 1495// 2008.03 James. { 1496 if (change_passwd == 1) { 1497 change_passwd = 0; 1498 reget_passwd = 1; 1499 } 1500// 2008.03 James. } 1501 }else if(fromapp_flag != 0){ 1502 delete_logout_from_list(cookies); 1503} 1504} 1505//2008 magic} 1506// 1507 1508int is_auth(void) 1509{ 1510 if (http_port==SERVER_PORT || 1511/* http_port==nvram_get_int("http_lanport") ||*/ 1512#ifdef RTCONFIG_HTTPS 1513 http_port==SERVER_PORT_SSL || 1514 http_port==nvram_get_int("https_lanport") || 1515#endif 1516 strcmp(nvram_get_x("PrinterStatus", "usb_webhttpcheck_x"), "1")==0) return 1; 1517 else return 0; 1518} 1519 1520int is_firsttime(void) 1521{ 1522 if (strcmp(nvram_get("x_Setting"), "1")==0) 1523 return 0; 1524 else 1525 return 1; 1526} 1527 1528/* str_replace 1529* @param {char*} source 1530* @param {char*} find 1531* @param {char*} rep 1532* */ 1533char *config_model_name(char *source, char *find, char *rep){ 1534 int find_L=strlen(find); 1535 int rep_L=strlen(rep); 1536 int length=strlen(source)+1; 1537 int gap=0; 1538 1539 char *result = (char*)malloc(sizeof(char) * length); 1540 strcpy(result, source); 1541 1542 char *former=source; 1543 char *location= strstr(former, find); 1544 1545 /* stop searching when there is no finding string */ 1546 while(location!=NULL){ 1547 gap+=(location - former); 1548 result[gap]='\0'; 1549 1550 length+=(rep_L-find_L); 1551 result = (char*)realloc(result, length * sizeof(char)); 1552 strcat(result, rep); 1553 gap+=rep_L; 1554 1555 former=location+find_L; 1556 strcat(result, former); 1557 1558 location= strstr(former, find); 1559 } 1560 return result; 1561} 1562 1563#ifdef TRANSLATE_ON_FLY 1564/* Whether a language support should be enabled or not. 1565 * @lang: 1566 * @return: 1567 * 0: lang should not be supported. 1568 * <0: invalid parameter. 1569 * >0: lang can be supported. 1570 */ 1571int check_lang_support(char *lang) 1572{ 1573 int r = 1; 1574 1575 if (!lang) 1576 return -1; 1577 1578#if defined(RTCONFIG_TCODE) 1579 if (!find_word(nvram_safe_get("rc_support"), "tcode") || !nvram_get("territory_code")) 1580 return 1; 1581 if (!strncmp(nvram_get("territory_code"), "UK", 2) || 1582 !strncmp(nvram_get("territory_code"), "NE", 2)) { 1583 if (!strcmp(lang, "DA") || !strcmp(lang, "EN") || 1584 !strcmp(lang, "FI") || !strcmp(lang, "NO") || 1585 !strcmp(lang, "SV")) { 1586 r = 1; 1587 } else { 1588 r = 0; 1589 } 1590 } else { 1591 if (!strcmp(lang, "DA") || !strcmp(lang, "FI") || 1592 !strcmp(lang, "NO") || !strcmp(lang, "SV")) { 1593 r = 0; 1594 } else { 1595 r = 1; 1596 } 1597 } 1598#endif 1599 1600 return r; 1601} 1602 1603#ifdef RTCONFIG_AUTODICT 1604int 1605load_dictionary (char *lang, pkw_t pkw) 1606{ 1607 char dfn[16]; 1608 char dummy_buf[16]; 1609 int dict_item_idx; 1610 char* tmp_ptr; 1611 int dict_item; // number of dict item, now get from text file 1612 char *q; 1613 FILE *dfp = NULL; 1614 int remain_dict; 1615 int dict_size = 0; 1616// struct timeval tv1, tv2; 1617 const char *eng_dict = "EN.dict"; 1618#ifndef RELOAD_DICT 1619 static char loaded_dict[12] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'}; 1620#endif // RELOAD_DICT 1621#ifdef RTCONFIG_DYN_DICT_NAME 1622 char *dyn_dict_buf; 1623 char *dyn_dict_buf_new; 1624#endif 1625 1626//printf ("lang=%s\n", lang); 1627 1628// gettimeofday (&tv1, NULL); 1629 if (lang == NULL || (lang != NULL && strlen (lang) == 0)) { 1630 // if "lang" is invalid, use English as default 1631 snprintf (dfn, sizeof (dfn), eng_dict); 1632 } else { 1633 snprintf (dfn, sizeof (dfn), "%s.dict", lang); 1634 } 1635 1636#ifndef RELOAD_DICT 1637// printf ("loaded_dict (%s) v.s. dfn (%s)\n", loaded_dict, dfn); 1638 if (strcmp (dfn, loaded_dict) == 0) { 1639 return 1; 1640 } 1641 release_dictionary (pkw); 1642#endif // RELOAD_DICT 1643 1644 do { 1645// printf("Open (%s) dictionary file.\n", dfn); 1646// 1647// Now DICT files all use UTF-8, it is no longer a text file 1648// it need to use open as binary 1649// 1650 dfp = fopen (dfn, "rb"); 1651 if (dfp != NULL) { 1652#ifndef RELOAD_DICT 1653 snprintf (loaded_dict, sizeof (loaded_dict), "%s", dfn); 1654#endif // RELOAD_DICT 1655 break; 1656 } 1657 1658// printf ("Open (%s) failure. errno %d (%s)\n", dfn, errno, strerror (errno)); 1659 if (dfp == NULL && strcmp (dfn, eng_dict) == 0) { 1660 return 0; 1661 } else { 1662 // If we can't open specified language file, use English as default 1663 snprintf (dfn, sizeof (dfn), eng_dict); 1664 } 1665 } while (1); 1666 1667 memset (pkw, 0, sizeof (kw_t)); 1668 fseek (dfp, 0L, SEEK_END); 1669 dict_size = ftell (dfp) + 128; 1670 // skip BOM header length 1671 dict_size -= 3; 1672 printf ("dict_size %d\n", dict_size); 1673 1674#ifdef RTCONFIG_DYN_DICT_NAME 1675 dyn_dict_buf = (char *) malloc(dict_size); 1676 fseek (dfp, 0L, SEEK_SET); 1677 // skip BOM 1678 fread (dummy_buf, 1, 3, dfp); 1679 // read to dict string buffer 1680 memset(dyn_dict_buf, 0, dict_size); 1681 fread (dyn_dict_buf, 1, dict_size, dfp); 1682 dyn_dict_buf_new = config_model_name(dyn_dict_buf, "ZVDYNMODELVZ", nvram_safe_get("productid")); 1683 1684 free(dyn_dict_buf); 1685 1686 dict_size = sizeof(char) * strlen(dyn_dict_buf_new); 1687 pkw->buf = (unsigned char *) (q = malloc (dict_size)); 1688 strcpy(pkw->buf, dyn_dict_buf_new); 1689 free(dyn_dict_buf_new); 1690#else 1691 pkw->buf = (unsigned char *) (q = malloc (dict_size)); 1692 1693 fseek (dfp, 0L, SEEK_SET); 1694 // skip BOM 1695 fread (dummy_buf, 1, 3, dfp); 1696 // read to dict string buffer 1697 memset(pkw->buf, 0, dict_size); 1698 fread (pkw->buf, 1, dict_size, dfp); 1699#endif 1700 // calc how many dict item , dict_item 1701 remain_dict = dict_size; 1702 tmp_ptr = (char *) pkw->buf; 1703 dict_item = 0; 1704 while (remain_dict>0) { 1705 if (*tmp_ptr == 0x0a) { 1706 dict_item++; 1707 tmp_ptr++; 1708 remain_dict--; 1709 } 1710 else if (*tmp_ptr == 0) { 1711 break; 1712 } 1713 else { 1714 tmp_ptr++; 1715 remain_dict--; 1716 } 1717 } 1718 // allocate memory according dict_item 1719 pkw->idx = malloc (dict_item * sizeof(unsigned char*)); 1720 1721 printf ("dict_item %d\n", dict_item); 1722 1723 // get all string start and put to pkw->idx 1724 remain_dict = dict_size; 1725 for (dict_item_idx = 0; dict_item_idx < dict_item; dict_item_idx++) { 1726 pkw->idx[dict_item_idx] = (unsigned char *) q; 1727 while (remain_dict>0) { 1728 if (*q == 0x0a) { 1729 *q=0; 1730 q++; 1731 remain_dict--; 1732 break; 1733 } 1734 if (*q == 0) { 1735 break; 1736 } 1737 q++; 1738 remain_dict--; 1739 } 1740 } 1741 1742 pkw->len = dict_item; 1743 1744 fclose (dfp); 1745 1746 return 1; 1747} 1748 1749 1750void 1751release_dictionary (pkw_t pkw) 1752{ 1753 if (pkw == NULL) { 1754 return; 1755 } 1756 1757 //pkw->len = pkw->tlen = 0; 1758 pkw->len = 0; 1759 1760 if (pkw->idx != NULL) { 1761 free (pkw->idx); 1762 pkw->idx = NULL; 1763 } 1764 1765 if (pkw->buf != NULL) { 1766 free (pkw->buf); 1767 pkw->buf = NULL; 1768 } 1769} 1770 1771char* 1772search_desc (pkw_t pkw, char *name) 1773{ 1774 int i; 1775 char *ret = NULL; 1776 int dict_idx; 1777 char name_buf[128]; 1778 1779/* 1780 printf("search_desc:"); 1781 printf(name); 1782 printf("\n"); 1783*/ 1784 1785 if (pkw == NULL || (pkw != NULL && pkw->len <= 0)) { 1786 return NULL; 1787 } 1788 1789 // remove equal 1790 memset(name_buf,0,sizeof(name_buf)); 1791 // minus one for reserver one char for string zero char 1792 for (i = 0; i<sizeof(name_buf)-1; i++) { 1793 if (*name == 0 || *name == '=') { 1794 break; 1795 } 1796 name_buf[i]=*name++; 1797 } 1798 1799/* 1800 for (i = 0; i < pkw->len; ++i) { 1801 char *p; 1802 p = pkw->idx[i]; 1803 if (strncmp (name, p, strlen (name)) == 0) { 1804 ret = p + strlen (name); 1805 break; 1806 } 1807 } 1808*/ 1809 1810/* 1811 printf("search_desc:"); 1812 printf(name_buf); 1813 printf("\n"); 1814*/ 1815 1816 dict_idx = atoi(name_buf); 1817// printf("%d , %d\n",dict_idx,pkw->len); 1818 if (dict_idx < pkw->len) { 1819 ret = (char *) pkw->idx[dict_idx]; 1820 } 1821 else { 1822 ret = (char *) pkw->idx[0]; 1823 } 1824 1825/* 1826 printf("ret:"); 1827 printf(ret); 1828 printf("\n"); 1829*/ 1830 1831 return ret; 1832} 1833#else 1834int 1835load_dictionary (char *lang, pkw_t pkw) 1836{ 1837 char dfn[16]; 1838 char *p, *q; 1839 FILE *dfp = NULL; 1840 int dict_size = 0; 1841// struct timeval tv1, tv2; 1842 const char *eng_dict = "EN.dict"; 1843#ifndef RELOAD_DICT 1844 static char loaded_dict[12] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'}; 1845#endif // RELOAD_DICT 1846 1847// gettimeofday (&tv1, NULL); 1848 if (lang == NULL || (lang != NULL && strlen (lang) == 0)) { 1849 // if "lang" is invalid, use English as default 1850 snprintf (dfn, sizeof (dfn), eng_dict); 1851 } else { 1852 snprintf (dfn, sizeof (dfn), "%s.dict", lang); 1853 } 1854 1855#ifndef RELOAD_DICT 1856// printf ("loaded_dict (%s) v.s. dfn (%s)\n", loaded_dict, dfn); 1857 if (strcmp (dfn, loaded_dict) == 0) { 1858 return 1; 1859 } 1860 release_dictionary (pkw); 1861#endif // RELOAD_DICT 1862 1863 do { 1864// printf("Open (%s) dictionary file.\n", dfn); 1865 dfp = fopen (dfn, "r"); 1866 if (dfp != NULL) { 1867#ifndef RELOAD_DICT 1868 snprintf (loaded_dict, sizeof (loaded_dict), "%s", dfn); 1869#endif // RELOAD_DICT 1870 break; 1871 } 1872 1873// printf ("Open (%s) failure. errno %d (%s)\n", dfn, errno, strerror (errno)); 1874 if (dfp == NULL && strcmp (dfn, eng_dict) == 0) { 1875 return 0; 1876 } else { 1877 // If we can't open specified language file, use English as default 1878 snprintf (dfn, sizeof (dfn), eng_dict); 1879 } 1880 } while (1); 1881 1882 memset (pkw, 0, sizeof (kw_t)); 1883 fseek (dfp, 0L, SEEK_END); 1884 dict_size = ftell (dfp) + 128; 1885// printf ("dict_size %d\n", dict_size); 1886 REALLOC_VECTOR (pkw->idx, pkw->len, pkw->tlen, sizeof (unsigned char*)); 1887 pkw->buf = q = malloc (dict_size); 1888 1889 fseek (dfp, 0L, SEEK_SET); 1890#if 0 1891 while (!feof (dfp)) { 1892 // if pkw->idx is not enough, add 32 item to pkw->idx 1893 REALLOC_VECTOR (pkw->idx, pkw->len, pkw->tlen, sizeof (unsigned char*)); 1894 1895 fscanf (dfp, "%[^\n]%*c", q); 1896 if ((p = strchr (q, '=')) != NULL) { 1897 pkw->idx[pkw->len] = q; 1898 pkw->len++; 1899 q = p + strlen (p); 1900 *q = '\0'; 1901 q++; 1902 } 1903 } 1904#else 1905 while ((fscanf(dfp, "%[^\n]", q)) != EOF) { 1906 fgetc(dfp); 1907 1908 // if pkw->idx is not enough, add 32 item to pkw->idx 1909 REALLOC_VECTOR (pkw->idx, pkw->len, pkw->tlen, sizeof (unsigned char*)); 1910 1911 if ((p = strchr (q, '=')) != NULL) { 1912 pkw->idx[pkw->len] = q; 1913 pkw->len++; 1914 q = p + strlen (p); 1915 *q = '\0'; 1916 q++; 1917 } 1918 } 1919 1920#endif 1921 1922 fclose (dfp); 1923// gettimeofday (&tv2, NULL); 1924// printf("Load %d keywords spent %ldms\n", pkw->len, ((tv2.tv_sec * 1000000 + tv2.tv_usec) - (tv1.tv_sec * 1000000 + tv1.tv_usec)) / 1000); 1925 1926 return 1; 1927} 1928 1929 1930void 1931release_dictionary (pkw_t pkw) 1932{ 1933 if (pkw == NULL) { 1934 return; 1935 } 1936 1937 pkw->len = pkw->tlen = 0; 1938 1939 if (pkw->idx != NULL) { 1940 free (pkw->idx); 1941 pkw->idx = NULL; 1942 } 1943 1944 if (pkw->buf != NULL) { 1945 free (pkw->buf); 1946 pkw->buf = NULL; 1947 } 1948} 1949 1950char* 1951search_desc (pkw_t pkw, char *name) 1952{ 1953 int i; 1954 char *p, *ret = NULL; 1955 1956 if (pkw == NULL || (pkw != NULL && pkw->len <= 0)) { 1957 return NULL; 1958 } 1959 for (i = 0; i < pkw->len; ++i) { 1960 p = pkw->idx[i]; 1961 if (strncmp (name, p, strlen (name)) == 0) { 1962 ret = p + strlen (name); 1963 break; 1964 } 1965 } 1966 1967 return ret; 1968} 1969#endif 1970#endif //TRANSLATE_ON_FLY 1971 1972void reapchild() // 0527 add 1973{ 1974 signal(SIGCHLD, reapchild); 1975 wait(NULL); 1976} 1977 1978int do_ssl = 0; // use Global for HTTPS upgrade judgment in web.c 1979int ssl_stream_fd; // use Global for HTTPS stream fd in web.c 1980int main(int argc, char **argv) 1981{ 1982 usockaddr usa; 1983 int listen_fd[2]; 1984 socklen_t sz; 1985 char pidfile[32]; 1986 fd_set active_rfds; 1987 conn_list_t pool; 1988 int i, c; 1989 //int do_ssl = 0; 1990 1991 do_ssl = 0; // default 1992 1993 // usage : httpd -s -p [port] 1994 while ((c = getopt(argc, argv, "sp:i:")) != -1) { 1995 switch (c) { 1996 case 's': 1997#ifdef RTCONFIG_HTTPS 1998 do_ssl = 1; 1999#endif 2000 break; 2001 case 'p': 2002 http_port = atoi(optarg); 2003 break; 2004 case 'i': 2005 http_ifname = optarg; 2006 break; 2007 default: 2008 fprintf(stderr, "ERROR: unknown option %c\n", c); 2009 break; 2010 } 2011 } 2012 2013 /* -p might be specified before -s */ 2014 if (http_port == 0) { 2015#ifdef RTCONFIG_HTTPS 2016 if (do_ssl) { 2017 http_port = SERVER_PORT_SSL; 2018 } else 2019#endif 2020 { 2021 http_port = SERVER_PORT; 2022 } 2023 } 2024 2025 //websSetVer(); 2026 //2008.08 magic 2027 nvram_unset("login_timestamp"); 2028 nvram_unset("login_ip"); 2029 nvram_unset("login_ip_str"); 2030 MAX_login = nvram_get_int("login_max_num"); 2031 if(MAX_login <= DEFAULT_LOGIN_MAX_NUM) 2032 MAX_login = DEFAULT_LOGIN_MAX_NUM; 2033 2034 detect_timestamp_old = 0; 2035 detect_timestamp = 0; 2036 signal_timestamp = 0; 2037 2038 http_get_access_ip(); 2039 2040 /* Ignore broken pipes */ 2041 signal(SIGPIPE, SIG_IGN); 2042 signal(SIGCHLD, reapchild); // 0527 add 2043 2044#ifdef RTCONFIG_HTTPS 2045 //if (do_ssl) 2046 start_ssl(); 2047#endif 2048 2049 /* Initialize listen socket */ 2050 for (i = 0; i < ARRAY_SIZE(listen_fd); i++) 2051 listen_fd[i] = -1; 2052 if ((listen_fd[0] = initialize_listen_socket(&usa, http_ifname)) < 2) { 2053 fprintf(stderr, "can't bind to %s address\n", http_ifname ? : "any"); 2054 exit(errno); 2055 } 2056 if ((http_ifname && strcmp(http_ifname, "lo") != 0) && 2057 (listen_fd[1] = initialize_listen_socket(&usa, "lo")) < 2) { 2058 fprintf(stderr, "can't bind to %s address\n", "loopback"); 2059 /* allow fail if previous bind to interface was ok */ 2060 /* exit(errno); */ 2061 } 2062 2063 FILE *pid_fp; 2064 if (http_port==SERVER_PORT) 2065 strcpy(pidfile, "/var/run/httpd.pid"); 2066 else sprintf(pidfile, "/var/run/httpd-%d.pid", http_port); 2067 2068 if (!(pid_fp = fopen(pidfile, "w"))) { 2069 perror(pidfile); 2070 return errno; 2071 } 2072 fprintf(pid_fp, "%d", getpid()); 2073 fclose(pid_fp); 2074 2075 /* Init connection pool */ 2076 FD_ZERO(&active_rfds); 2077 TAILQ_INIT(&pool.head); 2078 pool.count = 0; 2079 2080 /* Loop forever handling requests */ 2081 for (;;) { 2082 int max_fd, count; 2083 struct timeval tv; 2084 fd_set rfds; 2085 conn_item_t *item, *next; 2086 2087 memcpy(&rfds, &active_rfds, sizeof(rfds)); 2088 max_fd = -1; 2089 if (pool.count < MAX_CONN_ACCEPT) { 2090 for (i = 0; i < ARRAY_SIZE(listen_fd); i++) { 2091 if (listen_fd[i] < 0) 2092 continue; 2093 FD_SET(listen_fd[i], &rfds); 2094 max_fd = max(listen_fd[i], max_fd); 2095 } 2096 } 2097 TAILQ_FOREACH(item, &pool.head, entry) 2098 max_fd = max(item->fd, max_fd); 2099 2100 /* Wait for new connection or incoming request */ 2101 tv.tv_sec = MAX_CONN_TIMEOUT; 2102 tv.tv_usec = 0; 2103 while ((count = select(max_fd + 1, &rfds, NULL, NULL, &tv)) < 0 && errno == EINTR) 2104 continue; 2105 if (count < 0) { 2106 perror("select"); 2107 return errno; 2108 } 2109 2110 /* Check and accept new connection */ 2111 item = NULL; 2112 for (i = 0; count && i < ARRAY_SIZE(listen_fd); i++) { 2113 if (listen_fd[i] < 0 || !FD_ISSET(listen_fd[i], &rfds)) 2114 continue; 2115 2116 item = malloc(sizeof(*item)); 2117 if (item == NULL) { 2118 perror("malloc"); 2119 return errno; 2120 } 2121 sz = sizeof(item->usa); 2122 while ((item->fd = accept(listen_fd[i], &item->usa.sa, &sz)) < 0 && errno == EINTR) 2123 continue; 2124 if (item->fd < 0) { 2125 perror("accept"); 2126 free(item); 2127 continue; 2128 } 2129 2130 /* Set the KEEPALIVE option to cull dead connections */ 2131 setsockopt(item->fd, SOL_SOCKET, SO_KEEPALIVE, &int_1, sizeof(int_1)); 2132 2133 /* Add to active connections */ 2134 FD_SET(item->fd, &active_rfds); 2135 TAILQ_INSERT_TAIL(&pool.head, item, entry); 2136 pool.count++; 2137 } 2138 /* Continue waiting over again */ 2139 if (count && item) 2140 continue; 2141 2142 /* Check and process pending or expired requests */ 2143 TAILQ_FOREACH_SAFE(item, &pool.head, entry, next) { 2144 if (count && !FD_ISSET(item->fd, &rfds)) 2145 continue; 2146 2147 /* Delete from active connections */ 2148 FD_CLR(item->fd, &active_rfds); 2149 TAILQ_REMOVE(&pool.head, item, entry); 2150 pool.count--; 2151 2152 /* Process request if any */ 2153 if (count) { 2154#ifdef RTCONFIG_HTTPS 2155 if (do_ssl) { 2156 ssl_stream_fd = item->fd; 2157 if (!(conn_fp = ssl_server_fopen(item->fd))) { 2158 perror("fdopen(ssl)"); 2159 goto skip; 2160 } 2161 } else 2162#endif 2163 if (!(conn_fp = fdopen(item->fd, "r+"))) { 2164 perror("fdopen"); 2165 goto skip; 2166 } 2167 2168 http_login_cache(&item->usa); 2169 if (http_client_ip_check()) 2170 handle_request(); 2171 fflush(conn_fp); 2172#ifdef RTCONFIG_HTTPS 2173 if (!do_ssl) 2174#endif 2175 shutdown(item->fd, 2), item->fd = -1; 2176 fclose(conn_fp); 2177 2178 skip: 2179 /* Skip the rest of */ 2180 if (--count == 0) 2181 next = NULL; 2182 2183 } 2184 2185 /* Close timed out and/or still alive */ 2186 if (item->fd >= 0) { 2187 shutdown(item->fd, 2); 2188 close(item->fd); 2189 } 2190 2191 free(item); 2192 } 2193 } 2194 2195 for (i = 0; i < ARRAY_SIZE(listen_fd); i++) { 2196 if (listen_fd[i] < 0) 2197 continue; 2198 shutdown(listen_fd[i], 2); 2199 close(listen_fd[i]); 2200 } 2201 2202 return 0; 2203} 2204 2205#ifdef RTCONFIG_HTTPS 2206void save_cert(void) 2207{ 2208 if (eval("tar", "-C", "/", "-czf", "/tmp/cert.tgz", "etc/cert.pem", "etc/key.pem") == 0) { 2209 if (nvram_set_file("https_crt_file", "/tmp/cert.tgz", 8192)) { 2210 nvram_commit_x(); 2211 } 2212 } 2213 unlink("/tmp/cert.tgz"); 2214} 2215 2216void erase_cert(void) 2217{ 2218 unlink("/etc/cert.pem"); 2219 unlink("/etc/key.pem"); 2220 nvram_unset("https_crt_file"); 2221 //nvram_unset("https_crt_gen"); 2222 nvram_set("https_crt_gen", "0"); 2223} 2224 2225void start_ssl(void) 2226{ 2227 int ok; 2228 int save; 2229 int retry; 2230 unsigned long long sn; 2231 char t[32]; 2232 2233 //fprintf(stderr,"[httpd] start_ssl running!!\n"); 2234 //nvram_set("https_crt_gen", "1"); 2235 2236 if (nvram_match("https_crt_gen", "1")) { 2237 erase_cert(); 2238 } 2239 2240 retry = 1; 2241 while (1) { 2242 save = nvram_match("https_crt_save", "1"); 2243 2244 if ((!f_exists("/etc/cert.pem")) || (!f_exists("/etc/key.pem"))) { 2245 ok = 0; 2246 if (save) { 2247 fprintf(stderr, "Save SSL certificate...\n"); // tmp test 2248 if (nvram_get_file("https_crt_file", "/tmp/cert.tgz", 8192)) { 2249 if (eval("tar", "-xzf", "/tmp/cert.tgz", "-C", "/", "etc/cert.pem", "etc/key.pem") == 0){ 2250 system("cat /etc/key.pem /etc/cert.pem > /etc/server.pem"); 2251 ok = 1; 2252 } 2253 2254 int save_intermediate_crt = nvram_match("https_intermediate_crt_save", "1"); 2255 if(save_intermediate_crt){ 2256 eval("tar", "-xzf", "/tmp/cert.tgz", "-C", "/", "etc/intermediate_cert.pem"); 2257 } 2258 2259 unlink("/tmp/cert.tgz"); 2260 } 2261 } 2262 if (!ok) { 2263 erase_cert(); 2264 syslog(LOG_NOTICE, "Generating SSL certificate..."); 2265 fprintf(stderr, "Generating SSL certificate...\n"); // tmp test 2266 // browsers seems to like this when the ip address moves... -- zzz 2267 f_read("/dev/urandom", &sn, sizeof(sn)); 2268 2269 sprintf(t, "%llu", sn & 0x7FFFFFFFFFFFFFFFULL); 2270 eval("gencert.sh", t); 2271 } 2272 } 2273 2274 if ((save) && (*nvram_safe_get("https_crt_file")) == 0) { 2275 save_cert(); 2276 } 2277 2278 if (mssl_init("/etc/cert.pem", "/etc/key.pem")) return; 2279 2280 erase_cert(); 2281 2282 if (!retry) exit(1); 2283 retry = 0; 2284 } 2285} 2286#endif 2287 2288