HTTPS GET Anfrage scheitert
Answer
17/01/19 11:55

Hallo zusammen,

Ich versuche aktuell ein Projekt durchzuführen, bei welchem nach Auslesen eines Sensors in einem gewissen Wertebereich ein HTTPS GET Request durchgeführt werden soll. Dieser scheitert jedoch (sl_Send failed: -1), obwohl die Netzwerkverbindung funktioniert. Der Code für die HTTPS Anfrage ist aus dem entsprechenden Guide entnommen. Der restliche Code ist auch aus Beispielen oder Guides entnommen, da ich wenig Erfahrung mit C/FreeRTOS/Programmierung im Allgemeinen besitze.

#include "XdkAppInfo.h"
#undef BCDS_MODULE_ID  /* Module ID define before including Basics package*/
#define BCDS_MODULE_ID XDK_APP_MODULE_ID_APP_CONTROLLER

#define SECONDS(x) ((portTickType) (x*1000) /portTICK_RATE_MS)

#define MINUTES(x) ((portTickType) (x*1000*60) /portTICK_RATE_MS)

#define APP_CONTROLLER_TX_DELAY UINT32_C(1000)


#include "AppController.h"
#include <stdio.h>
#include "BCDS_CmdProcessor.h"
#include "XDK_Utils.h"
#include "FreeRTOS.h"
#include "task.h"
#include "BCDS_Assert.h"
#include "XDK_Sensor.h"

#include "BCDS_WlanConnect.h"
#include "BCDS_NetworkConfig.h"
#include <simplelink.h>
#include "PIp.h"
#include <device.h>
#include <Serval_HttpClient.h>

#include "PAL_initialize_ih.h"
#include "PAL_socketMonitor_ih.h"


static CmdProcessor_T * AppCmdProcessor;/**< Handle to store the main Command processor handle to be used by run-time event driven threads */

static xTaskHandle AppControllerHandle = NULL;/**< OS thread handle for Application controller to be used by run-time blocking threads */

static void LightAppCallback(void *param1, uint32_t param2);



#define HOST_NAME "1.2.3.4:1234"



#define CA_FILE_NAME "digicert.der"

unsigned char digicert_root_crt[] ={
		0x2D, 0x2D, 0x2D, 0x2D, ..., 0x0D, 0x0A //Aus Gründen der Übersichtlichkeit entfernt
};

int digicert_root_crt_len = 969;


static Sensor_Setup_T SensorSetup =
        {
                .CmdProcessorHandle = NULL,
                .Enable =
                        {

                              .Light = true,

                        },
                .Config =
                        {

                                .Light =
                                        {
                                                .IsInteruptEnabled = true,
                                                .Callback = LightAppCallback,
                                        },

                        },
        };



static void LightAppCallback(void *param1, uint32_t param2)
{
    BCDS_UNUSED(param1);
    BCDS_UNUSED(param2);

    //printf("*******Light sensor application callback received*******\r\n");
}


void connectServerSecure(void){
	

	Ip_Address_T destAddr; // = 0;
	//PAL_getIpaddress((uint8_t*) HOST_NAME, &destAddr);
	Ip_convertOctetsToAddr(1, 2, 3, 4, &destAddr);

	_i16 socketHandle = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_SEC_SOCKET);

	sl_SetSockOpt(
			socketHandle,
			SL_SOL_SOCKET,
			SL_SO_SECURE_FILES_CA_FILE_NAME,
			CA_FILE_NAME,
			strlen(CA_FILE_NAME)
			);

	SlSockAddrIn_t addr;
	addr.sin_family = SL_AF_INET;
	addr.sin_port = sl_Htons(1234);
	addr.sin_addr.s_addr = destAddr;

	sl_Connect(socketHandle, (SlSockAddr_t *)&addr, sizeof(SlSockAddrIn_t));


	  sendGetRequest(socketHandle, HOST_NAME,"/beispiel");


	sl_Close (socketHandle);
}



void flashCertificate(char *fileName, _u8* data, _u32 length){
	printf("TLS Zertifikat wird geflasht\n");
	SlDateTime_t dateTime;
	dateTime.sl_tm_day = (_u32)14;
	dateTime.sl_tm_mon = (_u32)1;
	dateTime.sl_tm_year = (_u32)2019;
	dateTime.sl_tm_hour = (_u32)0;
	dateTime.sl_tm_min = (_u32)0;
	dateTime.sl_tm_sec = (_u32)0;


	sl_DevSet(
			SL_DEVICE_GENERAL_CONFIGURATION,
			SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME,
			sizeof(SlDateTime_t),
			(_u8 *)(&dateTime)
			);



	_i32 fileHandle = 0;

	sl_FsOpen(
			(_u8*)fileName,
			FS_MODE_OPEN_CREATE(
					1024, _FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ
					),
					NULL,
					&fileHandle
					);


	_i32 writtenLen= sl_FsWrite(fileHandle, 0, data, length);
	sl_FsClose(fileHandle, NULL, NULL, 0);


}


void sendGetRequest(_i16 socketHandle, char* host, char* path)
{
	char outBuf[1024];
	char inBuf[1024];

	_i16 bytesSent = 0;
	_i16 bytesReceived = 0;


	sprintf(
			outBuf,
			"GET https://%s%s HTTP/1.1\r\nHost: %s\r\n\r\n", host, path, host
			);


	printf("HTTP request:\r\n");
	printf("\r\n======\r\n");
	printf("%s", outBuf);
	printf("\r\n======\r\n");

	bytesSent = sl_Send(
			socketHandle, (const void *) outBuf, strlen(outBuf), 0
			);

	if (bytesSent <=0){
		printf("sl_Send failed: %i\r\n", bytesSent);
		return;
	}

	printf("HTTP response:\r\n");
	printf("\r\n======\r\n");

	int linesPrinted = 0;

	do{
		bytesReceived = sl_Recv(socketHandle, inBuf, 1024, 0);
		int lastStart = 0;
		int pos = 0;

		while (linesPrinted < 10 && pos > bytesReceived){
			if(inBuf[pos] == '\n'){
				printf("%.*s", pos - lastStart - 1, inBuf + lastStart);
						lastStart = pos;
						linesPrinted++;
			}
		pos++;
		}

	}while(bytesReceived>0);

}



static void AppControllerFire(void* pvParameters)
{
    BCDS_UNUSED(pvParameters);



    Retcode_T retcode = RETCODE_OK;
    Sensor_Value_T sensorValue;

    while (1)
    {
     
    	  retcode = Sensor_GetData(&sensorValue);
    	  if (RETCODE_OK == retcode)
    	  	  {

    		  printf("Lichtsensor [millilux]:%d \n\r", (unsigned int) sensorValue.Light);

    		  	  if (sensorValue.Light < 40000 && sensorValue.Light > 0) //Beispielwert
    		  	  	  {

    		  		  printf("Herstellung WiFi Verbindung wird gestartet \n");

    		  		  EnterpriseWiFi();

    		  		  flashCertificate(CA_FILE_NAME, digicert_root_crt, digicert_root_crt_len);

    		  		  connectServerSecure();


    		  		  printf("Platzhalter\n");

    		  		  vTaskDelay(SECONDS(15));
    		  }

    	  	  }

    	  if (RETCODE_OK != retcode)
    	         {
    	             Retcode_RaiseError(retcode);
    	         }
    	         vTaskDelay(pdMS_TO_TICKS(APP_CONTROLLER_TX_DELAY));

    }
}


static void AppControllerEnable(void * param1, uint32_t param2)
{
    BCDS_UNUSED(param1);
    BCDS_UNUSED(param2);

    Retcode_T retcode = Sensor_Enable();

  
    if (RETCODE_OK == retcode)
    {
        if (pdPASS != xTaskCreate(AppControllerFire, (const char * const ) "AppController", TASK_STACK_SIZE_APP_CONTROLLER, NULL, TASK_PRIO_APP_CONTROLLER, &AppControllerHandle))
        {
            retcode = RETCODE(RETCODE_SEVERITY_ERROR, RETCODE_OUT_OF_RESOURCES);
        }
    }
    if (RETCODE_OK != retcode)
    {
        printf("AppControllerEnable : Failed \r\n");
        Retcode_RaiseError(retcode);
        assert(0); /* To provide LED indication for the user */
    }
    Utils_PrintResetCause();
}

static void AppControllerSetup(void * param1, uint32_t param2)
{
    BCDS_UNUSED(param1);
    BCDS_UNUSED(param2);
    //Retcode_T retcode = RETCODE_OK;


    SensorSetup.CmdProcessorHandle = AppCmdProcessor;
    Retcode_T retcode = Sensor_Setup(&SensorSetup);


    if (RETCODE_OK == retcode)
    {
    retcode = CmdProcessor_Enqueue(AppCmdProcessor, AppControllerEnable, NULL, UINT32_C(0));
    }

    if (RETCODE_OK != retcode)
    {
        printf("AppControllerSetup : Failed \r\n");
        Retcode_RaiseError(retcode);
        assert(0); /* To provide LED indication for the user */
    }
}

void AppController_Init(void * cmdProcessorHandle, uint32_t param2)
{
    BCDS_UNUSED(param2);

    Retcode_T retcode = RETCODE_OK;

    if (cmdProcessorHandle == NULL)
    {
        printf("AppController_Init : Command processor handle is NULL \r\n");
        retcode = RETCODE(RETCODE_SEVERITY_ERROR, RETCODE_NULL_POINTER);
    }
    else
    {


        AppCmdProcessor = (CmdProcessor_T *) cmdProcessorHandle;
        retcode = CmdProcessor_Enqueue(AppCmdProcessor, AppControllerSetup, NULL, UINT32_C(0));
    }

    if (RETCODE_OK != retcode)
    {
        Retcode_RaiseError(retcode);
        assert(0); /* To provide LED indication for the user */
    }
}

 

Vielen Dank schon mal!

 

 

 

0 (0 Votes)
RE: HTTPS GET Anfrage scheitert
Answer
17/01/19 15:21 as a reply to Till Lemmer.
Hallo Till,

Zuallererst, möchte ich dich herzlich in der XDK Community begrüßen. Bezüglich deines Problems kann es mehrere Möglichkeiten geben, weshalb eine HTTPS GET Anfrage nicht ausgeführt werden kann. Der Fehlercodes von sl_send() ist nicht aussagekräftig, da er lediglich besagt, dass die Nachricht nicht gesendet werden konnte.

Um die Fehlerquelle eingrenzen zu können, müsste zuerst der Fehlercode von sl_connect() überprüft werden. Dieser gibt Aufschluss darüber, ob eine verschlüsselte Verbindung aufgebaut werden konnte und unter anderem das Zertifikat richtig eingebunden wurde.

Daher empfehle ich diesen zu Beginn zu untersuchen.

Um weitere Fehlerquellen ausschließen zu können, empfehle ich auch zu überprüfen, ob die Länge 969 für das einzulesende Zertifikat korrekt ist. Diese erscheint mir zu identisch mit der angegebenen Länge für das GitHub Zertifikat aus dem HTTPS Guide. Ein falsch eingelesenes Zertifikat ist in den meisten Fällen die Ursache für eine nicht zustande kommende Verbindung.

Weiterhin habe ich bemerkt, dass du die HTTPS Anfrage aus einem Firmennetzwerk, welches Enterprise Wi-Fi nutzt, verwenden möchtest. Ist hierfür auch der entsprechende Serverport innerhalb der Firmen Firewall offen? Dies kann auch dazu führen, dass eine Verbindung über HTTPS nicht aufgebaut werden kann.

Als letzte mögliche Ursache empfehle ich den HTTPS Server zu dem die Anfrage gesendet werden soll auf seine zu unterstützenden Chiffrensammlung (Cipher Suite) zu überprüfen. Die HTTPS Simplelink Implementierung, welche du verwendet weißt nur eine geringe Anzahl von unterstützten Chiffrensammlung auf, welche im Interface socket.h im SDK gelistet werden. Du findest das Interface mit dem folgenden Ordnerpfad:

SDK > xdk110 > Libraries > WiFi > 3rd-party > TI > simplelink > include

Sofern die aufgelisteten Chiffrensammlung nicht von deinem HTTPS Server unterstützt werden, könnte dies auch eine Ursache für eine nicht zustande kommende Verbindung sein.

Ich hoffe, das hilft dir für den Anfang weiter. Bitte zögere nicht, falls du weiter Fragen hast diese zu stellen.

Mit freundlichen Grüßen,
Franjo



Dear XDK community,

Till is facing the issue that he is unable to send an HTTPS GET request with his own XDK application, which he build on the base of the HTTPS guide. He provided the sample code of his application and told me that he is receiving -1 as return code from the function sl_send() .

I told him that it might have multiple reasons why an HTTPS GET request can fail.

On the first occasion, I told him that he needs to check the return code of the function sl_connect() instead of the function sl_send() . This is necessary because the return code of sl_connect() is providing information about the actual connection to the HTTPS server as well as if the certificate has been loaded properly.

I noticed here that the length of his certificate is identical with the length of the GitHub certificate provided in the HTTPS guide. I told him to check this first since this is one of the most likely reasons a connection could not be established.

Furthermore, I noticed that he is using Enterprise Wi-Fi in his application, which is pointing to a corporate network. There the HTTPS port he is using might be blocked by a corporate firewall. I told him to check if the port is open within the corporate network.

As last reason, I mentioned checking if his HTTPS server is actually supporting the cipher suites the simplelink implementation HTTPS uses. I told him that he can get the list of available cipher suites from simplelink in the interface socket.h , which can be found in the following folderpath:

SDK > xdk110 > Libraries > WiFi > 3rd-party > TI > simplelink > include

Please let me know if this was helpful and feel free to ask if you have further questions.

Kind regards,
Franjo
+1 (1 Vote)
RE: HTTPS GET Anfrage scheitert
Answer
18/01/19 16:21 as a reply to Franjo Stjepandic.

Hallo Franjo,

Vielen Dank schon mal für die ausführliche Antwort.

 

Du hattest natürlich Recht, die Zertifikatslänge habe ich vergessen anzupassen. Diese beträgt 1814, aber nach der Korrektur bleibt das XDK in flashCertificate hängen. Ich nehme mal an, das hat damit zu tun, dass das Zertifikat länger als 1024 ist. Wie kann ich das Schreiben loopen, so wie es im HTTPS Guide angedeutet wird?

Bei fehlerhafter Angabe der Länge gibt sl_connect() -456 zurück, sofern meine Ausgabe korrekt ist. Im Code konnte ich leider nicht herausfinden, was das zu bedeuten hat.

 

EDIT: Ich habe nun den Loop aus https://xdk.bosch-connectivity.com/community/-/message_boards/message/349621 übernommen, jetzt gibt mir sl_connect() -155 zurück.

0 (0 Votes)
RE: HTTPS GET Anfrage scheitert
Answer
21/01/19 17:00 as a reply to Till Lemmer.
Hallo Till,

Der Fehlercode -456 verweist auf den define SL_ESECBADCAFILE welcher ein Indiz dafür ist, dass das Zertifikat nicht richtig geflashed wurde. Das liegt, wie du schon vermutest daran, dass die Zertifikatlänge größer als 1024 ist.

Du findest die Angaben der Fehlercodes der Simplelink API in der Headerdatei socket.h , zu der du über den folgenden Ordnerpfad gelangst:

SDK > xdk110 > Libraries > WiFi > 3rd-party > TI > simplelink > include

Weiterhin habe ich dir den folgenden relevanten Code Teilausschnitt angehängt, welches du verwenden kannst um Zertifikate mit einer länge größer als 1024 in den Wi-Fi Chip des XDKs flashen zu können.

 

_i32 fileHandle = 0;

sl_FsOpen((_u8*) fileName, FS_MODE_OPEN_CREATE(1024,
_FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ),NULL,&fileHandle);

_u32 remainingLength = length;
while(remainingLength > 0) {
remainingLength -= (_u32) sl_FsWrite(fileHandle, length - remainingLength,data+(length - remainingLength),
remainingLength > 1024 ? 1024 : remainingLength // equal to max(remainingLength, 1024)
);
}

sl_FsClose(fileHandle, NULL, NULL, 0);


Um diesen zu nutzen, ersetze einfach die bestehende Implementierung in der Funktion flashCertificate() ab dem Funktionsaufruf von sl_DevSet() durch den bereitgestellten Teilcode.

Im Anschluss sollte dein Zertifikat richtig geflasht werden.

Ich hoffe, das hilft dir weiter, falls du weitere Fragen hast, zögere nicht diese zu stellen.

Mit freundlichen Grüßen, Franjo Dear XDK community,

Till confirmed that the error he had with the failed HTTPS GET request was mainly caused by an incorrect certificate length in his implementation. As such, the certificate was not flashed properly.

Furthermore, he modified the length to 1814, which is the actual length of the certificate and is now facing the issue that the certificate is still not being flashed correctly to the XDKs Wi-Fi chip. This is caused by the fact, that he is used an implementation, which is only capable of flashing certificates to the XDKs Wi-Fi chip, which have maximum length of 1024.

Additionally, he checked the return code of the function sl_connect() , which is returning -456 .

I told him that the return code is corrsponding to SL_ESECBADCAFILE , which is indicating that the certificate was not flashed correctly. Furthermore, I told him that he can find a detailed list of the return codes of the simplelink API in the headerfile socket.h . The file can be found via the following folderpath:

SDK > xdk110 > Libraries > WiFi > 3rd-party > TI > simplelink > include

Additionally, I provided the following source code that can handle longer certificates, which can be exchanged with the existing implementation within the function flashCertificate() after the function call of sl_DevSet() .

 

_i32 fileHandle = 0;

sl_FsOpen((_u8*) fileName, FS_MODE_OPEN_CREATE(1024,
_FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ),NULL,&fileHandle);

_u32 remainingLength = length;
while(remainingLength > 0) {
remainingLength -= (_u32) sl_FsWrite(fileHandle, length - remainingLength,data+(length - remainingLength),
remainingLength > 1024 ? 1024 : remainingLength // equal to max(remainingLength, 1024)
);
}

sl_FsClose(fileHandle, NULL, NULL, 0);


Kind regards,
Franjo
0 (0 Votes)