mirror of
https://github.com/lammertb/libhttp.git
synced 2025-08-09 03:22:45 +03:00
168 lines
6.0 KiB
C
168 lines
6.0 KiB
C
/*
|
|
* Copyright (c) 2016 Lammert Bies
|
|
* Copyright (c) 2013-2016 the Civetweb developers
|
|
* Copyright (c) 2004-2013 Sergey Lyubka
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*
|
|
* ============
|
|
* Release: 1.9
|
|
*/
|
|
|
|
#include "httplib_main.h"
|
|
#include "httplib_pthread.h"
|
|
#include "httplib_ssl.h"
|
|
#include "httplib_string.h"
|
|
|
|
static struct httplib_connection * httplib_connect_client_impl( struct httplib_context *ctx, const struct httplib_client_options *client_options, int use_ssl );
|
|
|
|
/*
|
|
* struct httplib_connection *httplib_connect_client_secure( struct httplib_context_*ctx, const struct httplib_client_options *client options, char *error buffer, size_t error_buffer_size );
|
|
*
|
|
* The function httplib_connect_client_secure() creates a secure connection as a
|
|
* client to a remote server and returns a pointer to the connection
|
|
* information, or NULL if an error occured.
|
|
*/
|
|
|
|
LIBHTTP_API struct httplib_connection *httplib_connect_client_secure( struct httplib_context *ctx, const struct httplib_client_options *client_options ) {
|
|
|
|
return httplib_connect_client_impl( ctx, client_options, true );
|
|
|
|
} /* httplib_connect_client_secure */
|
|
|
|
/*
|
|
* struct httplib_connection *httplib_connect_client( struct httplib_context *ctx, const char *host, int port, int use_ssl );
|
|
*
|
|
* The function httplib_connect_client() connects to a remote server as a client
|
|
* with the options of the connection provided as parameters.
|
|
*/
|
|
|
|
struct httplib_connection *httplib_connect_client( struct httplib_context *ctx, const char *host, int port, int use_ssl ) {
|
|
|
|
struct httplib_client_options opts;
|
|
|
|
memset( &opts, 0, sizeof(opts) );
|
|
opts.host = host;
|
|
opts.port = port;
|
|
|
|
return httplib_connect_client_impl( ctx, &opts, use_ssl );
|
|
|
|
} /* httplib_connect_client */
|
|
|
|
|
|
|
|
/*
|
|
* static struct httplib_connection *httplib_connect_client_impl( struct httplib_context *ctx, const struct httplib_client_options *client_options, int use_ssl );
|
|
*
|
|
* The function httplib_connect_client_impl() is the background function doing the
|
|
* heavy lifting to make connections as a client to remote servers.
|
|
*/
|
|
|
|
static struct httplib_connection *httplib_connect_client_impl( struct httplib_context *ctx, const struct httplib_client_options *client_options, int use_ssl ) {
|
|
|
|
struct httplib_connection *conn;
|
|
SOCKET sock;
|
|
union usa sa;
|
|
socklen_t len;
|
|
struct sockaddr *psa;
|
|
char error_string[ERROR_STRING_LEN];
|
|
|
|
if ( ctx == NULL ) return NULL;
|
|
|
|
if ( ! XX_httplib_connect_socket( ctx, client_options->host, client_options->port, use_ssl, &sock, &sa ) ) return NULL;
|
|
|
|
if ( (conn = httplib_calloc( 1, sizeof(*conn) + MAX_REQUEST_SIZE )) == NULL ) {
|
|
|
|
httplib_cry( DEBUG_LEVEL_ERROR, ctx, NULL, "%s: calloc(): %s", __func__, httplib_error_string( ERRNO, error_string, ERROR_STRING_LEN ) );
|
|
closesocket( sock );
|
|
}
|
|
#ifndef NO_SSL
|
|
|
|
else if ( use_ssl && (conn->client_ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL ) {
|
|
|
|
httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s: SSL_CTX_new error", __func__ );
|
|
closesocket( sock );
|
|
conn = httplib_free( conn );
|
|
}
|
|
#endif /* NO_SSL */
|
|
|
|
else {
|
|
|
|
len = (sa.sa.sa_family == AF_INET) ? sizeof(conn->client.rsa.sin) : sizeof(conn->client.rsa.sin6);
|
|
psa = (sa.sa.sa_family == AF_INET) ? (struct sockaddr *)&(conn->client.rsa.sin) : (struct sockaddr *)&(conn->client.rsa.sin6);
|
|
|
|
conn->buf_size = MAX_REQUEST_SIZE;
|
|
conn->buf = (char *)(conn + 1);
|
|
conn->client.sock = sock;
|
|
conn->client.lsa = sa;
|
|
|
|
if ( getsockname( sock, psa, &len ) != 0 ) httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s: getsockname() failed: %s", __func__, httplib_error_string( ERRNO, error_string, ERROR_STRING_LEN ) );
|
|
|
|
conn->client.has_ssl = (use_ssl) ? true : false;
|
|
httplib_pthread_mutex_init( &conn->mutex, &XX_httplib_pthread_mutex_attr );
|
|
|
|
#ifndef NO_SSL
|
|
if ( use_ssl ) {
|
|
|
|
ctx->ssl_ctx = conn->client_ssl_ctx;
|
|
|
|
/*
|
|
* TODO: Check ssl_verify_peer and ssl_ca_path here.
|
|
* SSL_CTX_set_verify call is needed to switch off server
|
|
* certificate checking, which is off by default in OpenSSL and
|
|
* on in yaSSL.
|
|
*
|
|
* TODO: SSL_CTX_set_verify(conn->client_ssl_ctx,
|
|
* SSL_VERIFY_PEER, verify_ssl_server);
|
|
*/
|
|
|
|
if ( client_options->client_cert ) {
|
|
|
|
if ( ! XX_httplib_ssl_use_pem_file( ctx, client_options->client_cert ) ) {
|
|
|
|
httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s: can not use SSL client certificate", __func__ );
|
|
SSL_CTX_free( conn->client_ssl_ctx );
|
|
closesocket( sock );
|
|
conn = httplib_free( conn );
|
|
}
|
|
}
|
|
|
|
if ( client_options->server_cert ) {
|
|
|
|
SSL_CTX_load_verify_locations( conn->client_ssl_ctx, client_options->server_cert, NULL );
|
|
SSL_CTX_set_verify( conn->client_ssl_ctx, SSL_VERIFY_PEER, NULL );
|
|
}
|
|
|
|
else SSL_CTX_set_verify( conn->client_ssl_ctx, SSL_VERIFY_NONE, NULL );
|
|
|
|
if ( ! XX_httplib_sslize( ctx, conn, conn->client_ssl_ctx, SSL_connect ) ) {
|
|
|
|
httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s: SSL connection error", __func__ );
|
|
SSL_CTX_free( conn->client_ssl_ctx );
|
|
closesocket( sock );
|
|
conn = httplib_free( conn );
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return conn;
|
|
|
|
} /* httplib_connect_client_impl */
|