From d45b4bc26f330d2ce29e4a06ffdae74d82e8b43b Mon Sep 17 00:00:00 2001 From: snowdrop Date: Sat, 18 Feb 2006 20:14:35 +0000 Subject: added basic authentication and SOAP-Header capabilities for request objects Thanks to Heiko Ronsdorf --- nanohttp/Makefile.am | 2 + nanohttp/nanohttp-client.c | 393 ++++++++++--------------------------------- nanohttp/nanohttp-client.h | 3 +- nanohttp/nanohttp-common.c | 84 ++++----- nanohttp/nanohttp-common.h | 13 +- nanohttp/nanohttp-mime.c | 14 +- nanohttp/nanohttp-request.c | 15 +- nanohttp/nanohttp-response.c | 13 +- nanohttp/nanohttp-server.c | 354 +++++++++++++++++++++----------------- nanohttp/nanohttp-server.h | 11 +- nanohttp/nanohttp-socket.c | 217 +++++++++--------------- nanohttp/nanohttp-socket.h | 3 +- nanohttp/nanohttp-ssl.c | 71 +++++--- nanohttp/nanohttp-stream.c | 14 +- 14 files changed, 515 insertions(+), 692 deletions(-) (limited to 'nanohttp') diff --git a/nanohttp/Makefile.am b/nanohttp/Makefile.am index 6e6be3a..2ad1fb8 100644 --- a/nanohttp/Makefile.am +++ b/nanohttp/Makefile.am @@ -9,6 +9,7 @@ nanohttp-stream.h\ nanohttp-mime.h\ nanohttp-request.h\ nanohttp-response.h\ +nanohttp-base64.h\ nanohttp-ssl.h @@ -20,6 +21,7 @@ nanohttp-stream.c\ nanohttp-mime.c\ nanohttp-request.c\ nanohttp-response.c\ +nanohttp-base64.c\ nanohttp-ssl.c diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c index 44ba815..802e021 100644 --- a/nanohttp/nanohttp-client.c +++ b/nanohttp/nanohttp-client.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-client.c,v 1.37 2006/02/08 11:13:14 snowdrop Exp $ +* $Id: nanohttp-client.c,v 1.38 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,30 +21,37 @@ * * Email: ferhatayaz@yahoo.com ******************************************************************/ -#include -#include - #ifdef HAVE_CONFIG_H #include #endif +#ifdef HAVE_TIME_H #include +#endif + +#ifdef HAVE_STDIO_H #include +#endif + +#ifdef HAVE_STDLIB_H #include +#endif + +#ifdef HAVE_STDARG_H #include +#endif + +#ifdef HAVE_STRING_H #include +#endif #ifdef MEM_DEBUG #include #endif -#if 0 -static int -httpc_send_data(httpc_conn_t * conn, const unsigned char *data, size_t size) -{ - return -1; -} -#endif +#include "nanohttp-client.h" +#include "nanohttp-socket.h" + /*-------------------------------------------------- FUNCTION: httpc_init DESC: Initialize http client connection @@ -54,24 +61,21 @@ herror_t httpc_init(int argc, char *argv[]) { hoption_init_args(argc, argv); - hsocket_module_init(); -#ifdef HAVE_SSL - start_ssl(); -#endif - return H_OK; -} + return hsocket_module_init(); +} /*-------------------------------------------------- FUNCTION: httpc_destroy DESC: Destroy the http client module ----------------------------------------------------*/ void -httpc_destroy() +httpc_destroy(void) { hsocket_module_destroy(); -} + return; +} /*-------------------------------------------------- FUNCTION: httpc_new @@ -80,26 +84,27 @@ You need to create at least 1 http client connection to communicate via http. ----------------------------------------------------*/ httpc_conn_t * -httpc_new() +httpc_new(void) { static int counter = 10000; - httpc_conn_t *res = (httpc_conn_t *) malloc(sizeof(httpc_conn_t)); + httpc_conn_t *res; + + if (!(res = (httpc_conn_t *) malloc(sizeof(httpc_conn_t)))) + return NULL; if (hsocket_init(&res->sock) != H_OK) - { return NULL; - } + res->header = NULL; res->version = HTTP_1_1; res->out = NULL; res->_dime_package_nr = 0; res->_dime_sent_bytes = 0; res->id = counter++; - res->block = 0; + return res; } - /*-------------------------------------------------- FUNCTION: httpc_free DESC: Free the given http client object. @@ -129,6 +134,7 @@ httpc_free(httpc_conn_t * conn) hsocket_free(conn->sock); free(conn); + return; } /*-------------------------------------------------- @@ -143,6 +149,8 @@ httpc_close_free(httpc_conn_t * conn) hsocket_close(conn->sock); httpc_free(conn); + + return; } int @@ -168,7 +176,7 @@ httpc_add_headers(httpc_conn_t *conn, const hpair_t *values) return; } - for(;values; values=values->next) + for ( ;values; values=values->next) httpc_add_header(conn, values->key, values->value); return; @@ -190,59 +198,40 @@ httpc_set_header(httpc_conn_t *conn, const char *key, const char *value) log_warn1("Connection object is NULL"); return 0; } - p = conn->header; - while (p != NULL) + + for (p = conn->header; p; p = p->next) { - if (p->key != NULL) + if (p->key && !strcmp(p->key, key)) { - if (!strcmp(p->key, key)) - { - free(p->value); - p->value = (char *) malloc(strlen(value) + 1); - strcpy(p->value, value); - return 1; - } + free(p->value); + p->value = strdup(value); + return 1; } - p = p->next; } conn->header = hpairnode_new(key, value, conn->header); + return 0; } /*-------------------------------------------------- -FUNCTION: httpc_header_add_date -DESC: Adds the current date to the header. -----------------------------------------------------*/ -/* static void -_httpc_set_error(httpc_conn_t * conn, int errcode, const char *format, ...) -{ - va_list ap; - - conn->errcode = errcode; - - va_start(ap, format); - vsprintf(conn->errmsg, format, ap); - va_end(ap); -} */ - -/*-------------------------------------------------- -FUNCTION: httpc_header_add_date +FUNCTION: httpc_header_set_date DESC: Adds the current date to the header. ----------------------------------------------------*/ static void -httpc_header_add_date(httpc_conn_t * conn) +httpc_header_set_date(httpc_conn_t * conn) { - char buffer[255]; - time_t nw; + char buffer[32]; + time_t ts; struct tm stm; - /* Set date */ - nw = time(NULL); - localtime_r(&nw, &stm); - strftime(buffer, 255, "%a, %d %b %Y %H:%M:%S GMT", &stm); + ts = time(NULL); + localtime_r(&ts, &stm); + strftime(buffer, 32, "%a, %d %b %Y %H:%M:%S GMT", &stm); + httpc_set_header(conn, HEADER_DATE, buffer); + return; } @@ -254,25 +243,21 @@ in conn through conn->sock. herror_t httpc_send_header(httpc_conn_t * conn) { - hpair_t *p; + hpair_t *walker; herror_t status; char buffer[1024]; - p = conn->header; - while (p != NULL) + for (walker = conn->header; walker; walker = walker->next) { - if (p->key && p->value) + if (walker->key && walker->value) { - sprintf(buffer, "%s: %s\r\n", p->key, p->value); - status = hsocket_send(conn->sock, buffer); - if (status != H_OK) + sprintf(buffer, "%s: %s\r\n", walker->key, walker->value); + if ((status = hsocket_send(conn->sock, buffer)) != H_OK) return status; } - p = p->next; } - status = hsocket_send(conn->sock, "\r\n"); - return status; + return hsocket_send(conn->sock, "\r\n"); } /*-------------------------------------------------- @@ -335,11 +320,9 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, GENERAL_INVALID_PARAM, "httpc_conn_t param is NULL"); } /* Build request header */ - httpc_header_add_date(conn); + httpc_header_set_date(conn); - /* Create url */ - status = hurl_parse(&url, urlstr); - if (status != H_OK) + if ((status = hurl_parse(&url, urlstr)) != H_OK) { log_error2("Can not parse URL '%s'", SAVE_STR(urlstr)); return status; @@ -350,61 +333,42 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, httpc_set_header(conn, HEADER_HOST, url.host); /* Open connection */ - status = hsocket_open(&conn->sock, url.host, url.port); - if (status != H_OK) - { + if ((status = hsocket_open(&conn->sock, url.host, url.port)) != H_OK) return status; - } -#ifdef HAVE_SSL - /* TODO XXX XXX this is probably not right -- matt */ - if (!&conn->sock.ssl) - { - status = hsocket_block(conn->sock, conn->block); - if (status != H_OK) - { - log_error1("Cannot make socket non-blocking"); - return status; - } - } -#endif - /* check method */ - if (method == HTTP_REQUEST_GET) + + switch(method) { + case HTTP_REQUEST_GET: - /* Set GET Header */ - sprintf(buffer, "GET %s HTTP/%s\r\n", - (url.context[0] != '\0') ? url.context : ("/"), - (conn->version == HTTP_1_0) ? "1.0" : "1.1"); + sprintf(buffer, "GET %s HTTP/%s\r\n", + (url.context[0] != '\0') ? url.context : ("/"), + (conn->version == HTTP_1_0) ? "1.0" : "1.1"); + break; - } - else if (method == HTTP_REQUEST_POST) - { + case HTTP_REQUEST_POST: - /* Set POST Header */ - sprintf(buffer, "POST %s HTTP/%s\r\n", - (url.context[0] != '\0') ? url.context : ("/"), - (conn->version == HTTP_1_0) ? "1.0" : "1.1"); - } - else - { + sprintf(buffer, "POST %s HTTP/%s\r\n", + (url.context[0] != '\0') ? url.context : ("/"), + (conn->version == HTTP_1_0) ? "1.0" : "1.1"); + break; - log_error1("Unknown method type!"); - return herror_new("httpc_talk_to_server", - GENERAL_INVALID_PARAM, - "hreq_method_t must be HTTP_REQUEST_GET or HTTP_REQUEST_POST"); + default: + log_error1("Unknown method type!"); + return herror_new("httpc_talk_to_server", + GENERAL_INVALID_PARAM, + "hreq_method_t must be HTTP_REQUEST_GET or HTTP_REQUEST_POST"); } - log_verbose1("Sending header..."); - status = hsocket_send(conn->sock, buffer); - if (status != H_OK) + log_verbose1("Sending request..."); + if ((status = hsocket_send(conn->sock, buffer)) != H_OK) { log_error2("Can not send request (status:%d)", status); hsocket_close(conn->sock); return status; } - /* Send Header */ - status = httpc_send_header(conn); - if (status != H_OK) + + log_verbose1("Sending header..."); + if ((status = httpc_send_header(conn)) != H_OK) { log_error2("Can not send header (status:%d)", status); hsocket_close(conn->sock); @@ -412,7 +376,6 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, } return H_OK; - } /*-------------------------------------------------- @@ -424,19 +387,11 @@ httpc_get(httpc_conn_t * conn, hresponse_t ** out, const char *urlstr) { herror_t status; - status = httpc_talk_to_server(HTTP_REQUEST_GET, conn, urlstr); - - if (status != H_OK) - { + if ((status = httpc_talk_to_server(HTTP_REQUEST_GET, conn, urlstr)) != H_OK) return status; - } - status = hresponse_new_from_socket(conn->sock, out); - if (status != H_OK) - { + if ((status = hresponse_new_from_socket(conn->sock, out)) != H_OK) return status; - } - return H_OK; } @@ -449,11 +404,9 @@ DESC: Returns H_OK if success herror_t httpc_post_begin(httpc_conn_t * conn, const char *url) { - herror_t status; - status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, url); - if (status != H_OK) + if ((status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, url)) != H_OK) return status; conn->out = http_output_stream_new(conn->sock, conn->header); @@ -472,171 +425,15 @@ httpc_post_end(httpc_conn_t * conn, hresponse_t ** out) { herror_t status; - status = http_output_stream_flush(conn->out); - - if (status != H_OK) - { + if ((status = http_output_stream_flush(conn->out)) != H_OK) return status; - } - status = hresponse_new_from_socket(conn->sock, out); - if (status != H_OK) - { + if ((status = hresponse_new_from_socket(conn->sock, out)) != H_OK) return status; - } return H_OK; } - - -/* --------------------------------------------------- - DIME support functions httpc_dime_* function set ------------------------------------------------------*/ -/* -int httpc_dime_begin(httpc_conn_t *conn, const char *url) -{ - int status; - - httpc_set_header(conn, HEADER_CONTENT_TYPE, "application/dime"); - - status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, url); - if (status != H_OK) - return status; - - conn->out = http_output_stream_new(conn->sock, conn->header); - - return H_OK; -} - -static _print_binary_ascii(int n) -{ - int i,c=0; - char ascii[36]; - - for (i=0;i<32;i++) { - ascii[34-i-c] = (n & (1<_dime_package_nr == 0) - header[0] |= DIME_FIRST_PACKAGE; - - if (last) - header[0] |= DIME_LAST_PACKAGE; - - header[1] = DIME_TYPE_URI; - - tmp = strlen(dime_options); - header[2] = tmp >> 8; - header[3] = tmp; - - tmp = strlen(id); - header[4] = tmp >> 8; - header[5] = tmp; - - tmp = strlen(content_type); - header[6] = tmp >> 8; - header[7] = tmp; - - header[8] = (byte_t)content_length >> 24; - header[9] = (byte_t)content_length >> 16; - header[10] = (byte_t)content_length >> 8; - header[11] = (byte_t)content_length; - - - _print_binary_ascii32(header[0], header[1], header[2], header[3]); - _print_binary_ascii32(header[4], header[5], header[6], header[7]); - _print_binary_ascii32(header[8], header[9], header[10], header[11]); - - status = http_output_stream_write(conn->out, header, 12); - if (status != H_OK) - return status; - - status = http_output_stream_write(conn->out, (const byte_t*)dime_options, strlen(dime_options)); - if (status != H_OK) - return status; - - status = http_output_stream_write(conn->out, (const byte_t*)id, strlen(id)); - if (status != H_OK) - return status; - - status = http_output_stream_write(conn->out, (const byte_t*)content_type, strlen(content_type)); - if (status != H_OK) - return status; - - return status; -} - - -hresponse_t* httpc_dime_end(httpc_conn_t *conn) -{ - int status; - hresponse_t *res; - - Flush put stream - status = http_output_stream_flush(conn->out); - - if (status != H_OK) - { - _httpc_set_error(conn, status, "Can not flush output stream"); - return NULL; - } - - res = hresponse_new_from_socket(conn->sock); - if (res == NULL) - { - _httpc_set_error(conn, -1, "Can not get response "); - return NULL; - } - - return res; -} - -*/ /* --------------------------------------------------- MIME support functions httpc_mime_* function set -----------------------------------------------------*/ @@ -699,7 +496,6 @@ httpc_mime_begin(httpc_conn_t * conn, const char *url, return status; } - herror_t httpc_mime_next(httpc_conn_t * conn, const char *content_id, @@ -726,10 +522,8 @@ httpc_mime_next(httpc_conn_t * conn, HEADER_CONTENT_TRANSFER_ENCODING, transfer_encoding, HEADER_CONTENT_ID, content_id); - status = http_output_stream_write(conn->out, + return http_output_stream_write(conn->out, (const byte_t *) buffer, strlen(buffer)); - - return status; } @@ -751,22 +545,13 @@ httpc_mime_end(httpc_conn_t * conn, hresponse_t ** out) if (status != H_OK) return status; - /* Flush put stream */ - status = http_output_stream_flush(conn->out); - - if (status != H_OK) - { + if ((status = http_output_stream_flush(conn->out)) != H_OK) return status; - } - status = hresponse_new_from_socket(conn->sock, out); - if (status != H_OK) - { + if ((status = hresponse_new_from_socket(conn->sock, out)) != H_OK) return status; - } return H_OK; - } diff --git a/nanohttp/nanohttp-client.h b/nanohttp/nanohttp-client.h index 03e1e16..221ae34 100644 --- a/nanohttp/nanohttp-client.h +++ b/nanohttp/nanohttp-client.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-client.h,v 1.19 2006/02/08 11:13:14 snowdrop Exp $ + * $Id: nanohttp-client.h,v 1.20 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -44,7 +44,6 @@ typedef struct httpc_conn char errmsg[150]; http_output_stream_t *out; int id; /* uniq id */ - int block; } httpc_conn_t; diff --git a/nanohttp/nanohttp-common.c b/nanohttp/nanohttp-common.c index d7b1f27..1f2040d 100644 --- a/nanohttp/nanohttp-common.c +++ b/nanohttp/nanohttp-common.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-common.c,v 1.26 2006/02/09 13:43:49 mrcsys Exp $ +* $Id: nanohttp-common.c,v 1.27 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,17 +21,31 @@ * * Email: ayaz@jprogrammer.net ******************************************************************/ +#ifdef HAVE_CONFIG_H +#include +#endif -#include - - +#ifdef HAVE_STDIO_H #include +#endif + +#ifdef HAVE_STDLIB_H #include +#endif + +#ifdef HAVE_STDARG_H #include +#endif + +#ifdef HAVE_STRING_H #include +#endif + +#ifdef HAVE_CTYPE_H #include +#endif -#ifndef WIN32 +#ifdef HAVE_PTHREAD_H #include #endif @@ -39,19 +53,35 @@ #include #endif +#include #define MAX_OPTION_SIZE 50 #define MAX_OPTION_VALUE_SIZE 150 static char _hoption_table[MAX_OPTION_SIZE][MAX_OPTION_VALUE_SIZE]; -#ifdef HAVE_SSL -/*extern char *SSLCert; -extern char *SSLPass; -extern char *SSLCA; -extern int SSLCertLess; -*/ -#endif +static int +strcmpigcase(const char *s1, const char *s2) +{ + int l1, l2, i; + + if (s1 == NULL && s2 == NULL) + return 1; + if (s1 == NULL || s2 == NULL) + return 0; + + l1 = strlen(s1); + l2 = strlen(s2); + + if (l1 != l2) + return 0; + + for (i = 0; i < l1; i++) + if (toupper(s1[i]) != toupper(s2[i])) + return 0; + + return 1; +} /* option stuff */ void @@ -64,6 +94,8 @@ hoption_set(int opt, const char *value) } strncpy(_hoption_table[opt], value, MAX_OPTION_VALUE_SIZE); + + return; } @@ -173,7 +205,6 @@ typedef struct _herror_impl_t char func[100]; } herror_impl_t; - herror_t herror_new(const char *func, int errcode, const char *format, ...) { @@ -363,32 +394,6 @@ log_error(const char *FUNC, const char *format, ...) } -/* ----------------------------------------- - FUNCTION: strcmpigcase - ------------------------------------------*/ -int -strcmpigcase(const char *s1, const char *s2) -{ - int l1, l2, i; - - if (s1 == NULL && s2 == NULL) - return 1; - if (s1 == NULL || s2 == NULL) - return 0; - - l1 = strlen(s1); - l2 = strlen(s2); - - if (l1 != l2) - return 0; - - for (i = 0; i < l1; i++) - if (toupper(s1[i]) != toupper(s2[i])) - return 0; - - return 1; -} - hpair_t * hpairnode_new(const char *key, const char *value, hpair_t * next) @@ -607,7 +612,6 @@ hurl_dump(const hurl_t * url) log_verbose2(" CONTEXT : %s", url->context); } - herror_t hurl_parse(hurl_t * url, const char *urlstr) { diff --git a/nanohttp/nanohttp-common.h b/nanohttp/nanohttp-common.h index 607fc2b..d982d51 100644 --- a/nanohttp/nanohttp-common.h +++ b/nanohttp/nanohttp-common.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-common.h,v 1.24 2006/01/18 16:28:24 mrcsys Exp $ + * $Id: nanohttp-common.h,v 1.25 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -39,6 +39,8 @@ #define HEADER_DATE "Date" #define HEADER_ACCEPT "Accept" +#define HEADER_AUTHORIZATION "Authorization" +#define HEADER_WWW_AUTHENTICATE "WWW-Authenticate" #define NHTTPD_ARG_PORT "-NHTTPport" #define NHTTPD_ARG_TERMSIG "-NHTTPtsig" @@ -189,15 +191,6 @@ char *herror_func(herror_t err); char *herror_message(herror_t err); void herror_release(herror_t err); - -/* - string function to compare strings ignoring case - Returns 1 if s1 equals s2 and 0 otherwise. - */ -int strcmpigcase(const char *s1, const char *s2); - - - /* hpairnode_t represents a pair (key, value) pair. This is also a linked list. diff --git a/nanohttp/nanohttp-mime.c b/nanohttp/nanohttp-mime.c index 5ca7df9..10926fe 100755 --- a/nanohttp/nanohttp-mime.c +++ b/nanohttp/nanohttp-mime.c @@ -3,7 +3,7 @@ * | \/ | | | | \/ | | _/ * |_''_| |_| |_''_| |_'/ PARSER * -* $Id: nanohttp-mime.c,v 1.9 2006/01/10 11:29:05 snowdrop Exp $ +* $Id: nanohttp-mime.c,v 1.10 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -25,12 +25,17 @@ * * Email: ferhatayaz@yahoo.com ******************************************************************/ +#ifdef HAVE_CONFIG_H +#include +#endif - - -#include +#ifdef HAVE_STDIO_H #include +#endif + +#ifdef HAVE_STRING_H #include +#endif /*---------------------------------------------------------------- Buffered Reader. A helper object to read bytes from a source @@ -40,6 +45,7 @@ Buffered Reader. A helper object to read bytes from a source #include #endif +#include /* ------------------------------------------------------------------ diff --git a/nanohttp/nanohttp-request.c b/nanohttp/nanohttp-request.c index 1bd8a1d..98880f2 100755 --- a/nanohttp/nanohttp-request.c +++ b/nanohttp/nanohttp-request.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-request.c,v 1.9 2006/01/11 10:54:43 snowdrop Exp $ +* $Id: nanohttp-request.c,v 1.10 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,16 +21,21 @@ * * Email: ayaz@jprogrammer.net ******************************************************************/ +#ifdef HAVE_CONFIG_H +#include +#endif -#include -#include - +#ifdef HAVE_STRING_H #include +#endif #ifdef MEM_DEBUG #include #endif +#include +#include + /* request stuff */ @@ -197,7 +202,7 @@ _hrequest_parse_header(char *data) } /* Check Content-type */ - tmp = hpairnode_get(req->header, HEADER_CONTENT_TYPE); + tmp = hpairnode_get_ignore_case(req->header, HEADER_CONTENT_TYPE); if (tmp != NULL) req->content_type = content_type_new(tmp); diff --git a/nanohttp/nanohttp-response.c b/nanohttp/nanohttp-response.c index 2253640..cf728e4 100755 --- a/nanohttp/nanohttp-response.c +++ b/nanohttp/nanohttp-response.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-response.c,v 1.7 2006/01/10 11:29:05 snowdrop Exp $ +* $Id: nanohttp-response.c,v 1.8 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -21,16 +21,21 @@ * * Email: ferhatayaz@yahoo.com ******************************************************************/ +#ifdef HAVE_CONFIG_H +#include +#endif -#include -#include - +#ifdef HAVE_STRING_H #include +#endif #ifdef MEM_DEBUG #include #endif +#include +#include + static hresponse_t * hresponse_new() { diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c index e063045..19d741a 100644 --- a/nanohttp/nanohttp-server.c +++ b/nanohttp/nanohttp-server.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-server.c,v 1.48 2006/02/08 11:13:14 snowdrop Exp $ +* $Id: nanohttp-server.c,v 1.49 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,44 +21,62 @@ * * Email: ayaz@jprogrammer.net ******************************************************************/ -#include -#include - -#include -#include -#include -#include - #ifdef HAVE_CONFIG_H #include #endif -#ifndef WIN32 - -/* According to POSIX 1003.1-2001 */ +#ifdef HAVE_SYS_SELECT_H #include +#endif -/* According to earlier standards */ +#ifdef HAVE_SYS_TIME_H #include +#endif + +#ifdef HAVE_SYS_TYPES_H #include +#endif + +#ifdef HAVE_STDIO_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_SIGNAL_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_UNISTD_H #include +#endif +#ifdef HAVE_PTHREAD_H #include +#endif -#ifdef HAVE_SOCKET +#ifdef HAVE_SOCKET_H #include #endif -#else - +#ifdef WIN32 #include - +#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2) #endif #ifdef MEM_DEBUG #include #endif +#include "nanohttp-server.h" +#include "nanohttp-base64.h" +#include "nanohttp-ssl.h" typedef struct _conndata { @@ -81,26 +99,21 @@ conndata_t; */ static int _httpd_port = 10000; static int _httpd_max_connections = 20; -#ifdef WIN32 -static int _httpd_max_idle = 120; -#endif static hsocket_t _httpd_socket; static hservice_t *_httpd_services_default = NULL; static hservice_t *_httpd_services_head = NULL; static hservice_t *_httpd_services_tail = NULL; static int _httpd_run = 1; -#ifdef WIN32 -static DWORD _httpd_terminate_signal = CTRL_C_EVENT; -#else -static int _httpd_terminate_signal = SIGINT; -#endif static conndata_t *_httpd_connection; - #ifdef WIN32 +static DWORD _httpd_terminate_signal = CTRL_C_EVENT; +static int _httpd_max_idle = 120; static void WSAReaper (void *x); +#define strncasecmp(s1, s2, num) strncmp(s1, s2, num) #else -sigset_t thrsigset; +static int _httpd_terminate_signal = SIGINT; +static sigset_t thrsigset; #endif #ifdef HAVE_SSL @@ -125,8 +138,7 @@ httpd_init (int argc, char *argv[]) hoption_init_args (argc, argv); - status = hsocket_module_init (); - if (status != H_OK) + if ((status = hsocket_module_init()) != H_OK) return status; /* write argument information */ @@ -171,19 +183,18 @@ httpd_init (int argc, char *argv[]) */ #endif -#ifdef HAVE_SSL - start_ssl(); -#endif - /* create socket */ #ifdef HAVE_SSL SSLCert = hoption_get(HOPTION_SSL_CERT); SSLPass = hoption_get(HOPTION_SSL_PASS); SSLCA = hoption_get(HOPTION_SSL_CA); log_verbose3("SSL: %s %s", SSLCert, SSLCA); - if(SSLCert[0] != '\0'){ - status = hsocket_init_ssl(&_httpd_socket, SSLCert, SSLPass, SSLCA); - } else + if (SSLCert[0] != '\0'){ + + start_ssl(); + status = hsocket_init_ssl(&_httpd_socket, SSLCert, SSLPass, SSLCA); + } + else #endif { status = hsocket_init (&_httpd_socket); @@ -193,9 +204,8 @@ httpd_init (int argc, char *argv[]) { return status; } - status = hsocket_bind (&_httpd_socket, _httpd_port); - return status; + return hsocket_bind (&_httpd_socket, _httpd_port); } /* @@ -205,12 +215,18 @@ httpd_init (int argc, char *argv[]) */ int -httpd_register (const char *ctx, httpd_service func) +httpd_register_secure(const char *ctx, httpd_service func, httpd_auth auth) { hservice_t *service; - service = (hservice_t *) malloc (sizeof (hservice_t)); + if (!(service = (hservice_t *) malloc (sizeof (hservice_t)))) + { + log_error1("malloc failed"); + return -1; + } + service->next = NULL; + service->auth = auth; service->func = func; strcpy (service->ctx, ctx); @@ -229,11 +245,17 @@ httpd_register (const char *ctx, httpd_service func) } int -httpd_register_default (const char *ctx, httpd_service func) +httpd_register(const char *ctx, httpd_service service) +{ + return httpd_register_secure(ctx, service, NULL); +} + +int +httpd_register_default_secure(const char *ctx, httpd_service service, httpd_auth auth) { int ret; - ret = httpd_register(ctx, func); + ret = httpd_register_secure(ctx, service, auth); /* this is broken, but working */ _httpd_services_default = _httpd_services_tail; @@ -241,6 +263,12 @@ httpd_register_default (const char *ctx, httpd_service func) return ret; } +int +httpd_register_default(const char *ctx, httpd_service service) +{ + return httpd_register_default_secure(ctx, service, NULL); +} + int httpd_get_port(void) { @@ -325,9 +353,8 @@ httpd_send_header (httpd_conn_t * res, int code, const char *text) /* set date */ nw = time (NULL); localtime_r (&nw, &stm); - strftime (buffer, 255, "Date: %a, %d %b %Y %H:%M:%S GMT", &stm); + strftime (buffer, 255, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", &stm); strcat (header, buffer); - strcat (header, "\r\n"); /* set content-type */ /* @@ -343,20 +370,17 @@ httpd_send_header (httpd_conn_t * res, int code, const char *text) // strcat (header, "Connection: close\r\n"); /* add pairs */ - cur = res->header; - while (cur != NULL) + for(cur = res->header; cur; cur = cur->next) { sprintf (buffer, "%s: %s\r\n", cur->key, cur->value); strcat (header, buffer); - cur = cur->next; } /* set end of header */ strcat (header, "\r\n"); /* send header */ - status = hsocket_nsend (res->sock, header, strlen (header)); - if (status != 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); @@ -373,9 +397,6 @@ httpd_send_internal_error (httpd_conn_t * conn, const char *errmsg) char buffer[4064]; char buflen[5]; sprintf (buffer, template1, errmsg); -#ifdef WIN32 -#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2) -#endif snprintf (buflen, 5, "%d", strlen (buffer)); httpd_set_header (conn, HEADER_CONTENT_LENGTH, buflen); httpd_send_header (conn, 500, "INTERNAL"); @@ -435,7 +456,7 @@ void httpd_free (httpd_conn_t * conn) { if(!conn) - return; + return; if (conn->out != NULL) http_output_stream_free (conn->out); @@ -464,6 +485,61 @@ do_req_timeout (int signum) #endif } +static int httpd_decode_authorization(const char *value, char **user, char **pass) +{ + + unsigned char *tmp, *tmp2; + + tmp = malloc(strlen(value) * 2); + bzero(tmp, strlen(value) * 2); + + value = index(value, ' '); + value++; + log_debug2("Authorization (base64) = \"%s\"", value); + + base64_decode(value, tmp); + + log_debug2("Authorization (ascii) = \"%s\"", tmp); + + tmp2 = index(tmp, ':'); + *tmp2++ = '\0'; + + *pass = strdup(tmp2); + *user = strdup(tmp); + + free(tmp); + + return 1; +} + +static int httpd_authenticate_request(hrequest_t *req, httpd_auth auth) +{ + char *user, *pass; + char *authorization; + int ret; + + if (!auth) + return 1; + + if (!(authorization = hpairnode_get_ignore_case(req->header, HEADER_AUTHORIZATION))) { + return 0; + } + + if (!httpd_decode_authorization(authorization, &user, &pass)) + { + log_error1("httpd_base64_decode_failed"); + return 0; + } + + if (!(ret = auth(user, pass))) + log_info1("Authentication failed"); + + free(user); + free(pass); + + return ret; +} + /* * ----------------------------------------------------- * FUNCTION: httpd_session_main @@ -515,28 +591,22 @@ httpd_session_main (void *data) while (!done) { log_verbose1 ("starting HTTP request"); - rconn = httpd_new (conn->sock); - status = hrequest_new_from_socket (conn->sock, &req); + rconn = httpd_new (conn->sock); - if (status != H_OK) + if ((status = hrequest_new_from_socket (conn->sock, &req)) != H_OK) { + /* "Request parse error!" */ if (herror_code (status) != HSOCKET_ERROR_SSLCLOSE) { - httpd_send_internal_error (rconn, herror_message (status) /* "Request - parse - error!" */ ); + httpd_send_internal_error (rconn, herror_message (status)); herror_release (status); } done = 1; } else { - char *conn_str = - hpairnode_get_ignore_case (req->header, HEADER_CONNECTION); -#ifdef WIN32 -#define strncasecmp(s1, s2, num) strncmp(s1, s2, num) -#endif + char *conn_str = hpairnode_get_ignore_case (req->header, HEADER_CONNECTION); if (conn_str && strncasecmp (conn_str, "close", 5) == 0) { done = 1; @@ -547,29 +617,34 @@ httpd_session_main (void *data) } httpd_request_print (req); - service = httpd_find_service (req->path); if (service != NULL) { - log_verbose2 ("service '%s' found", req->path); - if (service->func != NULL) - { - service->func (rconn, req); - if (rconn->out - && rconn->out->type == HTTP_TRANSFER_CONNECTION_CLOSE) + log_verbose3 ("service '%s' for '%s' found", service->ctx, req->path); + + if (httpd_authenticate_request(req, service->auth)) { + + if (service->func != NULL) { - log_verbose1 ("Connection close requested"); - done = 1; + service->func (rconn, req); + if (rconn->out && rconn->out->type == HTTP_TRANSFER_CONNECTION_CLOSE) { + log_verbose1 ("Connection close requested"); + done = 1; + } + } + else + { + sprintf (buffer, "service '%s' not registered properly (func == NULL)", req->path); + log_verbose1 (buffer); + httpd_send_internal_error (rconn, buffer); } } - else - { - sprintf (buffer, - "service '%s' not registered properly (func == NULL)", - req->path); - log_verbose1 (buffer); - httpd_send_internal_error (rconn, buffer); - } + else { + + httpd_set_header(rconn, HEADER_WWW_AUTHENTICATE, "Basic realm=\"nanoHTTP\""); + httpd_send_header(rconn, 401, "Unauthorized"); + hsocket_send(conn->sock, "Unauthorized

Unauthorized

"); + } } else { @@ -577,9 +652,6 @@ httpd_session_main (void *data) log_verbose1 (buffer); httpd_send_internal_error (rconn, buffer); } - - /* httpd_response_free(res); */ - /* hrequest_free (req); */ } } @@ -588,13 +660,14 @@ httpd_session_main (void *data) conn->sock.sock = 0; hrequest_free (req); httpd_free (rconn); + #ifdef WIN32 CloseHandle ((HANDLE) conn->tid); _endthread (); return 0; #else - pthread_exit (NULL); - return service; + /* pthread_exits automagically */ + return NULL; #endif } @@ -696,14 +769,13 @@ httpd_term (int sig) #endif - /* * ----------------------------------------------------- * FUNCTION: _httpd_register_signal_handler * ----------------------------------------------------- */ static void -_httpd_register_signal_handler () +_httpd_register_signal_handler (void) { log_verbose2 ("registering termination signal handler (SIGNAL:%d)", _httpd_terminate_signal); @@ -716,16 +788,15 @@ _httpd_register_signal_handler () #else signal (_httpd_terminate_signal, httpd_term); #endif -} - - + return; +} /*-------------------------------------------------- FUNCTION: _httpd_wait_for_empty_conn ----------------------------------------------------*/ static conndata_t * -_httpd_wait_for_empty_conn () +_httpd_wait_for_empty_conn (void) { int i; for (i = 0;; i++) @@ -758,25 +829,22 @@ _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)); + #ifdef PTHREAD_CREATE_DETACHED pthread_attr_setdetachstate (&(conn->attr), PTHREAD_CREATE_DETACHED); #endif + pthread_sigmask (SIG_BLOCK, &thrsigset, NULL); - err = - pthread_create (&(conn->tid), &(conn->attr), httpd_session_main, conn); + err = pthread_create (&(conn->tid), &(conn->attr), httpd_session_main, conn); if (err) - { log_error2 ("Error creating thread: ('%d')", err); - } #endif } - /* * ----------------------------------------------------- * FUNCTION: httpd_run @@ -784,28 +852,25 @@ _httpd_start_thread (conndata_t * conn) */ herror_t -httpd_run () +httpd_run (void) { herror_t err; conndata_t *conn; fd_set fds; struct timeval timeout; - log_verbose1 ("starting run routine"); timeout.tv_sec = 1; timeout.tv_usec = 0; -#ifdef WIN32 -#else + +#ifndef WIN32 sigemptyset (&thrsigset); sigaddset (&thrsigset, SIGALRM); #endif - /* listen to port */ - err = hsocket_listen (_httpd_socket); - if (err != H_OK) + if ((err = hsocket_listen (_httpd_socket)) != H_OK) { log_error2 ("httpd_run(): '%d'", herror_message (err)); return err; @@ -816,14 +881,12 @@ httpd_run () _httpd_register_signal_handler (); /* make the socket non blocking */ - err = hsocket_block (_httpd_socket, 0); - if (err != H_OK) + if ((err = hsocket_block (_httpd_socket, 0)) != H_OK) { log_error2 ("httpd_run(): '%s'", herror_message (err)); return err; } - while (_httpd_run) { /* Get an empty connection struct */ @@ -870,15 +933,14 @@ httpd_run () /* Accept a socket */ err = hsocket_accept (_httpd_socket, &(conn->sock)); if (err != H_OK - /* TODO (#1#) is this check neccessary? - && herror_code (err) == SSL_ERROR_INIT*/ - ) + /* TODO (#1#) is this check neccessary? + && herror_code (err) == SSL_ERROR_INIT*/ + ) { hsocket_close (conn->sock); - conn->sock.sock = -1; -#ifdef HAVE_SSL - conn->sock.ssl = NULL; -#endif + + hsocket_init(&(conn->sock)); + log_error1 (herror_message (err)); continue; } @@ -896,7 +958,7 @@ httpd_run () } void -httpd_destroy () +httpd_destroy (void) { hservice_t *tmp, *cur = _httpd_services_head; @@ -908,6 +970,8 @@ httpd_destroy () } hsocket_module_destroy (); + + return; } #ifdef WIN32 @@ -969,8 +1033,7 @@ 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); @@ -1020,6 +1083,8 @@ _httpd_mime_get_boundary (httpd_conn_t * conn, char *dest) { sprintf (dest, "---=.Part_NH_%p", conn); log_verbose2 ("boundary= \"%s\"", dest); + + return; } @@ -1028,23 +1093,14 @@ _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;"); @@ -1081,9 +1137,7 @@ httpd_mime_send_header (httpd_conn_t * conn, 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]; @@ -1094,9 +1148,7 @@ httpd_mime_next (httpd_conn_t * conn, 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; @@ -1109,9 +1161,7 @@ httpd_mime_next (httpd_conn_t * conn, 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; } @@ -1121,22 +1171,17 @@ httpd_mime_next (httpd_conn_t * conn, 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) { - herror_t status; - FILE *fd = fopen (filename, "rb"); byte_t buffer[MAX_FILE_BUFFER_SIZE]; + herror_t status; + FILE *fd; size_t size; - if (fd == 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); @@ -1149,8 +1194,7 @@ httpd_mime_send_file (httpd_conn_t * conn, if (size == -1) { fclose (fd); - return herror_new ("httpd_mime_send_file", FILE_ERROR_READ, - "Can not read from file '%d'", filename); + return herror_new ("httpd_mime_send_file", FILE_ERROR_READ, "Can not read from file '%d'", filename); } status = http_output_stream_write (conn->out, buffer, size); @@ -1181,9 +1225,7 @@ httpd_mime_end (httpd_conn_t * conn) 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; diff --git a/nanohttp/nanohttp-server.h b/nanohttp/nanohttp-server.h index ccafe8f..4c50d23 100644 --- a/nanohttp/nanohttp-server.h +++ b/nanohttp/nanohttp-server.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-server.h,v 1.12 2006/02/08 11:13:14 snowdrop Exp $ + * $Id: nanohttp-server.h,v 1.13 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -45,7 +45,7 @@ typedef struct httpd_conn Service callback */ typedef void (*httpd_service) (httpd_conn_t *, hrequest_t *); - +typedef int (*httpd_auth) (const char *user, const char *password); /* * Service representation object @@ -54,6 +54,7 @@ typedef struct tag_hservice { char ctx[255]; httpd_service func; + httpd_auth auth; struct tag_hservice *next; } hservice_t; @@ -63,7 +64,13 @@ typedef struct tag_hservice Begin httpd_* function set */ herror_t httpd_init(int argc, char *argv[]); + 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_secure_default(const char *ctx, httpd_service service, httpd_auth auth); + herror_t httpd_run(); void httpd_destroy(); diff --git a/nanohttp/nanohttp-socket.c b/nanohttp/nanohttp-socket.c index e2c9312..cdcfea0 100644 --- a/nanohttp/nanohttp-socket.c +++ b/nanohttp/nanohttp-socket.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-socket.c,v 1.48 2006/02/09 13:47:21 mrcsys Exp $ +* $Id: nanohttp-socket.c,v 1.49 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,25 +21,8 @@ * * Email: ferhatayaz@yahoo.com ******************************************************************/ -#include -#include -#include - -#ifdef WIN32 -#include "wsockcompat.h" -#include -#include - -#ifndef __MINGW32__ -typedef int ssize_t; -#endif - -#else -#include -#endif - #ifdef HAVE_CONFIG_H -#include "config.h" +#include #endif #ifdef HAVE_SYS_TYPES_H @@ -50,7 +33,7 @@ typedef int ssize_t; #include #endif -#ifndef WIN32 +#ifdef HAVE_NETINET_IN_H #include #endif @@ -58,6 +41,10 @@ typedef int ssize_t; #include #endif +#ifdef HAVE_FCNTL_H +#include +#endif + #ifdef HAVE_NETDB_H #include #endif @@ -66,20 +53,39 @@ typedef int ssize_t; #include #endif +#ifdef HAVE_STDIO_H #include -#include -#include +#endif -#ifdef MEM_DEBUG -#include +#ifdef HAVE_ERRNO_H +#include #endif +#ifdef HAVE_STRING_H +#include +#endif #ifdef WIN32 +#include "wsockcompat.h" +#include +#include + +#ifndef __MINGW32__ +typedef int ssize_t; +#endif + #undef errno #define errno WSAGetLastError() + #endif +#ifdef MEM_DEBUG +#include +#endif + +#include "nanohttp-socket.h" +#include "nanohttp-common.h" +#include "nanohttp-ssl.h" #ifdef HAVE_SSL /*SSL_CTX *SSLctx = NULL; @@ -100,10 +106,12 @@ hsocket_module_init() #ifdef WIN32 struct WSAData info; WSAStartup(MAKEWORD(2, 2), &info); +#endif + +#ifdef HAVE_SSL + start_ssl(); +#endif -#else /* */ - /* nothing to init for unix sockets */ -#endif /* */ return H_OK; } @@ -115,10 +123,9 @@ hsocket_module_destroy() { #ifdef WIN32 WSACleanup(); +#endif -#else /* */ - /* nothing to destroy for unix sockets */ -#endif /* */ + return; } /*-------------------------------------------------- @@ -128,13 +135,9 @@ herror_t hsocket_init(hsocket_t * sock) { log_verbose1("Starting hsocket init"); - /* just set the descriptor to -1 */ - sock->sock = -1; -#ifdef HAVE_SSL - sock->ssl = NULL; - sock->sslCtx = NULL; -#endif + bzero(sock, sizeof(hsocket_t)); + sock->sock = -1; return H_OK; } @@ -172,6 +175,7 @@ void hsocket_free(hsocket_t sock) { /* nothing to free for unix sockets */ + return; } /*-------------------------------------------------- @@ -185,14 +189,12 @@ hsocket_open(hsocket_t * dsock, const char *hostname, int port) struct sockaddr_in address; struct hostent *host; - sock.sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock.sock <= 0) + if ((sock.sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0) return herror_new("hsocket_open", HSOCKET_ERROR_CREATE, "Socket error: %d", errno); /* Get host data */ - host = gethostbyname(hostname); - if (host == NULL) + if (!(host = gethostbyname(hostname))) return herror_new("hsocket_open", HSOCKET_ERROR_GET_HOSTNAME, "Socket error: %d", errno); @@ -218,10 +220,17 @@ hsocket_open(hsocket_t * dsock, const char *hostname, int port) } else { + herror_t status; log_verbose1("Using HTTPS"); dsock->ssl = init_ssl(dsock->sslCtx, sock.sock, SSL_CLIENT); + if ((status = hsocket_block(*dsock, dsock->block)) != H_OK) + { + log_error1("Cannot make socket non-blocking"); + return status; + } } #endif + return H_OK; } @@ -236,8 +245,7 @@ hsocket_bind(hsocket_t * dsock, int port) int opt = 1; /* create socket */ - sock.sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock.sock == -1) + if ((sock.sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { log_error3("Can not create socket: '%s'", "Socket error: %d", errno); return herror_new("hsocket_bind", HSOCKET_ERROR_CREATE, @@ -330,45 +338,6 @@ hsocket_listen(hsocket_t sock) return H_OK; } -#if 0 -static void -_hsocket_wait_until_receive(hsocket_t sock) -{ - fd_set fds; - struct timeval timeout; - - - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - while (1) - { - log_verbose1("waiting until receive mode"); - /* zero and set file descriptior */ - FD_ZERO(&fds); - FD_SET(sock, &fds); - - /* select socket descriptor */ - switch (select(sock + 1, &fds, NULL, NULL, &timeout)) - { - case 0: - /* descriptor is not ready */ - continue; - case -1: - /* got a signal? */ - continue; - default: - /* no nothing */ - break; - } - if (FD_ISSET(sock, &fds)) - { - break; - } - } -} -#endif - /*-------------------------------------------------- FUNCTION: hsocket_close ----------------------------------------------------*/ @@ -390,11 +359,9 @@ hsocket_close(hsocket_t sock) #ifdef WIN32 /* shutdown(sock,SD_RECEIVE); */ - shutdown(sock.sock, SD_SEND); - while (recv(sock.sock, junk, sizeof(junk), 0) > 0) - { - }; + while (recv(sock.sock, junk, sizeof(junk), 0) > 0) ; + /* nothing */ closesocket(sock.sock); #else @@ -405,40 +372,21 @@ hsocket_close(hsocket_t sock) { log_verbose1("Closing SSL"); ssl_cleanup(sock.ssl); - shutdown(sock.sock, SHUT_RDWR); - while (recv(sock.sock, junk, sizeof(junk), 0) > 0) - { - }; - close(sock.sock); - } - else - { -#endif - shutdown(sock.sock, SHUT_RDWR); - while (recv(sock.sock, junk, sizeof(junk), 0) > 0) - { - }; - close(sock.sock); -#ifdef HAVE_SSL + sock.ssl = NULL; } #endif + + shutdown(sock.sock, SHUT_RDWR); + while (recv(sock.sock, junk, sizeof(junk), 0) > 0) ; + /* nothing */ + close(sock.sock); #endif + log_verbose1("socket closed"); -} -#if 0 -static int -_test_send_to_file(const char *filename, const byte_t * bytes, int n) -{ - int size; - FILE *f = fopen(filename, "ab"); - if (!f) - f = fopen(filename, "wb"); - size = fwrite(bytes, 1, n, f); - fclose(f); - return size; + return; } -#endif + /*-------------------------------------------------- FUNCTION: hsocket_send ----------------------------------------------------*/ @@ -448,12 +396,8 @@ hsocket_nsend(hsocket_t sock, const byte_t * bytes, int n) int size; int total = 0; - log_verbose1("Starting to send"); -#ifdef HAVE_SSL - if (sock.sock <= 0 && !sock.ssl) -#else + log_verbose2("Starting to send on sock=%p", &sock); if (sock.sock <= 0) -#endif return herror_new("hsocket_nsend", HSOCKET_ERROR_NOT_INITIALIZED, "Called hsocket_listen() before initializing!"); @@ -463,6 +407,7 @@ hsocket_nsend(hsocket_t sock, const byte_t * bytes, int n) while (1) { #ifdef HAVE_SSL + log_verbose2("ssl = %p", sock.ssl); if (sock.ssl) { size = SSL_write(sock.ssl, bytes + total, n); @@ -542,24 +487,27 @@ hsocket_read(hsocket_t sock, byte_t * buffer, int total, int force, FD_SET(sock.sock, &fds); timeout.tv_sec = 10; timeout.tv_usec = 0; -#ifdef WIN32 -#else +#ifndef WIN32 fcntl(sock.sock, F_SETFL, O_NONBLOCK); #endif /* log_verbose1("START READ LOOP"); do{ log_verbose2("DEBUG A %d",i); */ status = SSL_read(sock.ssl, &buffer[totalRead], total - totalRead); - log_verbose2("DEBUG SSL_read %d",status); - if (SSL_get_error(sock.ssl, status) == SSL_ERROR_ZERO_RETURN || - SSL_get_error(sock.ssl, status) == SSL_ERROR_SSL || - SSL_get_error(sock.ssl, status) == SSL_ERROR_SYSCALL || - SSL_get_error(sock.ssl, status) == SSL_ERROR_SSL || - SSL_get_shutdown(sock.ssl) == SSL_RECEIVED_SHUTDOWN ) - { - log_verbose1("SSL Error"); - return herror_new("hsocket_read", HSOCKET_ERROR_SSLCLOSE, "SSL Error"); + log_verbose2("DEBUG SSL_read %d",status); + + switch (SSL_get_error(sock.ssl, status)) { + case SSL_ERROR_ZERO_RETURN: + case SSL_ERROR_SSL: + case SSL_ERROR_SYSCALL: + log_verbose1("SSL Error"); + return herror_new("hsocket_read", HSOCKET_ERROR_SSLCLOSE, "SSL Error"); + } + if (SSL_get_shutdown(sock.ssl) == SSL_RECEIVED_SHUTDOWN) { + log_verbose1("SSL shutdown error"); + return herror_new("hsocket_read", HSOCKET_ERROR_SSLCLOSE, "SSL shutdown error"); } + if (status < 1) { int ret = select(sock.sock + 1, &fds, NULL, NULL, &timeout); @@ -588,8 +536,7 @@ hsocket_read(hsocket_t sock, byte_t * buffer, int total, int force, buffer[totalRead], SSL_get_error(sock.ssl, status));*/ } /* } while( SSL_get_error(sock.ssl, status) == SSL_ERROR_WANT_READ); */ -#ifdef WIN32 -#else +#ifndef WIN32 fcntl(sock.sock, F_SETFL, 0); #endif } @@ -618,14 +565,6 @@ hsocket_read(hsocket_t sock, byte_t * buffer, int total, int force, } #else } -/* - switch (errno) { - case EWOULDBLOCK: - case EALREADY: - case EINPROGRESS: - return true; - } -*/ #ifdef HAVE_SSL if (sock.ssl && status < 1) diff --git a/nanohttp/nanohttp-socket.h b/nanohttp/nanohttp-socket.h index e0228e9..3c4529d 100644 --- a/nanohttp/nanohttp-socket.h +++ b/nanohttp/nanohttp-socket.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-socket.h,v 1.21 2006/01/11 10:54:43 snowdrop Exp $ + * $Id: nanohttp-socket.h,v 1.22 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -53,6 +53,7 @@ typedef struct hsocket_t #else int sock; #endif + int block; } hsocket_t; /* end of socket definition */ diff --git a/nanohttp/nanohttp-ssl.c b/nanohttp/nanohttp-ssl.c index b0f3aa2..85c8ca2 100644 --- a/nanohttp/nanohttp-ssl.c +++ b/nanohttp/nanohttp-ssl.c @@ -24,12 +24,18 @@ /* Enter only if --with-ssl was specified to the configure script */ #ifdef HAVE_SSL +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H #include -#include -#include -#ifndef WIN32 +#endif + +#ifdef HAVE_NETINET_IN_H #include #endif + #if HAVE_INTTYPES_H #include #else @@ -40,24 +46,44 @@ typedef unsigned int uint32_t; # endif #endif +#ifdef HAVE_STRING_H #include +#endif + +#ifdef HAVE_STDLIB_H #include +#endif + +#ifdef HAVE_TIME_H #include +#endif +#ifdef HAVE_FCNTL_H #include +#endif -#include "nanohttp-ssl.h" -#include "nanohttp-common.h" -#include "nanohttp-socket.h" - +#ifdef HAVE_UNISTD_H +#include +#endif #ifdef WIN32 #include typedef unsigned int uint32_t; #else -#include #endif +#ifdef HAVE_OPENSSL_RAND_H +#include +#endif + +#ifdef HAVE_OPENSSL_ERR_H +#include +#endif + +#include "nanohttp-common.h" +#include "nanohttp-socket.h" +#include "nanohttp-ssl.h" + #define MAXCHUNK 1024 #define HEADER_LEN 5 char HEADER[HEADER_LEN] = { 186, 84, 202, 86, 224 }; @@ -126,6 +152,18 @@ verify_sn (X509 * cert, int who, int nid, char *str) } } +#ifdef NOUSER_VERIFY +static int +user_verify (X509 * 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."); + return 1; +} +#endif + static int verify_cb (int prev_ok, X509_STORE_CTX * ctx) { @@ -152,26 +190,17 @@ verify_cb (int prev_ok, X509_STORE_CTX * ctx) #endif } -#ifdef NOUSER_VERIFY -int -user_verify (X509 * 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."); - return 1; -} -#endif - void -start_ssl( void ){ +start_ssl( void ) +{ /* Global system initialization */ log_verbose1 ("Initializing library"); SSL_library_init (); SSL_load_error_strings (); ERR_load_crypto_strings (); OpenSSL_add_ssl_algorithms (); + + return; } SSL_CTX * diff --git a/nanohttp/nanohttp-stream.c b/nanohttp/nanohttp-stream.c index c8ba216..8908e54 100755 --- a/nanohttp/nanohttp-stream.c +++ b/nanohttp/nanohttp-stream.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-stream.c,v 1.9 2006/01/10 11:29:05 snowdrop Exp $ +* $Id: nanohttp-stream.c,v 1.10 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -21,14 +21,20 @@ * * Email: ferhatayaz@yahoo.com ******************************************************************/ +#ifdef HAVE_CONFIG_H +#include +#endif -#include - +#ifdef HAVE_STRING_H #include +#endif #ifdef MEM_DEBUG #include #endif + +#include "nanohttp-stream.h" + void _log_str(char *fn, char *str, int size) { @@ -416,7 +422,7 @@ _http_input_stream_file_read(http_input_stream_t * stream, byte_t * dest, int http_input_stream_is_ready(http_input_stream_t * stream) { - /* paranoya check */ + /* paranoia check */ if (stream == NULL) return 0; -- cgit v1.1-32-gdbae