From 6b424c5406afec25d6c01fdfe02562cda02dc21c Mon Sep 17 00:00:00 2001 From: vemax78 Date: Tue, 6 Aug 2013 22:15:19 +0200 Subject: [PATCH] Add support to HTTPS SOAP request --- conf/ac.conf | 13 +- src/ac/ac.c | 74 +++++++- src/ac/ac_soap.c | 83 ++++++--- src/ac/ac_soap.h | 7 + src/common/capwap_socket.c | 344 +++++++++++++++++++++++++++++++++++-- src/common/capwap_socket.h | 27 ++- 6 files changed, 503 insertions(+), 45 deletions(-) diff --git a/conf/ac.conf b/conf/ac.conf index 23df6f5..8dc841b 100755 --- a/conf/ac.conf +++ b/conf/ac.conf @@ -19,7 +19,7 @@ application: { presharedkey = false; x509 = false; }; - + rmacfiled: { supported = false; }; @@ -53,16 +53,16 @@ application: { presharedkey: { hint = "esempio"; - identity = "prova"; - pskkey = "123456"; + identity = "prova"; + pskkey = "123456"; }; - + x509: { calist = "/etc/capwap/ca.crt"; certificate = "/etc/capwap/ac.crt"; privatekey = "/etc/capwap/ac.key"; privatekeypassword = ""; - }; + }; }; network: { @@ -78,7 +78,8 @@ application: { backend: { server: ( - { url = "http://localhost/csoap.php"; } + { url = "http://localhost/csoap.php"; }, + { url = "https://localhost/csoap.php"; x509: { calist = "/etc/capwap/ca.crt"; certificate = "/etc/capwap/ac.crt"; privatekey = "/etc/capwap/ac.key"; privatekeypassword = ""; }; } ); }; diff --git a/src/ac/ac.c b/src/ac/ac.c index a0fd169..5353947 100644 --- a/src/ac/ac.c +++ b/src/ac/ac.c @@ -1,6 +1,7 @@ #include "ac.h" #include "ac_soap.h" #include "capwap_dtls.h" +#include "capwap_socket.h" #include @@ -570,7 +571,7 @@ static int ac_parsing_configuration_1_0(config_t* config) { /* Backend */ configSetting = config_lookup(config, "backend.server"); - if (configSetting != NULL) { + if (configSetting) { int count = config_setting_length(configSetting); /* Retrieve server */ @@ -578,14 +579,79 @@ static int ac_parsing_configuration_1_0(config_t* config) { config_setting_t* configServer = config_setting_get_elem(configSetting, i); if (configServer != NULL) { if (config_setting_lookup_string(configServer, "url", &configString) == CONFIG_TRUE) { - struct ac_http_soap_server** server = (struct ac_http_soap_server**)capwap_array_get_item_pointer(g_ac.availablebackends, g_ac.availablebackends->count); + struct ac_http_soap_server* server; + struct ac_http_soap_server** itemserver; /* */ - *server = ac_soapclient_create_server(configString); - if (!*server) { + server = ac_soapclient_create_server(configString); + if (!server) { capwap_logging_error("Invalid configuration file, invalid backend.server value"); return 0; } + + /* HTTPS params */ + if (server->protocol == SOAP_HTTPS_PROTOCOL) { + char* calist = NULL; + char* certificate = NULL; + char* privatekey = NULL; + char* privatekeypassword = NULL; + config_setting_t* configSSL; + + /* */ + configSSL = config_setting_get_member(configServer, "x509"); + if (!configSSL) { + capwap_logging_error("Invalid configuration file, invalid backend.server.x509 value"); + return 0; + } + + if (config_setting_lookup_string(configSSL, "calist", &configString) == CONFIG_TRUE) { + if (strlen(configString) > 0) { + calist = capwap_duplicate_string(configString); + } + } + + if (config_setting_lookup_string(configSSL, "certificate", &configString) == CONFIG_TRUE) { + if (strlen(configString) > 0) { + certificate = capwap_duplicate_string(configString); + } + } + + if (config_setting_lookup_string(configSSL, "privatekey", &configString) == CONFIG_TRUE) { + if (strlen(configString) > 0) { + privatekey = capwap_duplicate_string(configString); + } + } + + if (config_setting_lookup_string(configSSL, "privatekeypassword", &configString) == CONFIG_TRUE) { + if (strlen(configString) > 0) { + privatekeypassword = capwap_duplicate_string(configString); + } + } + + /* */ + if (calist && certificate && privatekey) { + server->sslcontext = capwap_socket_crypto_createcontext(calist, certificate, privatekey, privatekeypassword); + if (!server->sslcontext) { + capwap_logging_error("Invalid configuration file, invalid backend.server.x509 value"); + return 0; + } + } else { + capwap_logging_error("Invalid configuration file, invalid backend.server.x509 value"); + return 0; + } + + /* Free SSL param */ + capwap_free(calist); + capwap_free(certificate); + capwap_free(privatekey); + if (privatekeypassword) { + capwap_free(privatekeypassword); + } + } + + /* Add item */ + itemserver = (struct ac_http_soap_server**)capwap_array_get_item_pointer(g_ac.availablebackends, g_ac.availablebackends->count); + *itemserver= server; } } } diff --git a/src/ac/ac_soap.c b/src/ac/ac_soap.c index 6626a1e..05dad46 100644 --- a/src/ac/ac_soap.c +++ b/src/ac/ac_soap.c @@ -105,9 +105,8 @@ static int ac_soapclient_parsing_url(struct ac_http_soap_server* server, const c /* Parsing protocol */ if (!strncasecmp(url, "http", protocol)) { server->protocol = SOAP_HTTP_PROTOCOL; - /* TODO: write code for SSL connection } else if (!strncasecmp(url, "https", protocol)) { - server->protocol = SOAP_HTTPS_PROTOCOL;*/ + server->protocol = SOAP_HTTPS_PROTOCOL; } else { /* Unknown protocol */ return 0; @@ -180,6 +179,26 @@ static int ac_soapclient_parsing_url(struct ac_http_soap_server* server, const c return 1; } +/* */ +static int ac_soapclient_connect(struct ac_http_soap_request* httprequest) { + int result = 0; + + if (httprequest->server->protocol == SOAP_HTTP_PROTOCOL) { + result = capwap_socket_connect(httprequest->sock, &httprequest->server->address, SOAP_PROTOCOL_CONNECT_TIMEOUT); + } else if (httprequest->server->protocol == SOAP_HTTPS_PROTOCOL) { + result = capwap_socket_connect(httprequest->sock, &httprequest->server->address, SOAP_PROTOCOL_CONNECT_TIMEOUT); + if (result) { + /* Establish SSL/TLS connection */ + httprequest->sslsock = capwap_socket_ssl_connect(httprequest->sock, httprequest->server->sslcontext, SOAP_PROTOCOL_CONNECT_TIMEOUT); + if (!httprequest->sslsock) { + result = 0; + } + } + } + + return result; +} + /* */ static int ac_soapclient_send_http(struct ac_http_soap_request* httprequest, char* soapaction, char* body, int length) { time_t ts; @@ -225,11 +244,17 @@ static int ac_soapclient_send_http(struct ac_http_soap_request* httprequest, cha if (result < 0) { result = 0; } else { - if (capwap_socket_send_timeout(httprequest->sock, buffer, result, httprequest->requesttimeout) == result) { - result = 1; - } else { - result = 0; + int sendlength = -1; + + /* Send packet */ + if (httprequest->server->protocol == SOAP_HTTP_PROTOCOL) { + sendlength = capwap_socket_send(httprequest->sock, buffer, result, httprequest->requesttimeout); + } else if (httprequest->server->protocol == SOAP_HTTPS_PROTOCOL) { + sendlength = capwap_socket_crypto_send(httprequest->sslsock, buffer, result, httprequest->requesttimeout); } + + /* Check result */ + result = ((sendlength == result) ? 1 : 0); } /* */ @@ -244,8 +269,14 @@ static int ac_soapclient_http_readline(struct ac_http_soap_request* httprequest, for (;;) { /* Receive packet into temporaly buffer */ - if (capwap_socket_recv_timeout(httprequest->sock, &buffer[bufferpos], 1, httprequest->responsetimeout) != 1) { - break; /* Connection error */ + if (httprequest->server->protocol == SOAP_HTTP_PROTOCOL) { + if (capwap_socket_recv(httprequest->sock, &buffer[bufferpos], 1, httprequest->responsetimeout) != 1) { + break; /* Connection error */ + } + } else if (httprequest->server->protocol == SOAP_HTTPS_PROTOCOL) { + if (capwap_socket_crypto_recv(httprequest->sslsock, &buffer[bufferpos], 1, httprequest->responsetimeout) != 1) { + break; /* Connection error */ + } } /* Update buffer size */ @@ -349,7 +380,12 @@ static int ac_soapclient_xml_io_read(void* ctx, char* buffer, int len) { } /* Receive body directly into XML buffer */ - result = capwap_socket_recv_timeout(httprequest->sock, buffer, len, httprequest->responsetimeout); + if (httprequest->server->protocol == SOAP_HTTP_PROTOCOL) { + result = capwap_socket_recv(httprequest->sock, buffer, len, httprequest->responsetimeout); + } else if (httprequest->server->protocol == SOAP_HTTPS_PROTOCOL) { + result = capwap_socket_crypto_recv(httprequest->sslsock, buffer, len, httprequest->responsetimeout); + } + if (result > 0) { httprequest->contentlength -= result; } @@ -420,6 +456,10 @@ void ac_soapclient_free_server(struct ac_http_soap_server* server) { capwap_free(server->path); } + if (server->sslcontext) { + capwap_socket_crypto_freecontext(server->sslcontext); + } + capwap_free(server); } @@ -560,12 +600,6 @@ struct ac_http_soap_request* ac_soapclient_prepare_request(struct ac_soap_reques return NULL; } - /* Non blocking socket */ - if (!capwap_socket_nonblocking(httprequest->sock, 1)) { - ac_soapclient_close_request(httprequest, 0); - return NULL; - } - return httprequest; } @@ -587,7 +621,7 @@ int ac_soapclient_send_request(struct ac_http_soap_request* httprequest, char* s buffer = (char*)xmlBufferContent(xmlBuffer); /* Connect to remote host */ - if (!capwap_socket_connect_timeout(httprequest->sock, &httprequest->server->address, SOAP_PROTOCOL_CONNECT_TIMEOUT)) { + if (!ac_soapclient_connect(httprequest)) { xmlBufferFree(xmlBuffer); return 0; } @@ -607,9 +641,12 @@ int ac_soapclient_send_request(struct ac_http_soap_request* httprequest, char* s void ac_soapclient_shutdown_request(struct ac_http_soap_request* httprequest) { ASSERT(httprequest != NULL); + if (httprequest->sslsock) { + capwap_socket_ssl_shutdown(httprequest->sslsock, SOAP_PROTOCOL_CLOSE_TIMEOUT); + } + if (httprequest->sock >= 0) { - capwap_socket_nonblocking(httprequest->sock, 0); - shutdown(httprequest->sock, SHUT_RDWR); + capwap_socket_shutdown(httprequest->sock); } } @@ -622,10 +659,16 @@ void ac_soapclient_close_request(struct ac_http_soap_request* httprequest, int c ac_soapclient_free_request(httprequest->request); } + /* */ + if (httprequest->sslsock) { + capwap_socket_ssl_shutdown(httprequest->sslsock, SOAP_PROTOCOL_CLOSE_TIMEOUT); + capwap_socket_ssl_close(httprequest->sslsock); + capwap_free(httprequest->sslsock); + } + /* Close socket */ if (httprequest->sock >= 0) { - ac_soapclient_shutdown_request(httprequest); - close(httprequest->sock); + capwap_socket_close(httprequest->sock); } capwap_free(httprequest); diff --git a/src/ac/ac_soap.h b/src/ac/ac_soap.h index 3438298..b2879ce 100644 --- a/src/ac/ac_soap.h +++ b/src/ac/ac_soap.h @@ -16,6 +16,7 @@ #define SOAP_PROTOCOL_REQUEST_TIMEOUT 10000 #define SOAP_PROTOCOL_RESPONSE_TIMEOUT 10000 +#define SOAP_PROTOCOL_CLOSE_TIMEOUT 10000 /* */ struct ac_http_soap_server { @@ -24,6 +25,9 @@ struct ac_http_soap_server { char* host; char* path; + + /* SSL/TLS context */ + void* sslcontext; }; /* */ @@ -45,6 +49,9 @@ struct ac_http_soap_request { int requesttimeout; int responsetimeout; + /* SSL info */ + struct capwap_socket_ssl* sslsock; + /* Information for SOAP Response */ int httpstate; int responsecode; diff --git a/src/common/capwap_socket.c b/src/common/capwap_socket.c index f41607f..37eba01 100644 --- a/src/common/capwap_socket.c +++ b/src/common/capwap_socket.c @@ -1,8 +1,17 @@ #include "capwap.h" #include "capwap_socket.h" +#include +#include +#include +#include +#include + /* */ -int capwap_socket_nonblocking(int sock, int nonblocking) { +#define OPENSSL_EXDATA_PRIVATE_KEY_PASSWORD 1 + +/* */ +static int capwap_socket_nonblocking(int sock, int nonblocking) { int flags; ASSERT(sock >= 0); @@ -27,7 +36,7 @@ int capwap_socket_nonblocking(int sock, int nonblocking) { } /* */ -int capwap_socket_connect_timeout(int sock, struct sockaddr_storage* address, int timeout) { +int capwap_socket_connect(int sock, struct sockaddr_storage* address, int timeout) { int result; struct pollfd fds; socklen_t size; @@ -35,6 +44,11 @@ int capwap_socket_connect_timeout(int sock, struct sockaddr_storage* address, in ASSERT(sock >= 0); ASSERT(address != NULL); + /* Non blocking socket */ + if (!capwap_socket_nonblocking(sock, 1)) { + return 0; + } + /* */ result = connect(sock, (struct sockaddr*)address, sizeof(struct sockaddr_storage)); if (result < 0) { @@ -73,7 +87,319 @@ int capwap_socket_connect_timeout(int sock, struct sockaddr_storage* address, in } /* */ -int capwap_socket_send_timeout(int sock, void* buffer, size_t length, int timeout) { +static int capwap_socket_crypto_checkpasswd(char* buffer, int size, int rwflag, void* userdata) { + if (!userdata) { + return 0; + } + + /* */ + strncpy(buffer, (char*)userdata, size); + buffer[size - 1] = 0; + return strlen(buffer); +} + +/* */ +static int capwap_socket_crypto_verifycertificate(int preverify_ok, X509_STORE_CTX* ctx) { + int err; + X509* err_cert; + char buf[256]; + + err_cert = X509_STORE_CTX_get_current_cert(ctx); + err = X509_STORE_CTX_get_error(ctx); + X509_verify_cert_error_string(err); + + X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256); + + if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) { + X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256); + } + + return preverify_ok; +} + +/* */ +void* capwap_socket_crypto_createcontext(char* calist, char* cert, char* privatekey, char* privatekeypasswd) { + SSL_CTX* context = NULL; + + ASSERT(calist != NULL); + ASSERT(cert != NULL); + ASSERT(privatekey != NULL); + + /* Create SSL context */ + context = (void*)SSL_CTX_new(SSLv23_client_method()); + if (context) { + char* privkey = NULL; + + /* Public certificate */ + if (!SSL_CTX_use_certificate_file(context, cert, SSL_FILETYPE_PEM)) { + capwap_logging_debug("Error to load certificate file"); + capwap_socket_crypto_freecontext(context); + return NULL; + } + + /* Save private key */ + if (privatekeypasswd && *privatekeypasswd) { + privkey = capwap_duplicate_string(privatekeypasswd); + SSL_CTX_set_ex_data(context, OPENSSL_EXDATA_PRIVATE_KEY_PASSWORD, (void*)privkey); + } + + /* */ + SSL_CTX_set_default_passwd_cb(context, capwap_socket_crypto_checkpasswd); + SSL_CTX_set_default_passwd_cb_userdata(context, privkey); + + /* Private key */ + if (!SSL_CTX_use_PrivateKey_file(context, privatekey, SSL_FILETYPE_PEM)) { + capwap_logging_debug("Error to load private key file"); + capwap_socket_crypto_freecontext(context); + return NULL; + } + + if (!SSL_CTX_check_private_key(context)) { + capwap_logging_debug("Error to check private key"); + capwap_socket_crypto_freecontext(context); + return NULL; + } + + /* Certificate Authority */ + if (!SSL_CTX_load_verify_locations(context, calist, NULL)) { + capwap_logging_debug("Error to load ca file"); + capwap_socket_crypto_freecontext(context); + return NULL; + } + + /* Verify certificate callback */ + SSL_CTX_set_verify(context, SSL_VERIFY_PEER, capwap_socket_crypto_verifycertificate); + + /* Set only high security cipher list */ + if (!SSL_CTX_set_cipher_list(context, "HIGH:!DSS:!aNULL@STRENGTH")) { + capwap_logging_debug("Error to select cipher list"); + capwap_socket_crypto_freecontext(context); + return NULL; + } + + /* */ + SSL_CTX_set_mode(context, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + } + + return (void*)context; +} + +/* */ +void capwap_socket_crypto_freecontext(void* context) { + char* privkey; + SSL_CTX* sslcontext = (SSL_CTX*)context; + + if (sslcontext) { + privkey = (char*)SSL_CTX_get_ex_data(sslcontext, OPENSSL_EXDATA_PRIVATE_KEY_PASSWORD); + if (privkey) { + capwap_free(privkey); + } + + SSL_CTX_free(sslcontext); + } +} + +/* */ +struct capwap_socket_ssl* capwap_socket_ssl_connect(int sock, void* sslcontext, int timeout) { + int result; + struct pollfd fds; + struct capwap_socket_ssl* sslsock; + + ASSERT(sock >= 0); + ASSERT(sslcontext != NULL); + + /* */ + sslsock = capwap_alloc(sizeof(struct capwap_socket_ssl)); + if (!sslsock) { + capwap_outofmemory(); + } + + /* Create SSL session */ + sslsock->sock = sock; + sslsock->sslcontext = sslcontext; + sslsock->sslsession = (void*)SSL_new((SSL_CTX*)sslcontext); + if (!sslsock->sslsession) { + capwap_free(sslsock); + return NULL; + } + + /* Set socket to SSL session */ + if (!SSL_set_fd((SSL*)sslsock->sslsession, sock)) { + SSL_free((SSL*)sslsock->sslsession); + capwap_free(sslsock); + return NULL; + } + + /* Establish SSL connection */ + for (;;) { + ERR_clear_error(); + result = SSL_connect((SSL*)sslsock->sslsession); + if (result == 1) { + break; /* Connection complete */ + } else { + int error = SSL_get_error((SSL*)sslsock->sslsession, result); + if ((error == SSL_ERROR_WANT_READ) || (error == SSL_ERROR_WANT_WRITE)) { + memset(&fds, 0, sizeof(struct pollfd)); + fds.fd = sock; + fds.events = ((error == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT); + + result = poll(&fds, 1, timeout); + if (((result < 0) && (errno != EINTR)) || ((result > 0) && (fds.events != fds.revents))) { + SSL_free((SSL*)sslsock->sslsession); + capwap_free(sslsock); + return NULL; + } + } else { + SSL_free((SSL*)sslsock->sslsession); + capwap_free(sslsock); + return NULL; + } + } + } + + return sslsock; +} + +/* */ +int capwap_socket_crypto_send(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout) { + int result; + struct pollfd fds; + size_t sendlength; + + ASSERT(sslsock != NULL); + ASSERT(sslsock->sslsession != NULL); + ASSERT(sslsock->sock >= 0); + ASSERT(buffer != NULL); + ASSERT(length > 0); + + sendlength = 0; + while (sendlength < length) { + size_t leftlength = length - sendlength; + + ERR_clear_error(); + result = SSL_write((SSL*)sslsock->sslsession, &((char*)buffer)[sendlength], leftlength); + if (result > 0) { + sendlength += result; + } else { + int error = SSL_get_error((SSL*)sslsock->sslsession, result); + if ((error == SSL_ERROR_WANT_READ) || (error == SSL_ERROR_WANT_WRITE)) { + memset(&fds, 0, sizeof(struct pollfd)); + fds.fd = sslsock->sock; + fds.events = ((error == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT); + + result = poll(&fds, 1, timeout); + if (((result < 0) && (errno != EINTR)) || ((result > 0) && (fds.events != fds.revents))) { + return -1; + } + } else { + return -1; + } + } + } + + return sendlength; +} + +/* */ +int capwap_socket_crypto_recv(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout) { + int result; + struct pollfd fds; + + ASSERT(sslsock != NULL); + ASSERT(sslsock->sslsession != NULL); + ASSERT(sslsock->sock >= 0); + ASSERT(buffer != NULL); + ASSERT(length > 0); + + for (;;) { + ERR_clear_error(); + result = SSL_read((SSL*)sslsock->sslsession, buffer, length); + if (result >= 0) { + return result; + } else { + int error = SSL_get_error((SSL*)sslsock->sslsession, result); + if ((error == SSL_ERROR_WANT_READ) || (error == SSL_ERROR_WANT_WRITE)) { + memset(&fds, 0, sizeof(struct pollfd)); + fds.fd = sslsock->sock; + fds.events = ((error == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT); + + result = poll(&fds, 1, timeout); + if (((result < 0) && (errno != EINTR)) || ((result > 0) && (fds.events != fds.revents))) { + break; + } + } else { + break; + } + } + } + + return -1; +} + +/* */ +void capwap_socket_ssl_shutdown(struct capwap_socket_ssl* sslsock, int timeout) { + int result; + struct pollfd fds; + + ASSERT(sslsock != NULL); + ASSERT(sslsock->sslsession != NULL); + ASSERT(sslsock->sock >= 0); + + /* */ + for (;;) { + ERR_clear_error(); + result = SSL_shutdown((SSL*)sslsock->sslsession); + if (result >= 0) { + break; /* Shutdown complete */ + } else { + int error = SSL_get_error((SSL*)sslsock->sslsession, result); + if ((error == SSL_ERROR_WANT_READ) || (error == SSL_ERROR_WANT_WRITE)) { + memset(&fds, 0, sizeof(struct pollfd)); + fds.fd = sslsock->sock; + fds.events = ((error == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT); + + result = poll(&fds, 1, timeout); + if (((result < 0) && (errno != EINTR)) || ((result > 0) && (fds.events != fds.revents))) { + break; /* Shutdown error */ + } + } else { + break; /* Shutdown error */ + } + } + } +} + +/* */ +void capwap_socket_ssl_close(struct capwap_socket_ssl* sslsock) { + ASSERT(sslsock != NULL); + ASSERT(sslsock->sslsession != NULL); + + SSL_free((SSL*)sslsock->sslsession); + sslsock->sslsession = NULL; +} + +/* */ +void capwap_socket_shutdown(int sock) { + ASSERT(sock >= 0); + + shutdown(sock, SHUT_RDWR); +} + +/* */ +void capwap_socket_close(int sock) { + ASSERT(sock >= 0); + + capwap_socket_shutdown(sock); + capwap_socket_nonblocking(sock, 0); + close(sock); + + /* */ + ERR_clear_error(); + ERR_remove_state(0); +} + +/* */ +int capwap_socket_send(int sock, void* buffer, size_t length, int timeout) { int result; struct pollfd fds; size_t sendlength; @@ -111,7 +437,7 @@ int capwap_socket_send_timeout(int sock, void* buffer, size_t length, int timeou } /* */ -int capwap_socket_recv_timeout(int sock, void* buffer, size_t length, int timeout) { +int capwap_socket_recv(int sock, void* buffer, size_t length, int timeout) { int result; struct pollfd fds; @@ -126,19 +452,17 @@ int capwap_socket_recv_timeout(int sock, void* buffer, size_t length, int timeou result = poll(&fds, 1, timeout); if ((result < 0) && (errno != EINTR)) { - return -1; + break; } else if (result > 0) { if (fds.revents == POLLIN) { result = recv(sock, buffer, length, 0); if ((result < 0) && (errno != EINTR)) { - return -1; - } else if (!result) { - return 0; - } else if (result > 0) { + break; + } else if (result >= 0) { return result; } } else { - return -1; + break; } } } diff --git a/src/common/capwap_socket.h b/src/common/capwap_socket.h index c7c1e01..96e7b8a 100644 --- a/src/common/capwap_socket.h +++ b/src/common/capwap_socket.h @@ -2,12 +2,29 @@ #define __CAPWAP_SOCKET_HEADER__ /* */ -int capwap_socket_nonblocking(int sock, int nonblocking); +int capwap_socket_connect(int sock, struct sockaddr_storage* address, int timeout); +void capwap_socket_shutdown(int sock); +void capwap_socket_close(int sock); -/* */ -int capwap_socket_connect_timeout(int sock, struct sockaddr_storage* address, int timeout); -int capwap_socket_send_timeout(int sock, void* buffer, size_t length, int timeout); -int capwap_socket_recv_timeout(int sock, void* buffer, size_t length, int timeout); +/* Plain send/recv */ +int capwap_socket_send(int sock, void* buffer, size_t length, int timeout); +int capwap_socket_recv(int sock, void* buffer, size_t length, int timeout); +/* SSL send/recv */ +struct capwap_socket_ssl { + int sock; + void* sslcontext; + void* sslsession; +}; + +void* capwap_socket_crypto_createcontext(char* calist, char* cert, char* privatekey, char* privatekeypasswd); +void capwap_socket_crypto_freecontext(void* context); + +int capwap_socket_crypto_send(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout); +int capwap_socket_crypto_recv(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout); + +struct capwap_socket_ssl* capwap_socket_ssl_connect(int sock, void* sslcontext, int timeout); +void capwap_socket_ssl_shutdown(struct capwap_socket_ssl* sslsock, int timeout); +void capwap_socket_ssl_close(struct capwap_socket_ssl* sslsock); #endif /* __CAPWAP_SOCKET_HEADER__ */