From c0da63b1fa1bfd2790d41b535256590a615b8ea9 Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Wed, 5 Apr 2023 11:25:46 -0500 Subject: [PATCH 1/6] testing certificate auth Signed-off-by: Jordan Filteau --- c/httpserver.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/c/httpserver.c b/c/httpserver.c index f88962e18..5c46ebbeb 100644 --- a/c/httpserver.c +++ b/c/httpserver.c @@ -3161,6 +3161,21 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * if (service->authExtractionFunction(service, request) == 0){ authDataFound = TRUE; + } else { + if (request->contentLength > 1) { + // certificate authentication + char userid[9] = {0}; + int mapReturnCode = 0, mapReasonCode = 0; + int rc = getUseridByCertificate(request->contentBody, request->contentLength, userid, &mapReturnCode, &mapReasonCode); + if (rc == 0) { + request->username = userid; + printf("Found user = %s\n", request->username); + request->password = NULL; + authDataFound = TRUE; + } else { + printf("No user found. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n"); + } + } } } } From ee4c9184e8d744d823024e678f3a8066568f1102 Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Wed, 5 Apr 2023 13:48:25 -0500 Subject: [PATCH 2/6] working certificate based authentication with R_usermap. Signed-off-by: Jordan Filteau --- c/httpserver.c | 73 +++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/c/httpserver.c b/c/httpserver.c index 5c46ebbeb..1d5280181 100644 --- a/c/httpserver.c +++ b/c/httpserver.c @@ -2653,19 +2653,23 @@ static int safAuthenticate(HttpService *service, HttpRequest *request, AuthRespo } else if (authDataFound){ ACEE *acee = NULL; strupcase(request->username); /* upfold username */ + if (request->password == NULL) { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "Password is null. Calling safAuthenticate without a password.\n"); + } else { #ifdef ENABLE_DANGEROUS_AUTH_TRACING #ifdef METTLE - printf("SAF auth for user: '%s'\n", request->username); + printf("SAF auth for user: '%s'\n", request->username); #else - printf("u: '%s' p: '%s'\n",request->username,request->password); + printf("u: '%s' p: '%s'\n",request->username,request->password); #endif #endif - if (isLowerCasePasswordAllowed() || isPassPhrase(request->password)) { - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "mixed-case system or a pass phrase, not upfolding password\n"); - /* don't upfold password */ - } else { - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "non-mixed-case system, not a pass phrase, upfolding password\n"); - strupcase(request->password); /* upfold password */ + if (isLowerCasePasswordAllowed() || isPassPhrase(request->password)) { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "mixed-case system or a pass phrase, not upfolding password\n"); + /* don't upfold password */ + } else { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "non-mixed-case system, not a pass phrase, upfolding password\n"); + strupcase(request->password); /* upfold password */ + } } #if APF_AUTHORIZED @@ -2675,10 +2679,17 @@ static int safAuthenticate(HttpService *service, HttpRequest *request, AuthRespo CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); int pwdCheckRC = 0, pwdCheckRSN = 0; - pwdCheckRC = zisCheckUsernameAndPassword(privilegedServerName, - request->username, request->password, &status); - authResponse->type = AUTH_TYPE_RACF; - authResponse->responseDetails.safStatus = status.safStatus; + if (request->password != NULL) { + pwdCheckRC = zisCheckUsernameAndPassword(privilegedServerName, + request->username, request->password, &status); + authResponse->type = AUTH_TYPE_RACF; + authResponse->responseDetails.safStatus = status.safStatus; + } else { + pwdCheckRC = zisCheckUsername(privilegedServerName, + request->username, &status); + authResponse->type = AUTH_TYPE_RACF; + authResponse->responseDetails.safStatus = status.safStatus; + } if (pwdCheckRC != 0) { #ifdef DEBUG_AUTH @@ -3142,7 +3153,7 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * int authDataFound = FALSE; HttpHeader *authenticationHeader = getHeader(request,"Authorization"); char *tokenCookieText = getCookieValue(request,getSessionTokenCookieName(service)); - + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "serviceAuthNativeWithSessionToken: authenticationHeader 0x%p\n", "extractFunction 0x%p\n", @@ -3161,22 +3172,30 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * if (service->authExtractionFunction(service, request) == 0){ authDataFound = TRUE; + } + } + } + + char userid[9] = {0}; + int mapReturnCode = 0, mapReasonCode = 0; + int rc = 0; + + if (authDataFound == FALSE) { + if (request->contentLength > 1) { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There was no token found or credentials in the request. Attempting certificate authentication.\n"); + int rc = getUseridByCertificate(request->contentBody, request->contentLength, userid, &mapReturnCode, &mapReasonCode); + if (rc == 0) { + request->username = userid; + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "Found user = %s\n", request->username); + request->password = NULL; + // null password with a valid user tells the server we authenticated with a certificate + authDataFound = TRUE; } else { - if (request->contentLength > 1) { - // certificate authentication - char userid[9] = {0}; - int mapReturnCode = 0, mapReasonCode = 0; - int rc = getUseridByCertificate(request->contentBody, request->contentLength, userid, &mapReturnCode, &mapReasonCode); - if (rc == 0) { - request->username = userid; - printf("Found user = %s\n", request->username); - request->password = NULL; - authDataFound = TRUE; - } else { - printf("No user found. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n"); - } - } + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, + "No user found. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n", rc, mapReturnCode, mapReasonCode); } + } else { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There is no certificate in the request body. Not attempting certificate authentication.\n"); } } From 0d82a1c4ff6fd7e1fe6b2f7b2eff9c0bbd96e41f Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Mon, 10 Apr 2023 15:47:22 -0500 Subject: [PATCH 3/6] grabbing cert from tls handshake Signed-off-by: Jordan Filteau --- c/httpserver.c | 47 ++++++++++++++++++++++++----------- c/tls.c | 67 +++++++++++++++++++++++++++++++++++++++++++++----- h/tls.h | 1 + 3 files changed, 95 insertions(+), 20 deletions(-) diff --git a/c/httpserver.c b/c/httpserver.c index 1d5280181..ef4fba1c2 100644 --- a/c/httpserver.c +++ b/c/httpserver.c @@ -3172,33 +3172,52 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * if (service->authExtractionFunction(service, request) == 0){ authDataFound = TRUE; - } + } } } - char userid[9] = {0}; - int mapReturnCode = 0, mapReasonCode = 0; - int rc = 0; + /* Doubtful that it would be greater than 8k... */ + +#define TLS_CLIENT_CERTIFICATE_MAX_LENGTH 8000 + + char clientCertificate[TLS_CLIENT_CERTIFICATE_MAX_LENGTH] = {0}; + unsigned int clientCertificateLength = 0; - if (authDataFound == FALSE) { - if (request->contentLength > 1) { - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There was no token found or credentials in the request. Attempting certificate authentication.\n"); - int rc = getUseridByCertificate(request->contentBody, request->contentLength, userid, &mapReturnCode, &mapReasonCode); - if (rc == 0) { + int rc = getClientCertificate(response->socket->tlsSocket->socketHandle, clientCertificate, sizeof(clientCertificate), &clientCertificateLength); + if (rc != 0) { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "getClientCertificate - %d.\n", rc); + } + +#ifdef ENABLE_DANGEROUS_AUTH_TRACING + /* We probably don't want to dump their certificate, right? */ + dumpbuffer(clientCertificate, clientCertificateLength); +#endif + + if (rc == 0 && clientCertificateLength > 0) { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "There is a client certificate attached to the request.\n"); + /* + * We don't want to do this if we already found authentication data. + */ + if (authDataFound == FALSE) { +#define TLS_USERID_LENGTH 9 + char userid[TLS_USERID_LENGTH] = {0}; + int racfReturnCode = 0, racfReasonCode = 0; + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There was no token or credentials found in the request. Server is attempting to map the client certificate.\n"); + int safReturnCode = getUseridByCertificate(clientCertificate, clientCertificateLength, userid, &racfReturnCode, &racfReasonCode); + if (safReturnCode == 0) { request->username = userid; - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "Found user = %s\n", request->username); + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "Found user '%s' from client certificate.\n", request->username); request->password = NULL; // null password with a valid user tells the server we authenticated with a certificate authDataFound = TRUE; } else { - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, - "No user found. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n", rc, mapReturnCode, mapReasonCode); + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "No user was found for client certificate. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n", safReturnCode, racfReturnCode, racfReasonCode); } } else { - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There is no certificate in the request body. Not attempting certificate authentication.\n"); + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "Client certificate was attached to request, but credentials are also attached. Server won't attempt to map the client certificate.\n"); } } - + response->sessionCookie = NULL; AUTH_TRACE("AUTH: tokenCookieText: %s\n",(tokenCookieText ? tokenCookieText : "")); diff --git a/c/tls.c b/c/tls.c index 44a98aec3..cedf4801c 100644 --- a/c/tls.c +++ b/c/tls.c @@ -15,6 +15,40 @@ #include "fdpoll.h" #include "tls.h" +int getClientCertificate(gsk_handle soc_handle, char *clientCertificate, unsigned int clientCertificateBufferSize, unsigned int *clientCertificateLength) { + + if (clientCertificate == NULL || clientCertificateBufferSize <= 0) { + return -1; + } + + memset(clientCertificate, 0, clientCertificateBufferSize); + *clientCertificateLength = 0; + + gsk_cert_data_elem *gskCertificateArray = NULL; + int gskCertificateArrayElementCount = 0; + + int rc = gsk_attribute_get_cert_info(soc_handle, GSK_PARTNER_CERT_INFO, &gskCertificateArray, &gskCertificateArrayElementCount); + + if (rc != 0) { + return rc; + } + + gsk_cert_data_elem *tmp = gskCertificateArray; + + for (int i = 0; i++ < gskCertificateArrayElementCount; tmp++) { + if (tmp->cert_data_id == CERT_BODY_DER) { + if (clientCertificateBufferSize >= tmp->cert_data_l) { + memcpy(clientCertificate, tmp->cert_data_p, tmp->cert_data_l); + *clientCertificateLength = tmp->cert_data_l; + } + } + } + + gsk_free_cert_data(gskCertificateArray, gskCertificateArrayElementCount); + + return 0; +} + int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { int rc = 0; TlsEnvironment *env = (TlsEnvironment *)safeMalloc(sizeof(*env), "Tls Environment"); @@ -29,6 +63,23 @@ int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_PROTOCOL_TLSV1_1, GSK_PROTOCOL_TLSV1_1_OFF); rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_PROTOCOL_TLSV1_2, GSK_PROTOCOL_TLSV1_2_ON); rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_SERVER_EPHEMERAL_DH_GROUP_SIZE, GSK_SERVER_EPHEMERAL_DH_GROUP_SIZE_2048); + + /* + * Don't validate certificates, maybe put behind a dangerous ifdef. + * + * rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_TYPE, GSK_CLIENT_AUTH_PASSTHRU_TYPE); + */ + +#ifdef DEV_DO_NOT_VALIDATE_CLIENT_CERTIFICATES + rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_TYPE, GSK_CLIENT_AUTH_PASSTHRU_TYPE); +#endif + + /* + * Only allow requests with client certificates, maybe put behind a different ifdef. + * + * rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_ALERT, GSK_CLIENT_AUTH_NOCERT_ALERT_ON); + */ + rc = rc || gsk_attribute_set_buffer(env->envHandle, GSK_KEYRING_FILE, settings->keyring, 0); if (settings->stash) { rc = rc || gsk_attribute_set_buffer(env->envHandle, GSK_KEYRING_STASH_FILE, settings->stash, 0); @@ -43,6 +94,7 @@ int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { safeFree((char*)env, sizeof(*env)); *outEnv = NULL; } + //printf("tlsInit - rc=%d\n", rc); return rc; } @@ -50,6 +102,7 @@ int tlsDestroy(TlsEnvironment *env) { int rc = 0; rc = gsk_environment_close(env->envHandle); safeFree((char*)env, sizeof(*env)); + //printf("tlsDestroy - rc=%d\n", rc); return rc; } @@ -72,6 +125,7 @@ static int secureSocketRecv(int fd, void *data, int len, char *userData) { break; } } + //printf("secureSocketRecv = %d\n", rc); return rc; } @@ -92,11 +146,12 @@ static int secureSocketSend(int fd, void *data, int len, char *userData) { break; } } + //printf("secureSocketSend = %d\n", rc); return rc; } - + int tlsSocketInit(TlsEnvironment *env, TlsSocket **outSocket, int fd, bool isServer) { - int rc = 0; + int rc = 0; gsk_iocallback ioCallbacks = {secureSocketRecv, secureSocketSend, NULL, NULL, NULL, NULL}; TlsSocket *socket = (TlsSocket*)safeMalloc(sizeof(TlsSocket), "Tls Socket"); if (!socket) { @@ -104,25 +159,25 @@ int tlsSocketInit(TlsEnvironment *env, TlsSocket **outSocket, int fd, bool isSer } char *label = env->settings->label; char *ciphers = env->settings->ciphers; - rc = rc || gsk_secure_socket_open(env->envHandle, &socket->socketHandle); + rc = gsk_secure_socket_open(env->envHandle, &socket->socketHandle); rc = rc || gsk_attribute_set_numeric_value(socket->socketHandle, GSK_FD, fd); if (label) { rc = rc || gsk_attribute_set_buffer(socket->socketHandle, GSK_KEYRING_LABEL, label, 0); } - rc = rc || gsk_attribute_set_enum(socket->socketHandle, GSK_SESSION_TYPE, - isServer ? GSK_SERVER_SESSION : GSK_CLIENT_SESSION); + rc = gsk_attribute_set_enum(socket->socketHandle, GSK_SESSION_TYPE, isServer ? GSK_SERVER_SESSION_WITH_CL_AUTH : GSK_CLIENT_SESSION); if (ciphers) { rc = rc || gsk_attribute_set_buffer(socket->socketHandle, GSK_V3_CIPHER_SPECS_EXPANDED, ciphers, 0); rc = rc || gsk_attribute_set_enum(socket->socketHandle, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4); } rc = rc || gsk_attribute_set_callback(socket->socketHandle, GSK_IO_CALLBACK, &ioCallbacks); - rc = rc || gsk_secure_socket_init(socket->socketHandle); + rc = gsk_secure_socket_init(socket->socketHandle); if (rc == 0) { *outSocket = socket; } else { safeFree((char*)socket, sizeof(*socket)); *outSocket = NULL; } + //printf("tlsSocketInit - rc=%d\n", rc); return rc; } diff --git a/h/tls.h b/h/tls.h index 47ec2935d..f1f9bd59f 100644 --- a/h/tls.h +++ b/h/tls.h @@ -140,6 +140,7 @@ int tlsSocketClose(TlsSocket *socket); int tlsRead(TlsSocket *socket, const char *buf, int size, int *outLength); int tlsWrite(TlsSocket *socket, const char *buf, int size, int *outLength); const char *tlsStrError(int rc); +int getClientCertificate(gsk_handle soc_handle, char *clientCertificate, unsigned int clientCertificateBufferSize, unsigned int *clientCertificateLength); #define TLS_ALLOC_ERROR (-1) From 31fe0d327dd4f4630dfd295726cda7e8e8f1ff68 Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Mon, 10 Apr 2023 15:52:22 -0500 Subject: [PATCH 4/6] reverting unintentional changes Signed-off-by: Jordan Filteau --- c/tls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/c/tls.c b/c/tls.c index cedf4801c..25a3ee31a 100644 --- a/c/tls.c +++ b/c/tls.c @@ -159,18 +159,18 @@ int tlsSocketInit(TlsEnvironment *env, TlsSocket **outSocket, int fd, bool isSer } char *label = env->settings->label; char *ciphers = env->settings->ciphers; - rc = gsk_secure_socket_open(env->envHandle, &socket->socketHandle); + rc = rc || gsk_secure_socket_open(env->envHandle, &socket->socketHandle); rc = rc || gsk_attribute_set_numeric_value(socket->socketHandle, GSK_FD, fd); if (label) { rc = rc || gsk_attribute_set_buffer(socket->socketHandle, GSK_KEYRING_LABEL, label, 0); } - rc = gsk_attribute_set_enum(socket->socketHandle, GSK_SESSION_TYPE, isServer ? GSK_SERVER_SESSION_WITH_CL_AUTH : GSK_CLIENT_SESSION); + rc = rc || gsk_attribute_set_enum(socket->socketHandle, GSK_SESSION_TYPE, isServer ? GSK_SERVER_SESSION_WITH_CL_AUTH : GSK_CLIENT_SESSION); if (ciphers) { rc = rc || gsk_attribute_set_buffer(socket->socketHandle, GSK_V3_CIPHER_SPECS_EXPANDED, ciphers, 0); rc = rc || gsk_attribute_set_enum(socket->socketHandle, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4); } rc = rc || gsk_attribute_set_callback(socket->socketHandle, GSK_IO_CALLBACK, &ioCallbacks); - rc = gsk_secure_socket_init(socket->socketHandle); + rc = rc || gsk_secure_socket_init(socket->socketHandle); if (rc == 0) { *outSocket = socket; } else { From 43802703c337b537c9f3d8d171883298fe5b9dcc Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Fri, 11 Aug 2023 15:31:41 -0500 Subject: [PATCH 5/6] using a flag to determine type of saf verify; removing dead code in tls.c; simplying logic for loop in tls.c Signed-off-by: Jordan Filteau --- c/httpserver.c | 9 +++++---- c/tls.c | 31 +++++++++---------------------- h/http.h | 1 + 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/c/httpserver.c b/c/httpserver.c index ef4fba1c2..a841f1c0b 100644 --- a/c/httpserver.c +++ b/c/httpserver.c @@ -2653,7 +2653,7 @@ static int safAuthenticate(HttpService *service, HttpRequest *request, AuthRespo } else if (authDataFound){ ACEE *acee = NULL; strupcase(request->username); /* upfold username */ - if (request->password == NULL) { + if (!(request->flags & HTTP_REQUEST_NO_PASSWORD)) { zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "Password is null. Calling safAuthenticate without a password.\n"); } else { #ifdef ENABLE_DANGEROUS_AUTH_TRACING @@ -2679,7 +2679,7 @@ static int safAuthenticate(HttpService *service, HttpRequest *request, AuthRespo CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); int pwdCheckRC = 0, pwdCheckRSN = 0; - if (request->password != NULL) { + if (!(request->flags & HTTP_REQUEST_NO_PASSWORD)) { pwdCheckRC = zisCheckUsernameAndPassword(privilegedServerName, request->username, request->password, &status); authResponse->type = AUTH_TYPE_RACF; @@ -3202,12 +3202,13 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * #define TLS_USERID_LENGTH 9 char userid[TLS_USERID_LENGTH] = {0}; int racfReturnCode = 0, racfReasonCode = 0; - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There was no token or credentials found in the request. Server is attempting to map the client certificate.\n"); + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "There was no token or credentials found in the request. Server is attempting to map the client certificate.\n"); int safReturnCode = getUseridByCertificate(clientCertificate, clientCertificateLength, userid, &racfReturnCode, &racfReasonCode); if (safReturnCode == 0) { request->username = userid; - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "Found user '%s' from client certificate.\n", request->username); + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "Found user '%s' from client certificate.\n", request->username); request->password = NULL; + request->flags = HTTP_REQUEST_NO_PASSWORD; // null password with a valid user tells the server we authenticated with a certificate authDataFound = TRUE; } else { diff --git a/c/tls.c b/c/tls.c index 25a3ee31a..2264d2da2 100644 --- a/c/tls.c +++ b/c/tls.c @@ -17,6 +17,8 @@ int getClientCertificate(gsk_handle soc_handle, char *clientCertificate, unsigned int clientCertificateBufferSize, unsigned int *clientCertificateLength) { + int rc = 0; + if (clientCertificate == NULL || clientCertificateBufferSize <= 0) { return -1; } @@ -27,26 +29,28 @@ int getClientCertificate(gsk_handle soc_handle, char *clientCertificate, unsigne gsk_cert_data_elem *gskCertificateArray = NULL; int gskCertificateArrayElementCount = 0; - int rc = gsk_attribute_get_cert_info(soc_handle, GSK_PARTNER_CERT_INFO, &gskCertificateArray, &gskCertificateArrayElementCount); + rc = gsk_attribute_get_cert_info(soc_handle, GSK_PARTNER_CERT_INFO, &gskCertificateArray, &gskCertificateArrayElementCount); if (rc != 0) { return rc; } - gsk_cert_data_elem *tmp = gskCertificateArray; - - for (int i = 0; i++ < gskCertificateArrayElementCount; tmp++) { + for (int i = 0; i < gskCertificateArrayElementCount; i++) { + gsk_cert_data_elem *tmp = &gskCertificateArray[i]; if (tmp->cert_data_id == CERT_BODY_DER) { if (clientCertificateBufferSize >= tmp->cert_data_l) { memcpy(clientCertificate, tmp->cert_data_p, tmp->cert_data_l); *clientCertificateLength = tmp->cert_data_l; + } else { + rc = -1; /* tls rc are all positive */ } + break; } } gsk_free_cert_data(gskCertificateArray, gskCertificateArrayElementCount); - return 0; + return rc; } int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { @@ -64,22 +68,10 @@ int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_PROTOCOL_TLSV1_2, GSK_PROTOCOL_TLSV1_2_ON); rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_SERVER_EPHEMERAL_DH_GROUP_SIZE, GSK_SERVER_EPHEMERAL_DH_GROUP_SIZE_2048); - /* - * Don't validate certificates, maybe put behind a dangerous ifdef. - * - * rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_TYPE, GSK_CLIENT_AUTH_PASSTHRU_TYPE); - */ - #ifdef DEV_DO_NOT_VALIDATE_CLIENT_CERTIFICATES rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_TYPE, GSK_CLIENT_AUTH_PASSTHRU_TYPE); #endif - /* - * Only allow requests with client certificates, maybe put behind a different ifdef. - * - * rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_ALERT, GSK_CLIENT_AUTH_NOCERT_ALERT_ON); - */ - rc = rc || gsk_attribute_set_buffer(env->envHandle, GSK_KEYRING_FILE, settings->keyring, 0); if (settings->stash) { rc = rc || gsk_attribute_set_buffer(env->envHandle, GSK_KEYRING_STASH_FILE, settings->stash, 0); @@ -94,7 +86,6 @@ int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { safeFree((char*)env, sizeof(*env)); *outEnv = NULL; } - //printf("tlsInit - rc=%d\n", rc); return rc; } @@ -102,7 +93,6 @@ int tlsDestroy(TlsEnvironment *env) { int rc = 0; rc = gsk_environment_close(env->envHandle); safeFree((char*)env, sizeof(*env)); - //printf("tlsDestroy - rc=%d\n", rc); return rc; } @@ -125,7 +115,6 @@ static int secureSocketRecv(int fd, void *data, int len, char *userData) { break; } } - //printf("secureSocketRecv = %d\n", rc); return rc; } @@ -146,7 +135,6 @@ static int secureSocketSend(int fd, void *data, int len, char *userData) { break; } } - //printf("secureSocketSend = %d\n", rc); return rc; } @@ -177,7 +165,6 @@ int tlsSocketInit(TlsEnvironment *env, TlsSocket **outSocket, int fd, bool isSer safeFree((char*)socket, sizeof(*socket)); *outSocket = NULL; } - //printf("tlsSocketInit - rc=%d\n", rc); return rc; } diff --git a/h/http.h b/h/http.h index b46114ab3..f7462c7c6 100644 --- a/h/http.h +++ b/h/http.h @@ -126,6 +126,7 @@ typedef struct HttpRequest_tag{ Socket *socket; BufferedInputStream *input; int flags; +#define HTTP_REQUEST_NO_PASSWORD 0x01 int characterEncoding; int contentLength; /* -1 if unknown */ char *contentType; From 28accacb730d50f0a431eeacc3bc5f9e4c90e7a0 Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Fri, 11 Aug 2023 15:39:08 -0500 Subject: [PATCH 6/6] using a bigger buffer for client certificate. Signed-off-by: Jordan Filteau --- c/httpserver.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/c/httpserver.c b/c/httpserver.c index a841f1c0b..729988432 100644 --- a/c/httpserver.c +++ b/c/httpserver.c @@ -3176,14 +3176,12 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * } } - /* Doubtful that it would be greater than 8k... */ +#define TLS_CLIENT_CERTIFICATE_MAX_LENGTH 65536 -#define TLS_CLIENT_CERTIFICATE_MAX_LENGTH 8000 - - char clientCertificate[TLS_CLIENT_CERTIFICATE_MAX_LENGTH] = {0}; + char *clientCertificate = safeMalloc(TLS_CLIENT_CERTIFICATE_MAX_LENGTH, "Client Certificate"); unsigned int clientCertificateLength = 0; - int rc = getClientCertificate(response->socket->tlsSocket->socketHandle, clientCertificate, sizeof(clientCertificate), &clientCertificateLength); + int rc = getClientCertificate(response->socket->tlsSocket->socketHandle, clientCertificate, TLS_CLIENT_CERTIFICATE_MAX_LENGTH, &clientCertificateLength); if (rc != 0) { zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "getClientCertificate - %d.\n", rc); } @@ -3209,7 +3207,6 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "Found user '%s' from client certificate.\n", request->username); request->password = NULL; request->flags = HTTP_REQUEST_NO_PASSWORD; - // null password with a valid user tells the server we authenticated with a certificate authDataFound = TRUE; } else { zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "No user was found for client certificate. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n", safReturnCode, racfReturnCode, racfReasonCode); @@ -3219,6 +3216,11 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * } } + if (clientCertificate) { + safeFree(clientCertificate, TLS_CLIENT_CERTIFICATE_MAX_LENGTH); + clientCertificate = NULL; + } + response->sessionCookie = NULL; AUTH_TRACE("AUTH: tokenCookieText: %s\n",(tokenCookieText ? tokenCookieText : ""));