Add support to HTTPS SOAP request

This commit is contained in:
vemax78
2013-08-06 22:15:19 +02:00
parent 9a57f2806d
commit 6b424c5406
6 changed files with 503 additions and 45 deletions

View File

@ -1,6 +1,7 @@
#include "ac.h"
#include "ac_soap.h"
#include "capwap_dtls.h"
#include "capwap_socket.h"
#include <libconfig.h>
@ -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;
}
}
}

View File

@ -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);

View File

@ -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;