Skip to content

Commit

Permalink
Merge pull request #447 from achmelo/staging
Browse files Browse the repository at this point in the history
Support for SAF IDT
  • Loading branch information
JoeNemo authored May 11, 2022
2 parents 2ec7100 + 253edeb commit f64143e
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 57 deletions.
16 changes: 10 additions & 6 deletions c/safIdtService.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Json *parseContentBody(HttpRequest *request) {
static int authenticate(HttpResponse *response, CrossMemoryServerName *privilegedServerName) {

ZISAuthServiceStatus status = {0};
char safIdt[ZIS_AUTH_SERVICE_PARMLIST_SAFIDT_LENGTH + 1] = {0};
char safIdt[ZIS_AUTH_SERVICE_SAFIDT_LENGTH + 1] = {0};
HttpRequest *request = response->request;

Json *body = parseContentBody(request);
Expand All @@ -63,6 +63,7 @@ static int authenticate(HttpResponse *response, CrossMemoryServerName *privilege
JsonObject *jsonObject = jsonAsObject(body);
char *username = jsonObjectGetString(jsonObject, "username");
char *pass = jsonObjectGetString(jsonObject, "pass");
char *appl = jsonObjectGetString(jsonObject, "appl");

if (username == NULL || strlen(username) == 0) {
respondWithJsonStatus(response, "No username provided", HTTP_STATUS_BAD_REQUEST, "Bad Request");
Expand All @@ -80,8 +81,9 @@ static int authenticate(HttpResponse *response, CrossMemoryServerName *privilege
strupcase(pass); /* upfold password */
}

int zisRC = zisGenerateOrValidateSafIdt(privilegedServerName, username,
int zisRC = zisGenerateOrValidateSafIdtWithAppl(privilegedServerName, username,
pass,
appl,
safIdt,
&status);

Expand Down Expand Up @@ -208,7 +210,7 @@ void extractUsernameFromJwt(HttpResponse *response, char *jwt, char *username) {
static int verify(HttpResponse *response, CrossMemoryServerName *privilegedServerName) {

ZISAuthServiceStatus status = {0};
char safIdt[ZIS_AUTH_SERVICE_PARMLIST_SAFIDT_LENGTH + 1] = {0};
char safIdt[ZIS_AUTH_SERVICE_SAFIDT_LENGTH + 1] = {0};
char username[9] = {0};
HttpRequest *request = response->request;

Expand All @@ -220,14 +222,15 @@ static int verify(HttpResponse *response, CrossMemoryServerName *privilegedServe

JsonObject *jsonObject = jsonAsObject(body);
char *jwt = jsonObjectGetString(jsonObject, "jwt");
char *appl = jsonObjectGetString(jsonObject, "appl");

if (jwt == NULL || strlen(jwt) == 0) {
respondWithJsonStatus(response, "No jwt provided", HTTP_STATUS_BAD_REQUEST, "Bad Request");
return HTTP_SERVICE_FAILED;
}

if (strlen(jwt) > ZIS_AUTH_SERVICE_PARMLIST_SAFIDT_LENGTH) {
respondWithJsonStatus(response, "JWT size exceeds length of "STRINGIFY(ZIS_AUTH_SERVICE_PARMLIST_SAFIDT_LENGTH),
if (strlen(jwt) > ZIS_AUTH_SERVICE_SAFIDT_LENGTH) {
respondWithJsonStatus(response, "JWT size exceeds length of "STRINGIFY(ZIS_AUTH_SERVICE_SAFIDT_LENGTH),
HTTP_STATUS_BAD_REQUEST, "Bad Request");
return HTTP_SERVICE_FAILED;
}
Expand All @@ -242,8 +245,9 @@ static int verify(HttpResponse *response, CrossMemoryServerName *privilegedServe
extractUsernameFromJwt(response, jwt, username);
zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "extracted username is: %s\n", username);

int zisRC = zisGenerateOrValidateSafIdt(privilegedServerName, username,
int zisRC = zisGenerateOrValidateSafIdtWithAppl(privilegedServerName, username,
"",
appl,
safIdt,
&status);

Expand Down
50 changes: 39 additions & 11 deletions c/zis/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,19 @@ static int authRequest(const CrossMemoryServerName *serverName,
}

/*
* safIdt - a buffer for SAF IDT token. The buffer must be ZIS_AUTH_SERVICE_PARMLIST_SAFIDT_LENGTH + 1 bytes long.
* safIdt - a buffer for SAF IDT token. The buffer must be ZIS_AUTH_SERVICE_SAFIDT_LENGTH + 1 bytes long.
* appl - application name to be included in the audience claim of SAF IDT. It is an optional parameter and can be null.
*/
int zisGenerateOrValidateSafIdt(const CrossMemoryServerName *serverName,
int zisGenerateOrValidateSafIdtWithAppl(const CrossMemoryServerName *serverName,
const char *userName, const char *password,
const char *safIdt,
const char *appl,
char *safIdt,
ZISAuthServiceStatus *status) {
AuthServiceParmList parmList = {0};

memcpy(&parmList.eyecatcher[0], ZIS_AUTH_SERVICE_PARMLIST_EYECATCHER,
sizeof(parmList.eyecatcher));
parmList.fc = ZIS_AUTH_SERVICE_PARMLIST_FC_VERIFY_PASSWORD;
parmList.fc = ZIS_AUTH_SERVICE_PARMLIST_FC_GENERATE_TOKEN;

if (strlen(userName) >= sizeof (parmList.userIDNullTerm)) {
status->baseStatus.serviceRC = RC_ZIS_AUTHSRV_INPUT_STRING_TOO_LONG;
Expand All @@ -162,25 +164,51 @@ int zisGenerateOrValidateSafIdt(const CrossMemoryServerName *serverName,
}
strncpy(parmList.passwordNullTerm, password, sizeof(parmList.passwordNullTerm));

parmList.options |= ZIS_AUTH_SERVICE_PARMLIST_OPTION_GENERATE_IDT;
parmList.safIdtLen = strlen(safIdt);
if (appl != NULL && strlen(appl) != 0) {
if (strlen(appl) >= sizeof (parmList.safIdtService.applNullTerm)) {
status->baseStatus.serviceRC = RC_ZIS_AUTHSRV_INPUT_STRING_TOO_LONG;
return RC_ZIS_SRVC_SERVICE_FAILED;
}
strcpy(parmList.safIdtService.applNullTerm, appl);

parmList.safIdtService.options |= ZIS_AUTH_SERVICE_SAFIDT_OPTION_IDT_APPL;
}

if (strlen(safIdt) >= sizeof(parmList.safIdt)) {
parmList.safIdtService.safIdtLen = strlen(safIdt);
parmList.safIdtService.safIdtServiceVersion = 1;
if (strlen(safIdt) >= sizeof(parmList.safIdtService.safIdt)) {
status->baseStatus.serviceRC = RC_ZIS_AUTHSRV_INPUT_STRING_TOO_LONG;
return RC_ZIS_SRVC_SERVICE_FAILED;
}
memcpy((void *)parmList.safIdt, (void *)safIdt, strlen(safIdt));
memcpy((void *)parmList.safIdtService.safIdt, safIdt, strlen(safIdt));

int rc = authRequest(serverName, &parmList, status);

if (parmList.safIdtLen > 0) {
memset((void *)safIdt, 0, ZIS_AUTH_SERVICE_PARMLIST_SAFIDT_LENGTH + 1);
memcpy((void *)safIdt, (void *)parmList.safIdt, parmList.safIdtLen);
if (parmList.safIdtService.safIdtLen > 0) {
memset(safIdt, 0, ZIS_AUTH_SERVICE_SAFIDT_LENGTH + 1);
memcpy(safIdt, (void *)parmList.safIdtService.safIdt, parmList.safIdtService.safIdtLen);
}

return rc;
}

/*
* safIdt - a buffer for SAF IDT token. The buffer must be ZIS_AUTH_SERVICE_SAFIDT_LENGTH + 1 bytes long.
*/
int zisGenerateOrValidateSafIdt(const CrossMemoryServerName *serverName,
const char *userName, const char *password,
char *safIdt,
ZISAuthServiceStatus *status) {

return zisGenerateOrValidateSafIdtWithAppl(serverName,
userName,
password,
NULL,
safIdt,
status
);
}

int zisCheckUsernameAndPassword(const CrossMemoryServerName *serverName,
const char *userName, const char *password,
ZISAuthServiceStatus *status) {
Expand Down
100 changes: 68 additions & 32 deletions c/zis/services/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,48 +35,84 @@ static int handleVerifyPassword(AuthServiceParmList *parmList,
int safRC = 0, racfRC = 0, racfRsn = 0;
int deleteSAFRC = 0, deleteRACFRC = 0, deleteRACFRsn = 0;
int rc = RC_ZIS_AUTHSRV_OK;
IDTA *idta = NULL;
int options = VERIFY_CREATE;

if (parmList->options & ZIS_AUTH_SERVICE_PARMLIST_OPTION_GENERATE_IDT) {
idta = (IDTA *) safeMalloc31(sizeof(IDTA), "Idta structure");
memset(idta, 0, sizeof(IDTA));
memcpy(idta->id, "IDTA", 4);
idta->version = IDTA_VERSION_0001;
idta->length = sizeof(IDTA);
idta->idtType = IDTA_JWT_IDT_Type;
idta->idtBufferPtr = parmList->safIdt;
idta->idtBufferLen = sizeof(parmList->safIdt);
idta->idtLen = parmList->safIdtLen;
idta->idtPropIn = IDTA_End_User_IDT;
options |= VERIFY_GENERATE_IDT;
}

CMS_DEBUG(globalArea, "handleVerifyPassword(): username = %s, password = %s\n",
parmList->userIDNullTerm, "******");
if (idta == NULL) {
safRC = safVerify(VERIFY_CREATE, parmList->userIDNullTerm,
parmList->passwordNullTerm, &acee, &racfRC, &racfRsn);

if (parmList->_padding0[0] & ZIS_AUTH_SERVICE_SAFIDT_OPTION_RESERVED) {
return RC_ZIS_AUTHSRV_BAD_SAF_SERVICE_VERSION;
}

safRC = safVerify(VERIFY_CREATE, parmList->userIDNullTerm,
parmList->passwordNullTerm, &acee, &racfRC, &racfRsn);

CMS_DEBUG(globalArea, "safVerify(VERIFY_CREATE) safStatus = %d, RACF RC = %d, "
"RSN = %d, ACEE=0x%p\n", safRC, racfRC, racfRsn, acee);

if (safRC != 0) {
rc = RC_ZIS_AUTHSRV_SAF_ERROR;
goto acee_deleted;
}
deleteSAFRC = safVerify(VERIFY_DELETE, NULL, NULL, &acee, &deleteRACFRC,
&deleteRACFRsn);
CMS_DEBUG(globalArea, "safVerify(VERIFY_DELETE) safStatus = %d, RACF RC = %d, "
"RSN = %d, ACEE=0x%p\n", deleteSAFRC, deleteRACFRC, deleteRACFRsn,
acee);
if (deleteSAFRC != 0) {
rc = RC_ZIS_AUTHSRV_DELETE_FAILED;
}
acee_deleted:

FILL_SAF_STATUS(&parmList->safStatus, safRC, racfRC, racfRsn);
CMS_DEBUG(globalArea, "handleVerifyPassword() done\n");
return rc;
}

static int handleGenerateToken(AuthServiceParmList *parmList,
const CrossMemoryServerGlobalArea *globalArea) {
if(parmList->safIdtService.safIdtServiceVersion > ZIS_SAF_IDT_SERVICE_CURRENT_VERSION) {
return RC_ZIS_AUTHSRV_BAD_SAF_SERVICE_VERSION;
}
ACEE *acee = NULL;
int safRC = 0, racfRC = 0, racfRsn = 0;
int deleteSAFRC = 0, deleteRACFRC = 0, deleteRACFRsn = 0;
int rc = RC_ZIS_AUTHSRV_OK;
int options = VERIFY_CREATE;

IDTA idtaVar;
memset(&idtaVar, 0, sizeof(idtaVar));
idtaVar.version = IDTA_VERSION_0001;
idtaVar.length = sizeof(IDTA);
idtaVar.idtBufferPtr = parmList->safIdtService.safIdt;
idtaVar.idtBufferLen = sizeof(parmList->safIdtService.safIdt);
idtaVar.idtLen = parmList->safIdtService.safIdtLen;
idtaVar.idtType = IDTA_JWT_IDT_Type;
idtaVar.idtPropIn = IDTA_End_User_IDT;
memcpy(idtaVar.id, "IDTA", 4);
IDTA *idta = &idtaVar;

CMS_DEBUG(globalArea, "handleGenerateToken(): username = %s, password = %s\n",
parmList->userIDNullTerm, "******");
if (parmList->safIdtService.options & ZIS_AUTH_SERVICE_SAFIDT_OPTION_IDT_APPL) {
safRC = safVerify7(options, parmList->userIDNullTerm,
parmList->passwordNullTerm, &acee, parmList->safIdtService.applNullTerm, &racfRC, &racfRsn, idta);
} else {
safRC = safVerify6(options, parmList->userIDNullTerm,
parmList->passwordNullTerm, &acee, &racfRC, &racfRsn, idta);
parmList->passwordNullTerm, &acee, &racfRC, &racfRsn, idta);
}

CMS_DEBUG(globalArea, "safVerify(VERIFY_CREATE) safStatus = %d, RACF RC = %d, "
"RSN = %d, ACEE=0x%p\n", safRC, racfRC, racfRsn, acee);
if (idta != NULL) {
CMS_DEBUG(globalArea, "IDTA token: gen_rc = %d, prop_out = %X, prop_in = %X "
CMS_DEBUG(globalArea, "IDTA token: gen_rc = %d, prop_out = %X, prop_in = %X "
"token length = %d\n", idta->idtGenRc, idta->idtPropOut, idta->idtPropIn,
idta->idtLen);
}

if (safRC != 0) {
rc = RC_ZIS_AUTHSRV_SAF_ERROR;
goto acee_deleted;
}

if (idta != NULL) {
parmList->safIdtLen = idta->idtLen;
}
parmList->safIdtService.safIdtLen = idta->idtLen;

deleteSAFRC = safVerify(VERIFY_DELETE, NULL, NULL, &acee, &deleteRACFRC,
&deleteRACFRsn);
Expand All @@ -86,14 +122,11 @@ static int handleVerifyPassword(AuthServiceParmList *parmList,
if (deleteSAFRC != 0) {
rc = RC_ZIS_AUTHSRV_DELETE_FAILED;
}
acee_deleted:
acee_deleted:

FILL_SAF_STATUS(&parmList->safStatus, safRC, racfRC, racfRsn);
CMS_DEBUG(globalArea, "handleVerifyPassword() done\n");
if (idta != NULL) {
safeFree(idta, sizeof(IDTA));
idta = NULL;
}
CMS_DEBUG(globalArea, "handleGenerateToken() done rc = %d \n",rc);

return rc;
}

Expand Down Expand Up @@ -357,6 +390,9 @@ int zisAuthServiceFunction(CrossMemoryServerGlobalArea *globalArea,
case ZIS_AUTH_SERVICE_PARMLIST_FC_GET_ACCESS:
handlerRC = handleAccessRetrieval(&localParmList, globalArea);
break;
case ZIS_AUTH_SERVICE_PARMLIST_FC_GENERATE_TOKEN:
handlerRC = handleGenerateToken(&localParmList, globalArea);
break;
default:
handlerRC = RC_ZIS_AUTHSRV_UNKNOWN_FUNCTION_CODE;
}
Expand Down
2 changes: 1 addition & 1 deletion deps/zowe-common-c
Submodule zowe-common-c updated 2 files
+17 −0 c/zos.c
+5 −0 h/zos.h
38 changes: 37 additions & 1 deletion h/zis/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,9 +420,45 @@ int zisCallNWMService(const CrossMemoryServerName *serverName,

#define RC_ZIS_SRVC_NWM_BUFFER_NULL (ZIS_MAX_GEN_SRVC_RC + 1)

/**
* @brief This function generates the SAF ID token when username and password is provided and SAF ID token is empty.
* This function validates the SAF ID token for username when token is provided and password is empty. Supports only
* JWT as identity token. Supports application name as audience claim. Returns RC_ZIS_AUTHSRV_SAF_ERROR when username,
* password and SAF ID token is empty.
*
* @param serverName Cross-memory server that validates the parameters
* @param userName Name of the user to whom the token belongs
* @param password Password of the user
* @param appl Application name parameter to specify the audience claim for SAF IDT. It is optional parameter. When
* provided for generation the token, this will be included in the token. When provided for validation, it will be
* validated against audience claim.
* @param safIdt Token that will be validated.
* @param status Status code from ZIS.
*
* @return One of the RC_ZIS_AUTHSRV_xx return codes.
*/
int zisGenerateOrValidateSafIdtWithAppl(const CrossMemoryServerName *serverName,
const char *userName, const char *password,
const char *appl,
char *safIdt,
ZISAuthServiceStatus *status);

/**
* @brief This function generates the SAF ID token when username and password is provided and SAF ID token is empty.
* This function validates the SAF ID token for username when token is provided and password is empty. Supports only
* JWT as identity token.Returns RC_ZIS_AUTHSRV_SAF_ERROR when username, password and SAF ID token is empty.
*
* @param serverName Cross-memory server that validates the parameters
* @param userName Name of the user to whom the token belongs
* @param password Password of the user
* @param safIdt Token that will be validated.
* @param status Status code from ZIS.
*
* @return One of the RC_ZIS_AUTHSRV_xx return codes.
*/
int zisGenerateOrValidateSafIdt(const CrossMemoryServerName *serverName,
const char *userName, const char *password,
const char *safIdt,
char *safIdt,
ZISAuthServiceStatus *status);

#endif /* ZIS_CLIENT_H_ */
Expand Down
Loading

0 comments on commit f64143e

Please sign in to comment.