reverted HTTPCLient debug back to defaulted off

Dependencies:   CyaSSL

Fork of HTTPClient-SSL by Keith Ruenheck

Files at this revision

API Documentation at this revision

Comitter:
Vanger
Date:
Wed Jan 14 22:39:59 2015 +0000
Parent:
37:293e8eae4230
Child:
39:d7c5541a9124
Commit message:
Added functions to add Root Certificates for SSL verification of Peers, added a function to set the peer verify settings for the CyaSSL library, tweaked some debug and memory operations in the client.

Changed in this revision

CyaSSL.lib Show annotated file Show diff for this revision Revisions of this file
HTTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPClient.h Show annotated file Show diff for this revision Revisions of this file
--- a/CyaSSL.lib	Tue Jan 06 16:46:44 2015 +0000
+++ b/CyaSSL.lib	Wed Jan 14 22:39:59 2015 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/teams/Multi-Hackers/code/CyaSSL/#eb845606fd41
+http://developer.mbed.org/users/Vanger/code/CyaSSL/#e505054279ed
--- 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;
     }
--- a/HTTPClient.h	Tue Jan 06 16:46:44 2015 +0000
+++ b/HTTPClient.h	Wed Jan 14 22:39:59 2015 +0000
@@ -32,6 +32,13 @@
 #include "mbed.h"
 #include "TCPSocketConnection.h"
 
+///SSL peer verification setting    
+enum SSLMethod {
+    VERIFY_NONE                 = 0, ///Don't check peer certificate
+    VERIFY_PEER                 = 1, ///Check peer certificate and skip if none available (insecure)
+    VERIFY_FAIL_IF_NO_PEER_CERT = 2, ///Check peer certificate and fail if unavailable
+};
+
 ///HTTP client results
 enum HTTPResult {
     HTTP_OK = 0, ///<Success
@@ -123,9 +130,35 @@
     */
     int getHTTPResponseCode();
     
-    void setHeader(const char *header) ;   /* set http headers */
-    HTTPResult setSSLversion(int minorV) ; /* set SSL/TLS version. 0: SSL3, 1: TLS1.0, 2: TLS1.1, 3: TLS1.2 */
-    void setLocationBuf(char *url, int size) ; /* set URL buffer for redirection */
+    /** Set headers to be included in the following HTTP requests. Pass a NULL pointer to reset the headers stored. 
+    * Make sure the headers are formatted with a "\r\n" after each header.
+    * @param header pointer to array containing the headers to be added*/
+    void setHeader(const char *header) ;
+    
+    /** Set SSL/TLS version. 
+    * @param minorV integer witha a value between 0 and 3
+    * 0: SSL3, 1: TLS1.0, 2: TLS1.1, 3: TLS1.2 
+    * @returns HTTPResult based on success*/
+    HTTPResult setSSLversion(int minorV) ; 
+    
+    /* set URL buffer for redirection */
+    void setLocationBuf(char *url, int size) ; 
+    
+    /** Stores a root CA certificate for host authentication of a website.
+    * Each new line should end with "\r\n" including the last line of each certificate.
+    * Pass a pointer to the char array containing the certificate stored as a c-string.
+    * Pass a NULL pointer to reset all certificates stored. 
+    * (Can pass in multiple certificates with one function call if the array contains concatenated certificates) */
+    HTTPResult addRootCACertificate(const char* cert) ;
+    
+    /** Sets the verification for peer authenticity when connecting with SSL
+    * @param method specifies the method to use for peer verification
+    * @VERIFY_NONE Sets the client to not verify the peer's certificates
+    * @VERIFY_PEER Sets the client to verify the peer's certificates but skips if certificates unavailable
+    * @VERIFY_FAIL_IF_NO_PEER_CERT Sets the client to verify the peer's certificates and throw an error if the 
+    * certificates are unavailable.
+    * */
+    void setPeerVerification(SSLMethod method);
 
 private:
     enum HTTP_METH {
@@ -149,7 +182,7 @@
     TCPSocketConnection _m_sock;
 
     int m_timeout;
-
+    
     const char* m_basicAuthUser;
     const char* m_basicAuthPassword;
     int m_httpResponseCode;
@@ -160,6 +193,8 @@
     int    redirect ;
     
     /* for CyaSSL */
+    const char* certificates; //CA certificates
+    SSLMethod peerMethod;
     int    SSLver ;
     uint16_t port;
     struct CYASSL_CTX* ctx ;