|
@@ -3,6 +3,7 @@
|
|
|
#include "module.h"
|
|
|
#include "lauxlib.h"
|
|
|
#include "platform.h"
|
|
|
+#include "lmem.h"
|
|
|
|
|
|
#include "c_string.h"
|
|
|
#include "c_stdlib.h"
|
|
@@ -13,18 +14,19 @@
|
|
|
#include "espconn.h"
|
|
|
#include "lwip/dns.h"
|
|
|
|
|
|
-#ifdef CLIENT_SSL_ENABLE
|
|
|
-unsigned char *default_certificate;
|
|
|
-unsigned int default_certificate_len = 0;
|
|
|
-unsigned char *default_private_key;
|
|
|
-unsigned int default_private_key_len = 0;
|
|
|
-#endif
|
|
|
-
|
|
|
#define TCP ESPCONN_TCP
|
|
|
#define UDP ESPCONN_UDP
|
|
|
|
|
|
static ip_addr_t host_ip; // for dns
|
|
|
|
|
|
+#ifdef HAVE_SSL_SERVER_CRT
|
|
|
+#include HAVE_SSL_SERVER_CRT
|
|
|
+#else
|
|
|
+__attribute__((section(".servercert.flash"))) unsigned char net_server_cert_area[INTERNAL_FLASH_SECTOR_SIZE];
|
|
|
+#endif
|
|
|
+
|
|
|
+__attribute__((section(".clientcert.flash"))) unsigned char net_client_cert_area[INTERNAL_FLASH_SECTOR_SIZE];
|
|
|
+
|
|
|
#if 0
|
|
|
static int expose_array(lua_State* L, char *array, unsigned short len);
|
|
|
#endif
|
|
@@ -1432,6 +1434,201 @@ static int net_multicastLeave( lua_State* L )
|
|
|
return net_multicastJoinLeave(L,0);
|
|
|
}
|
|
|
|
|
|
+// Returns NULL on success, error message otherwise
|
|
|
+static const char *append_pem_blob(const char *pem, const char *type, uint8_t **buffer_p, uint8_t *buffer_limit, const char *name) {
|
|
|
+ char unb64[256];
|
|
|
+ memset(unb64, 0xff, sizeof(unb64));
|
|
|
+ int i;
|
|
|
+ for (i = 0; i < 64; i++) {
|
|
|
+ unb64["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!pem) {
|
|
|
+ return "No PEM blob";
|
|
|
+ }
|
|
|
+
|
|
|
+ // Scan for -----BEGIN CERT
|
|
|
+ pem = strstr(pem, "-----BEGIN ");
|
|
|
+ if (!pem) {
|
|
|
+ return "No PEM header";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (strncmp(pem + 11, type, strlen(type))) {
|
|
|
+ return "Wrong PEM type";
|
|
|
+ }
|
|
|
+
|
|
|
+ pem = strchr(pem, '\n');
|
|
|
+ if (!pem) {
|
|
|
+ return "Incorrect PEM format";
|
|
|
+ }
|
|
|
+ //
|
|
|
+ // Base64 encoded data starts here
|
|
|
+ // Get all the base64 data into a single buffer....
|
|
|
+ // We will use the back end of the buffer....
|
|
|
+ //
|
|
|
+
|
|
|
+ uint8_t *buffer = *buffer_p;
|
|
|
+
|
|
|
+ uint8_t *dest = buffer + 32 + 2; // Leave space for name and length
|
|
|
+ int bitcount = 0;
|
|
|
+ int accumulator = 0;
|
|
|
+ for (; *pem && dest < buffer_limit; pem++) {
|
|
|
+ int val = unb64[*(uint8_t*) pem];
|
|
|
+ if (val & 0xC0) {
|
|
|
+ // not a base64 character
|
|
|
+ if (isspace(*(uint8_t*) pem)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (*pem == '=') {
|
|
|
+ // just ignore -- at the end
|
|
|
+ bitcount = 0;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (*pem == '-') {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return "Invalid character in PEM";
|
|
|
+ } else {
|
|
|
+ bitcount += 6;
|
|
|
+ accumulator = (accumulator << 6) + val;
|
|
|
+ if (bitcount >= 8) {
|
|
|
+ bitcount -= 8;
|
|
|
+ *dest++ = accumulator >> bitcount;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (dest >= buffer_limit || strncmp(pem, "-----END ", 9) || strncmp(pem + 9, type, strlen(type)) || bitcount) {
|
|
|
+ return "Invalid PEM format data";
|
|
|
+ }
|
|
|
+ size_t len = dest - (buffer + 32 + 2);
|
|
|
+
|
|
|
+ memset(buffer, 0, 32);
|
|
|
+ strcpy(buffer, name);
|
|
|
+ buffer[32] = len & 0xff;
|
|
|
+ buffer[33] = (len >> 8) & 0xff;
|
|
|
+ *buffer_p = dest;
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static const char *fill_page_with_pem(lua_State *L, const unsigned char *flash_memory, int flash_offset, const char **types, const char **names)
|
|
|
+{
|
|
|
+ uint8_t *buffer = luaM_malloc(L, INTERNAL_FLASH_SECTOR_SIZE);
|
|
|
+ uint8_t *buffer_base = buffer;
|
|
|
+ uint8_t *buffer_limit = buffer + INTERNAL_FLASH_SECTOR_SIZE;
|
|
|
+
|
|
|
+ int argno;
|
|
|
+
|
|
|
+ for (argno = 1; argno <= lua_gettop(L) && types[argno - 1]; argno++) {
|
|
|
+ const char *pem = lua_tostring(L, argno);
|
|
|
+
|
|
|
+ const char *error = append_pem_blob(pem, types[argno - 1], &buffer, buffer_limit, names[argno - 1]);
|
|
|
+ if (error) {
|
|
|
+ luaM_free(L, buffer_base);
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ memset(buffer, 0xff, buffer_limit - buffer);
|
|
|
+
|
|
|
+ // Lets see if it matches what is already there....
|
|
|
+ if (c_memcmp(buffer_base, flash_memory, INTERNAL_FLASH_SECTOR_SIZE) != 0) {
|
|
|
+ // Starts being dangerous
|
|
|
+ if (platform_flash_erase_sector(flash_offset / INTERNAL_FLASH_SECTOR_SIZE) != PLATFORM_OK) {
|
|
|
+ luaM_free(L, buffer_base);
|
|
|
+ return "Failed to erase sector";
|
|
|
+ }
|
|
|
+ if (platform_s_flash_write(buffer_base, flash_offset, INTERNAL_FLASH_SECTOR_SIZE) != INTERNAL_FLASH_SECTOR_SIZE) {
|
|
|
+ luaM_free(L, buffer_base);
|
|
|
+ return "Failed to write sector";
|
|
|
+ }
|
|
|
+ // ends being dangerous
|
|
|
+ }
|
|
|
+
|
|
|
+ luaM_free(L, buffer_base);
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+// Lua: net.cert.auth(true / false | PEM data [, PEM data] )
|
|
|
+static int net_cert_auth(lua_State *L)
|
|
|
+{
|
|
|
+ int enable;
|
|
|
+
|
|
|
+ uint32_t flash_offset = platform_flash_mapped2phys((uint32_t) &net_client_cert_area[0]);
|
|
|
+ if ((flash_offset & 0xfff) || flash_offset > 0xff000 || INTERNAL_FLASH_SECTOR_SIZE != 0x1000) {
|
|
|
+ // THis should never happen
|
|
|
+ return luaL_error( L, "bad offset" );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (lua_type(L, 1) == LUA_TSTRING) {
|
|
|
+ const char *types[3] = { "CERTIFICATE", "RSA PRIVATE KEY", NULL };
|
|
|
+ const char *names[2] = { "certificate", "private_key" };
|
|
|
+ const char *error = fill_page_with_pem(L, &net_client_cert_area[0], flash_offset, types, names);
|
|
|
+ if (error) {
|
|
|
+ return luaL_error(L, error);
|
|
|
+ }
|
|
|
+
|
|
|
+ enable = 1;
|
|
|
+ } else {
|
|
|
+ enable = lua_toboolean(L, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool rc;
|
|
|
+
|
|
|
+ if (enable) {
|
|
|
+ // See if there is a cert there
|
|
|
+ if (net_client_cert_area[0] == 0x00 || net_client_cert_area[0] == 0xff) {
|
|
|
+ return luaL_error( L, "no certificates found" );
|
|
|
+ }
|
|
|
+ rc = espconn_secure_cert_req_enable(1, flash_offset / INTERNAL_FLASH_SECTOR_SIZE);
|
|
|
+ } else {
|
|
|
+ rc = espconn_secure_cert_req_disable(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ lua_pushboolean(L, rc);
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+// Lua: net.cert.verify(true / false | PEM data [, PEM data] )
|
|
|
+static int net_cert_verify(lua_State *L)
|
|
|
+{
|
|
|
+ int enable;
|
|
|
+
|
|
|
+ uint32_t flash_offset = platform_flash_mapped2phys((uint32_t) &net_server_cert_area[0]);
|
|
|
+ if ((flash_offset & 0xfff) || flash_offset > 0xff000 || INTERNAL_FLASH_SECTOR_SIZE != 0x1000) {
|
|
|
+ // THis should never happen
|
|
|
+ return luaL_error( L, "bad offset" );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (lua_type(L, 1) == LUA_TSTRING) {
|
|
|
+ const char *types[2] = { "CERTIFICATE", NULL };
|
|
|
+ const char *names[1] = { "certificate" };
|
|
|
+
|
|
|
+ const char *error = fill_page_with_pem(L, &net_server_cert_area[0], flash_offset, types, names);
|
|
|
+ if (error) {
|
|
|
+ return luaL_error(L, error);
|
|
|
+ }
|
|
|
+
|
|
|
+ enable = 1;
|
|
|
+ } else {
|
|
|
+ enable = lua_toboolean(L, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool rc;
|
|
|
+
|
|
|
+ if (enable) {
|
|
|
+ // See if there is a cert there
|
|
|
+ if (net_server_cert_area[0] == 0x00 || net_server_cert_area[0] == 0xff) {
|
|
|
+ return luaL_error( L, "no certificates found" );
|
|
|
+ }
|
|
|
+ rc = espconn_secure_ca_enable(1, flash_offset / INTERNAL_FLASH_SECTOR_SIZE);
|
|
|
+ } else {
|
|
|
+ rc = espconn_secure_ca_disable(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ lua_pushboolean(L, rc);
|
|
|
+ return 1;
|
|
|
+}
|
|
|
|
|
|
// Lua: s = net.dns.setdnsserver(ip_addr, [index])
|
|
|
static int net_setdnsserver( lua_State* L )
|
|
@@ -1539,6 +1736,14 @@ static const LUA_REG_TYPE net_array_map[] = {
|
|
|
};
|
|
|
#endif
|
|
|
|
|
|
+static const LUA_REG_TYPE net_cert_map[] = {
|
|
|
+ { LSTRKEY( "verify" ), LFUNCVAL( net_cert_verify ) },
|
|
|
+#ifdef CLIENT_SSL_CERT_AUTH_ENABLE
|
|
|
+ { LSTRKEY( "auth" ), LFUNCVAL( net_cert_auth ) },
|
|
|
+#endif
|
|
|
+ { LNILKEY, LNILVAL }
|
|
|
+};
|
|
|
+
|
|
|
static const LUA_REG_TYPE net_dns_map[] = {
|
|
|
{ LSTRKEY( "setdnsserver" ), LFUNCVAL( net_setdnsserver ) },
|
|
|
{ LSTRKEY( "getdnsserver" ), LFUNCVAL( net_getdnsserver ) },
|
|
@@ -1552,6 +1757,9 @@ static const LUA_REG_TYPE net_map[] = {
|
|
|
{ LSTRKEY( "multicastJoin"), LFUNCVAL( net_multicastJoin ) },
|
|
|
{ LSTRKEY( "multicastLeave"), LFUNCVAL( net_multicastLeave ) },
|
|
|
{ LSTRKEY( "dns" ), LROVAL( net_dns_map ) },
|
|
|
+#ifdef CLIENT_SSL_ENABLE
|
|
|
+ { LSTRKEY( "cert" ), LROVAL(net_cert_map) },
|
|
|
+#endif
|
|
|
{ LSTRKEY( "TCP" ), LNUMVAL( TCP ) },
|
|
|
{ LSTRKEY( "UDP" ), LNUMVAL( UDP ) },
|
|
|
{ LSTRKEY( "__metatable" ), LROVAL( net_map ) },
|