diff --git a/bin/zssServer.sh b/bin/zssServer.sh index bc2f108f6..43ed5f2c1 100755 --- a/bin/zssServer.sh +++ b/bin/zssServer.sh @@ -13,6 +13,9 @@ export _BPXK_AUTOCVT=ON COMPONENT_HOME="${ZWE_zowe_runtimeDirectory}/components/zss" ZSS_SCRIPT_DIR="${COMPONENT_HOME}/bin" +# this is to resolve ZSS bin path in LIBPATH variable. +LIBPATH="${LIBPATH}:${ZSS_SCRIPT_DIR}" + # this is to resolve (builtin) plugins that use ZLUX_ROOT_DIR as a relative path. if it doesnt exist, the plugins shouldn't either, so no problem if [ -z "${ZLUX_ROOT_DIR}" ]; then if [ -d "${ZWE_zowe_runtimeDirectory}/components/app-server/share" ]; then diff --git a/c/safIdtService.c b/c/safIdtService.c index 5d211acdd..fc0182558 100755 --- a/c/safIdtService.c +++ b/c/safIdtService.c @@ -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); @@ -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"); @@ -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); @@ -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; @@ -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; } @@ -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); diff --git a/c/zis/client.c b/c/zis/client.c index 5324133df..6873d3c68 100644 --- a/c/zis/client.c +++ b/c/zis/client.c @@ -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; @@ -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) { diff --git a/c/zis/services/auth.c b/c/zis/services/auth.c index 4325a4f66..c3e3c1d5e 100644 --- a/c/zis/services/auth.c +++ b/c/zis/services/auth.c @@ -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); @@ -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; } @@ -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; } diff --git a/deps/zowe-common-c b/deps/zowe-common-c index ed8ae5f97..8e3c31d58 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit ed8ae5f9794179da06102c13970081d308e09543 +Subproject commit 8e3c31d58cfda6c9d133ef393ee020c4ace442d5 diff --git a/h/zis/client.h b/h/zis/client.h index 3e42a3e41..0ae157d5b 100644 --- a/h/zis/client.h +++ b/h/zis/client.h @@ -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_ */ diff --git a/h/zis/services/auth.h b/h/zis/services/auth.h index 5b29878b4..f5667aac6 100644 --- a/h/zis/services/auth.h +++ b/h/zis/services/auth.h @@ -43,7 +43,24 @@ typedef struct AbendInfo_tag { #define ZIS_AUTH_SERVICE_PASSWORD_MAX_LENGTH 100 #define ZIS_AUTH_SERVICE_CLASS_MAX_LENGTH 8 #define ZIS_AUTH_SERVICE_ENTITY_MAX_LENGTH 255 +#define ZIS_AUTH_SERVICE_APPL_MAX_LENGTH 8 +#define ZIS_SAF_IDT_SERVICE_CURRENT_VERSION 1 + +typedef struct SafIdtService_tag{ + int safIdtServiceVersion; + int safIdtLen; + char options; + #define ZIS_AUTH_SERVICE_SAFIDT_LENGTH (2 * IDTA_IDT_BUFFER_LEN_MIN) + #define ZIS_AUTH_SERVICE_SAFIDT_OPTION_GENERATE_IDT 0x80 + #define ZIS_AUTH_SERVICE_SAFIDT_OPTION_IDT_APPL 0x40 + char safIdt[ZIS_AUTH_SERVICE_SAFIDT_LENGTH]; + char applNullTerm[ZIS_AUTH_SERVICE_APPL_MAX_LENGTH + 1]; +} SafIdtService; + +/* The #define for ZIS_AUTH_SERVICE_SAFIDT_OPTION_GENERATE_IDT has been deprecated, and will be removed + in the future. + */ typedef struct AuthServiceParmList_tag { char eyecatcher[8]; #define ZIS_AUTH_SERVICE_PARMLIST_EYECATCHER "RSCMPASS" @@ -51,12 +68,13 @@ typedef struct AuthServiceParmList_tag { #define ZIS_AUTH_SERVICE_PARMLIST_FC_VERIFY_PASSWORD 0 #define ZIS_AUTH_SERVICE_PARMLIST_FC_ENTITY_CHECK 1 #define ZIS_AUTH_SERVICE_PARMLIST_FC_GET_ACCESS 2 +#define ZIS_AUTH_SERVICE_PARMLIST_FC_GENERATE_TOKEN 3 char userIDNullTerm[ZIS_AUTH_SERVICE_USER_ID_MAX_LENGTH + 1]; char passwordNullTerm[ZIS_AUTH_SERVICE_PASSWORD_MAX_LENGTH + 1]; /* up to 8 characters: */ char classNullTerm[ZIS_AUTH_SERVICE_CLASS_MAX_LENGTH + 1]; - char options; -#define ZIS_AUTH_SERVICE_PARMLIST_OPTION_GENERATE_IDT 0x80 + char _padding0[1]; +#define ZIS_AUTH_SERVICE_SAFIDT_OPTION_RESERVED 0x80 int access; /* up to 255 characters: */ char entityNullTerm[ZIS_AUTH_SERVICE_ENTITY_MAX_LENGTH + 1]; @@ -65,9 +83,7 @@ typedef struct AuthServiceParmList_tag { AbendInfo abendInfo; }; int traceLevel; - int safIdtLen; - #define ZIS_AUTH_SERVICE_PARMLIST_SAFIDT_LENGTH (2 * IDTA_IDT_BUFFER_LEN_MIN) - char safIdt[ZIS_AUTH_SERVICE_PARMLIST_SAFIDT_LENGTH]; + SafIdtService safIdtService; } AuthServiceParmList; ZOWE_PRAGMA_PACK_RESET @@ -90,7 +106,9 @@ int zisAuthServiceFunction(CrossMemoryServerGlobalArea *globalArea, #define RC_ZIS_AUTHSRV_USER_CLASS_TOO_LONG 19 #define RC_ZIS_AUTHSRV_CUSTOM_CLASS_NOT_ALLOWED 20 #define RC_ZIS_AUTHSRV_INPUT_STRING_TOO_SHORT 21 -#define RC_ZIS_AUTHSRV_MAX_RC 21 +#define RC_ZIS_AUTHSRV_BAD_SAF_SERVICE_VERSION 22 +#define RC_ZIS_AUTHSRV_IDT_NULL 23 +#define RC_ZIS_AUTHSRV_MAX_RC 23 #endif /* ZIS_SERVICES_AUTH_H_ */ diff --git a/version.txt b/version.txt index 7ec1d6db4..ccbccc3dc 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.1.0 +2.2.0