My squashed commits

This commit is contained in:
Chandra Penke 2011-02-07 23:18:58 +05:30 committed by Marcelo Roberto Jimenez
parent 8eec345e49
commit 20b3fe3c48
10 changed files with 197 additions and 12 deletions

View File

@ -2,6 +2,18 @@
Version 1.8.0
*******************************************************************************
2011-02-07 Chandra Penke <chandrapenke(at)mcntech.com>
Add HTTPS support using OpenSSL. HTTPS support is optional and can
be enabled by passing the --enable-open-ssl argument to the
configure script.
The following methods are introduced to the public API:
UpnpInitOpenSslContext
When enabled, HTTPS can be used by using "https://" instead of
"http://" when passing URLs to the HTTP Client API.
2011-02-07 Chandra Penke <chandrapenke(at)mcntech.com>
Refactor HTTP Client API to be more generic.

View File

@ -324,6 +324,11 @@ if test "x$enable_ipv6" = xyes ; then
AC_DEFINE(UPNP_ENABLE_IPV6, 1, [see upnpconfig.h])
fi
RT_BOOL_ARG_ENABLE([open_ssl], [no], [open-ssl support])
if test "x$enable_open_ssl" = xyes ; then
AC_DEFINE(UPNP_ENABLE_OPEN_SSL, 1, [see upnpconfig.h])
fi
RT_BOOL_ARG_ENABLE([notification_reordering], [yes], [GENA notification reordering in gena_device.c])
if test "x$enable_notification_reordering" = xyes ; then
AC_DEFINE(UPNP_ENABLE_NOTIFICATION_REORDERING, 1, [see upnpconfig.h])

View File

@ -57,6 +57,10 @@
/* Other systems ??? */
#endif
#ifdef UPNP_ENABLE_OPEN_SSL
#include <openssl/ssl.h>
#endif
#define LINE_SIZE 180
#define NAME_SIZE 256
#define MNFT_NAME_SIZE 64
@ -578,6 +582,29 @@ EXPORT_SPEC int UpnpInit2(
unsigned short DestPort);
#endif
/*!
* \brief Initializes the OpenSSL library, and the OpenSSL context for use
* with pupnp
*
* \note This method is only enabled if pupnp is compiled with open-ssl support.
*
* \return An integer representing one of the following:
* \li \c UPNP_E_SUCCESS: The operation completed successfully.
* \li \c UPNP_E_INIT: The SDK is already initialized.
* \li \c UPNP_E_INIT_FAILED: The SDK initialization
* failed for an unknown reason.
*/
#ifdef UPNP_ENABLE_OPEN_SSL
EXPORT_SPEC int UpnpInitSslContext(
/*! If set to 1 initializes the OpenSSL library. Otherwise the application
* is responsible for initializing it. If set to 1, then OpenSSL is intialized
* with all error strings, and all ciphers loaded. */
int initOpenSslLib,
/*! The SSL_METHOD to use to create the context. See OpenSSL docs
* for more info */
const SSL_METHOD *sslMethod);
#endif
/*!
* \brief Terminates the Linux SDK for UPnP Devices.
*

View File

@ -107,5 +107,9 @@
* (i.e. configure --enable-ipv6) */
#undef UPNP_ENABLE_IPV6
/** Defined to 1 if the library has been compiled with OpenSSL support
* (i.e. configure --enable-open_ssl) */
#undef UPNP_ENABLE_OPEN_SSL
#endif /* UPNP_CONFIG_H */

View File

@ -77,6 +77,10 @@
#include <sys/types.h>
#endif
#ifdef UPNP_ENABLE_OPEN_SSL
#include <openssl/ssl.h>
#endif
#ifndef IN6_IS_ADDR_GLOBAL
#define IN6_IS_ADDR_GLOBAL(a) \
(((((__const uint8_t *) (a))[0] & htonl(0xff000000)) <= htonl(0x3f000000) \
@ -177,6 +181,12 @@ int UpnpSdkDeviceregisteredV6 = 0;
/*! Global variable used in discovery notifications. */
Upnp_SID gUpnpSdkNLSuuid;
/*! Global variable used as to store the OpenSSL context object
* to be used for all SSL/TLS connections
*/
#ifdef UPNP_ENABLE_OPEN_SSL
SSL_CTX *gSslCtx = NULL;
#endif
/*!
* \brief (Windows Only) Initializes the Windows Winsock library.
@ -520,6 +530,24 @@ exit_function:
}
#endif
#ifdef UPNP_ENABLE_OPEN_SSL
int UpnpInitSslContext(int initOpenSslLib, const SSL_METHOD *sslMethod)
{
if (gSslCtx)
return UPNP_E_INIT;
if (initOpenSslLib) {
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
}
gSslCtx = SSL_CTX_new(sslMethod);
if (!gSslCtx) {
return UPNP_E_INIT_FAILED;
}
return UPNP_E_SUCCESS;
}
#endif
int UpnpFinish(void)
{
#ifdef INCLUDE_DEVICE_APIS
@ -529,7 +557,12 @@ int UpnpFinish(void)
UpnpClient_Handle client_handle;
#endif
struct Handle_Info *temp;
#ifdef UPNP_ENABLE_OPEN_SSL
if (gSslCtx) {
SSL_CTX_free(gSslCtx);
gSslCtx = NULL;
}
#endif
if (UpnpSdkInit != 1)
return UPNP_E_FINISH;
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,

View File

@ -216,9 +216,18 @@ int http_FixUrl(IN uri_type *url, OUT uri_type *fixed_url)
const char *temp_path = "/";
*fixed_url = *url;
if (token_string_casecmp(&fixed_url->scheme, "http") != 0) {
#ifdef UPNP_ENABLE_OPEN_SSL
if (token_string_casecmp(&fixed_url->scheme, "http") != 0 &&
token_string_casecmp(&fixed_url->scheme, "https") != 0)
{
return UPNP_E_INVALID_URL;
}
#else
if (token_string_casecmp(&fixed_url->scheme, "http") != 0)
{
return UPNP_E_INVALID_URL;
}
#endif
if( fixed_url->hostport.text.size == 0 ) {
return UPNP_E_INVALID_URL;
}
@ -1072,6 +1081,16 @@ int http_OpenHttpConnection(const char *url_str, void **Handle, int timeout)
ret_code = UPNP_E_SOCKET_CONNECT;
goto errorHandler;
}
#ifdef UPNP_ENABLE_OPEN_SSL
/* For HTTPS connections start the TLS/SSL handshake. */
if (token_string_casecmp(&url.scheme, "https") == 0) {
ret_code = sock_ssl_connect(&handle->sock_info);
if (ret_code != UPNP_E_SUCCESS) {
sock_destroy(&handle->sock_info, SD_BOTH);
goto errorHandler;
}
}
#endif
errorHandler:
*Handle = handle;
return ret_code;

View File

@ -52,10 +52,19 @@
#include <time.h>
#include <string.h>
#ifdef UPNP_ENABLE_OPEN_SSL
#include <openssl/ssl.h>
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
#ifdef UPNP_ENABLE_OPEN_SSL
/* OpenSSL context defined in upnpapi.c */
extern SSL_CTX *gSslCtx;
#endif
int sock_init(SOCKINFO *info, SOCKET sockfd)
{
assert(info);
@ -82,11 +91,37 @@ int sock_init_with_ip(SOCKINFO *info, SOCKET sockfd,
return UPNP_E_SUCCESS;
}
#ifdef UPNP_ENABLE_OPEN_SSL
int sock_ssl_connect(SOCKINFO *info)
{
int status = 0;
info->ssl = SSL_new(gSslCtx);
if (!info->ssl) {
return UPNP_E_SOCKET_ERROR;
}
status = SSL_set_fd(info->ssl, info->socket);
if (status == 1) {
status = SSL_connect(info->ssl);
}
if (status == 1) {
return UPNP_E_SUCCESS;
}
return UPNP_E_SOCKET_ERROR;
}
#endif
int sock_destroy(SOCKINFO *info, int ShutdownMethod)
{
int ret = UPNP_E_SUCCESS;
if (info->socket != -1) {
#ifdef UPNP_ENABLE_OPEN_SSL
if (info->ssl) {
SSL_shutdown(info->ssl);
SSL_free(info->ssl);
info->ssl = NULL;
}
#endif
shutdown(info->socket, ShutdownMethod);
if (sock_close(info->socket) == -1) {
ret = UPNP_E_SOCKET_ERROR;
@ -163,16 +198,36 @@ static int sock_read_write(
setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(set));
#endif
if (bRead) {
/* read data. */
numBytes = (long)recv(sockfd, buffer, (size_t)bufsize, MSG_NOSIGNAL);
#ifdef UPNP_ENABLE_OPEN_SSL
if (info->ssl) {
numBytes = (long)SSL_read(info->ssl,
buffer, (size_t)bufsize);
}
else {
#endif
/* read data. */
numBytes = (long)recv(sockfd, buffer, (size_t)bufsize, MSG_NOSIGNAL);
#ifdef UPNP_ENABLE_OPEN_SSL
}
#endif
} else {
byte_left = bufsize;
bytes_sent = 0;
while (byte_left > 0) {
/* write data. */
num_written = send(sockfd,
buffer + bytes_sent, (size_t)byte_left,
MSG_DONTROUTE | MSG_NOSIGNAL);
#ifdef UPNP_ENABLE_OPEN_SSL
if (info->ssl) {
num_written = SSL_write(info->ssl,
buffer + bytes_sent, (size_t)byte_left);
}
else {
#endif
/* write data. */
num_written = send(sockfd,
buffer + bytes_sent, (size_t)byte_left,
MSG_DONTROUTE | MSG_NOSIGNAL);
#ifdef UPNP_ENABLE_OPEN_SSL
}
#endif
if (num_written == -1) {
#ifdef SO_NOSIGPIPE
setsockopt(sockfd, SOL_SOCKET,

View File

@ -312,6 +312,7 @@ int token_cmp(token *in1, token *in2)
int parse_hostport(
const char *in,
size_t max,
int defaultPort,
hostport_type *out)
{
char workbuf[256];
@ -402,9 +403,10 @@ int parse_hostport(
if (port == 0)
/* Bad port number. */
return UPNP_E_INVALID_URL;
} else
} else {
/* Port was not specified, use default port. */
port = 80;
port = defaultPort;
}
/* The length of the host and port string can be calculated by */
/* subtracting pointers. */
hostport_size = (size_t)(c - workbuf);
@ -673,6 +675,7 @@ int parse_uri(const char *in, size_t max, uri_type *out)
int begin_path = 0;
size_t begin_hostport = 0;
size_t begin_fragment = 0;
int defaultPort = 80;
begin_hostport = parse_scheme(in, max, &out->scheme);
if (begin_hostport) {
@ -687,9 +690,13 @@ int parse_uri(const char *in, size_t max, uri_type *out)
in[begin_hostport] == '/' &&
in[begin_hostport + 1] == '/') {
begin_hostport += 2;
if (token_string_casecmp(&out->scheme, "https") == 0) {
defaultPort = 443;
}
begin_path = parse_hostport(&in[begin_hostport],
max - begin_hostport,
&out->hostport);
max - begin_hostport,
defaultPort,
&out->hostport);
if (begin_path >= 0) {
begin_path += (int)begin_hostport;
} else

View File

@ -40,8 +40,12 @@
* \file
*/
#include "upnpconfig.h"
#include "UpnpInet.h" /* for SOCKET, netinet/in */
#include "UpnpGlobal.h" /* for UPNP_INLINE */
#ifdef UPNP_ENABLE_OPEN_SSL
#include <openssl/ssl.h>
#endif
/* The following are not defined under winsock.h */
#ifndef SD_RECEIVE
@ -57,6 +61,9 @@ typedef struct
SOCKET socket;
/*! The following two fields are filled only in incoming requests. */
struct sockaddr_storage foreign_sockaddr;
#ifdef UPNP_ENABLE_OPEN_SSL
SSL *ssl;
#endif
} SOCKINFO;
#ifdef __cplusplus
@ -112,6 +119,20 @@ int sock_init_with_ip(
/*! [in] Remote socket address. */
struct sockaddr *foreign_sockaddr);
/*!
* \brief Associates an SSL object with the socket and begins
* the client-side SSL/TLS handshake.
*
* \return Integer:
* \li \c UPNP_E_SUCCESS
* \li \c UPNP_E_SOCKET_ERROR
*/
#ifdef UPNP_ENABLE_OPEN_SSL
int sock_ssl_connect(
/*! [out] Socket Information Object. */
SOCKINFO* info);
#endif
/*!
* \brief Shutsdown the socket using the ShutdownMethod to indicate whether
* sends and receives on the socket will be dis-allowed.

View File

@ -285,6 +285,8 @@ int parse_hostport(
const char *in,
/*! [in] Sets a maximum limit. */
size_t max,
/*! [in] The default port if the port is not specified. */
int defaultPort,
/*! [out] Output parameter where the host and port are represented as
* an internet address. */
hostport_type *out);