From e4a56ea6a916ec6052c981a61c5d2a543ca4aba0 Mon Sep 17 00:00:00 2001 From: mrcsys Date: Wed, 26 Apr 2006 17:48:29 +0000 Subject: Fixed a significant bug in updated ssl code that would allow processes to "run away" Added a new option and helper functions for socket timeout Added new helper function for ssl arguments --- nanohttp/nanohttp-server.c | 521 +++++++++++++++++++++++++-------------------- nanohttp/nanohttp-server.h | 81 ++++--- nanohttp/nanohttp-socket.c | 90 +++++--- nanohttp/nanohttp-socket.h | 36 ++-- nanohttp/nanohttp-ssl.c | 258 +++++++++++++--------- nanohttp/nanohttp-ssl.h | 75 +++++-- 6 files changed, 626 insertions(+), 435 deletions(-) (limited to 'nanohttp') diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c index fdcc73c..661c958 100644 --- a/nanohttp/nanohttp-server.c +++ b/nanohttp/nanohttp-server.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-server.c,v 1.56 2006/04/21 08:39:11 m0gg Exp $ +* $Id: nanohttp-server.c,v 1.57 2006/04/26 17:48:30 mrcsys Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -92,7 +92,8 @@ typedef struct _conndata pthread_attr_t attr; #endif time_t atime; -} conndata_t; +} +conndata_t; #define CONNECTION_FREE 0 #define CONNECTION_IN_USE 1 @@ -108,6 +109,7 @@ static volatile int _httpd_run = 1; static hsocket_t _httpd_socket; static int _httpd_port = 10000; static int _httpd_max_connections = 20; +static int _httpd_timeout = 10; static hservice_t *_httpd_services_default = NULL; static hservice_t *_httpd_services_head = NULL; @@ -122,7 +124,7 @@ static int _httpd_enable_statistics = 0; #ifdef WIN32 static DWORD _httpd_terminate_signal = CTRL_C_EVENT; static int _httpd_max_idle = 120; -static void WSAReaper (void *x); +static void WSAReaper(void *x); #define strncasecmp(s1, s2, num) strncmp(s1, s2, num) #define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2) #else @@ -135,23 +137,27 @@ _httpd_parse_arguments(int argc, char **argv) { int i; - for (i=1; i < argc; i++) + for (i = 1; i < argc; i++) { - if (!strcmp(argv[i-1], NHTTPD_ARG_PORT)) + if (!strcmp(argv[i - 1], NHTTPD_ARG_PORT)) { _httpd_port = atoi(argv[i]); } - else if (!strcmp(argv[i-1], NHTTPD_ARG_TERMSIG)) + else if (!strcmp(argv[i - 1], NHTTPD_ARG_TERMSIG)) { _httpd_terminate_signal = atoi(argv[i]); } - else if (!strcmp(argv[i-1], NHTTPD_ARG_MAXCONN)) + else if (!strcmp(argv[i - 1], NHTTPD_ARG_MAXCONN)) { _httpd_max_connections = atoi(argv[i]); } + else if (!strcmp(argv[i - 1], NHTTPD_ARG_TIMEOUT)) + { + _httpd_timeout = atoi(argv[i]); + } } - log_verbose2 ("socket bind to port '%d'", _httpd_port); + log_verbose2("socket bind to port '%d'", _httpd_port); return; } @@ -163,7 +169,7 @@ _httpd_connection_slots_init(void) int i; pthread_mutex_init(&_httpd_connection_lock, NULL); - _httpd_connection = calloc (_httpd_max_connections, sizeof (conndata_t)); + _httpd_connection = calloc(_httpd_max_connections, sizeof(conndata_t)); for (i = 0; i < _httpd_max_connections; i++) hsocket_init(&(_httpd_connection[i].sock)); @@ -175,10 +181,12 @@ _httpd_register_builtin_services(void) { if (_httpd_enable_service_list) -;/* httpd_register("/httpd/services", _httpd_list_services); */ + ; /* httpd_register("/httpd/services", + _httpd_list_services); */ if (_httpd_enable_statistics) -;/* httpd_register("/httpd/statistics", _httpd_statistics); */ + ; /* httpd_register("/httpd/statistics", + _httpd_statistics); */ return; } @@ -190,7 +198,7 @@ _httpd_register_builtin_services(void) * ----------------------------------------------------- */ herror_t -httpd_init (int argc, char *argv[]) +httpd_init(int argc, char *argv[]) { herror_t status; @@ -199,7 +207,7 @@ httpd_init (int argc, char *argv[]) if ((status = hsocket_module_init(argc, argv)) != H_OK) return status; - log_verbose2 ("socket bind to port '%d'", _httpd_port); + log_verbose2("socket bind to port '%d'", _httpd_port); _httpd_connection_slots_init(); @@ -213,7 +221,7 @@ httpd_init (int argc, char *argv[]) */ #endif - if ((status = hsocket_init (&_httpd_socket)) != H_OK) + if ((status = hsocket_init(&_httpd_socket)) != H_OK) { log_error2("hsocket_init failed (%s)", herror_message(status)); return status; @@ -232,7 +240,7 @@ httpd_register_secure(const char *ctx, httpd_service func, httpd_auth auth) { hservice_t *service; - if (!(service = (hservice_t *) malloc (sizeof (hservice_t)))) + if (!(service = (hservice_t *) malloc(sizeof(hservice_t)))) { log_error2("malloc failed (%s)", strerror(errno)); return -1; @@ -241,9 +249,9 @@ httpd_register_secure(const char *ctx, httpd_service func, httpd_auth auth) service->next = NULL; service->auth = auth; service->func = func; - strcpy (service->ctx, ctx); + strcpy(service->ctx, ctx); - log_verbose3 ("register service:t(%p):%s", service, SAVE_STR (ctx)); + log_verbose3("register service:t(%p):%s", service, SAVE_STR(ctx)); if (_httpd_services_head == NULL) { _httpd_services_head = _httpd_services_tail = service; @@ -264,7 +272,8 @@ httpd_register(const char *ctx, httpd_service service) } int -httpd_register_default_secure(const char *ctx, httpd_service service, httpd_auth auth) +httpd_register_default_secure(const char *ctx, httpd_service service, + httpd_auth auth) { int ret; @@ -288,10 +297,22 @@ httpd_get_port(void) return _httpd_port; } +int +httpd_get_timeout(void) +{ + return _httpd_timeout; +} + +void +httpd_set_timeout(int t) +{ + _httpd_timeout = t; +} + const char * httpd_get_protocol(void) { - return hssl_enabled() ? "https" : "http"; + return hssl_enabled()? "https" : "http"; } /* @@ -313,7 +334,7 @@ httpd_services(void) static void hservice_free(hservice_t * service) { - free (service); + free(service); return; } @@ -324,13 +345,13 @@ hservice_free(hservice_t * service) * ----------------------------------------------------- */ static hservice_t * -httpd_find_service (const char *ctx) +httpd_find_service(const char *ctx) { hservice_t *cur = _httpd_services_head; while (cur != NULL) { - if (!strcmp (cur->ctx, ctx)) + if (!strcmp(cur->ctx, ctx)) { return cur; } @@ -347,9 +368,9 @@ httpd_find_service (const char *ctx) * ----------------------------------------------------- */ void -httpd_response_set_content_type (httpd_conn_t * res, const char *content_type) +httpd_response_set_content_type(httpd_conn_t * res, const char *content_type) { - strncpy (res->content_type, content_type, 25); + strncpy(res->content_type, content_type, 25); return; } @@ -361,7 +382,7 @@ httpd_response_set_content_type (httpd_conn_t * res, const char *content_type) * ----------------------------------------------------- */ herror_t -httpd_send_header (httpd_conn_t * res, int code, const char *text) +httpd_send_header(httpd_conn_t * res, int code, const char *text) { struct tm stm; time_t nw; @@ -371,13 +392,13 @@ httpd_send_header (httpd_conn_t * res, int code, const char *text) herror_t status; /* set status code */ - sprintf (header, "HTTP/1.1 %d %s\r\n", code, text); + sprintf(header, "HTTP/1.1 %d %s\r\n", code, text); /* set date */ - nw = time (NULL); - localtime_r (&nw, &stm); - strftime (buffer, 255, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", &stm); - strcat (header, buffer); + nw = time(NULL); + localtime_r(&nw, &stm); + strftime(buffer, 255, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", &stm); + strcat(header, buffer); /* set content-type */ /* @@ -387,32 +408,32 @@ httpd_send_header (httpd_conn_t * res, int code, const char *text) */ /* set server name */ - strcat (header, "Server: Nano HTTPD library\r\n"); + strcat(header, "Server: Nano HTTPD library\r\n"); /* set _httpd_connection status */ /* strcat (header, "Connection: close\r\n"); */ /* add pairs */ - for(cur = res->header; cur; cur = cur->next) + for (cur = res->header; cur; cur = cur->next) { - sprintf (buffer, "%s: %s\r\n", cur->key, cur->value); - strcat (header, buffer); + sprintf(buffer, "%s: %s\r\n", cur->key, cur->value); + strcat(header, buffer); } /* set end of header */ - strcat (header, "\r\n"); + strcat(header, "\r\n"); /* send header */ - if ((status = hsocket_nsend (res->sock, header, strlen (header))) != H_OK) + if ((status = hsocket_nsend(res->sock, header, strlen(header))) != H_OK) return status; - res->out = http_output_stream_new (res->sock, res->header); + res->out = http_output_stream_new(res->sock, res->header); return H_OK; } herror_t -httpd_send_internal_error (httpd_conn_t * conn, const char *errmsg) +httpd_send_internal_error(httpd_conn_t * conn, const char *errmsg) { const char *template1 = "

Error!


Message: '%s' \r\n"; @@ -420,11 +441,11 @@ httpd_send_internal_error (httpd_conn_t * conn, const char *errmsg) char buffer[4064]; char buflen[5]; - sprintf (buffer, template1, errmsg); - snprintf (buflen, 5, "%d", strlen (buffer)); + sprintf(buffer, template1, errmsg); + snprintf(buflen, 5, "%d", strlen(buffer)); - httpd_set_header (conn, HEADER_CONTENT_LENGTH, buflen); - httpd_send_header (conn, 500, "INTERNAL"); + httpd_set_header(conn, HEADER_CONTENT_LENGTH, buflen); + httpd_send_header(conn, 500, "INTERNAL"); return http_output_stream_write_string(conn->out, buffer); } @@ -435,40 +456,41 @@ httpd_send_internal_error (httpd_conn_t * conn, const char *errmsg) * ----------------------------------------------------- */ static void -httpd_request_print (hrequest_t * req) +httpd_request_print(hrequest_t * req) { hpair_t *pair; - log_verbose1 ("++++++ Request +++++++++"); - log_verbose2 (" Method : '%s'", - (req->method == HTTP_REQUEST_POST) ? "POST" : "GET"); - log_verbose2 (" Path : '%s'", req->path); - log_verbose2 (" Spec : '%s'", - (req->version == HTTP_1_0) ? "HTTP/1.0" : "HTTP/1.1"); - log_verbose1 (" Parsed query string :"); + log_verbose1("++++++ Request +++++++++"); + log_verbose2(" Method : '%s'", + (req->method == HTTP_REQUEST_POST) ? "POST" : "GET"); + log_verbose2(" Path : '%s'", req->path); + log_verbose2(" Spec : '%s'", + (req->version == HTTP_1_0) ? "HTTP/1.0" : "HTTP/1.1"); + log_verbose1(" Parsed query string :"); for (pair = req->query; pair; pair = pair->next) - log_verbose3 (" %s = '%s'", pair->key, pair->value); + log_verbose3(" %s = '%s'", pair->key, pair->value); - log_verbose1 (" Parsed header :"); + log_verbose1(" Parsed header :"); for (pair = req->header; pair; pair = pair->next) - log_verbose3 (" %s = '%s'", pair->key, pair->value); + log_verbose3(" %s = '%s'", pair->key, pair->value); - log_verbose1 ("++++++++++++++++++++++++"); + log_verbose1("++++++++++++++++++++++++"); return; } httpd_conn_t * -httpd_new (hsocket_t *sock) +httpd_new(hsocket_t * sock) { httpd_conn_t *conn; - if (!(conn = (httpd_conn_t *) malloc (sizeof (httpd_conn_t)))) { + if (!(conn = (httpd_conn_t *) malloc(sizeof(httpd_conn_t)))) + { - log_error2("malloc failed (%s)", strerror(errno)); - return NULL; + log_error2("malloc failed (%s)", strerror(errno)); + return NULL; } conn->sock = sock; conn->out = NULL; @@ -480,24 +502,24 @@ httpd_new (hsocket_t *sock) void -httpd_free (httpd_conn_t * conn) +httpd_free(httpd_conn_t * conn) { if (!conn) return; if (conn->out) - http_output_stream_free (conn->out); + http_output_stream_free(conn->out); if (conn->header) - hpairnode_free_deep (conn->header); + hpairnode_free_deep(conn->header); - free (conn); + free(conn); return; } void -do_req_timeout (int signum) +do_req_timeout(int signum) { /* struct sigaction req_timeout; @@ -507,29 +529,31 @@ do_req_timeout (int signum) */ /* XXX this is not real pretty, is there a better way? */ - log_verbose1 ("Thread timeout."); + log_verbose1("Thread timeout."); #ifdef WIN32 - _endthread (); + _endthread(); #else - pthread_exit (0); + pthread_exit(0); #endif } -static int _httpd_decode_authorization(const char *value, char **user, char **pass) +static int +_httpd_decode_authorization(const char *value, char **user, char **pass) { unsigned char *tmp, *tmp2; size_t len; len = strlen(value) * 2; - if (!(tmp = (char *)calloc(1, len))) { + if (!(tmp = (char *) calloc(1, len))) + { log_error2("calloc failed (%s)", strerror(errno)); return -1; } value = strstr(value, " ") + 1; - + log_verbose2("Authorization (base64) = \"%s\"", value); base64_decode(value, tmp); @@ -552,7 +576,8 @@ static int _httpd_decode_authorization(const char *value, char **user, char **pa return 0; } -static int _httpd_authenticate_request(hrequest_t *req, httpd_auth auth) +static int +_httpd_authenticate_request(hrequest_t * req, httpd_auth auth) { char *user, *pass; char *authorization; @@ -561,7 +586,10 @@ static int _httpd_authenticate_request(hrequest_t *req, httpd_auth auth) if (!auth) return 1; - if (!(authorization = hpairnode_get_ignore_case(req->header, HEADER_AUTHORIZATION))) { + if (! + (authorization = + hpairnode_get_ignore_case(req->header, HEADER_AUTHORIZATION))) + { log_debug2("%s header not set", HEADER_AUTHORIZATION); return 0; } @@ -590,13 +618,13 @@ static int _httpd_authenticate_request(hrequest_t *req, httpd_auth auth) */ #ifdef WIN32 static unsigned _stdcall -httpd_session_main (void *data) +httpd_session_main(void *data) #else static void * -httpd_session_main (void *data) +httpd_session_main(void *data) #endif { - hrequest_t *req; /* only for test */ + hrequest_t *req; /* only for test */ conndata_t *conn; httpd_conn_t *rconn; hservice_t *service; @@ -617,19 +645,20 @@ httpd_session_main (void *data) /* XXX: only used in WSAreaper */ conn->atime = time(NULL); - if ((status = hrequest_new_from_socket (&(conn->sock), &req)) != H_OK) + if ((status = hrequest_new_from_socket(&(conn->sock), &req)) != H_OK) { int code; - switch((code = herror_code(status))) + switch ((code = herror_code(status))) { - case HSOCKET_ERROR_SSLCLOSE: - case HSOCKET_ERROR_RECEIVE: - log_error2("hrequest_new_from_socket failed (%s)", herror_message(status)); - break; - default: - httpd_send_internal_error(rconn, herror_message(status)); - break; + case HSOCKET_ERROR_SSLCLOSE: + case HSOCKET_ERROR_RECEIVE: + log_error2("hrequest_new_from_socket failed (%s)", + herror_message(status)); + break; + default: + httpd_send_internal_error(rconn, herror_message(status)); + break; } herror_release(status); done = 1; @@ -637,27 +666,29 @@ httpd_session_main (void *data) else { char *conn_str; - - httpd_request_print (req); - conn_str = hpairnode_get_ignore_case (req->header, HEADER_CONNECTION); - if (conn_str && strncasecmp (conn_str, "close", 6) == 0) + httpd_request_print(req); + + conn_str = hpairnode_get_ignore_case(req->header, HEADER_CONNECTION); + if (conn_str && strncasecmp(conn_str, "close", 6) == 0) done = 1; if (!done) done = req->version == HTTP_1_0 ? 1 : 0; - if ((service = httpd_find_service (req->path))) + if ((service = httpd_find_service(req->path))) { - log_verbose3 ("service '%s' for '%s' found", service->ctx, req->path); + log_verbose3("service '%s' for '%s' found", service->ctx, req->path); if (_httpd_authenticate_request(req, service->auth)) - { + { if (service->func != NULL) { - service->func (rconn, req); - if (rconn->out && rconn->out->type == HTTP_TRANSFER_CONNECTION_CLOSE) { - log_verbose1 ("Connection close requested"); + service->func(rconn, req); + if (rconn->out + && rconn->out->type == HTTP_TRANSFER_CONNECTION_CLOSE) + { + log_verbose1("Connection close requested"); done = 1; } } @@ -665,36 +696,37 @@ httpd_session_main (void *data) { char buffer[256]; - sprintf (buffer, "service '%s' not registered properly (func == NULL)", req->path); - log_verbose1 (buffer); - httpd_send_internal_error (rconn, buffer); + sprintf(buffer, + "service '%s' not registered properly (func == NULL)", + req->path); + log_verbose1(buffer); + httpd_send_internal_error(rconn, buffer); } } else { - char *template = - "" - "" - "Unauthorized" - "" - "" - "

Unauthorized request logged

" - "" - ""; - - httpd_set_header(rconn, HEADER_WWW_AUTHENTICATE, "Basic realm=\"nanoHTTP\""); - httpd_send_header(rconn, 401, "Unauthorized"); - http_output_stream_write_string(rconn->out, template); - done = 1; + char *template = + "" + "" + "Unauthorized" + "" + "" + "

Unauthorized request logged

" "" ""; + + httpd_set_header(rconn, HEADER_WWW_AUTHENTICATE, + "Basic realm=\"nanoHTTP\""); + httpd_send_header(rconn, 401, "Unauthorized"); + http_output_stream_write_string(rconn->out, template); + done = 1; } } else { char buffer[256]; - sprintf (buffer, "no service for '%s' found", req->path); - log_verbose1 (buffer); - httpd_send_internal_error (rconn, buffer); - done = 1; + sprintf(buffer, "no service for '%s' found", req->path); + log_verbose1(buffer); + httpd_send_internal_error(rconn, buffer); + done = 1; } hrequest_free(req); } @@ -705,7 +737,7 @@ httpd_session_main (void *data) hsocket_close(&(conn->sock)); #ifdef WIN32 - CloseHandle ((HANDLE) conn->tid); + CloseHandle((HANDLE) conn->tid); #else pthread_attr_destroy(&(conn->attr)); #endif @@ -713,52 +745,52 @@ httpd_session_main (void *data) conn->flag = CONNECTION_FREE; #ifdef WIN32 - _endthread (); + _endthread(); return 0; -#else +#else /* pthread_exits automagically */ return NULL; #endif } int -httpd_set_header (httpd_conn_t * conn, const char *key, const char *value) +httpd_set_header(httpd_conn_t * conn, const char *key, const char *value) { hpair_t *p; if (conn == NULL) { - log_warn1 ("Connection object is NULL"); + log_warn1("Connection object is NULL"); return 0; } - for (p=conn->header; p; p=p->next) + for (p = conn->header; p; p = p->next) { if (p->key && !strcmp(p->key, key)) { - free (p->value); + free(p->value); p->value = strdup(value); return 1; } } - conn->header = hpairnode_new (key, value, conn->header); + conn->header = hpairnode_new(key, value, conn->header); return 0; } void -httpd_set_headers (httpd_conn_t * conn, hpair_t * header) +httpd_set_headers(httpd_conn_t * conn, hpair_t * header) { while (header) { - httpd_set_header (conn, header->key, header->value); + httpd_set_header(conn, header->key, header->value); header = header->next; } } int -httpd_add_header (httpd_conn_t *conn, const char *key, const char *value) +httpd_add_header(httpd_conn_t * conn, const char *key, const char *value) { if (!conn) { @@ -772,7 +804,7 @@ httpd_add_header (httpd_conn_t *conn, const char *key, const char *value) } void -httpd_add_headers (httpd_conn_t *conn, const hpair_t *values) +httpd_add_headers(httpd_conn_t * conn, const hpair_t * values) { if (!conn) { @@ -795,7 +827,7 @@ httpd_add_headers (httpd_conn_t *conn, const hpair_t *values) */ #ifdef WIN32 BOOL WINAPI -httpd_term (DWORD sig) +httpd_term(DWORD sig) { /* log_debug2 ("Got signal %d", sig); */ if (sig == _httpd_terminate_signal) @@ -805,9 +837,9 @@ httpd_term (DWORD sig) } #else void -httpd_term (int sig) +httpd_term(int sig) { - log_debug2 ("Got signal %d", sig); + log_debug2("Got signal %d", sig); if (sig == _httpd_terminate_signal) _httpd_run = 0; @@ -822,18 +854,18 @@ httpd_term (int sig) * ----------------------------------------------------- */ static void -_httpd_register_signal_handler (void) +_httpd_register_signal_handler(void) { - log_verbose2 ("registering termination signal handler (SIGNAL:%d)", - _httpd_terminate_signal); + log_verbose2("registering termination signal handler (SIGNAL:%d)", + _httpd_terminate_signal); #ifdef WIN32 - if (SetConsoleCtrlHandler ((PHANDLER_ROUTINE) httpd_term, TRUE) == FALSE) + if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) httpd_term, TRUE) == FALSE) { - log_error1 ("Unable to install console event handler!"); + log_error1("Unable to install console event handler!"); } #else - signal (_httpd_terminate_signal, httpd_term); + signal(_httpd_terminate_signal, httpd_term); #endif return; @@ -843,14 +875,15 @@ _httpd_register_signal_handler (void) FUNCTION: _httpd_wait_for_empty_conn ----------------------------------------------------*/ static conndata_t * -_httpd_wait_for_empty_conn (void) +_httpd_wait_for_empty_conn(void) { int i; pthread_mutex_lock(&_httpd_connection_lock); - for (i = 0; ; i++) + for (i = 0;; i++) { - if (!_httpd_run) { + if (!_httpd_run) + { pthread_mutex_unlock(&_httpd_connection_lock); return NULL; @@ -858,7 +891,7 @@ _httpd_wait_for_empty_conn (void) if (i >= _httpd_max_connections) { - system_sleep (1); + system_sleep(1); i = -1; } else if (_httpd_connection[i].flag == CONNECTION_FREE) @@ -878,22 +911,24 @@ _httpd_wait_for_empty_conn (void) * ----------------------------------------------------- */ static void -_httpd_start_thread (conndata_t * conn) +_httpd_start_thread(conndata_t * conn) { int err; #ifdef WIN32 - conn->tid = (HANDLE) _beginthreadex (NULL, 65535, httpd_session_main, conn, 0, &err); + conn->tid = + (HANDLE) _beginthreadex(NULL, 65535, httpd_session_main, conn, 0, &err); #else - pthread_attr_init (&(conn->attr)); + pthread_attr_init(&(conn->attr)); #ifdef PTHREAD_CREATE_DETACHED - pthread_attr_setdetachstate (&(conn->attr), PTHREAD_CREATE_DETACHED); + pthread_attr_setdetachstate(&(conn->attr), PTHREAD_CREATE_DETACHED); #endif - pthread_sigmask (SIG_BLOCK, &thrsigset, NULL); - if ((err = pthread_create (&(conn->tid), &(conn->attr), httpd_session_main, conn))) - log_error2 ("pthread_create failed (%s)", strerror(err)); + pthread_sigmask(SIG_BLOCK, &thrsigset, NULL); + if ((err = + pthread_create(&(conn->tid), &(conn->attr), httpd_session_main, conn))) + log_error2("pthread_create failed (%s)", strerror(err)); #endif return; @@ -907,31 +942,31 @@ _httpd_start_thread (conndata_t * conn) */ herror_t -httpd_run (void) +httpd_run(void) { struct timeval timeout; conndata_t *conn; herror_t err; fd_set fds; - log_verbose1 ("starting run routine"); + log_verbose1("starting run routine"); #ifndef WIN32 - sigemptyset (&thrsigset); - sigaddset (&thrsigset, SIGALRM); + sigemptyset(&thrsigset); + sigaddset(&thrsigset, SIGALRM); #endif - _httpd_register_signal_handler (); + _httpd_register_signal_handler(); if ((err = hsocket_listen(&_httpd_socket)) != H_OK) { - log_error2 ("hsocket_listen failed (%s)", herror_message (err)); + log_error2("hsocket_listen failed (%s)", herror_message(err)); return err; } while (_httpd_run) { - conn = _httpd_wait_for_empty_conn (); + conn = _httpd_wait_for_empty_conn(); if (!_httpd_run) break; @@ -944,11 +979,11 @@ httpd_run (void) timeout.tv_usec = 0; /* zero and set file descriptior */ - FD_ZERO (&fds); - FD_SET (_httpd_socket.sock, &fds); + FD_ZERO(&fds); + FD_SET(_httpd_socket.sock, &fds); /* select socket descriptor */ - switch (select (_httpd_socket.sock + 1, &fds, NULL, NULL, &timeout)) + switch (select(_httpd_socket.sock + 1, &fds, NULL, NULL, &timeout)) { case 0: /* descriptor is not ready */ @@ -960,7 +995,7 @@ httpd_run (void) /* no nothing */ break; } - if (FD_ISSET (_httpd_socket.sock, &fds)) + if (FD_ISSET(_httpd_socket.sock, &fds)) { break; } @@ -972,34 +1007,34 @@ httpd_run (void) if ((err = hsocket_accept(&_httpd_socket, &(conn->sock))) != H_OK) { - log_error2("hsocket_accept failed (%s)", herror_message (err)); + log_error2("hsocket_accept failed (%s)", herror_message(err)); hsocket_close(&(conn->sock)); continue; } - _httpd_start_thread (conn); + _httpd_start_thread(conn); } return 0; } void -httpd_destroy (void) +httpd_destroy(void) { hservice_t *tmp, *cur = _httpd_services_head; while (cur != NULL) { tmp = cur->next; - hservice_free (cur); + hservice_free(cur); cur = tmp; } - hsocket_module_destroy (); + hsocket_module_destroy(); - free (_httpd_connection); + free(_httpd_connection); return; } @@ -1007,7 +1042,7 @@ httpd_destroy (void) #ifdef WIN32 static void -WSAReaper (void *x) +WSAReaper(void *x) { short int connections; short int i; @@ -1018,34 +1053,32 @@ WSAReaper (void *x) for (;;) { connections = 0; - ctime = time ((time_t) 0); + ctime = time((time_t) 0); for (i = 0; i < _httpd_max_connections; i++) { if (_httpd_connection[i].tid == 0) continue; - GetExitCodeThread ((HANDLE) _httpd_connection[i].tid, (PDWORD) & rc); + GetExitCodeThread((HANDLE) _httpd_connection[i].tid, (PDWORD) & rc); if (rc != STILL_ACTIVE) continue; connections++; if ((ctime - _httpd_connection[i].atime < _httpd_max_idle) || (_httpd_connection[i].atime == 0)) continue; - log_verbose3 ("Reaping socket %u from (runtime ~= %d seconds)", - _httpd_connection[i].sock, - ctime - _httpd_connection[i].atime); - shutdown (_httpd_connection[i].sock.sock, 2); - while (recv (_httpd_connection[i].sock.sock, junk, sizeof (junk), 0) > - 0) + log_verbose3("Reaping socket %u from (runtime ~= %d seconds)", + _httpd_connection[i].sock, + ctime - _httpd_connection[i].atime); + shutdown(_httpd_connection[i].sock.sock, 2); + while (recv(_httpd_connection[i].sock.sock, junk, sizeof(junk), 0) > 0) { }; - closesocket (_httpd_connection[i].sock.sock); + closesocket(_httpd_connection[i].sock.sock); _httpd_connection[i].sock.sock = 0; - TerminateThread (_httpd_connection[i].tid, (DWORD) & rc); - CloseHandle (_httpd_connection[i].tid); - memset ((char *) &_httpd_connection[i], 0, - sizeof (_httpd_connection[i])); + TerminateThread(_httpd_connection[i].tid, (DWORD) & rc); + CloseHandle(_httpd_connection[i].tid); + memset((char *) &_httpd_connection[i], 0, sizeof(_httpd_connection[i])); } - Sleep (100); + Sleep(100); } return; } @@ -1053,8 +1086,8 @@ WSAReaper (void *x) #endif unsigned char * -httpd_get_postdata (httpd_conn_t * conn, hrequest_t * req, long *received, - long max) +httpd_get_postdata(httpd_conn_t * conn, hrequest_t * req, long *received, + long max) { char *content_length_str; long content_length = 0; @@ -1063,15 +1096,16 @@ httpd_get_postdata (httpd_conn_t * conn, hrequest_t * req, long *received, if (req->method == HTTP_REQUEST_POST) { - content_length_str = hpairnode_get_ignore_case (req->header, HEADER_CONTENT_LENGTH); + content_length_str = + hpairnode_get_ignore_case(req->header, HEADER_CONTENT_LENGTH); if (content_length_str != NULL) - content_length = atol (content_length_str); + content_length = atol(content_length_str); } else { - log_warn1 ("Not a POST method"); + log_warn1("Not a POST method"); return NULL; } @@ -1081,26 +1115,27 @@ httpd_get_postdata (httpd_conn_t * conn, hrequest_t * req, long *received, if (content_length == 0) { *received = 0; - if (!(postdata = (char *) malloc (1))) { + if (!(postdata = (char *) malloc(1))) + { - log_error2("malloc failed (%s)", strerror(errno)); - return NULL; + log_error2("malloc failed (%s)", strerror(errno)); + return NULL; } postdata[0] = '\0'; return postdata; } - if (!(postdata = (unsigned char *) malloc (content_length + 1))) + if (!(postdata = (unsigned char *) malloc(content_length + 1))) { - log_error2 ("malloc failed (%)", strerror(errno)); + log_error2("malloc failed (%)", strerror(errno)); return NULL; } - if (http_input_stream_read (req->in, postdata, (int) content_length) > 0) + if (http_input_stream_read(req->in, postdata, (int) content_length) > 0) { *received = content_length; postdata[content_length] = '\0'; return postdata; } - free (postdata); + free(postdata); return NULL; } @@ -1110,10 +1145,10 @@ httpd_get_postdata (httpd_conn_t * conn, hrequest_t * req, long *received, */ static void -_httpd_mime_get_boundary (httpd_conn_t * conn, char *dest) +_httpd_mime_get_boundary(httpd_conn_t * conn, char *dest) { - sprintf (dest, "---=.Part_NH_%p", conn); - log_verbose2 ("boundary= \"%s\"", dest); + sprintf(dest, "---=.Part_NH_%p", conn); + log_verbose2("boundary= \"%s\"", dest); return; } @@ -1124,42 +1159,45 @@ _httpd_mime_get_boundary (httpd_conn_t * conn, char *dest) Returns: H_OK or error flag */ herror_t -httpd_mime_send_header (httpd_conn_t * conn, const char *related_start, const char *related_start_info, const char *related_type, int code, const char *text) +httpd_mime_send_header(httpd_conn_t * conn, const char *related_start, + const char *related_start_info, + const char *related_type, int code, const char *text) { char buffer[300]; char temp[250]; char boundary[250]; - /* Set Content-type Set multipart/related parameter type=..; start=.. ; start-info= ..; boundary=... - using sprintf instead of snprintf because visual c does not support snprintf */ + /* Set Content-type Set multipart/related parameter type=..; start=.. ; + start-info= ..; boundary=... using sprintf instead of snprintf because + visual c does not support snprintf */ - sprintf (buffer, "multipart/related;"); + sprintf(buffer, "multipart/related;"); if (related_type) { - snprintf (temp, 75, " type=\"%s\";", related_type); - strcat (buffer, temp); + snprintf(temp, 75, " type=\"%s\";", related_type); + strcat(buffer, temp); } if (related_start) { - snprintf (temp, 250, " start=\"%s\";", related_start); - strcat (buffer, temp); + snprintf(temp, 250, " start=\"%s\";", related_start); + strcat(buffer, temp); } if (related_start_info) { - snprintf (temp, 250, " start-info=\"%s\";", related_start_info); - strcat (buffer, temp); + snprintf(temp, 250, " start-info=\"%s\";", related_start_info); + strcat(buffer, temp); } - _httpd_mime_get_boundary (conn, boundary); - snprintf (temp, 250, " boundary=\"%s\"", boundary); - strcat (buffer, temp); + _httpd_mime_get_boundary(conn, boundary); + snprintf(temp, 250, " boundary=\"%s\"", boundary); + strcat(buffer, temp); - httpd_set_header (conn, HEADER_CONTENT_TYPE, buffer); + httpd_set_header(conn, HEADER_CONTENT_TYPE, buffer); - return httpd_send_header (conn, code, text); + return httpd_send_header(conn, code, text); } @@ -1168,31 +1206,36 @@ httpd_mime_send_header (httpd_conn_t * conn, const char *related_start, const ch with next part */ herror_t -httpd_mime_next (httpd_conn_t * conn, const char *content_id, const char *content_type, const char *transfer_encoding) +httpd_mime_next(httpd_conn_t * conn, const char *content_id, + const char *content_type, const char *transfer_encoding) { herror_t status; char buffer[512]; char boundary[75]; /* Get the boundary string */ - _httpd_mime_get_boundary (conn, boundary); - sprintf (buffer, "\r\n--%s\r\n", boundary); + _httpd_mime_get_boundary(conn, boundary); + sprintf(buffer, "\r\n--%s\r\n", boundary); /* Send boundary */ - status = http_output_stream_write (conn->out, (const byte_t *) buffer, strlen (buffer)); + status = + http_output_stream_write(conn->out, (const byte_t *) buffer, + strlen(buffer)); if (status != H_OK) return status; /* Send Content header */ - sprintf (buffer, "%s: %s\r\n%s: %s\r\n%s: %s\r\n\r\n", - HEADER_CONTENT_TYPE, content_type ? content_type : "text/plain", - HEADER_CONTENT_TRANSFER_ENCODING, - transfer_encoding ? transfer_encoding : "binary", - HEADER_CONTENT_ID, - content_id ? content_id : ""); + sprintf(buffer, "%s: %s\r\n%s: %s\r\n%s: %s\r\n\r\n", + HEADER_CONTENT_TYPE, content_type ? content_type : "text/plain", + HEADER_CONTENT_TRANSFER_ENCODING, + transfer_encoding ? transfer_encoding : "binary", + HEADER_CONTENT_ID, + content_id ? content_id : ""); - status = http_output_stream_write (conn->out, (const byte_t *) buffer, strlen (buffer)); + status = + http_output_stream_write(conn->out, (const byte_t *) buffer, + strlen(buffer)); return status; } @@ -1202,40 +1245,44 @@ httpd_mime_next (httpd_conn_t * conn, const char *content_id, const char *conten with next part */ herror_t -httpd_mime_send_file (httpd_conn_t * conn, const char *content_id, const char *content_type, const char *transfer_encoding, const char *filename) +httpd_mime_send_file(httpd_conn_t * conn, const char *content_id, + const char *content_type, const char *transfer_encoding, + const char *filename) { byte_t buffer[MAX_FILE_BUFFER_SIZE]; herror_t status; FILE *fd; size_t size; - if ((fd = fopen (filename, "rb")) == NULL) - return herror_new ("httpd_mime_send_file", FILE_ERROR_OPEN, "Can not open file '%d'", filename); + if ((fd = fopen(filename, "rb")) == NULL) + return herror_new("httpd_mime_send_file", FILE_ERROR_OPEN, + "Can not open file '%d'", filename); - status = httpd_mime_next (conn, content_id, content_type, transfer_encoding); + status = httpd_mime_next(conn, content_id, content_type, transfer_encoding); if (status != H_OK) { - fclose (fd); + fclose(fd); return status; } - while (!feof (fd)) + while (!feof(fd)) { - size = fread (buffer, 1, MAX_FILE_BUFFER_SIZE, fd); + size = fread(buffer, 1, MAX_FILE_BUFFER_SIZE, fd); if (size == -1) { - fclose (fd); - return herror_new ("httpd_mime_send_file", FILE_ERROR_READ, "Can not read from file '%d'", filename); + fclose(fd); + return herror_new("httpd_mime_send_file", FILE_ERROR_READ, + "Can not read from file '%d'", filename); } - if ((status = http_output_stream_write (conn->out, buffer, size)) != H_OK) + if ((status = http_output_stream_write(conn->out, buffer, size)) != H_OK) { - fclose (fd); + fclose(fd); return status; } } - fclose (fd); + fclose(fd); return H_OK; } @@ -1244,24 +1291,26 @@ httpd_mime_send_file (httpd_conn_t * conn, const char *content_id, const char *c Returns: H_OK or error flag */ herror_t -httpd_mime_end (httpd_conn_t * conn) +httpd_mime_end(httpd_conn_t * conn) { herror_t status; char buffer[512]; char boundary[75]; /* Get the boundary string */ - _httpd_mime_get_boundary (conn, boundary); - sprintf (buffer, "\r\n--%s--\r\n\r\n", boundary); + _httpd_mime_get_boundary(conn, boundary); + sprintf(buffer, "\r\n--%s--\r\n\r\n", boundary); /* Send boundary */ - status = http_output_stream_write (conn->out, (const byte_t *) buffer, strlen (buffer)); + status = + http_output_stream_write(conn->out, (const byte_t *) buffer, + strlen(buffer)); if (status != H_OK) return status; /* Flush put stream */ - status = http_output_stream_flush (conn->out); + status = http_output_stream_flush(conn->out); return status; } diff --git a/nanohttp/nanohttp-server.h b/nanohttp/nanohttp-server.h index 85402c5..77b384f 100644 --- a/nanohttp/nanohttp-server.h +++ b/nanohttp/nanohttp-server.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-server.h,v 1.19 2006/04/21 08:39:11 m0gg Exp $ + * $Id: nanohttp-server.h,v 1.20 2006/04/26 17:48:30 mrcsys Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -38,14 +38,16 @@ typedef struct httpd_conn char content_type[25]; http_output_stream_t *out; hpair_t *header; -} httpd_conn_t; +} +httpd_conn_t; /* Service callback */ typedef void (*httpd_service) (httpd_conn_t *, hrequest_t *); -typedef int (*httpd_auth) (hrequest_t *req, const char *user, const char *password); +typedef int (*httpd_auth) (hrequest_t * req, const char *user, + const char *password); /* * Service representation object @@ -56,40 +58,49 @@ typedef struct tag_hservice httpd_service func; httpd_auth auth; struct tag_hservice *next; -} hservice_t; +} +hservice_t; #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif /* Begin httpd_* function set */ -herror_t httpd_init(int argc, char *argv[]); -void httpd_destroy(void); + herror_t httpd_init(int argc, char *argv[]); + void httpd_destroy(void); + + herror_t httpd_run(void); -herror_t httpd_run(void); + int httpd_register(const char *ctx, httpd_service service); + int httpd_register_secure(const char *ctx, httpd_service service, + httpd_auth auth); -int httpd_register(const char *ctx, httpd_service service); -int httpd_register_secure(const char *ctx, httpd_service service, httpd_auth auth); + int httpd_register_default(const char *ctx, httpd_service service); + int httpd_register_default_secure(const char *ctx, httpd_service service, + httpd_auth auth); -int httpd_register_default(const char *ctx, httpd_service service); -int httpd_register_default_secure(const char *ctx, httpd_service service, httpd_auth auth); + int httpd_get_port(void); + int httpd_get_timeout(void); + void httpd_set_timeout(int t); -int httpd_get_port(void); -const char *httpd_get_protocol(void); + const char *httpd_get_protocol(void); -hservice_t *httpd_services(void); + hservice_t *httpd_services(void); -herror_t httpd_send_header(httpd_conn_t * res, int code, const char *text); + herror_t httpd_send_header(httpd_conn_t * res, int code, const char *text); -int httpd_set_header(httpd_conn_t * conn, const char *key, const char *value); -void httpd_set_headers(httpd_conn_t * conn, hpair_t * header); + int httpd_set_header(httpd_conn_t * conn, const char *key, + const char *value); + void httpd_set_headers(httpd_conn_t * conn, hpair_t * header); -int httpd_add_header(httpd_conn_t * conn, const char *key, const char *value); -void httpd_add_headers(httpd_conn_t * conn, const hpair_t *values); + int httpd_add_header(httpd_conn_t * conn, const char *key, + const char *value); + void httpd_add_headers(httpd_conn_t * conn, const hpair_t * values); /* unsigned char *httpd_get_postdata(httpd_conn_t *conn, @@ -106,36 +117,36 @@ unsigned char *httpd_get_postdata(httpd_conn_t *conn, Begin MIME multipart/related POST Returns: HSOCKET_OK or error flag */ -herror_t httpd_mime_send_header(httpd_conn_t * conn, - const char *related_start, - const char *related_start_info, - const char *related_type, int code, - const char *text); + herror_t httpd_mime_send_header(httpd_conn_t * conn, + const char *related_start, + const char *related_start_info, + const char *related_type, int code, + const char *text); /** Send boundary and part header and continue with next part */ -herror_t httpd_mime_next(httpd_conn_t * conn, - const char *content_id, - const char *content_type, - const char *transfer_encoding); + herror_t httpd_mime_next(httpd_conn_t * conn, + const char *content_id, + const char *content_type, + const char *transfer_encoding); /** Send boundary and part header and continue with next part */ -herror_t httpd_mime_send_file(httpd_conn_t * conn, - const char *content_id, - const char *content_type, - const char *transfer_encoding, - const char *filename); + herror_t httpd_mime_send_file(httpd_conn_t * conn, + const char *content_id, + const char *content_type, + const char *transfer_encoding, + const char *filename); /** Finish MIME request Returns: HSOCKET_OK or error flag */ -herror_t httpd_mime_end(httpd_conn_t * conn); + herror_t httpd_mime_end(httpd_conn_t * conn); #ifdef __cplusplus diff --git a/nanohttp/nanohttp-socket.c b/nanohttp/nanohttp-socket.c index 4d34389..84ee578 100644 --- a/nanohttp/nanohttp-socket.c +++ b/nanohttp/nanohttp-socket.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-socket.c,v 1.58 2006/04/13 06:25:11 m0gg Exp $ +* $Id: nanohttp-socket.c,v 1.59 2006/04/26 17:48:29 mrcsys Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -105,8 +105,16 @@ _hsocket_module_sys_destroy(void) return; } #else -static inline void _hsocket_module_sys_init(int argc, char **argv) { return; } -static inline void _hsocket_module_sys_destroy(void) { return; } +static inline void +_hsocket_module_sys_init(int argc, char **argv) +{ + return; +} +static inline void +_hsocket_module_sys_destroy(void) +{ + return; +} #endif /*-------------------------------------------------- @@ -137,7 +145,7 @@ hsocket_module_destroy(void) FUNCTION: hsocket_init ----------------------------------------------------*/ herror_t -hsocket_init(hsocket_t *sock) +hsocket_init(hsocket_t * sock) { memset(sock, 0, sizeof(hsocket_t)); @@ -150,7 +158,7 @@ hsocket_init(hsocket_t *sock) FUNCTION: hsocket_free ----------------------------------------------------*/ void -hsocket_free(hsocket_t *sock) +hsocket_free(hsocket_t * sock) { /* nop */ @@ -186,7 +194,8 @@ hsocket_open(hsocket_t * dsock, const char *hostname, int port, int ssl) log_verbose4("Opening %s://%s:%i", ssl ? "https" : "http", hostname, port); /* connect to the server */ - if (connect(dsock->sock, (struct sockaddr *) &address, sizeof(address)) != 0) + if (connect(dsock->sock, (struct sockaddr *) &address, sizeof(address)) != + 0) return herror_new("hsocket_open", HSOCKET_ERROR_CONNECT, "Socket error (%s)", strerror(errno)); @@ -242,7 +251,7 @@ hsocket_bind(hsocket_t * dsock, int port) #ifdef WIN32 static herror_t -_hsocket_sys_accept(hsocket_t *sock, hsocket_t *dest) +_hsocket_sys_accept(hsocket_t * sock, hsocket_t * dest) { socklen_t asize; hsocket_t sockfd; @@ -250,7 +259,8 @@ _hsocket_sys_accept(hsocket_t *sock, hsocket_t *dest) asize = sizeof(struct sockaddr_in); while (1) { - sockfd.sock = accept(sock->sock, (struct sockaddr *) &(dest->addr), &asize); + sockfd.sock = + accept(sock->sock, (struct sockaddr *) &(dest->addr), &asize); if (sockfd.sock == INVALID_SOCKET) { if (WSAGetLastError() != WSAEWOULDBLOCK) @@ -269,16 +279,19 @@ _hsocket_sys_accept(hsocket_t *sock, hsocket_t *dest) } #else static herror_t -_hsocket_sys_accept(hsocket_t *sock, hsocket_t *dest) +_hsocket_sys_accept(hsocket_t * sock, hsocket_t * dest) { socklen_t len; len = sizeof(struct sockaddr_in); - if ((dest->sock = accept(sock->sock, (struct sockaddr *) &(dest->addr), &len)) == -1) + if ((dest->sock = + accept(sock->sock, (struct sockaddr *) &(dest->addr), &len)) == -1) { log_warn2("accept failed (%s)", strerror(errno)); - return herror_new("hsocket_accept", HSOCKET_ERROR_ACCEPT, "Cannot accept network connection (%s)", strerror(errno)); + return herror_new("hsocket_accept", HSOCKET_ERROR_ACCEPT, + "Cannot accept network connection (%s)", + strerror(errno)); } return H_OK; @@ -289,7 +302,7 @@ _hsocket_sys_accept(hsocket_t *sock, hsocket_t *dest) FUNCTION: hsocket_accept ----------------------------------------------------------*/ herror_t -hsocket_accept(hsocket_t *sock, hsocket_t *dest) +hsocket_accept(hsocket_t * sock, hsocket_t * dest) { herror_t status; @@ -307,7 +320,8 @@ hsocket_accept(hsocket_t *sock, hsocket_t *dest) } log_verbose3("accepting connection from '%s' socket=%d", - SAVE_STR(((char *) inet_ntoa(dest->addr.sin_addr))), dest->sock); + SAVE_STR(((char *) inet_ntoa(dest->addr.sin_addr))), + dest->sock); return H_OK; } @@ -316,7 +330,7 @@ hsocket_accept(hsocket_t *sock, hsocket_t *dest) FUNCTION: hsocket_listen ----------------------------------------------------*/ herror_t -hsocket_listen(hsocket_t *sock) +hsocket_listen(hsocket_t * sock) { if (sock->sock < 0) return herror_new("hsocket_listen", HSOCKET_ERROR_NOT_INITIALIZED, @@ -334,22 +348,22 @@ hsocket_listen(hsocket_t *sock) #ifdef WIN32 static inline void -_hsocket_sys_close(hsocket_t *sock) +_hsocket_sys_close(hsocket_t * sock) { char junk[10]; /* shutdown(sock,SD_RECEIVE); */ shutdown(sock->sock, SD_SEND); - while (recv(sock->sock, junk, sizeof(junk), 0) > 0) ; - /* nothing */ + while (recv(sock->sock, junk, sizeof(junk), 0) > 0); + /* nothing */ closesocket(sock->sock); return; } #else static inline void -_hsocket_sys_close(hsocket_t *sock) +_hsocket_sys_close(hsocket_t * sock) { shutdown(sock->sock, SHUT_RDWR); @@ -364,7 +378,7 @@ _hsocket_sys_close(hsocket_t *sock) FUNCTION: hsocket_close ----------------------------------------------------*/ void -hsocket_close(hsocket_t *sock) +hsocket_close(hsocket_t * sock) { log_verbose3("closing socket %p (%d)...", sock, sock->sock); @@ -381,7 +395,7 @@ hsocket_close(hsocket_t *sock) FUNCTION: hsocket_send ----------------------------------------------------*/ herror_t -hsocket_nsend(hsocket_t *sock, const byte_t * bytes, int n) +hsocket_nsend(hsocket_t * sock, const byte_t * bytes, int n) { herror_t status; size_t total = 0; @@ -392,7 +406,7 @@ hsocket_nsend(hsocket_t *sock, const byte_t * bytes, int n) return herror_new("hsocket_nsend", HSOCKET_ERROR_NOT_INITIALIZED, "hsocket not initialized"); - /* log_verbose2( "SENDING %s", bytes );*/ + /* log_verbose2( "SENDING %s", bytes ); */ while (1) { @@ -416,13 +430,34 @@ hsocket_nsend(hsocket_t *sock, const byte_t * bytes, int n) FUNCTION: hsocket_send ----------------------------------------------------*/ herror_t -hsocket_send(hsocket_t *sock, const char *str) +hsocket_send(hsocket_t * sock, const char *str) { return hsocket_nsend(sock, str, strlen(str)); } +int +hsocket_select_read(int sock, char *buf, size_t len) +{ + struct timeval timeout; + fd_set fds; + int ret; + FD_ZERO(&fds); + FD_SET(sock, &fds); + timeout.tv_sec = httpd_get_timeout(); + timeout.tv_usec = 0; + ret = select(sock + 1, &fds, NULL, NULL, &timeout); + if (ret == 0) + { + errno = ETIMEDOUT; + log_verbose2("Socket %d timeout", sock); + return -1; + } + return read(sock, buf, len); +} + herror_t -hsocket_read(hsocket_t *sock, byte_t * buffer, int total, int force, int *received) +hsocket_read(hsocket_t * sock, byte_t * buffer, int total, int force, + int *received) { herror_t status; size_t totalRead; @@ -434,7 +469,9 @@ hsocket_read(hsocket_t *sock, byte_t * buffer, int total, int force, int *receiv do { - if ((status = hssl_read(sock, &buffer[totalRead], (size_t)total - totalRead, &count)) != H_OK) + if ((status = + hssl_read(sock, &buffer[totalRead], (size_t) total - totalRead, + &count)) != H_OK) { log_warn2("hssl_read failed (%s)", herror_message(status)); return status; @@ -442,8 +479,8 @@ hsocket_read(hsocket_t *sock, byte_t * buffer, int total, int force, int *receiv if (!force) { - /* log_verbose3("Leaving !force (received=%d)(status=%d)", *received, status); - */ + /* log_verbose3("Leaving !force (received=%d)(status=%d)", *received, + status); */ *received = count; return H_OK; } @@ -462,4 +499,3 @@ hsocket_read(hsocket_t *sock, byte_t * buffer, int total, int force, int *receiv } while (1); } - diff --git a/nanohttp/nanohttp-socket.h b/nanohttp/nanohttp-socket.h index a5ef903..fd05040 100644 --- a/nanohttp/nanohttp-socket.h +++ b/nanohttp/nanohttp-socket.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-socket.h,v 1.26 2006/03/07 16:20:37 m0gg Exp $ + * $Id: nanohttp-socket.h,v 1.27 2006/04/26 17:48:30 mrcsys Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -54,10 +54,12 @@ typedef struct hsocket_t #endif struct sockaddr_in addr; void *ssl; -} hsocket_t; /* end of socket definition */ +} +hsocket_t; /* end of socket definition */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif /** @@ -66,14 +68,14 @@ extern "C" { @returns This function should always return H_OK. */ -herror_t hsocket_module_init(int argc, char **argv); + herror_t hsocket_module_init(int argc, char **argv); /** Destroys the socket modul. This should be called after finishing an application. */ -void hsocket_module_destroy(void); + void hsocket_module_destroy(void); /** @@ -86,14 +88,14 @@ void hsocket_module_destroy(void); @see hsocket_init_ssl @returns This function should always return H_OK. */ -herror_t hsocket_init(hsocket_t *sock); + herror_t hsocket_init(hsocket_t * sock); /** Destroys and releases a given socket. @param sock the socket to destroy */ -void hsocket_free(hsocket_t *sock); + void hsocket_free(hsocket_t * sock); /** @@ -110,7 +112,8 @@ void hsocket_free(hsocket_t *sock);
HSOCKET_ERROR_GET_HOSTNAME
HSOCKET_ERROR_CONNECT */ -herror_t hsocket_open(hsocket_t *sock, const char *host, int port, int ssl); + herror_t hsocket_open(hsocket_t * sock, const char *host, int port, + int ssl); /** @@ -118,7 +121,7 @@ herror_t hsocket_open(hsocket_t *sock, const char *host, int port, int ssl); @param sock the socket to close */ -void hsocket_close(hsocket_t *sock); + void hsocket_close(hsocket_t * sock); /** @@ -134,7 +137,7 @@ void hsocket_close(hsocket_t *sock); @see hsocket_listen */ -herror_t hsocket_bind(hsocket_t *sock, int port); + herror_t hsocket_bind(hsocket_t * sock, int port); /** @@ -148,7 +151,7 @@ herror_t hsocket_bind(hsocket_t *sock, int port);
HSOCKET_ERROR_NOT_INITIALIZED
HSOCKET_ERROR_LISTEN */ -herror_t hsocket_listen(hsocket_t *sock); + herror_t hsocket_listen(hsocket_t * sock); /** @@ -162,7 +165,7 @@ herror_t hsocket_listen(hsocket_t *sock);
HSOCKET_ERROR_NOT_INITIALIZED
HSOCKET_ERROR_ACCEPT */ -herror_t hsocket_accept(hsocket_t *sock, hsocket_t * dest); + herror_t hsocket_accept(hsocket_t * sock, hsocket_t * dest); /** @@ -176,7 +179,7 @@ herror_t hsocket_accept(hsocket_t *sock, hsocket_t * dest);
HSOCKET_ERROR_NOT_INITIALIZED
HSOCKET_ERROR_SEND */ -herror_t hsocket_nsend(hsocket_t *sock, const byte_t * bytes, int size); + herror_t hsocket_nsend(hsocket_t * sock, const byte_t * bytes, int size); /** @@ -189,9 +192,10 @@ herror_t hsocket_nsend(hsocket_t *sock, const byte_t * bytes, int size);
HSOCKET_ERROR_NOT_INITIALIZED
HSOCKET_ERROR_SEND */ -herror_t hsocket_send(hsocket_t *sock, const char *str); + herror_t hsocket_send(hsocket_t * sock, const char *str); + int hsocket_select_read(int sock, char *buf, size_t len); /** Reads data from the socket. @@ -208,8 +212,8 @@ herror_t hsocket_send(hsocket_t *sock, const char *str); the socket. */ -herror_t hsocket_read(hsocket_t *sock, byte_t * buffer, int size, int force, - int *readed); + herror_t hsocket_read(hsocket_t * sock, byte_t * buffer, int size, + int force, int *readed); #ifdef __cplusplus } diff --git a/nanohttp/nanohttp-ssl.c b/nanohttp/nanohttp-ssl.c index 79506ea..b9e4af1 100644 --- a/nanohttp/nanohttp-ssl.c +++ b/nanohttp/nanohttp-ssl.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-ssl.c,v 1.24 2006/04/17 12:26:17 mrcsys Exp $ +* $Id: nanohttp-ssl.c,v 1.25 2006/04/26 17:48:30 mrcsys Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2001-2005 Rochester Institute of Technology @@ -87,43 +87,47 @@ static int enabled = 0; int (*_hssl_verify_cert) (X509 * cert) = _hssl_dummy_verify_cert; static void -_hssl_superseed (void) +_hssl_superseed(void) { int buf[256], i; - srand (time (NULL)); + srand(time(NULL)); for (i = 0; i < 256; i++) { - buf[i] = rand (); + buf[i] = rand(); } - RAND_seed ((unsigned char *) buf, sizeof (buf)); + RAND_seed((unsigned char *) buf, sizeof(buf)); return; } static char * -_hssl_get_error(SSL *ssl, int ret) +_hssl_get_error(SSL * ssl, int ret) { switch (SSL_get_error(ssl, ret)) { - case SSL_ERROR_NONE: - return "None"; - case SSL_ERROR_ZERO_RETURN: - return "Zero return"; - case SSL_ERROR_WANT_READ: - return "Want read"; - case SSL_ERROR_WANT_WRITE: - return "Want write"; - case SSL_ERROR_WANT_X509_LOOKUP: - return "Want x509 lookup"; - case SSL_ERROR_SYSCALL: - return "Syscall failed"; - case SSL_ERROR_SSL: - return "SSL error"; - default: - return "Unkown error"; + case SSL_ERROR_NONE: + return "None"; + case SSL_ERROR_ZERO_RETURN: + return "Zero return"; + case SSL_ERROR_WANT_READ: + return "Want read"; + case SSL_ERROR_WANT_WRITE: + return "Want write"; + case SSL_ERROR_WANT_X509_LOOKUP: + return "Want x509 lookup"; + case SSL_ERROR_SYSCALL: + if (ERR_get_error() == 0 && ret == -1) + { + return strerror(errno); + } + return "Syscall failed"; + case SSL_ERROR_SSL: + return "SSL error"; + default: + return "Unkown error"; } } @@ -144,45 +148,46 @@ _hssl_password_callback(char *buf, int num, int rwflag, void *userdata) int -verify_sn (X509 * cert, int who, int nid, char *str) +verify_sn(X509 * cert, int who, int nid, char *str) { char name[256]; char buf[256]; - memset (name, '\0', 256); - memset (buf, '\0', 256); + memset(name, '\0', 256); + memset(buf, '\0', 256); if (who == CERT_SUBJECT) { - X509_NAME_oneline (X509_get_subject_name (cert), name, 256); + X509_NAME_oneline(X509_get_subject_name(cert), name, 256); } else { - X509_NAME_oneline (X509_get_issuer_name (cert), name, 256); + X509_NAME_oneline(X509_get_issuer_name(cert), name, 256); } buf[0] = '/'; - strcat (buf, OBJ_nid2sn (nid)); - strcat (buf, "="); - strcat (buf, str); + strcat(buf, OBJ_nid2sn(nid)); + strcat(buf, "="); + strcat(buf, str); return strstr(name, buf) ? 1 : 0; } void -hssl_set_hssl_verify_cert( int func(X509 * cert) ){ - _hssl_verify_cert = func; +hssl_set_hssl_verify_cert(int func(X509 * cert)) +{ + _hssl_verify_cert = func; } static int _hssl_dummy_verify_cert(X509 * cert) { - /* TODO: Make sure that the client is providing a client cert, - or that the Module is providing the Module cert */ + /* TODO: Make sure that the client is providing a client cert, or that the + Module is providing the Module cert */ /* connect to anyone */ - log_verbose1 ("Validating certificate."); + log_verbose1("Validating certificate."); return 1; } @@ -196,18 +201,41 @@ _hssl_cert_verify_callback(int prev_ok, X509_STORE_CTX * ctx) return 1; } */ - log_verbose2 ("Cert depth = %d", X509_STORE_CTX_get_error_depth(ctx) ); + log_verbose2("Cert depth = %d", X509_STORE_CTX_get_error_depth(ctx)); if (X509_STORE_CTX_get_error_depth(ctx) == 0) { return _hssl_verify_cert(X509_STORE_CTX_get_current_cert(ctx)); } else { - log_verbose1 ("Cert ok (prev)"); + log_verbose1("Cert ok (prev)"); return prev_ok; } } +void +hssl_set_certificate(char *c) +{ + certificate = c; +} + +void +hssl_set_certpass(char *c) +{ + certpass = c; +} + +void +hssl_set_ca(char *c) +{ + ca_list = c; +} + +void +hssl_enable(void) +{ + enabled = 1; +} static void _hssl_parse_arguments(int argc, char **argv) @@ -215,21 +243,21 @@ _hssl_parse_arguments(int argc, char **argv) int i; - for (i=1; isock); + SSL_set_fd(ssl, sock->sock); if ((ret = SSL_connect(ssl)) <= 0) { herror_t err; - log_error2 ("SSL connect error (%s)", _hssl_get_error(ssl, -1)); - err = herror_new("hssl_client_ssl", HSSL_ERROR_CONNECT, "SSL_connect failed (%s)", _hssl_get_error(ssl, ret)); - SSL_free (ssl); + log_error2("SSL connect error (%s)", _hssl_get_error(ssl, -1)); + err = + herror_new("hssl_client_ssl", HSSL_ERROR_CONNECT, + "SSL_connect failed (%s)", _hssl_get_error(ssl, ret)); + SSL_free(ssl); return err; } - /* SSL_connect should take care of this for us. - if (SSL_get_peer_certificate(ssl) == NULL) - { - log_error1("No certificate provided"); - SSL_free(ssl); - return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "No certificate provided"); - } + /* SSL_connect should take care of this for us. if + (SSL_get_peer_certificate(ssl) == NULL) { log_error1("No certificate + provided"); SSL_free(ssl); return herror_new("hssl_client_ssl", + HSSL_ERROR_CERTIFICATE, "No certificate provided"); } - if (SSL_get_verify_result(ssl) != X509_V_OK) - { - log_error1("Certificate did not verify"); - SSL_free(ssl); - return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "Verfiy certificate failed"); - } */ + if (SSL_get_verify_result(ssl) != X509_V_OK) { log_error1("Certificate + did not verify"); SSL_free(ssl); return herror_new("hssl_client_ssl", + HSSL_ERROR_CERTIFICATE, "Verfiy certificate failed"); } */ + + log_verbose1("SSL client initialization completed"); - log_verbose1 ("SSL client initialization completed"); - sock->ssl = ssl; - + return H_OK; } +long +hssl_bio_read(BIO * b, char *out, int outl) +{ + + return hsocket_select_read(b->num, out, outl);; +} herror_t -hssl_server_ssl(hsocket_t *sock) +hssl_server_ssl(hsocket_t * sock) { SSL *ssl; int ret; + BIO *sbio; if (!enabled) return H_OK; @@ -428,18 +464,33 @@ hssl_server_ssl(hsocket_t *sock) if (!(ssl = SSL_new(context))) { log_warn1("SSL_new failed"); - return herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "Cannot create SSL object"); + return herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, + "Cannot create SSL object"); } - SSL_set_fd(ssl, sock->sock); + /* SSL_set_fd(ssl, sock->sock); */ + + sbio = BIO_new_socket(sock->sock, BIO_NOCLOSE); + + if (sbio == NULL) + { + log_error1("BIO_new_socket failed"); + return NULL; + } + // BIO_set_callback(sbio, hssl_bio_cb); + sbio->method->bread = hssl_bio_read; + SSL_set_bio(ssl, sbio, sbio); + if ((ret = SSL_accept(ssl)) <= 0) { herror_t err; - log_error2 ("SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); + log_error2("SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); - err = herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); - SSL_free (ssl); + err = + herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, + "SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); + SSL_free(ssl); return err; } @@ -451,21 +502,20 @@ hssl_server_ssl(hsocket_t *sock) void -hssl_cleanup(hsocket_t *sock) +hssl_cleanup(hsocket_t * sock) { if (sock->ssl) { - SSL_shutdown (sock->ssl); - SSL_free (sock->ssl); + SSL_shutdown(sock->ssl); + SSL_free(sock->ssl); sock->ssl = NULL; } return; } - herror_t -hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) +hssl_read(hsocket_t * sock, char *buf, size_t len, size_t * received) { int count; @@ -474,12 +524,15 @@ hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) if (sock->ssl) { if ((count = SSL_read(sock->ssl, buf, len)) == -1) - return herror_new("SSL_read", HSOCKET_ERROR_RECEIVE, "SSL_read failed (%s)", _hssl_get_error(sock->ssl, count)); + return herror_new("SSL_read", HSOCKET_ERROR_RECEIVE, + "SSL_read failed (%s)", _hssl_get_error(sock->ssl, + count)); } else { - if ((count = recv(sock->sock, buf, len, 0)) == -1) - return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", strerror(errno)); + if ((count = hsocket_select_read(sock->sock, buf, len)) == -1) + return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, + "recv failed (%s)", strerror(errno)); } *received = count; @@ -488,7 +541,7 @@ hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) herror_t -hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) +hssl_write(hsocket_t * sock, const char *buf, size_t len, size_t * sent) { int count; @@ -497,12 +550,15 @@ hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) if (sock->ssl) { if ((count = SSL_write(sock->ssl, buf, len)) == -1) - return herror_new("SSL_write", HSOCKET_ERROR_SEND, "SSL_write failed (%s)", _hssl_get_error(sock->ssl, count)); + return herror_new("SSL_write", HSOCKET_ERROR_SEND, + "SSL_write failed (%s)", _hssl_get_error(sock->ssl, + count)); } else { if ((count = send(sock->sock, buf, len, 0)) == -1) - return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", strerror(errno)); + return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", + strerror(errno)); } *sent = count; @@ -512,24 +568,26 @@ hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) #else herror_t -hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) +hssl_read(hsocket_t * sock, char *buf, size_t len, size_t * received) { int count; - if ((count = recv(sock->sock, buf, len, 0)) == -1) - return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", strerror(errno)); + if ((count = hsocket_select_read(sock->sock, buf, len)) == -1) + return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", + strerror(errno)); *received = count; return H_OK; } herror_t -hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) +hssl_write(hsocket_t * sock, const char *buf, size_t len, size_t * sent) { int count; if ((count = send(sock->sock, buf, len, 0)) == -1) - return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", strerror(errno)); + return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", + strerror(errno)); *sent = count; return H_OK; } diff --git a/nanohttp/nanohttp-ssl.h b/nanohttp/nanohttp-ssl.h index af99069..7559c8b 100644 --- a/nanohttp/nanohttp-ssl.h +++ b/nanohttp/nanohttp-ssl.h @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-ssl.h,v 1.16 2006/04/17 12:26:17 mrcsys Exp $ +* $Id: nanohttp-ssl.h,v 1.17 2006/04/26 17:48:30 mrcsys Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2001-2005 Rochester Institute of Technology @@ -35,7 +35,8 @@ #endif #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif /** @@ -43,20 +44,25 @@ extern "C" { * Initialization and shutdown of the SSL module * */ -herror_t hssl_module_init(int argc, char **argv); -void hssl_module_destroy(void); + herror_t hssl_module_init(int argc, char **argv); + void hssl_module_destroy(void); -int hssl_enabled(void); + void hssl_set_certificate(char *c); + void hssl_set_certpass(char *c); + void hssl_set_ca(char *c); + void hssl_enable(void); + + int hssl_enabled(void); /** * * Socket initialization and shutdown * */ -herror_t hssl_client_ssl(hsocket_t *sock); -herror_t hssl_server_ssl(hsocket_t *sock); + herror_t hssl_client_ssl(hsocket_t * sock); + herror_t hssl_server_ssl(hsocket_t * sock); -void hssl_cleanup(hsocket_t *sock); + void hssl_cleanup(hsocket_t * sock); /* * Callback for password checker @@ -70,7 +76,7 @@ void hssl_cleanup(hsocket_t *sock); */ #define CERT_SUBJECT 1 -int verify_sn(X509 * cert, int who, int nid, char *str); + int verify_sn(X509 * cert, int who, int nid, char *str); /* * Called by framework for verify @@ -81,9 +87,9 @@ int verify_sn(X509 * cert, int who, int nid, char *str); /* * This function MUST be implemented by user client/server code somewhere */ -void hssl_set_user_verify( int func(X509 * cert) ); + void hssl_set_user_verify(int func(X509 * cert)); -static int _hssl_dummy_verify_cert(X509 * cert); + static int _hssl_dummy_verify_cert(X509 * cert); #ifdef __cplusplus } @@ -91,24 +97,51 @@ static int _hssl_dummy_verify_cert(X509 * cert); #else /* HAVE_SSL */ -static inline herror_t hssl_module_init(int argc, char **argv) { return H_OK; } -static inline void hssl_module_destroy(void) { return; } +static inline herror_t +hssl_module_init(int argc, char **argv) +{ + return H_OK; +} +static inline void +hssl_module_destroy(void) +{ + return; +} -static inline int hssl_enabled(void) { return 0; } +static inline int +hssl_enabled(void) +{ + return 0; +} -static inline herror_t hssl_client_ssl(hsocket_t *sock) { return H_OK; } -static inline herror_t hssl_server_ssl(hsocket_t *sock) { return H_OK; } +static inline herror_t +hssl_client_ssl(hsocket_t * sock) +{ + return H_OK; +} +static inline herror_t +hssl_server_ssl(hsocket_t * sock) +{ + return H_OK; +} -static inline void hssl_cleanup(hsocket_t *sock) { return; } +static inline void +hssl_cleanup(hsocket_t * sock) +{ + return; +} #endif /* HAVE_SSL */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif - -herror_t hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received); -herror_t hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent); + long hssl_bio_read(BIO * b, char *out, int outl); + herror_t hssl_read(hsocket_t * sock, char *buf, size_t len, + size_t * received); + herror_t hssl_write(hsocket_t * sock, const char *buf, size_t len, + size_t * sent); #ifdef __cplusplus } -- cgit v1.1-32-gdbae