summaryrefslogtreecommitdiffstats
path: root/src/core/transport/http/sender/ssl/ssl_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/transport/http/sender/ssl/ssl_utils.c')
-rw-r--r--src/core/transport/http/sender/ssl/ssl_utils.c227
1 files changed, 227 insertions, 0 deletions
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 <openssl/err.h>
+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
+