Change buffer sizes to support GR-PEACH

Dependencies:   CyaSSL

Dependents:   GR-PEACH_Azure_Speech

Fork of HTTPClient-SSL by MultiTech

Revision:
38:a4ccad70be9d
Parent:
37:293e8eae4230
Child:
39:d7c5541a9124
--- a/HTTPClient.cpp	Tue Jan 06 16:46:44 2015 +0000
+++ b/HTTPClient.cpp	Wed Jan 14 22:39:59 2015 +0000
@@ -113,13 +113,18 @@
 HTTPClient::HTTPClient() :
     m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0)
 {
+    set_time(1421106306);
+    
+    CyaSSL_Init(); //Initialize CyaSSL
+
     m_sock = &_m_sock;
-    /* CyaSSL_Debugging_ON() ; */
+    /* CyaSSL_Debugging_ON() ; */  //Turn on if the CyaSSL library isn't working for debug printf's
     
+    peerMethod = VERIFY_FAIL_IF_NO_PEER_CERT;
     ctx = 0 ;
     ssl = 0 ;
     SSLver = 3 ; 
-    m_basicAuthUser = NULL ;
+    certificates = NULL;
     redirect_url = NULL ;
     redirect = 0 ;
     header = NULL ;
@@ -127,7 +132,12 @@
 
 HTTPClient::~HTTPClient()
 {
-
+    free((void *)m_basicAuthPassword);
+    m_basicAuthPassword = NULL;
+    free((void *)m_basicAuthUser);
+    m_basicAuthUser = NULL;
+    free((void *)certificates);
+    certificates = NULL;
 }
 
 HTTPResult HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
@@ -140,13 +150,17 @@
     if (user != NULL) {
         m_basicAuthUser = (char *)malloc(strlen(user)+1);
         strcpy((char *)m_basicAuthUser, user);
+    } else {
+        m_basicAuthUser = NULL;
     }
     
     if (m_basicAuthPassword) free((void *)m_basicAuthPassword);
     if (password != NULL) {
         m_basicAuthPassword = (char *)malloc(strlen(password)+1);
         strcpy((char *)m_basicAuthPassword, password); 
-    }   
+    }   else {
+        m_basicAuthPassword = NULL;
+    }
     
     return HTTP_OK ;
 }
@@ -202,6 +216,37 @@
     return HTTP_OK ;
 }
 
+HTTPResult HTTPClient::addRootCACertificate(const char* cert)
+{
+    if(cert == NULL) {
+        if(certificates != NULL) {
+            free((void *)certificates);
+        }
+    } else {
+        //Append certificate, else allocate new certificate
+        if(certificates != NULL) {
+            certificates = (char *)realloc((void *)certificates, strlen(cert) + 1 + strlen(certificates)); //+1 is for '\0' char
+            if(certificates == NULL) {
+                return HTTP_ERROR;
+            } else {
+                strcat((char *)certificates, cert);
+            }
+        } else {
+            certificates = (char *)malloc(strlen(cert) + 1);
+            if(certificates == NULL) {
+                return HTTP_ERROR;
+            } else {
+                strcpy((char *)certificates, cert);
+            }
+        }
+    }
+    return HTTP_OK;
+}
+
+void HTTPClient::setPeerVerification(SSLMethod method) {
+    peerMethod = method;
+}
+
 
 #define CHECK_CONN_ERR(ret) \
   do{ \
@@ -299,14 +344,38 @@
             case 0 : SSLmethod = CyaSSLv3_client_method() ; break ;
             case 1 : SSLmethod = CyaTLSv1_client_method() ; break ;
             case 2 : SSLmethod = CyaTLSv1_1_client_method() ; break ;           
-            case 3 : SSLmethod = CyaTLSv1_2_client_method() ; break ;      
+            case 3 : SSLmethod = CyaTLSv1_2_client_method() ; break ;   
             }
             ctx = CyaSSL_CTX_new((CYASSL_METHOD *)SSLmethod);
             if (ctx == NULL) {
                 ERR("unable to get ctx");
                 return HTTP_CONN;
             }
-            CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
+            
+            if(certificates == NULL && peerMethod != VERIFY_NONE) {
+                ERR("No certificates passed for peer verification");
+                return HTTP_PROCESSING;
+            }
+            
+            { //Localize pMethod array for less overall memory time-use
+                std::string pMethod;
+                if(peerMethod == VERIFY_NONE) {
+                    pMethod = "not verify peer";
+                } else if (peerMethod == VERIFY_PEER) {
+                    pMethod = "verify peer if certificates available";
+                } else if (peerMethod == VERIFY_FAIL_IF_NO_PEER_CERT) {
+                    pMethod = "verify peer and fail if no peer certificates available";
+                }
+                DBG("SSL connection set to %s", pMethod.c_str());
+            }
+            
+            CyaSSL_CTX_set_verify(ctx, peerMethod, 0); //SSL_VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_NONE, SSL_VERIFY_PEER
+            
+            //Load the CA certificate(s) (If using multiple, concatenate them in the buffer being passed)
+            if (SSL_SUCCESS != CyaSSL_CTX_load_verify_buffer(ctx, (const unsigned char*)certificates, strlen(certificates), SSL_FILETYPE_PEM)) {
+                ERR("unable to load root certificates");
+                return HTTP_CONN;
+            }
             CyaSSL_SetIORecv(ctx, SocketReceive) ;
             CyaSSL_SetIOSend(ctx, SocketSend) ;
         }
@@ -321,8 +390,18 @@
 
         DBG("ctx=%x, ssl=%x, ssl->ctx->CBIORecv, CBIOSend=%x, %x\r\n",
             ctx, ssl, SocketReceive, SocketSend ) ;
-        if (CyaSSL_connect(ssl) != SSL_SUCCESS) {
+            int ret = CyaSSL_connect(ssl);
+        if (ret != SSL_SUCCESS) {
             ERR("SSL_connect failed");
+            int err = CyaSSL_get_error(ssl, ret);
+            char data[32];
+            char data_new[32];
+            strcpy(data_new, CyaSSL_ERR_error_string(err, data));
+            if(!strcmp(data,data_new)) {
+                printf("Error code [%d] is [%s]\r\n", err, data);
+            } else {
+                printf("Failed to get error code [%d], Reason: [%s]\r\n", err, data_new);
+            }
             cyassl_free() ;
             return HTTP_CONN;
         }
@@ -793,6 +872,15 @@
         *port=0;
     }
     char* pathPtr = strchr(hostPtr, '/');
+    if(pathPtr == NULL) {
+        pathPtr = strchr(hostPtr, '#');
+        if(pathPtr != NULL) {
+            pathPtr++;
+        } else {
+            pathPtr = (char *)(url + strlen(url));
+        }
+    }
+    
     if( hostLen == 0 ) {
         hostLen = pathPtr - hostPtr;
     }