Commit fcef9b5d authored by Ian Craggs's avatar Ian Craggs

Merge branch 'develop' into mqttv5

parents b0a1e8a4 0ca079ab
This diff is collapsed.
/*******************************************************************************
* Copyright (c) 2018 Wind River Systems, Inc. All Rights Reserved.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Keith Holman - initial implementation and documentation
*******************************************************************************/
#if !defined(BASE64_H)
#define BASE64_H
/** type for size of a buffer, it saves passing around @p size_t (unsigned long long or unsigned long int) */
typedef unsigned int b64_size_t;
/** type for raw base64 data */
typedef unsigned char b64_data_t;
/**
* Decodes base64 data
*
* @param[out] out decoded data
* @param[in] out_len length of output buffer
* @param[in] in base64 string to decode
* @param[in] in_len length of input buffer
*
* @return the amount of data decoded
*
* @see Base64_decodeLength
* @see Base64_encode
*/
b64_size_t Base64_decode( b64_data_t *out, b64_size_t out_len,
const char *in, b64_size_t in_len );
/**
* Size of buffer required to decode base64 data
*
* @param[in] in base64 string to decode
* @param[in] in_len length of input buffer
*
* @return the size of buffer the decoded string would require
*
* @see Base64_decode
* @see Base64_encodeLength
*/
b64_size_t Base64_decodeLength( const char *in, b64_size_t in_len );
/**
* Encodes base64 data
*
* @param[out] out encode base64 string
* @param[in] out_len length of output buffer
* @param[in] in raw data to encode
* @param[in] in_len length of input buffer
*
* @return the amount of data encoded
*
* @see Base64_decode
* @see Base64_encodeLength
*/
b64_size_t Base64_encode( char *out, b64_size_t out_len,
const b64_data_t *in, b64_size_t in_len );
/**
* Size of buffer required to encode base64 data
*
* @param[in] in raw data to encode
* @param[in] in_len length of input buffer
*
* @return the size of buffer the encoded string would require
*
* @see Base64_decodeLength
* @see Base64_encode
*/
b64_size_t Base64_encodeLength( const b64_data_t *in, b64_size_t in_len );
#endif /* BASE64_H */
......@@ -48,6 +48,9 @@ SET(common_src
Heap.c
LinkedList.c
MQTTProperties.c
Base64.c
SHA1.c
WebSocket.c
)
IF (WIN32)
......@@ -62,7 +65,6 @@ ELSEIF (UNIX)
ENDIF()
ENDIF()
## common compilation for libpaho-mqtt3c and libpaho-mqtt3a
ADD_LIBRARY(common_obj OBJECT ${common_src})
SET_PROPERTY(TARGET common_obj PROPERTY POSITION_INDEPENDENT_CODE ON)
......@@ -165,3 +167,21 @@ IF (PAHO_WITH_SSL)
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
ENDIF()
ENDIF()
# Base64 test
ADD_EXECUTABLE( Base64Test EXCLUDE_FROM_ALL Base64.c Base64.h )
TARGET_COMPILE_DEFINITIONS( Base64Test PUBLIC "-DBASE64_TEST" )
IF (PAHO_WITH_SSL)
ADD_EXECUTABLE( Base64TestOpenSSL EXCLUDE_FROM_ALL Base64.c Base64.h )
TARGET_LINK_LIBRARIES( Base64TestOpenSSL ${OPENSSL_LIB} ${OPENSSLCRYPTO_LIB} )
TARGET_COMPILE_DEFINITIONS( Base64TestOpenSSL PUBLIC "-DBASE64_TEST -DOPENSSL=1" )
ENDIF (PAHO_WITH_SSL)
# SHA1 test
ADD_EXECUTABLE( Sha1Test EXCLUDE_FROM_ALL SHA1.c SHA1.h )
TARGET_COMPILE_DEFINITIONS( Sha1Test PUBLIC "-DSHA1_TEST" )
IF (PAHO_WITH_SSL)
ADD_EXECUTABLE( Sha1TestOpenSSL EXCLUDE_FROM_ALL SHA1.c SHA1.h )
TARGET_LINK_LIBRARIES( Sha1TestOpenSSL ${OPENSSL_LIB} ${OPENSSLCRYPTO_LIB} )
TARGET_COMPILE_DEFINITIONS( Sha1TestOpenSSL PUBLIC "-DSHA1_TEST -DOPENSSL=1" )
ENDIF (PAHO_WITH_SSL)
......@@ -83,8 +83,25 @@ typedef struct
SSL* ssl;
SSL_CTX* ctx;
#endif
int websocket; /**< socket has been upgraded to use web sockets */
char *websocket_key;
} networkHandles;
/* connection states */
/** no connection in progress, see connected value */
#define NOT_IN_PROGRESS 0x0
/** TCP connection in progress */
#define TCP_IN_PROGRESS 0x1
/** SSL connection in progress */
#define SSL_IN_PROGRESS 0x2
/** Websocket connection in progress */
#define WEBSOCKET_IN_PROGRESS 0x3
/** TCP completed, waiting for MQTT ACK */
#define WAIT_FOR_CONNACK 0x4
/** Disconnecting */
#define DISCONNECTING -2
/**
* Data related to one client
*/
......
This diff is collapsed.
This diff is collapsed.
......@@ -32,6 +32,7 @@
#endif
#include "Messages.h"
#include "StackTrace.h"
#include "WebSocket.h"
#include <stdlib.h>
#include <string.h>
......@@ -110,11 +111,7 @@ void* MQTTPacket_Factory(int MQTTVersion, networkHandles* net, int* error)
*error = SOCKET_ERROR; /* indicate whether an error occurred, or not */
/* read the packet data from the socket */
#if defined(OPENSSL)
*error = (net->ssl) ? SSLSocket_getch(net->ssl, net->socket, &header.byte) : Socket_getch(net->socket, &header.byte);
#else
*error = Socket_getch(net->socket, &header.byte);
#endif
*error = WebSocket_getch(net, &header.byte);
if (*error != TCPSOCKET_COMPLETE) /* first byte is the header byte */
goto exit; /* packet not read, *error indicates whether SOCKET_ERROR occurred */
......@@ -123,12 +120,7 @@ void* MQTTPacket_Factory(int MQTTVersion, networkHandles* net, int* error)
goto exit; /* packet not read, *error indicates whether SOCKET_ERROR occurred */
/* now read the rest, the variable header and payload */
#if defined(OPENSSL)
data = (net->ssl) ? SSLSocket_getdata(net->ssl, net->socket, remaining_length, &actual_len) :
Socket_getdata(net->socket, remaining_length, &actual_len);
#else
data = Socket_getdata(net->socket, remaining_length, &actual_len);
#endif
data = WebSocket_getdata(net, remaining_length, &actual_len);
if (data == NULL)
{
*error = SOCKET_ERROR;
......@@ -183,13 +175,17 @@ int MQTTPacket_send(networkHandles* net, Header header, char* buffer, size_t buf
{
int rc;
size_t buf0len;
size_t ws_header;
char *buf;
int count = 0;
FUNC_ENTRY;
buf = malloc(10);
buf[0] = header.byte;
buf0len = 1 + MQTTPacket_encode(&buf[1], buflen);
ws_header = WebSocket_calculateFrameHeaderSize(net, 1, buflen + 10);
buf = malloc(10 + ws_header);
if ( !buf ) return -1;
buf[ws_header] = header.byte;
buf0len = 1 + MQTTPacket_encode(&buf[ws_header + 1], buflen);
if (buffer != NULL)
count = 1;
......@@ -199,18 +195,13 @@ int MQTTPacket_send(networkHandles* net, Header header, char* buffer, size_t buf
{
char* ptraux = buffer;
int msgId = readInt(&ptraux);
rc = MQTTPersistence_put(net->socket, buf, buf0len, count, &buffer, &buflen,
rc = MQTTPersistence_put(net->socket, &buf[ws_header], buf0len, count, &buffer, &buflen,
header.bits.type, msgId, 0);
}
#endif
rc = WebSocket_putdatas(net, &buf[ws_header], buf0len, count, &buffer, &buflen, &freeData);
#if defined(OPENSSL)
if (net->ssl)
rc = SSLSocket_putdatas(net->ssl, net->socket, buf, buf0len, count, &buffer, &buflen, &freeData);
else
#endif
rc = Socket_putdatas(net->socket, buf, buf0len, count, &buffer, &buflen, &freeData);
if (rc == TCPSOCKET_COMPLETE)
time(&(net->lastSent));
......@@ -235,30 +226,31 @@ int MQTTPacket_sends(networkHandles* net, Header header, int count, char** buffe
{
int i, rc;
size_t buf0len, total = 0;
size_t ws_header;
char *buf;
FUNC_ENTRY;
buf = malloc(10);
buf[0] = header.byte;
for (i = 0; i < count; i++)
total += buflens[i];
buf0len = 1 + MQTTPacket_encode(&buf[1], total);
ws_header = WebSocket_calculateFrameHeaderSize(net, 1, total + 10);
buf = malloc(10 + ws_header);
if ( !buf ) return -1;
buf[ws_header] = header.byte;
buf0len = 1 + MQTTPacket_encode(&buf[ws_header + 1], total);
#if !defined(NO_PERSISTENCE)
if (header.bits.type == PUBLISH && header.bits.qos != 0)
{ /* persist PUBLISH QoS1 and Qo2 */
char *ptraux = buffers[2];
int msgId = readInt(&ptraux);
rc = MQTTPersistence_put(net->socket, buf, buf0len, count, buffers, buflens,
rc = MQTTPersistence_put(net->socket, &buf[ws_header], buf0len, count, buffers, buflens,
header.bits.type, msgId, 0);
}
#endif
#if defined(OPENSSL)
if (net->ssl)
rc = SSLSocket_putdatas(net->ssl, net->socket, buf, buf0len, count, buffers, buflens, frees);
else
#endif
rc = Socket_putdatas(net->socket, buf, buf0len, count, buffers, buflens, frees);
rc = WebSocket_putdatas(net, &buf[ws_header], buf0len, count, buffers, buflens, frees);
if (rc == TCPSOCKET_COMPLETE)
time(&(net->lastSent));
......@@ -317,11 +309,7 @@ int MQTTPacket_decode(networkHandles* net, size_t* value)
rc = SOCKET_ERROR; /* bad data */
goto exit;
}
#if defined(OPENSSL)
rc = (net->ssl) ? SSLSocket_getch(net->ssl, net->socket, &c) : Socket_getch(net->socket, &c);
#else
rc = Socket_getch(net->socket, &c);
#endif
rc = WebSocket_getch(net, &c);
if (rc != TCPSOCKET_COMPLETE)
goto exit;
*value += (c & 127) * multiplier;
......
......@@ -224,13 +224,14 @@ Publications* MQTTProtocol_storePublication(Publish* publish, int* len)
p->refcount = 1;
*len = (int)strlen(publish->topic)+1;
p->topic = malloc(*len);
strcpy(p->topic, publish->topic);
if (Heap_findItem(publish->topic))
p->topic = publish->topic;
else
{
p->topic = malloc(*len);
strcpy(p->topic, publish->topic);
free(publish->topic);
publish->topic = NULL;
}
*len += sizeof(Publications);
p->topiclen = publish->topiclen;
......@@ -321,8 +322,19 @@ int MQTTProtocol_handlePublishes(void* pack, int sock)
rc = MQTTPacket_send_pubrec(publish->msgId, &client->net, client->clientID);
if (m->MQTTVersion >= MQTTVERSION_5 && already_received == 0)
{
publish->payload = m->publish->payload;
Protocol_processPublication(publish, client);
Publish publish;
publish.header.bits.qos = m->qos;
publish.header.bits.retain = m->retain;
publish.msgId = m->msgid;
publish.topic = m->publish->topic;
publish.topiclen = m->publish->topiclen;
publish.payload = m->publish->payload;
publish.payloadlen = m->publish->payloadlen;
publish.MQTTVersion = m->MQTTVersion;
publish.properties = m->properties;
Protocol_processPublication(&publish, client);
}
publish->topic = NULL;
}
......
......@@ -36,6 +36,7 @@
#include "MQTTProtocolOut.h"
#include "StackTrace.h"
#include "Heap.h"
#include "WebSocket.h"
extern ClientStates* bstate;
......@@ -43,11 +44,12 @@ extern ClientStates* bstate;
/**
* Separates an address:port into two separate values
* @param uri the input string - hostname:port
* @param port the returned port integer
* @param[in] uri the input string - hostname:port
* @param[out] port the returned port integer
* @param[out] topic optional topic portion of the address starting with '/'
* @return the address string
*/
char* MQTTProtocol_addressPort(const char* uri, int* port)
size_t MQTTProtocol_addressPort(const char* uri, int* port, const char **topic)
{
char* colon_pos = strrchr(uri, ':'); /* reverse find to allow for ':' in IPv6 addresses */
char* buf = (char*)uri;
......@@ -62,27 +64,31 @@ char* MQTTProtocol_addressPort(const char* uri, int* port)
if (colon_pos) /* have to strip off the port */
{
size_t addr_len = colon_pos - uri;
buf = malloc(addr_len + 1);
len = colon_pos - uri;
*port = atoi(colon_pos + 1);
MQTTStrncpy(buf, uri, addr_len+1);
}
else
{
len = strlen(buf);
*port = DEFAULT_PORT;
}
/* try and find topic portion */
if ( topic )
{
const char* addr_start = uri;
if ( colon_pos )
addr_start = colon_pos;
*topic = strchr( addr_start, '/' );
}
len = strlen(buf);
if (buf[len - 1] == ']')
{
if (buf == (char*)uri)
{
buf = malloc(len); /* we are stripping off the final ], so length is 1 shorter */
MQTTStrncpy(buf, uri, len);
}
else
buf[len - 1] = '\0';
/* we are stripping off the final ], so length is 1 shorter */
--len;
}
FUNC_EXIT;
return buf;
return len;
}
......@@ -95,51 +101,54 @@ char* MQTTProtocol_addressPort(const char* uri, int* port)
* @return return code
*/
#if defined(OPENSSL)
int MQTTProtocol_connect(const char* ip_address, Clients* aClient, int ssl, int MQTTVersion,
int MQTTProtocol_connect(const char* ip_address, Clients* aClient, int ssl, int websocket, int MQTTVersion,
MQTTProperties* connectProperties, MQTTProperties* willProperties)
#else
int MQTTProtocol_connect(const char* ip_address, Clients* aClient, int MQTTVersion,
int MQTTProtocol_connect(const char* ip_address, Clients* aClient, int websocket, int MQTTVersion,
MQTTProperties* connectProperties, MQTTProperties* willProperties)
#endif
{
int rc, port;
char* addr;
size_t addr_len;
FUNC_ENTRY;
aClient->good = 1;
addr = MQTTProtocol_addressPort(ip_address, &port);
rc = Socket_new(addr, port, &(aClient->net.socket));
addr_len = MQTTProtocol_addressPort(ip_address, &port, NULL);
rc = Socket_new(ip_address, addr_len, port, &(aClient->net.socket));
if (rc == EINPROGRESS || rc == EWOULDBLOCK)
aClient->connect_state = 1; /* TCP connect called - wait for connect completion */
aClient->connect_state = TCP_IN_PROGRESS; /* TCP connect called - wait for connect completion */
else if (rc == 0)
{ /* TCP connect completed. If SSL, send SSL connect */
#if defined(OPENSSL)
if (ssl)
{
if (SSLSocket_setSocketForSSL(&aClient->net, aClient->sslopts, addr) == 1)
if (SSLSocket_setSocketForSSL(&aClient->net, aClient->sslopts, ip_address, addr_len) == 1)
{
rc = SSLSocket_connect(aClient->net.ssl, aClient->net.socket,
addr, aClient->sslopts->verify);
ip_address, aClient->sslopts->verify);
if (rc == TCPSOCKET_INTERRUPTED)
aClient->connect_state = 2; /* SSL connect called - wait for completion */
aClient->connect_state = SSL_IN_PROGRESS; /* SSL connect called - wait for completion */
}
else
rc = SOCKET_ERROR;
}
#endif
if ( websocket )
{
rc = WebSocket_connect( &aClient->net, ip_address );
if ( rc == TCPSOCKET_INTERRUPTED )
aClient->connect_state = WEBSOCKET_IN_PROGRESS; /* Websocket connect called - wait for completion */
}
if (rc == 0)
{
/* Now send the MQTT connect packet */
if ((rc = MQTTPacket_send_connect(aClient, MQTTVersion, connectProperties, willProperties)) == 0)
aClient->connect_state = 3; /* MQTT Connect sent - wait for CONNACK */
aClient->connect_state = WAIT_FOR_CONNACK; /* MQTT Connect sent - wait for CONNACK */
else
aClient->connect_state = 0;
aClient->connect_state = NOT_IN_PROGRESS;
}
}
if (addr != ip_address)
free(addr);
FUNC_EXIT_RC(rc);
return rc;
......
......@@ -31,13 +31,13 @@
#define DEFAULT_PORT 1883
char* MQTTProtocol_addressPort(const char* uri, int* port);
size_t MQTTProtocol_addressPort(const char* uri, int* port, const char **topic);
void MQTTProtocol_reconnect(const char* ip_address, Clients* client);
#if defined(OPENSSL)
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int ssl, int MQTTVersion,
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int ssl, int websocket, int MQTTVersion,
MQTTProperties* connectProperties, MQTTProperties* willProperties);
#else
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int MQTTVersion,
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int websocket, int MQTTVersion,
MQTTProperties* connectProperties, MQTTProperties* willProperties);
#endif
int MQTTProtocol_handlePingresps(void* pack, int sock);
......
......@@ -60,7 +60,7 @@
char* FindString(char* filename, const char* eyecatcher_input);
int printVersionInfo(MQTTAsync_nameValue* info);
int loadandcall(char* libname);
int loadandcall(const char* libname);
void printEyecatchers(char* filename);
......@@ -133,16 +133,14 @@ int printVersionInfo(MQTTAsync_nameValue* info)
typedef MQTTAsync_nameValue* (*func_type)(void);
int loadandcall(char* libname)
int loadandcall(const char* libname)
{
int rc = 0;
MQTTAsync_nameValue* (*func_address)(void) = NULL;
#if defined(WIN32) || defined(WIN64)
wchar_t wlibname[30];
HMODULE APILibrary;
mbstowcs(wlibname, libname, strlen(libname) + 1);
if ((APILibrary = LoadLibrary(wlibname)) == NULL)
if ((APILibrary = LoadLibraryA(libname)) == NULL)
printf("Error loading library %s, error code %d\n", libname, GetLastError());
else
{
......
/*******************************************************************************
* Copyright (c) 2018 Wind River Systems, Inc. All Rights Reserved.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Keith Holman - initial implementation and documentation
*******************************************************************************/
#include "SHA1.h"
#if !defined(OPENSSL)
#if defined(WIN32) || defined(WIN64)
#pragma comment(lib, "crypt32.lib")
int SHA1_Init(SHA_CTX *c)
{
if (!CryptAcquireContext(&c->hProv, NULL, NULL,
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
return 0;
if (!CryptCreateHash(c->hProv, CALG_SHA1, 0, 0, &c->hHash))
{
CryptReleaseContext(c->hProv, 0);
return 0;
}
return 1;
}
int SHA1_Update(SHA_CTX *c, const void *data, size_t len)
{
int rv = 1;
if (!CryptHashData(c->hHash, data, len, 0))
rv = 0;
return rv;
}
int SHA1_Final(unsigned char *md, SHA_CTX *c)
{
int rv = 0;
DWORD md_len = SHA1_DIGEST_LENGTH;
if (CryptGetHashParam(c->hHash, HP_HASHVAL, md, &md_len, 0))
rv = 1;
CryptDestroyHash(c->hHash);
CryptReleaseContext(c->hProv, 0);
return rv;
}
#else /* if defined(WIN32) || defined(WIN64) */
#if defined(__linux__)
# include <endian.h>
#elif defined(__APPLE__)
# include <libkern/OSByteOrder.h>
# define htobe32(x) OSSwapHostToBigInt32(x)
# define be32toh(x) OSSwapBigToHostInt32(x)
#elif defined(__FreeBSD__) || defined(__NetBSD__)
# include <sys/endian.h>
#endif
#include <string.h>
static unsigned char pad[64] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int SHA1_Init(SHA_CTX *ctx)
{
int ret = 0;
if ( ctx )
{
ctx->h[0] = 0x67452301;
ctx->h[1] = 0xEFCDAB89;
ctx->h[2] = 0x98BADCFE;
ctx->h[3] = 0x10325476;
ctx->h[4] = 0xC3D2E1F0;
ctx->size = 0u;
ctx->total = 0u;
ret = 1;
}
return ret;
}
#define ROTATE_LEFT32(a, n) (((a) << (n)) | ((a) >> (32 - (n))))
static void SHA1_ProcessBlock(SHA_CTX *ctx)
{
uint32_t blks[5];
uint32_t *w;
int i;
/* initialize */
for ( i = 0; i < 5; ++i )
blks[i] = ctx->h[i];
w = ctx->w;
/* perform SHA-1 hash */
for ( i = 0; i < 16; ++i )
w[i] = be32toh(w[i]);
for( i = 0; i < 80; ++i )
{
int tmp;
if ( i >= 16 )
w[i & 0x0F] = ROTATE_LEFT32( w[(i+13) & 0x0F] ^ w[(i+8) & 0x0F] ^ w[(i+2) & 0x0F] ^ w[i & 0x0F], 1 );
if ( i < 20 )
tmp = ROTATE_LEFT32(blks[0], 5) + ((blks[1] & blks[2]) | (~(blks[1]) & blks[3])) + blks[4] + w[i & 0x0F] + 0x5A827999;
else if ( i < 40 )
tmp = ROTATE_LEFT32(blks[0], 5) + (blks[1]^blks[2]^blks[3]) + blks[4] + w[i & 0x0F] + 0x6ED9EBA1;
else if ( i < 60 )
tmp = ROTATE_LEFT32(blks[0], 5) + ((blks[1] & blks[2]) | (blks[1] & blks[3]) | (blks[2] & blks[3])) + blks[4] + w[i & 0x0F] + 0x8F1BBCDC;
else
tmp = ROTATE_LEFT32(blks[0], 5) + (blks[1]^blks[2]^blks[3]) + blks[4] + w[i & 0x0F] + 0xCA62C1D6;
/* update registers */
blks[4] = blks[3];
blks[3] = blks[2];
blks[2] = ROTATE_LEFT32(blks[1], 30);
blks[1] = blks[0];
blks[0] = tmp;
}
/* update of hash */
for ( i = 0; i < 5; ++i )
ctx->h[i] += blks[i];
}
int SHA1_Final(unsigned char *md, SHA_CTX *ctx)
{
int i;
int ret = 0;
size_t pad_amount;
uint64_t total;
/* length before pad */
total = ctx->total * 8;
if ( ctx->size < 56 )
pad_amount = 56 - ctx->size;
else
pad_amount = 64 + 56 - ctx->size;
SHA1_Update(ctx, pad, pad_amount);
ctx->w[14] = htobe32((uint32_t)(total >> 32));
ctx->w[15] = htobe32((uint32_t)total);
SHA1_ProcessBlock(ctx);
for ( i = 0; i < 5; ++i )
ctx->h[i] = htobe32(ctx->h[i]);
if ( md )
{
memcpy( md, &ctx->h[0], SHA1_DIGEST_LENGTH );
ret = 1;
}
return ret;
}
int SHA1_Update(SHA_CTX *ctx, const void *data, size_t len)
{
while ( len > 0 )
{
unsigned int n = 64 - ctx->size;
if ( len < n )
n = len;
memcpy(ctx->buffer + ctx->size, data, n);
ctx->size += n;
ctx->total += n;
data = (uint8_t *)data + n;
len -= n;
if ( ctx->size == 64 )
{
SHA1_ProcessBlock(ctx);
ctx->size = 0;
}
}
return 1;
}
#endif /* else if defined(WIN32) || defined(WIN64) */
#endif /* elif !defined(OPENSSL) */
#if defined(SHA1_TEST)
#include <stdio.h>
#include <string.h>
#define TEST_EXPECT(i,x) if (!(x)) {fprintf( stderr, "failed test: %s (for i == %d)\n", #x, i ); ++fails;}
int main(int argc, char *argv[])
{
struct _td
{
const char *in;
const char *out;
};
int i;
unsigned int fails = 0u;
struct _td test_data[] = {
{ "", "da39a3ee5e6b4b0d3255bfef95601890afd80709" },
{ "this string", "fda4e74bc7489a18b146abdf23346d166663dab8" },
{ NULL, NULL }
};
/* only 1 update */
i = 0;
while ( test_data[i].in != NULL )
{
int r[3] = { 1, 1, 1 };
unsigned char sha_out[SHA1_DIGEST_LENGTH];
char out[SHA1_DIGEST_LENGTH * 2 + 1];
SHA_CTX c;
int j;
r[0] = SHA1_Init( &c );
r[1] = SHA1_Update( &c, test_data[i].in, strlen(test_data[i].in));
r[2] = SHA1_Final( sha_out, &c );
for ( j = 0u; j < SHA1_DIGEST_LENGTH; ++j )
snprintf( &out[j*2], 3u, "%02x", sha_out[j] );
out[SHA1_DIGEST_LENGTH * 2] = '\0';
TEST_EXPECT( i, r[0] == 1 && r[1] == 1 && r[2] == 1 && strncmp(out, test_data[i].out, strlen(test_data[i].out)) == 0 );
++i;
}
if ( fails )
printf( "%u test failed!\n", fails );
else
printf( "all tests passed\n" );
return fails;
}
#endif /* if defined(SHA1_TEST) */
/*******************************************************************************
* Copyright (c) 2018 Wind River Systems, Inc. All Rights Reserved.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Keith Holman - initial implementation and documentation
*******************************************************************************/
#if !defined(SHA1_H)
#define SHA1_H
#if defined(OPENSSL)
#include <openssl/sha.h>
/** SHA-1 Digest Length */
#define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
#else /* if defined(OPENSSL) */
#if defined(WIN32) || defined(WIN64)
#include <Windows.h>
#include <WinCrypt.h>
typedef struct SHA_CTX_S
{
HCRYPTPROV hProv;
HCRYPTHASH hHash;
} SHA_CTX;
#else /* if defined(WIN32) || defined(WIN64) */
#include <stdint.h>
typedef struct SHA_CTX_S {
uint32_t h[5];
union {
uint32_t w[16];
uint8_t buffer[64];
};
unsigned int size;
unsigned int total;
} SHA_CTX;
#endif /* else if defined(WIN32) || defined(WIN64) */
#include <stddef.h>
/** SHA-1 Digest Length (number of bytes in SHA1) */
#define SHA1_DIGEST_LENGTH (160/8)
/**
* Initializes the SHA1 hashing algorithm
*
* @param[in,out] ctx hashing context structure
*
* @see SHA1_Update
* @see SHA1_Final
*/
int SHA1_Init(SHA_CTX *ctx);
/**
* Updates a block to the SHA1 hash
*
* @param[in,out] ctx hashing context structure
* @param[in] data block of data to hash
* @param[in] len length of block to hash
*
* @see SHA1_Init
* @see SHA1_Final
*/
int SHA1_Update(SHA_CTX *ctx, const void *data, size_t len);
/**
* Produce final SHA1 hash
*
* @param[out] md SHA1 hash produced (must be atleast
* @p SHA1_DIGEST_LENGTH in length)
* @param[in,out] ctx hashing context structure
*
* @see SHA1_Init
* @see SHA1_Final
*/
int SHA1_Final(unsigned char *md, SHA_CTX *ctx);
#endif /* if defined(OPENSSL) */
#endif /* SHA1_H */
......@@ -30,11 +30,11 @@
#include "SocketBuffer.h"
#include "MQTTClient.h"
#include "MQTTProtocolOut.h"
#include "SSLSocket.h"
#include "Log.h"
#include "StackTrace.h"
#include "Socket.h"
char* MQTTProtocol_addressPort(const char* uri, int* port);
#include "Heap.h"
......@@ -620,7 +620,8 @@ exit:
}
int SSLSocket_setSocketForSSL(networkHandles* net, MQTTClient_SSLOptions* opts, char* hostname)
int SSLSocket_setSocketForSSL(networkHandles* net, MQTTClient_SSLOptions* opts,
const char* hostname, size_t hostname_len)
{
int rc = 1;
......@@ -628,6 +629,7 @@ int SSLSocket_setSocketForSSL(networkHandles* net, MQTTClient_SSLOptions* opts,
if (net->ctx != NULL || (rc = SSLSocket_createContext(net, opts)) == 1)
{
char *hostname_plus_null;
int i;
SSL_CTX_set_info_callback(net->ctx, SSL_CTX_info_callback);
......@@ -648,8 +650,11 @@ int SSLSocket_setSocketForSSL(networkHandles* net, MQTTClient_SSLOptions* opts,
if ((rc = SSL_set_fd(net->ssl, net->socket)) != 1)
SSLSocket_error("SSL_set_fd", net->ssl, net->socket, rc);
if ((rc = SSL_set_tlsext_host_name(net->ssl, hostname)) != 1)
hostname_plus_null = malloc(hostname_len + 1u );
MQTTStrncpy(hostname_plus_null, hostname, hostname_len + 1u);
if ((rc = SSL_set_tlsext_host_name(net->ssl, hostname_plus_null)) != 1)
SSLSocket_error("SSL_set_tlsext_host_name", NULL, net->socket, rc);
free(hostname_plus_null);
}
FUNC_EXIT_RC(rc);
......@@ -659,7 +664,7 @@ int SSLSocket_setSocketForSSL(networkHandles* net, MQTTClient_SSLOptions* opts,
/*
* Return value: 1 - success, TCPSOCKET_INTERRUPTED - try again, anything else is failure
*/
int SSLSocket_connect(SSL* ssl, int sock, char* hostname, int verify)
int SSLSocket_connect(SSL* ssl, int sock, const char* hostname, int verify)
{
int rc = 0;
......@@ -680,21 +685,24 @@ int SSLSocket_connect(SSL* ssl, int sock, char* hostname, int verify)
{
char* peername = NULL;
int port;
char* addr = NULL;
size_t hostname_len;
X509* cert = SSL_get_peer_certificate(ssl);
addr = MQTTProtocol_addressPort(hostname, &port);
hostname_len = MQTTProtocol_addressPort(hostname, &port, NULL);
rc = X509_check_host(cert, addr, strlen(addr), 0, &peername);
if (rc == 0)
rc = SOCKET_ERROR;
rc = X509_check_host(cert, hostname, hostname_len, 0, &peername);
Log(TRACE_MIN, -1, "rc from X509_check_host is %d", rc);
Log(TRACE_MIN, -1, "peername from X509_check_host is %s", peername);
if (peername != NULL)
OPENSSL_free(peername);
// 0 == fail, -1 == SSL internal error
if (rc == 0 || rc == -1)
rc = SSL_FATAL;
if (cert)
X509_free(cert);
if (addr != hostname)
free(addr);
}
#endif
......
......@@ -37,14 +37,14 @@ void SSLSocket_handleOpensslInit(int bool_value);
int SSLSocket_initialize(void);
void SSLSocket_terminate(void);
int SSLSocket_setSocketForSSL(networkHandles* net, MQTTClient_SSLOptions* opts, char* hostname);
int SSLSocket_setSocketForSSL(networkHandles* net, MQTTClient_SSLOptions* opts, const char* hostname, size_t hostname_len);
int SSLSocket_getch(SSL* ssl, int socket, char* c);
char *SSLSocket_getdata(SSL* ssl, int socket, size_t bytes, size_t* actual_len);
int SSLSocket_close(networkHandles* net);
int SSLSocket_putdatas(SSL* ssl, int socket, char* buf0, size_t buf0len, int count, char** buffers, size_t* buflens, int* frees);
int SSLSocket_connect(SSL* ssl, int sock, char* hostname, int verify);
int SSLSocket_connect(SSL* ssl, int sock, const char* hostname, int verify);
int SSLSocket_getPendingRead(void);
int SSLSocket_continueWrite(pending_writes* pw);
......
......@@ -650,9 +650,10 @@ void Socket_close(int socket)
* @param sock returns the new socket
* @return completion code
*/
int Socket_new(char* addr, int port, int* sock)
int Socket_new(const char* addr, size_t addr_len, int port, int* sock)
{
int type = SOCK_STREAM;
char *addr_mem;
struct sockaddr_in address;
#if defined(AF_INET6)
struct sockaddr_in6 address6;
......@@ -671,9 +672,16 @@ int Socket_new(char* addr, int port, int* sock)
memset(&address6, '\0', sizeof(address6));
if (addr[0] == '[')
++addr;
{
++addr;
--addr_len;
}
addr_mem = malloc( addr_len + 1u );
memcpy( addr_mem, addr, addr_len );
addr_mem[addr_len] = '\0';
if ((rc = getaddrinfo(addr, NULL, &hints, &result)) == 0)
if ((rc = getaddrinfo(addr_mem, NULL, &hints, &result)) == 0)
{
struct addrinfo* res = result;
......@@ -708,10 +716,10 @@ int Socket_new(char* addr, int port, int* sock)
freeaddrinfo(result);
}
else
Log(LOG_ERROR, -1, "getaddrinfo failed for addr %s with rc %d", addr, rc);
Log(LOG_ERROR, -1, "getaddrinfo failed for addr %s with rc %d", addr_mem, rc);
if (rc != 0)
Log(LOG_ERROR, -1, "%s is not a valid IP address", addr);
Log(LOG_ERROR, -1, "%s is not a valid IP address", addr_mem);
else
{
*sock = (int)socket(family, type, 0);
......@@ -771,6 +779,10 @@ int Socket_new(char* addr, int port, int* sock)
}
}
}
if (addr_mem)
free(addr_mem);
FUNC_EXIT_RC(rc);
return rc;
}
......
......@@ -131,7 +131,7 @@ int Socket_getch(int socket, char* c);
char *Socket_getdata(int socket, size_t bytes, size_t* actual_len);
int Socket_putdatas(int socket, char* buf0, size_t buf0len, int count, char** buffers, size_t* buflens, int* frees);
void Socket_close(int socket);
int Socket_new(char* addr, int port, int* socket);
int Socket_new(const char* addr, size_t addr_len, int port, int* socket);
int Socket_noPendingWrites(int socket);
char* Socket_getpeer(int sock);
......
/*******************************************************************************
* Copyright (c) 2009, 2017 IBM Corp.
* Copyright (c) 2009, 2018 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
......@@ -16,6 +16,7 @@
* Ian Craggs - bug #415042 - start Linux thread as disconnected
* Ian Craggs - fix for bug #420851
* Ian Craggs - change MacOS semaphore implementation
* Ian Craggs - fix for clock #284
*******************************************************************************/
/**
......@@ -247,6 +248,9 @@ int Thread_wait_sem(sem_type sem, int timeout)
usleep(interval); /* microseconds - .1 of a second */
}
#else
/* We have to use CLOCK_REALTIME rather than MONOTONIC for sem_timedwait interval.
* Does this make it susceptible to system clock changes?
*/
if (clock_gettime(CLOCK_REALTIME, &ts) != -1)
{
ts.tv_sec += timeout;
......@@ -333,11 +337,17 @@ int Thread_destroy_sem(sem_type sem)
cond_type Thread_create_cond(void)
{
cond_type condvar = NULL;
pthread_condattr_t attr;
int rc = 0;
FUNC_ENTRY;
pthread_condattr_init(&attr);
#if !defined(OSX)
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
#endif
condvar = malloc(sizeof(cond_type_struct));
rc = pthread_cond_init(&condvar->cond, NULL);
rc = pthread_cond_init(&condvar->cond, &attr);
rc = pthread_mutex_init(&condvar->mutex, NULL);
FUNC_EXIT_RC(rc);
......@@ -368,13 +378,14 @@ int Thread_wait_cond(cond_type condvar, int timeout)
FUNC_ENTRY;
int rc = 0;
struct timespec cond_timeout;
struct timeval cur_time;
gettimeofday(&cur_time, NULL);
cond_timeout.tv_sec = cur_time.tv_sec + timeout;
cond_timeout.tv_nsec = cur_time.tv_usec * 1000;
#if defined(OSX)
clock_gettime(CLOCK_REALTIME, &cond_timeout);
#else
clock_gettime(CLOCK_MONOTONIC, &cond_timeout);
#endif
cond_timeout.tv_sec += timeout;
pthread_mutex_lock(&condvar->mutex);
rc = pthread_cond_timedwait(&condvar->cond, &condvar->mutex, &cond_timeout);
pthread_mutex_unlock(&condvar->mutex);
......
This diff is collapsed.
/*******************************************************************************
* Copyright (c) 2018 Wind River Systems, Inc. All Rights Reserved.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Keith Holman - initial implementation and documentation
*******************************************************************************/
#if !defined(WEBSOCKET_H)
#define WEBSOCKET_H
#include "Clients.h"
/**
* WebSocket op codes
* @{
*/
#define WebSocket_OP_CONTINUE 0x0 /* 0000 - continue frame */
#define WebSocket_OP_TEXT 0x1 /* 0001 - text frame */
#define WebSocket_OP_BINARY 0x2 /* 0010 - binary frame */
#define WebSocket_OP_CLOSE 0x8 /* 1000 - close frame */
#define WebSocket_OP_PING 0x9 /* 1001 - ping frame */
#define WebSocket_OP_PONG 0xA /* 1010 - pong frame */
/** @} */
/**
* Various close status codes
* @{
*/
#define WebSocket_CLOSE_NORMAL 1000
#define WebSocket_CLOSE_GOING_AWAY 1001
#define WebSocket_CLOSE_PROTOCOL_ERROR 1002
#define WebSocket_CLOSE_UNKNOWN_DATA 1003
#define WebSocket_CLOSE_RESERVED 1004
#define WebSocket_CLOSE_NO_STATUS_CODE 1005 /* reserved: not to be used */
#define WebSocket_CLOSE_ABNORMAL 1006 /* reserved: not to be used */
#define WebSocket_CLOSE_BAD_DATA 1007
#define WebSocket_CLOSE_POLICY 1008
#define WebSocket_CLOSE_MSG_TOO_BIG 1009
#define WebSocket_CLOSE_NO_EXTENSION 1010
#define WebScoket_CLOSE_UNEXPECTED 1011
#define WebSocket_CLOSE_TLS_FAIL 1015 /* reserved: not be used */
/** @} */
/* closes a websocket connection */
void WebSocket_close(networkHandles *net, int status_code, const char *reason);
/* sends upgrade request */
int WebSocket_connect(networkHandles *net, const char *uri);
/* calculates the extra data required in a packet to hold a WebSocket frame header */
size_t WebSocket_calculateFrameHeaderSize(networkHandles *net, int mask_data,
size_t data_len);
/* obtain data from network socket */
int WebSocket_getch(networkHandles *net, char* c);
char *WebSocket_getdata(networkHandles *net, size_t bytes, size_t* actual_len);
/* send data out, in websocket format only if required */
int WebSocket_putdatas(networkHandles* net, char* buf0, size_t buf0len,
int count, char** buffers, size_t* buflens, int* freeData);
/* releases any resources used by the websocket system */
void WebSocket_terminate(void);
/* handles websocket upgrade request */
int WebSocket_upgrade(networkHandles *net);
#endif /* WEBSOCKET_H */
......@@ -106,7 +106,7 @@ void onConnect(void* context, MQTTAsync_successData* response)
opts.context = client;
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = strlen(PAYLOAD);
pubmsg.payloadlen = (int)strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
deliveredtoken = 0;
......
......@@ -45,7 +45,7 @@ int main(int argc, char* argv[])
exit(EXIT_FAILURE);
}
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = strlen(PAYLOAD);
pubmsg.payloadlen = (int)strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
......
......@@ -547,7 +547,7 @@ int test2(struct Options options)
opts.MQTTVersion = options.MQTTVersion;
opts.username = "testuser";
opts.binarypwd.data = "testpassword";
opts.binarypwd.len = strlen(opts.binarypwd.data);
opts.binarypwd.len = (int)strlen(opts.binarypwd.data);
if (options.haconnections != NULL)
{
opts.serverURIs = options.haconnections;
......@@ -1068,7 +1068,7 @@ int test6a(struct Options options)
opts.MQTTVersion = MQTTVERSION_3_1_1;
opts.will = &wopts;
opts.will->payload.data = test6_will_message;
opts.will->payload.len = strlen(test6_will_message) + 1;
opts.will->payload.len = (int)strlen(test6_will_message) + 1;
opts.will->qos = 1;
opts.will->retained = 0;
opts.will->topicName = test6_will_topic;
......
......@@ -473,7 +473,7 @@ int test2(struct Options options)
opts.cleansession = 1;
opts.username = "testuser";
opts.binarypwd.data = "testpassword";
opts.binarypwd.len = strlen(opts.binarypwd.data);
opts.binarypwd.len = (int)strlen(opts.binarypwd.data);
opts.MQTTVersion = options.MQTTVersion;
opts.will = &wopts;
......
......@@ -1726,7 +1726,7 @@ int test6(struct Options options)
/* let client c go: connect, and send disconnect command to proxy */
opts.will = &wopts;
opts.will->payload.data = "will message";
opts.will->payload.len = strlen(opts.will->payload.data) + 1;
opts.will->payload.len = (int)strlen(opts.will->payload.data) + 1;
opts.will->qos = 1;
opts.will->retained = 0;
opts.will->topicName = willTopic;
......@@ -1870,7 +1870,6 @@ void test7cOnConnectSuccess(void* context, MQTTAsync_successData* response)
{
MQTTAsync c = (MQTTAsync)context;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
int rc;
MyLog(LOGA_DEBUG, "In connect onSuccess callback for client c, context %p\n", context);
......@@ -1904,7 +1903,6 @@ void test7dOnConnectSuccess(void* context, MQTTAsync_successData* response)
{
MQTTAsync c = (MQTTAsync)context;
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
int rc;
int qoss[2] = {2, 2};
char* topics[2] = {willTopic, test_topic};
......@@ -1933,7 +1931,6 @@ int test7(struct Options options)
char clientidc[50];
char clientidd[50];
int i = 0;
MQTTAsync_token *tokens;
test7_will_message_received = 0;
test7_messages_received = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment