Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added ssl authentication #168

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
56 changes: 41 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,76 +5,82 @@
This is MQTT client library for ESP8266, port from: [MQTT client library for Contiki](https://github.com/esar/contiki-mqtt) (thanks)



**Features:**

* Support subscribing, publishing, authentication, will messages, keep alive pings and all 3 QoS levels (it should be a fully functional client).
* Support multiple connection (to multiple hosts).
* Support SSL connection
* Support SSL connection (including cert verification).
* Easy to setup and use


***Prerequire:***

- ESPTOOL.PY: https://github.com/themadinventor/esptool
- SDK 2.0 or higher: http://bbs.espressif.com/viewtopic.php?f=46&t=2451
- ESP8266 compiler:
- ESP8266 compiler:
+ OSX or Linux: http://tuanpm.net/esp8266-development-kit-on-mac-os-yosemite-and-eclipse-ide/
+ Windows: http://programs74.ru/udkew-en.html
+ Windows: http://programs74.ru/udkew-en.html


**Compile:**

- Copy file `include/user_config.sample.h` to `include/user_config.local.h` and change settings, included: SSID, PASS, MQTT configurations ...


Make sure to add PYTHON PATH and compile PATH to Eclipse environment variable if using Eclipse


```bash
git clone --recursive https://github.com/tuanpmt/esp_mqtt
cd esp_mqtt
#clean
make clean
#make
make SDK_BASE=/tools/esp8266/sdk/ESP8266_NONOS_SDK ESPTOOL=tools/esp8266/esptool/esptool.py all
make SDK_BASE=/tools/esp8266/sdk/ESP8266_NONOS_SDK ESPTOOL=/tools/esp8266/esptool/esptool.py all
#flash
make ESPPORT=/dev/ttyUSB0 flash
```
To create the library (and removing the uart debug output) use

```bash
make SDK_BASE=/tools/esp8266/sdk/ESP8266_NONOS_SDK FLAVOR=release lib
```


**Usage**

See file: `user/user_main.c`


**Notes**
- The client id needs to be unique. If not, When there are more than 2 clients use the same ClientID, the following logged-in client will kick the ahead logged-in client, and so on forever
- The client id needs to be unique. If not, when there are more than 2 clients use the same ClientID, the following logged-in client will kick the ahead logged-in client, and so on forever.


**Publish message and Subscribe**

```c
/* TRUE if success */
BOOL MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos);

BOOL MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain);
BOOL MQTT_Subscribe(MQTT_Client *client, const char* topic, uint8_t qos);

BOOL MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, uint8_t qos, uint8_t retain);
```


**Already support LWT: (Last Will and Testament)**

```c

/* Broker will publish a message with qos = 0, retain = 0, data = "offline" to topic "/lwt" if client don't send keepalive packet */
MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0);

```


# Default configuration

See: **include/user_config.sample.h**

**Define protocol name in include/user_config.local.h**
Define protocol name in `include/user_config.local.h`

```c
#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/
//PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/
//#define PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/
```


Expand All @@ -84,6 +90,26 @@ See: **include/user_config.sample.h**
openssl req -x509 -newkey rsa:1024 -keyout key.pem -out cert.pem -days XXX
```

On client side (ESP8266) you need to provide a `ca.crt` and a `client.crt`, `client.key` pair depending what kind of security you choose (SEC_SSL_ONE_WAY_AUTH or SEC_SSL_TWO_WAY_AUTH).

```c
//#define DEFAULT_SECURITY SEC_NONSSL // disable SSL/TLS
#define DEFAULT_SECURITY SEC_SSL_WITHOUT_AUTH // enable SSL/TLS, but there is no a certificate verify
//#define DEFAULT_SECURITY SEC_SSL_ONE_WAY_AUTH // enable SSL/TLS, ESP8266 would verify the SSL server certificate at the same time
//#define DEFAULT_SECURITY SEC_SSL_TWO_WAY_AUTH // enable SSL/TLS, ESP8266 would verify the SSL server certificate and SSL server would verify ESP8266 certificate
```

For more details how to create and flash the `ca.crt` and `client.crt` see the `tools` folder in [SDK_BASE](https://github.com/espressif/ESP8266_NONOS_SDK/tree/master/tools).
See also [ESP8266 Non-OS SDK SSL User Manual](https://www.espressif.com/sites/default/files/documentation/5a-esp8266_sdk_ssl_user_manual_en.pdf) in the Espressif documentation.

If needed you may configure the flash locations of the certificates in `include/user_config.local.h`

```c
#define CA_CERT_FLASH_ADDRESS 0x77 // CA certificate address in flash to read, 0x77 means address 0x77000
#define CLIENT_CERT_FLASH_ADDRESS 0x78 // client certificate and private key address in flash to read, 0x78 means address 0x78000
```


**SSL Mqtt broker for test**

```javascript
Expand Down
41 changes: 27 additions & 14 deletions include/user_config.sample.h
Original file line number Diff line number Diff line change
@@ -1,31 +1,44 @@
#ifndef __MQTT_CONFIG_H__
#define __MQTT_CONFIG_H__

#define MQTT_SSL_ENABLE
#include "mqtt.h"

/*DEFAULT CONFIGURATIONS*/

#define MQTT_HOST "192.168.0.101" //or "mqtt.yourdomain.com"
#define MQTT_PORT 1883
#define MQTT_BUF_SIZE 1024
#define MQTT_KEEPALIVE 120 /*second*/
#define MQTT_HOST "192.168.0.101" //or "mqtt.yourdomain.com"
#define MQTT_CLIENT_ID "CLIENT_1234"
#define MQTT_USER "USER"
#define MQTT_PASS "PASS"

#define MQTT_CLIENT_ID "CLIENT_1234"
#define MQTT_USER "USER"
#define MQTT_PASS "PASS"
#define MQTT_BUF_SIZE 1024
#define MQTT_SSL_SIZE 3072
#define MQTT_KEEPALIVE 120 /*second*/
#define MQTT_CLEAN_SESSION 1
#define MQTT_KEEPALIVE 120
#define MQTT_RECONNECT_TIMEOUT 5 /*second*/
#define QUEUE_BUFFER_SIZE 2048


#define STA_SSID "SSID"
#define STA_PASS "PASS"

#define MQTT_RECONNECT_TIMEOUT 5 /*second*/

#define DEFAULT_SECURITY 0
#define QUEUE_BUFFER_SIZE 2048
//#define DEFAULT_SECURITY SEC_NONSSL // disable SSL/TLS
#define DEFAULT_SECURITY SEC_SSL_WITHOUT_AUTH // enable SSL/TLS, but there is no a certificate verify
//#define DEFAULT_SECURITY SEC_SSL_ONE_WAY_AUTH // enable SSL/TLS, ESP8266 would verify the SSL server certificate at the same time
//#define DEFAULT_SECURITY SEC_SSL_TWO_WAY_AUTH // enable SSL/TLS, ESP8266 would verify the SSL server certificate and SSL server would verify ESP8266 certificate

#if DEFAULT_SECURITY == SEC_NONSSL
#define MQTT_PORT 1883
#else
#define MQTT_PORT 8883
#define MQTT_SSL_ENABLE
#define CA_CERT_FLASH_ADDRESS 0x77 // CA certificate address in flash to read, 0x77 means address 0x77000
#define CLIENT_CERT_FLASH_ADDRESS 0x78 // client certificate and private key address in flash to read, 0x78 means address 0x78000
// also add mbedtls to the Makefile LIBS
#endif

#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/
//PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/
//#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/
#define PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/

#if defined(DEBUG_ON)
#define INFO( format, ... ) os_printf( format, ## __VA_ARGS__ )
Expand Down
2 changes: 1 addition & 1 deletion modules/include/wifi.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
#define USER_WIFI_H_
#include "os_type.h"
typedef void (*WifiCallback)(uint8_t);
void ICACHE_FLASH_ATTR WIFI_Connect(uint8_t* ssid, uint8_t* pass, WifiCallback cb);
void ICACHE_FLASH_ATTR WIFI_Connect(const char* ssid, const char* pass, WifiCallback cb);
#endif /* USER_WIFI_H_ */
3 changes: 1 addition & 2 deletions modules/wifi.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ static void ICACHE_FLASH_ATTR wifi_check_ip(void *arg)
}
}

void ICACHE_FLASH_ATTR WIFI_Connect(uint8_t* ssid, uint8_t* pass, WifiCallback cb)
void ICACHE_FLASH_ATTR WIFI_Connect(const char* ssid, const char* pass, WifiCallback cb)
{
struct station_config stationConf;

Expand All @@ -76,4 +76,3 @@ void ICACHE_FLASH_ATTR WIFI_Connect(uint8_t* ssid, uint8_t* pass, WifiCallback c
os_timer_arm(&WiFiLinker, 1000, 0);
wifi_station_connect();
}

32 changes: 17 additions & 15 deletions mqtt/include/mqtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@
*/
#ifndef USER_AT_MQTT_H_
#define USER_AT_MQTT_H_
#include "user_config.h"
#include "mqtt_msg.h"
#include "user_interface.h"

#include "queue.h"

typedef struct mqtt_event_data_t
{
uint8_t type;
Expand Down Expand Up @@ -94,7 +93,7 @@ typedef void (*MqttDataCallback)(uint32_t *args, const char* topic, uint32_t top
typedef struct {
struct espconn *pCon;
uint8_t security;
uint8_t* host;
char* host;
uint32_t port;
ip_addr_t ip;
mqtt_state_t mqtt_state;
Expand All @@ -113,36 +112,39 @@ typedef struct {
void* user_data;
} MQTT_Client;

#define SEC_NONSSL 0
#define SEC_SSL 1
// define the possible MQTT SSL/TLS certificate options
#define SEC_NONSSL 0 // disable SSL/TLS
#define SEC_SSL_WITHOUT_AUTH 1 // enable SSL/TLS, but there is no a certificate verify
#define SEC_SSL_ONE_WAY_AUTH 2 // enable SSL/TLS, ESP8266 would verify the SSL server certificate at the same time
#define SEC_SSL_TWO_WAY_AUTH 3 // enable SSL/TLS, ESP8266 would verify the SSL server certificate and SSL server would verify ESP8266 certificate

#define MQTT_FLAG_CONNECTED 1
#define MQTT_FLAG_CONNECTED 1
#define MQTT_FLAG_READY 2
#define MQTT_FLAG_EXIT 4

#define MQTT_EVENT_TYPE_NONE 0
#define MQTT_EVENT_TYPE_NONE 0
#define MQTT_EVENT_TYPE_CONNECTED 1
#define MQTT_EVENT_TYPE_DISCONNECTED 2
#define MQTT_EVENT_TYPE_SUBSCRIBED 3
#define MQTT_EVENT_TYPE_UNSUBSCRIBED 4
#define MQTT_EVENT_TYPE_PUBLISH 5
#define MQTT_EVENT_TYPE_PUBLISH 5
#define MQTT_EVENT_TYPE_PUBLISHED 6
#define MQTT_EVENT_TYPE_EXITED 7
#define MQTT_EVENT_TYPE_EXITED 7
#define MQTT_EVENT_TYPE_PUBLISH_CONTINUATION 8

void ICACHE_FLASH_ATTR MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security);
BOOL ICACHE_FLASH_ATTR MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession);
void ICACHE_FLASH_ATTR MQTT_InitConnection(MQTT_Client *mqttClient, const char* host, uint32_t port, uint8_t security);
BOOL ICACHE_FLASH_ATTR MQTT_InitClient(MQTT_Client *mqttClient, const char* client_id, const char* client_user, const char* client_pass, uint32_t keepAliveTime, uint8_t cleanSession);
void ICACHE_FLASH_ATTR MQTT_DeleteClient(MQTT_Client *mqttClient);
void ICACHE_FLASH_ATTR MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t* will_topic, uint8_t* will_msg, uint8_t will_qos, uint8_t will_retain);
void ICACHE_FLASH_ATTR MQTT_InitLWT(MQTT_Client *mqttClient, const char* will_topic, const char* will_msg, uint8_t will_qos, uint8_t will_retain);
void ICACHE_FLASH_ATTR MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb);
void ICACHE_FLASH_ATTR MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb);
void ICACHE_FLASH_ATTR MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb);
void ICACHE_FLASH_ATTR MQTT_OnTimeout(MQTT_Client *mqttClient, MqttCallback timeoutCb);
void ICACHE_FLASH_ATTR MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb);
BOOL ICACHE_FLASH_ATTR MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos);
BOOL ICACHE_FLASH_ATTR MQTT_UnSubscribe(MQTT_Client *client, char* topic);
BOOL ICACHE_FLASH_ATTR MQTT_Subscribe(MQTT_Client *client, const char* topic, uint8_t qos);
BOOL ICACHE_FLASH_ATTR MQTT_UnSubscribe(MQTT_Client *client, const char* topic);
void ICACHE_FLASH_ATTR MQTT_Connect(MQTT_Client *mqttClient);
void ICACHE_FLASH_ATTR MQTT_Disconnect(MQTT_Client *mqttClient);
BOOL ICACHE_FLASH_ATTR MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain);
BOOL ICACHE_FLASH_ATTR MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, uint8_t qos, uint8_t retain);

#endif /* USER_AT_MQTT_H_ */
2 changes: 0 additions & 2 deletions mqtt/include/mqtt_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

#ifndef MQTT_MSG_H
#define MQTT_MSG_H
#include "user_config.h"
#include "c_types.h"
#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -138,4 +137,3 @@ mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connect
#endif

#endif /* MQTT_MSG_H */

13 changes: 13 additions & 0 deletions mqtt/include/typedef.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,17 @@ typedef long I32;
typedef unsigned long U32;
typedef unsigned long long U64;

#ifdef __cplusplus
// fix bug in c_types.h include, not defining BOOL, TRUE, FALSE for c++
#ifndef BOOL
# define BOOL bool
#endif // BOOL
#ifndef TRUE
# define TRUE true
#endif // TRUE
#ifndef FALSE
# define FALSE false
#endif // FALSE
#endif // __cplusplus

#endif
6 changes: 3 additions & 3 deletions mqtt/include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include "c_types.h"

uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const int8_t *s);
uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const int8_t* str, void *ip);
uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (int8_t *str);
uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const char *s);
uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const char *str, void *ip);
uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (const char *str);
#endif
Loading