Ignore:
Timestamp:
2010-08-14T02:54:24+02:00 (6 years ago)
Author:
jow
Message:

[package] uhttpd:

  • more robust handling of network failures on static file serving
  • support unlimited amount of authentication realms, listener and client sockets
  • support for interpreters (.php => /usr/bin/php-cgi)
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/package/uhttpd/src/uhttpd.c

    r22607 r22630  
    5252        FILE *c; 
    5353        char line[512]; 
    54         char *user = NULL; 
    55         char *pass = NULL; 
     54        char *col1 = NULL; 
     55        char *col2 = NULL; 
    5656        char *eol  = NULL; 
    5757 
     
    6767                        if( (line[0] == '/') && (strchr(line, ':') != NULL) ) 
    6868                        { 
    69                                 if( !(user = strchr(line, ':')) || (*user++ = 0) || 
    70                                     !(pass = strchr(user, ':')) || (*pass++ = 0) || 
    71                                         !(eol = strchr(pass, '\n')) || (*eol++  = 0) ) 
     69                                if( !(col1 = strchr(line, ':')) || (*col1++ = 0) || 
     70                                    !(col2 = strchr(col1, ':')) || (*col2++ = 0) || 
     71                                        !(eol = strchr(col2, '\n')) || (*eol++  = 0) ) 
    7272                                                continue; 
    7373 
    74                                 if( !uh_auth_add(line, user, pass) ) 
     74                                if( !uh_auth_add(line, col1, col2) ) 
    7575                                { 
    7676                                        fprintf(stderr, 
    7777                                                "Notice: No password set for user %s, ignoring " 
    78                                                 "authentication on %s\n", user, line 
     78                                                "authentication on %s\n", col1, line 
    7979                                        ); 
    8080                                } 
     
    8282                        else if( !strncmp(line, "I:", 2) ) 
    8383                        { 
    84                                 if( !(user = strchr(line, ':')) || (*user++ = 0) || 
    85                                     !(eol = strchr(user, '\n')) || (*eol++  = 0) ) 
     84                                if( !(col1 = strchr(line, ':')) || (*col1++ = 0) || 
     85                                    !(eol = strchr(col1, '\n')) || (*eol++  = 0) ) 
    8686                                        continue; 
    8787 
    88                                 conf->index_file = strdup(user); 
     88                                conf->index_file = strdup(col1); 
    8989                        } 
    9090                        else if( !strncmp(line, "E404:", 5) ) 
    9191                        { 
    92                                 if( !(user = strchr(line, ':')) || (*user++ = 0) || 
    93                                     !(eol = strchr(user, '\n')) || (*eol++  = 0) ) 
     92                                if( !(col1 = strchr(line, ':')) || (*col1++ = 0) || 
     93                                    !(eol = strchr(col1, '\n')) || (*eol++  = 0) ) 
    9494                                                continue; 
    9595 
    96                                 conf->error_handler = strdup(user); 
    97                         } 
     96                                conf->error_handler = strdup(col1); 
     97                        } 
     98#ifdef HAVE_CGI 
     99                        else if( (line[0] == '.') && (strchr(line, ':') != NULL) ) 
     100                        { 
     101                                if( !(col1 = strchr(line, ':')) || (*col1++ = 0) || 
     102                                    !(eol = strchr(col1, '\n')) || (*eol++  = 0) ) 
     103                                                continue; 
     104 
     105                                if( !uh_interpreter_add(line, col1) ) 
     106                                { 
     107                                        fprintf(stderr, 
     108                                                "Unable to add interpreter %s for extension %s: " 
     109                                                "Out of memory\n", col1, line 
     110                                        ); 
     111                                } 
     112                        } 
     113#endif 
    98114                } 
    99115 
     
    163179                if( ! (l = uh_listener_add(sock, conf)) ) 
    164180                { 
    165                         fprintf(stderr, 
    166                                 "uh_listener_add(): Can not create more than " 
    167                                 "%i listen sockets\n", UH_LIMIT_LISTENERS 
    168                         ); 
    169  
     181                        fprintf(stderr, "uh_listener_add(): Failed to allocate memory\n"); 
    170182                        goto error; 
    171183                } 
     
    398410} 
    399411 
     412#if defined(HAVE_LUA) || defined(HAVE_CGI) 
    400413static int uh_path_match(const char *prefix, const char *url) 
    401414{ 
     
    410423        return 0; 
    411424} 
    412  
    413  
    414 int main (int argc, char **argv) 
     425#endif 
     426 
     427static void uh_dispatch_request( 
     428        struct client *cl, struct http_request *req, struct path_info *pin 
     429) { 
     430#ifdef HAVE_CGI 
     431        struct interpreter *ipr = NULL; 
     432 
     433        if( uh_path_match(cl->server->conf->cgi_prefix, pin->name) || 
     434                (ipr = uh_interpreter_lookup(pin->phys)) ) 
     435        { 
     436                uh_cgi_request(cl, req, pin, ipr); 
     437        } 
     438        else 
     439#endif 
     440        { 
     441                uh_file_request(cl, req, pin); 
     442        } 
     443} 
     444 
     445static void uh_mainloop(struct config *conf, fd_set serv_fds, int max_fd) 
    415446{ 
    416 #ifdef HAVE_LUA 
    417         /* Lua runtime */ 
    418         lua_State *L = NULL; 
    419 #endif 
    420  
    421447        /* master file descriptor list */ 
    422         fd_set used_fds, serv_fds, read_fds; 
     448        fd_set used_fds, read_fds; 
    423449 
    424450        /* working structs */ 
    425         struct addrinfo hints; 
    426451        struct http_request *req; 
    427452        struct path_info *pin; 
    428453        struct client *cl; 
     454 
     455        /* maximum file descriptor number */ 
     456        int new_fd, cur_fd = 0; 
     457 
     458        /* clear the master and temp sets */ 
     459        FD_ZERO(&used_fds); 
     460        FD_ZERO(&read_fds); 
     461 
     462        /* backup server descriptor set */ 
     463        used_fds = serv_fds; 
     464 
     465        /* loop */ 
     466        while(run) 
     467        { 
     468                /* create a working copy of the used fd set */ 
     469                read_fds = used_fds; 
     470 
     471                /* sleep until socket activity */ 
     472                if( select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1 ) 
     473                { 
     474                        perror("select()"); 
     475                        exit(1); 
     476                } 
     477 
     478                /* run through the existing connections looking for data to be read */ 
     479                for( cur_fd = 0; cur_fd <= max_fd; cur_fd++ ) 
     480                { 
     481                        /* is a socket managed by us */ 
     482                        if( FD_ISSET(cur_fd, &read_fds) ) 
     483                        { 
     484                                /* is one of our listen sockets */ 
     485                                if( FD_ISSET(cur_fd, &serv_fds) ) 
     486                                { 
     487                                        /* handle new connections */ 
     488                                        if( (new_fd = accept(cur_fd, NULL, 0)) != -1 ) 
     489                                        { 
     490                                                /* add to global client list */ 
     491                                                if( (cl = uh_client_add(new_fd, uh_listener_lookup(cur_fd))) != NULL ) 
     492                                                { 
     493#ifdef HAVE_TLS 
     494                                                        /* setup client tls context */ 
     495                                                        if( conf->tls ) 
     496                                                                conf->tls_accept(cl); 
     497#endif 
     498 
     499                                                        /* add client socket to global fdset */ 
     500                                                        FD_SET(new_fd, &used_fds); 
     501                                                        fd_cloexec(new_fd); 
     502                                                        max_fd = max(max_fd, new_fd); 
     503                                                } 
     504 
     505                                                /* insufficient resources */ 
     506                                                else 
     507                                                { 
     508                                                        fprintf(stderr, 
     509                                                                "uh_client_add(): Cannot allocate memory\n"); 
     510 
     511                                                        close(new_fd); 
     512                                                } 
     513                                        } 
     514                                } 
     515 
     516                                /* is a client socket */ 
     517                                else 
     518                                { 
     519                                        if( ! (cl = uh_client_lookup(cur_fd)) ) 
     520                                        { 
     521                                                /* this should not happen! */ 
     522                                                fprintf(stderr, 
     523                                                        "uh_client_lookup(): No entry for fd %i!\n", 
     524                                                        cur_fd); 
     525 
     526                                                goto cleanup; 
     527                                        } 
     528 
     529                                        /* parse message header */ 
     530                                        if( (req = uh_http_header_recv(cl)) != NULL ) 
     531                                        { 
     532                                                /* RFC1918 filtering required? */ 
     533                                                if( conf->rfc1918_filter && 
     534                                                    sa_rfc1918(&cl->peeraddr) && 
     535                                                    !sa_rfc1918(&cl->servaddr) ) 
     536                                                { 
     537                                                        uh_http_sendhf(cl, 403, "Forbidden", 
     538                                                                "Rejected request from RFC1918 IP " 
     539                                                                "to public server address"); 
     540                                                } 
     541                                                else 
     542#ifdef HAVE_LUA 
     543                                                /* Lua request? */ 
     544                                                if( conf->lua_state && 
     545                                                    uh_path_match(conf->lua_prefix, req->url) ) 
     546                                                { 
     547                                                        conf->lua_request(cl, req, conf->lua_state); 
     548                                                } 
     549                                                else 
     550#endif 
     551                                                /* dispatch request */ 
     552                                                if( (pin = uh_path_lookup(cl, req->url)) != NULL ) 
     553                                                { 
     554                                                        /* auth ok? */ 
     555                                                        if( uh_auth_check(cl, req, pin) ) 
     556                                                                uh_dispatch_request(cl, req, pin); 
     557                                                } 
     558 
     559                                                /* 404 */ 
     560                                                else 
     561                                                { 
     562                                                        /* Try to invoke an error handler */ 
     563                                                        pin = uh_path_lookup(cl, conf->error_handler); 
     564 
     565                                                        if( pin && uh_auth_check(cl, req, pin) ) 
     566                                                        { 
     567                                                                req->redirect_status = 404; 
     568                                                                uh_dispatch_request(cl, req, pin); 
     569                                                        } 
     570                                                        else 
     571                                                        { 
     572                                                                uh_http_sendhf(cl, 404, "Not Found", 
     573                                                                        "No such file or directory"); 
     574                                                        } 
     575                                                } 
     576                                        } 
     577 
     578#ifdef HAVE_TLS 
     579                                        /* free client tls context */ 
     580                                        if( conf->tls ) 
     581                                                conf->tls_close(cl); 
     582#endif 
     583 
     584                                        cleanup: 
     585 
     586                                        /* close client socket */ 
     587                                        close(cur_fd); 
     588                                        FD_CLR(cur_fd, &used_fds); 
     589 
     590                                        /* remove from global client list */ 
     591                                        uh_client_remove(cur_fd); 
     592                                } 
     593                        } 
     594                } 
     595        } 
     596 
     597#ifdef HAVE_LUA 
     598        /* destroy the Lua state */ 
     599        if( conf->lua_state != NULL ) 
     600                conf->lua_close(conf->lua_state); 
     601#endif 
     602} 
     603 
     604 
     605int main (int argc, char **argv) 
     606{ 
     607        /* master file descriptor list */ 
     608        fd_set used_fds, serv_fds, read_fds; 
     609 
     610        /* working structs */ 
     611        struct addrinfo hints; 
    429612        struct sigaction sa; 
    430613        struct config conf; 
     
    434617 
    435618        /* maximum file descriptor number */ 
    436         int new_fd, cur_fd, max_fd = 0; 
     619        int cur_fd, max_fd = 0; 
    437620 
    438621#ifdef HAVE_TLS 
     
    526709 
    527710        while( (opt = getopt(argc, argv, 
    528                 "fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0 
     711                "fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:i:t:T:")) > 0 
    529712        ) { 
    530713                switch(opt) 
     
    658841                        case 'x': 
    659842                                conf.cgi_prefix = optarg; 
     843                                break; 
     844 
     845                        /* interpreter */ 
     846                        case 'i': 
     847                                if( (optarg[0] == '.') && (port = strchr(optarg, '=')) ) 
     848                                { 
     849                                        *port++ = 0; 
     850                                        uh_interpreter_add(optarg, port); 
     851                                } 
     852                                else 
     853                                { 
     854                                        fprintf(stderr, "Error: Invalid interpreter: %s\n", 
     855                                                optarg); 
     856                                        exit(1); 
     857                                } 
    660858                                break; 
    661859#endif 
     
    741939#ifdef HAVE_CGI 
    742940                                        "       -x string       URL prefix for CGI handler, default is '/cgi-bin'\n" 
     941                                        "       -i .ext=path    Use interpreter at path for files with the given extension\n" 
    743942#endif 
    744943#if defined(HAVE_CGI) || defined(HAVE_LUA) 
     
    8311030                                conf.lua_prefix = "/lua"; 
    8321031 
    833                         L = conf.lua_init(conf.lua_handler); 
     1032                        conf.lua_state = conf.lua_init(conf.lua_handler); 
    8341033                } 
    8351034        } 
     
    8661065        } 
    8671066 
    868         /* backup server descriptor set */ 
    869         used_fds = serv_fds; 
    870  
    871         /* loop */ 
    872         while(run) 
    873         { 
    874                 /* create a working copy of the used fd set */ 
    875                 read_fds = used_fds; 
    876  
    877                 /* sleep until socket activity */ 
    878                 if( select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1 ) 
    879                 { 
    880                         perror("select()"); 
    881                         exit(1); 
    882                 } 
    883  
    884                 /* run through the existing connections looking for data to be read */ 
    885                 for( cur_fd = 0; cur_fd <= max_fd; cur_fd++ ) 
    886                 { 
    887                         /* is a socket managed by us */ 
    888                         if( FD_ISSET(cur_fd, &read_fds) ) 
    889                         { 
    890                                 /* is one of our listen sockets */ 
    891                                 if( FD_ISSET(cur_fd, &serv_fds) ) 
    892                                 { 
    893                                         /* handle new connections */ 
    894                                         if( (new_fd = accept(cur_fd, NULL, 0)) != -1 ) 
    895                                         { 
    896                                                 /* add to global client list */ 
    897                                                 if( (cl = uh_client_add(new_fd, uh_listener_lookup(cur_fd))) != NULL ) 
    898                                                 { 
    899 #ifdef HAVE_TLS 
    900                                                         /* setup client tls context */ 
    901                                                         if( conf.tls ) 
    902                                                                 conf.tls_accept(cl); 
    903 #endif 
    904  
    905                                                         /* add client socket to global fdset */ 
    906                                                         FD_SET(new_fd, &used_fds); 
    907                                                         fd_cloexec(new_fd); 
    908                                                         max_fd = max(max_fd, new_fd); 
    909                                                 } 
    910  
    911                                                 /* insufficient resources */ 
    912                                                 else 
    913                                                 { 
    914                                                         fprintf(stderr, 
    915                                                                 "uh_client_add(): Can not manage more than " 
    916                                                                 "%i client sockets, connection dropped\n", 
    917                                                                 UH_LIMIT_CLIENTS 
    918                                                         ); 
    919  
    920                                                         close(new_fd); 
    921                                                 } 
    922                                         } 
    923                                 } 
    924  
    925                                 /* is a client socket */ 
    926                                 else 
    927                                 { 
    928                                         if( ! (cl = uh_client_lookup(cur_fd)) ) 
    929                                         { 
    930                                                 /* this should not happen! */ 
    931                                                 fprintf(stderr, 
    932                                                         "uh_client_lookup(): No entry for fd %i!\n", 
    933                                                         cur_fd); 
    934  
    935                                                 goto cleanup; 
    936                                         } 
    937  
    938                                         /* parse message header */ 
    939                                         if( (req = uh_http_header_recv(cl)) != NULL ) 
    940                                         { 
    941                                                 /* RFC1918 filtering required? */ 
    942                                                 if( conf.rfc1918_filter && sa_rfc1918(&cl->peeraddr) && 
    943                                                     !sa_rfc1918(&cl->servaddr) ) 
    944                                                 { 
    945                                                         uh_http_sendhf(cl, 403, "Forbidden", 
    946                                                                 "Rejected request from RFC1918 IP to public server address"); 
    947                                                 } 
    948                                                 else 
    949 #ifdef HAVE_LUA 
    950                                                 /* Lua request? */ 
    951                                                 if( L && uh_path_match(conf.lua_prefix, req->url) ) 
    952                                                 { 
    953                                                         conf.lua_request(cl, req, L); 
    954                                                 } 
    955                                                 else 
    956 #endif 
    957                                                 /* dispatch request */ 
    958                                                 if( (pin = uh_path_lookup(cl, req->url)) != NULL ) 
    959                                                 { 
    960                                                         /* auth ok? */ 
    961                                                         if( uh_auth_check(cl, req, pin) ) 
    962                                                         { 
    963 #ifdef HAVE_CGI 
    964                                                                 if( uh_path_match(conf.cgi_prefix, pin->name) ) 
    965                                                                 { 
    966                                                                         uh_cgi_request(cl, req, pin); 
    967                                                                 } 
    968                                                                 else 
    969 #endif 
    970                                                                 { 
    971                                                                         uh_file_request(cl, req, pin); 
    972                                                                 } 
    973                                                         } 
    974                                                 } 
    975  
    976                                                 /* 404 */ 
    977                                                 else 
    978                                                 { 
    979                                                         /* Try to invoke an error handler */ 
    980                                                         pin = uh_path_lookup(cl, conf.error_handler); 
    981  
    982                                                         if( pin && uh_auth_check(cl, req, pin) ) 
    983                                                         { 
    984                                                                 req->redirect_status = 404; 
    985  
    986 #ifdef HAVE_CGI 
    987                                                                 if( uh_path_match(conf.cgi_prefix, pin->name) ) 
    988                                                                 { 
    989                                                                         uh_cgi_request(cl, req, pin); 
    990                                                                 } 
    991                                                                 else 
    992 #endif 
    993                                                                 { 
    994                                                                         uh_file_request(cl, req, pin); 
    995                                                                 } 
    996                                                         } 
    997                                                         else 
    998                                                         { 
    999                                                                 uh_http_sendhf(cl, 404, "Not Found", 
    1000                                                                         "No such file or directory"); 
    1001                                                         } 
    1002                                                 } 
    1003                                         } 
    1004  
    1005 #ifdef HAVE_TLS 
    1006                                         /* free client tls context */ 
    1007                                         if( conf.tls ) 
    1008                                                 conf.tls_close(cl); 
    1009 #endif 
    1010  
    1011                                         cleanup: 
    1012  
    1013                                         /* close client socket */ 
    1014                                         close(cur_fd); 
    1015                                         FD_CLR(cur_fd, &used_fds); 
    1016  
    1017                                         /* remove from global client list */ 
    1018                                         uh_client_remove(cur_fd); 
    1019                                 } 
    1020                         } 
    1021                 } 
    1022         } 
     1067        /* server main loop */ 
     1068        uh_mainloop(&conf, serv_fds, max_fd); 
    10231069 
    10241070#ifdef HAVE_LUA 
    10251071        /* destroy the Lua state */ 
    1026         if( L != NULL ) 
    1027                 conf.lua_close(L); 
     1072        if( conf.lua_state != NULL ) 
     1073                conf.lua_close(conf.lua_state); 
    10281074#endif 
    10291075 
Note: See TracChangeset for help on using the changeset viewer.