diff --git a/lib/Microgear/AuthClient.c b/lib/Microgear/AuthClient.c index 8818e68..19bc4ff 100644 --- a/lib/Microgear/AuthClient.c +++ b/lib/Microgear/AuthClient.c @@ -88,7 +88,7 @@ int ICACHE_FLASH_ATTR getAccessToken(Token *token, char* appid, char* key, char* #endif if (memcmp(token->key, key, KEYSIZE)!=0) { - callRevokeTokenAPI(token); + //callRevokeTokenAPI(token); token->type = 0; } @@ -119,7 +119,8 @@ int ICACHE_FLASH_ATTR getAccessToken(Token *token, char* appid, char* key, char* } } -int ICACHE_FLASH_ATTR connectAuthServer() { +SOCKCLIENT ICACHE_FLASH_ATTR connectAuthServer() { +#ifndef TLS const struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, @@ -127,20 +128,48 @@ int ICACHE_FLASH_ATTR connectAuthServer() { struct addrinfo *res; int err = getaddrinfo(AUTH_ADDRESS, AUTH_PORT, &hints, &res); struct in_addr *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr; - int client = socket(res->ai_family, res->ai_socktype, 0); + SOCKCLIENT client = socket(res->ai_family, res->ai_socktype, 0); if(connect(client, res->ai_addr, res->ai_addrlen) == 0) return client; - else return -1; + else return NULLSOCKET; +#else + SSLConnection* ssl_conn = NULLSOCKET; + int ret = 0; + ssl_conn = (SSLConnection *) malloc(sizeof(SSLConnection)); + ssl_init(ssl_conn); + + // ssl_conn->ca_cert_str = ca_cert; + // ssl_conn->client_cert_str = client_cert; + // ssl_conn->client_key_str = client_key; + + ret = ssl_connect(ssl_conn, AUTH_ADDRESS, SECURE_AUTH_PORT); + if (ret) { + ssl_destroy(ssl_conn); + free(ssl_conn); + return NULLSOCKET; + } + else return ssl_conn; +#endif +} + +void ICACHE_FLASH_ATTR closeAuthServer(SOCKCLIENT client) { + if (client != NULLSOCKET) { + closeAuthServer(client); + #ifdef TLS + free(client); + #endif + client = NULLSOCKET; + } } // Read http client socket, set buff as a body, return http status -int ICACHE_FLASH_ATTR getHTTPResponse(int client, char *buff) { +int ICACHE_FLASH_ATTR getHTTPResponse(SOCKCLIENT client, char *buff) { int r, clen = -1; int httpstatus = -1; char *h, *p, *t; char header = 1; t = buff; - while ((r = read(client , t, READ_CHUNK_SIZE)) > 0) { + while ((r = sockread(client , t, READ_CHUNK_SIZE, 0)) > 0) { h = p = buff; t += r; *t = 0; @@ -169,6 +198,7 @@ int ICACHE_FLASH_ATTR getHTTPResponse(int client, char *buff) { t = buff+(t-h); } } + os_printf("r = %d \n\n",r); if (clen >= 0) *(buff+clen)=0; return httpstatus; } @@ -176,15 +206,15 @@ int ICACHE_FLASH_ATTR getHTTPResponse(int client, char *buff) { uint32_t ICACHE_FLASH_ATTR getServerTime() { #define REQUESTCMD "GET /api/time HTTP/1.1\r\nConnection: close\r\n\r\n" char* buff; - int tmclient; + SOCKCLIENT tmclient; uint32_t time = 0; - if ((tmclient = connectAuthServer()) >= 0) { + if ((tmclient = connectAuthServer()) != NULLSOCKET) { buff = (char *)malloc(HTTP_BUFFER_SIZE); memset(buff, 0, HTTP_BUFFER_SIZE); - if (write(tmclient, REQUESTCMD, STRLEN(REQUESTCMD)) < 0) { - close(tmclient); + if (sockwrite(tmclient, REQUESTCMD, STRLEN(REQUESTCMD), 0) < 0) { + closeAuthServer(tmclient); return 0; } memset(buff, 0, strlen(buff)); @@ -193,15 +223,15 @@ uint32_t ICACHE_FLASH_ATTR getServerTime() { } free(buff); } - close(tmclient); + closeAuthServer(tmclient); return time; } int ICACHE_FLASH_ATTR getOAuthToken(Token *token, char* appid, char* key, char* secret, char* alias, char* uri) { - int authclient; + SOCKCLIENT authclient; char *buff; - if ((authclient = connectAuthServer()) >= 0) { + if ((authclient = connectAuthServer()) != NULLSOCKET) { char *p, *r; char rep[3]; char hashkey[HASKKEYSIZE+1]; @@ -224,9 +254,9 @@ int ICACHE_FLASH_ATTR getOAuthToken(Token *token, char* appid, char* key, char* } p = addattr(p, "\",oauth_version=\"1.0\"",NULL); - if (write(authclient, buff, strlen(buff)) < 0) { + if (sockwrite(authclient, buff, strlen(buff), 0) < 0) { printf("... socket send failed\r\n"); - close(authclient); + closeAuthServer(authclient); free(buff); return 0; } @@ -307,20 +337,20 @@ int ICACHE_FLASH_ATTR getOAuthToken(Token *token, char* appid, char* key, char* os_printf("oauth_signature = %s\n",buff+18); #endif - write(authclient, buff, strlen(buff)); + sockwrite(authclient, buff, strlen(buff), 0); memset(buff, 0, HTTP_BUFFER_SIZE); p = addattr(buff, "Host: ", AUTH_ADDRESS); p = addattr(p, ":", AUTH_PORT); p = addattr(p, "\r\nConnection: close\r\nUser-Agent: E8R\r\n\r\n", NULL); - if (write(authclient, buff, strlen(buff)) < 0) { + if (sockwrite(authclient, buff, strlen(buff), 0) < 0) { printf("... socket send failed\r\n"); - close(authclient); + closeAuthServer(authclient); free(buff); return 0; } } else { - close(authclient); + closeAuthServer(authclient); } char *h, *p, *t; @@ -393,32 +423,35 @@ int ICACHE_FLASH_ATTR getOAuthToken(Token *token, char* appid, char* key, char* #endif free(buff); - close(authclient); + closeAuthServer(authclient); return 1; } int ICACHE_FLASH_ATTR callRevokeTokenAPI(Token* token) { char* buff; - int client; + SOCKCLIENT client; int success = 0; - if ((client = connectAuthServer()) >= 0) { + if ((client = connectAuthServer()) != NULLSOCKET) { buff = (char *)malloc(HTTP_BUFFER_SIZE); memset(buff, 0, HTTP_BUFFER_SIZE); memcpy(buff,"GET /api/revoke/",16); addattr(buff+16, token->token, "/"); addattr(tail(buff), token->revokecode, " HTTP/1.1\r\nConnection: close\r\n\r\n"); - if (write(client, buff, strlen(buff)) < 0) { + if (sockwrite(client, buff, strlen(buff), 0) < 0) { free(buff); - close(client); + closeAuthServer(client); return 0; } memset(buff, 0, strlen(buff)); + os_printf("1>>>>"); if (getHTTPResponse(client, buff) == 200) { + os_printf("2>>>>"); success = (memcmp("FAILED", buff, 6)!=0); } + os_printf("3>>>>"); free(buff); } - close(client); + closeAuthServer(client); return success; } diff --git a/lib/Microgear/AuthClient.h b/lib/Microgear/AuthClient.h index 86e3870..6114152 100644 --- a/lib/Microgear/AuthClient.h +++ b/lib/Microgear/AuthClient.h @@ -16,6 +16,11 @@ #include "ESPTime.h" #include "TokenStore.h" +#ifdef TLS +#include "sslcon.h" +#endif +#include "sock.h" + #define REQUESTTOKEN 1 #define ACCESSTOKEN 2 @@ -34,6 +39,7 @@ #define AUTH_ADDRESS "ga.netpie.io" #define AUTH_PORT "8080" +#define SECURE_AUTH_PORT 8081 #define AUTH_REQUEST_TOKEN_URI "/api/rtoken" #define AUTH_ACCESS_TOKEN_URI "/api/atoken" diff --git a/lib/Microgear/config.h b/lib/Microgear/config.h index c04c9a0..3fc9b6a 100644 --- a/lib/Microgear/config.h +++ b/lib/Microgear/config.h @@ -6,4 +6,6 @@ #define PUBSUBQUEUE_PAYLOADSIZE 256 #define PUBSUBQUEUE_LENGTH 3 +#define TLS + #endif \ No newline at end of file diff --git a/lib/Microgear/sock.c b/lib/Microgear/sock.c new file mode 100644 index 0000000..46e0bc8 --- /dev/null +++ b/lib/Microgear/sock.c @@ -0,0 +1,25 @@ +#include "sock.h" + +int sockwrite(SOCKCLIENT n, unsigned char* buffer, int len, int timeout_ms) { + #ifndef TLS + return write(n, buffer, len); + #else + return ssl_write(n, buffer, len, timeout_ms); + #endif +} + +int sockread(SOCKCLIENT n, unsigned char* buffer, int len, int timeout_ms) { + #ifndef TLS + return read(n, buffer, len); + #else + return ssl_read(n, buffer, len, timeout_ms); + #endif +} + +int sockclose(SOCKCLIENT conn) { + #ifdef TLS + return ssl_destroy(conn); + #else + return close(conn); + #endif +} diff --git a/lib/Microgear/sock.h b/lib/Microgear/sock.h new file mode 100644 index 0000000..d23291c --- /dev/null +++ b/lib/Microgear/sock.h @@ -0,0 +1,25 @@ +#include "config.h" + +#ifndef _SOCK_ +#define _SOCK_ + +#ifdef TLS + #include "sslcon.h" + #define SOCKCLIENT SSLConnection* + #define NULLSOCKET NULL +#else + #include "lwip/err.h" + #include "lwip/sockets.h" + #include "lwip/sys.h" + #include "lwip/netdb.h" + #include "lwip/dns.h" + + #define SOCKCLIENT int + #define NULLSOCKET -1 +#endif + +int sockread(SOCKCLIENT, unsigned char*, int, int); +int sockwrite(SOCKCLIENT, unsigned char*, int, int); +int sockclose(SOCKCLIENT); + +#endif /* _SOCK_ */ \ No newline at end of file diff --git a/lib/Microgear/sslcon.c b/lib/Microgear/sslcon.c new file mode 100644 index 0000000..507012b --- /dev/null +++ b/lib/Microgear/sslcon.c @@ -0,0 +1,194 @@ +#include "sslcon.h" + +#ifdef TLS + +// add a missing variable +//unsigned int max_content_len = 16384; +//unsigned int max_content_len = 8000; +unsigned int max_content_len = 3072; + +#define SSL_READ_TIMEOUT_MS 2000 + +const char *pers = "esp-tls"; + +static int handle_error(int err) { + +#ifdef MBEDTLS_ERROR_C + char error_buf[100]; + mbedtls_strerror(err, error_buf, 100); + printf("%s\n", error_buf); +#endif + printf("Error: %d\n", err); + return err; +} + +void ssl_init(SSLConnection* conn) { + /* + * Initialize the RNG and the session data + */ + mbedtls_net_init(&conn->net_ctx); + mbedtls_ssl_init(&conn->ssl_ctx); + mbedtls_ssl_config_init(&conn->ssl_conf); + +// mbedtls_x509_crt_init(&conn->ca_cert); +// mbedtls_x509_crt_init(&conn->client_cert); +// mbedtls_pk_init(&conn->client_key); + + mbedtls_ctr_drbg_init(&conn->drbg_ctx); + mbedtls_entropy_init(&conn->entropy_ctx); + +} + +int ssl_connect(SSLConnection* conn, const char* host, int port) { + int ret; + char buffer[8]; + + ret = mbedtls_ctr_drbg_seed(&conn->drbg_ctx, mbedtls_entropy_func, + &conn->entropy_ctx, (const unsigned char *) pers, strlen(pers)); + if (ret < 0) { + return -1; + } + + // ret = mbedtls_x509_crt_parse(&conn->ca_cert, + // (const unsigned char *) conn->ca_cert_str, + // strlen(conn->ca_cert_str) + 1); + // if (ret < 0) { + // return handle_error(ret); + // } +os_printf("1----"); + +// ret = mbedtls_x509_crt_parse(&conn->client_cert, +// (const unsigned char *) conn->client_cert_str, +// strlen(conn->client_cert_str) + 1); +// if (ret < 0) { +// return handle_error(ret); +// } + +// ret = mbedtls_pk_parse_key(&conn->client_key, +// (const unsigned char *) conn->client_key_str, +// strlen(conn->client_key_str) + 1, NULL, 0); +// if (ret != 0) { +// return handle_error(ret); +// } + + snprintf(buffer, sizeof(buffer), "%d", port); + ret = mbedtls_net_connect(&conn->net_ctx, host, buffer, + MBEDTLS_NET_PROTO_TCP); + if (ret != 0) { + return handle_error(ret); + } +os_printf("1.5----"); + + ret = mbedtls_ssl_config_defaults(&conn->ssl_conf, MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); + if (ret != 0) { + return handle_error(ret); + } +os_printf("2----"); + +// mbedtls_ssl_conf_authmode(&conn->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_authmode(&conn->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); +os_printf("4----"); + + mbedtls_ssl_conf_rng(&conn->ssl_conf, mbedtls_ctr_drbg_random, + &conn->drbg_ctx); +os_printf("5----"); + mbedtls_ssl_conf_read_timeout(&conn->ssl_conf, SSL_READ_TIMEOUT_MS); +os_printf("6----"); + mbedtls_ssl_conf_ca_chain(&conn->ssl_conf, &conn->ca_cert, NULL); +os_printf("7----"); + + // ret = mbedtls_ssl_conf_own_cert(&conn->ssl_conf, &conn->client_cert, + // &conn->client_key); + // if (ret != 0) { + // return handle_error(ret); + // } + + //ori superhouse + // mbedtls_ssl_set_bio(&conn->ssl_ctx, &conn->net_ctx, mbedtls_net_send, NULL, + // mbedtls_net_recv_timeout); + // not ori -- from ? + // mbedtls_ssl_set_bio(&conn->ssl_ctx, &conn->net_ctx, mbedtls_net_send, mbedtls_net_recv, NULL ); + + + ret = mbedtls_ssl_setup(&conn->ssl_ctx, &conn->ssl_conf); + if (ret != 0) { + return handle_error(ret); + } +os_printf("8----"); + + ret = mbedtls_ssl_set_hostname(&conn->ssl_ctx, host); + if (ret != 0) { + return handle_error(ret); + } +os_printf("9----"); + +// try -- https://github.com/SuperHouse/esp-open-rtos/issues/182 +//mbedtls_net_set_nonblock(&conn->net_ctx); + + //--> mbedtls_ssl_set_bio used to be here ...... + mbedtls_ssl_set_bio(&conn->ssl_ctx, &conn->net_ctx, mbedtls_net_send, NULL, + mbedtls_net_recv_timeout); + + // while((ret = mbedtls_ssl_handshake(&conn->ssl_ctx)) != 0) { + // if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + // os_printf(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret); + // //return handle_error(ret); + // } + // } + + +os_printf("p----"); + while ((ret = mbedtls_ssl_handshake(&conn->ssl_ctx)) != 0) { +os_printf("p2----"); + if (ret != MBEDTLS_ERR_SSL_WANT_READ + && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { +os_printf("q----"); + if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { + return handle_error(ret); + } + } + handle_error(ret); +os_printf("r----"); + vTaskDelay(5000 / portTICK_RATE_MS); + } + + + +os_printf("s----"); + + mbedtls_ssl_get_record_expansion(&conn->ssl_ctx); + ret = mbedtls_ssl_get_verify_result(&conn->ssl_ctx); + if (ret != 0) { + return handle_error(ret); + } +os_printf("s----"); + + return ret; +} + +int ssl_destroy(SSLConnection* conn) { + mbedtls_net_free(&conn->net_ctx); + mbedtls_ssl_free(&conn->ssl_ctx); + mbedtls_ssl_config_free(&conn->ssl_conf); + mbedtls_ctr_drbg_free(&conn->drbg_ctx); + mbedtls_entropy_free(&conn->entropy_ctx); + // mbedtls_x509_crt_free(&conn->ca_cert); + // mbedtls_x509_crt_free(&conn->client_cert); + //mbedtls_pk_free(&conn->client_key); + + return 0; +} + +int ssl_read(SSLConnection* n, unsigned char* buffer, int len, int timeout_ms) { + // NB: timeout_ms is ignored, so blocking read will timeout after SSL_READ_TIMEOUT_MS + return mbedtls_ssl_read(&n->ssl_ctx, buffer, len); +} + +int ssl_write(SSLConnection* n, unsigned char* buffer, int len, + int timeout_ms) { + // NB: timeout_ms is ignored, so write is always block write + return mbedtls_ssl_write(&n->ssl_ctx, buffer, len); +} + +#endif diff --git a/lib/Microgear/sslcon.h b/lib/Microgear/sslcon.h new file mode 100644 index 0000000..a104d92 --- /dev/null +++ b/lib/Microgear/sslcon.h @@ -0,0 +1,58 @@ +#ifndef _SSLCON_H_ +#define _SSLCON_H_ + +#include "config.h" + +#ifdef TLS + +#include +#include +#include +#include +#include +#include +#include + +#ifdef MBEDTLS_DEBUG_C + #define DEBUG_TLS +#endif + +// this must be ahead of any mbedtls header files so the local mbedtls/config.h can be properly referenced +#include "mbedtls/config.h" + +#include "mbedtls/net.h" +//#include "mbedtls/net_sockets.h" +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" + +typedef struct SSLConnection { + mbedtls_net_context net_ctx; + mbedtls_ssl_context ssl_ctx; + mbedtls_ssl_config ssl_conf; + + mbedtls_ctr_drbg_context drbg_ctx; + mbedtls_entropy_context entropy_ctx; + + mbedtls_x509_crt ca_cert; + mbedtls_x509_crt client_cert; + mbedtls_pk_context client_key; + + char *ca_cert_str; + char *client_cert_str; + char *client_key_str; +} SSLConnection; + +extern void ssl_init(SSLConnection* n); +extern int ssl_connect(SSLConnection* n, const char* host, int port); +extern int ssl_destroy(SSLConnection* n); +extern int ssl_read(SSLConnection* n, unsigned char* buffer, int len, + int timeout_ms); +extern int ssl_write(SSLConnection* n, unsigned char* buffer, int len, + int timeout_ms); + +#endif /* TLS*/ +#endif /* _SSLCON_H_ */