diff options
Diffstat (limited to 'examples/xkms-server.c')
-rw-r--r-- | examples/xkms-server.c | 839 |
1 files changed, 0 insertions, 839 deletions
diff --git a/examples/xkms-server.c b/examples/xkms-server.c deleted file mode 100644 index 188d5c73..00000000 --- a/examples/xkms-server.c +++ /dev/null @@ -1,839 +0,0 @@ -/** - * XML Security Library example: simple XKMS server - * - * Starts XKMS server on specified port. - * - * Usage: - * ./xkms-server [--port <port>] [--format plain|soap-1.1|soap-1.2] <keys-file> - * - * Example: - * ./xkms-server --port 8080 --format soap-1.1 keys.xml - * - * This is free software; see Copyright file in the source - * distribution for preciese wording. - * - * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> - */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <errno.h> - -#ifdef XMLSEC_NO_XKMS - -int main(int argc, char** argv) { - fprintf(stderr, "ERROR: XKMS is disabled.\n"); - return 1; -} - -#else /* XMLSEC_NO_XKMS */ - -#include <libxml/tree.h> -#include <libxml/xmlmemory.h> -#include <libxml/parser.h> - -#ifndef XMLSEC_NO_XSLT -#include <libxslt/xslt.h> -#include <libxslt/security.h> -#endif /* XMLSEC_NO_XSLT */ - -#include <xmlsec/xmlsec.h> -#include <xmlsec/xmltree.h> -#include <xmlsec/buffer.h> -#include <xmlsec/xkms.h> -#include <xmlsec/crypto.h> - -#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING -#include <xmlsec/app.h> -#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */ - -#ifdef UNIX_SOCKETS -#include <netinet/in.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netinet/tcp.h> -#include <netdb.h> -#include <fcntl.h> -#include <signal.h> -#else /* UNIX_SOCKETS */ -#ifdef WIN32_SOCKETS -#include <windows.h> -#include <winsock.h> -#else /* WIN32_SOCKETS */ -#error "Your operating system is not supported" -#endif /* WIN32_SOCKETS */ -#endif /* UNIX_SOCKETS */ - -#define DEFAULT_PORT 1234 -#define PENDING_QUEUE_SIZE 100 - -#define LOG_LEVEL_SILENT 0 -#define LOG_LEVEL_INFO 1 -#define LOG_LEVEL_DATA 2 -#define LOG_LEVEL_DEBUG 3 - -#ifdef UNIX_SOCKETS -static int sockfd = -1; -#endif /* UNIX_SOCKETS */ - -#ifdef WIN32_SOCKETS -static SOCKET sockfd = -1; -#endif /* WIN32_SOCKETS */ - -static int finished = 0; -static int log_level = LOG_LEVEL_INFO; - -static int init_server(unsigned short port); -static void stop_server(); -static void int_signal_handler(int sig_num); -static const xmlChar* my_strnstr(const xmlChar* str, xmlSecSize strLen, const xmlChar* tmpl, xmlSecSize tmplLen); - -static int handle_connection(int fd, xmlSecXkmsServerCtxPtr xkmsCtx, xmlSecXkmsServerFormat format); -static int read_request(int fd, const char* in_ip, xmlSecBufferPtr buffer); -static int send_response(int fd, const char* in_ip, int resp_code, - const char* body, int body_size); - -static char usage[] = "[--port <port>] [--format plain|soap-1.1|soap-1.2] <keys-file>"; -static char http_header[] = - "HTTP/1.0 %d\n" - "Server: XML Security Library: Simple XKMS Server/1.0\n" - "Content-length: %d\n" - "\n"; -static char http_503[] = - "Error 503 - Service Unavailable\n"; - -int main(int argc, char** argv) { - int argpos; - unsigned short port = DEFAULT_PORT; -#ifndef XMLSEC_NO_XSLT - xsltSecurityPrefsPtr xsltSecPrefs = NULL; -#endif /* XMLSEC_NO_XSLT */ - xmlSecKeysMngrPtr mngr = NULL; - xmlSecXkmsServerCtxPtr xkmsCtx = NULL; - xmlSecXkmsServerFormat format = xmlSecXkmsServerFormatPlain; - int ret; - - fprintf(stdout, "Log: server is starting up\n"); - - /* Init libxml and libxslt libraries */ - xmlInitParser(); - LIBXML_TEST_VERSION - xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; - xmlSubstituteEntitiesDefault(1); -#ifndef XMLSEC_NO_XSLT - xmlIndentTreeOutput = 1; -#endif /* XMLSEC_NO_XSLT */ - - /* Init libxslt */ -#ifndef XMLSEC_NO_XSLT - /* disable everything */ - xsltSecPrefs = xsltNewSecurityPrefs(); - xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid); - xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid); - xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid); - xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid); - xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid); - xsltSetDefaultSecurityPrefs(xsltSecPrefs); -#endif /* XMLSEC_NO_XSLT */ - - /* Init xmlsec library */ - if(xmlSecInit() < 0) { - fprintf(stderr, "Error %d: xmlsec initialization failed.\n", errno); - return(-1); - } - - /* Check loaded library version */ - if(xmlSecCheckVersion() != 1) { - fprintf(stderr, "Error %d: loaded xmlsec library version is not compatible.\n", errno); - return(-1); - } - - /* Load default crypto engine if we are supporting dynamic - * loading for xmlsec-crypto libraries. Use the crypto library - * name ("openssl", "nss", etc.) to load corresponding - * xmlsec-crypto library. - */ -#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING - if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) { - fprintf(stderr, "Error %d: unable to load default xmlsec-crypto library. Make sure\n" - "that you have it installed and check shared libraries path\n" - "(LD_LIBRARY_PATH) envornment variable.\n", errno); - return(-1); - } -#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */ - - /* Init crypto library */ - if(xmlSecCryptoAppInit(NULL) < 0) { - fprintf(stderr, "Error %d: crypto initialization failed.\n", errno); - return(-1); - } - - /* Init xmlsec-crypto library */ - if(xmlSecCryptoInit() < 0) { - fprintf(stderr, "Error %d: xmlsec-crypto initialization failed.\n", errno); - return(-1); - } - - /* Create and initialize keys manager */ - mngr = xmlSecKeysMngrCreate(); - if(mngr == NULL) { - fprintf(stderr, "Error %d: failed to create keys manager.\n", errno); - goto done; - } - if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) { - fprintf(stderr, "Error %d: failed to initialize keys manager.\n", errno); - goto done; - } - - /* Create XKMS server context */ - xkmsCtx = xmlSecXkmsServerCtxCreate(mngr); - if(xkmsCtx == NULL) { - fprintf(stderr, "Error %d: XKMS server context initialization failed\n", errno); - goto done; - } - - /* Process input parameters */ - for(argpos = 1; (argpos < argc) && (argv[argpos][0] == '-'); argpos++) { - if((strcmp(argv[argpos], "--port") == 0) || (strcmp(argv[argpos], "-p") == 0)) { - argpos++; - port = atoi(argv[argpos]); - if(port == 0) { - fprintf(stderr, "Error %d: invalid port number \"%s\".\nUsage: %s %s\n", errno, argv[argpos], argv[0], usage); - goto done; - } - } else if((strcmp(argv[argpos], "--format") == 0) || (strcmp(argv[argpos], "-f") == 0)) { - argpos++; - format = xmlSecXkmsServerFormatFromString(BAD_CAST argv[argpos]); - if(format == xmlSecXkmsServerFormatUnknown) { - fprintf(stderr, "Error %d: invalid format \"%s\".\nUsage: %s %s\n", errno, argv[argpos], argv[0], usage); - goto done; - } - } else if((strcmp(argv[argpos], "--log-level") == 0) || (strcmp(argv[argpos], "-l") == 0)) { - argpos++; - log_level = atoi(argv[argpos]); - } else { - fprintf(stderr, "Error %d: unknown parameter \"%s\".\nUsage: %s %s\n", errno, argv[argpos], argv[0], usage); - goto done; - } - } - if(argpos >= argc) { - fprintf(stderr, "Error %d: keys file is not specified.\nUsage: %s %s\n", errno, argv[0], usage); - goto done; - } - - /* Load keys */ - for(; argpos < argc; argpos++) { - if(xmlSecCryptoAppDefaultKeysMngrLoad(mngr, argv[argpos]) < 0) { - fprintf(stderr, "Error %d: failed to load xml keys file \"%s\".\nUsage: %s %s\n", errno, argv[argpos], argv[0], usage); - goto done; - } - if(log_level >= LOG_LEVEL_INFO) { - fprintf(stdout, "Log: loaded keys from \"%s\"\n", argv[argpos]); - } - } - - /* Startup TCP server */ - if(init_server(port) < 0) { - fprintf(stderr, "Error, errno: server initialization failed\n", errno); - goto done; - } - assert(sockfd != -1); - - /* main loop: accept connections and process requests */ - while(finished == 0) { - fd_set fds; - struct timeval timeout; - - /* Set up polling using select() */ - FD_ZERO(&fds); - FD_SET(sockfd, &fds); - memset(&timeout, 0, sizeof(timeout)); - timeout.tv_sec = 1; - ret = select(sockfd + 1, &fds, NULL, NULL, &timeout); - if((ret <= 0) || !FD_ISSET(sockfd, &fds)) { - /* error, timed out or not our socket: try again */ - continue; - } - - if(handle_connection(sockfd, xkmsCtx, format) < 0) { - fprintf(stderr, "Error %d: unable to accept incomming connection\n"); - goto done; - } - } - -done: - if(log_level >= LOG_LEVEL_INFO) { - fprintf(stdout, "Log: server is shutting down\n"); - } - - /* Shutdown TCP server */ - stop_server(); - - /* Destroy xkms server context */ - if(xkmsCtx != NULL) { - xmlSecXkmsServerCtxDestroy(xkmsCtx); - xkmsCtx = NULL; - } - - /* Destroy keys manager */ - if(mngr != NULL) { - xmlSecKeysMngrDestroy(mngr); - mngr = NULL; - } - - /* Shutdown xmlsec-crypto library */ - xmlSecCryptoShutdown(); - - /* Shutdown crypto library */ - xmlSecCryptoAppShutdown(); - - /* Shutdown xmlsec library */ - xmlSecShutdown(); - - /* Shutdown libxslt/libxml */ -#ifndef XMLSEC_NO_XSLT - xsltFreeSecurityPrefs(xsltSecPrefs); - xsltCleanupGlobals(); -#endif /* XMLSEC_NO_XSLT */ - xmlCleanupParser(); - - fprintf(stdout, "Log: server is down, bye!\n"); - return(0); -} - -/** - * init_server: - * @port: the server'xmlSecBufferGetData(buffer) TCP port number. - * - * Starts up a TCP server listening on given @port. - * - * Returns 0 on success or a negative value if an error occurs. - */ -static int -init_server(unsigned short port) { -#ifdef WIN32_SOCKETS - WSADATA data; -#endif /* WIN32_SOCKETS */ - struct sockaddr_in saddr; - int flags; - -#ifdef WIN32_SOCKETS - if(WSAStartup(MAKEWORD(1,1), &data)) { - fprintf(stderr, "Error %d: WSAStartup() failed\n", errno); - return(-1); - } -#endif /* WIN32_SOCKETS */ - - /* create socket */ - sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); -#ifdef UNIX_SOCKETS - if(sockfd == -1) { -#endif /* UNIX_SOCKETS */ - -#ifdef WIN32_SOCKETS - if(sockfd == INVALID_SOCKET) { -#endif /* WIN32_SOCKETS */ - - fprintf(stderr, "Error %d: socket() failed\n", errno); - return(-1); - } - - /* enable reuse of address */ - flags = 1; - if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&flags, sizeof(flags)) != 0) { - fprintf(stderr, "Error %d: setsockopt(SO_REUSEADDR) failed\n", errno); - return(-1); - } - -#ifdef UNIX_SOCKETS - /* set non-blocking */ - flags = fcntl(sockfd, F_GETFL); - if(flags < 0) { - fprintf(stderr, "Error %d: fcntl(F_GETFL) failed\n", errno); - return(-1); - } - if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) { - fprintf(stderr, "Error %d: fcntl(F_SETFL) failed\n", errno); - return(-1); - } -#endif /* UNIX_SOCKETS */ - - /* preset socket structure for socket binding */ - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_port = htons(port); - saddr.sin_addr.s_addr = INADDR_ANY; - if(bind(sockfd, (struct sockaddr *)&saddr, sizeof(struct sockaddr)) != 0) { - fprintf(stderr, "Error %d: bind() failed\n", errno); - return(-1); - } - - /* prepare for listening */ - if(listen(sockfd, PENDING_QUEUE_SIZE) != 0) { - fprintf(stderr, "Error %d: listen() failed\n", errno); - return(-1); - } - -#ifdef UNIX_SOCKETS - /* setup SIGINT handler that will stop the server */ - signal(SIGINT, int_signal_handler); -#endif /* UNIX_SOCKETS */ - - if(log_level >= LOG_LEVEL_INFO) { - fprintf(stdout, "Log: server is ready and listening on port %d\n", port); - } - return(0); -} - -/** - * stop_server: - * - * Shuts down TCP server. - */ -static void -stop_server() { -#ifdef UNIX_SOCKETS - if(sockfd != -1) { - shutdown(sockfd, SHUT_RDWR); - close(sockfd); - sockfd = -1; - } -#endif /* UNIX_SOCKETS */ - -#ifdef WIN32_SOCKETS - if(sockfd != -1) { - close(sockfd); - sockfd = -1; - } -#endif /* WIN32_SOCKETS */ - if(log_level >= LOG_LEVEL_INFO) { - fprintf(stdout, "Log: server is shutted down\n"); - } -} - -/** - * int_signal_handler: - * @sig_num: the signal number. - * - * Unix's Ctrl-C signal handler that stops the server. - */ -static void -int_signal_handler(int sig_num) { - if(log_level >= LOG_LEVEL_INFO) { - fprintf(stdout, "Log: server is asked to shutdown\n"); - } - finished = 1; -} - -/** - * handle_connection: - * @sockfd: the server's socket. - * @xkmsCtx: the template XKMS server context. - * @format: the expected format of XKMS requests. - * - * Establishs a connection, forks a child process (onUnix), reads the request, - * processes it and writes back the response. - * - * Returns 0 on success or a negative value if an error occurs. - */ -static int -handle_connection(int sockfd, xmlSecXkmsServerCtxPtr xkmsCtx, xmlSecXkmsServerFormat format) { -#ifdef UNIX_SOCKETS - int fd = -1; -#endif /* UNIX_SOCKETS */ - -#ifdef WIN32_SOCKETS - SOCKET fd = -1; -#endif /* WIN32_SOCKETS */ - - int in_child_process = 0; - struct sockaddr_in saddr; - int saddr_size; - xmlSecXkmsServerCtxPtr xkmsCtx2 = NULL; - xmlSecBufferPtr buffer = NULL; - xmlDocPtr inDoc = NULL; - xmlDocPtr outDoc = NULL; - xmlNodePtr result = NULL; - xmlOutputBufferPtr output = NULL; - int resp_ready = 0; - int ret; - - assert(sockfd != -1); - assert(xkmsCtx != NULL); - - /* Get the socket connection */ - saddr_size = sizeof(struct sockaddr_in); - fd = accept(sockfd, (struct sockaddr *)&saddr, &saddr_size); - -#ifdef UNIX_SOCKETS - if(sockfd == -1) { -#endif /* UNIX_SOCKETS */ - -#ifdef WIN32_SOCKETS - if(sockfd == INVALID_SOCKET) { -#endif /* WIN32_SOCKETS */ - - fprintf(stderr, "Error %d: accept() failed\n", errno); - return(-1); - } - if(log_level >= LOG_LEVEL_INFO) { - fprintf(stdout, "Log [%s]: got connection\n", inet_ntoa(saddr.sin_addr)); - } - - /* Create a copy of XKMS server context */ - xkmsCtx2 = xmlSecXkmsServerCtxCreate(NULL); - if(xkmsCtx2 == NULL) { - fprintf(stderr, "Error %d [%s]: a copy of XKMS server context initialization failed\n", errno, inet_ntoa(saddr.sin_addr)); - goto done; - } - if(xmlSecXkmsServerCtxCopyUserPref(xkmsCtx2, xkmsCtx) < 0) { - fprintf(stderr, "Error %d [%s]: XKMS server context copy failed\n", errno, inet_ntoa(saddr.sin_addr)); - goto done; - } - -#ifdef UNIX_SOCKETS - /* on Unix we use child process to process requests */ - if(fork()) { - /* parent process */ - return(0); - } - - /* child process */ - in_child_process = 1; - close(sockfd); /* we don't need listening socket */ -#endif /* UNIX_SOCKETS */ - - buffer = xmlSecBufferCreate(0); - if(buffer == NULL) { - fprintf(stderr, "Error %d [%s]: xmlSecBufferCreate() failed\n", errno, inet_ntoa(saddr.sin_addr)); - goto done; - } - - /* read input request */ - ret = read_request(fd, inet_ntoa(saddr.sin_addr), buffer); - if(ret < 0) { - fprintf(stderr, "Error %d [%s]: read_request() failed\n", errno, inet_ntoa(saddr.sin_addr)); - goto done; - } - - /* parse request */ - inDoc = xmlParseMemory(xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer) ); - if((inDoc == NULL) || (xmlDocGetRootElement(inDoc) == NULL)) { - fprintf(stderr, "Error %d [%s]: failed to parse request\n", errno, inet_ntoa(saddr.sin_addr)); - goto done; - } - xmlSecBufferEmpty(buffer); - - /* prepare result document */ - outDoc = xmlNewDoc(BAD_CAST "1.0"); - if(outDoc == NULL) { - fprintf(stderr, "Error %d [%s]: failed to create result doc\n", errno, inet_ntoa(saddr.sin_addr)); - goto done; - } - - result = xmlSecXkmsServerCtxProcess(xkmsCtx2, xmlDocGetRootElement(inDoc), format, outDoc); - if(result == NULL) { - fprintf(stderr, "Error %d [%s]: failed to process xkms server request\n", errno, inet_ntoa(saddr.sin_addr)); - goto done; - } - - /* apppend returned result node to the output document */ - xmlDocSetRootElement(outDoc, result); - - /* create LibXML2 output buffer */ - output = xmlSecBufferCreateOutputBuffer(buffer); - if(output == NULL) { - fprintf(stderr, "Error %d [%s]: xmlSecBufferCreateOutputBuffer() failed\n", errno, inet_ntoa(saddr.sin_addr)); - goto done; - } - xmlNodeDumpOutput(output, result->doc, result, 0, 0, NULL); - - xmlOutputBufferClose(output); output = NULL; - resp_ready = 1; -done: - /* send back response */ - if((resp_ready == 1) && (xmlSecBufferGetData(buffer) != NULL)) { - ret = send_response(fd, inet_ntoa(saddr.sin_addr), 200, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer)); - if(log_level >= LOG_LEVEL_INFO) { - fprintf(stdout, "Log [%s]: processed request\n", inet_ntoa(saddr.sin_addr)); - } - } else if(fd >= 0) { - ret = send_response(fd, inet_ntoa(saddr.sin_addr), 503, http_503, strlen(http_503)); - if(log_level >= LOG_LEVEL_INFO) { - fprintf(stdout, "Log [%s]: failed to process request\n", inet_ntoa(saddr.sin_addr)); - } - } else { - ret = -1; - } - if(ret < 0) { - fprintf(stderr, "Error %d [%s]: send_response() failed\n", errno, inet_ntoa(saddr.sin_addr)); - } - - /* cleanup */ - if(output != NULL) { - xmlOutputBufferClose(output); - output = NULL; - } - - if(outDoc != NULL) { - xmlFreeDoc(outDoc); - outDoc = NULL; - } - - if(inDoc != NULL) { - xmlFreeDoc(inDoc); - inDoc = NULL; - } - - if(buffer != NULL) { - xmlSecBufferDestroy(buffer); - buffer = NULL; - } - - if(xkmsCtx2 != NULL) { - xmlSecXkmsServerCtxDestroy(xkmsCtx2); - xkmsCtx2 = NULL; - } - - if(fd >= 0) { -#ifdef UNIX_SOCKETS - shutdown(fd, SHUT_RDWR); - close(fd); -#endif /* UNIX_SCOKETS */ - -#ifdef WIN32_SOCKETS - close(fd); -#endif /* WIN32_SCOKETS */ - - fd = -1; - } - - if(in_child_process) { - exit(0); - } - return(0); -} - -/** - * read_request: - * @fd: the request's socket. - * @in_ip: the request's IP address (for logging). - * @buffer: the output buffer. - * - * Reads the request from socket @fd and stores it in the @buffer. - * - * Returns 0 on success or a negative value if an error occurs. - */ -static int -read_request(int fd, const char* in_ip, xmlSecBufferPtr buffer) { - char buf[1024]; - const xmlChar* s; - const xmlChar* p; - int nread; - int length = 0; - int found = 0; - int counter; - - assert(fd != -1); - assert(in_ip != NULL); - assert(buffer); - - /* first read the http headers */ - counter = 5; - while(my_strnstr(xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), BAD_CAST "\r\n\r\n", 4) == NULL) { - nread = recv(fd, buf, sizeof(buf), 0); - if(nread < 0) { - fprintf(stderr, "Error %d [%s]: read() failed\n", errno, in_ip); - return(-1); - } - - if((nread > 0) && (xmlSecBufferAppend(buffer, buf, nread) < 0)) { - fprintf(stderr, "Error %d [%s]: xmlSecBufferAppend(%d) failed\n", errno, in_ip, nread); - return(-1); - } - - if(nread < sizeof(buffer)) { - counter--; - if(counter <= 0) { - break; - } - } - } - - if(xmlSecBufferGetData(buffer) == NULL) { - fprintf(stderr, "Error %d [%s]: no bytes read\n", errno, in_ip); - return(-1); - } - - if(log_level >= LOG_LEVEL_DEBUG) { - xmlSecBufferAppend(buffer, BAD_CAST "\0", 1); - fprintf(stdout, "Debug [%s]: request headers:\n%s\n", in_ip, xmlSecBufferGetData(buffer)); - xmlSecBufferRemoveTail(buffer, 1); - } - - /* Parse the request and extract the body. We expect the request to look - * like this: - * POST <path> HTTP/1.x\r\n - * <header1>\r\n - * <header2>\r\n - * ... - * <headerN>\r\n - * \r\n - * <body> - */ - - /* analyze the first line */ - p = my_strnstr(xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), BAD_CAST "\r\n", 2); - if(p == NULL) { - fprintf(stderr, "Error %d [%s]: there is no HTTP header\n", errno, in_ip); - return(-1); - } - if(xmlStrncasecmp(xmlSecBufferGetData(buffer), BAD_CAST "POST ", 5) != 0) { - fprintf(stderr, "Error %d [%s]: not a POST request\n", errno, in_ip); - return(-1); - } - /* "POST " + " HTTP/1.x" == 14 */ - s = xmlSecBufferGetData(buffer); - if(p - s <= 14) { - fprintf(stderr, "Error %d [%s]: first line has bad length\n", errno, in_ip); - return(-1); - } - if((xmlStrncasecmp(p - 9, BAD_CAST " HTTP/1.0", 9) != 0) && - (xmlStrncasecmp(p - 9, BAD_CAST " HTTP/1.1", 9) != 0)) { - - fprintf(stderr, "Error %d [%s]: first line does not end with \" HTTP/1.x\"\n", errno, in_ip); - return(-1); - } - if(xmlSecBufferRemoveHead(buffer, p - xmlSecBufferGetData(buffer) + 2) < 0) { - fprintf(stderr, "Error %d [%s]: failed to skip first line\n", errno, in_ip); - return(-1); - } - - /* now skip all the headers (i.e. everything until empty line) */ - found = 0; - while(!found) { - p = my_strnstr(xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), BAD_CAST "\r\n", 2); - if(p == NULL) { - fprintf(stderr, "Error %d [%s]: there is no HTTP body\n", errno, in_ip); - return(-1); - } - - if(p == xmlSecBufferGetData(buffer)) { - found = 1; - } else if(xmlStrncasecmp(xmlSecBufferGetData(buffer), BAD_CAST "Content-length: ", 16) == 0) { - length = atoi(xmlSecBufferGetData(buffer) + 16); - } - - if(xmlSecBufferRemoveHead(buffer, p - xmlSecBufferGetData(buffer) + 2) < 0) { - fprintf(stderr, "Error %d [%s]: failed to skip header line\n", errno, in_ip); - return(-1); - } - } - - /* remove the trailing \0 we added */ - xmlSecBufferRemoveTail(buffer, 1); - - /* now read the body */ - counter = 5; - while(xmlSecBufferGetSize(buffer) < length) { - nread = recv(fd, buf, sizeof(buf), 0); - if(nread < 0) { - fprintf(stderr, "Error %d [%s]: read() failed\n", errno, in_ip); - return(-1); - } - - if((nread > 0) && (xmlSecBufferAppend(buffer, buf, nread) < 0)) { - fprintf(stderr, "Error %d [%s]: xmlSecBufferAppend(%d) failed\n", errno, in_ip, nread); - return(-1); - } - if(nread < sizeof(buffer)) { - counter--; - if(counter <= 0) { - break; - } - } - } - if(log_level >= LOG_LEVEL_INFO) { - fprintf(stdout, "Log [%s]: body size is %d bytes\n", in_ip, xmlSecBufferGetSize(buffer)); - } - if(log_level >= LOG_LEVEL_DATA) { - xmlSecBufferAppend(buffer, BAD_CAST "\0", 1); - fprintf(stdout, "Log [%s]: request body:\n%s\n", in_ip, xmlSecBufferGetData(buffer)); - xmlSecBufferRemoveTail(buffer, 1); - } - return(0); -} - -/** - * send_response: - * @fd: the request's socket. - * @in_ip: the request's IP address (for logging). - * @resp_code: the HTTP response code. - * @body: the response body. - * @body_len: the response body length. - * - * Writes HTTP response headers and @body to the @socket. - * - * Returns 0 on success or a negative value if an error occurs. - */ -static int -send_response(int fd, const char* in_ip, int resp_code, const char* body, int body_size) { - char header[sizeof(http_header) + 100]; - - assert(fd != -1); - assert(in_ip != NULL); - assert(resp_code > 0); - assert(body != NULL); - - /* prepare and send http header */ - sprintf(header, http_header, resp_code, body_size); - if(send(fd, header, strlen(header), 0) == -1) { - fprintf(stderr, "Error %d [%s]: send(header) failed\n", errno, in_ip); - return(-1); - } - - if(log_level >= LOG_LEVEL_DATA) { - xmlChar* tmp = xmlStrndup(body, body_size); - fprintf(stdout, "Log [%s]: response is\n%s\n", in_ip, tmp); - xmlFree(tmp); - } - - /* send body */ - if(send(fd, body, body_size, 0) == -1) { - fprintf(stderr, "Error %d [%s]: send(body) failed\n", errno, in_ip); - return(-1); - } - - return(0); -} - -/** - * my_strnstr: - * @str: the soruce string. - * @strLen: the source string length. - * @tmpl: the template string. - * @tmplLen: the template string length. - * - * Searches for the first occurence of @tmpl in @str. - * - * Returns pointer to the first occurence of @tmpl in @str or NULL if it is not found. - */ -static const xmlChar* -my_strnstr(const xmlChar* str, xmlSecSize strLen, const xmlChar* tmpl, xmlSecSize tmplLen) { - xmlSecSize pos; - - if((str == NULL) || (tmpl == NULL)) { - return(NULL); - } - for(pos = 0; pos + tmplLen <= strLen; pos++) { - if(xmlStrncmp(str + pos, tmpl, tmplLen) == 0) { - return(str + pos); - } - } - - return(NULL); -} - -#endif /* XMLSEC_NO_XKMS */ - |