From 0425aadc78680e53000fd0108b540d6eca048516 Mon Sep 17 00:00:00 2001 From: gmcdonald Date: Sat, 13 Feb 2010 01:32:03 +0000 Subject: Moving axis svn, part of TLP move INFRA-2441 git-svn-id: http://svn.apache.org/repos/asf/axis/axis2/c/core/trunk@909681 13f79535-47bb-0310-9956-ffa450edef68 --- src/core/transport/http/sender/Makefile.am | 51 + src/core/transport/http/sender/http_client.c | 965 ++++++ src/core/transport/http/sender/http_sender.c | 3332 ++++++++++++++++++++ .../transport/http/sender/http_transport_sender.c | 859 +++++ src/core/transport/http/sender/libcurl/Makefile.am | 2 + .../transport/http/sender/libcurl/axis2_libcurl.c | 1169 +++++++ .../transport/http/sender/libcurl/axis2_libcurl.h | 53 + .../transport/http/sender/libcurl/libcurl_stream.c | 192 ++ .../transport/http/sender/libcurl/libcurl_stream.h | 51 + src/core/transport/http/sender/ssl/Makefile.am | 2 + src/core/transport/http/sender/ssl/ssl_stream.c | 239 ++ src/core/transport/http/sender/ssl/ssl_stream.h | 50 + src/core/transport/http/sender/ssl/ssl_utils.c | 227 ++ src/core/transport/http/sender/ssl/ssl_utils.h | 56 + 14 files changed, 7248 insertions(+) create mode 100644 src/core/transport/http/sender/Makefile.am create mode 100644 src/core/transport/http/sender/http_client.c create mode 100644 src/core/transport/http/sender/http_sender.c create mode 100644 src/core/transport/http/sender/http_transport_sender.c create mode 100644 src/core/transport/http/sender/libcurl/Makefile.am create mode 100644 src/core/transport/http/sender/libcurl/axis2_libcurl.c create mode 100644 src/core/transport/http/sender/libcurl/axis2_libcurl.h create mode 100644 src/core/transport/http/sender/libcurl/libcurl_stream.c create mode 100644 src/core/transport/http/sender/libcurl/libcurl_stream.h create mode 100644 src/core/transport/http/sender/ssl/Makefile.am create mode 100644 src/core/transport/http/sender/ssl/ssl_stream.c create mode 100644 src/core/transport/http/sender/ssl/ssl_stream.h create mode 100644 src/core/transport/http/sender/ssl/ssl_utils.c create mode 100644 src/core/transport/http/sender/ssl/ssl_utils.h (limited to 'src/core/transport/http/sender') diff --git a/src/core/transport/http/sender/Makefile.am b/src/core/transport/http/sender/Makefile.am new file mode 100644 index 0000000..399ed39 --- /dev/null +++ b/src/core/transport/http/sender/Makefile.am @@ -0,0 +1,51 @@ +SUBDIRS=ssl libcurl +lib_LTLIBRARIES = libaxis2_http_sender.la + + + +if AXIS2_LIBCURL_ENABLED +LIBCURL_SOURCES=libcurl/axis2_libcurl.c\ + libcurl/libcurl_stream.c +LIBCURL_LIBS=-lssl -lcrypto -lcurl -ldl -lz +else +LIBCURL_SOURCES= +LIBCURL_LIBS= +endif + + +if AXIS2_SSL_ENABLED +SSL_SOURCES = ssl/ssl_stream.c\ + ssl/ssl_utils.c +SSL_LIBS = -lssl -lcrypto +else +SSL_SOURCES= +SSL_LIBS= +endif + +libaxis2_http_sender_la_SOURCES = http_transport_sender.c \ + http_sender.c \ + http_client.c \ + $(SSL_SOURCES) \ + $(LIBCURL_SOURCES) + +libaxis2_http_sender_la_LIBADD = $(top_builddir)/src/core/transport/http/common/libaxis2_http_common.la\ + $(top_builddir)/src/core/transport/http/util/libaxis2_http_util.la\ + $(top_builddir)/axiom/src/om/libaxis2_axiom.la\ + $(top_builddir)/util/src/libaxutil.la\ + $(LIBCURL_LIBS)\ + $(SSL_LIBS) + + +libaxis2_http_sender_la_LDFLAGS = -version-info $(VERSION_NO) + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/core/transport\ + -I$(top_builddir)/src/core/transport/http \ + -I$(top_builddir)/src/core/transport/http/sender/libcurl \ + -I$(top_builddir)/src/core/description \ + -I$(top_builddir)/src/core/context \ + -I$(top_builddir)/src/core/phaseresolver \ + -I$(top_builddir)/src/core/engine \ + -I$(top_builddir)/src/core/deployment \ + -I$(top_builddir)/util/include \ + -I$(top_builddir)/axiom/include diff --git a/src/core/transport/http/sender/http_client.c b/src/core/transport/http/sender/http_client.c new file mode 100644 index 0000000..80e7ee3 --- /dev/null +++ b/src/core/transport/http/sender/http_client.c @@ -0,0 +1,965 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef AXIS2_SSL_ENABLED +#include "ssl/ssl_stream.h" +#endif + +struct axis2_http_client +{ + int sockfd; + axutil_stream_t *data_stream; + axutil_url_t *url; + axis2_http_simple_response_t *response; + axis2_bool_t request_sent; + int timeout; + axis2_bool_t proxy_enabled; + axis2_char_t *proxy_host; + int proxy_port; + axis2_char_t *proxy_host_port; + axis2_bool_t dump_input_msg; + axis2_char_t *server_cert; + axis2_char_t *key_file; + axis2_char_t *req_body; + int req_body_size; + + /* These are for mtom case */ + axutil_array_list_t *mime_parts; + axis2_bool_t doing_mtom; + axis2_char_t *mtom_sending_callback_name; +}; + +AXIS2_EXTERN axis2_http_client_t *AXIS2_CALL +axis2_http_client_create( + const axutil_env_t * env, + axutil_url_t * url) +{ + axis2_http_client_t *http_client = NULL; + + http_client = (axis2_http_client_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_http_client_t)); + + if(!http_client) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + memset(http_client, 0, sizeof(axis2_http_client_t)); + + http_client->url = url; + http_client->data_stream = NULL; + http_client->sockfd = -1; + http_client->response = NULL; + http_client->request_sent = AXIS2_FALSE; + + /* default timeout is 60000 milliseconds */ + http_client->timeout = AXIS2_HTTP_DEFAULT_CONNECTION_TIMEOUT; + http_client->proxy_enabled = AXIS2_FALSE; + http_client->proxy_port = 0; + http_client->proxy_host = NULL; + http_client->proxy_host_port = NULL; + http_client->dump_input_msg = AXIS2_FALSE; + http_client->server_cert = NULL; + http_client->key_file = NULL; + http_client->req_body = NULL; + http_client->req_body_size = 0; + http_client->mime_parts = NULL; + http_client->doing_mtom = AXIS2_FALSE; + http_client->mtom_sending_callback_name = NULL; + + return http_client; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_client_free( + axis2_http_client_t * http_client, + const axutil_env_t * env) +{ + if(http_client->proxy_host) + { + AXIS2_FREE(env->allocator, http_client->proxy_host); + } + if(http_client->proxy_host_port) + { + AXIS2_FREE(env->allocator, http_client->proxy_host_port); + } + if(http_client->url) + { + axutil_url_free(http_client->url, env); + } + if(http_client->response) + { + axis2_http_simple_response_free(http_client->response, env); + } + if(-1 != http_client->sockfd) + { + axutil_network_handler_close_socket(env, http_client->sockfd); + http_client->sockfd = -1; + } + + if(http_client->req_body) + { + AXIS2_FREE(env->allocator, http_client->req_body); + } + + /* There is no other appropriate place to free the mime_part list when a + * particular client send requests. */ + + if(http_client->mime_parts) + { + int i = 0; + for(i = 0; i < axutil_array_list_size(http_client->mime_parts, env); i++) + { + axiom_mime_part_t *mime_part = NULL; + mime_part = (axiom_mime_part_t *)axutil_array_list_get(http_client->mime_parts, env, i); + if(mime_part) + { + axiom_mime_part_free(mime_part, env); + } + } + axutil_array_list_free(http_client->mime_parts, env); + } + + AXIS2_FREE(env->allocator, http_client); + return; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_client_free_void_arg( + void *client, + const axutil_env_t * env) +{ + axis2_http_client_t *client_l = NULL; + + client_l = (axis2_http_client_t *)client; + axis2_http_client_free(client_l, env); + return; +} + +/* This is the main method which writes to the socket in the case of a client + * sends an http_request. Previously this method does not distinguish between a + * mtom request and non mtom request. Because what finally it had was the + * complete buffer with the request. But now MTOM invocations are done + * differently in order to support large attachments so this method should + * distinguish those invocations */ + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_send( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_http_simple_request_t * request, + axis2_char_t * ssl_pp) +{ + char *wire_format = NULL; + axutil_array_list_t *headers = NULL; + char *str_header = NULL; + char *str_request_line = NULL; + int written = 0; + axis2_status_t status = AXIS2_FAILURE; + axis2_bool_t chunking_enabled = AXIS2_FALSE; + axis2_char_t *host = NULL; + unsigned int port = 0; + + /* In the MTOM case request body is not set. Instead mime_parts + array_list is there */ + + if(client->req_body) + { + AXIS2_FREE(env->allocator, client->req_body); + client->req_body = NULL; + } + if(!client->req_body && !(client->doing_mtom)) + { + client->req_body_size = axis2_http_simple_request_get_body_bytes(request, env, + &client->req_body); + } + + if(client->dump_input_msg == AXIS2_TRUE) + { + return AXIS2_SUCCESS; + } + + if(!client->url) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_URL, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Request url not set"); + return AXIS2_FAILURE; + } + + host = axutil_url_get_host(client->url, env); + port = axutil_url_get_port(client->url, env); + + if(client->proxy_enabled) + { + if(!client->proxy_host || client->proxy_port <= 0) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Proxy port or Host not set"); + return AXIS2_FAILURE; + } + + if(client->sockfd < 0) + { + client->sockfd = (int)axutil_network_handler_open_socket(env, client->proxy_host, + client->proxy_port); + } + } + else + { + /*Proxy is not enabled*/ + + if(client->sockfd < 0) + { + client->sockfd = (int)axutil_network_handler_open_socket(env, host, port); + } + } + + if(client->sockfd < 0) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Socket Creation failed."); + return AXIS2_FAILURE; + } + + if(client->timeout > 0) + { + /*Set the receiving time out*/ + axutil_network_handler_set_sock_option(env, client->sockfd, SO_RCVTIMEO, client->timeout); + /*Set the sending time out*/ + + axutil_network_handler_set_sock_option(env, client->sockfd, SO_SNDTIMEO, client->timeout); + } + + if(0 == axutil_strcasecmp(axutil_url_get_protocol(client->url, env), AXIS2_TRANSPORT_URL_HTTPS)) + { +#ifdef AXIS2_SSL_ENABLED + if (client->proxy_enabled) + { + if (AXIS2_SUCCESS != axis2_http_client_connect_ssl_host(client, env, host, port)) + { + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "HTTPS connection creation failed"); + return AXIS2_FAILURE; + } + } + client->data_stream = + axutil_stream_create_ssl(env, client->sockfd, axis2_http_client_get_server_cert(client, + env), axis2_http_client_get_key_file(client, env), ssl_pp); +#else + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_TRANSPORT_PROTOCOL, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Invalid Transport Protocol, HTTPS transport not enabled."); + + return AXIS2_FAILURE; +#endif + } + else + { + client->data_stream = axutil_stream_create_socket(env, client->sockfd); + } + + if(!client->data_stream) + { + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Data stream creation failed for Host %s and %d port", host, port); + + return AXIS2_FAILURE; + } + + /*Accessing HTTP headers*/ + + headers = axis2_http_simple_request_get_headers(request, env); + if(headers) + { + int header_count = axutil_array_list_size(headers, env); + int i = 0; + char *str_header2 = NULL; + for(i = 0; i < header_count; i++) + { + axis2_char_t *header_ext_form = NULL; + axis2_http_header_t *tmp_header = (axis2_http_header_t *)axutil_array_list_get(headers, + env, i); + + if(!tmp_header) + { + /* This continue is added as a safey mechanism, + * However I see a problem with this logic, AFAIC + * see there can't be null headers in the headers + * array list, because number of headers in "headers" + * array list count with axutil_array_list_size, + * therefore this check and continue might not have a + * real effect.*/ + + continue; + } + + /* check whether we have transfer encoding and then see whether the + * value is "chunked" */ + if(!axutil_strcmp(axis2_http_header_get_name(tmp_header, env), + AXIS2_HTTP_HEADER_TRANSFER_ENCODING) && !axutil_strcmp(axis2_http_header_get_value( + tmp_header, env), AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)) + { + chunking_enabled = AXIS2_TRUE; + } + + header_ext_form = axis2_http_header_to_external_form(tmp_header, env); + + /* str_header2 is to hold intermediate value of str_header */ + str_header2 = axutil_stracat(env, str_header, header_ext_form); + if(str_header) + { + AXIS2_FREE(env->allocator, str_header); + str_header = NULL; + } + if(header_ext_form) + { + AXIS2_FREE(env->allocator, header_ext_form); + header_ext_form = NULL; + } + + /* str_header has all HTTP headers to send. */ + str_header = str_header2; + } + } + + if(AXIS2_FALSE == client->proxy_enabled) + { + str_request_line = axis2_http_request_line_to_string( + axis2_http_simple_request_get_request_line(request, env), env); + } + else + { + /* proxy enabled case */ + + /* we need the request line in the format + * POST http://host:port/path HTTP/1.x if we have enabled proxies + */ + axis2_char_t *host_port_str = NULL; + axis2_char_t *host = axutil_url_get_host(client->url, env); + axis2_http_request_line_t *request_line = axis2_http_simple_request_get_request_line( + request, env); + axis2_char_t *path = axis2_http_request_line_get_uri(request_line, env); + + host_port_str = AXIS2_MALLOC(env->allocator, axutil_strlen(host) + axutil_strlen(path) + 20 + * sizeof(axis2_char_t)); + + if(!host_port_str) + { + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Memory allocation failed for host %s and %s path", host, path); + + return AXIS2_FAILURE; + } + + sprintf(host_port_str, "http://%s:%d%s", host, axutil_url_get_port(client->url, env), path); + str_request_line = AXIS2_MALLOC(env->allocator, axutil_strlen(host_port_str) + 20 + * sizeof(axis2_char_t)); + + if(!str_request_line) + { + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_FREE(env->allocator, host_port_str); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "memory allocation failed for host %s and %s path", host, path); + + return AXIS2_FAILURE; + } + + sprintf(str_request_line, "%s %s %s\r\n", axis2_http_request_line_get_method(request_line, + env), host_port_str, axis2_http_request_line_get_http_version(request_line, env)); + + AXIS2_FREE(env->allocator, host_port_str); + host_port_str = NULL; + + } + + /* Here first we send the http header part */ + + wire_format = axutil_stracat(env, str_request_line, str_header); + AXIS2_FREE(env->allocator, str_header); + str_header = NULL; + AXIS2_FREE(env->allocator, str_request_line); + str_request_line = NULL; + written + = axutil_stream_write(client->data_stream, env, wire_format, axutil_strlen(wire_format)); + AXIS2_FREE(env->allocator, wire_format); + wire_format = NULL; + + /* Then we write the two new line charaters before the http body*/ + + written = axutil_stream_write(client->data_stream, env, AXIS2_HTTP_CRLF, 2); + + /* When sending MTOM it is bit different. We keep the attachment + other + mime headers in an array_list and send them one by one */ + + if(client->doing_mtom) + { + axis2_status_t status = AXIS2_SUCCESS; + axutil_http_chunked_stream_t *chunked_stream = NULL; + + /* If the callback name is not there, then we will check whether there + * is any mime_parts which has type callback. If we found then no point + * of continuing we should return a failure */ + + if(!(client->mtom_sending_callback_name)) + { + if(axis2_http_transport_utils_is_callback_required(env, client->mime_parts)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Sender callback not specified"); + return AXIS2_FAILURE; + } + } + + /* For MTOM we automatically enabled chunking */ + chunked_stream = axutil_http_chunked_stream_create(env, client->data_stream); + + /* This method will write the Attachment + data to the wire */ + + status = axis2_http_transport_utils_send_mtom_message(chunked_stream, env, + client->mime_parts, client->mtom_sending_callback_name); + + axutil_http_chunked_stream_free(chunked_stream, env); + chunked_stream = NULL; + + } + /* Non MTOM case */ + else if(client->req_body_size > 0 && client->req_body) + { + int len = 0; + written = 0; + + /* Keep on writing data in a loop until we finised + with all the data in the buffer */ + + if(!chunking_enabled) + { + status = AXIS2_SUCCESS; + while(written < client->req_body_size) + { + len = 0; + len = axutil_stream_write(client->data_stream, env, client->req_body + written, + client->req_body_size - written); + if(-1 == len) + { + status = AXIS2_FAILURE; + break; + } + else + { + written += len; + } + } + } + else + { + /* Not MTOM but chunking is enabled */ + axutil_http_chunked_stream_t *chunked_stream = NULL; + chunked_stream = axutil_http_chunked_stream_create(env, client->data_stream); + status = AXIS2_SUCCESS; + if(!chunked_stream) + { + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Creatoin of chunked stream failed"); + return AXIS2_FAILURE; + } + + while(written < client->req_body_size) + { + written = axutil_http_chunked_stream_write(chunked_stream, env, client->req_body, + client->req_body_size); + + if(-1 == written) + { + status = AXIS2_FAILURE; + break; + } + } + + if(AXIS2_SUCCESS == status) + { + /* Writing the trailing null charactor */ + axutil_http_chunked_stream_write_last_chunk(chunked_stream, env); + } + + axutil_http_chunked_stream_free(chunked_stream, env); + } + } + + client->request_sent = AXIS2_TRUE; + return status; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_http_client_recieve_header( + axis2_http_client_t * client, + const axutil_env_t * env) +{ + int status_code = -1; + axis2_http_status_line_t *status_line = NULL; + axis2_char_t str_status_line[512]; + axis2_char_t tmp_buf[3]; + axis2_char_t str_header[512]; + int read = 0; + int http_status = 0; + axis2_bool_t end_of_line = AXIS2_FALSE; + axis2_bool_t end_of_headers = AXIS2_FALSE; + + if(-1 == client->sockfd || !client->data_stream || AXIS2_FALSE == client->request_sent) + { + axis2_char_t *host; + unsigned int port; + host = axutil_url_get_host(client->url, env); + port = axutil_url_get_port(client->url, env); + + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "client data stream null or socket error for host \ +%s and %d port", host, port); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_REQUEST_NOT_SENT, AXIS2_FAILURE); + return -1; + } + + /* read the status line */ + do + { + memset(str_status_line, 0, 512); + while((read = axutil_stream_read(client->data_stream, env, tmp_buf, 1)) > 0) + { + /* "read" variable is number of characters read by stream */ + tmp_buf[read] = '\0'; + strcat(str_status_line, tmp_buf); + if(0 != strstr(str_status_line, AXIS2_HTTP_CRLF)) + { + end_of_line = AXIS2_TRUE; + break; + } + } + + if(read < 0) + { + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "http client , response timed out"); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_RESPONSE_TIMED_OUT, AXIS2_FAILURE); + return -1; + } + else if(read == 0) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_RESPONSE_SERVER_SHUTDOWN, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Response error, Server Shutdown"); + return 0; + } + + status_line = axis2_http_status_line_create(env, str_status_line); + if(!status_line) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "axis2_http_status_line_create failed for \ +str_status_line %s", str_status_line); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + http_status = 0; + continue; + + } + http_status = axis2_http_status_line_get_status_code(status_line, env); + + } + while(AXIS2_HTTP_RESPONSE_OK_CODE_VAL > http_status); + + if(client->response) + axis2_http_simple_response_free(client->response, env); + client->response = axis2_http_simple_response_create_default(env); + axis2_http_simple_response_set_status_line(client->response, env, + axis2_http_status_line_get_http_version(status_line, env), + axis2_http_status_line_get_status_code(status_line, env), + axis2_http_status_line_get_reason_phrase(status_line, env)); + + /* now read the headers */ + memset(str_header, 0, 512); + end_of_line = AXIS2_FALSE; + while(AXIS2_FALSE == end_of_headers) + { + while((read = axutil_stream_read(client->data_stream, env, tmp_buf, 1)) > 0) + { + tmp_buf[read] = '\0'; + strcat(str_header, tmp_buf); + if(0 != strstr(str_header, AXIS2_HTTP_CRLF)) + { + end_of_line = AXIS2_TRUE; + break; + } + } + if(AXIS2_TRUE == end_of_line) + { + if(0 == axutil_strcmp(str_header, AXIS2_HTTP_CRLF)) + { + end_of_headers = AXIS2_TRUE; + } + else + { + axis2_http_header_t *tmp_header = axis2_http_header_create_by_str(env, str_header); + memset(str_header, 0, 512); + if(tmp_header) + { + axis2_http_simple_response_set_header(client->response, env, tmp_header); + } + } + } + end_of_line = AXIS2_FALSE; + } + axis2_http_simple_response_set_body_stream(client->response, env, client->data_stream); + if(status_line) + { + status_code = axis2_http_status_line_get_status_code(status_line, env); + axis2_http_status_line_free(status_line, env); + status_line = NULL; + } + + if(AXIS2_FALSE == axis2_http_simple_response_contains_header(client->response, env, + AXIS2_HTTP_HEADER_CONTENT_TYPE) && 202 != status_code + && axis2_http_simple_response_get_content_length(client->response, env) > 0) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_RESPONSE_CONTENT_TYPE_MISSING, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Response does not contain" " Content-Type"); + return -1; + } + return status_code; +} + +AXIS2_EXTERN axis2_http_simple_response_t *AXIS2_CALL +axis2_http_client_get_response( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + return client->response; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_url( + axis2_http_client_t * client, + const axutil_env_t * env, + axutil_url_t * url) +{ + AXIS2_PARAM_CHECK(env->error, url, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + + if(client->url) + { + axutil_url_free(client->url, env); + client->url = NULL; + } + client->url = url; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axutil_url_t *AXIS2_CALL +axis2_http_client_get_url( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, client, NULL); + return client->url; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_timeout( + axis2_http_client_t * client, + const axutil_env_t * env, + int timeout_ms) +{ + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + client->timeout = timeout_ms; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_http_client_get_timeout( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + return client->timeout; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_proxy( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_char_t * proxy_host, + int proxy_port) +{ + AXIS2_PARAM_CHECK(env->error, proxy_host, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + + if(proxy_port <= 0) + { + return AXIS2_FAILURE; + } + + client->proxy_port = proxy_port; + if(client->proxy_host) + { + AXIS2_FREE(env->allocator, client->proxy_host); + client->proxy_host = NULL; + } + + if(client->proxy_host_port) + { + AXIS2_FREE(env->allocator, client->proxy_host_port); + client->proxy_host_port = NULL; + } + + client->proxy_host = axutil_strdup(env, proxy_host); + if(!client->proxy_host) + { + return AXIS2_FAILURE; + } + + client->proxy_host_port = AXIS2_MALLOC(env->allocator, axutil_strlen(proxy_host) + 10 + * sizeof(axis2_char_t)); + + sprintf(client->proxy_host_port, "%s:%d", proxy_host, proxy_port); + client->proxy_enabled = AXIS2_TRUE; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_client_get_proxy( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, client, NULL); + return client->proxy_host_port; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_connect_ssl_host( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_char_t * host, + int port) +{ + axutil_stream_t *tmp_stream = NULL; + axis2_char_t *connect_string = NULL; + axis2_char_t str_status_line[512]; + axis2_char_t tmp_buf[3]; + int read = 0; + axis2_bool_t end_of_line = AXIS2_FALSE; + axis2_bool_t end_of_response = AXIS2_FALSE; + axis2_http_status_line_t *status_line = NULL; + + AXIS2_PARAM_CHECK(env->error, host, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, client->url, AXIS2_FAILURE); + /* This host and port will use for give undersandable log messages + * */ + + if(port <= 0) + { + return AXIS2_FAILURE; + } + + tmp_stream = axutil_stream_create_socket(env, client->sockfd); + if(!tmp_stream) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "unable to create open socket for ssl host %s and %d \ +port", host, port); + return AXIS2_FAILURE; + } + + connect_string = AXIS2_MALLOC(env->allocator, axutil_strlen(host) * sizeof(axis2_char_t) + 30 + * sizeof(axis2_char_t)); + sprintf(connect_string, "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port); + axutil_stream_write(tmp_stream, env, connect_string, axutil_strlen(connect_string) + * sizeof(axis2_char_t)); + + memset(str_status_line, 0, 512); + while((read = axutil_stream_read(tmp_stream, env, tmp_buf, 1)) > 0) + { + tmp_buf[read] = '\0'; + strcat(str_status_line, tmp_buf); + if(0 != strstr(str_status_line, AXIS2_HTTP_CRLF)) + { + end_of_line = AXIS2_TRUE; + break; + } + } + if(read < 0) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_RESPONSE_TIMED_OUT, AXIS2_FAILURE); + AXIS2_FREE(env->allocator, connect_string); + axutil_stream_free(tmp_stream, env); + return AXIS2_FAILURE; + } + status_line = axis2_http_status_line_create(env, str_status_line); + if(!status_line) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + AXIS2_FREE(env->allocator, connect_string); + axutil_stream_free(tmp_stream, env); + return AXIS2_FAILURE; + } + if(200 != axis2_http_status_line_get_status_code(status_line, env)) + { + AXIS2_FREE(env->allocator, connect_string); + axutil_stream_free(tmp_stream, env); + return AXIS2_FAILURE; + } + /* We need to empty the stream before we return + */ + memset(str_status_line, 0, 512); + while(AXIS2_FALSE == end_of_response) + { + while((read = axutil_stream_read(tmp_stream, env, tmp_buf, 1)) > 0) + { + tmp_buf[read] = '\0'; + strcat(str_status_line, tmp_buf); + if(0 != strstr(str_status_line, AXIS2_HTTP_CRLF)) + { + end_of_line = AXIS2_TRUE; + break; + } + } + if(AXIS2_TRUE == end_of_line) + { + if(0 == axutil_strcmp(str_status_line, AXIS2_HTTP_CRLF)) + { + end_of_response = AXIS2_TRUE; + } + } + } + AXIS2_FREE(env->allocator, connect_string); + axutil_stream_free(tmp_stream, env); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_dump_input_msg( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_bool_t dump_input_msg) +{ + client->dump_input_msg = dump_input_msg; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_server_cert( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_char_t * server_cert) +{ + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, server_cert, AXIS2_FAILURE); + client->server_cert = server_cert; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_client_get_server_cert( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + return client->server_cert; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_key_file( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_char_t * key_file) +{ + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, key_file, AXIS2_FAILURE); + client->key_file = key_file; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_client_get_key_file( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + return client->key_file; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_mime_parts( + axis2_http_client_t * client, + const axutil_env_t * env, + axutil_array_list_t *mime_parts) +{ + client->mime_parts = mime_parts; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL +axis2_http_client_get_mime_parts( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + return client->mime_parts; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_doing_mtom( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_bool_t doing_mtom) +{ + client->doing_mtom = doing_mtom; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_client_get_doing_mtom( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + return client->doing_mtom; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_mtom_sending_callback_name( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_char_t *callback_name) +{ + client->mtom_sending_callback_name = callback_name; + return AXIS2_SUCCESS; +} diff --git a/src/core/transport/http/sender/http_sender.c b/src/core/transport/http/sender/http_sender.c new file mode 100644 index 0000000..56f11e0 --- /dev/null +++ b/src/core/transport/http/sender/http_sender.c @@ -0,0 +1,3332 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef AXIS2_LIBCURL_ENABLED +#include "libcurl/axis2_libcurl.h" +#else +#define CLIENT_NONCE_LENGTH 8 +#endif + +struct axis2_http_sender +{ + axis2_char_t *http_version; + axis2_bool_t chunked; + int so_timeout; + axiom_output_t *om_output; + axis2_http_client_t *client; + axis2_bool_t is_soap; + axis2_bool_t keep_alive; +}; + +#ifndef AXIS2_LIBCURL_ENABLED +static void +axis2_http_sender_add_header_list( + axis2_http_simple_request_t * request, + const axutil_env_t * env, + axutil_array_list_t * array_list); + +static axis2_status_t +axis2_http_sender_configure_proxy( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +static axis2_status_t +axis2_http_sender_configure_server_cert( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +static axis2_status_t +axis2_http_sender_configure_key_file( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +static axis2_status_t +axis2_http_sender_configure_http_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_configure_proxy_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_set_http_auth_type( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_set_proxy_auth_type( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_configure_http_basic_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_configure_proxy_basic_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_configure_http_digest_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request, + axis2_char_t * header_data); + +static axis2_status_t +axis2_http_sender_configure_proxy_digest_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request, + axis2_char_t * header_data); + + + +#endif + +static axutil_hash_t * +axis2_http_sender_connection_map_create( + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx); + +static void +axis2_http_sender_connection_map_remove( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx, + axis2_http_client_t *http_client); + +static void +axis2_http_sender_connection_map_add( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx, + axis2_http_client_t *http_client); + +static axis2_http_client_t * +axis2_http_sender_connection_map_get( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx); + +static void AXIS2_CALL +axis2_http_sender_connection_map_free( + void *cm_void, + const axutil_env_t *env); + +AXIS2_EXTERN axis2_http_sender_t *AXIS2_CALL +axis2_http_sender_create( + const axutil_env_t * env) +{ + axis2_http_sender_t *sender = NULL; + + sender = (axis2_http_sender_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_http_sender_t)); + + if(!sender) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + memset(sender, 0, sizeof(axis2_http_sender_t)); + sender->http_version = (axis2_char_t *)AXIS2_HTTP_HEADER_PROTOCOL_11; + sender->so_timeout = AXIS2_HTTP_DEFAULT_SO_TIMEOUT; + /* unlike the java impl we don't have a default om output + * it should be explicitly set and it's a MUST + */ + sender->om_output = NULL; + sender->chunked = AXIS2_FALSE; + sender->client = NULL; + sender->keep_alive = AXIS2_TRUE; + + return sender; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_sender_free( + axis2_http_sender_t * sender, + const axutil_env_t * env) +{ + if(sender->http_version) + { + AXIS2_FREE(env->allocator, sender->http_version); + } + + /* Do not free this here since it will be required in later processing + * of the response soap message + */ + sender->client = NULL; + AXIS2_FREE(env->allocator, sender); + return; +} + +#ifndef AXIS2_LIBCURL_ENABLED +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_send( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axiom_soap_envelope_t * out, + const axis2_char_t * str_url, + const axis2_char_t * soap_action) +{ + axis2_http_simple_request_t *request = NULL; + axis2_http_request_line_t *request_line = NULL; + + /* url is to hold url given in str_url */ + axutil_url_t *url = NULL; + axiom_xml_writer_t *xml_writer = NULL; + axis2_char_t *buffer = NULL; + unsigned int buffer_size = 0; + const axis2_char_t *char_set_enc = NULL; + axutil_string_t *char_set_enc_str = NULL; + int status_code = -1; + axis2_http_simple_response_t *response = NULL; + axis2_char_t *content_type = NULL; + axis2_bool_t content_type_deepl_copy = AXIS2_TRUE; + axis2_byte_t *output_stream = NULL; + int output_stream_size = 0; + axis2_bool_t doing_mtom = AXIS2_FALSE; + axutil_property_t *dump_property = NULL; + axutil_param_t *ssl_pp_param = NULL; + /* ssl passphrase */ + axis2_char_t *ssl_pp = NULL; + axutil_property_t *ssl_pp_property = NULL; + axutil_property_t *test_auth_property = NULL; + axis2_char_t *test_auth_property_value = NULL; + axis2_bool_t test_proxy_auth = AXIS2_FALSE; + axis2_bool_t test_http_auth = AXIS2_FALSE; + + /* http proxy authentication */ + axutil_property_t *proxy_auth_property = NULL; + axis2_char_t *proxy_auth_property_value = NULL; + axis2_bool_t force_proxy_auth = AXIS2_FALSE; + axis2_bool_t force_proxy_auth_with_head = AXIS2_FALSE; + axutil_property_t *http_auth_property = NULL; + axis2_char_t *http_auth_property_value = NULL; + axis2_bool_t force_http_auth = AXIS2_FALSE; + axis2_bool_t force_http_auth_with_head = AXIS2_FALSE; + axutil_property_t *content_type_property = NULL; + axutil_hash_t *content_type_hash = NULL; + axis2_char_t *content_type_value = NULL; + axutil_property_t *method = NULL; + axis2_char_t *method_value = NULL; + + /* handling REST requests */ + axis2_bool_t send_via_get = AXIS2_FALSE; + axis2_bool_t send_via_head = AXIS2_FALSE; + axis2_bool_t send_via_delete = AXIS2_FALSE; + axis2_bool_t send_via_put = AXIS2_FALSE; + axiom_node_t *data_out = NULL; + axiom_node_t *body_node = NULL; + axiom_soap_body_t *soap_body = NULL; + axis2_bool_t is_soap = AXIS2_TRUE; + axis2_bool_t add_keepalive_header = AXIS2_FALSE; + + /* http header property to get HTTP headers from msg_ctx and give + * it to http_sender */ + axutil_property_t *http_property = NULL; + axutil_array_list_t *array_list; + axis2_bool_t http_auth_header_added = AXIS2_FALSE; + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_out_desc_t *trans_desc = NULL; + axutil_param_t *write_xml_declaration_param = NULL; + axutil_hash_t *transport_attrs = NULL; + axis2_bool_t write_xml_declaration = AXIS2_FALSE; + axutil_property_t *property = NULL;/* Property for holding http client */ + /*axis2_char_t *header_value = NULL;*/ + axis2_char_t *cookie_str = NULL; + axutil_hash_t *connection_map = NULL; + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Entry:axis2_http_sender_send"); + soap_body = axiom_soap_envelope_get_body(out, env); + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, out, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, str_url, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, soap_action, AXIS2_FAILURE); + + if(AXIS2_TRUE == axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + is_soap = AXIS2_FALSE; + } + else + { + is_soap = AXIS2_TRUE; + } + + url = axutil_url_parse_string(env, str_url); + + if(!is_soap) + { + if(soap_body) + { + body_node = axiom_soap_body_get_base_node(soap_body, env); + } + if(body_node) + { + data_out = axiom_node_get_first_element(body_node, env); + } + + method = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_METHOD); + if(method) + { + method_value = (axis2_char_t *)axutil_property_get_value(method, env); + } + + /* The default is POST */ + if(method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_GET)) + { + send_via_get = AXIS2_TRUE; + } + else if(method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_HEAD)) + { + send_via_head = AXIS2_TRUE; + } + else if(method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_PUT)) + { + send_via_put = AXIS2_TRUE; + } + else if(method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_DELETE)) + { + send_via_delete = AXIS2_TRUE; + } + } + + if(!url) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "url is null for string %s", str_url); + return AXIS2_FAILURE; + } + + /*if(sender->client) + { + axis2_http_client_free(sender->client, env); + sender->client = NULL; + }*/ + + /* This property may be set by the application client. This get the priority over the keep alive + * parameter set in the axix2.xml + */ + property = (axutil_property_t *) axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_HTTP_HEADER_CONNECTION_KEEPALIVE); + if(property) + { + axis2_char_t *keep_alive_value = NULL; + + keep_alive_value = axutil_property_get_value(property, env); + if(!axutil_strcmp(keep_alive_value, AXIS2_VALUE_FALSE)) + { + sender->keep_alive = AXIS2_FALSE; + } + } + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + if(conf_ctx) + { + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + } + + /* Because keep alive is not still supported at callback receiver we check + * for client side + */ + if(sender->keep_alive && !axis2_msg_ctx_get_server_side(msg_ctx, env)) + { + axutil_property_t *connection_map_property = NULL; + + connection_map_property = axis2_conf_ctx_get_property(conf_ctx, env, + AXIS2_HTTP_CONNECTION_MAP); + if(!connection_map_property) + { + connection_map = axis2_http_sender_connection_map_create(env, msg_ctx); + if(!connection_map) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return AXIS2_FAILURE; + } + } + else + { + connection_map = axutil_property_get_value(connection_map_property, env); + if(connection_map) + { + sender->client = axis2_http_sender_connection_map_get(connection_map, env, msg_ctx); + } + } + if(!axutil_strcasecmp(sender->http_version, AXIS2_HTTP_HEADER_PROTOCOL_10)) + { + add_keepalive_header = AXIS2_TRUE; + } + } /* End if sender->keep_alive */ + if(!sender->client) + { + sender->client = axis2_http_client_create(env, url); + } + if(!sender->client) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "sender->client creation failed for url %s", url); + return AXIS2_FAILURE; + } + /* configure proxy settings if we have set so + */ + + axis2_http_sender_configure_proxy(sender, env, msg_ctx); + + if(conf) + { + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + } + + if(trans_desc) + { + /* get xml declaration details from axis2.xml */ + write_xml_declaration_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, AXIS2_XML_DECLARATION); + } + + if(write_xml_declaration_param) + { + /* accessing attributes of the HTTP transport's , xml + * declaration element from axis2.xml*/ + + transport_attrs = axutil_param_get_attributes(write_xml_declaration_param, env); + if(transport_attrs) + { + axutil_generic_obj_t *obj = NULL; + axiom_attribute_t *write_xml_declaration_attr = NULL; + axis2_char_t *write_xml_declaration_attr_value = NULL; + + obj + = axutil_hash_get(transport_attrs, AXIS2_ADD_XML_DECLARATION, AXIS2_HASH_KEY_STRING); + if(obj) + { + write_xml_declaration_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, + env); + } + + if(write_xml_declaration_attr) + { + write_xml_declaration_attr_value = axiom_attribute_get_value( + write_xml_declaration_attr, env); + } + + if(write_xml_declaration_attr_value && 0 == axutil_strcasecmp( + write_xml_declaration_attr_value, AXIS2_VALUE_TRUE)) + { + write_xml_declaration = AXIS2_TRUE; + } + } + } + + if(write_xml_declaration) + { + axiom_output_write_xml_version_encoding(sender->om_output, env); + } + + if(!send_via_get && !send_via_head && !send_via_delete) + { + /* processing POST and PUT methods */ + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "msg_ctx_id:%s", axis2_msg_ctx_get_msg_id(msg_ctx, + env)); + + doing_mtom = axis2_msg_ctx_get_doing_mtom(msg_ctx, env); + + if(!sender->om_output) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_OM_OUTPUT, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "%s", AXIS2_ERROR_GET_MESSAGE(env->error)); + return AXIS2_FAILURE; + } + + xml_writer = axiom_output_get_xml_writer(sender->om_output, env); + + char_set_enc_str = axis2_msg_ctx_get_charset_encoding(msg_ctx, env); + + if(!char_set_enc_str) + { + /* if there is no character encoding details available + * use default one. + * #define AXIS2_DEFAULT_CHAR_SET_ENCODING "UTF-8" + */ + char_set_enc = AXIS2_DEFAULT_CHAR_SET_ENCODING; + } + else + { + char_set_enc = axutil_string_get_buffer(char_set_enc_str, env); + } + + if(!send_via_put && is_soap) + { + /* HTTP POST case */ + /* dump property use to dump message without sending */ + dump_property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_DUMP_INPUT_MSG_TRUE); + if(dump_property) + { + axis2_char_t *dump_true = axutil_property_get_value(dump_property, env); + if(0 == axutil_strcmp(dump_true, AXIS2_VALUE_TRUE)) + { + axis2_http_client_set_dump_input_msg(sender->client, env, AXIS2_TRUE); + } + } + + axiom_output_set_do_optimize(sender->om_output, env, doing_mtom); + axiom_soap_envelope_serialize(out, env, sender->om_output, AXIS2_FALSE); + } + else if(is_soap) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Attempt to send SOAP message using HTTP PUT failed"); + return AXIS2_FAILURE; + } + else + { + if(!data_out) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "body node payload is NULL"); + return AXIS2_FAILURE; + } + axiom_node_serialize(data_out, env, sender->om_output); + } + + if(doing_mtom) + { + axutil_param_t *callback_name_param = NULL; + axis2_status_t mtom_status = AXIS2_FAILURE; + axutil_array_list_t *mime_parts = NULL; + axis2_char_t *mtom_sending_callback_name = NULL; + + /* Getting the sender callback name paramter if it is + * specified in the configuration file */ + + callback_name_param = axis2_msg_ctx_get_parameter(msg_ctx, env, + AXIS2_MTOM_SENDING_CALLBACK); + if(callback_name_param) + { + mtom_sending_callback_name = (axis2_char_t *)axutil_param_get_value( + callback_name_param, env); + if(mtom_sending_callback_name) + { + axis2_http_client_set_mtom_sending_callback_name(sender->client, env, + mtom_sending_callback_name); + } + } + + /* Here we put all the attachment related stuff in a array_list + After this method we have the message in parts */ + + mtom_status = axiom_output_flush(sender->om_output, env); + if(mtom_status == AXIS2_FAILURE) + { + return mtom_status; + } + /* HTTP client should distinguish an MTOM invocation because the way + of sending the message in MTOM case is different */ + axis2_http_client_set_doing_mtom(sender->client, env, doing_mtom); + + /* HTTP client will keep this mime_parts, which it will send in chunks at + th end */ + mime_parts = axiom_output_get_mime_parts(sender->om_output, env); + if(mime_parts) + { + axis2_http_client_set_mime_parts(sender->client, env, mime_parts); + } + } + else + { + buffer = axiom_xml_writer_get_xml(xml_writer, env); + } + + if(!(buffer || doing_mtom)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "NULL xml returned from xml writer"); + return AXIS2_FAILURE; + } + + if(!send_via_put) + { + /* HTTP POST */ + axis2_char_t *path_with_query = NULL; + + path_with_query = axutil_strcat(env, axutil_url_get_path(url, env), + axutil_url_get_query(url, env), NULL); + request_line = axis2_http_request_line_create(env, AXIS2_HTTP_POST, path_with_query, + sender->http_version); + AXIS2_FREE(env->allocator, path_with_query); + } + else + { + /* HTTP PUT */ + request_line = axis2_http_request_line_create(env, AXIS2_HTTP_PUT, axutil_url_get_path( + url, env), sender->http_version); + } + } + else + { + /* Processing HTTP GET, HEAD and DELETE */ + + axis2_char_t *request_params = NULL; + axis2_char_t *path = NULL; + + request_params = axis2_http_sender_get_param_string(sender, env, msg_ctx); + + if(request_params) + { + /* substituting AXIS2_Q_MARK for "?" */ + path = axutil_strcat(env, axutil_url_get_path(url, env), AXIS2_Q_MARK_STR, + request_params, NULL); + AXIS2_FREE(env->allocator, request_params); + request_params = NULL; + } + else + { + path = axutil_strdup(env, axutil_url_get_path(url, env)); + } + + if(send_via_get) + { + request_line = axis2_http_request_line_create(env, AXIS2_HTTP_GET, path, + sender->http_version); + } + else if(send_via_head) + { + request_line = axis2_http_request_line_create(env, AXIS2_HTTP_HEAD, path, + sender->http_version); + } + else if(send_via_delete) + { + request_line = axis2_http_request_line_create(env, AXIS2_HTTP_DELETE, path, + sender->http_version); + } + + if(path) + { + AXIS2_FREE(env->allocator, path); + path = NULL; + } + } + + request = axis2_http_simple_request_create(env, request_line, NULL, 0, NULL); + if(add_keepalive_header) + { + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_CONNECTION, + AXIS2_HTTP_HEADER_CONNECTION_KEEPALIVE); + } + /** + * If there is a session related stuff handle it + */ + /*header_value = axis2_http_transport_utils_get_session(env, msg_ctx); + if(header_value) + { + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_SET_COOKIE, header_value); + }*/ + + /** + * In the client side sender if a cookie is sent by server add it to the http header + */ + cookie_str = axis2_http_transport_utils_read_from_cookie_store(env, msg_ctx); + if(cookie_str) + { + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_COOKIE, cookie_str); + } + + /* User-Agent:Axis2/C header */ + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_USER_AGENT, AXIS2_USER_AGENT); + + http_property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_TRANSPORT_HEADER_PROPERTY); + if(http_property) + { + array_list = (axutil_array_list_t *)axutil_property_get_value(http_property, env); + axis2_http_sender_add_header_list(request, env, array_list); + } + + if(!send_via_get && !send_via_head && !send_via_put && !send_via_delete && AXIS2_TRUE + == axis2_msg_ctx_get_is_soap_11(msg_ctx, env)) + { + if(AXIS2_ESC_DOUBLE_QUOTE != *soap_action) + { + axis2_char_t *tmp_soap_action = NULL; + tmp_soap_action = AXIS2_MALLOC(env->allocator, (axutil_strlen(soap_action) + 5) + * sizeof(axis2_char_t)); + sprintf(tmp_soap_action, "\"%s\"", soap_action); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_SOAP_ACTION, + tmp_soap_action); + AXIS2_FREE(env->allocator, tmp_soap_action); + } + else + { + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_SOAP_ACTION, + (const axis2_char_t *)soap_action); + } + } + else if(AXIS2_TRUE == axis2_msg_ctx_get_is_soap_11(msg_ctx, env)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Adding of SOAP Action Failed for REST request"); + + return AXIS2_FAILURE; + } + + if(!send_via_get && !send_via_head && !send_via_delete) + { + /* processing PUT and POST */ + buffer_size = axiom_xml_writer_get_xml_size(xml_writer, env); + + if(AXIS2_FALSE == sender->chunked) + { + axis2_char_t tmp_buf[10]; + if(!buffer) + { + buffer_size = output_stream_size; + } + + if(buffer_size) + { + sprintf(tmp_buf, "%d", buffer_size); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_CONTENT_LENGTH, + tmp_buf); + } + } + else + { + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_TRANSFER_ENCODING, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED); + } + + if(!send_via_put && is_soap) + { + /* HTTP POST */ + if(doing_mtom) + { + content_type = (axis2_char_t *)axiom_output_get_content_type(sender-> om_output, + env); + if(AXIS2_TRUE != axis2_msg_ctx_get_is_soap_11(msg_ctx, env) && axutil_strcmp( + soap_action, "")) + { + /* handle SOAP action for SOAP 1.2 case */ + axis2_char_t *temp_content_type = NULL; + temp_content_type + = axutil_stracat(env, content_type, AXIS2_CONTENT_TYPE_ACTION); + content_type = temp_content_type; + temp_content_type = axutil_stracat(env, content_type, soap_action); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + temp_content_type = axutil_stracat(env, content_type, + AXIS2_ESC_DOUBLE_QUOTE_STR); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + } + else + { + content_type_deepl_copy = AXIS2_FALSE; + } + } + else if(AXIS2_TRUE == axis2_msg_ctx_get_is_soap_11(msg_ctx, env)) + { + /* SOAP 1.1 without MTOM */ + axis2_char_t *temp_content_type = NULL; + content_type = (axis2_char_t *)AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML; + content_type = axutil_stracat(env, content_type, AXIS2_CONTENT_TYPE_CHARSET); + temp_content_type = axutil_stracat(env, content_type, char_set_enc); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + } + else + { + /* SOAP 1.2 without MTOM */ + axis2_char_t *temp_content_type = NULL; + content_type = (axis2_char_t *)AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP; + content_type = axutil_stracat(env, content_type, AXIS2_CONTENT_TYPE_CHARSET); + temp_content_type = axutil_stracat(env, content_type, char_set_enc); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + if(axutil_strcmp(soap_action, "")) + { + temp_content_type + = axutil_stracat(env, content_type, AXIS2_CONTENT_TYPE_ACTION); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + temp_content_type = axutil_stracat(env, content_type, soap_action); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + temp_content_type = axutil_stracat(env, content_type, + AXIS2_ESC_DOUBLE_QUOTE_STR); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + } + } + } + else if(is_soap) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Attempt to send SOAP message using HTTP PUT failed"); + return AXIS2_FAILURE; + } + else + { + content_type_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_USER_DEFINED_HTTP_HEADER_CONTENT_TYPE); + + if(content_type_property) + { + content_type_hash = (axutil_hash_t *)axutil_property_get_value( + content_type_property, env); + if(content_type_hash) + { + content_type_value = (char *)axutil_hash_get(content_type_hash, + AXIS2_HTTP_HEADER_CONTENT_TYPE, AXIS2_HASH_KEY_STRING); + } + } + + if(content_type_value) + { + content_type = content_type_value; + } + else + { + content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML; + } + + content_type_deepl_copy = AXIS2_FALSE; + } + + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_CONTENT_TYPE, + content_type); + + if(content_type_deepl_copy && content_type) + { + AXIS2_FREE(env->allocator, content_type); + content_type = NULL; + } + /* Finished Processing PUT and POST */ + } + + if(0 == axutil_strcasecmp(sender->http_version, AXIS2_HTTP_HEADER_PROTOCOL_11)) + { + /* HTTP 1.1 */ + axis2_char_t *header = NULL; + int host_len = 0; + host_len = axutil_strlen(axutil_url_get_host(url, env)); + header = AXIS2_MALLOC(env->allocator, host_len + 10 * sizeof(axis2_char_t)); + sprintf(header, "%s:%d", axutil_url_get_host(url, env), axutil_url_get_port(url, env)); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_HOST, header); + AXIS2_FREE(env->allocator, header); + header = NULL; + } + + /* If this is a normal invocation the buffer has the full SOAP message + which needs to be send. In the MTOM case instead of this buffer + it has the mime_parts array_list */ + + if(!doing_mtom) + { + axis2_http_simple_request_set_body_string(request, env, buffer, buffer_size); + } + + /* HTTPS request processing */ + axis2_http_sender_configure_server_cert(sender, env, msg_ctx); + + axis2_http_sender_configure_key_file(sender, env, msg_ctx); + + axis2_http_sender_get_timeout_values(sender, env, msg_ctx); + axis2_http_client_set_timeout(sender->client, env, sender->so_timeout); + + ssl_pp_property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_SSL_PASSPHRASE); + + if(ssl_pp_property) + { + ssl_pp = (axis2_char_t *)axutil_property_get_value(ssl_pp_property, env); + } + else + { + ssl_pp_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_SSL_PASSPHRASE); + + if(ssl_pp_param) + { + ssl_pp = axutil_param_get_value(ssl_pp_param, env); + } + } + + test_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_TEST_PROXY_AUTH); + if(test_auth_property) + { + test_auth_property_value = (axis2_char_t *)axutil_property_get_value(test_auth_property, + env); + } + + if(test_auth_property_value && 0 == axutil_strcmp(test_auth_property_value, AXIS2_VALUE_TRUE)) + { + test_proxy_auth = AXIS2_TRUE; + } + + test_auth_property = NULL; + test_auth_property_value = NULL; + + test_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_TEST_HTTP_AUTH); + if(test_auth_property) + { + test_auth_property_value = (axis2_char_t *)axutil_property_get_value(test_auth_property, + env); + } + + if(test_auth_property_value && 0 == axutil_strcmp(test_auth_property_value, AXIS2_VALUE_TRUE)) + { + test_http_auth = AXIS2_TRUE; + } + + if(!test_proxy_auth) + { + proxy_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_FORCE_PROXY_AUTH); + } + if(proxy_auth_property) + { + proxy_auth_property_value = (axis2_char_t *)axutil_property_get_value(proxy_auth_property, + env); + } + + if(proxy_auth_property_value && 0 == axutil_strcmp(proxy_auth_property_value, AXIS2_VALUE_TRUE)) + { + force_proxy_auth = AXIS2_TRUE; + } + + proxy_auth_property = NULL; + proxy_auth_property_value = NULL; + + if(force_proxy_auth) + { + proxy_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_PROXY_AUTH_TYPE); + } + + if(proxy_auth_property) + { + proxy_auth_property_value = (axis2_char_t *)axutil_property_get_value(proxy_auth_property, + env); + } + + if(proxy_auth_property_value && 0 == axutil_strcmp(proxy_auth_property_value, + AXIS2_PROXY_AUTH_TYPE_DIGEST)) + { + force_proxy_auth = AXIS2_FALSE; + force_proxy_auth_with_head = AXIS2_TRUE; + } + + if(!test_http_auth) + { + http_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_FORCE_HTTP_AUTH); + } + + if(http_auth_property) + { + http_auth_property_value = (axis2_char_t *)axutil_property_get_value(http_auth_property, + env); + } + + if(http_auth_property_value && 0 == axutil_strcmp(http_auth_property_value, AXIS2_VALUE_TRUE)) + { + force_http_auth = AXIS2_TRUE; + } + + http_auth_property = NULL; + http_auth_property_value = NULL; + + if(force_http_auth) + { + http_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_HTTP_AUTH_TYPE); + } + + if(http_auth_property) + { + http_auth_property_value = (axis2_char_t *)axutil_property_get_value(http_auth_property, + env); + } + + if(http_auth_property_value && 0 == axutil_strcmp(http_auth_property_value, + AXIS2_HTTP_AUTH_TYPE_DIGEST)) + { + force_http_auth = AXIS2_FALSE; + force_http_auth_with_head = AXIS2_TRUE; + } + + axis2_msg_ctx_set_auth_type(msg_ctx, env, NULL); + + if(force_proxy_auth || force_proxy_auth_with_head) + { + status_code = AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL; + } + else + { + /* NOT forcing proxy authentication */ + if(force_http_auth) + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_http_auth(sender, env, msg_ctx, request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting HTTP Authentication header"); + } + http_auth_header_added = AXIS2_TRUE; + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + + else if(force_http_auth_with_head) + { + axis2_http_request_line_t *head_request_line = NULL; + axis2_http_request_line_t *temp = NULL; + + temp = axis2_http_simple_request_get_request_line(request, env); + head_request_line = axis2_http_request_line_create(env, AXIS2_HTTP_HEAD, + axis2_http_request_line_get_uri(temp, env), + axis2_http_request_line_get_http_version(temp, env)); + axis2_http_simple_request_set_request_line(request, env, head_request_line); + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + axis2_http_simple_request_set_request_line(request, env, temp); + axis2_http_request_line_free(head_request_line, env); + + if(status_code == AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL) + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_http_auth(sender, env, msg_ctx, request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting HTTP Authentication\ + header"); + } + http_auth_header_added = AXIS2_TRUE; + } + + if(status_code != AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL) + { + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + + if(status_code == AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL) + { + http_auth_header_added = AXIS2_FALSE; + force_http_auth_with_head = AXIS2_FALSE; + } + } + } + else + { + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + } + + if(AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL == status_code + && !test_proxy_auth) + { + if(force_proxy_auth_with_head) + { + axis2_http_request_line_t *head_request_line = NULL; + axis2_http_request_line_t *temp = NULL; + + temp = axis2_http_simple_request_get_request_line(request, env); + head_request_line = axis2_http_request_line_create(env, AXIS2_HTTP_HEAD, + axis2_http_request_line_get_uri(temp, env), + axis2_http_request_line_get_http_version(temp, env)); + axis2_http_simple_request_set_request_line(request, env, head_request_line); + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + axis2_http_simple_request_set_request_line(request, env, temp); + axis2_http_request_line_free(head_request_line, env); + + if(status_code == AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL) + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_proxy_auth(sender, env, msg_ctx, request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting Proxy Authentication\ + header"); + } + + if((force_http_auth_with_head || force_http_auth) && !http_auth_header_added) + { + status_code = AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL; + } + else + { + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + } + else if(status_code != AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL) + { + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + + /* Proxies have no idea about HTTP Methods therefore, if + * it fails no need to re-check */ + if(AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL == status_code) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Proxy Authentication failed"); + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_FALSE); + } + } + else + { + + /* not forcing proxy auth with head */ + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_proxy_auth(sender, env, msg_ctx, request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting Proxy Authentication \ +header"); + } + + if((force_http_auth_with_head || force_http_auth) && !http_auth_header_added) + { + status_code = AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL; + } + else + { + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + + if(AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL == status_code) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Proxy Authentication failed"); + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_FALSE); + } + } + } + } + else if(AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL == status_code) + { + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_FALSE); + axis2_http_sender_set_proxy_auth_type(sender, env, msg_ctx, request); + } + + if(AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL == status_code && !test_http_auth) + { + if(!http_auth_header_added) + { + if(force_proxy_auth_with_head) + { + axis2_http_request_line_t *head_request_line = NULL; + axis2_http_request_line_t *temp = NULL; + + temp = axis2_http_simple_request_get_request_line(request, env); + head_request_line = axis2_http_request_line_create(env, AXIS2_HTTP_HEAD, + axis2_http_request_line_get_uri(temp, env), + axis2_http_request_line_get_http_version(temp, env)); + axis2_http_simple_request_set_request_line(request, env, head_request_line); + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + axis2_http_simple_request_set_request_line(request, env, temp); + axis2_http_request_line_free(head_request_line, env); + + if(status_code == AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL) + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_http_auth(sender, env, msg_ctx, + request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting HTTP Authentication \ +header"); + } + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + if(status_code == AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL) + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_http_auth(sender, env, msg_ctx, + request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting HTTP \ +Authentication header"); + } + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + + } + } + else + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_http_auth(sender, env, msg_ctx, request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting HTTP Authentication \ +header"); + } + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + + if(AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL == status_code) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "HTTP Authentication failed"); + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_TRUE); + } + + if(AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL == status_code) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Proxy Authentication failed"); + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_FALSE); + } + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "HTTP Authentication failed"); + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_TRUE); + } + } + else if(AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL == status_code) + { + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_TRUE); + axis2_http_sender_set_http_auth_type(sender, env, msg_ctx, request); + } + + axis2_http_simple_request_free(request, env); + request = NULL; + + if(output_stream) + { + AXIS2_FREE(env->allocator, output_stream); + output_stream = NULL; + } + + if(status_code < 0) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "status_code < 0"); + return AXIS2_FAILURE; + } + + axis2_msg_ctx_set_status_code(msg_ctx, env, status_code); + + /* Start processing response */ + response = axis2_http_client_get_response(sender->client, env); + if(!is_soap) + { + return axis2_http_sender_process_response(sender, env, msg_ctx, response); + } + else if(AXIS2_HTTP_RESPONSE_OK_CODE_VAL == status_code || AXIS2_HTTP_RESPONSE_ACK_CODE_VAL + == status_code) + { + return axis2_http_sender_process_response(sender, env, msg_ctx, response); + } + else if(AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_VAL == status_code) + { + axis2_http_header_t *tmp_header = NULL; + axis2_char_t *tmp_header_val = NULL; + axis2_op_t *op = NULL; + + op = axis2_msg_ctx_get_op(msg_ctx, env); + if(op) + { + const axis2_char_t *mep = axis2_op_get_msg_exchange_pattern(op, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + /* handle one way case */ + + if(!axutil_strcmp(mep, AXIS2_MEP_URI_OUT_ONLY)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "mep is AXIS2_MEP_URI_OUT_ONLY"); + return AXIS2_FAILURE; + } + } + + /* set an error to indicate error code status */ + tmp_header = axis2_http_simple_response_get_first_header(response, env, + AXIS2_HTTP_HEADER_CONTENT_TYPE); + if(tmp_header) + { + tmp_header_val = axis2_http_header_get_value(tmp_header, env); + } + + if(tmp_header_val && (axutil_strstr(tmp_header_val, AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP) + || axutil_strstr(tmp_header_val, AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML))) + { + return axis2_http_sender_process_response(sender, env, msg_ctx, response); + } + } + + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_sender_send"); + return AXIS2_FAILURE; +} +#endif + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_set_chunked( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_bool_t chunked) +{ + sender->chunked = chunked; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_set_om_output( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axiom_output_t * om_output) +{ + sender->om_output = om_output; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_get_header_info( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_response_t * response) +{ + axutil_array_list_t *headers = NULL; + axis2_char_t *charset = NULL; + int i = 0; + axis2_bool_t response_chunked = AXIS2_FALSE; + int *content_length = NULL; + axutil_property_t *property = NULL; + axis2_char_t *content_type = NULL; + int status_code = 0; + axis2_bool_t set_cookie_header_present = AXIS2_FALSE; + axis2_bool_t connection_header_present = AXIS2_FALSE; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, response, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, sender, AXIS2_FAILURE); + + headers = axis2_http_simple_response_get_headers(response, env); + if(headers == NULL) + { + return AXIS2_SUCCESS; + } + + for(i = 0; i < axutil_array_list_size(headers, env); i++) + { + axis2_http_header_t *header = axutil_array_list_get(headers, env, i); + axis2_char_t *name = axis2_http_header_get_name((axis2_http_header_t *)header, env); + if(name) + { + if(0 == axutil_strcasecmp(name, AXIS2_HTTP_HEADER_TRANSFER_ENCODING) && 0 + == axutil_strcasecmp(axis2_http_header_get_value(header, env), + AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)) + { + axis2_char_t *transfer_encoding = NULL; + transfer_encoding = axutil_strdup(env, AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED); + response_chunked = AXIS2_TRUE; + axis2_msg_ctx_set_transfer_encoding(msg_ctx, env, transfer_encoding); + + } + if(0 != axutil_strcasecmp(name, AXIS2_HTTP_HEADER_CONTENT_TYPE)) + { + axis2_char_t *tmp_charset = NULL; + axis2_char_t *content_type = axis2_http_header_get_value(header, env); + tmp_charset = strstr(content_type, AXIS2_HTTP_CHAR_SET_ENCODING); + if(charset) + { + charset = axutil_strdup(env, tmp_charset); + break; + } + } + if(!axutil_strcasecmp(name, AXIS2_HTTP_HEADER_SET_COOKIE)) + { + axis2_char_t *cookie_str = axis2_http_header_get_value(header, env); + if(cookie_str) + { + axis2_http_transport_utils_store_cookie(env, msg_ctx, cookie_str); + } + set_cookie_header_present = AXIS2_TRUE; + } + + if(!axutil_strcasecmp(name, AXIS2_HTTP_HEADER_CONNECTION)) + { + axis2_char_t *connection_header_value = NULL; + axutil_property_t *connection_map_property = NULL; + axutil_hash_t *connection_map = NULL; + axis2_conf_ctx_t *conf_ctx = NULL; + connection_header_present = AXIS2_TRUE; + connection_header_value = axis2_http_header_get_value(header, env); + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + connection_map_property = axis2_conf_ctx_get_property(conf_ctx, env, + AXIS2_HTTP_CONNECTION_MAP); + + if(connection_map_property) + { + connection_map = axutil_property_get_value(connection_map_property, env); + } + /** + * In HTTP1.1 if connection header has value close then drop the connection + */ + if(connection_header_value && !axutil_strcasecmp(connection_header_value, "close")) + { + if(connection_map) + { + axis2_http_sender_connection_map_remove(connection_map, env, + msg_ctx, sender->client); + } + } + else if(connection_header_value && !axutil_strcasecmp(connection_header_value, + "Keep-Alive")) + { + if(connection_map) + { + axis2_http_sender_connection_map_add(connection_map, env, + msg_ctx, sender->client); + } + } + } /* End if name is connection */ + } /* End if name of the header present */ + } + if(!set_cookie_header_present) /* We need to remove any cookie set previously for this endpoint */ + { + axis2_http_transport_utils_store_cookie(env, msg_ctx, NULL); + } + if(!connection_header_present) /* No connection header present */ + { + /** In HTTP1.0 if there is no keep alive header sent back from server we drop the + * connection + */ + axutil_property_t *connection_map_property = NULL; + axutil_hash_t *connection_map = NULL; + axis2_conf_ctx_t *conf_ctx = NULL; + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + + connection_map_property = axis2_conf_ctx_get_property(conf_ctx, env, + AXIS2_HTTP_CONNECTION_MAP); + if(connection_map_property) + { + connection_map = axutil_property_get_value(connection_map_property, env); + } /* End if connectin_map_property */ + if(!axutil_strcasecmp(sender->http_version, AXIS2_HTTP_HEADER_PROTOCOL_10)) + { + if(connection_map) + { + axis2_http_sender_connection_map_remove(connection_map, env, msg_ctx, + sender->client); + } + } /* End if http version 1.0 */ + else if(!axutil_strcasecmp(sender->http_version, AXIS2_HTTP_HEADER_PROTOCOL_11)) + { + /** + * If keep alive enabled we store the http client for reuse. + */ + if(connection_map) + { + axis2_http_sender_connection_map_add(connection_map, env, msg_ctx, + sender->client); + } + } /* End if http version 1.1 */ + } /* End if !connection_header_present */ + + content_type = (axis2_char_t *)axis2_http_simple_response_get_content_type(response, env); + if(content_type) + { + if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_MULTIPART_RELATED) && strstr(content_type, + AXIS2_HTTP_HEADER_ACCEPT_XOP_XML)) + { + axis2_ctx_t *axis_ctx = axis2_op_ctx_get_base(axis2_msg_ctx_get_op_ctx(msg_ctx, env), + env); + property = axutil_property_create(env); + axutil_property_set_scope(property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_value(property, env, axutil_strdup(env, content_type)); + axis2_ctx_set_property(axis_ctx, env, MTOM_RECIVED_CONTENT_TYPE, property); + } + } + + if(charset) + { + axis2_ctx_t *axis_ctx = axis2_op_ctx_get_base(axis2_msg_ctx_get_op_ctx(msg_ctx, env), env); + if(axis_ctx) + { + property = axutil_property_create(env); + axutil_property_set_scope(property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_value(property, env, charset); + axis2_ctx_set_property(axis_ctx, env, AXIS2_CHARACTER_SET_ENCODING, property); + } + } + + if(AXIS2_FALSE == response_chunked) + { + int tmp_len = 0; + content_length = AXIS2_MALLOC(env->allocator, sizeof(int)); + if(!content_length) + { + return AXIS2_FAILURE; + } + tmp_len = axis2_http_simple_response_get_content_length(response, env); + memcpy(content_length, &tmp_len, sizeof(int)); + property = axutil_property_create(env); + axutil_property_set_scope(property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_value(property, env, content_length); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_HEADER_CONTENT_LENGTH, property); + } + + status_code = axis2_http_simple_response_get_status_code(response, env); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_process_response( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_response_t * response) +{ + axutil_stream_t *in_stream = NULL; + axutil_property_t *property = NULL; + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Entry:axis2_http_sender_process_response"); + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, response, AXIS2_FAILURE); + + in_stream = axis2_http_simple_response_get_body(response, env); + if(!in_stream) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_STREAM_IN_RESPONSE_BODY, AXIS2_FAILURE); + return AXIS2_FAILURE; + } + + axis2_http_sender_get_header_info(sender, env, msg_ctx, response); + axis2_msg_ctx_set_http_output_headers(msg_ctx, env, axis2_http_simple_response_extract_headers( + response, env)); + property = axutil_property_create(env); + axutil_property_set_scope(property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_free_func(property, env, axutil_stream_free_void_arg); + axutil_property_set_value(property, env, in_stream); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_TRANSPORT_IN, property); + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_sender_process_response"); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_get_timeout_values( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axis2_char_t *so_str = NULL; + axis2_char_t *connection_str = NULL; + axutil_param_t *tmp_param = NULL; + axutil_property_t *property = NULL; + + AXIS2_PARAM_CHECK(env->error, sender, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + /* check if timeout has been set by user using options + * with axis2_options_set_timeout_in_milli_seconds + */ + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_CONNECTION_TIMEOUT); + if(property) + { + axis2_char_t *value = axutil_property_get_value(property, env); + if(value) + { + sender->so_timeout = AXIS2_ATOI(value); + return AXIS2_SUCCESS; + } + } + + tmp_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_HTTP_SO_TIMEOUT); + + if(tmp_param) + { + so_str = (axis2_char_t *)axutil_param_get_value(tmp_param, env); + if(so_str) + { + sender->so_timeout = AXIS2_ATOI(so_str); + return AXIS2_SUCCESS; + } + } + + tmp_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_HTTP_CONNECTION_TIMEOUT); + if(tmp_param) + { + connection_str = (axis2_char_t *)axutil_param_get_value(tmp_param, env); + if(connection_str) + { + sender->so_timeout = AXIS2_ATOI(connection_str); + return AXIS2_SUCCESS; + } + } + return AXIS2_FAILURE; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_set_http_version( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_char_t * version) +{ + sender->http_version = axutil_strdup(env, version); + if(!sender->http_version) + { + return AXIS2_FAILURE; + } + return AXIS2_SUCCESS; +} + +#ifndef AXIS2_LIBCURL_ENABLED +static void +axis2_http_sender_add_header_list( + axis2_http_simple_request_t * request, + const axutil_env_t * env, + axutil_array_list_t * array_list) +{ + int ii = 0; + int kk = 0; + axis2_http_header_t *http_header = NULL; + ii = axutil_array_list_size(array_list, env); + for(; kk < ii; kk++) + { + http_header = (axis2_http_header_t *)axutil_array_list_get(array_list, env, kk); + axis2_http_simple_request_add_header(request, env, http_header); + } +} + +static axis2_status_t +axis2_http_sender_configure_proxy( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_out_desc_t *trans_desc = NULL; + axutil_param_t *proxy_param = NULL; + axutil_hash_t *transport_attrs = NULL; + axis2_char_t *proxy_host = NULL; + axis2_char_t *proxy_port = NULL; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + if(!conf_ctx) + { + return AXIS2_FAILURE; + } + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + if(!conf) + { + return AXIS2_FAILURE; + } + + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + if(!trans_desc) + { + return AXIS2_FAILURE; + } + + proxy_param = axutil_param_container_get_param(axis2_transport_out_desc_param_container( + trans_desc, env), env, AXIS2_HTTP_PROXY_API); + if(!proxy_param) + { + proxy_param = axutil_param_container_get_param(axis2_transport_out_desc_param_container( + trans_desc, env), env, AXIS2_HTTP_PROXY); + } + if(proxy_param) + { + transport_attrs = axutil_param_get_attributes(proxy_param, env); + if(transport_attrs) + { + axutil_generic_obj_t *obj = NULL; + axiom_attribute_t *host_attr = NULL; + axiom_attribute_t *port_attr = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_HOST, AXIS2_HASH_KEY_STRING); + if(!obj) + { + return AXIS2_FAILURE; + } + host_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + if(!host_attr) + { + return AXIS2_FAILURE; + } + proxy_host = axiom_attribute_get_value(host_attr, env); + if(!proxy_host) + { + return AXIS2_FAILURE; + } + /* Now we get the port */ + obj = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_PORT, AXIS2_HASH_KEY_STRING); + port_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + if(!port_attr) + { + return AXIS2_FAILURE; + } + proxy_port = axiom_attribute_get_value(port_attr, env); + if(!proxy_port) + { + return AXIS2_FAILURE; + } + } + } + if(proxy_port && proxy_host) + { + axis2_http_client_set_proxy(sender->client, env, proxy_host, AXIS2_ATOI(proxy_port)); + } + return AXIS2_SUCCESS; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_configure_server_cert( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axutil_property_t *server_cert_property = NULL; + axutil_param_t *server_cert_param = NULL; + axis2_char_t *server_cert = NULL; + axis2_status_t status = AXIS2_FAILURE; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + + server_cert_property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_SSL_SERVER_CERT); + if(server_cert_property) + { + server_cert = (axis2_char_t *)axutil_property_get_value(server_cert_property, env); + } + else + { + server_cert_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_SSL_SERVER_CERT); + if(server_cert_param) + { + server_cert = (axis2_char_t *)axutil_param_get_value(server_cert_param, env); + } + } + + if(server_cert) + { + status = axis2_http_client_set_server_cert(sender->client, env, server_cert); + } + + return status; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_configure_key_file( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axutil_property_t *key_file_property = NULL; + axutil_param_t *key_file_param = NULL; + axis2_char_t *key_file = NULL; + axis2_status_t status = AXIS2_FAILURE; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + + key_file_property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_SSL_KEY_FILE); + if(key_file_property) + { + key_file = (axis2_char_t *)axutil_property_get_value(key_file_property, env); + } + else + { + key_file_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_SSL_KEY_FILE); + if(key_file_param) + { + key_file = (axis2_char_t *)axutil_param_get_value(key_file_param, env); + } + } + + if(key_file) + { + status = axis2_http_client_set_key_file(sender->client, env, key_file); + } + + return status; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_configure_http_basic_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axutil_property_t *http_auth_un = NULL; + axutil_property_t *http_auth_pw = NULL; + axis2_char_t *uname = NULL; + axis2_char_t *passwd = NULL; + + http_auth_un = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_UNAME); + http_auth_pw = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_PASSWD); + if(http_auth_un && http_auth_pw) + { + uname = (axis2_char_t *)axutil_property_get_value(http_auth_un, env); + passwd = (axis2_char_t *)axutil_property_get_value(http_auth_pw, env); + } + if(!uname || !passwd) + { + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_out_desc_t *trans_desc = NULL; + axutil_param_t *http_auth_param = NULL; + axutil_hash_t *transport_attrs = NULL; + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + if(conf_ctx) + { + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + if(conf) + { + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + } + } + if(trans_desc) + { + http_auth_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, + AXIS2_HTTP_AUTHENTICATION); + if(http_auth_param) + { + transport_attrs = axutil_param_get_attributes(http_auth_param, env); + if(transport_attrs) + { + axutil_generic_obj_t *obj = NULL; + axiom_attribute_t *username_attr = NULL; + axiom_attribute_t *password_attr = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_AUTHENTICATION_USERNAME, + AXIS2_HASH_KEY_STRING); + if(obj) + { + username_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(username_attr) + { + uname = axiom_attribute_get_value(username_attr, env); + } + obj = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_AUTHENTICATION_PASSWORD, + AXIS2_HASH_KEY_STRING); + if(obj) + { + password_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(password_attr) + { + passwd = axiom_attribute_get_value(password_attr, env); + } + } + } + } + } + if(uname && passwd) + { + int elen; + int plen = axutil_strlen(uname) + axutil_strlen(passwd) + 1; + axis2_char_t *to_encode = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, + sizeof(axis2_char_t) * plen + 1)); + axis2_char_t *encoded = NULL; + axis2_char_t *auth_str = NULL; + sprintf(to_encode, "%s:%s", uname, passwd); + elen = axutil_base64_encode_len(plen); + encoded = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * elen)); + auth_str + = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (elen + 6))); + axutil_base64_encode(encoded, to_encode, plen); + sprintf(auth_str, "%s %s", AXIS2_HTTP_AUTH_TYPE_BASIC, encoded); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_AUTHORIZATION, auth_str); + + AXIS2_FREE(env->allocator, to_encode); + to_encode = NULL; + AXIS2_FREE(env->allocator, encoded); + encoded = NULL; + AXIS2_FREE(env->allocator, auth_str); + auth_str = NULL; + + return AXIS2_SUCCESS; + } + + return AXIS2_FAILURE; + +} + +static axis2_status_t +axis2_http_sender_configure_proxy_basic_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axutil_property_t *proxy_auth_un = NULL; + axutil_property_t *proxy_auth_pw = NULL; + axis2_char_t *uname = NULL; + axis2_char_t *passwd = NULL; + + proxy_auth_un = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_UNAME); + proxy_auth_pw = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_PASSWD); + + if(proxy_auth_un && proxy_auth_pw) + { + uname = (axis2_char_t *)axutil_property_get_value(proxy_auth_un, env); + passwd = (axis2_char_t *)axutil_property_get_value(proxy_auth_pw, env); + } + if(!uname || !passwd) + { + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_out_desc_t *trans_desc = NULL; + axutil_param_t *proxy_param = NULL; + axutil_hash_t *transport_attrs = NULL; + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + if(conf_ctx) + { + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + if(conf) + { + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + } + } + if(trans_desc) + { + proxy_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, + AXIS2_HTTP_PROXY_API); + if(!proxy_param) + { + proxy_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, + AXIS2_HTTP_PROXY); + } + if(proxy_param) + { + transport_attrs = axutil_param_get_attributes(proxy_param, env); + if(transport_attrs) + { + axutil_generic_obj_t *obj = NULL; + axiom_attribute_t *username_attr = NULL; + axiom_attribute_t *password_attr = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_USERNAME, + AXIS2_HASH_KEY_STRING); + if(obj) + { + username_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(username_attr) + { + uname = axiom_attribute_get_value(username_attr, env); + } + obj = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_PASSWORD, + AXIS2_HASH_KEY_STRING); + if(obj) + { + password_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(password_attr) + { + passwd = axiom_attribute_get_value(password_attr, env); + } + } + } + } + } + if(uname && passwd) + { + int elen; + int plen = axutil_strlen(uname) + axutil_strlen(passwd) + 1; + axis2_char_t *to_encode = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, + sizeof(axis2_char_t) * plen + 1)); + axis2_char_t *encoded = NULL; + axis2_char_t *auth_str = NULL; + sprintf(to_encode, "%s:%s", uname, passwd); + elen = axutil_base64_encode_len(plen); + encoded = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * elen)); + auth_str + = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (elen + 6))); + axutil_base64_encode(encoded, to_encode, plen); + sprintf(auth_str, "%s %s", AXIS2_PROXY_AUTH_TYPE_BASIC, encoded); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_PROXY_AUTHORIZATION, + auth_str); + + AXIS2_FREE(env->allocator, to_encode); + to_encode = NULL; + AXIS2_FREE(env->allocator, encoded); + encoded = NULL; + AXIS2_FREE(env->allocator, auth_str); + auth_str = NULL; + + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_configure_http_digest_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request, + axis2_char_t * header_data) +{ + axutil_property_t *http_auth_un = NULL; + axutil_property_t *http_auth_pw = NULL; + axis2_char_t *uname = NULL; + axis2_char_t *passwd = NULL; + + if(!header_data || !*header_data) + return AXIS2_FAILURE; + + http_auth_un = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_UNAME); + http_auth_pw = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_PASSWD); + if(http_auth_un && http_auth_pw) + { + uname = (axis2_char_t *)axutil_property_get_value(http_auth_un, env); + passwd = (axis2_char_t *)axutil_property_get_value(http_auth_pw, env); + } + if(!uname || !passwd) + { + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_out_desc_t *trans_desc = NULL; + axutil_param_t *http_auth_param = NULL; + axutil_hash_t *transport_attrs = NULL; + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + if(conf_ctx) + { + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + if(conf) + { + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + } + } + if(trans_desc) + { + http_auth_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, + AXIS2_HTTP_AUTHENTICATION); + if(http_auth_param) + { + transport_attrs = axutil_param_get_attributes(http_auth_param, env); + if(transport_attrs) + { + axutil_generic_obj_t *obj = NULL; + axiom_attribute_t *username_attr = NULL; + axiom_attribute_t *password_attr = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_AUTHENTICATION_USERNAME, + AXIS2_HASH_KEY_STRING); + if(obj) + { + username_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(username_attr) + { + uname = axiom_attribute_get_value(username_attr, env); + } + obj = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_AUTHENTICATION_PASSWORD, + AXIS2_HASH_KEY_STRING); + if(obj) + { + password_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(password_attr) + { + passwd = axiom_attribute_get_value(password_attr, env); + } + } + } + } + } + if(uname && passwd) + { + int elen = 0; /* length of header content */ + int print_const = 5; /* constant accounts for printing the + quoatation marks, comma, and space */ + int response_length = 32; + axis2_char_t *temp = NULL; + axis2_char_t *alloc_temp = NULL; + axis2_char_t *algo = AXIS2_HTTP_AUTHORIZATION_REQUEST_ALGORITHM_MD5; + axis2_char_t *realm = NULL; + axis2_char_t *qop = NULL; + axis2_char_t *nonce = NULL; + axis2_char_t *opaque = NULL; + axis2_char_t *cnonce = NULL; + axis2_char_t *nc = NULL; + axutil_digest_hash_hex_t h_a1; + axutil_digest_hash_hex_t h_a2; + axutil_digest_hash_hex_t response; + axis2_char_t *auth_str = NULL; + axutil_property_t *method = NULL; + axis2_char_t *method_value = NULL; + axis2_char_t *url = NULL; + + url = axis2_http_request_line_get_uri(axis2_http_simple_request_get_request_line(request, + env), env); + + if(!url) + { + return AXIS2_FAILURE; + } + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI) + + axutil_strlen(url); + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME) + + axutil_strlen(uname); + + method = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_METHOD); + if(method) + { + method_value = (axis2_char_t *)axutil_property_get_value(method, env); + } + else + { + method_value = AXIS2_HTTP_POST; + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM); + if(temp) + { + realm = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(realm) + { + realm++; + temp = axutil_strchr(realm, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - realm + 1))); + strncpy(alloc_temp, realm, (temp - realm)); + if(alloc_temp) + alloc_temp[temp - realm] = AXIS2_ESC_NULL; + realm = alloc_temp; + alloc_temp = NULL; + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM) + + axutil_strlen(realm); + } + else + { + return AXIS2_FAILURE; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP); + if(temp) + { + qop = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(qop) + { + qop++; + temp = axutil_strchr(qop, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - qop + 1))); + strncpy(alloc_temp, qop, (temp - qop)); + if(alloc_temp) + alloc_temp[temp - qop] = AXIS2_ESC_NULL; + qop = alloc_temp; + alloc_temp = NULL; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE); + if(temp) + { + nonce = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(nonce) + { + nonce++; + temp = axutil_strchr(nonce, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - nonce + 1))); + strncpy(alloc_temp, nonce, (temp - nonce)); + if(alloc_temp) + alloc_temp[temp - nonce] = AXIS2_ESC_NULL; + nonce = alloc_temp; + alloc_temp = NULL; + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE) + + axutil_strlen(nonce); + } + else + { + if(realm) + AXIS2_FREE(env->allocator, realm); + return AXIS2_FAILURE; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE); + if(temp) + { + opaque = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(opaque) + { + opaque++; + temp = axutil_strchr(opaque, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - opaque + 1))); + strncpy(alloc_temp, opaque, (temp - opaque)); + if(alloc_temp) + alloc_temp[temp - opaque] = AXIS2_ESC_NULL; + opaque = alloc_temp; + alloc_temp = NULL; + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE) + + axutil_strlen(opaque); + } + else + { + if(realm) + AXIS2_FREE(env->allocator, realm); + if(nonce) + AXIS2_FREE(env->allocator, nonce); + return AXIS2_FAILURE; + } + } + + if(qop) + { + nc = AXIS2_HTTP_AUTHORIZATION_REQUEST_DEFAULT_CLIENT_NONCE; + temp = qop; + if(!axutil_strstr(temp, AXIS2_HTTP_AUTHORIZATION_REQUEST_QOP_OPTION_AUTH)) + { + return AXIS2_FAILURE; + } + AXIS2_FREE(env->allocator, qop); + qop = AXIS2_HTTP_AUTHORIZATION_REQUEST_QOP_OPTION_AUTH; + temp = axutil_uuid_gen(env); + cnonce = temp; + temp += CLIENT_NONCE_LENGTH; + if(temp) + *temp = AXIS2_ESC_NULL; + elen += 11 + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_DEFAULT_CLIENT_NONCE) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP) + CLIENT_NONCE_LENGTH + + axutil_strlen(qop); + } + + axutil_digest_calc_get_h_a1(env, algo, uname, realm, passwd, cnonce, nonce, h_a1); + axutil_digest_calc_get_response(env, h_a1, nonce, nc, cnonce, qop, method_value, url, h_a2, + response); + + elen += 4 + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_RESPONSE) + axutil_strlen( + AXIS2_HTTP_AUTH_TYPE_DIGEST) + response_length; + + auth_str + = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (elen + 1))); + temp = auth_str; + sprintf(temp, "%s %s=\"%s\", ", AXIS2_HTTP_AUTH_TYPE_DIGEST, + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME, uname); + temp += ((int)strlen(AXIS2_HTTP_AUTH_TYPE_DIGEST) + (int)strlen( + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME) + (int)strlen(uname) + 6); + if(realm) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM, realm); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM) + (int)strlen(realm) + + 5); + } + if(nonce) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE, nonce); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE) + (int)strlen(nonce) + + 5); + } + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI, url); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI) + (int)strlen(url) + 5); + if(qop) + { + sprintf(temp, "%s=%s, %s=%s, %s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP, + qop, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT, nc, + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE, cnonce); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP) + (int)strlen(qop) + + (int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT) + (int)strlen(nc) + + (int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE) + (int)strlen( + cnonce) + 11); + } + if(opaque) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE, opaque); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE) + (int)strlen( + opaque) + 5); + } + sprintf(temp, "%s=\"%s\"", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_RESPONSE, response); + + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_AUTHORIZATION, auth_str); + if(realm) + AXIS2_FREE(env->allocator, realm); + if(nonce) + AXIS2_FREE(env->allocator, nonce); + if(cnonce) + AXIS2_FREE(env->allocator, cnonce); + if(opaque) + AXIS2_FREE(env->allocator, opaque); + if(auth_str) + AXIS2_FREE(env->allocator, auth_str); + auth_str = NULL; + + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} + +static axis2_status_t +axis2_http_sender_configure_proxy_digest_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request, + axis2_char_t * header_data) +{ + axutil_property_t *proxy_auth_un = NULL; + axutil_property_t *proxy_auth_pw = NULL; + axis2_char_t *uname = NULL; + axis2_char_t *passwd = NULL; + + if(!header_data || !*header_data) + return AXIS2_FAILURE; + + proxy_auth_un = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_UNAME); + proxy_auth_pw = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_PASSWD); + + if(proxy_auth_un && proxy_auth_pw) + { + uname = (axis2_char_t *)axutil_property_get_value(proxy_auth_un, env); + passwd = (axis2_char_t *)axutil_property_get_value(proxy_auth_pw, env); + } + if(!uname || !passwd) + { + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_out_desc_t *trans_desc = NULL; + axutil_param_t *proxy_param = NULL; + axutil_hash_t *transport_attrs = NULL; + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + if(conf_ctx) + { + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + if(conf) + { + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + } + } + if(trans_desc) + { + proxy_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, + AXIS2_HTTP_PROXY_API); + if(!proxy_param) + { + proxy_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, + AXIS2_HTTP_PROXY); + } + if(proxy_param) + { + transport_attrs = axutil_param_get_attributes(proxy_param, env); + + if(transport_attrs) + { + axutil_generic_obj_t *obj = NULL; + axiom_attribute_t *username_attr = NULL; + axiom_attribute_t *password_attr = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_USERNAME, + AXIS2_HASH_KEY_STRING); + if(obj) + { + username_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(username_attr) + { + uname = axiom_attribute_get_value(username_attr, env); + } + + obj = NULL; + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_PASSWORD, + AXIS2_HASH_KEY_STRING); + if(obj) + { + password_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(password_attr) + { + passwd = axiom_attribute_get_value(password_attr, env); + } + } + } + } + } + if(uname && passwd) + { + int elen = 0; /* length of header content */ + int print_const = 5; /* constant accounts for printing the + quoatation marks, comma, and space */ + int response_length = 32; + axis2_char_t *temp = NULL; + axis2_char_t *alloc_temp = NULL; + axis2_char_t *algo = AXIS2_HTTP_AUTHORIZATION_REQUEST_ALGORITHM_MD5; + axis2_char_t *realm = NULL; + axis2_char_t *qop = NULL; + axis2_char_t *nonce = NULL; + axis2_char_t *opaque = NULL; + axis2_char_t *cnonce = NULL; + axis2_char_t *nc = NULL; + axutil_digest_hash_hex_t h_a1; + axutil_digest_hash_hex_t h_a2; + axutil_digest_hash_hex_t response; + axis2_char_t *auth_str = NULL; + axutil_property_t *method = NULL; + axis2_char_t *method_value = NULL; + axis2_char_t *url = NULL; + + url = axis2_http_request_line_get_uri(axis2_http_simple_request_get_request_line(request, + env), env); + + if(!url) + { + return AXIS2_FAILURE; + } + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI) + + axutil_strlen(url); + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME) + + axutil_strlen(uname); + + method = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_METHOD); + if(method) + { + method_value = (axis2_char_t *)axutil_property_get_value(method, env); + } + else + { + method_value = AXIS2_HTTP_POST; + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM); + if(temp) + { + realm = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(realm) + { + realm++; + temp = axutil_strchr(realm, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - realm + 1))); + strncpy(alloc_temp, realm, (temp - realm)); + if(alloc_temp) + alloc_temp[temp - realm] = AXIS2_ESC_NULL; + realm = alloc_temp; + alloc_temp = NULL; + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM) + + axutil_strlen(realm); + } + else + { + return AXIS2_FAILURE; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP); + if(temp) + { + qop = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(qop) + { + qop++; + temp = axutil_strchr(qop, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - qop + 1))); + strncpy(alloc_temp, qop, (temp - qop)); + if(alloc_temp) + alloc_temp[temp - qop] = AXIS2_ESC_NULL; + qop = alloc_temp; + alloc_temp = NULL; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE); + if(temp) + { + nonce = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(nonce) + { + nonce++; + temp = axutil_strchr(nonce, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - nonce + 1))); + strncpy(alloc_temp, nonce, (temp - nonce)); + if(alloc_temp) + alloc_temp[temp - nonce] = AXIS2_ESC_NULL; + nonce = alloc_temp; + alloc_temp = NULL; + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE) + + axutil_strlen(nonce); + } + else + { + if(realm) + AXIS2_FREE(env->allocator, realm); + return AXIS2_FAILURE; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE); + if(temp) + { + opaque = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(opaque) + { + opaque++; + temp = axutil_strchr(opaque, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - opaque + 1))); + strncpy(alloc_temp, opaque, (temp - opaque)); + if(alloc_temp) + alloc_temp[temp - opaque] = AXIS2_ESC_NULL; + opaque = alloc_temp; + alloc_temp = NULL; + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE) + + axutil_strlen(opaque); + } + else + { + if(realm) + AXIS2_FREE(env->allocator, realm); + if(nonce) + AXIS2_FREE(env->allocator, nonce); + return AXIS2_FAILURE; + } + } + + if(qop) + { + nc = AXIS2_HTTP_AUTHORIZATION_REQUEST_DEFAULT_CLIENT_NONCE; + temp = qop; + if(!axutil_strstr(temp, AXIS2_HTTP_AUTHORIZATION_REQUEST_QOP_OPTION_AUTH)) + { + return AXIS2_FAILURE; + } + AXIS2_FREE(env->allocator, qop); + qop = AXIS2_HTTP_AUTHORIZATION_REQUEST_QOP_OPTION_AUTH; + temp = axutil_uuid_gen(env); + cnonce = temp; + temp += CLIENT_NONCE_LENGTH; + if(temp) + *temp = AXIS2_ESC_NULL; + elen += 11 + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_DEFAULT_CLIENT_NONCE) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP) + CLIENT_NONCE_LENGTH + + axutil_strlen(qop); + } + + axutil_digest_calc_get_h_a1(env, algo, uname, realm, passwd, cnonce, nonce, h_a1); + axutil_digest_calc_get_response(env, h_a1, nonce, nc, cnonce, qop, method_value, url, h_a2, + response); + + elen += 4 + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_RESPONSE) + axutil_strlen( + AXIS2_PROXY_AUTH_TYPE_DIGEST) + response_length; + + auth_str + = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (elen + 1))); + temp = auth_str; + sprintf(temp, "%s %s=\"%s\", ", AXIS2_PROXY_AUTH_TYPE_DIGEST, + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME, uname); + temp += ((int)strlen(AXIS2_HTTP_AUTH_TYPE_DIGEST) + (int)strlen( + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME) + (int)strlen(uname) + 6); + if(realm) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM, realm); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM) + (int)strlen(realm) + + 5); + } + if(nonce) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE, nonce); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE) + (int)strlen(nonce) + + 5); + } + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI, url); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI) + (int)strlen(url) + 5); + if(qop) + { + sprintf(temp, "%s=%s, %s=%s, %s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP, + qop, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT, nc, + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE, cnonce); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP) + (int)strlen(qop) + + (int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT) + (int)strlen(nc) + + (int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE) + (int)strlen( + cnonce) + 11); + } + if(opaque) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE, opaque); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE) + (int)strlen( + opaque) + 5); + } + sprintf(temp, "%s=\"%s\"", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_RESPONSE, response); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_PROXY_AUTHORIZATION, + auth_str); + if(realm) + { + AXIS2_FREE(env->allocator, realm); + } + + if(nonce) + { + AXIS2_FREE(env->allocator, nonce); + } + + if(cnonce) + { + AXIS2_FREE(env->allocator, cnonce); + } + + if(opaque) + { + AXIS2_FREE(env->allocator, opaque); + } + + if(auth_str) + { + AXIS2_FREE(env->allocator, auth_str); + } + + auth_str = NULL; + + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_configure_http_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axis2_char_t *auth_type = NULL; + axis2_status_t status = AXIS2_FALSE; + axutil_property_t *http_auth_property = NULL; + axis2_char_t *http_auth_property_value = NULL; + axis2_bool_t force_http_auth = AXIS2_FALSE; + axutil_property_t *http_auth_type_property = NULL; + axis2_char_t *http_auth_type_property_value = NULL; + axis2_char_t *auth_type_end = NULL; + + http_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_FORCE_HTTP_AUTH); + if(http_auth_property) + { + http_auth_property_value = (axis2_char_t *)axutil_property_get_value(http_auth_property, + env); + } + + if(http_auth_property_value && 0 == axutil_strcmp(http_auth_property_value, AXIS2_VALUE_TRUE)) + { + force_http_auth = AXIS2_TRUE; + } + + if(force_http_auth) + { + http_auth_type_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_HTTP_AUTH_TYPE); + if(http_auth_type_property) + { + http_auth_type_property_value = (axis2_char_t *)axutil_property_get_value( + http_auth_type_property, env); + } + + if(http_auth_type_property_value) + { + auth_type = http_auth_type_property_value; + } + } + if(!force_http_auth || axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_DIGEST) == 0) + { + axis2_http_header_t *auth_header = NULL; + axis2_http_simple_response_t *response = NULL; + + response = axis2_http_client_get_response(sender->client, env); + + if(response) + { + auth_header = axis2_http_simple_response_get_first_header(response, env, + AXIS2_HTTP_HEADER_WWW_AUTHENTICATE); + } + + if(auth_header) + { + auth_type = axis2_http_header_get_value(auth_header, env); + } + + if(auth_type) + { + auth_type_end = axutil_strchr(auth_type, ' '); + *auth_type_end = AXIS2_ESC_NULL; + auth_type_end++; + /*Read the realm and the rest stuff now from auth_type_end */ + } + if(force_http_auth && axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_DIGEST) != 0) + { + auth_type = NULL; + } + } + if(auth_type) + { + if(axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_BASIC) == 0) + { + status = axis2_http_sender_configure_http_basic_auth(sender, env, msg_ctx, request); + } + else if(axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_DIGEST) == 0) + { + status = axis2_http_sender_configure_http_digest_auth(sender, env, msg_ctx, request, + auth_type_end); + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Authtype %s is not" + "supported", auth_type); + } + } + else + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + } + + return status; +} + +static axis2_status_t +axis2_http_sender_configure_proxy_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axis2_char_t *auth_type = NULL; + axis2_status_t status = AXIS2_FALSE; + axutil_property_t *proxy_auth_property = NULL; + axis2_char_t *proxy_auth_property_value = NULL; + axis2_bool_t force_proxy_auth = AXIS2_FALSE; + axutil_property_t *proxy_auth_type_property = NULL; + axis2_char_t *proxy_auth_type_property_value = NULL; + axis2_char_t *auth_type_end = NULL; + + proxy_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_FORCE_PROXY_AUTH); + if(proxy_auth_property) + { + proxy_auth_property_value = (axis2_char_t *)axutil_property_get_value(proxy_auth_property, + env); + } + + if(proxy_auth_property_value && 0 == axutil_strcmp(proxy_auth_property_value, AXIS2_VALUE_TRUE)) + { + force_proxy_auth = AXIS2_TRUE; + } + + if(force_proxy_auth) + { + proxy_auth_type_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_PROXY_AUTH_TYPE); + if(proxy_auth_type_property) + { + proxy_auth_type_property_value = (axis2_char_t *)axutil_property_get_value( + proxy_auth_type_property, env); + } + + if(proxy_auth_type_property_value) + { + auth_type = proxy_auth_type_property_value; + } + } + else + { + axis2_http_header_t *auth_header = NULL; + axis2_http_simple_response_t *response = NULL; + + response = axis2_http_client_get_response(sender->client, env); + + if(response) + { + auth_header = axis2_http_simple_response_get_first_header(response, env, + AXIS2_HTTP_HEADER_PROXY_AUTHENTICATE); + } + + if(auth_header) + { + auth_type = axis2_http_header_get_value(auth_header, env); + } + + if(auth_type) + { + auth_type_end = axutil_strchr(auth_type, ' '); + *auth_type_end = AXIS2_ESC_NULL; + auth_type_end++; + /*Read the realm and the rest stuff now from auth_type_end */ + } + } + if(auth_type) + { + if(axutil_strcasecmp(auth_type, AXIS2_PROXY_AUTH_TYPE_BASIC) == 0) + { + status = axis2_http_sender_configure_proxy_basic_auth(sender, env, msg_ctx, request); + } + else if(axutil_strcasecmp(auth_type, AXIS2_PROXY_AUTH_TYPE_DIGEST) == 0) + { + status = axis2_http_sender_configure_proxy_digest_auth(sender, env, msg_ctx, request, + auth_type_end); + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Authtype %s is not supported", auth_type); + } + } + else + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + } + + return status; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_set_http_auth_type( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axis2_char_t *auth_type = NULL; + axis2_status_t status = AXIS2_FALSE; + axis2_char_t *auth_type_end = NULL; + axis2_http_header_t *auth_header = NULL; + axis2_http_simple_response_t *response = NULL; + + response = axis2_http_client_get_response(sender->client, env); + + if(response) + { + auth_header = axis2_http_simple_response_get_first_header(response, env, + AXIS2_HTTP_HEADER_WWW_AUTHENTICATE); + } + + if(auth_header) + { + auth_type = axis2_http_header_get_value(auth_header, env); + } + + if(auth_type) + { + auth_type_end = axutil_strchr(auth_type, ' '); + *auth_type_end = AXIS2_ESC_NULL; + auth_type_end++; + /*Read the realm and the rest stuff now from auth_type_end */ + } + + if(auth_type) + { + if(axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_BASIC) == 0) + { + status = axis2_msg_ctx_set_auth_type(msg_ctx, env, AXIS2_HTTP_AUTH_TYPE_BASIC); + } + else if(axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_DIGEST) == 0) + { + status = axis2_msg_ctx_set_auth_type(msg_ctx, env, AXIS2_HTTP_AUTH_TYPE_DIGEST); + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Authtype %s is not supported", auth_type); + } + } + else + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + } + return status; +} + +static axis2_status_t +axis2_http_sender_set_proxy_auth_type( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axis2_char_t *auth_type = NULL; + axis2_status_t status = AXIS2_FALSE; + axis2_char_t *auth_type_end = NULL; + axis2_http_header_t *auth_header = NULL; + axis2_http_simple_response_t *response = NULL; + + response = axis2_http_client_get_response(sender->client, env); + + if(response) + { + auth_header = axis2_http_simple_response_get_first_header(response, env, + AXIS2_HTTP_HEADER_PROXY_AUTHENTICATE); + } + + if(auth_header) + { + auth_type = axis2_http_header_get_value(auth_header, env); + } + + if(auth_type) + { + auth_type_end = axutil_strchr(auth_type, ' '); + *auth_type_end = AXIS2_ESC_NULL; + auth_type_end++; + /*Read the realm and the rest stuff now from auth_type_end */ + } + + if(auth_type) + { + if(axutil_strcasecmp(auth_type, AXIS2_PROXY_AUTH_TYPE_BASIC) == 0) + { + status = axis2_msg_ctx_set_auth_type(msg_ctx, env, AXIS2_PROXY_AUTH_TYPE_BASIC); + } + else if(axutil_strcasecmp(auth_type, AXIS2_PROXY_AUTH_TYPE_DIGEST) == 0) + { + status = axis2_msg_ctx_set_auth_type(msg_ctx, env, AXIS2_PROXY_AUTH_TYPE_DIGEST); + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Authtype %s is not supported", auth_type); + } + } + else + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + } + return status; +} +#endif + +#ifdef AXIS2_LIBCURL_ENABLED +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_libcurl_http_send (axis2_libcurl_t * curl, + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axiom_soap_envelope_t * out, + const axis2_char_t * str_url, + const axis2_char_t * soap_action) +{ + return axis2_libcurl_send (curl, sender->om_output, + env, msg_ctx, out, str_url, soap_action); +} +#endif + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_sender_get_param_string( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axiom_soap_envelope_t *soap_env = NULL; + axiom_soap_body_t *soap_body = NULL; + axiom_node_t *body_node = NULL; + axiom_node_t *data_node = NULL; + axiom_element_t *data_element = NULL; + axiom_child_element_iterator_t *iterator = NULL; + axutil_array_list_t *param_list = NULL; + axis2_char_t *param_string = NULL; + int i = 0; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, NULL); + + soap_env = axis2_msg_ctx_get_soap_envelope(msg_ctx, env); + if(!soap_env) + { + return NULL; + } + soap_body = axiom_soap_envelope_get_body(soap_env, env); + body_node = axiom_soap_body_get_base_node(soap_body, env); + if(!body_node) + { + /* This could be the situation where service client does not provide + * a xml payload and instead add url parameters to the endpoint url + */ + return NULL; + } + data_node = axiom_node_get_first_child(body_node, env); + if(!data_node) + { + return NULL; + } + + param_list = axutil_array_list_create(env, AXIS2_ARRAY_LIST_DEFAULT_CAPACITY); + + data_element = axiom_node_get_data_element(data_node, env); + + iterator = axiom_element_get_child_elements(data_element, env, data_node); + + if(iterator) + { + while(AXIS2_TRUE == AXIOM_CHILD_ELEMENT_ITERATOR_HAS_NEXT(iterator, env)) + { + axiom_node_t *node = NULL; + axiom_element_t *element = NULL; + axis2_char_t *name = NULL; + axis2_char_t *value = NULL; + axis2_char_t *encoded_value = NULL; + + node = AXIOM_CHILD_ELEMENT_ITERATOR_NEXT(iterator, env); + element = axiom_node_get_data_element(node, env); + name = axiom_element_get_localname(element, env); + value = axiom_element_get_text(element, env, node); + if(value) + { + encoded_value = (axis2_char_t *)AXIS2_MALLOC(env->allocator, strlen(value)); + memset(encoded_value, 0, strlen(value)); + encoded_value = axutil_url_encode(env, encoded_value, value, (int)strlen(value)); + /* We are sure that the difference lies within the int range */ + + axutil_array_list_add(param_list, env, axutil_strcat(env, name, "=", encoded_value, + NULL)); + AXIS2_FREE(env->allocator, encoded_value); + encoded_value = NULL; + } + } + } + for(i = 0; i < axutil_array_list_size(param_list, env); i++) + { + axis2_char_t *tmp_string = NULL; + axis2_char_t *pair = NULL; + + pair = axutil_array_list_get(param_list, env, i); + if(i == 0) + { + tmp_string = axutil_stracat(env, param_string, pair); + } + else + { + tmp_string = axutil_strcat(env, param_string, AXIS2_AND_SIGN, pair, NULL); + } + + if(param_string) + { + AXIS2_FREE(env->allocator, param_string); + param_string = NULL; + } + AXIS2_FREE(env->allocator, pair); + param_string = tmp_string; + } + axutil_array_list_free(param_list, env); + return param_string; +} + +void AXIS2_CALL +axis2_http_sender_util_add_header( + const axutil_env_t * env, + axis2_http_simple_request_t * request, + axis2_char_t * header_name, + const axis2_char_t * header_value) +{ + axis2_http_header_t *http_header; + http_header = axis2_http_header_create(env, header_name, header_value); + axis2_http_simple_request_add_header(request, env, http_header); +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_sender_set_keep_alive( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_bool_t keep_alive) +{ + sender->keep_alive = keep_alive; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_sender_get_keep_alive( + axis2_http_sender_t * sender, + const axutil_env_t * env) +{ + return sender->keep_alive; +} + +static axutil_hash_t * +axis2_http_sender_connection_map_create( + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx) +{ + axutil_hash_t *connection_map = NULL; + connection_map = axutil_hash_make(env); + if(!connection_map) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + } + else + { + axis2_conf_ctx_t *conf_ctx = NULL; + axutil_property_t *connection_map_property = NULL; + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + connection_map_property = axutil_property_create_with_args(env, AXIS2_SCOPE_SESSION, + AXIS2_TRUE, axis2_http_sender_connection_map_free, connection_map); + axis2_conf_ctx_set_property(conf_ctx, env, AXIS2_HTTP_CONNECTION_MAP, + connection_map_property); + } + return connection_map; +} + +static void +axis2_http_sender_connection_map_remove( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx, + axis2_http_client_t *http_client) +{ + axutil_property_t *property = NULL; + axis2_endpoint_ref_t *endpoint = NULL; + /** + * Put the http client into message context with own value true so that it will be freed + * after response processed + */ + property = axutil_property_create_with_args(env, AXIS2_SCOPE_REQUEST, AXIS2_TRUE, + axis2_http_client_free_void_arg, http_client); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_CLIENT, property); + endpoint = axis2_msg_ctx_get_to(msg_ctx, env); + if(endpoint) + { + const axis2_char_t *address = NULL; + address = axis2_endpoint_ref_get_address(endpoint, env); + if(address) + { + axutil_url_t *url = NULL; + url = axutil_url_parse_string(env, address); + if(url) + { + axis2_char_t *server = axutil_url_get_server(url, env); + if(server) + { + axutil_hash_set(connection_map, server, AXIS2_HASH_KEY_STRING, NULL); + } + axutil_url_free(url, env); + } + } + } +} + +static void +axis2_http_sender_connection_map_add( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx, + axis2_http_client_t *http_client) +{ + axutil_property_t *property = NULL; + axis2_endpoint_ref_t *endpoint = NULL; + /** + * Put the http client into message context. Is this neccessary? + */ + property = axutil_property_create_with_args(env, AXIS2_SCOPE_REQUEST, AXIS2_FALSE, + axis2_http_client_free_void_arg, http_client); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_CLIENT, property); + endpoint = axis2_msg_ctx_get_to(msg_ctx, env); + if(endpoint) + { + const axis2_char_t *address = NULL; + address = axis2_endpoint_ref_get_address(endpoint, env); + if(address) + { + axutil_url_t *url = NULL; + url = axutil_url_parse_string(env, address); + if(url) + { + axis2_char_t *server = axutil_url_get_server(url, env); + if(server) + { + axutil_hash_set(connection_map, axutil_strdup(env, server), + AXIS2_HASH_KEY_STRING, http_client); + } + axutil_url_free(url, env); + } + } + } +} + +static axis2_http_client_t * +axis2_http_sender_connection_map_get( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx) +{ + axis2_http_client_t *http_client = NULL; + axis2_endpoint_ref_t *endpoint = NULL; + endpoint = axis2_msg_ctx_get_to(msg_ctx, env); + if(endpoint) + { + const axis2_char_t *address = NULL; + address = axis2_endpoint_ref_get_address(endpoint, env); + if(address) + { + axutil_url_t *url = NULL; + url = axutil_url_parse_string(env, address); + if(url) + { + axis2_char_t *server = axutil_url_get_server(url, env); + if(server) + { + http_client = axutil_hash_get(connection_map, server, AXIS2_HASH_KEY_STRING); + } + axutil_url_free(url, env); + } + } + } + return http_client; +} + +static void AXIS2_CALL +axis2_http_sender_connection_map_free( + void *cm_void, + const axutil_env_t *env) +{ + void *val = NULL; + const void *key = NULL; + axutil_hash_index_t *hi = NULL; + axutil_hash_t *ht = (axutil_hash_t *)cm_void; + + for(hi = axutil_hash_first(ht, env); hi; hi = axutil_hash_next(env, hi)) + { + axis2_char_t *name = NULL; + axis2_http_client_t *value = NULL; + + axutil_hash_this(hi, &key, NULL, &val); + name = (axis2_char_t *) key; + if(name) + { + AXIS2_FREE(env->allocator, name); + } + value = (axis2_http_client_t *) val; + if(value) + { + axis2_http_client_free(value, env); + } + } + axutil_hash_free(ht, env); +} + diff --git a/src/core/transport/http/sender/http_transport_sender.c b/src/core/transport/http/sender/http_transport_sender.c new file mode 100644 index 0000000..3ef55b0 --- /dev/null +++ b/src/core/transport/http/sender/http_transport_sender.c @@ -0,0 +1,859 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef AXIS2_LIBCURL_ENABLED +#include "libcurl/axis2_libcurl.h" +#endif + +/** + * HTTP Transport Sender struct impl + * Axis2 HTTP Transport Sender impl + */ + +typedef struct axis2_http_transport_sender_impl +{ + axis2_transport_sender_t transport_sender; + axis2_char_t *http_version; + axis2_bool_t chunked; + int connection_timeout; + int so_timeout; + axis2_bool_t keep_alive; +#ifdef AXIS2_LIBCURL_ENABLED + axis2_libcurl_t *libcurl; +#endif +} axis2_http_transport_sender_impl_t; + +#define AXIS2_WS_RM_ANONYMOUS_URL "http://docs.oasis-open.org/ws-rx/wsmc/200702/anonymous?id=" +#define AXIS2_INTF_TO_IMPL(transport_sender) \ + ((axis2_http_transport_sender_impl_t *)\ + (transport_sender)) + +/***************************** Function headers *******************************/ +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_invoke( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_clean_up( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_init( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx, + axis2_transport_out_desc_t * out_desc); + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_write_message( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_endpoint_ref_t * epr, + axiom_soap_envelope_t * out, + axiom_output_t * om_output); + +void AXIS2_CALL axis2_http_transport_sender_free( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env); + +static const axis2_transport_sender_ops_t http_transport_sender_ops_var = { + axis2_http_transport_sender_init, axis2_http_transport_sender_invoke, + axis2_http_transport_sender_clean_up, axis2_http_transport_sender_free }; + +axis2_transport_sender_t *AXIS2_CALL +axis2_http_transport_sender_create( + const axutil_env_t * env) +{ + axis2_http_transport_sender_impl_t *transport_sender_impl = NULL; + + transport_sender_impl = (axis2_http_transport_sender_impl_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_transport_sender_impl_t)); + + if(!transport_sender_impl) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + memset((void *)transport_sender_impl, 0, sizeof(axis2_http_transport_sender_impl_t)); + + transport_sender_impl->http_version = axutil_strdup(env, AXIS2_HTTP_HEADER_PROTOCOL_11); + transport_sender_impl->chunked = AXIS2_TRUE; + transport_sender_impl->connection_timeout = AXIS2_HTTP_DEFAULT_CONNECTION_TIMEOUT; + transport_sender_impl->so_timeout = AXIS2_HTTP_DEFAULT_SO_TIMEOUT; + transport_sender_impl->keep_alive = AXIS2_TRUE; + transport_sender_impl->transport_sender.ops = &http_transport_sender_ops_var; + +#ifdef AXIS2_LIBCURL_ENABLED + transport_sender_impl->libcurl = axis2_libcurl_create(env); + if (!transport_sender_impl->libcurl) + { + AXIS2_FREE(env->allocator, transport_sender_impl); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } +#endif + + return &(transport_sender_impl->transport_sender); +} + +void AXIS2_CALL +axis2_http_transport_sender_free( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env) +{ + + axis2_http_transport_sender_impl_t *transport_sender_impl = NULL; + if(!transport_sender) + { + return; + } + + transport_sender_impl = AXIS2_INTF_TO_IMPL(transport_sender); + + if(transport_sender_impl->http_version) + { + AXIS2_FREE(env->allocator, transport_sender_impl->http_version); + transport_sender_impl->http_version = NULL; + } + +#ifdef AXIS2_LIBCURL_ENABLED + if (transport_sender_impl->libcurl) + { + axis2_libcurl_free(transport_sender_impl->libcurl, env); + } +#endif + + AXIS2_FREE(env->allocator, transport_sender_impl); + return; +} + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_invoke( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + const axis2_char_t *char_set_enc = NULL; + axutil_string_t *char_set_enc_str = NULL; + axis2_endpoint_ref_t *epr = NULL; + axis2_char_t *transport_url = NULL; + axiom_xml_writer_t *xml_writer = NULL; + axiom_output_t *om_output = NULL; + axis2_char_t *buffer = NULL; + axiom_soap_envelope_t *soap_data_out = NULL; + axis2_bool_t do_mtom; + axutil_property_t *property = NULL; + axiom_node_t *data_out = NULL; + int buffer_size = 0; + axis2_status_t status = AXIS2_SUCCESS; + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_out_desc_t *trans_desc = NULL; + axutil_param_t *write_xml_declaration_param = NULL; + axutil_hash_t *transport_attrs = NULL; + axis2_bool_t write_xml_declaration = AXIS2_FALSE; + axis2_bool_t fault = AXIS2_FALSE; + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Entry:axis2_http_transport_sender_invoke"); + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + + char_set_enc_str = axis2_msg_ctx_get_charset_encoding(msg_ctx, env); + if(char_set_enc_str) + { + char_set_enc = axutil_string_get_buffer(char_set_enc_str, env); + } + + if(!char_set_enc) + { + axis2_op_ctx_t *op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env); + if(op_ctx) + { + axis2_ctx_t *ctx = axis2_op_ctx_get_base(op_ctx, env); + if(ctx) + { + property = axis2_ctx_get_property(ctx, env, AXIS2_CHARACTER_SET_ENCODING); + if(property) + { + char_set_enc = axutil_property_get_value(property, env); + property = NULL; + } + } + } + } + + /** + * If we still can't find the char set enc we will + * use default + */ + if(!char_set_enc) + { + char_set_enc = AXIS2_DEFAULT_CHAR_SET_ENCODING; + } + + do_mtom = axis2_http_transport_utils_do_write_mtom(env, msg_ctx); + + transport_url = axis2_msg_ctx_get_transport_url(msg_ctx, env); + if(transport_url) + { + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "transport_url:%s", transport_url); + epr = axis2_endpoint_ref_create(env, transport_url); + } + else + { + /* when transport url is not available in msg_ctx */ + axis2_endpoint_ref_t *ctx_epr = axis2_msg_ctx_get_to(msg_ctx, env); + if(ctx_epr) + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "ctx_epr:%s", axis2_endpoint_ref_get_address( + ctx_epr, env)); + + if(ctx_epr && axutil_strcmp(AXIS2_WSA_ANONYMOUS_URL_SUBMISSION, + axis2_endpoint_ref_get_address(ctx_epr, env)) && axutil_strcmp(AXIS2_WSA_ANONYMOUS_URL, + axis2_endpoint_ref_get_address(ctx_epr, env)) && !(axutil_strstr( + axis2_endpoint_ref_get_address(ctx_epr, env), AXIS2_WS_RM_ANONYMOUS_URL))) + { + epr = ctx_epr; + } + } + + soap_data_out = axis2_msg_ctx_get_soap_envelope(msg_ctx, env); + if(!soap_data_out) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_SOAP_ENVELOPE_IN_MSG_CTX, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "%s", AXIS2_ERROR_GET_MESSAGE(env->error)); + return AXIS2_SUCCESS; + } + + xml_writer = axiom_xml_writer_create_for_memory(env, NULL, AXIS2_TRUE, 0, + AXIS2_XML_PARSER_TYPE_BUFFER); + if(!xml_writer) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Could not create xml_writer for \ +AXIS2_XML_PARSER_TYPE_BUFFER"); + return AXIS2_FAILURE; + } + + om_output = axiom_output_create(env, xml_writer); + if(!om_output) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Could not create om_output for xml writer of \ +AXIS2_XML_PARSER_TYPE_BUFFER"); + axiom_xml_writer_free(xml_writer, env); + xml_writer = NULL; + return AXIS2_FAILURE; + } + + /* setting SOAP version for OM_OUTPUT. */ + axiom_output_set_soap11(om_output, env, axis2_msg_ctx_get_is_soap_11(msg_ctx, env)); + + /* This is the case where normal client send the requet using a http_client*/ + + if(epr) + { + if(axutil_strcmp(AXIS2_WSA_NONE_URL_SUBMISSION, axis2_endpoint_ref_get_address(epr, env)) + == 0 || axutil_strcmp(AXIS2_WSA_NONE_URL, axis2_endpoint_ref_get_address(epr, env)) + == 0) + { + epr = NULL; + } + else + { + status = axis2_http_transport_sender_write_message(transport_sender, env, msg_ctx, epr, + soap_data_out, om_output); + } + } + + /* If no endpoint reference could be derived from the the message context. It could well be the + * single channel two way scenario in the application server side send. + */ + if(!epr) + { + axutil_stream_t *out_stream = axis2_msg_ctx_get_transport_out_stream(msg_ctx, env); + + if(AXIS2_TRUE == axis2_msg_ctx_get_server_side(msg_ctx, env)) + { + axis2_http_out_transport_info_t *out_info = NULL; + axis2_bool_t is_soap11 = AXIS2_FALSE; + axis2_op_ctx_t *op_ctx = NULL; + /*axis2_char_t *header_value = NULL;*/ + + out_info = (axis2_http_out_transport_info_t *)axis2_msg_ctx_get_out_transport_info( + msg_ctx, env); + + if(!out_info) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_OUT_TRNSPORT_INFO_NULL, AXIS2_FAILURE); + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + return AXIS2_FAILURE; + } + /*header_value = axis2_http_transport_utils_get_session(env, msg_ctx); + if(header_value) + { + AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_COOKIE_HEADER(out_info, env, header_value); + }*/ + + is_soap11 = axis2_msg_ctx_get_is_soap_11(msg_ctx, env); + + AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_CHAR_ENCODING(out_info, env, char_set_enc); + if(AXIS2_TRUE == is_soap11) + { + /* SOAP1.1 */ + AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_CONTENT_TYPE(out_info, env, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML); + } + else + { + /* SOAP1.2 */ + AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_CONTENT_TYPE(out_info, env, + AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP); + } + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + if(conf_ctx) + { + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + } + + if(conf) + { + /* get access to HTTP transport for sending */ + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + } + + if(trans_desc) + { + + /* accessing parameter in axis2.xml which set to have + * an ability to send xml versoin processing + * instruction */ + write_xml_declaration_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, + AXIS2_XML_DECLARATION); + } + + if(write_xml_declaration_param) + { + transport_attrs = axutil_param_get_attributes(write_xml_declaration_param, env); + if(transport_attrs) + { + /* Accessing attribute values */ + axutil_generic_obj_t *obj = NULL; + axiom_attribute_t *write_xml_declaration_attr = NULL; + axis2_char_t *write_xml_declaration_attr_value = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_ADD_XML_DECLARATION, + AXIS2_HASH_KEY_STRING); + if(obj) + { + write_xml_declaration_attr + = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + + if(write_xml_declaration_attr) + { + write_xml_declaration_attr_value = axiom_attribute_get_value( + write_xml_declaration_attr, env); + } + + if(write_xml_declaration_attr_value && 0 == axutil_strcasecmp( + write_xml_declaration_attr_value, AXIS2_VALUE_TRUE)) + { + write_xml_declaration = AXIS2_TRUE; + } + } + } + + if(write_xml_declaration) + { + axiom_output_write_xml_version_encoding(om_output, env); + } + + if(AXIS2_TRUE == axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + axiom_node_t *body_node = NULL; + /* axis2_bool_t fault = AXIS2_FALSE;*/ + axiom_soap_fault_t *soap_fault; + axiom_soap_body_t *soap_body = axiom_soap_envelope_get_body(soap_data_out, env); + axiom_soap_fault_detail_t *soap_fault_detial; + + if(!soap_body) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SOAP_ENVELOPE_OR_SOAP_BODY_NULL, + AXIS2_FAILURE); + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + return AXIS2_FAILURE; + } + + fault = axiom_soap_body_has_fault(soap_body, env); + + if(fault == AXIS2_TRUE) + { + soap_fault = axiom_soap_body_get_fault(soap_body, env); + + if(!soap_fault) + { + + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Rest fault has occur, error described below"); + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + return AXIS2_FAILURE; + } + + soap_fault_detial = axiom_soap_fault_get_detail(soap_fault, env); + + if(!soap_fault_detial) + { + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "Returning failure to obtain soap_fault_detail from soap_fault"); + return AXIS2_FAILURE; + } + + body_node = axiom_soap_fault_detail_get_base_node(soap_fault_detial, env); + if(!body_node) + { + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "failure to get base node from soap_fault_detail."); + return AXIS2_FAILURE; + } + + } + else + { + + body_node = axiom_soap_body_get_base_node(soap_body, env); + if(!body_node) + { + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "failure to get base node from soap_body."); + return AXIS2_FAILURE; + } + } + + data_out = axiom_node_get_first_element(body_node, env); + + if(!data_out || axiom_node_get_node_type(data_out, env) != AXIOM_ELEMENT) + { + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "unable to get first element from soap_body, base node."); + return AXIS2_FAILURE; + } + + axiom_node_serialize(data_out, env, om_output); + buffer = (axis2_char_t *)axiom_xml_writer_get_xml(xml_writer, env); + buffer_size = axiom_xml_writer_get_xml_size(xml_writer, env); + axutil_stream_write(out_stream, env, buffer, buffer_size); + /* Finish Rest Processing */ + + } + else + { + axiom_soap_body_t *body = NULL; + + body = axiom_soap_envelope_get_body(soap_data_out, env); + fault = axiom_soap_body_has_fault(body, env); + + /* SOAP Processing */ + axiom_output_set_do_optimize(om_output, env, do_mtom); + axiom_soap_envelope_serialize(soap_data_out, env, om_output, AXIS2_FALSE); + if(do_mtom && !fault) + { + axis2_status_t mtom_status = AXIS2_FAILURE; + axis2_char_t *content_type = NULL; + axutil_array_list_t *mime_parts = NULL; + + /*Create the attachment related data and put them to an + *array_list */ + mtom_status = axiom_output_flush(om_output, env); + if(mtom_status == AXIS2_SUCCESS) + { + mime_parts = axiom_output_get_mime_parts(om_output, env); + if(!mime_parts) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Unable to create the mime_part list from om_output"); + return AXIS2_FAILURE; + } + else + { + axis2_msg_ctx_set_mime_parts(msg_ctx, env, mime_parts); + } + } + /*om_out put has the details of content_type */ + content_type = (axis2_char_t *)axiom_output_get_content_type(om_output, env); + AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_CONTENT_TYPE(out_info, env, content_type); + } + else + { + buffer = (axis2_char_t *)axiom_xml_writer_get_xml(xml_writer, env); + buffer_size = axiom_xml_writer_get_xml_size(xml_writer, env); + + /* This is where it actually fill the buffer in out_stream. In application server + * side this is the out_stream passed to the in message context from http_worker + * function and then copied to the out message context. + */ + axutil_stream_write(out_stream, env, buffer, buffer_size); + } + } + + op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env); + axis2_op_ctx_set_response_written(op_ctx, env, AXIS2_TRUE); + } + } + + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + + if(transport_url) + { + if(epr) + { + axis2_endpoint_ref_free(epr, env); + epr = NULL; + } + } + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_transport_sender_invoke"); + return status; +} + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_clean_up( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, transport_sender, AXIS2_FAILURE); + /* + * Clean up is not used. If the http sender needs + * to be cleaned up it should be done here. + */ + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_init( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx, + axis2_transport_out_desc_t * out_desc) +{ + axutil_param_t *version_param = NULL; + axis2_char_t *version = NULL; + axis2_char_t *temp = NULL; + axutil_param_t *temp_param = NULL; + + AXIS2_PARAM_CHECK(env->error, conf_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, out_desc, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, transport_sender, AXIS2_FAILURE); + + /* Getting HTTP version from axis2.xml */ + version_param = axutil_param_container_get_param(axis2_transport_out_desc_param_container( + out_desc, env), env, AXIS2_HTTP_PROTOCOL_VERSION); + + if(version_param) + { + version = axutil_param_get_value(version_param, env); + } + + if(version) + { + /* handling HTTP 1.1 */ + if(0 == axutil_strcmp(version, AXIS2_HTTP_HEADER_PROTOCOL_11)) + { + axis2_char_t *encoding = NULL; + axutil_param_t *encoding_param = NULL; + if(AXIS2_INTF_TO_IMPL(transport_sender)->http_version) + { + AXIS2_FREE(env->allocator, AXIS2_INTF_TO_IMPL(transport_sender)->http_version); + } + + AXIS2_INTF_TO_IMPL(transport_sender)->http_version = axutil_strdup(env, version); + AXIS2_INTF_TO_IMPL(transport_sender)->keep_alive = AXIS2_TRUE; + encoding_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(out_desc, env), env, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING); + + if(encoding_param) + { + encoding = axutil_param_get_value(encoding_param, env); + } + + if(encoding && 0 + == axutil_strcmp(encoding, AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)) + { + AXIS2_INTF_TO_IMPL(transport_sender)->chunked = AXIS2_TRUE; + } + else + { + AXIS2_INTF_TO_IMPL(transport_sender)->chunked = AXIS2_FALSE; + } + + } + else if(0 == axutil_strcmp(version, AXIS2_HTTP_HEADER_PROTOCOL_10)) + { + axutil_param_t *keepalive_param = NULL; + + /* Handling HTTP 1.0 */ + if(AXIS2_INTF_TO_IMPL(transport_sender)->http_version) + { + AXIS2_FREE(env->allocator, AXIS2_INTF_TO_IMPL(transport_sender)->http_version); + } + AXIS2_INTF_TO_IMPL(transport_sender)->http_version = axutil_strdup(env, version); + AXIS2_INTF_TO_IMPL(transport_sender)->chunked = AXIS2_FALSE; + keepalive_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(out_desc, env), env, + AXIS2_HTTP_HEADER_CONNECTION_KEEPALIVE); + if(keepalive_param) + { + axis2_char_t *keepalive_value = NULL; + keepalive_value = axutil_param_get_value(keepalive_param, env); + if(!axutil_strcmp(keepalive_value, AXIS2_VALUE_FALSE)) + { + AXIS2_INTF_TO_IMPL(transport_sender)->keep_alive = AXIS2_FALSE; + } + } + } + } + else + { + /* HTTP version is not available in axis2.xml */ + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_HTTP_VERSION, AXIS2_FAILURE); + return AXIS2_FAILURE; + } + + /* Getting HTTP_SO_TIMEOUT value from axis2.xml */ + temp_param = axutil_param_container_get_param(axis2_transport_out_desc_param_container( + out_desc, env), env, AXIS2_HTTP_SO_TIMEOUT); + + if(temp_param) + { + temp = axutil_param_get_value(temp_param, env); + } + + if(temp) + { + AXIS2_INTF_TO_IMPL(transport_sender)->so_timeout = AXIS2_ATOI(temp); + } + + /* Getting HTTP_CONNECTION_TIMEOUT from axis2.xml */ + temp + = (axis2_char_t *)axutil_param_container_get_param( + axis2_transport_out_desc_param_container(out_desc, env), env, + AXIS2_HTTP_CONNECTION_TIMEOUT); + if(temp_param) + { + temp = axutil_param_get_value(temp_param, env); + } + + /* set axis2.xml connection timeout value to http_sender */ + if(temp) + { + AXIS2_INTF_TO_IMPL(transport_sender)->connection_timeout = AXIS2_ATOI(temp); + } + + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_write_message( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_endpoint_ref_t * epr, + axiom_soap_envelope_t * out, + axiom_output_t * om_output) +{ + const axis2_char_t *soap_action = NULL; + const axis2_char_t *url = NULL; + axis2_http_sender_t *sender = NULL; + axis2_status_t status = AXIS2_FAILURE; + const axis2_char_t *soap_ns_uri = NULL; + axiom_soap_envelope_t *response_envelope = NULL; + axis2_op_t *op = NULL; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, epr, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, om_output, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, transport_sender, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, out, AXIS2_FAILURE); + + /* epr is already passed NULL checking */ + url = axis2_endpoint_ref_get_address(epr, env); + + soap_action = axutil_string_get_buffer(axis2_msg_ctx_get_soap_action(msg_ctx, env), env); + + if(!soap_action) + { + soap_action = ""; + } + + sender = axis2_http_sender_create(env); + + if(!sender) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "http sender creation failed"); + return AXIS2_FAILURE; + } + axis2_http_sender_set_keep_alive(sender, env, AXIS2_INTF_TO_IMPL(transport_sender)->keep_alive); + + /* For the MTOM case we should on chunking. And for chunking to work the + * protocol should be http 1.1*/ + + if(axis2_msg_ctx_get_doing_mtom(msg_ctx, env)) + { + AXIS2_HTTP_SENDER_SET_CHUNKED(sender, env, AXIS2_TRUE); + AXIS2_HTTP_SENDER_SET_HTTP_VERSION(sender, env, AXIS2_HTTP_HEADER_PROTOCOL_11); + } + else + { + AXIS2_HTTP_SENDER_SET_CHUNKED(sender, env, AXIS2_INTF_TO_IMPL(transport_sender)->chunked); + AXIS2_HTTP_SENDER_SET_HTTP_VERSION(sender, env, + AXIS2_INTF_TO_IMPL(transport_sender)->http_version); + } + AXIS2_HTTP_SENDER_SET_OM_OUTPUT(sender, env, om_output); + +#ifdef AXIS2_LIBCURL_ENABLED + AXIS2_LOG_DEBUG (env->log, AXIS2_LOG_SI, "using axis2 libcurl http sender."); + status = + axis2_libcurl_http_send(AXIS2_INTF_TO_IMPL(transport_sender)->libcurl, + sender, env, msg_ctx, out, url, soap_action); +#else + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "using axis2 native http sender."); + status = AXIS2_HTTP_SENDER_SEND(sender, env, msg_ctx, out, url, soap_action); +#endif + + AXIS2_HTTP_SENDER_FREE(sender, env); + sender = NULL; + + /* if the send was not successful, do not process any response */ + if(status != AXIS2_SUCCESS) + return status; + + op = axis2_msg_ctx_get_op(msg_ctx, env); + if(op) + { + /* handle one way case */ + const axis2_char_t *mep = axis2_op_get_msg_exchange_pattern(op, env); + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "OP name axutil_qname_get_localpart = %s", mep); + if(axutil_strcmp(mep, AXIS2_MEP_URI_OUT_ONLY) == 0 || axutil_strcmp(mep, + AXIS2_MEP_URI_ROBUST_OUT_ONLY) == 0 || axutil_strcmp(mep, AXIS2_MEP_URI_IN_ONLY) == 0) + { + return status; + } + else + { + /* AXIS2_MEP_URI_IN_OUT case , we have a response this + * time */ + soap_ns_uri + = axis2_msg_ctx_get_is_soap_11(msg_ctx, env) ? AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI + : AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI; + response_envelope = axis2_http_transport_utils_create_soap_msg(env, msg_ctx, + soap_ns_uri); + if(response_envelope) + { + axis2_msg_ctx_set_response_soap_envelope(msg_ctx, env, response_envelope); + } + } + } + + return status; +} + +/** + * Following block distinguish the exposed part of the dll. + */ + +/* When building for static deployment, give the get and remove methods + * unique names. This avoids having the linker fail with duplicate symbol + * errors. + */ + +AXIS2_EXPORT int +#ifndef AXIS2_STATIC_DEPLOY +axis2_get_instance( +#else + axis2_http_transport_sender_get_instance( +#endif + struct axis2_transport_sender **inst, + const axutil_env_t * env) +{ + *inst = axis2_http_transport_sender_create(env); + if(!(*inst)) + { + return AXIS2_FAILURE; + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXPORT int +#ifndef AXIS2_STATIC_DEPLOY +axis2_remove_instance( +#else + axis2_http_transport_sender_remove_instance( +#endif + axis2_transport_sender_t * inst, + const axutil_env_t * env) +{ + if(inst) + { + AXIS2_TRANSPORT_SENDER_FREE(inst, env); + } + return AXIS2_SUCCESS; +} + diff --git a/src/core/transport/http/sender/libcurl/Makefile.am b/src/core/transport/http/sender/libcurl/Makefile.am new file mode 100644 index 0000000..90e5ce6 --- /dev/null +++ b/src/core/transport/http/sender/libcurl/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST= axis2_libcurl.h axis2_libcurl.c libcurl_stream.h libcurl_stream.c + diff --git a/src/core/transport/http/sender/libcurl/axis2_libcurl.c b/src/core/transport/http/sender/libcurl/axis2_libcurl.c new file mode 100644 index 0000000..834e69b --- /dev/null +++ b/src/core/transport/http/sender/libcurl/axis2_libcurl.c @@ -0,0 +1,1169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef AXIS2_LIBCURL_ENABLED + +#include "axis2_libcurl.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libcurl_stream.h" + +static int ref = 0; + +struct axis2_libcurl +{ + axis2_char_t *memory; + axutil_array_list_t *alist; + unsigned int size; + const axutil_env_t *env; + char errorbuffer[CURL_ERROR_SIZE]; + CURL *handler; + axis2_bool_t cookies; +}; + +static size_t +axis2_libcurl_write_memory_callback( + void *ptr, + size_t size, + size_t nmemb, + void *data); + +static size_t +axis2_libcurl_header_callback( + void *ptr, + size_t size, + size_t nmemb, + void *data); + +static axis2_char_t * +axis2_libcurl_get_content_type( + axis2_libcurl_t *curl, + const axutil_env_t * env); + +static int +axis2_libcurl_get_content_length( + axis2_libcurl_t *curl, + const axutil_env_t * env); + +static axis2_http_header_t * +axis2_libcurl_get_first_header( + axis2_libcurl_t *curl, + const axutil_env_t * env, + const axis2_char_t * str); + +static void +axis2_libcurl_free_headers( + axis2_libcurl_t *curl, + const axutil_env_t * env); + +static axis2_status_t +axis2_libcurl_set_options( + CURL *handler, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +axis2_status_t AXIS2_CALL +axis2_libcurl_send( + axis2_libcurl_t *data, + axiom_output_t * om_output, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axiom_soap_envelope_t * out, + const axis2_char_t * str_url, + const axis2_char_t * soap_action) +{ + struct curl_slist *headers = NULL; + axiom_soap_body_t *soap_body; + axis2_bool_t is_soap = AXIS2_TRUE; + axis2_bool_t send_via_get = AXIS2_FALSE; + axis2_bool_t send_via_head = AXIS2_FALSE; + axis2_bool_t send_via_put = AXIS2_FALSE; + axis2_bool_t send_via_delete = AXIS2_FALSE; + axis2_bool_t doing_mtom = AXIS2_FALSE; + axiom_node_t *body_node = NULL; + axiom_node_t *data_out = NULL; + axutil_property_t *method = NULL; + axis2_char_t *method_value = NULL; + axiom_xml_writer_t *xml_writer = NULL; + axis2_char_t *buffer = NULL; + unsigned int buffer_size = 0; + int content_length = -1; + axis2_char_t *content_type = NULL; + axis2_char_t *content_len = AXIS2_HTTP_HEADER_CONTENT_LENGTH_; + const axis2_char_t *char_set_enc = NULL; + axis2_char_t *content = AXIS2_HTTP_HEADER_CONTENT_TYPE_; + axis2_char_t *soap_action_header = AXIS2_HTTP_HEADER_SOAP_ACTION_; + axutil_stream_t *in_stream; + axutil_property_t *trans_in_property; + axutil_string_t *char_set_enc_str; + axis2_byte_t *output_stream = NULL; + int output_stream_size = 0; + CURL *handler; + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_out_desc_t *trans_desc = NULL; + axutil_param_t *write_xml_declaration_param = NULL; + axutil_hash_t *transport_attrs = NULL; + axis2_bool_t write_xml_declaration = AXIS2_FALSE; + axutil_property_t *property; + int *response_length = NULL; + axis2_http_status_line_t *status_line = NULL; + axis2_char_t *status_line_str = NULL; + axis2_char_t *tmp_strcat = NULL; + int status_code = 0; + + AXIS2_PARAM_CHECK(env->error, data, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, data->handler, AXIS2_FAILURE); + + handler = data->handler; + curl_easy_reset(handler); + curl_easy_setopt(handler, CURLOPT_ERRORBUFFER, &data->errorbuffer); + headers = curl_slist_append(headers, AXIS2_HTTP_HEADER_USER_AGENT_AXIS2C); + headers = curl_slist_append(headers, AXIS2_HTTP_HEADER_ACCEPT_); + headers = curl_slist_append(headers, AXIS2_HTTP_HEADER_EXPECT_); + + if(AXIS2_FAILURE == axis2_libcurl_set_options(handler, env, msg_ctx)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[axis2libcurl]Setting options in Libcurl failed"); + return AXIS2_FAILURE; + } + + if (AXIS2_TRUE == axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + is_soap = AXIS2_FALSE; + } + else + { + is_soap = AXIS2_TRUE; + } + + if (!is_soap) + { + soap_body = axiom_soap_envelope_get_body(out, env); + if (!soap_body) + { + AXIS2_HANDLE_ERROR(env, + AXIS2_ERROR_SOAP_ENVELOPE_OR_SOAP_BODY_NULL, + AXIS2_FAILURE); + return AXIS2_FAILURE; + } + + body_node = axiom_soap_body_get_base_node(soap_body, env); + if (!body_node) + { + AXIS2_HANDLE_ERROR(env, + AXIS2_ERROR_SOAP_ENVELOPE_OR_SOAP_BODY_NULL, + AXIS2_FAILURE); + + return AXIS2_FAILURE; + } + data_out = axiom_node_get_first_element(body_node, env); + + method = (axutil_property_t *) axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_HTTP_METHOD); + + if (method) + { + method_value = + (axis2_char_t *) axutil_property_get_value(method, env); + } + + /* The default is POST */ + if (method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_GET)) + { + send_via_get = AXIS2_TRUE; + } + else if (method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_HEAD)) + { + send_via_head = AXIS2_TRUE; + } + else if (method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_PUT)) + { + send_via_put = AXIS2_TRUE; + } + else if (method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_DELETE)) + { + send_via_delete = AXIS2_TRUE; + } + } + + conf_ctx = axis2_msg_ctx_get_conf_ctx (msg_ctx, env); + if (conf_ctx) + { + conf = axis2_conf_ctx_get_conf (conf_ctx, env); + } + + if (conf) + { + trans_desc = axis2_conf_get_transport_out (conf, + env, AXIS2_TRANSPORT_ENUM_HTTP); + } + + if (trans_desc) + { + write_xml_declaration_param = + axutil_param_container_get_param + (axis2_transport_out_desc_param_container (trans_desc, env), env, + AXIS2_XML_DECLARATION); + } + + if (write_xml_declaration_param) + { + transport_attrs = + axutil_param_get_attributes (write_xml_declaration_param, env); + if (transport_attrs) + { + axutil_generic_obj_t *obj = NULL; + axiom_attribute_t *write_xml_declaration_attr = NULL; + axis2_char_t *write_xml_declaration_attr_value = NULL; + + obj = axutil_hash_get (transport_attrs, AXIS2_ADD_XML_DECLARATION, + AXIS2_HASH_KEY_STRING); + if (obj) + { + write_xml_declaration_attr = (axiom_attribute_t *) + axutil_generic_obj_get_value (obj, + env); + } + if (write_xml_declaration_attr) + { + write_xml_declaration_attr_value = + axiom_attribute_get_value (write_xml_declaration_attr, env); + } + if (write_xml_declaration_attr_value && + 0 == axutil_strcasecmp (write_xml_declaration_attr_value, + AXIS2_VALUE_TRUE)) + { + write_xml_declaration = AXIS2_TRUE; + } + } + } + + if (write_xml_declaration) + { + axiom_output_write_xml_version_encoding (om_output, env); + } + + if (!send_via_get && !send_via_head && !send_via_delete) + { + xml_writer = axiom_output_get_xml_writer(om_output, env); + + char_set_enc_str = axis2_msg_ctx_get_charset_encoding(msg_ctx, env); + + if (!char_set_enc_str) + { + char_set_enc = AXIS2_DEFAULT_CHAR_SET_ENCODING; + } + else + { + char_set_enc = axutil_string_get_buffer(char_set_enc_str, env); + } + + if (!send_via_put && is_soap) + { + doing_mtom = axis2_msg_ctx_get_doing_mtom(msg_ctx, env); + + axiom_output_set_do_optimize(om_output, env, doing_mtom); + axiom_soap_envelope_serialize(out, env, om_output, AXIS2_FALSE); + if (AXIS2_TRUE == axis2_msg_ctx_get_is_soap_11(msg_ctx, env)) + { + if (AXIS2_ESC_DOUBLE_QUOTE != *soap_action) + { + axis2_char_t *tmp_soap_action = NULL; + tmp_soap_action = + AXIS2_MALLOC(env->allocator, + (axutil_strlen(soap_action) + + 5) * sizeof(axis2_char_t)); + sprintf(tmp_soap_action, "\"%s\"", soap_action); + tmp_strcat = axutil_stracat(env, soap_action_header,tmp_soap_action); + headers = curl_slist_append(headers, tmp_strcat); + AXIS2_FREE(env->allocator, tmp_strcat); + AXIS2_FREE(env->allocator, tmp_soap_action); + } + else + { + tmp_strcat = axutil_stracat(env, soap_action_header, soap_action); + headers = curl_slist_append(headers, tmp_strcat ); + AXIS2_FREE(env->allocator, tmp_strcat); + } + } + + if (doing_mtom) + { + /*axiom_output_flush(om_output, env, &output_stream, + &output_stream_size);*/ + axiom_output_flush(om_output, env); + content_type = + (axis2_char_t *) axiom_output_get_content_type(om_output, + env); + if (AXIS2_TRUE != axis2_msg_ctx_get_is_soap_11(msg_ctx, env)) + { + if (axutil_strcmp(soap_action, "")) + { + /* handle SOAP action for SOAP 1.2 case */ + axis2_char_t *temp_content_type = NULL; + temp_content_type = axutil_stracat (env, + content_type, + AXIS2_CONTENT_TYPE_ACTION); + content_type = temp_content_type; + temp_content_type = axutil_stracat (env, + content_type, + soap_action); + AXIS2_FREE (env->allocator, content_type); + content_type = temp_content_type; + temp_content_type = + axutil_stracat (env, content_type, + AXIS2_ESC_DOUBLE_QUOTE_STR); + AXIS2_FREE (env->allocator, content_type); + content_type = temp_content_type; + } + } + } + else if (AXIS2_TRUE == axis2_msg_ctx_get_is_soap_11(msg_ctx, env)) + { + axis2_char_t *temp_content_type = NULL; + content_type = + (axis2_char_t *) AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML; + content_type = axutil_stracat(env, content_type, + AXIS2_CONTENT_TYPE_CHARSET); + temp_content_type = + axutil_stracat(env, content_type, char_set_enc); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + } + else + { + axis2_char_t *temp_content_type = NULL; + content_type = + (axis2_char_t *) AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP; + content_type = axutil_stracat(env, content_type, + AXIS2_CONTENT_TYPE_CHARSET); + temp_content_type = + axutil_stracat(env, content_type, char_set_enc); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + if (axutil_strcmp(soap_action, "")) + { + temp_content_type = + axutil_stracat(env, content_type, + AXIS2_CONTENT_TYPE_ACTION); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + temp_content_type = + axutil_stracat(env, content_type, soap_action); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + } + temp_content_type = axutil_stracat(env, content_type, + AXIS2_SEMI_COLON_STR); + AXIS2_FREE(env->allocator, content_type); + content_type = temp_content_type; + } + } + else if (is_soap) + { + AXIS2_LOG_ERROR (env->log, AXIS2_LOG_SI, "Attempt to send SOAP" + "message using HTTP PUT failed"); + return AXIS2_FAILURE; + } + else + { + axutil_property_t *content_type_property = NULL; + axutil_hash_t *content_type_hash = NULL; + axis2_char_t *content_type_value = NULL; + + axiom_node_serialize(data_out, env, om_output); + content_type_property = + (axutil_property_t *) + axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_USER_DEFINED_HTTP_HEADER_CONTENT_TYPE); + + if (content_type_property) + { + content_type_hash = + (axutil_hash_t *) + axutil_property_get_value(content_type_property, env); + + if (content_type_hash) + { + content_type_value = + (char *) axutil_hash_get(content_type_hash, + AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HASH_KEY_STRING); + } + } + + if (content_type_value) + { + content_type = content_type_value; + } + else + { + content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML; + } + + } + + buffer = axiom_xml_writer_get_xml(xml_writer, env); + if (!doing_mtom) + { + buffer_size = axiom_xml_writer_get_xml_size(xml_writer, env); + } + else + buffer_size = output_stream_size; + { + char tmp_buf[10]; + sprintf(tmp_buf, "%d", buffer_size); + tmp_strcat = axutil_stracat(env, content_len, tmp_buf); + headers = curl_slist_append(headers, tmp_strcat); + AXIS2_FREE(env->allocator, tmp_strcat); + tmp_strcat = NULL; + + tmp_strcat = axutil_stracat(env, content, content_type); + headers = curl_slist_append(headers, tmp_strcat); + AXIS2_FREE(env->allocator, tmp_strcat); + tmp_strcat = NULL; + } + + if (!doing_mtom) + { + curl_easy_setopt(handler, CURLOPT_POSTFIELDSIZE, buffer_size); + curl_easy_setopt(handler, CURLOPT_POSTFIELDS, buffer); + } + else + { + curl_easy_setopt(handler, CURLOPT_POSTFIELDSIZE, + output_stream_size); + curl_easy_setopt(handler, CURLOPT_POSTFIELDS, output_stream); + } + + if (send_via_put) + { + curl_easy_setopt(handler, CURLOPT_CUSTOMREQUEST, AXIS2_HTTP_PUT); + } + curl_easy_setopt(handler, CURLOPT_URL, str_url); + } + else + { + axis2_char_t *request_param; + axis2_char_t *url_encode; + request_param = + (axis2_char_t *) axis2_http_sender_get_param_string(NULL, env, + msg_ctx); + url_encode = axutil_strcat(env, str_url, AXIS2_Q_MARK_STR, + request_param, NULL); + if (send_via_get) + { + curl_easy_setopt(handler, CURLOPT_HTTPGET, 1); + } + else if (send_via_head) + { + curl_easy_setopt(handler, CURLOPT_NOBODY, 1); + } + else if (send_via_delete) + { + curl_easy_setopt(handler, CURLOPT_CUSTOMREQUEST, AXIS2_HTTP_DELETE); + } + curl_easy_setopt(handler, CURLOPT_URL, url_encode); + } + + { + axis2_bool_t manage_session; + manage_session = axis2_msg_ctx_get_manage_session(msg_ctx, env); + if (manage_session == AXIS2_TRUE) + { + if (data->cookies == AXIS2_FALSE) + { + /* Ensure cookies enabled to manage session */ + /* Pass empty cookie string to enable cookies */ + curl_easy_setopt(handler, CURLOPT_COOKIEFILE, " "); + data->cookies = AXIS2_TRUE; + } + } + else if (data->cookies == AXIS2_TRUE) + { + /* Pass special string ALL to reset cookies if any have been enabled. */ + /* If cookies have ever been enabled, we reset every time as long as + manage_session is false, as there is no clear curl option to + turn off the cookie engine once enabled. */ + curl_easy_setopt(handler, CURLOPT_COOKIELIST, AXIS2_ALL); + } + } + + curl_easy_setopt(handler, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(handler, CURLOPT_WRITEFUNCTION, + axis2_libcurl_write_memory_callback); + curl_easy_setopt(handler, CURLOPT_WRITEDATA, data); + + curl_easy_setopt (handler, CURLOPT_HEADERFUNCTION, axis2_libcurl_header_callback); + + curl_easy_setopt (handler, CURLOPT_WRITEHEADER, data); + + /* Free response data from previous request */ + if( data->size ) + { + if (data->memory) + { + AXIS2_FREE(data->env->allocator, data->memory); + } + data->size = 0; + } + + if (curl_easy_perform(handler)) + { + AXIS2_LOG_ERROR (env->log, AXIS2_LOG_SI, "%s", &data->errorbuffer); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, + AXIS2_FAILURE); + return AXIS2_FAILURE; + } + + in_stream = axutil_stream_create_libcurl(env, data->memory, data->size); + trans_in_property = axutil_property_create(env); + axutil_property_set_scope(trans_in_property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_free_func(trans_in_property, env, + libcurl_stream_free); + axutil_property_set_value(trans_in_property, env, in_stream); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_TRANSPORT_IN, + trans_in_property); + + if (axutil_array_list_size(data->alist, env) > 0) + { + status_line_str = axutil_array_list_get(data->alist, env, 0); + if (status_line_str) + { + status_line = axis2_http_status_line_create(env, status_line_str); + } + } + + if (status_line) + { + status_code = axis2_http_status_line_get_status_code(status_line, env); + } + + axis2_msg_ctx_set_status_code (msg_ctx, env, status_code); + AXIS2_FREE(data->env->allocator, content_type); + content_type = axis2_libcurl_get_content_type(data, env); + + if (content_type) + { + if (strstr (content_type, AXIS2_HTTP_HEADER_ACCEPT_MULTIPART_RELATED) + && strstr (content_type, AXIS2_HTTP_HEADER_ACCEPT_XOP_XML)) + { + axis2_ctx_t *axis_ctx = + axis2_op_ctx_get_base (axis2_msg_ctx_get_op_ctx (msg_ctx, env), + env); + property = axutil_property_create (env); + axutil_property_set_scope (property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_value (property, + env, axutil_strdup (env, content_type)); + axis2_ctx_set_property (axis_ctx, + env, MTOM_RECIVED_CONTENT_TYPE, property); + } + } + + content_length = axis2_libcurl_get_content_length(data, env); + if (content_length >= 0) + { + response_length = AXIS2_MALLOC (env->allocator, sizeof (int)); + memcpy (response_length, &content_length, sizeof (int)); + property = axutil_property_create (env); + axutil_property_set_scope (property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_value (property, env, response_length); + axis2_msg_ctx_set_property (msg_ctx, env, + AXIS2_HTTP_HEADER_CONTENT_LENGTH, property); + } + + curl_slist_free_all (headers); + /* release the read http headers. */ + /* (commenting out the call below is a clever way to force a premature EOF + condition in subsequent messages, as they will be read using the content-length + of the first message.) */ + axis2_libcurl_free_headers(data, env); + AXIS2_FREE(data->env->allocator, content_type); + axis2_http_status_line_free( status_line, env); + + return AXIS2_SUCCESS; +} + +static size_t +axis2_libcurl_write_memory_callback( + void *ptr, + size_t size, + size_t nmemb, + void *data) +{ + size_t realsize = size * nmemb; + axis2_libcurl_t *curl = (axis2_libcurl_t *) data; + axis2_char_t *buffer = + (axis2_char_t *) AXIS2_MALLOC(curl->env->allocator, + curl->size + realsize + 1); + if (buffer) + { + if (curl->size) + { + memcpy(&(buffer[0]), curl->memory, curl->size); + AXIS2_FREE(curl->env->allocator, curl->memory); + } + + memcpy(&(buffer[curl->size]), ptr, realsize); + curl->size += (int)realsize; + /* We are sure that the difference lies within the int range */ + buffer[curl->size] = 0; + curl->memory = buffer; + } + return realsize; +} + +static size_t +axis2_libcurl_header_callback( + void *ptr, + size_t size, + size_t nmemb, + void *data) +{ + axis2_char_t *memory; + size_t realsize = size * nmemb; + axis2_libcurl_t *curl = (axis2_libcurl_t *) data; + memory = (axis2_char_t *)AXIS2_MALLOC(curl->env->allocator, realsize + 1); + if (memory) + { + memcpy(&(memory[0]), ptr, realsize); + memory[realsize] = 0; + axutil_array_list_add(curl->alist, curl->env, memory); + } + return realsize; +} + +axis2_libcurl_t * AXIS2_CALL +axis2_libcurl_create( + const axutil_env_t * env) +{ + axis2_libcurl_t *curl = NULL; + CURLcode code; + + if (!ref) + { + /* curl_global_init is not thread-safe so it would be better + to do this, as well as the test and increment of ref, under + mutex if one is available, or as part of an + axis2_initialize() if a global initialize is created. + Otherwise the client application should perform the the + curl_global_init itself in a thread-safe fashion. + */ + code = curl_global_init(CURL_GLOBAL_ALL); + if (code) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "libcurl curl_global_init failed, error: %d", code); + return NULL; + } + ref++; + } + + curl = + (axis2_libcurl_t *) AXIS2_MALLOC(env->allocator, + sizeof(axis2_libcurl_t)); + if (curl) + { + curl->memory = 0; + curl->size = 0; + curl->alist = axutil_array_list_create(env, 15); + curl->env = env; + curl->handler = curl_easy_init(); + curl->cookies = AXIS2_FALSE; + if ((!curl->alist) || (!curl->handler)) + { + axis2_libcurl_free(curl, env); + curl = 0; + } + } + return curl; +} + +void AXIS2_CALL +axis2_libcurl_free( + axis2_libcurl_t *curl, + const axutil_env_t * env) +{ + if (!curl) + { + return; + } + + if (curl->handler) + { + curl_easy_cleanup (curl->handler); + } + if (curl->alist) + { + axis2_libcurl_free_headers(curl, env); + axutil_array_list_free(curl->alist, env); + curl->alist = NULL; + } + if (curl->memory) + { + AXIS2_FREE(env->allocator, curl->memory); + } + + AXIS2_FREE(env->allocator, curl); +} + +static void +axis2_libcurl_free_headers( + axis2_libcurl_t *curl, + const axutil_env_t * env) +{ + int count = 0; + axutil_array_list_t *header_group = curl->alist; + if (header_group) + { + while ((count = axutil_array_list_size(header_group, env)) > 0) + { + axis2_char_t *header = axutil_array_list_remove(header_group, env, count-1); + AXIS2_FREE(env->allocator, header); + } + } +} + +static axis2_http_header_t * +axis2_libcurl_get_first_header( + axis2_libcurl_t *curl, + const axutil_env_t * env, + const axis2_char_t * str) +{ + axis2_http_header_t *tmp_header = NULL; + axis2_char_t *tmp_header_str = NULL; + axis2_char_t *tmp_name = NULL; + int i = 0; + int count = 0; + axutil_array_list_t *header_group = NULL; + + AXIS2_PARAM_CHECK(env->error, curl, NULL); + AXIS2_PARAM_CHECK(env->error, str, NULL); + + header_group = curl->alist; + if (!header_group) + { + return NULL; + } + + if (0 == axutil_array_list_size(header_group, env)) + { + return NULL; + } + + count = axutil_array_list_size(header_group, env); + + for (i = 0; i < count; i++) + { + tmp_header_str = (axis2_char_t *) axutil_array_list_get(header_group, + env, i); + if(!tmp_header_str) + { + continue; + } + tmp_header = (axis2_http_header_t *) axis2_http_header_create_by_str(env, tmp_header_str); + if(!tmp_header) + { + continue; + } + + tmp_name = axis2_http_header_get_name(tmp_header, env); + if (0 == axutil_strcasecmp(str, tmp_name)) + { + return tmp_header; + } + else + { + axis2_http_header_free( tmp_header, env ); + } + + } + return NULL; +} + +static int +axis2_libcurl_get_content_length( + axis2_libcurl_t *curl, + const axutil_env_t * env) +{ + axis2_http_header_t *tmp_header; + int rtn_value = -1; + + tmp_header = axis2_libcurl_get_first_header + (curl, env, AXIS2_HTTP_HEADER_CONTENT_LENGTH); + if (tmp_header) + { + rtn_value = AXIS2_ATOI(axis2_http_header_get_value(tmp_header, env)); + axis2_http_header_free( tmp_header, env ); + } + return rtn_value; +} + +static axis2_char_t * +axis2_libcurl_get_content_type( + axis2_libcurl_t *curl, + const axutil_env_t * env) +{ + axis2_http_header_t *tmp_header; + axis2_char_t *rtn_value = NULL; + + tmp_header = axis2_libcurl_get_first_header + (curl, env, AXIS2_HTTP_HEADER_CONTENT_TYPE); + if (tmp_header) + { + rtn_value = axutil_strdup (env, axis2_http_header_get_value(tmp_header, env) ); + axis2_http_header_free( tmp_header, env ); + } + else + { + rtn_value = axutil_strdup (env, AXIS2_HTTP_HEADER_ACCEPT_TEXT_PLAIN); + } + + return rtn_value; +} + +/** + * axis2_libcurl_set_auth_options maps authentication AXIS2/C options to + * libcURL options. + * + * CURLOPT_USERPWD - char * user:password for authentication + * CURLOPT_HTTPAUTH - long bitmask which authentication methods to use + */ +static axis2_status_t +axis2_libcurl_set_auth_options( + CURL *handler, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axutil_property_t *property = NULL; + axis2_char_t *uname = NULL; + axis2_char_t *passwd = NULL; + axis2_char_t *auth_type = NULL; + + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_UNAME); + if (property) + { + uname = (axis2_char_t *) axutil_property_get_value(property, env); + } + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_PASSWD); + if (property) + { + passwd = (axis2_char_t *) axutil_property_get_value(property, env); + } + if (uname && passwd) + { + axis2_char_t buffer[256]; + strncpy(buffer, uname, 256); + strncat(buffer, ":", 256); + strncat(buffer, passwd, 256); + curl_easy_setopt(handler, CURLOPT_USERPWD, buffer); + } + + property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_TYPE); + + if (property) + { + auth_type = (axis2_char_t *) axutil_property_get_value(property, env); + } + + if (auth_type && 0 == axutil_strcmp(auth_type, AXIS2_HTTP_AUTH_TYPE_BASIC)) + { + curl_easy_setopt(handler, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + } + else + { + /* Uses anonymous connection.*/ + } + + return AXIS2_SUCCESS; +} + +/** + * axis2_libcurl_set_proxy_options maps proxy AXIS2/C options to + * libcURL options. + * + * CURLOPT_PROXY - char * proxy hostname + * CURLOPT_PROXYPORT - long proxy listen port + * CURLOPT_PROXYUSERPWD - char * user:password to authenticate to proxy + * + * TODO: + * CURLOPT_PROXYTYPE - long enum type of proxy (HTTP, SOCKS) + * CURLOPT_PROXYAUTH - long bitmask which authentication methods to use for proxy + */ +static axis2_status_t +axis2_libcurl_set_proxy_options( + CURL *handler, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_out_desc_t *trans_desc = NULL; + axutil_param_t *proxy_param = NULL; + axutil_hash_t *transport_attrs = NULL; + axutil_property_t *property = NULL; + axis2_char_t *uname = NULL; + axis2_char_t *passwd = NULL; + axis2_char_t *proxy_host = NULL; + axis2_char_t *proxy_port = NULL; + + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_UNAME); + if (property) + { + uname = (axis2_char_t *) axutil_property_get_value(property, env); + } + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_PASSWD); + if (property) + { + passwd = (axis2_char_t *) axutil_property_get_value(property, env); + } + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + if (conf_ctx) + { + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + if (conf) + { + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + } + } + if (trans_desc) + { + proxy_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, AXIS2_HTTP_PROXY_API); + if (!proxy_param) + { + proxy_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, AXIS2_HTTP_PROXY); + } + if (proxy_param) + { + transport_attrs = axutil_param_get_attributes(proxy_param, env); + } + } + + if (transport_attrs) + { + axutil_generic_obj_t *obj = NULL; + axiom_attribute_t *attr = NULL; + + if (!uname || !passwd) + { + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_USERNAME, AXIS2_HASH_KEY_STRING); + if (obj) + { + attr = (axiom_attribute_t *) axutil_generic_obj_get_value(obj, env); + } + if (attr) + { + uname = axiom_attribute_get_value(attr, env); + } + + attr = NULL; + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_PASSWORD, AXIS2_HASH_KEY_STRING); + if (obj) + { + attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if (attr) + { + passwd = axiom_attribute_get_value(attr, env); + } + } + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_HOST, AXIS2_HASH_KEY_STRING); + if (obj) + { + attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if (attr) + { + proxy_host = axiom_attribute_get_value(attr, env); + } + if (proxy_host) + { + curl_easy_setopt(handler, CURLOPT_PROXY, proxy_host); + } + + attr = NULL; + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_PORT, AXIS2_HASH_KEY_STRING); + if (obj) + { + attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if (attr) + { + proxy_port = axiom_attribute_get_value(attr, env); + } + if (proxy_port) + { + curl_easy_setopt(handler, CURLOPT_PROXYPORT, AXIS2_ATOI(proxy_port)); + } + } + if (uname && passwd) + { + axis2_char_t buffer[256]; + strncpy(buffer, uname, 256); + strncat(buffer, ":", 256); + strncat(buffer, passwd, 256); + curl_easy_setopt(handler, CURLOPT_PROXYUSERPWD, buffer); + } + + return AXIS2_SUCCESS; +} + +/** + * axis2_libcurl_set_ssl_options maps SSL AXIS2/C options to + * libcURL options. + * + * CURLOPT_SSL_VERIFYHOST - long enum whether to verify the server identity + * CURLOPT_SSL_VERIFYPEER - long boolean whether to verify the server certificate + */ +static axis2_status_t +axis2_libcurl_set_ssl_options( + CURL *handler, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axutil_property_t *property = NULL; + axis2_char_t *verify_peer = NULL; + axis2_char_t *verify_host = NULL; + + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_SSL_VERIFY_PEER); + if (property) + { + verify_peer = (axis2_char_t *)axutil_property_get_value(property, env); + } + if (verify_peer) + { + if (0 == axutil_strcasecmp(verify_peer, AXIS2_VALUE_TRUE)) + { + curl_easy_setopt(handler, CURLOPT_SSL_VERIFYPEER, 1); + } + else + { + curl_easy_setopt(handler, CURLOPT_SSL_VERIFYPEER, 0); + } + } + + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_SSL_VERIFY_HOST); + if (property) + { + verify_host = (axis2_char_t *)axutil_property_get_value(property, env); + } + if (verify_host) + { + curl_easy_setopt(handler, CURLOPT_SSL_VERIFYHOST, AXIS2_ATOI(verify_host)); + } + + return AXIS2_SUCCESS; +} + +/** + * axis2_libcurl_set_connection_options maps connection AXIS2/C options to + * libcURL options. + * CURLOPT_CONNECTTIMEOUT_MS - long connection timeout in milliseconds + * CURLOPT_TIMEOUT_MS - long transfer timeout in milliseconds + */ +static axis2_status_t +axis2_libcurl_set_connection_options( + CURL *handler, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axutil_property_t *property = NULL; + long long_property_value = 0; + + /* check if timeout has been set by user using options + * with axis2_options_set_timeout_in_milli_seconds + */ + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_CONNECTION_TIMEOUT); + if (property) + { + axis2_char_t *value = axutil_property_get_value(property, env); + if (value) + { + long_property_value = AXIS2_ATOI(value); + curl_easy_setopt(handler, CURLOPT_CONNECTTIMEOUT_MS, long_property_value); + } + } + + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_SO_TIMEOUT); + if (property) + { + axis2_char_t *value = axutil_property_get_value(property, env); + if (value) + { + long_property_value = AXIS2_ATOI(value); + curl_easy_setopt(handler, CURLOPT_TIMEOUT_MS, long_property_value); + } + } + + return AXIS2_SUCCESS; +} + +/** + * axis2_libcurl_set_options maps the AXIS2/C options to libcURL options. + */ +static axis2_status_t +axis2_libcurl_set_options( + CURL *handler, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + if (axis2_libcurl_set_auth_options(handler, env, msg_ctx) != AXIS2_SUCCESS) + { + return AXIS2_FAILURE; + } + + if (axis2_libcurl_set_proxy_options(handler, env, msg_ctx) != AXIS2_SUCCESS) + { + return AXIS2_FAILURE; + } + + if (axis2_libcurl_set_ssl_options(handler, env, msg_ctx) != AXIS2_SUCCESS) + { + return AXIS2_FAILURE; + } + + if (axis2_libcurl_set_connection_options(handler, env, msg_ctx) != AXIS2_SUCCESS) + { + return AXIS2_FAILURE; + } + + return AXIS2_SUCCESS; +} + + +#endif /* AXIS2_LIBCURL_ENABLED */ + diff --git a/src/core/transport/http/sender/libcurl/axis2_libcurl.h b/src/core/transport/http/sender/libcurl/axis2_libcurl.h new file mode 100644 index 0000000..f2971e5 --- /dev/null +++ b/src/core/transport/http/sender/libcurl/axis2_libcurl.h @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIS2_LIBCURL_H +#define AXIS2_LIBCURL_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* typedef struct axis2_libcurl axis2_libcurl_t; */ +/* actually defined in axis2_http_sender.h as it is part of axis2/include */ + +AXIS2_EXTERN axis2_libcurl_t *AXIS2_CALL +axis2_libcurl_create( + const axutil_env_t * env); + +AXIS2_EXTERN void AXIS2_CALL +axis2_libcurl_free( + axis2_libcurl_t *data, + const axutil_env_t * env); + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_libcurl_send( + axis2_libcurl_t *data, + axiom_output_t * om_output, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axiom_soap_envelope_t * out, + const axis2_char_t * str_url, + const axis2_char_t * soap_action); + +#endif /* AXIS2_LIBCURL_H */ diff --git a/src/core/transport/http/sender/libcurl/libcurl_stream.c b/src/core/transport/http/sender/libcurl/libcurl_stream.c new file mode 100644 index 0000000..0c9126d --- /dev/null +++ b/src/core/transport/http/sender/libcurl/libcurl_stream.c @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef AXIS2_LIBCURL_ENABLED + +#include "libcurl_stream.h" +#include + +typedef struct libcurl_stream_impl +{ + axutil_stream_t stream; + axutil_stream_type_t stream_type; + axis2_char_t *buffer; + int size; + int read_len; +} +libcurl_stream_impl_t; + +#define AXIS2_INTF_TO_IMPL(stream) ((libcurl_stream_impl_t *)(stream)) + +/********************************Function headers******************************/ +axutil_stream_type_t AXIS2_CALL libcurl_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env); + +int AXIS2_CALL libcurl_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count); + +int AXIS2_CALL libcurl_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count); + +int AXIS2_CALL libcurl_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count); + +int AXIS2_CALL libcurl_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env); + +/************************* End of function headers ****************************/ + +/* + * Internal function. Not exposed to outside + */ +AXIS2_EXTERN axutil_stream_t *AXIS2_CALL +axutil_stream_create_libcurl( + const axutil_env_t * env, + axis2_char_t * buffer, + unsigned int size) +{ + libcurl_stream_impl_t *stream_impl = NULL; + + AXIS2_PARAM_CHECK(env->error, buffer, NULL); + + stream_impl = + (libcurl_stream_impl_t *) AXIS2_MALLOC(env->allocator, + sizeof(libcurl_stream_impl_t)); + + if (!stream_impl) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + stream_impl->buffer = buffer; + stream_impl->size = size; + stream_impl->read_len = 0; + stream_impl->stream_type = AXIS2_STREAM_MANAGED; + + axutil_stream_set_read(&(stream_impl->stream), env, libcurl_stream_read); + axutil_stream_set_write(&(stream_impl->stream), env, libcurl_stream_write); + axutil_stream_set_skip(&(stream_impl->stream), env, libcurl_stream_skip); + + return &(stream_impl->stream); +} + +void AXIS2_CALL +libcurl_stream_free( + void * stream, + const axutil_env_t * env) +{ + libcurl_stream_impl_t *stream_impl = NULL; + + stream_impl = AXIS2_INTF_TO_IMPL(stream); + AXIS2_FREE(env->allocator, stream_impl); + + return; +} + +int AXIS2_CALL +libcurl_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count) +{ + libcurl_stream_impl_t *stream_impl = NULL; + int read = 0; + int unread = 0; + + stream_impl = AXIS2_INTF_TO_IMPL(stream); + if (stream_impl->size >= (int)count) + /* We are sure that the difference lies within the int range */ + { + if (buffer && (stream_impl->size > stream_impl->read_len)) + { + unread = (stream_impl->size - stream_impl->read_len); + if (unread > (int)count) + /* We are sure that the difference lies within the int range */ + { + memcpy(buffer, &stream_impl->buffer[stream_impl->read_len], + count); + read = (int)count; + /* We are sure that the difference lies within the int range */ + stream_impl->read_len += read; + } + else + { + memcpy(buffer, &stream_impl->buffer[stream_impl->read_len], + unread); + read = unread; + stream_impl->read_len += read; + } + } + else + read = 0; + } + else + { + if (buffer && (stream_impl->size > stream_impl->read_len)) + { + memcpy(buffer, &stream_impl->buffer[stream_impl->read_len], + stream_impl->size - stream_impl->read_len); + read = stream_impl->size - stream_impl->read_len; + stream_impl->read_len += read; + } + else + read = 0; + } + return read; +} + +int AXIS2_CALL +libcurl_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count) +{ + return (int)count; + /* We are sure that the difference lies within the int range */ +} + +int AXIS2_CALL +libcurl_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count) +{ + return 0; +} + +int AXIS2_CALL +libcurl_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + return 0; +} + +#endif /* AXIS2_LIBCURL_ENABLED */ + diff --git a/src/core/transport/http/sender/libcurl/libcurl_stream.h b/src/core/transport/http/sender/libcurl/libcurl_stream.h new file mode 100644 index 0000000..8a24fcc --- /dev/null +++ b/src/core/transport/http/sender/libcurl/libcurl_stream.h @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBCURL_STREAM_H +#define LIBCURL_STREAM_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** brief Constructor for creating apche2 stream + * @return axutil_stream (libcurl) + */ + AXIS2_EXTERN axutil_stream_t *AXIS2_CALL + axutil_stream_create_libcurl( + const axutil_env_t * env, + axis2_char_t * buffer, + unsigned int size); + + /** @} */ + + void AXIS2_CALL libcurl_stream_free( + void * stream, + const axutil_env_t * env); + + +#ifdef __cplusplus +} +#endif + +#endif /* LIBCURL_STREAM_H */ diff --git a/src/core/transport/http/sender/ssl/Makefile.am b/src/core/transport/http/sender/ssl/Makefile.am new file mode 100644 index 0000000..3e457e5 --- /dev/null +++ b/src/core/transport/http/sender/ssl/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST= ssl_stream.c ssl_stream.h ssl_utils.c ssl_utils.h + diff --git a/src/core/transport/http/sender/ssl/ssl_stream.c b/src/core/transport/http/sender/ssl/ssl_stream.c new file mode 100644 index 0000000..9360f1a --- /dev/null +++ b/src/core/transport/http/sender/ssl/ssl_stream.c @@ -0,0 +1,239 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef AXIS2_SSL_ENABLED + +#include +#include +#include "ssl_stream.h" +#include "ssl_utils.h" + +/** + * @brief Stream struct impl + * Streaming mechanisms for SSL + */ +typedef struct ssl_stream_impl ssl_stream_impl_t; + +struct ssl_stream_impl +{ + axutil_stream_t stream; + axutil_stream_type_t stream_type; + SSL *ssl; + SSL_CTX *ctx; + axis2_socket_t socket; +}; + +#define AXIS2_INTF_TO_IMPL(stream) ((ssl_stream_impl_t *)(stream)) + +void AXIS2_CALL axis2_ssl_stream_free( + axutil_stream_t * stream, + const axutil_env_t * env); + +axutil_stream_type_t AXIS2_CALL axis2_ssl_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env); + +int AXIS2_CALL axis2_ssl_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count); + +int AXIS2_CALL axis2_ssl_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count); + +int AXIS2_CALL axis2_ssl_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count); + +int AXIS2_CALL axis2_ssl_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env); + +AXIS2_EXTERN axutil_stream_t *AXIS2_CALL +axutil_stream_create_ssl( + const axutil_env_t * env, + axis2_socket_t socket, + axis2_char_t * server_cert, + axis2_char_t * key_file, + axis2_char_t * ssl_pp) +{ + ssl_stream_impl_t *stream_impl = NULL; + + stream_impl = + (ssl_stream_impl_t *) AXIS2_MALLOC(env->allocator, + sizeof(ssl_stream_impl_t)); + + if (!stream_impl) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + memset ((void *)stream_impl, 0, sizeof (ssl_stream_impl_t)); + stream_impl->socket = socket; + stream_impl->ctx = NULL; + stream_impl->ssl = NULL; + + stream_impl->ctx = axis2_ssl_utils_initialize_ctx(env, server_cert, + key_file, ssl_pp); + if (!stream_impl->ctx) + { + axis2_ssl_stream_free((axutil_stream_t *) stream_impl, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SSL_ENGINE, AXIS2_FAILURE); + return NULL; + } + stream_impl->ssl = axis2_ssl_utils_initialize_ssl(env, stream_impl->ctx, + stream_impl->socket); + if (!stream_impl->ssl) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SSL_ENGINE, AXIS2_FAILURE); + return NULL; + } + stream_impl->stream_type = AXIS2_STREAM_MANAGED; + + axutil_stream_set_read(&(stream_impl->stream), env, axis2_ssl_stream_read); + axutil_stream_set_write(&(stream_impl->stream), env, + axis2_ssl_stream_write); + axutil_stream_set_skip(&(stream_impl->stream), env, axis2_ssl_stream_skip); + + return &(stream_impl->stream); +} + +void AXIS2_CALL +axis2_ssl_stream_free( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + ssl_stream_impl_t *stream_impl = NULL; + + stream_impl = AXIS2_INTF_TO_IMPL(stream); + axis2_ssl_utils_cleanup_ssl(env, stream_impl->ctx, stream_impl->ssl); + AXIS2_FREE(env->allocator, stream_impl); + + return; +} + +int AXIS2_CALL +axis2_ssl_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count) +{ + ssl_stream_impl_t *stream_impl = NULL; + int read = -1; + int len = -1; + + stream_impl = AXIS2_INTF_TO_IMPL(stream); + + SSL_set_mode(stream_impl->ssl, SSL_MODE_AUTO_RETRY); + + read = SSL_read(stream_impl->ssl, buffer, (int)count); + /* We are sure that the difference lies within the int range */ + switch (SSL_get_error(stream_impl->ssl, read)) + { + case SSL_ERROR_NONE: + len = read; + break; + case SSL_ERROR_ZERO_RETURN: + len = -1; + break; + case SSL_ERROR_SYSCALL: + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "SSL Error: Premature close"); + len = -1; + break; + default: + len = -1; + break; + } + return len; +} + +int AXIS2_CALL +axis2_ssl_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buf, + size_t count) +{ + ssl_stream_impl_t *stream_impl = NULL; + int write = -1; + + AXIS2_PARAM_CHECK(env->error, buf, AXIS2_FAILURE); + stream_impl = AXIS2_INTF_TO_IMPL(stream); + write = SSL_write(stream_impl->ssl, buf, (int)count); + /* We are sure that the difference lies within the int range */ + + switch (SSL_get_error(stream_impl->ssl, write)) + { + case SSL_ERROR_NONE: + if ((int)count != write) + /* We are sure that the difference lies within the int range */ + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Incomplete SSL write!"); + break; + default: + return -1; + } + return write; +} + +int AXIS2_CALL +axis2_ssl_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count) +{ + ssl_stream_impl_t *stream_impl = NULL; + axis2_char_t *tmp_buffer = NULL; + int len = -1; + stream_impl = AXIS2_INTF_TO_IMPL(stream); + + tmp_buffer = AXIS2_MALLOC(env->allocator, count * sizeof(axis2_char_t)); + if (tmp_buffer == NULL) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return -1; + } + len = SSL_read(stream_impl->ssl, tmp_buffer, count); + AXIS2_FREE(env->allocator, tmp_buffer); + return len; + +} + +int AXIS2_CALL +axis2_ssl_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + int ret = -1; + + return ret; +} + +axutil_stream_type_t AXIS2_CALL +axis2_ssl_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + return AXIS2_INTF_TO_IMPL(stream)->stream_type; +} + +#endif + diff --git a/src/core/transport/http/sender/ssl/ssl_stream.h b/src/core/transport/http/sender/ssl/ssl_stream.h new file mode 100644 index 0000000..396da5d --- /dev/null +++ b/src/core/transport/http/sender/ssl/ssl_stream.h @@ -0,0 +1,50 @@ + +/* + * Copyright 2004,2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain count copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIS2_SSL_STREAM_H +#define AXIS2_SSL_STREAM_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** \brief Constructor for creating ssl stream + * @return axutil_stream (ssl) + */ + AXIS2_EXTERN axutil_stream_t *AXIS2_CALL + axutil_stream_create_ssl( + const axutil_env_t * env, + axis2_socket_t socket, + axis2_char_t * server_cert, + axis2_char_t * key_file, + axis2_char_t * ssl_pp); + + /** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* AXIS2_SSL_STREAM_H */ diff --git a/src/core/transport/http/sender/ssl/ssl_utils.c b/src/core/transport/http/sender/ssl/ssl_utils.c new file mode 100644 index 0000000..d565555 --- /dev/null +++ b/src/core/transport/http/sender/ssl/ssl_utils.c @@ -0,0 +1,227 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef AXIS2_SSL_ENABLED + +#include "ssl_utils.h" +#include +BIO *bio_err = 0; + +static int +password_cb( + char *buf, + int size, + int rwflag, + void *passwd) +{ + strncpy(buf, (char *) passwd, size); + buf[size - 1] = '\0'; + return (int)(strlen(buf)); + /* We are sure that the difference lies within the int range */ +} + +AXIS2_EXTERN SSL_CTX *AXIS2_CALL +axis2_ssl_utils_initialize_ctx( + const axutil_env_t * env, + axis2_char_t * server_cert, + axis2_char_t * key_file, + axis2_char_t * ssl_pp) +{ + SSL_METHOD *meth = NULL; + SSL_CTX *ctx = NULL; + axis2_char_t *ca_file = server_cert; + + if (!ca_file) + { + AXIS2_LOG_INFO(env->log, "[ssl client] CA certificate not specified"); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SSL_NO_CA_FILE, AXIS2_FAILURE); + return NULL; + } + + if (!bio_err) + { + /* Global system initialization */ + SSL_library_init(); + SSL_load_error_strings(); + + /* An error write context */ + bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); + } + + /* Create our context */ + meth = SSLv23_method(); + ctx = SSL_CTX_new(meth); + + /* Load our keys and certificates + * If we need client certificates it has to be done here + */ + if (key_file) /*can we check if the server needs client auth? */ + { + if (!ssl_pp) + { + AXIS2_LOG_INFO(env->log, + "[ssl client] No passphrase specified for \ +key file %s and server cert %s", key_file, server_cert); + } + + SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) ssl_pp); + SSL_CTX_set_default_passwd_cb(ctx, password_cb); + + if (!(SSL_CTX_use_certificate_chain_file(ctx, key_file))) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[ssl client] Loading client certificate failed \ +, key file %s", key_file); + SSL_CTX_free(ctx); + return NULL; + } + + if (!(SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM))) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[ssl client] Loading client key failed, key file \ +%s", key_file); + SSL_CTX_free(ctx); + return NULL; + } + } + else + { + AXIS2_LOG_INFO(env->log, + "[ssl client] Client certificate chain file" + "not specified"); + } + + /* Load the CAs we trust */ + if (!(SSL_CTX_load_verify_locations(ctx, ca_file, 0))) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[ssl client] Loading CA certificate failed, \ +ca_file is %s", ca_file); + SSL_CTX_free(ctx); + return NULL; + } + + return ctx; +} + +AXIS2_EXTERN SSL *AXIS2_CALL +axis2_ssl_utils_initialize_ssl( + const axutil_env_t * env, + SSL_CTX * ctx, + axis2_socket_t socket) +{ + SSL *ssl = NULL; + BIO *sbio = NULL; + + AXIS2_PARAM_CHECK(env->error, ctx, NULL); + + ssl = SSL_new(ctx); + if (!ssl) + { + AXIS2_LOG_ERROR (env->log, AXIS2_LOG_SI, + "[ssl]unable to create new ssl context"); + return NULL; + } + + sbio = BIO_new_socket((int)socket, BIO_NOCLOSE); + if (!sbio) + { + AXIS2_LOG_ERROR (env->log, AXIS2_LOG_SI, + "[ssl]unable to create BIO new socket for socket %d", + (int)socket); + return NULL; + } + + SSL_set_bio(ssl, sbio, sbio); + if (SSL_connect(ssl) <= 0) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SSL_ENGINE, AXIS2_FAILURE); + return NULL; + } + + if (SSL_get_verify_result(ssl) != X509_V_OK) + { + char sslerror[128]; /** error buffer must be at least 120 bytes long */ + X509 *peer_cert = NULL; + X509_STORE *cert_store = NULL; + X509_NAME *peer_name = NULL; + X509_OBJECT *client_object = NULL; + X509 *client_cert = NULL; + + peer_cert = SSL_get_peer_certificate(ssl); + if (peer_cert && peer_cert->cert_info) + { + peer_name = (peer_cert->cert_info)->subject; + } + + cert_store = SSL_CTX_get_cert_store(ctx); + if (peer_name && cert_store) + { + client_object = X509_OBJECT_retrieve_by_subject(cert_store->objs, + X509_LU_X509, + peer_name); + } + if (client_object) + { + client_cert = (client_object->data).x509; + if (client_cert && + (M_ASN1_BIT_STRING_cmp(client_cert->signature, + peer_cert->signature) == 0)) + { + if (peer_cert) + { + X509_free(peer_cert); + } + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "[ssl client] SSL certificate verified against peer"); + return ssl; + } + } + if (peer_cert) + { + X509_free(peer_cert); + } + ERR_error_string(SSL_get_verify_result(ssl), sslerror); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[ssl client] SSL certificate verification failed (%s)", + sslerror); + return NULL; + } + + return ssl; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_ssl_utils_cleanup_ssl( + const axutil_env_t * env, + SSL_CTX * ctx, + SSL * ssl) +{ + + if (ssl) + { + SSL_shutdown(ssl); + } + if (ctx) + { + SSL_CTX_free(ctx); + } + return AXIS2_SUCCESS; +} + +#endif + diff --git a/src/core/transport/http/sender/ssl/ssl_utils.h b/src/core/transport/http/sender/ssl/ssl_utils.h new file mode 100644 index 0000000..26dc16b --- /dev/null +++ b/src/core/transport/http/sender/ssl/ssl_utils.h @@ -0,0 +1,56 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIS2_SSL_UTILS_H +#define AXIS2_SSL_UTILS_H + + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + AXIS2_EXTERN SSL_CTX *AXIS2_CALL + axis2_ssl_utils_initialize_ctx( + const axutil_env_t * env, + axis2_char_t * server_cert, + axis2_char_t * key_file, + axis2_char_t * ssl_pp); + + AXIS2_EXTERN SSL *AXIS2_CALL + axis2_ssl_utils_initialize_ssl( + const axutil_env_t * env, + SSL_CTX * ctx, + axis2_socket_t socket); + + AXIS2_EXTERN axis2_status_t AXIS2_CALL + axis2_ssl_utils_cleanup_ssl( + const axutil_env_t * env, + SSL_CTX * ctx, + SSL * ssl); + +#ifdef __cplusplus +} +#endif + +#endif /* AXIS2_SSL_UTILS_H */ -- cgit v1.1-32-gdbae