Skip to content

Commit

Permalink
Merge pull request #371 from zowe/Jordan-branch
Browse files Browse the repository at this point in the history
Client Certificate Authentication with R_usermap
  • Loading branch information
JoeNemo authored Aug 11, 2023
2 parents 60382d1 + 28accac commit 18cd519
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 18 deletions.
84 changes: 70 additions & 14 deletions c/httpserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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->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
#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
Expand All @@ -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->flags & HTTP_REQUEST_NO_PASSWORD)) {
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
Expand Down Expand Up @@ -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",
Expand All @@ -3162,9 +3173,54 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest *
if (service->authExtractionFunction(service, request) == 0){
authDataFound = TRUE;
}
}
}

#define TLS_CLIENT_CERTIFICATE_MAX_LENGTH 65536

char *clientCertificate = safeMalloc(TLS_CLIENT_CERTIFICATE_MAX_LENGTH, "Client Certificate");
unsigned int clientCertificateLength = 0;

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);
}

#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_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_DEBUG, "Found user '%s' from client certificate.\n", request->username);
request->password = NULL;
request->flags = HTTP_REQUEST_NO_PASSWORD;
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);
}
} else {
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");
}
}


if (clientCertificate) {
safeFree(clientCertificate, TLS_CLIENT_CERTIFICATE_MAX_LENGTH);
clientCertificate = NULL;
}

response->sessionCookie = NULL;

AUTH_TRACE("AUTH: tokenCookieText: %s\n",(tokenCookieText ? tokenCookieText : "<noAuthToken>"));
Expand Down
50 changes: 46 additions & 4 deletions c/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,44 @@
#include "fdpoll.h"
#include "tls.h"

int getClientCertificate(gsk_handle soc_handle, char *clientCertificate, unsigned int clientCertificateBufferSize, unsigned int *clientCertificateLength) {

int rc = 0;

if (clientCertificate == NULL || clientCertificateBufferSize <= 0) {
return -1;
}

memset(clientCertificate, 0, clientCertificateBufferSize);
*clientCertificateLength = 0;

gsk_cert_data_elem *gskCertificateArray = NULL;
int gskCertificateArrayElementCount = 0;

rc = gsk_attribute_get_cert_info(soc_handle, GSK_PARTNER_CERT_INFO, &gskCertificateArray, &gskCertificateArrayElementCount);

if (rc != 0) {
return rc;
}

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 rc;
}

int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) {
int rc = 0;
TlsEnvironment *env = (TlsEnvironment *)safeMalloc(sizeof(*env), "Tls Environment");
Expand All @@ -29,6 +67,11 @@ 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);

#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

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);
Expand Down Expand Up @@ -94,9 +137,9 @@ static int secureSocketSend(int fd, void *data, int len, char *userData) {
}
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) {
Expand All @@ -109,8 +152,7 @@ int tlsSocketInit(TlsEnvironment *env, TlsSocket **outSocket, int fd, bool isSer
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 = 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);
Expand Down
1 change: 1 addition & 0 deletions h/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions h/tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down

0 comments on commit 18cd519

Please sign in to comment.