From 3a8e00be624b1f488f54f63b10dfc0dfafddf640 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Tue, 13 Apr 2021 02:19:38 -0400 Subject: [PATCH 01/68] Initial commit for SAF query interpretation methods Signed-off-by: Leanid Astrakou --- c/authService.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 209 insertions(+), 2 deletions(-) diff --git a/c/authService.c b/c/authService.c index 732df59a5..cdd231ef4 100644 --- a/c/authService.c +++ b/c/authService.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "authService.h" #include "zowetypes.h" @@ -66,6 +67,19 @@ static int serveAuthCheck(HttpService *service, HttpResponse *response); +const char* getProfileNameFromRequest(char *url, const char *method, int instanceID); + +const char* makeProfileName( + char *type, + char *productCode, + int instanceID, + char *pluginID, + char *rootServiceName, + char *serviceName, + char *method, + char *scope, + char subUrl[12][50]); + int installAuthCheckService(HttpServer *server) { // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "begin %s\n", // __FUNCTION__); @@ -74,6 +88,7 @@ int installAuthCheckService(HttpServer *server) { httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; httpService->serviceFunction = &serveAuthCheck; httpService->runInSubtask = FALSE; + getProfileNameFromRequest("/plugins", "GET", -1); registerHttpService(server, httpService); // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "end %s\n", // __FUNCTION__); @@ -173,16 +188,208 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { respondWithError(res, HTTP_STATUS_BAD_REQUEST, "Unexpected access level"); return 0; } - /* printf("query: user %s, class %s, entity %s, access %d\n", userName, class, - entity, access); */ + // printf("\n\nquery: user %s, class %s, entity %s, access %d accessStr %s\n", userName, class, + // entity, access, accessStr); privilegedServerName = getConfiguredProperty(service->server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); + printf("\n\nprivileged server name: %s", privilegedServerName); respond(res, rc, &reqStatus); return 0; } +const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { + char type[8] = "NULL"; // core || config || service + char productCode[50] = "NULL"; + char rootServiceName[50] = "NULL"; + char subUrl[12][50]; + char profileName[150]; + char scope[50]; + char _p[50] = "NULL", pluginID[50] = "NULL", _s[50] = "NULL", serviceName[50] = "NULL", _v[50] = "NULL"; + char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; + + regex_t regex; + int value; + value = regcomp(®ex, regexStr, REG_EXTENDED); + + if (value != 0) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, + "RegEx compiled successfully."); + } else { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, + "RegEx compilation error %s.", regexStr); + } + value = regexec(®ex, url, 0, NULL, 0); + char urlCpy[150]; + strcpy(urlCpy, url); + int index = 0; + while (urlCpy[index]) { // Capitalize query + urlCpy[index] = toupper(urlCpy[index]); + index++; + } + if (instanceID < 0) { // Set instanceID + instanceID = 0; + } + if (value == REG_NOMATCH) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, + "RegEx didn't match."); + char * token = strtok(urlCpy, "/"); + int subUrlIndex = -1; + while( token != NULL ) { + if (strcmp(rootServiceName, "NULL") == 0) + { + strcpy(rootServiceName, token); + } else { + strcpy(subUrl[subUrlIndex], token); + } + subUrlIndex++; + token = strtok(NULL, "/"); + } + strcpy(productCode, "ZLUX"); + strcpy(type, "core"); + } + else if (!value) { + char * token = strtok(urlCpy, "/"); + int subUrlIndex; + subUrlIndex = 0; + while( token != NULL ) { + switch(subUrlIndex) { + case 0: + strcpy(productCode, token); + break; + case 1: + strcpy(_p, token); + break; + case 2: + strcpy(pluginID, token); + break; + case 3: + strcpy(_s, token); + break; + case 4: + strcpy(serviceName, token); + break; + case 5: + strcpy(_v, token); + break; + default: + strcpy(subUrl[subUrlIndex-6], token); // subtract 6 from maximum index to begin init subUrl array at 0 + } + + subUrlIndex++; + token = strtok(NULL, "/"); + } + if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) + { + strcpy(type, "config"); + strcpy(pluginID, subUrl[0]); + strcpy(scope, subUrl[1]); + + } else { + strcpy(type, "service"); + } + char* ch; + char* chReplace; + ch = "."; + chReplace = "_"; + for (index = 0; index <= strlen(pluginID); index++) + { + if (pluginID[index] == *ch) + { + pluginID[index] = *chReplace; + } + } + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, + "RegEx match OK."); + } + else { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "RegEx match failed."); + } + strcpy(profileName, makeProfileName(type, + productCode, + instanceID, + pluginID, + rootServiceName, + serviceName, + method, + scope, + subUrl)); + // printf("\n\nFinal query profileName & URL %s - %s\n\n", profileName, url); + + /* Free memory allocated to the pattern buffer by regcomp() */ + regfree(®ex); + return profileName; +} + +const char* makeProfileName( + char *type, + char *productCode, + int instanceID, + char *pluginID, + char *rootServiceName, + char *serviceName, + char *method, + char *scope, + char subUrl[15][50]) { + char profileName[200] = ""; + if (strcmp(productCode, "NULL") == 0) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing product code."); + return "NULL"; + } + if (instanceID == -1) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing instance ID."); + return "NULL"; + } + if (strcmp(method, "NULL") == 0) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing method."); + return "NULL"; + } + // char someString[50] = { strcpy(*someString, type) }; + if (strcmp(type, "service") == 0) { + if (strcmp(pluginID, "NULL") == 0) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing plugin ID."); + return "NULL"; + } + if (strcmp(serviceName, "NULL") == 0) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing service name."); + return "NULL"; + } + snprintf(profileName, 1024, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); + return profileName; + + } else if (strcmp(type, "config") == 0) { + if (strcmp(pluginID, "NULL") == 0) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing plugin ID."); + return "NULL"; + } + if (strcmp(scope, "NULL") == 0) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing scope."); + return "NULL"; + } + snprintf(profileName, 1024, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); + return profileName; + } else if (strcmp(type, "core") == 0) { + if (strcmp(rootServiceName, "NULL") == 0) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing root service name."); + return "NULL"; + } + snprintf(profileName, 1024, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + return profileName; + } +} + +/* Method goes here to do the same thing serveAuthCheck is doing except w/o input HttpService */ + void respondWithJsonStatus(HttpResponse *response, const char *status, int statusCode, const char *statusMessage) { jsonPrinter *out = respondWithJsonPrinter(response); setResponseStatus(response,statusCode,(char *)statusMessage); From 94742a00b4e0dd23a8a6d15d1496ffc5cdb50610 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Tue, 13 Apr 2021 02:27:34 -0400 Subject: [PATCH 02/68] Increase buffer size for subUrl Signed-off-by: Leanid Astrakou --- c/authService.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/c/authService.c b/c/authService.c index cdd231ef4..b9a2e7677 100644 --- a/c/authService.c +++ b/c/authService.c @@ -78,7 +78,7 @@ const char* makeProfileName( char *serviceName, char *method, char *scope, - char subUrl[12][50]); + char subUrl[15][50]); int installAuthCheckService(HttpServer *server) { // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "begin %s\n", @@ -88,7 +88,7 @@ int installAuthCheckService(HttpServer *server) { httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; httpService->serviceFunction = &serveAuthCheck; httpService->runInSubtask = FALSE; - getProfileNameFromRequest("/plugins", "GET", -1); + // Test SAF query: getProfileNameFromRequest("/plugins", "GET", -1); registerHttpService(server, httpService); // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "end %s\n", // __FUNCTION__); @@ -203,8 +203,8 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { char type[8] = "NULL"; // core || config || service char productCode[50] = "NULL"; char rootServiceName[50] = "NULL"; - char subUrl[12][50]; - char profileName[150]; + char subUrl[15][50]; + char profileName[2000]; char scope[50]; char _p[50] = "NULL", pluginID[50] = "NULL", _s[50] = "NULL", serviceName[50] = "NULL", _v[50] = "NULL"; char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; @@ -221,7 +221,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { "RegEx compilation error %s.", regexStr); } value = regexec(®ex, url, 0, NULL, 0); - char urlCpy[150]; + char urlCpy[2000]; strcpy(urlCpy, url); int index = 0; while (urlCpy[index]) { // Capitalize query @@ -332,7 +332,7 @@ const char* makeProfileName( char *serviceName, char *method, char *scope, - char subUrl[15][50]) { + char subUrl[200][50]) { char profileName[200] = ""; if (strcmp(productCode, "NULL") == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, From 278dc2b343f6a2d5939d9d58190c48eccdafca8a Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Tue, 13 Apr 2021 03:18:31 -0400 Subject: [PATCH 03/68] Changed buffer size for some other strings Signed-off-by: Leanid Astrakou --- c/authService.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/c/authService.c b/c/authService.c index b9a2e7677..f8943bda4 100644 --- a/c/authService.c +++ b/c/authService.c @@ -204,7 +204,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { char productCode[50] = "NULL"; char rootServiceName[50] = "NULL"; char subUrl[15][50]; - char profileName[2000]; + char profileName[250]; char scope[50]; char _p[50] = "NULL", pluginID[50] = "NULL", _s[50] = "NULL", serviceName[50] = "NULL", _v[50] = "NULL"; char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; @@ -221,7 +221,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { "RegEx compilation error %s.", regexStr); } value = regexec(®ex, url, 0, NULL, 0); - char urlCpy[2000]; + char urlCpy[250]; strcpy(urlCpy, url); int index = 0; while (urlCpy[index]) { // Capitalize query @@ -332,8 +332,8 @@ const char* makeProfileName( char *serviceName, char *method, char *scope, - char subUrl[200][50]) { - char profileName[200] = ""; + char subUrl[250][50]) { + char profileName[250] = ""; if (strcmp(productCode, "NULL") == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing product code."); From 35fe4be64a47f38abae7f8861ca7818e62b99542 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Tue, 13 Apr 2021 23:34:11 -0400 Subject: [PATCH 04/68] Code review comments regarding NULL & buffer size Signed-off-by: Leanid Astrakou --- c/authService.c | 56 ++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/c/authService.c b/c/authService.c index f8943bda4..247bc2eb3 100644 --- a/c/authService.c +++ b/c/authService.c @@ -78,7 +78,7 @@ const char* makeProfileName( char *serviceName, char *method, char *scope, - char subUrl[15][50]); + char subUrl[15][128]); int installAuthCheckService(HttpServer *server) { // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "begin %s\n", @@ -200,13 +200,13 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { } const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { - char type[8] = "NULL"; // core || config || service - char productCode[50] = "NULL"; - char rootServiceName[50] = "NULL"; - char subUrl[15][50]; - char profileName[250]; - char scope[50]; - char _p[50] = "NULL", pluginID[50] = "NULL", _s[50] = "NULL", serviceName[50] = "NULL", _v[50] = "NULL"; + char type[8]; // core || config || service + char productCode[128]; + char rootServiceName[128]; + char subUrl[15][128]; + char profileName[1024]; + char scope[128]; + char _p[128], pluginID[128], _s[128], serviceName[128], _v[128]; char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; regex_t regex; @@ -221,7 +221,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { "RegEx compilation error %s.", regexStr); } value = regexec(®ex, url, 0, NULL, 0); - char urlCpy[250]; + char urlCpy[1024]; strcpy(urlCpy, url); int index = 0; while (urlCpy[index]) { // Capitalize query @@ -237,7 +237,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { char * token = strtok(urlCpy, "/"); int subUrlIndex = -1; while( token != NULL ) { - if (strcmp(rootServiceName, "NULL") == 0) + if (strcmp(rootServiceName, NULL) == 0) { strcpy(rootServiceName, token); } else { @@ -332,56 +332,56 @@ const char* makeProfileName( char *serviceName, char *method, char *scope, - char subUrl[250][50]) { - char profileName[250] = ""; - if (strcmp(productCode, "NULL") == 0) { + char subUrl[1024][128]) { + char profileName[1024] = ""; + if (strcmp(productCode, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing product code."); - return "NULL"; + return NULL; } if (instanceID == -1) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing instance ID."); - return "NULL"; + return NULL; } - if (strcmp(method, "NULL") == 0) { + if (strcmp(method, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing method."); - return "NULL"; + return NULL; } - // char someString[50] = { strcpy(*someString, type) }; + // char someString[128] = { strcpy(*someString, type) }; if (strcmp(type, "service") == 0) { - if (strcmp(pluginID, "NULL") == 0) { + if (strcmp(pluginID, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing plugin ID."); - return "NULL"; + return NULL; } - if (strcmp(serviceName, "NULL") == 0) { + if (strcmp(serviceName, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing service name."); - return "NULL"; + return NULL; } snprintf(profileName, 1024, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); return profileName; } else if (strcmp(type, "config") == 0) { - if (strcmp(pluginID, "NULL") == 0) { + if (strcmp(pluginID, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing plugin ID."); - return "NULL"; + return NULL; } - if (strcmp(scope, "NULL") == 0) { + if (strcmp(scope, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing scope."); - return "NULL"; + return NULL; } snprintf(profileName, 1024, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); return profileName; } else if (strcmp(type, "core") == 0) { - if (strcmp(rootServiceName, "NULL") == 0) { + if (strcmp(rootServiceName, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing root service name."); - return "NULL"; + return NULL; } snprintf(profileName, 1024, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); return profileName; From f4fb448e3f19ac61de8443b0b02b1e13facd4514 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Wed, 14 Apr 2021 00:09:46 -0400 Subject: [PATCH 05/68] Added safeMalloc Signed-off-by: Leanid Astrakou --- c/authService.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/c/authService.c b/c/authService.c index 247bc2eb3..5c3c4101a 100644 --- a/c/authService.c +++ b/c/authService.c @@ -204,7 +204,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { char productCode[128]; char rootServiceName[128]; char subUrl[15][128]; - char profileName[1024]; + char *profileName = (char*) safeMalloc(1024, "profileName"); char scope[128]; char _p[128], pluginID[128], _s[128], serviceName[128], _v[128]; char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; @@ -320,6 +320,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { /* Free memory allocated to the pattern buffer by regcomp() */ regfree(®ex); + return profileName; } @@ -333,7 +334,7 @@ const char* makeProfileName( char *method, char *scope, char subUrl[1024][128]) { - char profileName[1024] = ""; + char *profileName = (char*) safeMalloc(1024, "profileNameInner"); if (strcmp(productCode, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing product code."); From 9a191adbebd81e510c0dfe3e59b5b5a70a343bd1 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Wed, 14 Apr 2021 00:27:28 -0400 Subject: [PATCH 06/68] strcpy -> snprintf to avoid possible overflow Signed-off-by: Leanid Astrakou --- c/authService.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/c/authService.c b/c/authService.c index 5c3c4101a..68caa2289 100644 --- a/c/authService.c +++ b/c/authService.c @@ -222,7 +222,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { } value = regexec(®ex, url, 0, NULL, 0); char urlCpy[1024]; - strcpy(urlCpy, url); + sprintf(urlCpy, url); int index = 0; while (urlCpy[index]) { // Capitalize query urlCpy[index] = toupper(urlCpy[index]); @@ -239,15 +239,15 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { while( token != NULL ) { if (strcmp(rootServiceName, NULL) == 0) { - strcpy(rootServiceName, token); + sprintf(rootServiceName, token); } else { - strcpy(subUrl[subUrlIndex], token); + sprintf(subUrl[subUrlIndex], token); } subUrlIndex++; token = strtok(NULL, "/"); } - strcpy(productCode, "ZLUX"); - strcpy(type, "core"); + sprintf(productCode, "ZLUX"); + sprintf(type, "core"); } else if (!value) { char * token = strtok(urlCpy, "/"); @@ -256,25 +256,25 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { while( token != NULL ) { switch(subUrlIndex) { case 0: - strcpy(productCode, token); + sprintf(productCode, token); break; case 1: - strcpy(_p, token); + sprintf(_p, token); break; case 2: - strcpy(pluginID, token); + sprintf(pluginID, token); break; case 3: - strcpy(_s, token); + sprintf(_s, token); break; case 4: - strcpy(serviceName, token); + sprintf(serviceName, token); break; case 5: - strcpy(_v, token); + sprintf(_v, token); break; default: - strcpy(subUrl[subUrlIndex-6], token); // subtract 6 from maximum index to begin init subUrl array at 0 + sprintf(subUrl[subUrlIndex-6], token); // subtract 6 from maximum index to begin init subUrl array at 0 } subUrlIndex++; @@ -282,12 +282,12 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { } if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) { - strcpy(type, "config"); - strcpy(pluginID, subUrl[0]); - strcpy(scope, subUrl[1]); + sprintf(type, "config"); + sprintf(pluginID, subUrl[0]); + sprintf(scope, subUrl[1]); } else { - strcpy(type, "service"); + sprintf(type, "service"); } char* ch; char* chReplace; @@ -307,7 +307,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "RegEx match failed."); } - strcpy(profileName, makeProfileName(type, + sprintf(profileName, makeProfileName(type, productCode, instanceID, pluginID, @@ -350,7 +350,7 @@ const char* makeProfileName( "Broken SAF query. Missing method."); return NULL; } - // char someString[128] = { strcpy(*someString, type) }; + // char someString[128] = { sprintf(*someString, type) }; if (strcmp(type, "service") == 0) { if (strcmp(pluginID, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, From 2b271d71b71457e3d161185498e86c8fef4b8fbe Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Wed, 14 Apr 2021 00:31:10 -0400 Subject: [PATCH 07/68] Increased buffer for some variables Signed-off-by: Leanid Astrakou --- c/authService.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/c/authService.c b/c/authService.c index 68caa2289..50de0205f 100644 --- a/c/authService.c +++ b/c/authService.c @@ -78,7 +78,7 @@ const char* makeProfileName( char *serviceName, char *method, char *scope, - char subUrl[15][128]); + char subUrl[15][1024]); int installAuthCheckService(HttpServer *server) { // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "begin %s\n", @@ -201,12 +201,12 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { char type[8]; // core || config || service - char productCode[128]; - char rootServiceName[128]; - char subUrl[15][128]; + char productCode[1024]; + char rootServiceName[1024]; + char subUrl[15][1024]; char *profileName = (char*) safeMalloc(1024, "profileName"); - char scope[128]; - char _p[128], pluginID[128], _s[128], serviceName[128], _v[128]; + char scope[1024]; + char _p[1024], pluginID[1024], _s[1024], serviceName[1024], _v[1024]; char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; regex_t regex; @@ -333,7 +333,7 @@ const char* makeProfileName( char *serviceName, char *method, char *scope, - char subUrl[1024][128]) { + char subUrl[15][1024]) { char *profileName = (char*) safeMalloc(1024, "profileNameInner"); if (strcmp(productCode, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, From 40c07703606d8c205140a0d3a18c37dfd09190e5 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Wed, 14 Apr 2021 00:51:50 -0400 Subject: [PATCH 08/68] sprintf --> snprintf to avoid overflow Signed-off-by: Leanid Astrakou --- c/authService.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/c/authService.c b/c/authService.c index 50de0205f..d8838d9f5 100644 --- a/c/authService.c +++ b/c/authService.c @@ -222,7 +222,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { } value = regexec(®ex, url, 0, NULL, 0); char urlCpy[1024]; - sprintf(urlCpy, url); + snprintf(urlCpy, 1024, url); int index = 0; while (urlCpy[index]) { // Capitalize query urlCpy[index] = toupper(urlCpy[index]); @@ -239,15 +239,15 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { while( token != NULL ) { if (strcmp(rootServiceName, NULL) == 0) { - sprintf(rootServiceName, token); + snprintf(rootServiceName, 1024, token); } else { - sprintf(subUrl[subUrlIndex], token); + snprintf(subUrl[subUrlIndex], 1024, token); } subUrlIndex++; token = strtok(NULL, "/"); } - sprintf(productCode, "ZLUX"); - sprintf(type, "core"); + snprintf(productCode, 1024, "ZLUX"); + snprintf(type, 1024, "core"); } else if (!value) { char * token = strtok(urlCpy, "/"); @@ -256,25 +256,25 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { while( token != NULL ) { switch(subUrlIndex) { case 0: - sprintf(productCode, token); + snprintf(productCode, 1024, token); break; case 1: - sprintf(_p, token); + snprintf(_p, 1024, token); break; case 2: - sprintf(pluginID, token); + snprintf(pluginID, 1024, token); break; case 3: - sprintf(_s, token); + snprintf(_s, 1024, token); break; case 4: - sprintf(serviceName, token); + snprintf(serviceName, 1024, token); break; case 5: - sprintf(_v, token); + snprintf(_v, 1024, token); break; default: - sprintf(subUrl[subUrlIndex-6], token); // subtract 6 from maximum index to begin init subUrl array at 0 + snprintf(subUrl[subUrlIndex-6], 1024, token); // subtract 6 from maximum index to begin init subUrl array at 0 } subUrlIndex++; @@ -282,12 +282,12 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { } if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) { - sprintf(type, "config"); - sprintf(pluginID, subUrl[0]); - sprintf(scope, subUrl[1]); + snprintf(type, 1024, "config"); + snprintf(pluginID, 1024, subUrl[0]); + snprintf(scope, 1024, subUrl[1]); } else { - sprintf(type, "service"); + snprintf(type, 1024, "service"); } char* ch; char* chReplace; @@ -307,7 +307,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "RegEx match failed."); } - sprintf(profileName, makeProfileName(type, + snprintf(profileName, 1024, makeProfileName(type, productCode, instanceID, pluginID, @@ -350,7 +350,7 @@ const char* makeProfileName( "Broken SAF query. Missing method."); return NULL; } - // char someString[128] = { sprintf(*someString, type) }; + // char someString[128] = { snprintf(*someString, 1024, type) }; if (strcmp(type, "service") == 0) { if (strcmp(pluginID, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, From 7df838093462078b9672bd1abdac277fd99eaca6 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Wed, 14 Apr 2021 00:53:02 -0400 Subject: [PATCH 09/68] Small typo Signed-off-by: Leanid Astrakou --- c/authService.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/authService.c b/c/authService.c index d8838d9f5..eea8921bb 100644 --- a/c/authService.c +++ b/c/authService.c @@ -350,7 +350,7 @@ const char* makeProfileName( "Broken SAF query. Missing method."); return NULL; } - // char someString[128] = { snprintf(*someString, 1024, type) }; + // char someString[1024] = { snprintf(*someString, 1024, type) }; if (strcmp(type, "service") == 0) { if (strcmp(pluginID, NULL) == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, From 21eb96d4dc16617a5052d00b4806a5bf2fa9b350 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Thu, 15 Apr 2021 02:36:39 -0400 Subject: [PATCH 10/68] Changed snprintf method usage Signed-off-by: Leanid Astrakou --- c/authService.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/c/authService.c b/c/authService.c index eea8921bb..2bebaf2de 100644 --- a/c/authService.c +++ b/c/authService.c @@ -88,7 +88,7 @@ int installAuthCheckService(HttpServer *server) { httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; httpService->serviceFunction = &serveAuthCheck; httpService->runInSubtask = FALSE; - // Test SAF query: getProfileNameFromRequest("/plugins", "GET", -1); + // Test out SAF query: getProfileNameFromRequest("/plugins", "GET", -1); registerHttpService(server, httpService); // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "end %s\n", // __FUNCTION__); @@ -194,7 +194,7 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); - printf("\n\nprivileged server name: %s", privilegedServerName); + // printf("\n\nprivileged server name: %s", privilegedServerName); respond(res, rc, &reqStatus); return 0; } @@ -222,7 +222,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { } value = regexec(®ex, url, 0, NULL, 0); char urlCpy[1024]; - snprintf(urlCpy, 1024, url); + snprintf(urlCpy, sizeof(urlCpy), url); int index = 0; while (urlCpy[index]) { // Capitalize query urlCpy[index] = toupper(urlCpy[index]); @@ -239,15 +239,15 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { while( token != NULL ) { if (strcmp(rootServiceName, NULL) == 0) { - snprintf(rootServiceName, 1024, token); + snprintf(rootServiceName, sizeof(rootServiceName), token); } else { - snprintf(subUrl[subUrlIndex], 1024, token); + snprintf(subUrl[subUrlIndex], sizeof(subUrl[subUrlIndex]), token); } subUrlIndex++; token = strtok(NULL, "/"); } - snprintf(productCode, 1024, "ZLUX"); - snprintf(type, 1024, "core"); + snprintf(productCode, sizeof(productCode), "ZLUX"); + snprintf(type, sizeof(type), "core"); } else if (!value) { char * token = strtok(urlCpy, "/"); @@ -256,25 +256,25 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { while( token != NULL ) { switch(subUrlIndex) { case 0: - snprintf(productCode, 1024, token); + snprintf(productCode, sizeof(productCode), token); break; case 1: - snprintf(_p, 1024, token); + snprintf(_p, sizeof(_p), token); break; case 2: - snprintf(pluginID, 1024, token); + snprintf(pluginID, sizeof(pluginID), token); break; case 3: - snprintf(_s, 1024, token); + snprintf(_s, sizeof(_s), token); break; case 4: - snprintf(serviceName, 1024, token); + snprintf(serviceName, sizeof(serviceName), token); break; case 5: - snprintf(_v, 1024, token); + snprintf(_v, sizeof(_v), token); break; default: - snprintf(subUrl[subUrlIndex-6], 1024, token); // subtract 6 from maximum index to begin init subUrl array at 0 + snprintf(subUrl[subUrlIndex-6], sizeof(subUrl[subUrlIndex-6]), token); // subtract 6 from maximum index to begin init subUrl array at 0 } subUrlIndex++; @@ -282,12 +282,12 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { } if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) { - snprintf(type, 1024, "config"); - snprintf(pluginID, 1024, subUrl[0]); - snprintf(scope, 1024, subUrl[1]); + snprintf(type, sizeof(type), "config"); + snprintf(pluginID, sizeof(pluginID), subUrl[0]); + snprintf(scope, sizeof(scope), subUrl[1]); } else { - snprintf(type, 1024, "service"); + snprintf(type, sizeof(type), "service"); } char* ch; char* chReplace; @@ -307,7 +307,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "RegEx match failed."); } - snprintf(profileName, 1024, makeProfileName(type, + snprintf(profileName, sizeof(profileName), makeProfileName(type, productCode, instanceID, pluginID, @@ -362,7 +362,7 @@ const char* makeProfileName( "Broken SAF query. Missing service name."); return NULL; } - snprintf(profileName, 1024, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); + snprintf(profileName, sizeof(profileName), "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); return profileName; } else if (strcmp(type, "config") == 0) { @@ -376,7 +376,7 @@ const char* makeProfileName( "Broken SAF query. Missing scope."); return NULL; } - snprintf(profileName, 1024, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); + snprintf(profileName, sizeof(profileName), "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); return profileName; } else if (strcmp(type, "core") == 0) { if (strcmp(rootServiceName, NULL) == 0) { @@ -384,7 +384,7 @@ const char* makeProfileName( "Broken SAF query. Missing root service name."); return NULL; } - snprintf(profileName, 1024, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + snprintf(profileName, sizeof(profileName), "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); return profileName; } } From 038b915f572c2ffc6e79cf02617e3f8604e6d174 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Thu, 15 Apr 2021 09:01:29 -0400 Subject: [PATCH 11/68] Revert Signed-off-by: Leanid Astrakou --- c/authService.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/c/authService.c b/c/authService.c index 2bebaf2de..2751c356c 100644 --- a/c/authService.c +++ b/c/authService.c @@ -88,7 +88,7 @@ int installAuthCheckService(HttpServer *server) { httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; httpService->serviceFunction = &serveAuthCheck; httpService->runInSubtask = FALSE; - // Test out SAF query: getProfileNameFromRequest("/plugins", "GET", -1); + // getProfileNameFromRequest("/plugins", "GET", -1); registerHttpService(server, httpService); // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "end %s\n", // __FUNCTION__); @@ -222,7 +222,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { } value = regexec(®ex, url, 0, NULL, 0); char urlCpy[1024]; - snprintf(urlCpy, sizeof(urlCpy), url); + snprintf(urlCpy, 1024, url); int index = 0; while (urlCpy[index]) { // Capitalize query urlCpy[index] = toupper(urlCpy[index]); @@ -239,15 +239,15 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { while( token != NULL ) { if (strcmp(rootServiceName, NULL) == 0) { - snprintf(rootServiceName, sizeof(rootServiceName), token); + snprintf(rootServiceName, 1024, token); } else { - snprintf(subUrl[subUrlIndex], sizeof(subUrl[subUrlIndex]), token); + snprintf(subUrl[subUrlIndex], 1024, token); } subUrlIndex++; token = strtok(NULL, "/"); } - snprintf(productCode, sizeof(productCode), "ZLUX"); - snprintf(type, sizeof(type), "core"); + snprintf(productCode, 1024, "ZLUX"); + snprintf(type, 1024, "core"); } else if (!value) { char * token = strtok(urlCpy, "/"); @@ -256,25 +256,25 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { while( token != NULL ) { switch(subUrlIndex) { case 0: - snprintf(productCode, sizeof(productCode), token); + snprintf(productCode, 1024, token); break; case 1: - snprintf(_p, sizeof(_p), token); + snprintf(_p, 1024, token); break; case 2: - snprintf(pluginID, sizeof(pluginID), token); + snprintf(pluginID, 1024, token); break; case 3: - snprintf(_s, sizeof(_s), token); + snprintf(_s, 1024, token); break; case 4: - snprintf(serviceName, sizeof(serviceName), token); + snprintf(serviceName, 1024, token); break; case 5: - snprintf(_v, sizeof(_v), token); + snprintf(_v, 1024, token); break; default: - snprintf(subUrl[subUrlIndex-6], sizeof(subUrl[subUrlIndex-6]), token); // subtract 6 from maximum index to begin init subUrl array at 0 + snprintf(subUrl[subUrlIndex-6], 1024, token); // subtract 6 from maximum index to begin init subUrl array at 0 } subUrlIndex++; @@ -282,12 +282,12 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { } if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) { - snprintf(type, sizeof(type), "config"); - snprintf(pluginID, sizeof(pluginID), subUrl[0]); - snprintf(scope, sizeof(scope), subUrl[1]); + snprintf(type, 1024, "config"); + snprintf(pluginID, 1024, subUrl[0]); + snprintf(scope, 1024, subUrl[1]); } else { - snprintf(type, sizeof(type), "service"); + snprintf(type, 1024, "service"); } char* ch; char* chReplace; @@ -307,7 +307,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "RegEx match failed."); } - snprintf(profileName, sizeof(profileName), makeProfileName(type, + snprintf(profileName, 1024, makeProfileName(type, productCode, instanceID, pluginID, @@ -362,7 +362,7 @@ const char* makeProfileName( "Broken SAF query. Missing service name."); return NULL; } - snprintf(profileName, sizeof(profileName), "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); + snprintf(profileName, 1024, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); return profileName; } else if (strcmp(type, "config") == 0) { @@ -376,7 +376,7 @@ const char* makeProfileName( "Broken SAF query. Missing scope."); return NULL; } - snprintf(profileName, sizeof(profileName), "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); + snprintf(profileName, 1024, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); return profileName; } else if (strcmp(type, "core") == 0) { if (strcmp(rootServiceName, NULL) == 0) { @@ -384,7 +384,7 @@ const char* makeProfileName( "Broken SAF query. Missing root service name."); return NULL; } - snprintf(profileName, sizeof(profileName), "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + snprintf(profileName, 1024, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); return profileName; } } From 0d154ad3ea3e3ad1115cf8adadd31f962b6f1391 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Sat, 24 Apr 2021 22:02:17 -0400 Subject: [PATCH 12/68] Addressed more code review like NULL checks Signed-off-by: Leanid Astrakou --- c/authService.c | 77 +++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/c/authService.c b/c/authService.c index 2751c356c..f3854b907 100644 --- a/c/authService.c +++ b/c/authService.c @@ -69,15 +69,15 @@ static int serveAuthCheck(HttpService *service, HttpResponse *response); const char* getProfileNameFromRequest(char *url, const char *method, int instanceID); -const char* makeProfileName( - char *type, - char *productCode, +static const char* makeProfileName( + const char *type, + const char *productCode, int instanceID, - char *pluginID, - char *rootServiceName, - char *serviceName, - char *method, - char *scope, + const char *pluginID, + const char *rootServiceName, + const char *serviceName, + const char *method, + const char *scope, char subUrl[15][1024]); int installAuthCheckService(HttpServer *server) { @@ -88,7 +88,7 @@ int installAuthCheckService(HttpServer *server) { httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; httpService->serviceFunction = &serveAuthCheck; httpService->runInSubtask = FALSE; - // getProfileNameFromRequest("/plugins", "GET", -1); + getProfileNameFromRequest("/plugins", "GET", -1); registerHttpService(server, httpService); // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "end %s\n", // __FUNCTION__); @@ -194,7 +194,6 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); - // printf("\n\nprivileged server name: %s", privilegedServerName); respond(res, rc, &reqStatus); return 0; } @@ -204,15 +203,20 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { char productCode[1024]; char rootServiceName[1024]; char subUrl[15][1024]; - char *profileName = (char*) safeMalloc(1024, "profileName"); + char *profileName = safeMalloc(1024, "profileName"); char scope[1024]; - char _p[1024], pluginID[1024], _s[1024], serviceName[1024], _v[1024]; + char placeHolder1[1024], pluginID[1024], placeHolder2[1024], serviceName[1024], placeHolder3[1024]; char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; regex_t regex; int value; value = regcomp(®ex, regexStr, REG_EXTENDED); - + + if (profileName == NULL) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_SEVERE, + "safeMalloc failed. Not enough memory"); + return NULL; + } if (value != 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, "RegEx compiled successfully."); @@ -237,7 +241,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { char * token = strtok(urlCpy, "/"); int subUrlIndex = -1; while( token != NULL ) { - if (strcmp(rootServiceName, NULL) == 0) + if (rootServiceName == NULL) { snprintf(rootServiceName, 1024, token); } else { @@ -259,19 +263,19 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { snprintf(productCode, 1024, token); break; case 1: - snprintf(_p, 1024, token); + snprintf(placeHolder1, 1024, token); break; case 2: snprintf(pluginID, 1024, token); break; case 3: - snprintf(_s, 1024, token); + snprintf(placeHolder2, 1024, token); break; case 4: snprintf(serviceName, 1024, token); break; case 5: - snprintf(_v, 1024, token); + snprintf(placeHolder3, 1024, token); break; default: snprintf(subUrl[subUrlIndex-6], 1024, token); // subtract 6 from maximum index to begin init subUrl array at 0 @@ -316,7 +320,7 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { method, scope, subUrl)); - // printf("\n\nFinal query profileName & URL %s - %s\n\n", profileName, url); + printf("\n\nFinal query profileName & URL %s - %s\n\n", profileName, url); /* Free memory allocated to the pattern buffer by regcomp() */ regfree(®ex); @@ -324,18 +328,23 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { return profileName; } -const char* makeProfileName( - char *type, - char *productCode, +static const char* makeProfileName( + const char *type, + const char *productCode, int instanceID, - char *pluginID, - char *rootServiceName, - char *serviceName, - char *method, - char *scope, + const char *pluginID, + const char *rootServiceName, + const char *serviceName, + const char *method, + const char *scope, char subUrl[15][1024]) { - char *profileName = (char*) safeMalloc(1024, "profileNameInner"); - if (strcmp(productCode, NULL) == 0) { + char *profileName = safeMalloc(1024, "profileNameInner"); + if (profileName == NULL) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_SEVERE, + "safeMalloc failed. Not enough memory"); + return NULL; + } + if (productCode == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing product code."); return NULL; @@ -345,19 +354,19 @@ const char* makeProfileName( "Broken SAF query. Missing instance ID."); return NULL; } - if (strcmp(method, NULL) == 0) { + if (method == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing method."); return NULL; } // char someString[1024] = { snprintf(*someString, 1024, type) }; if (strcmp(type, "service") == 0) { - if (strcmp(pluginID, NULL) == 0) { + if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing plugin ID."); return NULL; } - if (strcmp(serviceName, NULL) == 0) { + if (serviceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing service name."); return NULL; @@ -366,12 +375,12 @@ const char* makeProfileName( return profileName; } else if (strcmp(type, "config") == 0) { - if (strcmp(pluginID, NULL) == 0) { + if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing plugin ID."); return NULL; } - if (strcmp(scope, NULL) == 0) { + if (scope == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing scope."); return NULL; @@ -379,7 +388,7 @@ const char* makeProfileName( snprintf(profileName, 1024, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); return profileName; } else if (strcmp(type, "core") == 0) { - if (strcmp(rootServiceName, NULL) == 0) { + if (rootServiceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing root service name."); return NULL; From c91b2dc70673b0724e728b1f591cacd7561c62e1 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Mon, 24 May 2021 02:54:20 -0400 Subject: [PATCH 13/68] Some prototype RBAC checking + unfinished comments Signed-off-by: Leanid Astrakou --- CHANGELOG.md | 5 +++++ c/authService.c | 46 +++++++++++++++++++++++++++++++++++----------- deps/zowe-common-c | 2 +- h/authService.h | 4 ++++ version.txt | 2 +- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dbedbcce..2f6d692c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to the ZSS package will be documented in this file. ## Recent Changes +## `1.22.0` + +### New features and enhancements +- Added RBAC capability via SAF checks + ## `1.21.0` - Set cookie path to root in order to avoid multiple cookies when browser tries to set path automatically diff --git a/c/authService.c b/c/authService.c index f3854b907..e1c98fcbd 100644 --- a/c/authService.c +++ b/c/authService.c @@ -65,9 +65,11 @@ * } */ -static int serveAuthCheck(HttpService *service, HttpResponse *response); +int serveAuthCheck(HttpService *service, HttpResponse *response); -const char* getProfileNameFromRequest(char *url, const char *method, int instanceID); +int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char* entity, int access); + +const char* getProfileNameFromRequest(char *profileName, char *url, const char *method, int instanceID); static const char* makeProfileName( const char *type, @@ -88,7 +90,6 @@ int installAuthCheckService(HttpServer *server) { httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; httpService->serviceFunction = &serveAuthCheck; httpService->runInSubtask = FALSE; - getProfileNameFromRequest("/plugins", "GET", -1); registerHttpService(server, httpService); // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "end %s\n", // __FUNCTION__); @@ -170,11 +171,16 @@ static void respond(HttpResponse *res, int rc, const ZISAuthServiceStatus finishResponse(res); } -static int serveAuthCheck(HttpService *service, HttpResponse *res) { +int serveAuthCheck(HttpService *service, HttpResponse *res) { HttpRequest *req = res->request; char *entity, *accessStr; int access = 0; int rc = 0, rsn = 0, safStatus = 0; + char *uri = safeMalloc(1024, "uri"); + snprintf(uri, 1024, "%s", req->uri); + destructivelyNativize(uri); + // TODO: Remove printf's for a merge + printf("\n\n\nBegin with this URI %s\n\n\n", uri); ZISAuthServiceStatus reqStatus = {0}; CrossMemoryServerName *privilegedServerName; const char *userName = req->username, *class = SAF_CLASS; @@ -188,22 +194,38 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { respondWithError(res, HTTP_STATUS_BAD_REQUEST, "Unexpected access level"); return 0; } + printf("\n\n\naccessStr - %s : entity - %s : rc - %d : parsedFile - %s\n\n\n", accessStr, entity, rc, req->parsedFile); + // printf("\n\nquery: user %s, class %s, entity %s, access %d accessStr %s\n", userName, class, // entity, access, accessStr); privilegedServerName = getConfiguredProperty(service->server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); + printf("\n\n\nRESULTS OF ZISCHECKENTITY privilegedServerName - %s : userName - %s : class - %s : entity - %s : access - %d: reqstatus - %s : rc - %d\n\n\n", privilegedServerName, userName, class, entity, access, + &reqStatus, rc); + respond(res, rc, &reqStatus); return 0; } -const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { +int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access) { + int rc = 0; + CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, + HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); + ZISAuthServiceStatus reqStatus = {0}; + rc = zisCheckEntity(privilegedServerName, userName, Class, entity, access, + &reqStatus); + printf("\n\n\nRESULTS OF serveAuthCheckByParams privilegedServerName - %s : userName - %s : class - %s : entity - %s : access - %d: reqstatus - %s : rc - %d\n\n\n", privilegedServerName, userName, Class, entity, access, + &reqStatus, rc); + return rc; +} + +const char* getProfileNameFromRequest(char *profileName, char *url, char *method, int instanceID) { char type[8]; // core || config || service char productCode[1024]; char rootServiceName[1024]; char subUrl[15][1024]; - char *profileName = safeMalloc(1024, "profileName"); char scope[1024]; char placeHolder1[1024], pluginID[1024], placeHolder2[1024], serviceName[1024], placeHolder3[1024]; char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; @@ -320,7 +342,6 @@ const char* getProfileNameFromRequest(char *url, char *method, int instanceID) { method, scope, subUrl)); - printf("\n\nFinal query profileName & URL %s - %s\n\n", profileName, url); /* Free memory allocated to the pattern buffer by regcomp() */ regfree(®ex); @@ -372,8 +393,6 @@ static const char* makeProfileName( return NULL; } snprintf(profileName, 1024, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); - return profileName; - } else if (strcmp(type, "config") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, @@ -386,7 +405,6 @@ static const char* makeProfileName( return NULL; } snprintf(profileName, 1024, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); - return profileName; } else if (strcmp(type, "core") == 0) { if (rootServiceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, @@ -394,8 +412,14 @@ static const char* makeProfileName( return NULL; } snprintf(profileName, 1024, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); - return profileName; } + // Child endpoints housed via subUrl + int index = 0; + while (index < 15 && strcmp(subUrl[index], "") != 0) { + snprintf(profileName, 1024, "%s.%s", profileName, subUrl[index]); + index++; + } + return profileName; } /* Method goes here to do the same thing serveAuthCheck is doing except w/o input HttpService */ diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 70d400259..9f2a07f42 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 70d400259a9dd22fe329742cb82e60ff091b799b +Subproject commit 9f2a07f42dd7ef5571eb0301e3f2a0b90ddf3ad6 diff --git a/h/authService.h b/h/authService.h index 6a28702f8..afcd638fa 100644 --- a/h/authService.h +++ b/h/authService.h @@ -28,6 +28,10 @@ int installAuthCheckService(HttpServer *server); void installZosPasswordService(HttpServer *server); +const char* getProfileNameFromRequest(char *profileName, char *url, char *method, int instanceID); +int serveAuthCheck(HttpService *service, HttpResponse *res); +int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access); + #endif diff --git a/version.txt b/version.txt index 3500250a4..57807d6d0 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.21.0 +1.22.0 From a618f31f311806901e29c0c2cfcf74e8c190ebb3 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Mon, 24 May 2021 03:04:17 -0400 Subject: [PATCH 14/68] Annoying char change Signed-off-by: Leanid Astrakou --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2611e4530..8b77c6fa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,10 @@ All notable changes to the ZSS package will be documented in this file. ## `1.22.0` -### New features and enhancements] +### New features and enhancements - Added RBAC capability via SAF checks -- Bugfix: Dataset contents API doesn't skip empty records while reading a dataset +- Bugfix: Dataset contents API doesn't skip empty records while reading a dataset ## `1.21.0` From a6ef66ea6dec81addd5ed6f256963a58dfd18b04 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Mon, 24 May 2021 17:50:01 -0400 Subject: [PATCH 15/68] Updated dep Signed-off-by: Leanid Astrakou --- deps/zowe-common-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 756b42cb0..37a9bd7cf 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 756b42cb0e52b837c1ec3a02970424134b8d3cf6 +Subproject commit 37a9bd7cf2f962e1b30065f82fccc4d9af1062db From 245cdbcbe9155f43d0b0d12c2a9d84610510c68a Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Tue, 25 May 2021 10:59:27 -0400 Subject: [PATCH 16/68] Added check for rbac: true | false Signed-off-by: Leanid Astrakou --- c/authService.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/c/authService.c b/c/authService.c index e1c98fcbd..a4c2168b3 100644 --- a/c/authService.c +++ b/c/authService.c @@ -211,9 +211,14 @@ int serveAuthCheck(HttpService *service, HttpResponse *res) { int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access) { int rc = 0; + JsonObject *dataserviceAuth = jsonObjectGetObject(service->server->sharedServiceMem, "dataserviceAuthentication"); + int rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); ZISAuthServiceStatus reqStatus = {0}; + if (!rbacParm) { + return rc; // When rbac isn't enabled, we don't try to check the auth query + } rc = zisCheckEntity(privilegedServerName, userName, Class, entity, access, &reqStatus); printf("\n\n\nRESULTS OF serveAuthCheckByParams privilegedServerName - %s : userName - %s : class - %s : entity - %s : access - %d: reqstatus - %s : rc - %d\n\n\n", privilegedServerName, userName, Class, entity, access, From a7a4e1e3b9606df8c8817ec8e1caf100941b49a1 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Mon, 31 May 2021 19:29:36 -0400 Subject: [PATCH 17/68] Updated zowe-common-c Signed-off-by: Leanid Astrakou --- deps/zowe-common-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 37a9bd7cf..552f55129 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 37a9bd7cf2f962e1b30065f82fccc4d9af1062db +Subproject commit 552f551295be87081241c409870047c8c2914335 From b0f89144987cf3be37be5f62e6d8654b4cb606af Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Thu, 3 Jun 2021 00:58:56 -0400 Subject: [PATCH 18/68] Moved core RBAC auth logic from zowe-common-c into ZSS Signed-off-by: Leanid Astrakou --- c/zss.c | 236 ++++++++++++--------------------------------- deps/zowe-common-c | 2 +- 2 files changed, 64 insertions(+), 174 deletions(-) diff --git a/c/zss.c b/c/zss.c index 6dff6f0fc..7d77a54a7 100644 --- a/c/zss.c +++ b/c/zss.c @@ -79,8 +79,6 @@ #ifdef USE_ZOWE_TLS #include "tls.h" #endif // USE_ZOWE_TLS -#include "storage.h" -#include "storageApiml.h" #define PRODUCT "ZLUX" #ifndef PRODUCT_MAJOR_VERSION @@ -123,12 +121,11 @@ static JsonObject *readPluginDefinition(ShortLivedHeap *slh, char *pluginLocation, char *relativeTo); static WebPluginListElt* readWebPluginDefinitions(HttpServer* server, ShortLivedHeap *slh, char *dirname, - const char *serverConfigFile, ApimlStorageSettings *apimlStorageSettings); + const char *serverConfigFile); static JsonObject *readServerSettings(ShortLivedHeap *slh, const char *filename); static hashtable *getServerTimeoutsHt(ShortLivedHeap *slh, Json *serverTimeouts, const char *key); static InternalAPIMap *makeInternalAPIMap(void); -static bool readGatewaySettings(JsonObject *serverConfig, JsonObject *envConfig, char **outGatewayHost, int *outGatewayPort); -static bool isCachingServiceEnabled(JsonObject *serverConfig, JsonObject *envConfig); +static int authHandlerFunction(); static int servePluginDefinitions(HttpService *service, HttpResponse *response){ zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); @@ -325,6 +322,39 @@ static void setPrivilegedServerName(HttpServer *server, JsonObject *mvdSettings, } #endif /* __ZOWE_OS_ZOS */ +static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpRequest *request, HttpService *service) { + if (conversation->parser) { + HttpRequestParser *parser = conversation->parser; + char *method = safeMalloc(1024, "method"); + char *uri = safeMalloc(1024, "uri"); + char *username = safeMalloc(1024, "username"); + snprintf(uri, 1024, "%s", request->uri); + snprintf(method, 1024, "%s", request->method); + destructivelyNativize(uri); + destructivelyNativize(method); + char *profileName = safeMalloc(1024, "profileName"); + // TODO: Remove printf's (not ready for merge) + printf("\n\n\nURI, METHOD, PROFILENAME PRE CONVERSION: %s - %s - %s - (old) %s\n\n", uri, method, profileName, request->uri); + getProfileNameFromRequest(profileName, uri, method, -1); + printf("\n\n\nURI, METHOD, PROFILENAME POST CONVERSION %s - %s - %s\n\n", uri, method, profileName); + int rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2); + return rc; + } + return -1; +} + +static void initializeAuthHandlers(HttpServer *server) { + void *handler = server->authHandler; + char arr[][1024] = { + "NATIVE_WITH_SESSION_TOKEN", // TODO: authHandlers needs to be an array + }; + //int size = sizeof arr / sizeof arr[0]; + + /* NATIVE_WITH_SESSION_TOKEN */ + server->authHandler->type = "NATIVE_WITH_SESSION_TOKEN"; // TODO: Needs to come from constants in httpserver.h + server->authHandler->authFunction = &nativeWithSessionTokenAuth; +} + static void loadWebServerConfig(HttpServer *server, JsonObject *mvdSettings, JsonObject *envSettings, hashtable *htUsers, hashtable *htGroups, int defaultSessionTimeout){ @@ -703,8 +733,7 @@ static int checkLoggingVerbosity(const char *serverConfigFile, char *pluginIdent } static WebPluginListElt* readWebPluginDefinitions(HttpServer *server, ShortLivedHeap *slh, char *dirname, - const char *serverConfigFile, - ApimlStorageSettings *apimlStorageSettings) { + const char *serverConfigFile) { int pluginDefinitionCount = 0; int returnCode; int reasonCode; @@ -753,12 +782,8 @@ static WebPluginListElt* readWebPluginDefinitions(HttpServer *server, ShortLived if (identifier && pluginLocation) { JsonObject *pluginDefinition = readPluginDefinition(slh, identifier, pluginLocation, relativeTo); if (pluginDefinition) { - Storage *remoteStorage = NULL; - if (apimlStorageSettings) { - remoteStorage = makeApimlStorage(apimlStorageSettings, identifier); - } - WebPlugin *plugin = makeWebPlugin2(pluginLocation, pluginDefinition, internalAPIMap, - &idMultiplier, pluginLogLevel, remoteStorage); + WebPlugin *plugin = makeWebPlugin(pluginLocation, pluginDefinition, internalAPIMap, + &idMultiplier, pluginLogLevel); if (plugin != NULL) { initalizeWebPlugin(plugin, server); //zlux does this, so don't bother doing it twice. @@ -820,40 +845,6 @@ static WebPluginListElt* readWebPluginDefinitions(HttpServer *server, ShortLived return webPluginListHead; } -static ApimlStorageSettings *readApimlStorageSettings(ShortLivedHeap *slh, JsonObject *serverConfig, JsonObject *envConfig, TlsEnvironment *tlsEnv) { - char *host = NULL; - int port = 0; - bool configured = false; - - do { - if (!isCachingServiceEnabled(serverConfig, envConfig)) { - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG, "Caching Service disabled\n"); - break; - } - if (!readGatewaySettings(serverConfig, envConfig, &host, &port)) { - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG, "Gateway settings not found\n"); - break; - } - if (!tlsEnv) { - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG, "TLS settings not found\n"); - break; - } - configured = true; - } while(0); - - if (!configured) { - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_CACHE_NOT_CFG_MSG); - return NULL; - } - ApimlStorageSettings *settings = (ApimlStorageSettings*)SLHAlloc(slh, sizeof(*settings)); - memset(settings, 0, sizeof(*settings)); - settings->host = host; - settings->port = port; - settings->tlsEnv = tlsEnv; - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_CACHE_SETTINGS_MSG settings->host, settings->port); - return settings; -} - static const char defaultConfigPath[] = "../defaults/serverConfig/server.json"; static @@ -907,7 +898,6 @@ static void initLoggingComponents(void) { logConfigureComponent(NULL, LOG_COMP_DATASERVICE, "ZSS dataservices", LOG_DEST_PRINTF_STDOUT, ZOWE_LOG_INFO); logConfigureComponent(NULL, LOG_COMP_ID_MVD_SERVER, "ZSS server", LOG_DEST_PRINTF_STDOUT, ZOWE_LOG_INFO); logConfigureComponent(NULL, LOG_COMP_ID_CTDS, "CT/DS", LOG_DEST_PRINTF_STDOUT, ZOWE_LOG_INFO); - logConfigureComponent(NULL, LOG_COMP_ID_APIML_STORAGE, "APIML Storage", LOG_DEST_PRINTF_STDOUT, ZOWE_LOG_INFO); zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_ZSS_START_VER_MSG, productVersion); } @@ -987,7 +977,7 @@ static bool readAgentHttpsSettings(ShortLivedHeap *slh, JsonObject *envConfig, char **outAddress, int *outPort, - TlsEnvironment **outTlsEnv + TlsSettings **outSettings ) { int port = jsonObjectGetNumber(envConfig, ENV_AGENT_HTTPS_KEY(PORT_KEY)); char *address = jsonObjectGetString(envConfig, ENV_AGENT_HTTPS_KEY(IP_ADDRESSES_KEY)); @@ -1032,120 +1022,13 @@ static bool readAgentHttpsSettings(ShortLivedHeap *slh, if (!address) { address = "127.0.0.1"; } - bool isHttpsConfigured = port && settings->keyring; - if (settings->keyring) { - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_TLS_SETTINGS_MSG, - settings->keyring, - settings->label ? settings->label : "(no label)", - settings->password ? "****" : "(no password)", - settings->stash ? settings->stash : "(no stash)"); - TlsEnvironment *tlsEnv = NULL; - int rc = tlsInit(&tlsEnv, settings); - if (rc != 0) { - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_WARNING, ZSS_LOG_TLS_INIT_MSG, rc, tlsStrError(rc)); - } else { - *outTlsEnv = tlsEnv; - } - } - if (isHttpsConfigured) { + bool httpsSettingsFound = port && settings->keyring; + if (httpsSettingsFound) { *outPort = port; *outAddress = address; + *outSettings = settings; } - return isHttpsConfigured; -} - -#define NODE_MEDIATION_LAYER_SERVER_PREFIX "ZWED_node_mediationLayer_server_" -#define ENV_NODE_MEDIATION_LAYER_SERVER_KEY(key) NODE_MEDIATION_LAYER_SERVER_PREFIX key - -// Returns false if gateway host and port not found -static bool readGatewaySettings(JsonObject *serverConfig, - JsonObject *envConfig, - char **outGatewayHost, - int *outGatewayPort - ) { - char *gatewayHost = jsonObjectGetString(envConfig, ENV_NODE_MEDIATION_LAYER_SERVER_KEY("gatewayHostname")); - char *hostname = jsonObjectGetString(envConfig, ENV_NODE_MEDIATION_LAYER_SERVER_KEY("hostname")); - int gatewayPort = jsonObjectGetNumber(envConfig, ENV_NODE_MEDIATION_LAYER_SERVER_KEY("gatewayPort")); - if (gatewayHost && gatewayPort) { - *outGatewayHost = gatewayHost; - *outGatewayPort = gatewayPort; - return true; - } - - JsonObject *nodeSettings = jsonObjectGetObject(serverConfig, "node"); - if (!nodeSettings) { - return false; - } - JsonObject *mediationLayerSettings = jsonObjectGetObject(nodeSettings, "mediationLayer"); - if (!mediationLayerSettings) { - return false; - } - JsonObject *serverSettings = jsonObjectGetObject(mediationLayerSettings, "server"); - if (!serverSettings) { - return false; - } - if (!gatewayHost) { - gatewayHost = jsonObjectGetString(serverSettings, "gatewayHostname"); - } - if (!gatewayHost) { - gatewayHost = hostname; - } - if (!gatewayHost) { - gatewayHost = jsonObjectGetString(serverSettings, "hostname"); - } - if (!gatewayPort) { - gatewayPort = jsonObjectGetNumber(serverSettings, "gatewayPort"); - } - if (!gatewayHost || !gatewayPort) { - return false; - } - *outGatewayHost = gatewayHost; - *outGatewayPort = gatewayPort; - return true; -} - -#define NODE_MEDIATION_LAYER_PREFIX "ZWED_node_mediationLayer_" -#define ENV_NODE_MEDIATION_LAYER_KEY(key) NODE_MEDIATION_LAYER_PREFIX key -#define NODE_MEDIATION_LAYER_CACHING_SERVICE_PREFIX NODE_MEDIATION_LAYER_PREFIX "cachingService_" -#define NODE_MEDIATION_LAYER_CACHING_SERVICE_KEY(key) NODE_MEDIATION_LAYER_CACHING_SERVICE_PREFIX key -#define ENABLED_KEY "enabled" - -static bool isCachingServiceEnabled(JsonObject *serverConfig, JsonObject *envConfig) { - bool enabledSettingFound = jsonObjectHasKey(envConfig, ENV_NODE_MEDIATION_LAYER_KEY(ENABLED_KEY)); - bool enabled = false; - if (enabledSettingFound) { - enabled = jsonObjectGetBoolean(envConfig, ENV_NODE_MEDIATION_LAYER_KEY(ENABLED_KEY)); - if (!enabled) { - return false; - } - } - JsonObject *nodeSettings = NULL; - JsonObject *mediationLayerSettings = NULL; - if (!enabled) { - nodeSettings = jsonObjectGetObject(serverConfig, "node"); - if (!nodeSettings) { - return false; - } - mediationLayerSettings = jsonObjectGetObject(nodeSettings, "mediationLayer"); - if (!mediationLayerSettings) { - return false; - } - enabled = jsonObjectGetBoolean(mediationLayerSettings, ENABLED_KEY); - if (!enabled) { - return false; - } - } - enabledSettingFound = jsonObjectGetBoolean(envConfig, NODE_MEDIATION_LAYER_CACHING_SERVICE_KEY(ENABLED_KEY)); - if (enabledSettingFound) { - enabled = jsonObjectGetBoolean(envConfig, NODE_MEDIATION_LAYER_CACHING_SERVICE_KEY(ENABLED_KEY)); - return enabled; - } - JsonObject *cachingServiceSettings = jsonObjectGetObject(mediationLayerSettings, "cachingService"); - if (!cachingServiceSettings) { - return false; - } - enabled = jsonObjectGetBoolean(cachingServiceSettings, ENABLED_KEY); - return enabled; + return httpsSettingsFound; } static int validateAddress(char *address, InetAddr **inetAddress, int *requiredTLSFlag) { @@ -1525,14 +1408,8 @@ int main(int argc, char **argv){ int port = 0; char *address = NULL; TlsSettings *tlsSettings = NULL; - TlsEnvironment *tlsEnv = NULL; - bool isHttpsConfigured = readAgentHttpsSettings(slh, mvdSettings, envSettings, &address, &port, &tlsEnv); - if (isHttpsConfigured && !tlsEnv) { - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_SEVERE, ZSS_LOG_HTTPS_INVALID_MSG); - zssStatus = ZSS_STATUS_ERROR; - goto out_term_stcbase; - } - if (!isHttpsConfigured) { + bool httpsSettingsFound = readAgentHttpsSettings(slh, mvdSettings, envSettings, &address, &port, &tlsSettings); + if (!httpsSettingsFound) { readAgentAddressAndPort(mvdSettings, envSettings, &address, &port); } InetAddr *inetAddress = NULL; @@ -1542,9 +1419,22 @@ int main(int argc, char **argv){ zssStatus = ZSS_STATUS_ERROR; goto out_term_stcbase; } - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_ZSS_SETTINGS_MSG, address, port, isHttpsConfigured ? "https" : "http"); - if (isHttpsConfigured) { - server = makeSecureHttpServer(base, inetAddress, port, tlsEnv, requiredTLSFlag, &returnCode, &reasonCode); + + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_ZSS_SETTINGS_MSG, address, port, httpsSettingsFound ? "https" : "http"); + if (httpsSettingsFound) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_TLS_SETTINGS_MSG, + tlsSettings->keyring, + tlsSettings->label ? tlsSettings->label : "(no label)", + tlsSettings->password ? "****" : "(no password)", + tlsSettings->stash ? tlsSettings->stash : "(no stash)"); + TlsEnvironment *env = NULL; + int rc = tlsInit(&env, tlsSettings); + if (rc != 0) { + zssStatus = ZSS_STATUS_ERROR; + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_SEVERE, ZSS_LOG_TLS_INIT_MSG, rc, tlsStrError(rc)); + goto out_term_stcbase; + } + server = makeSecureHttpServer(base, inetAddress, port, env, requiredTLSFlag, &returnCode, &reasonCode); } else { server = makeHttpServer2(base, inetAddress, port, requiredTLSFlag, &returnCode, &reasonCode); } @@ -1553,11 +1443,11 @@ int main(int argc, char **argv){ zssStatus = ZSS_STATUS_ERROR; goto out_term_stcbase; } - ApimlStorageSettings *apimlStorageSettings = readApimlStorageSettings(slh, mvdSettings, envSettings, tlsEnv); server->defaultProductURLPrefix = PRODUCT; initializePluginIDHashTable(server); + initializeAuthHandlers(server); loadWebServerConfig(server, mvdSettings, envSettings, htUsers, htGroups, defaultSeconds); - readWebPluginDefinitions(server, slh, pluginsDir, serverConfigFile, apimlStorageSettings); + readWebPluginDefinitions(server, slh, pluginsDir, serverConfigFile); installCertificateService(server); installUnixFileContentsService(server); installUnixFileRenameService(server); diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 552f55129..56d3941a8 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 552f551295be87081241c409870047c8c2914335 +Subproject commit 56d3941a822b1a76702b921f06256650b1e5783a From 63ce32fa9ffb0c6075c8465af0e958a2e1ce5468 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Fri, 4 Jun 2021 22:28:22 -0400 Subject: [PATCH 19/68] Fixed merge conflicts Signed-off-by: Leanid Astrakou --- c/zss.c | 96 ++++++++++++++++++++++++++++++++++------------ deps/zowe-common-c | 2 +- 2 files changed, 73 insertions(+), 25 deletions(-) diff --git a/c/zss.c b/c/zss.c index ab23e11e1..04a969de8 100644 --- a/c/zss.c +++ b/c/zss.c @@ -79,6 +79,8 @@ #ifdef USE_ZOWE_TLS #include "tls.h" #endif // USE_ZOWE_TLS +#include "storage.h" +#include "storageApiml.h" #define PRODUCT "ZLUX" #ifndef PRODUCT_MAJOR_VERSION @@ -120,10 +122,12 @@ static JsonObject *readPluginDefinition(ShortLivedHeap *slh, char *pluginIdentifier, char *resolvedPluginLocation); static WebPluginListElt* readWebPluginDefinitions(HttpServer* server, ShortLivedHeap *slh, char *dirname, - const char *serverConfigFile); + const char *serverConfigFile, ApimlStorageSettings *apimlStorageSettings); static JsonObject *readServerSettings(ShortLivedHeap *slh, const char *filename); static hashtable *getServerTimeoutsHt(ShortLivedHeap *slh, Json *serverTimeouts, const char *key); static InternalAPIMap *makeInternalAPIMap(void); +static bool readGatewaySettings(JsonObject *serverConfig, JsonObject *envConfig, char **outGatewayHost, int *outGatewayPort); +static bool isCachingServiceEnabled(JsonObject *serverConfig, JsonObject *envConfig); static int authHandlerFunction(); static int servePluginDefinitions(HttpService *service, HttpResponse *response){ @@ -761,7 +765,8 @@ static int checkLoggingVerbosity(const char *serverConfigFile, char *pluginIdent } static WebPluginListElt* readWebPluginDefinitions(HttpServer *server, ShortLivedHeap *slh, char *dirname, - const char *serverConfigFile) { + const char *serverConfigFile, + ApimlStorageSettings *apimlStorageSettings) { int pluginDefinitionCount = 0; int returnCode; int reasonCode; @@ -870,6 +875,40 @@ static WebPluginListElt* readWebPluginDefinitions(HttpServer *server, ShortLived return webPluginListHead; } +static ApimlStorageSettings *readApimlStorageSettings(ShortLivedHeap *slh, JsonObject *serverConfig, JsonObject *envConfig, TlsEnvironment *tlsEnv) { + char *host = NULL; + int port = 0; + bool configured = false; + + do { + if (!isCachingServiceEnabled(serverConfig, envConfig)) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG, "Caching Service disabled\n"); + break; + } + if (!readGatewaySettings(serverConfig, envConfig, &host, &port)) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG, "Gateway settings not found\n"); + break; + } + if (!tlsEnv) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG, "TLS settings not found\n"); + break; + } + configured = true; + } while(0); + + if (!configured) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_CACHE_NOT_CFG_MSG); + return NULL; + } + ApimlStorageSettings *settings = (ApimlStorageSettings*)SLHAlloc(slh, sizeof(*settings)); + memset(settings, 0, sizeof(*settings)); + settings->host = host; + settings->port = port; + settings->tlsEnv = tlsEnv; + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_CACHE_SETTINGS_MSG settings->host, settings->port); + return settings; +} + static const char defaultConfigPath[] = "../defaults/serverConfig/server.json"; static @@ -923,6 +962,7 @@ static void initLoggingComponents(void) { logConfigureComponent(NULL, LOG_COMP_DATASERVICE, "ZSS dataservices", LOG_DEST_PRINTF_STDOUT, ZOWE_LOG_INFO); logConfigureComponent(NULL, LOG_COMP_ID_MVD_SERVER, "ZSS server", LOG_DEST_PRINTF_STDOUT, ZOWE_LOG_INFO); logConfigureComponent(NULL, LOG_COMP_ID_CTDS, "CT/DS", LOG_DEST_PRINTF_STDOUT, ZOWE_LOG_INFO); + logConfigureComponent(NULL, LOG_COMP_ID_APIML_STORAGE, "APIML Storage", LOG_DEST_PRINTF_STDOUT, ZOWE_LOG_INFO); zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_ZSS_START_VER_MSG, productVersion); } @@ -1002,7 +1042,7 @@ static bool readAgentHttpsSettings(ShortLivedHeap *slh, JsonObject *envConfig, char **outAddress, int *outPort, - TlsSettings **outSettings + TlsEnvironment **outTlsEnv ) { int port = jsonObjectGetNumber(envConfig, ENV_AGENT_HTTPS_KEY(PORT_KEY)); char *address = jsonObjectGetString(envConfig, ENV_AGENT_HTTPS_KEY(IP_ADDRESSES_KEY)); @@ -1047,11 +1087,24 @@ static bool readAgentHttpsSettings(ShortLivedHeap *slh, if (!address) { address = "127.0.0.1"; } - bool httpsSettingsFound = port && settings->keyring; - if (httpsSettingsFound) { + bool isHttpsConfigured = port && settings->keyring; + if (settings->keyring) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_TLS_SETTINGS_MSG, + settings->keyring, + settings->label ? settings->label : "(no label)", + settings->password ? "****" : "(no password)", + settings->stash ? settings->stash : "(no stash)"); + TlsEnvironment *tlsEnv = NULL; + int rc = tlsInit(&tlsEnv, settings); + if (rc != 0) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_WARNING, ZSS_LOG_TLS_INIT_MSG, rc, tlsStrError(rc)); + } else { + *outTlsEnv = tlsEnv; + } + } + if (isHttpsConfigured) { *outPort = port; *outAddress = address; - *outSettings = settings; } return isHttpsConfigured; } @@ -1526,8 +1579,14 @@ int main(int argc, char **argv){ int port = 0; char *address = NULL; TlsSettings *tlsSettings = NULL; - bool httpsSettingsFound = readAgentHttpsSettings(slh, mvdSettings, envSettings, &address, &port, &tlsSettings); - if (!httpsSettingsFound) { + TlsEnvironment *tlsEnv = NULL; + bool isHttpsConfigured = readAgentHttpsSettings(slh, mvdSettings, envSettings, &address, &port, &tlsEnv); + if (isHttpsConfigured && !tlsEnv) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_SEVERE, ZSS_LOG_HTTPS_INVALID_MSG); + zssStatus = ZSS_STATUS_ERROR; + goto out_term_stcbase; + } + if (!isHttpsConfigured) { readAgentAddressAndPort(mvdSettings, envSettings, &address, &port); } InetAddr *inetAddress = NULL; @@ -1538,21 +1597,9 @@ int main(int argc, char **argv){ goto out_term_stcbase; } - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_ZSS_SETTINGS_MSG, address, port, httpsSettingsFound ? "https" : "http"); - if (httpsSettingsFound) { - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_TLS_SETTINGS_MSG, - tlsSettings->keyring, - tlsSettings->label ? tlsSettings->label : "(no label)", - tlsSettings->password ? "****" : "(no password)", - tlsSettings->stash ? tlsSettings->stash : "(no stash)"); - TlsEnvironment *env = NULL; - int rc = tlsInit(&env, tlsSettings); - if (rc != 0) { - zssStatus = ZSS_STATUS_ERROR; - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_SEVERE, ZSS_LOG_TLS_INIT_MSG, rc, tlsStrError(rc)); - goto out_term_stcbase; - } - server = makeSecureHttpServer(base, inetAddress, port, env, requiredTLSFlag, &returnCode, &reasonCode); + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_INFO, ZSS_LOG_ZSS_SETTINGS_MSG, address, port, isHttpsConfigured ? "https" : "http"); + if (isHttpsConfigured) { + server = makeSecureHttpServer(base, inetAddress, port, tlsEnv, requiredTLSFlag, &returnCode, &reasonCode); } else { server = makeHttpServer2(base, inetAddress, port, requiredTLSFlag, &returnCode, &reasonCode); } @@ -1561,11 +1608,12 @@ int main(int argc, char **argv){ zssStatus = ZSS_STATUS_ERROR; goto out_term_stcbase; } + ApimlStorageSettings *apimlStorageSettings = readApimlStorageSettings(slh, mvdSettings, envSettings, tlsEnv); server->defaultProductURLPrefix = PRODUCT; initializePluginIDHashTable(server); initializeAuthHandlers(server); loadWebServerConfig(server, mvdSettings, envSettings, htUsers, htGroups, defaultSeconds); - readWebPluginDefinitions(server, slh, pluginsDir, serverConfigFile); + readWebPluginDefinitions(server, slh, pluginsDir, serverConfigFile, apimlStorageSettings); installCertificateService(server); installUnixFileContentsService(server); installUnixFileRenameService(server); diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 56d3941a8..faa29df37 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 56d3941a822b1a76702b921f06256650b1e5783a +Subproject commit faa29df37da060890f6a38f5e3a0430ee1db6ecb From a132c8b8b4a297f411f4c76fc303c88a240141ec Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Sun, 6 Jun 2021 22:39:48 -0400 Subject: [PATCH 20/68] Updated zowe-common-c Signed-off-by: Leanid Astrakou --- c/zss.c | 36 ++++++++++++++++++++++++++++-------- deps/zowe-common-c | 2 +- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/c/zss.c b/c/zss.c index 04a969de8..42e96eaa7 100644 --- a/c/zss.c +++ b/c/zss.c @@ -346,17 +346,37 @@ static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpReques return -1; } +/* Future custom ZSS authorization handlers go here */ static void initializeAuthHandlers(HttpServer *server) { - void *handler = server->authHandler; - char arr[][1024] = { - "NATIVE_WITH_SESSION_TOKEN", // TODO: authHandlers needs to be an array - }; - //int size = sizeof arr / sizeof arr[0]; + // void *handler = server->authHandler; + // char arr[][1024] = { + // "NATIVE_WITH_SESSION_TOKEN", // TODO: authHandlers needs to be an array + // }; + /* NATIVE_WITH_SESSION_TOKEN */ - server->authHandler->type = "NATIVE_WITH_SESSION_TOKEN"; // TODO: Needs to come from constants in httpserver.h - server->authHandler->authFunction = &nativeWithSessionTokenAuth; -} + server->authHandler[0] = (HttpAuthHandler*)safeMalloc31(sizeof(HttpAuthHandler),"HttpAuthHandler"); + server->authHandler[0]->type = "NATIVE_WITH_SESSION_TOKEN"; // TODO: Needs to come from constants in httpserver.h + server->authHandler[0]->authFunction = &nativeWithSessionTokenAuth; + // int size = sizeof server->authHandler / sizeof server->authHandler[0]; + + // if (server->authHandler[0] == NULL) { + // printf("\n\n\n\nFIRST NULL %d %s %s\n\n\n\n", size, server->authHandler[0], server->authHandler[1]); + + // } + // if (server->authHandler[1] == NULL) { + // printf("\n\n\n\nAFTER FIRST NULL %d %s %s\n\n\n\n", size, server->authHandler[0]->type, server->authHandler[1]); + + // } + // if (server->authHandler[0]->type == NULL) { + // printf("\n\n\n\nSECOND NULL %d %s %s\n\n\n\n", size, server->authHandler[0]->type, server->authHandler[1]); + + // } + // if (server->authHandler[1]->type == NULL) { + // printf("\n\n\n\nTHIRD NULL %d %s %s\n\n\n\n", size, server->authHandler[0]->type, server->authHandler[1]); + + // } + } static void loadWebServerConfig(HttpServer *server, JsonObject *mvdSettings, JsonObject *envSettings, hashtable *htUsers, diff --git a/deps/zowe-common-c b/deps/zowe-common-c index faa29df37..f6d670dff 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit faa29df37da060890f6a38f5e3a0430ee1db6ecb +Subproject commit f6d670dffbd061a2ba23a114ddb3be99ca853846 From 0c1b0f5c1e872b9ff107749fb8f77e962309b297 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Mon, 7 Jun 2021 09:59:57 -0400 Subject: [PATCH 21/68] Changed authType to string Signed-off-by: Leanid Astrakou --- c/zss.c | 26 ++------------------------ deps/zowe-common-c | 2 +- 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/c/zss.c b/c/zss.c index 42e96eaa7..65d048314 100644 --- a/c/zss.c +++ b/c/zss.c @@ -348,35 +348,13 @@ static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpReques /* Future custom ZSS authorization handlers go here */ static void initializeAuthHandlers(HttpServer *server) { - // void *handler = server->authHandler; - // char arr[][1024] = { - // "NATIVE_WITH_SESSION_TOKEN", // TODO: authHandlers needs to be an array - // }; - /* NATIVE_WITH_SESSION_TOKEN */ server->authHandler[0] = (HttpAuthHandler*)safeMalloc31(sizeof(HttpAuthHandler),"HttpAuthHandler"); - server->authHandler[0]->type = "NATIVE_WITH_SESSION_TOKEN"; // TODO: Needs to come from constants in httpserver.h + server->authHandler[0]->type = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; server->authHandler[0]->authFunction = &nativeWithSessionTokenAuth; - // int size = sizeof server->authHandler / sizeof server->authHandler[0]; - - // if (server->authHandler[0] == NULL) { - // printf("\n\n\n\nFIRST NULL %d %s %s\n\n\n\n", size, server->authHandler[0], server->authHandler[1]); - - // } - // if (server->authHandler[1] == NULL) { - // printf("\n\n\n\nAFTER FIRST NULL %d %s %s\n\n\n\n", size, server->authHandler[0]->type, server->authHandler[1]); - - // } - // if (server->authHandler[0]->type == NULL) { - // printf("\n\n\n\nSECOND NULL %d %s %s\n\n\n\n", size, server->authHandler[0]->type, server->authHandler[1]); - // } - // if (server->authHandler[1]->type == NULL) { - // printf("\n\n\n\nTHIRD NULL %d %s %s\n\n\n\n", size, server->authHandler[0]->type, server->authHandler[1]); - - // } - } +} static void loadWebServerConfig(HttpServer *server, JsonObject *mvdSettings, JsonObject *envSettings, hashtable *htUsers, diff --git a/deps/zowe-common-c b/deps/zowe-common-c index f6d670dff..f8e6a20d7 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit f6d670dffbd061a2ba23a114ddb3be99ca853846 +Subproject commit f8e6a20d7f7c3c0a9e81402445574bf9a3c51fcc From 4c5018673ce777ae6a22b7493c2278a35a404c2c Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Mon, 7 Jun 2021 10:04:56 -0400 Subject: [PATCH 22/68] Missed a few things Signed-off-by: Leanid Astrakou --- deps/zowe-common-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zowe-common-c b/deps/zowe-common-c index f8e6a20d7..1b55568e9 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit f8e6a20d7f7c3c0a9e81402445574bf9a3c51fcc +Subproject commit 1b55568e910c888aadfdb6b4f4c1695fe7217544 From 8da72469fcc43c91d6a8b047c8450f55eee8c02d Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Mon, 7 Jun 2021 10:15:37 -0400 Subject: [PATCH 23/68] Removed comments Signed-off-by: Leanid Astrakou --- c/authService.c | 15 +-------------- h/authService.h | 2 +- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/c/authService.c b/c/authService.c index a4c2168b3..ebe9625c5 100644 --- a/c/authService.c +++ b/c/authService.c @@ -65,7 +65,7 @@ * } */ -int serveAuthCheck(HttpService *service, HttpResponse *response); +static int serveAuthCheck(HttpService *service, HttpResponse *response); int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char* entity, int access); @@ -179,8 +179,6 @@ int serveAuthCheck(HttpService *service, HttpResponse *res) { char *uri = safeMalloc(1024, "uri"); snprintf(uri, 1024, "%s", req->uri); destructivelyNativize(uri); - // TODO: Remove printf's for a merge - printf("\n\n\nBegin with this URI %s\n\n\n", uri); ZISAuthServiceStatus reqStatus = {0}; CrossMemoryServerName *privilegedServerName; const char *userName = req->username, *class = SAF_CLASS; @@ -194,17 +192,10 @@ int serveAuthCheck(HttpService *service, HttpResponse *res) { respondWithError(res, HTTP_STATUS_BAD_REQUEST, "Unexpected access level"); return 0; } - printf("\n\n\naccessStr - %s : entity - %s : rc - %d : parsedFile - %s\n\n\n", accessStr, entity, rc, req->parsedFile); - - // printf("\n\nquery: user %s, class %s, entity %s, access %d accessStr %s\n", userName, class, - // entity, access, accessStr); privilegedServerName = getConfiguredProperty(service->server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); - printf("\n\n\nRESULTS OF ZISCHECKENTITY privilegedServerName - %s : userName - %s : class - %s : entity - %s : access - %d: reqstatus - %s : rc - %d\n\n\n", privilegedServerName, userName, class, entity, access, - &reqStatus, rc); - respond(res, rc, &reqStatus); return 0; } @@ -221,8 +212,6 @@ int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, ch } rc = zisCheckEntity(privilegedServerName, userName, Class, entity, access, &reqStatus); - printf("\n\n\nRESULTS OF serveAuthCheckByParams privilegedServerName - %s : userName - %s : class - %s : entity - %s : access - %d: reqstatus - %s : rc - %d\n\n\n", privilegedServerName, userName, Class, entity, access, - &reqStatus, rc); return rc; } @@ -427,8 +416,6 @@ static const char* makeProfileName( return profileName; } -/* Method goes here to do the same thing serveAuthCheck is doing except w/o input HttpService */ - void respondWithJsonStatus(HttpResponse *response, const char *status, int statusCode, const char *statusMessage) { jsonPrinter *out = respondWithJsonPrinter(response); setResponseStatus(response,statusCode,(char *)statusMessage); diff --git a/h/authService.h b/h/authService.h index afcd638fa..ff462b351 100644 --- a/h/authService.h +++ b/h/authService.h @@ -29,7 +29,7 @@ int installAuthCheckService(HttpServer *server); void installZosPasswordService(HttpServer *server); const char* getProfileNameFromRequest(char *profileName, char *url, char *method, int instanceID); -int serveAuthCheck(HttpService *service, HttpResponse *res); +static int serveAuthCheck(HttpService *service, HttpResponse *res); int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access); From f11219fc61147e356c6cd2e7ff2e6ef7a48c146f Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Mon, 7 Jun 2021 11:52:48 -0400 Subject: [PATCH 24/68] Updated zowe-common-c Signed-off-by: Leanid Astrakou --- deps/zowe-common-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 1b55568e9..c5c9bacc0 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 1b55568e910c888aadfdb6b4f4c1695fe7217544 +Subproject commit c5c9bacc024bf4548eeeaa8f2bd16b125b2fdaae From efde2a247672e99ffe0b18aee7be2d11bdc6f907 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Mon, 7 Jun 2021 18:23:34 -0400 Subject: [PATCH 25/68] Removed leftover comments Signed-off-by: Leanid Astrakou --- c/zss.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/c/zss.c b/c/zss.c index 65d048314..3b374fb69 100644 --- a/c/zss.c +++ b/c/zss.c @@ -336,10 +336,7 @@ static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpReques destructivelyNativize(uri); destructivelyNativize(method); char *profileName = safeMalloc(1024, "profileName"); - // TODO: Remove printf's (not ready for merge) - printf("\n\n\nURI, METHOD, PROFILENAME PRE CONVERSION: %s - %s - %s - (old) %s\n\n", uri, method, profileName, request->uri); getProfileNameFromRequest(profileName, uri, method, -1); - printf("\n\n\nURI, METHOD, PROFILENAME POST CONVERSION %s - %s - %s\n\n", uri, method, profileName); int rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2); return rc; } From 0add3ecd7730af22cfb29cdf653e6d9ab11c472d Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Fri, 11 Jun 2021 02:45:49 -0400 Subject: [PATCH 26/68] Code review adjustments from Irek Signed-off-by: Leanid Astrakou --- c/authService.c | 125 ++++++++++++++++++++++++++------------------- c/zss.c | 6 +-- deps/zowe-common-c | 2 +- h/authService.h | 25 ++++++++- 4 files changed, 99 insertions(+), 59 deletions(-) diff --git a/c/authService.c b/c/authService.c index ebe9625c5..91dc9ab76 100644 --- a/c/authService.c +++ b/c/authService.c @@ -38,6 +38,7 @@ #define SAF_CLASS "ZOWE" #define JSON_ERROR_BUFFER_SIZE 1024 +#define SAF_SUB_URL_SIZE 16 #define SAF_PASSWORD_RESET_RC_OK 0 #define SAF_PASSWORD_RESET_RC_WRONG_PASSWORD 111 @@ -69,7 +70,7 @@ static int serveAuthCheck(HttpService *service, HttpResponse *response); int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char* entity, int access); -const char* getProfileNameFromRequest(char *profileName, char *url, const char *method, int instanceID); +const char* getProfileNameFromRequest(char *profileName, char *url, const char *method, int instanceID, HttpResponse *response); static const char* makeProfileName( const char *type, @@ -80,7 +81,14 @@ static const char* makeProfileName( const char *serviceName, const char *method, const char *scope, - char subUrl[15][1024]); + char subUrl[SAF_SUB_URL_SIZE][JSON_ERROR_BUFFER_SIZE]); + +static void setProfileNameAttribs( + char *pluginID, + char *serviceName, + char *type, + char *scope, + char subUrl[SAF_SUB_URL_SIZE][JSON_ERROR_BUFFER_SIZE]); int installAuthCheckService(HttpServer *server) { // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "begin %s\n", @@ -171,14 +179,11 @@ static void respond(HttpResponse *res, int rc, const ZISAuthServiceStatus finishResponse(res); } -int serveAuthCheck(HttpService *service, HttpResponse *res) { +static int serveAuthCheck(HttpService *service, HttpResponse *res) { HttpRequest *req = res->request; char *entity, *accessStr; int access = 0; int rc = 0, rsn = 0, safStatus = 0; - char *uri = safeMalloc(1024, "uri"); - snprintf(uri, 1024, "%s", req->uri); - destructivelyNativize(uri); ZISAuthServiceStatus reqStatus = {0}; CrossMemoryServerName *privilegedServerName; const char *userName = req->username, *class = SAF_CLASS; @@ -192,10 +197,12 @@ int serveAuthCheck(HttpService *service, HttpResponse *res) { respondWithError(res, HTTP_STATUS_BAD_REQUEST, "Unexpected access level"); return 0; } + privilegedServerName = getConfiguredProperty(service->server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); + respond(res, rc, &reqStatus); return 0; } @@ -215,13 +222,14 @@ int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, ch return rc; } -const char* getProfileNameFromRequest(char *profileName, char *url, char *method, int instanceID) { +const char* getProfileNameFromRequest(char *profileName, char *url, char *method, int instanceID, HttpResponse *response) { char type[8]; // core || config || service - char productCode[1024]; - char rootServiceName[1024]; - char subUrl[15][1024]; - char scope[1024]; - char placeHolder1[1024], pluginID[1024], placeHolder2[1024], serviceName[1024], placeHolder3[1024]; + char productCode[JSON_ERROR_BUFFER_SIZE]; + char rootServiceName[JSON_ERROR_BUFFER_SIZE]; + char subUrl[SAF_SUB_URL_SIZE][JSON_ERROR_BUFFER_SIZE]; + char scope[JSON_ERROR_BUFFER_SIZE]; + char placeHolder1[JSON_ERROR_BUFFER_SIZE], pluginID[JSON_ERROR_BUFFER_SIZE], placeHolder2[JSON_ERROR_BUFFER_SIZE], + serviceName[JSON_ERROR_BUFFER_SIZE], placeHolder3[JSON_ERROR_BUFFER_SIZE]; char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; regex_t regex; @@ -231,88 +239,82 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method if (profileName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_SEVERE, "safeMalloc failed. Not enough memory"); + respondWithError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Not enough memory"); return NULL; } - if (value != 0) { + if (value == 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, "RegEx compiled successfully."); } else { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, "RegEx compilation error %s.", regexStr); + respondWithError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "RegEx compilation error"); + return NULL; } value = regexec(®ex, url, 0, NULL, 0); - char urlCpy[1024]; - snprintf(urlCpy, 1024, url); - int index = 0; - while (urlCpy[index]) { // Capitalize query - urlCpy[index] = toupper(urlCpy[index]); - index++; - } + strupcase(url); if (instanceID < 0) { // Set instanceID instanceID = 0; } if (value == REG_NOMATCH) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, "RegEx didn't match."); - char * token = strtok(urlCpy, "/"); + char *context = NULL; + char *token = strtok_r(url, "/", &context); int subUrlIndex = -1; while( token != NULL ) { if (rootServiceName == NULL) { - snprintf(rootServiceName, 1024, token); + snprintf(rootServiceName, JSON_ERROR_BUFFER_SIZE, token); } else { - snprintf(subUrl[subUrlIndex], 1024, token); + if (subUrlIndex < SAF_SUB_URL_SIZE) { + snprintf(subUrl[subUrlIndex], JSON_ERROR_BUFFER_SIZE, token); + } } subUrlIndex++; - token = strtok(NULL, "/"); + token = strtok_r(NULL, "/", &context); } - snprintf(productCode, 1024, "ZLUX"); - snprintf(type, 1024, "core"); + snprintf(productCode, JSON_ERROR_BUFFER_SIZE, "ZLUX"); + snprintf(type, JSON_ERROR_BUFFER_SIZE, "core"); } else if (!value) { - char * token = strtok(urlCpy, "/"); + char *context = NULL; + char *token = strtok_r(url, "/", &context); int subUrlIndex; subUrlIndex = 0; while( token != NULL ) { switch(subUrlIndex) { case 0: - snprintf(productCode, 1024, token); + snprintf(productCode, JSON_ERROR_BUFFER_SIZE, token); break; case 1: - snprintf(placeHolder1, 1024, token); + snprintf(placeHolder1, JSON_ERROR_BUFFER_SIZE, token); break; case 2: - snprintf(pluginID, 1024, token); + snprintf(pluginID, JSON_ERROR_BUFFER_SIZE, token); break; case 3: - snprintf(placeHolder2, 1024, token); + snprintf(placeHolder2, JSON_ERROR_BUFFER_SIZE, token); break; case 4: - snprintf(serviceName, 1024, token); + snprintf(serviceName, JSON_ERROR_BUFFER_SIZE, token); break; case 5: - snprintf(placeHolder3, 1024, token); + snprintf(placeHolder3, JSON_ERROR_BUFFER_SIZE, token); break; default: - snprintf(subUrl[subUrlIndex-6], 1024, token); // subtract 6 from maximum index to begin init subUrl array at 0 + snprintf(subUrl[subUrlIndex-6], JSON_ERROR_BUFFER_SIZE, token); // subtract 6 from maximum index to begin init subUrl array at 0 } subUrlIndex++; - token = strtok(NULL, "/"); - } - if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) - { - snprintf(type, 1024, "config"); - snprintf(pluginID, 1024, subUrl[0]); - snprintf(scope, 1024, subUrl[1]); - - } else { - snprintf(type, 1024, "service"); + token = strtok_r(NULL, "/", &context); } + setProfileNameAttribs(pluginID, serviceName, type, scope, subUrl); char* ch; char* chReplace; ch = "."; chReplace = "_"; + int index = 0; for (index = 0; index <= strlen(pluginID); index++) { if (pluginID[index] == *ch) @@ -327,7 +329,7 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "RegEx match failed."); } - snprintf(profileName, 1024, makeProfileName(type, + snprintf(profileName, JSON_ERROR_BUFFER_SIZE, makeProfileName(type, productCode, instanceID, pluginID, @@ -343,6 +345,23 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method return profileName; } +static void setProfileNameAttribs( + char *pluginID, + char *serviceName, + char *type, + char *scope, + char subUrl[SAF_SUB_URL_SIZE][JSON_ERROR_BUFFER_SIZE]) { + if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) + { + snprintf(type, JSON_ERROR_BUFFER_SIZE, "config"); + snprintf(pluginID, JSON_ERROR_BUFFER_SIZE, subUrl[0]); + snprintf(scope, JSON_ERROR_BUFFER_SIZE, subUrl[1]); + + } else { + snprintf(type, JSON_ERROR_BUFFER_SIZE, "service"); + } +} + static const char* makeProfileName( const char *type, const char *productCode, @@ -352,8 +371,8 @@ static const char* makeProfileName( const char *serviceName, const char *method, const char *scope, - char subUrl[15][1024]) { - char *profileName = safeMalloc(1024, "profileNameInner"); + char subUrl[SAF_SUB_URL_SIZE][JSON_ERROR_BUFFER_SIZE]) { + char *profileName = safeMalloc(JSON_ERROR_BUFFER_SIZE, "profileNameInner"); if (profileName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_SEVERE, "safeMalloc failed. Not enough memory"); @@ -374,7 +393,7 @@ static const char* makeProfileName( "Broken SAF query. Missing method."); return NULL; } - // char someString[1024] = { snprintf(*someString, 1024, type) }; + // char someString[JSON_ERROR_BUFFER_SIZE] = { snprintf(*someString, JSON_ERROR_BUFFER_SIZE, type) }; if (strcmp(type, "service") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, @@ -386,7 +405,7 @@ static const char* makeProfileName( "Broken SAF query. Missing service name."); return NULL; } - snprintf(profileName, 1024, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); + snprintf(profileName, JSON_ERROR_BUFFER_SIZE, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); } else if (strcmp(type, "config") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, @@ -398,19 +417,19 @@ static const char* makeProfileName( "Broken SAF query. Missing scope."); return NULL; } - snprintf(profileName, 1024, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); + snprintf(profileName, JSON_ERROR_BUFFER_SIZE, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); } else if (strcmp(type, "core") == 0) { if (rootServiceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing root service name."); return NULL; } - snprintf(profileName, 1024, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + snprintf(profileName, JSON_ERROR_BUFFER_SIZE, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); } // Child endpoints housed via subUrl int index = 0; - while (index < 15 && strcmp(subUrl[index], "") != 0) { - snprintf(profileName, 1024, "%s.%s", profileName, subUrl[index]); + while (index < SAF_SUB_URL_SIZE && strcmp(subUrl[index], "") != 0) { + snprintf(profileName, JSON_ERROR_BUFFER_SIZE, "%s.%s", profileName, subUrl[index]); index++; } return profileName; diff --git a/c/zss.c b/c/zss.c index 3b374fb69..6bde38eef 100644 --- a/c/zss.c +++ b/c/zss.c @@ -325,7 +325,7 @@ static void setPrivilegedServerName(HttpServer *server, JsonObject *mvdSettings, } #endif /* __ZOWE_OS_ZOS */ -static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpRequest *request, HttpService *service) { +static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpRequest *request, HttpService *service, HttpResponse *response) { if (conversation->parser) { HttpRequestParser *parser = conversation->parser; char *method = safeMalloc(1024, "method"); @@ -336,7 +336,7 @@ static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpReques destructivelyNativize(uri); destructivelyNativize(method); char *profileName = safeMalloc(1024, "profileName"); - getProfileNameFromRequest(profileName, uri, method, -1); + getProfileNameFromRequest(profileName, uri, method, -1, response); int rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2); return rc; } @@ -703,7 +703,7 @@ static void installLoginService(HttpServer *server) { zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); HttpService *httpService = makeGeneratedService("com.rs.mvd.login", "/login/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->serviceFunction = serveLoginWithSessionToken; httpService->authExtractionFunction = extractAuthorizationFromJson; registerHttpService(server, httpService); diff --git a/deps/zowe-common-c b/deps/zowe-common-c index c5c9bacc0..1673b5f82 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit c5c9bacc024bf4548eeeaa8f2bd16b125b2fdaae +Subproject commit 1673b5f825570481e3452e68e90be8e6e0279227 diff --git a/h/authService.h b/h/authService.h index ff462b351..03efbf7b9 100644 --- a/h/authService.h +++ b/h/authService.h @@ -28,8 +28,29 @@ int installAuthCheckService(HttpServer *server); void installZosPasswordService(HttpServer *server); -const char* getProfileNameFromRequest(char *profileName, char *url, char *method, int instanceID); -static int serveAuthCheck(HttpService *service, HttpResponse *res); + +/** + * @brief The function uses makeProfileName function to generate profile name for SAF query + * @param profileName Generated profile name goes here + * @param url Refers to the URL used to generate query + * @param instanceID Refers to instanceID for query. If none specified, or negative, then 0 + * @param HttpResponse Describes the HttpResponse object to return if error encountered + * + * @return Return generated profile name or NULL if error + */ +const char* getProfileNameFromRequest(char *profileName, char *url, char *method, int instanceID, HttpResponse *response); + +/** + * @brief The function satisfies RBAC, by first checking if RBAC is enabled, then executing + * a ZIS check. + * @param service The calling HttpService + * @param userName Username to use in ZIS check + * @param Class Class to use in ZIS check i.e. "ZOWE" + * @param entity Describes the SAF query itself i.e. "ZLUX.0.COR.GET.SERVER.AGENT.CONFIG" + * @param access Describes the access type i.e. "READ" + * + * @return Return code where != 0 is a failed RBAC check + */ int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access); From 3eaf7a01f271090a38346053045118546b065adc Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Fri, 11 Jun 2021 10:16:25 -0400 Subject: [PATCH 27/68] Don't use URL query params in SAF query Signed-off-by: Leanid Astrakou --- c/zss.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/c/zss.c b/c/zss.c index 6bde38eef..acf599e29 100644 --- a/c/zss.c +++ b/c/zss.c @@ -101,6 +101,8 @@ static JsonObject *MVD_SETTINGS = NULL; static int traceLevel = 0; #define JSON_ERROR_BUFFER_SIZE 1024 +#define ZOWE_PROFILE_NAME_LEN 246 + #define DEFAULT_TLS_CIPHERS \ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 \ @@ -328,18 +330,24 @@ static void setPrivilegedServerName(HttpServer *server, JsonObject *mvdSettings, static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpRequest *request, HttpService *service, HttpResponse *response) { if (conversation->parser) { HttpRequestParser *parser = conversation->parser; - char *method = safeMalloc(1024, "method"); - char *uri = safeMalloc(1024, "uri"); - char *username = safeMalloc(1024, "username"); - snprintf(uri, 1024, "%s", request->uri); - snprintf(method, 1024, "%s", request->method); - destructivelyNativize(uri); + char *method = safeMalloc(JSON_ERROR_BUFFER_SIZE, "method"); + char *uri = safeMalloc(JSON_ERROR_BUFFER_SIZE, "uri"); + char *username = safeMalloc(JSON_ERROR_BUFFER_SIZE, "username"); + snprintf(uri, JSON_ERROR_BUFFER_SIZE, "%s", stringListPrint(request->parsedFile, 0, 1000, "/", 0)); + snprintf(method, JSON_ERROR_BUFFER_SIZE, "%s", request->method); destructivelyNativize(method); - char *profileName = safeMalloc(1024, "profileName"); + char *profileName = safeMalloc(JSON_ERROR_BUFFER_SIZE, "profileName"); getProfileNameFromRequest(profileName, uri, method, -1, response); + if (strlen(profileName) > ZOWE_PROFILE_NAME_LEN) { + char *errMsg = safeMalloc(JSON_ERROR_BUFFER_SIZE, "errMsg"); + snprintf(errMsg, JSON_ERROR_BUFFER_SIZE, "Generated SAF query longer than %d", ZOWE_PROFILE_NAME_LEN); + respondWithError(response, HTTP_STATUS_BAD_REQUEST, errMsg); + return -2; + } int rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2); return rc; } + respondWithError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Conversation object corrupt"); return -1; } From f35aa89a19129efdc18dc28001d7e7e75da8ace7 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Fri, 11 Jun 2021 12:52:51 -0400 Subject: [PATCH 28/68] Changed #define value name to be more relevant Signed-off-by: Leanid Astrakou --- c/authService.c | 65 +++++++++++++++++++++++++------------------------ c/zss.c | 15 ++++++------ 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/c/authService.c b/c/authService.c index 91dc9ab76..3b496bffd 100644 --- a/c/authService.c +++ b/c/authService.c @@ -38,6 +38,7 @@ #define SAF_CLASS "ZOWE" #define JSON_ERROR_BUFFER_SIZE 1024 +#define CHAR_BUFFER_SIZE 1024 #define SAF_SUB_URL_SIZE 16 #define SAF_PASSWORD_RESET_RC_OK 0 @@ -81,14 +82,14 @@ static const char* makeProfileName( const char *serviceName, const char *method, const char *scope, - char subUrl[SAF_SUB_URL_SIZE][JSON_ERROR_BUFFER_SIZE]); + char subUrl[SAF_SUB_URL_SIZE][CHAR_BUFFER_SIZE]); static void setProfileNameAttribs( char *pluginID, char *serviceName, char *type, char *scope, - char subUrl[SAF_SUB_URL_SIZE][JSON_ERROR_BUFFER_SIZE]); + char subUrl[SAF_SUB_URL_SIZE][CHAR_BUFFER_SIZE]); int installAuthCheckService(HttpServer *server) { // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "begin %s\n", @@ -224,12 +225,12 @@ int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, ch const char* getProfileNameFromRequest(char *profileName, char *url, char *method, int instanceID, HttpResponse *response) { char type[8]; // core || config || service - char productCode[JSON_ERROR_BUFFER_SIZE]; - char rootServiceName[JSON_ERROR_BUFFER_SIZE]; - char subUrl[SAF_SUB_URL_SIZE][JSON_ERROR_BUFFER_SIZE]; - char scope[JSON_ERROR_BUFFER_SIZE]; - char placeHolder1[JSON_ERROR_BUFFER_SIZE], pluginID[JSON_ERROR_BUFFER_SIZE], placeHolder2[JSON_ERROR_BUFFER_SIZE], - serviceName[JSON_ERROR_BUFFER_SIZE], placeHolder3[JSON_ERROR_BUFFER_SIZE]; + char productCode[CHAR_BUFFER_SIZE]; + char rootServiceName[CHAR_BUFFER_SIZE]; + char subUrl[SAF_SUB_URL_SIZE][CHAR_BUFFER_SIZE]; + char scope[CHAR_BUFFER_SIZE]; + char placeHolder1[CHAR_BUFFER_SIZE], pluginID[CHAR_BUFFER_SIZE], placeHolder2[CHAR_BUFFER_SIZE], + serviceName[CHAR_BUFFER_SIZE], placeHolder3[CHAR_BUFFER_SIZE]; char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; regex_t regex; @@ -265,17 +266,17 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method while( token != NULL ) { if (rootServiceName == NULL) { - snprintf(rootServiceName, JSON_ERROR_BUFFER_SIZE, token); + snprintf(rootServiceName, CHAR_BUFFER_SIZE, token); } else { if (subUrlIndex < SAF_SUB_URL_SIZE) { - snprintf(subUrl[subUrlIndex], JSON_ERROR_BUFFER_SIZE, token); + snprintf(subUrl[subUrlIndex], CHAR_BUFFER_SIZE, token); } } subUrlIndex++; token = strtok_r(NULL, "/", &context); } - snprintf(productCode, JSON_ERROR_BUFFER_SIZE, "ZLUX"); - snprintf(type, JSON_ERROR_BUFFER_SIZE, "core"); + snprintf(productCode, CHAR_BUFFER_SIZE, "ZLUX"); + snprintf(type, CHAR_BUFFER_SIZE, "core"); } else if (!value) { char *context = NULL; @@ -285,25 +286,25 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method while( token != NULL ) { switch(subUrlIndex) { case 0: - snprintf(productCode, JSON_ERROR_BUFFER_SIZE, token); + snprintf(productCode, CHAR_BUFFER_SIZE, token); break; case 1: - snprintf(placeHolder1, JSON_ERROR_BUFFER_SIZE, token); + snprintf(placeHolder1, CHAR_BUFFER_SIZE, token); break; case 2: - snprintf(pluginID, JSON_ERROR_BUFFER_SIZE, token); + snprintf(pluginID, CHAR_BUFFER_SIZE, token); break; case 3: - snprintf(placeHolder2, JSON_ERROR_BUFFER_SIZE, token); + snprintf(placeHolder2, CHAR_BUFFER_SIZE, token); break; case 4: - snprintf(serviceName, JSON_ERROR_BUFFER_SIZE, token); + snprintf(serviceName, CHAR_BUFFER_SIZE, token); break; case 5: - snprintf(placeHolder3, JSON_ERROR_BUFFER_SIZE, token); + snprintf(placeHolder3, CHAR_BUFFER_SIZE, token); break; default: - snprintf(subUrl[subUrlIndex-6], JSON_ERROR_BUFFER_SIZE, token); // subtract 6 from maximum index to begin init subUrl array at 0 + snprintf(subUrl[subUrlIndex-6], CHAR_BUFFER_SIZE, token); // subtract 6 from maximum index to begin init subUrl array at 0 } subUrlIndex++; @@ -329,7 +330,7 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "RegEx match failed."); } - snprintf(profileName, JSON_ERROR_BUFFER_SIZE, makeProfileName(type, + snprintf(profileName, CHAR_BUFFER_SIZE, makeProfileName(type, productCode, instanceID, pluginID, @@ -350,15 +351,15 @@ static void setProfileNameAttribs( char *serviceName, char *type, char *scope, - char subUrl[SAF_SUB_URL_SIZE][JSON_ERROR_BUFFER_SIZE]) { + char subUrl[SAF_SUB_URL_SIZE][CHAR_BUFFER_SIZE]) { if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) { - snprintf(type, JSON_ERROR_BUFFER_SIZE, "config"); - snprintf(pluginID, JSON_ERROR_BUFFER_SIZE, subUrl[0]); - snprintf(scope, JSON_ERROR_BUFFER_SIZE, subUrl[1]); + snprintf(type, CHAR_BUFFER_SIZE, "config"); + snprintf(pluginID, CHAR_BUFFER_SIZE, subUrl[0]); + snprintf(scope, CHAR_BUFFER_SIZE, subUrl[1]); } else { - snprintf(type, JSON_ERROR_BUFFER_SIZE, "service"); + snprintf(type, CHAR_BUFFER_SIZE, "service"); } } @@ -371,8 +372,8 @@ static const char* makeProfileName( const char *serviceName, const char *method, const char *scope, - char subUrl[SAF_SUB_URL_SIZE][JSON_ERROR_BUFFER_SIZE]) { - char *profileName = safeMalloc(JSON_ERROR_BUFFER_SIZE, "profileNameInner"); + char subUrl[SAF_SUB_URL_SIZE][CHAR_BUFFER_SIZE]) { + char *profileName = safeMalloc(CHAR_BUFFER_SIZE, "profileNameInner"); if (profileName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_SEVERE, "safeMalloc failed. Not enough memory"); @@ -393,7 +394,7 @@ static const char* makeProfileName( "Broken SAF query. Missing method."); return NULL; } - // char someString[JSON_ERROR_BUFFER_SIZE] = { snprintf(*someString, JSON_ERROR_BUFFER_SIZE, type) }; + // char someString[CHAR_BUFFER_SIZE] = { snprintf(*someString, CHAR_BUFFER_SIZE, type) }; if (strcmp(type, "service") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, @@ -405,7 +406,7 @@ static const char* makeProfileName( "Broken SAF query. Missing service name."); return NULL; } - snprintf(profileName, JSON_ERROR_BUFFER_SIZE, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); + snprintf(profileName, CHAR_BUFFER_SIZE, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); } else if (strcmp(type, "config") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, @@ -417,19 +418,19 @@ static const char* makeProfileName( "Broken SAF query. Missing scope."); return NULL; } - snprintf(profileName, JSON_ERROR_BUFFER_SIZE, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); + snprintf(profileName, CHAR_BUFFER_SIZE, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); } else if (strcmp(type, "core") == 0) { if (rootServiceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing root service name."); return NULL; } - snprintf(profileName, JSON_ERROR_BUFFER_SIZE, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + snprintf(profileName, CHAR_BUFFER_SIZE, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); } // Child endpoints housed via subUrl int index = 0; while (index < SAF_SUB_URL_SIZE && strcmp(subUrl[index], "") != 0) { - snprintf(profileName, JSON_ERROR_BUFFER_SIZE, "%s.%s", profileName, subUrl[index]); + snprintf(profileName, CHAR_BUFFER_SIZE, "%s.%s", profileName, subUrl[index]); index++; } return profileName; diff --git a/c/zss.c b/c/zss.c index acf599e29..f1af3bc0f 100644 --- a/c/zss.c +++ b/c/zss.c @@ -101,6 +101,7 @@ static JsonObject *MVD_SETTINGS = NULL; static int traceLevel = 0; #define JSON_ERROR_BUFFER_SIZE 1024 +#define CHAR_BUFFER_SIZE 1024 #define ZOWE_PROFILE_NAME_LEN 246 @@ -330,17 +331,17 @@ static void setPrivilegedServerName(HttpServer *server, JsonObject *mvdSettings, static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpRequest *request, HttpService *service, HttpResponse *response) { if (conversation->parser) { HttpRequestParser *parser = conversation->parser; - char *method = safeMalloc(JSON_ERROR_BUFFER_SIZE, "method"); - char *uri = safeMalloc(JSON_ERROR_BUFFER_SIZE, "uri"); - char *username = safeMalloc(JSON_ERROR_BUFFER_SIZE, "username"); - snprintf(uri, JSON_ERROR_BUFFER_SIZE, "%s", stringListPrint(request->parsedFile, 0, 1000, "/", 0)); - snprintf(method, JSON_ERROR_BUFFER_SIZE, "%s", request->method); + char *method = safeMalloc(CHAR_BUFFER_SIZE, "method"); + char *uri = safeMalloc(CHAR_BUFFER_SIZE, "uri"); + char *username = safeMalloc(CHAR_BUFFER_SIZE, "username"); + snprintf(uri, CHAR_BUFFER_SIZE, "%s", stringListPrint(request->parsedFile, 0, 1000, "/", 0)); + snprintf(method, CHAR_BUFFER_SIZE, "%s", request->method); destructivelyNativize(method); - char *profileName = safeMalloc(JSON_ERROR_BUFFER_SIZE, "profileName"); + char *profileName = safeMalloc(CHAR_BUFFER_SIZE, "profileName"); getProfileNameFromRequest(profileName, uri, method, -1, response); if (strlen(profileName) > ZOWE_PROFILE_NAME_LEN) { char *errMsg = safeMalloc(JSON_ERROR_BUFFER_SIZE, "errMsg"); - snprintf(errMsg, JSON_ERROR_BUFFER_SIZE, "Generated SAF query longer than %d", ZOWE_PROFILE_NAME_LEN); + snprintf(errMsg, CHAR_BUFFER_SIZE, "Generated SAF query longer than %d", ZOWE_PROFILE_NAME_LEN); respondWithError(response, HTTP_STATUS_BAD_REQUEST, errMsg); return -2; } From 357f0d0375eac6ff1cb1dc10c28235bcf3313978 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Fri, 11 Jun 2021 12:54:40 -0400 Subject: [PATCH 29/68] Rename Signed-off-by: Leanid Astrakou --- c/authService.c | 66 ++++++++++++++++++++++++------------------------- c/zss.c | 16 ++++++------ 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/c/authService.c b/c/authService.c index 3b496bffd..0eb047a9d 100644 --- a/c/authService.c +++ b/c/authService.c @@ -38,7 +38,7 @@ #define SAF_CLASS "ZOWE" #define JSON_ERROR_BUFFER_SIZE 1024 -#define CHAR_BUFFER_SIZE 1024 +#define STRING_BUFFER_SIZE 1024 #define SAF_SUB_URL_SIZE 16 #define SAF_PASSWORD_RESET_RC_OK 0 @@ -82,14 +82,14 @@ static const char* makeProfileName( const char *serviceName, const char *method, const char *scope, - char subUrl[SAF_SUB_URL_SIZE][CHAR_BUFFER_SIZE]); + char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]); static void setProfileNameAttribs( char *pluginID, char *serviceName, char *type, char *scope, - char subUrl[SAF_SUB_URL_SIZE][CHAR_BUFFER_SIZE]); + char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]); int installAuthCheckService(HttpServer *server) { // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "begin %s\n", @@ -225,12 +225,12 @@ int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, ch const char* getProfileNameFromRequest(char *profileName, char *url, char *method, int instanceID, HttpResponse *response) { char type[8]; // core || config || service - char productCode[CHAR_BUFFER_SIZE]; - char rootServiceName[CHAR_BUFFER_SIZE]; - char subUrl[SAF_SUB_URL_SIZE][CHAR_BUFFER_SIZE]; - char scope[CHAR_BUFFER_SIZE]; - char placeHolder1[CHAR_BUFFER_SIZE], pluginID[CHAR_BUFFER_SIZE], placeHolder2[CHAR_BUFFER_SIZE], - serviceName[CHAR_BUFFER_SIZE], placeHolder3[CHAR_BUFFER_SIZE]; + char productCode[STRING_BUFFER_SIZE]; + char rootServiceName[STRING_BUFFER_SIZE]; + char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]; + char scope[STRING_BUFFER_SIZE]; + char placeHolder1[STRING_BUFFER_SIZE], pluginID[STRING_BUFFER_SIZE], placeHolder2[STRING_BUFFER_SIZE], + serviceName[STRING_BUFFER_SIZE], placeHolder3[STRING_BUFFER_SIZE]; char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; regex_t regex; @@ -266,17 +266,17 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method while( token != NULL ) { if (rootServiceName == NULL) { - snprintf(rootServiceName, CHAR_BUFFER_SIZE, token); + snprintf(rootServiceName, STRING_BUFFER_SIZE, token); } else { if (subUrlIndex < SAF_SUB_URL_SIZE) { - snprintf(subUrl[subUrlIndex], CHAR_BUFFER_SIZE, token); + snprintf(subUrl[subUrlIndex], STRING_BUFFER_SIZE, token); } } subUrlIndex++; token = strtok_r(NULL, "/", &context); } - snprintf(productCode, CHAR_BUFFER_SIZE, "ZLUX"); - snprintf(type, CHAR_BUFFER_SIZE, "core"); + snprintf(productCode, STRING_BUFFER_SIZE, "ZLUX"); + snprintf(type, STRING_BUFFER_SIZE, "core"); } else if (!value) { char *context = NULL; @@ -286,25 +286,25 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method while( token != NULL ) { switch(subUrlIndex) { case 0: - snprintf(productCode, CHAR_BUFFER_SIZE, token); + snprintf(productCode, STRING_BUFFER_SIZE, token); break; case 1: - snprintf(placeHolder1, CHAR_BUFFER_SIZE, token); + snprintf(placeHolder1, STRING_BUFFER_SIZE, token); break; case 2: - snprintf(pluginID, CHAR_BUFFER_SIZE, token); + snprintf(pluginID, STRING_BUFFER_SIZE, token); break; case 3: - snprintf(placeHolder2, CHAR_BUFFER_SIZE, token); + snprintf(placeHolder2, STRING_BUFFER_SIZE, token); break; case 4: - snprintf(serviceName, CHAR_BUFFER_SIZE, token); + snprintf(serviceName, STRING_BUFFER_SIZE, token); break; case 5: - snprintf(placeHolder3, CHAR_BUFFER_SIZE, token); + snprintf(placeHolder3, STRING_BUFFER_SIZE, token); break; default: - snprintf(subUrl[subUrlIndex-6], CHAR_BUFFER_SIZE, token); // subtract 6 from maximum index to begin init subUrl array at 0 + snprintf(subUrl[subUrlIndex-6], STRING_BUFFER_SIZE, token); // subtract 6 from maximum index to begin init subUrl array at 0 } subUrlIndex++; @@ -330,7 +330,7 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "RegEx match failed."); } - snprintf(profileName, CHAR_BUFFER_SIZE, makeProfileName(type, + snprintf(profileName, STRING_BUFFER_SIZE, makeProfileName(type, productCode, instanceID, pluginID, @@ -351,15 +351,15 @@ static void setProfileNameAttribs( char *serviceName, char *type, char *scope, - char subUrl[SAF_SUB_URL_SIZE][CHAR_BUFFER_SIZE]) { + char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) { - snprintf(type, CHAR_BUFFER_SIZE, "config"); - snprintf(pluginID, CHAR_BUFFER_SIZE, subUrl[0]); - snprintf(scope, CHAR_BUFFER_SIZE, subUrl[1]); + snprintf(type, STRING_BUFFER_SIZE, "config"); + snprintf(pluginID, STRING_BUFFER_SIZE, subUrl[0]); + snprintf(scope, STRING_BUFFER_SIZE, subUrl[1]); } else { - snprintf(type, CHAR_BUFFER_SIZE, "service"); + snprintf(type, STRING_BUFFER_SIZE, "service"); } } @@ -372,8 +372,8 @@ static const char* makeProfileName( const char *serviceName, const char *method, const char *scope, - char subUrl[SAF_SUB_URL_SIZE][CHAR_BUFFER_SIZE]) { - char *profileName = safeMalloc(CHAR_BUFFER_SIZE, "profileNameInner"); + char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { + char *profileName = safeMalloc(STRING_BUFFER_SIZE, "profileNameInner"); if (profileName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_SEVERE, "safeMalloc failed. Not enough memory"); @@ -394,7 +394,7 @@ static const char* makeProfileName( "Broken SAF query. Missing method."); return NULL; } - // char someString[CHAR_BUFFER_SIZE] = { snprintf(*someString, CHAR_BUFFER_SIZE, type) }; + // char someString[STRING_BUFFER_SIZE] = { snprintf(*someString, STRING_BUFFER_SIZE, type) }; if (strcmp(type, "service") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, @@ -406,7 +406,7 @@ static const char* makeProfileName( "Broken SAF query. Missing service name."); return NULL; } - snprintf(profileName, CHAR_BUFFER_SIZE, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); + snprintf(profileName, STRING_BUFFER_SIZE, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); } else if (strcmp(type, "config") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, @@ -418,19 +418,19 @@ static const char* makeProfileName( "Broken SAF query. Missing scope."); return NULL; } - snprintf(profileName, CHAR_BUFFER_SIZE, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); + snprintf(profileName, STRING_BUFFER_SIZE, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); } else if (strcmp(type, "core") == 0) { if (rootServiceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing root service name."); return NULL; } - snprintf(profileName, CHAR_BUFFER_SIZE, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + snprintf(profileName, STRING_BUFFER_SIZE, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); } // Child endpoints housed via subUrl int index = 0; while (index < SAF_SUB_URL_SIZE && strcmp(subUrl[index], "") != 0) { - snprintf(profileName, CHAR_BUFFER_SIZE, "%s.%s", profileName, subUrl[index]); + snprintf(profileName, STRING_BUFFER_SIZE, "%s.%s", profileName, subUrl[index]); index++; } return profileName; diff --git a/c/zss.c b/c/zss.c index f1af3bc0f..fb8020494 100644 --- a/c/zss.c +++ b/c/zss.c @@ -101,7 +101,7 @@ static JsonObject *MVD_SETTINGS = NULL; static int traceLevel = 0; #define JSON_ERROR_BUFFER_SIZE 1024 -#define CHAR_BUFFER_SIZE 1024 +#define STRING_BUFFER_SIZE 1024 #define ZOWE_PROFILE_NAME_LEN 246 @@ -331,17 +331,17 @@ static void setPrivilegedServerName(HttpServer *server, JsonObject *mvdSettings, static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpRequest *request, HttpService *service, HttpResponse *response) { if (conversation->parser) { HttpRequestParser *parser = conversation->parser; - char *method = safeMalloc(CHAR_BUFFER_SIZE, "method"); - char *uri = safeMalloc(CHAR_BUFFER_SIZE, "uri"); - char *username = safeMalloc(CHAR_BUFFER_SIZE, "username"); - snprintf(uri, CHAR_BUFFER_SIZE, "%s", stringListPrint(request->parsedFile, 0, 1000, "/", 0)); - snprintf(method, CHAR_BUFFER_SIZE, "%s", request->method); + char *method = safeMalloc(STRING_BUFFER_SIZE, "method"); + char *uri = safeMalloc(STRING_BUFFER_SIZE, "uri"); + char *username = safeMalloc(STRING_BUFFER_SIZE, "username"); + snprintf(uri, STRING_BUFFER_SIZE, "%s", stringListPrint(request->parsedFile, 0, 1000, "/", 0)); + snprintf(method, STRING_BUFFER_SIZE, "%s", request->method); destructivelyNativize(method); - char *profileName = safeMalloc(CHAR_BUFFER_SIZE, "profileName"); + char *profileName = safeMalloc(STRING_BUFFER_SIZE, "profileName"); getProfileNameFromRequest(profileName, uri, method, -1, response); if (strlen(profileName) > ZOWE_PROFILE_NAME_LEN) { char *errMsg = safeMalloc(JSON_ERROR_BUFFER_SIZE, "errMsg"); - snprintf(errMsg, CHAR_BUFFER_SIZE, "Generated SAF query longer than %d", ZOWE_PROFILE_NAME_LEN); + snprintf(errMsg, STRING_BUFFER_SIZE, "Generated SAF query longer than %d", ZOWE_PROFILE_NAME_LEN); respondWithError(response, HTTP_STATUS_BAD_REQUEST, errMsg); return -2; } From 06a16ef5075274e017c05ae8c23b778471ecb1d5 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Tue, 15 Jun 2021 23:52:50 -0400 Subject: [PATCH 30/68] Removed regEx to use parsedFile instead Signed-off-by: Leanid Astrakou --- c/authService.c | 40 +++++++++++----------------------------- c/zss.c | 4 +--- h/authService.h | 4 ++-- 3 files changed, 14 insertions(+), 34 deletions(-) diff --git a/c/authService.c b/c/authService.c index 0eb047a9d..67b7e057e 100644 --- a/c/authService.c +++ b/c/authService.c @@ -71,7 +71,7 @@ static int serveAuthCheck(HttpService *service, HttpResponse *response); int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char* entity, int access); -const char* getProfileNameFromRequest(char *profileName, char *url, const char *method, int instanceID, HttpResponse *response); +const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response); static const char* makeProfileName( const char *type, @@ -223,7 +223,7 @@ int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, ch return rc; } -const char* getProfileNameFromRequest(char *profileName, char *url, char *method, int instanceID, HttpResponse *response) { +const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response) { char type[8]; // core || config || service char productCode[STRING_BUFFER_SIZE]; char rootServiceName[STRING_BUFFER_SIZE]; @@ -231,35 +231,25 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method char scope[STRING_BUFFER_SIZE]; char placeHolder1[STRING_BUFFER_SIZE], pluginID[STRING_BUFFER_SIZE], placeHolder2[STRING_BUFFER_SIZE], serviceName[STRING_BUFFER_SIZE], placeHolder3[STRING_BUFFER_SIZE]; - char regexStr[] = "^/[A-Za-z0-9]*/plugins/"; - - regex_t regex; - int value; - value = regcomp(®ex, regexStr, REG_EXTENDED); + char url[STRING_BUFFER_SIZE]; + char urlSegment[STRING_BUFFER_SIZE]; + snprintf(url, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, 0, 1000, "/", 0)); + snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, 1, 1, "/", 0)); if (profileName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_SEVERE, "safeMalloc failed. Not enough memory"); respondWithError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Not enough memory"); return NULL; } - if (value == 0) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "RegEx compiled successfully."); - } else { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "RegEx compilation error %s.", regexStr); - respondWithError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "RegEx compilation error"); - return NULL; - } - value = regexec(®ex, url, 0, NULL, 0); strupcase(url); + strupcase(urlSegment); if (instanceID < 0) { // Set instanceID instanceID = 0; } - if (value == REG_NOMATCH) { + if (strcmp(urlSegment, "PLUGINS") != 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "RegEx didn't match."); + "parsedFile urlSegment check didn't match."); char *context = NULL; char *token = strtok_r(url, "/", &context); int subUrlIndex = -1; @@ -277,8 +267,7 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method } snprintf(productCode, STRING_BUFFER_SIZE, "ZLUX"); snprintf(type, STRING_BUFFER_SIZE, "core"); - } - else if (!value) { + } else { char *context = NULL; char *token = strtok_r(url, "/", &context); int subUrlIndex; @@ -324,11 +313,7 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method } } zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "RegEx match OK."); - } - else { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "RegEx match failed."); + "parsedFile urlSegment check OK."); } snprintf(profileName, STRING_BUFFER_SIZE, makeProfileName(type, productCode, @@ -340,9 +325,6 @@ const char* getProfileNameFromRequest(char *profileName, char *url, char *method scope, subUrl)); - /* Free memory allocated to the pattern buffer by regcomp() */ - regfree(®ex); - return profileName; } diff --git a/c/zss.c b/c/zss.c index fb8020494..5cd10adfd 100644 --- a/c/zss.c +++ b/c/zss.c @@ -332,13 +332,11 @@ static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpReques if (conversation->parser) { HttpRequestParser *parser = conversation->parser; char *method = safeMalloc(STRING_BUFFER_SIZE, "method"); - char *uri = safeMalloc(STRING_BUFFER_SIZE, "uri"); char *username = safeMalloc(STRING_BUFFER_SIZE, "username"); - snprintf(uri, STRING_BUFFER_SIZE, "%s", stringListPrint(request->parsedFile, 0, 1000, "/", 0)); snprintf(method, STRING_BUFFER_SIZE, "%s", request->method); destructivelyNativize(method); char *profileName = safeMalloc(STRING_BUFFER_SIZE, "profileName"); - getProfileNameFromRequest(profileName, uri, method, -1, response); + getProfileNameFromRequest(profileName, request->parsedFile, method, -1, response); if (strlen(profileName) > ZOWE_PROFILE_NAME_LEN) { char *errMsg = safeMalloc(JSON_ERROR_BUFFER_SIZE, "errMsg"); snprintf(errMsg, STRING_BUFFER_SIZE, "Generated SAF query longer than %d", ZOWE_PROFILE_NAME_LEN); diff --git a/h/authService.h b/h/authService.h index 03efbf7b9..d4cdb05d3 100644 --- a/h/authService.h +++ b/h/authService.h @@ -32,13 +32,13 @@ void installZosPasswordService(HttpServer *server); /** * @brief The function uses makeProfileName function to generate profile name for SAF query * @param profileName Generated profile name goes here - * @param url Refers to the URL used to generate query + * @param parsedFile Refers to the StringList object which contains URL stripped of args * @param instanceID Refers to instanceID for query. If none specified, or negative, then 0 * @param HttpResponse Describes the HttpResponse object to return if error encountered * * @return Return generated profile name or NULL if error */ -const char* getProfileNameFromRequest(char *profileName, char *url, char *method, int instanceID, HttpResponse *response); +const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response); /** * @brief The function satisfies RBAC, by first checking if RBAC is enabled, then executing From 86ee872cc1b0ea12dd8415449f393b2a1d5f9e1c Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Fri, 18 Jun 2021 00:08:58 -0400 Subject: [PATCH 31/68] Re-added bypass services for NO RBAC Signed-off-by: Leanid Astrakou --- c/authService.c | 79 ++++++++++++++++++++++++++++++++------------- c/datasetService.c | 6 ++-- c/omvsService.c | 2 +- c/securityService.c | 8 ++--- c/unixFileService.c | 20 ++++++------ 5 files changed, 75 insertions(+), 40 deletions(-) diff --git a/c/authService.c b/c/authService.c index 67b7e057e..e0f24fa25 100644 --- a/c/authService.c +++ b/c/authService.c @@ -232,10 +232,16 @@ const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, char placeHolder1[STRING_BUFFER_SIZE], pluginID[STRING_BUFFER_SIZE], placeHolder2[STRING_BUFFER_SIZE], serviceName[STRING_BUFFER_SIZE], placeHolder3[STRING_BUFFER_SIZE]; char url[STRING_BUFFER_SIZE]; - char urlSegment[STRING_BUFFER_SIZE]; + char urlSegment[STRING_BUFFER_SIZE]; + char upperSegment[STRING_BUFFER_SIZE]; + int subUrlIndex = 0; - snprintf(url, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, 0, 1000, "/", 0)); + snprintf(url, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, subUrlIndex, 1000, "/", 0)); snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, 1, 1, "/", 0)); + StringListElt *pathSegment = firstStringListElt(parsedFile); + // TODO: Remove printf's (not ready for merge) + printf("\n\n\nURI, METHOD, PROFILENAME PRE CONVERSION: %s - %s - %s -%s\n\n", url, method, profileName, pathSegment->string); + if (profileName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_SEVERE, "safeMalloc failed. Not enough memory"); @@ -250,55 +256,82 @@ const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, if (strcmp(urlSegment, "PLUGINS") != 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, "parsedFile urlSegment check didn't match."); - char *context = NULL; - char *token = strtok_r(url, "/", &context); - int subUrlIndex = -1; - while( token != NULL ) { + subUrlIndex = -1; + while (pathSegment != NULL) { + snprintf(upperSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); + strupcase(upperSegment); if (rootServiceName == NULL) { - snprintf(rootServiceName, STRING_BUFFER_SIZE, token); + snprintf(rootServiceName, STRING_BUFFER_SIZE, upperSegment); } else { if (subUrlIndex < SAF_SUB_URL_SIZE) { - snprintf(subUrl[subUrlIndex], STRING_BUFFER_SIZE, token); + snprintf(subUrl[subUrlIndex], STRING_BUFFER_SIZE, upperSegment); } } subUrlIndex++; - token = strtok_r(NULL, "/", &context); + pathSegment = pathSegment->next; } snprintf(productCode, STRING_BUFFER_SIZE, "ZLUX"); snprintf(type, STRING_BUFFER_SIZE, "core"); } else { - char *context = NULL; - char *token = strtok_r(url, "/", &context); - int subUrlIndex; subUrlIndex = 0; - while( token != NULL ) { + + while (pathSegment != NULL) { + snprintf(upperSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); + strupcase(upperSegment); switch(subUrlIndex) { case 0: - snprintf(productCode, STRING_BUFFER_SIZE, token); + snprintf(productCode, STRING_BUFFER_SIZE, upperSegment); break; case 1: - snprintf(placeHolder1, STRING_BUFFER_SIZE, token); + snprintf(placeHolder1, STRING_BUFFER_SIZE, upperSegment); break; case 2: - snprintf(pluginID, STRING_BUFFER_SIZE, token); + snprintf(pluginID, STRING_BUFFER_SIZE, upperSegment); break; case 3: - snprintf(placeHolder2, STRING_BUFFER_SIZE, token); + snprintf(placeHolder2, STRING_BUFFER_SIZE, upperSegment); break; case 4: - snprintf(serviceName, STRING_BUFFER_SIZE, token); + snprintf(serviceName, STRING_BUFFER_SIZE, upperSegment); break; case 5: - snprintf(placeHolder3, STRING_BUFFER_SIZE, token); + snprintf(placeHolder3, STRING_BUFFER_SIZE, upperSegment); break; default: - snprintf(subUrl[subUrlIndex-6], STRING_BUFFER_SIZE, token); // subtract 6 from maximum index to begin init subUrl array at 0 + snprintf(subUrl[subUrlIndex-6], STRING_BUFFER_SIZE, upperSegment); // subtract 6 from maximum index to begin init subUrl array at 0 } - subUrlIndex++; - token = strtok_r(NULL, "/", &context); + pathSegment = pathSegment->next; } + + // while( token != NULL ) { + // switch(subUrlIndex) { + // case 0: + // snprintf(productCode, STRING_BUFFER_SIZE, token); + // break; + // case 1: + // snprintf(placeHolder1, STRING_BUFFER_SIZE, token); + // break; + // case 2: + // snprintf(pluginID, STRING_BUFFER_SIZE, token); + // break; + // case 3: + // snprintf(placeHolder2, STRING_BUFFER_SIZE, token); + // break; + // case 4: + // snprintf(serviceName, STRING_BUFFER_SIZE, token); + // break; + // case 5: + // snprintf(placeHolder3, STRING_BUFFER_SIZE, token); + // break; + // default: + // snprintf(subUrl[subUrlIndex-6], STRING_BUFFER_SIZE, token); // subtract 6 from maximum index to begin init subUrl array at 0 + // } + + // subUrlIndex++; + // token = strtok_r(NULL, "/", &context); + // } setProfileNameAttribs(pluginID, serviceName, type, scope, subUrl); char* ch; char* chReplace; @@ -324,6 +357,8 @@ const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, method, scope, subUrl)); + + printf("\n\n\nURI, METHOD, PROFILENAME POST CONVERSION %s - %s - %s\n\n", url, method, profileName); return profileName; } diff --git a/c/datasetService.c b/c/datasetService.c index 9a82ad5a9..e99c65d6d 100644 --- a/c/datasetService.c +++ b/c/datasetService.c @@ -187,7 +187,7 @@ void installDatasetContentsService(HttpServer *server) { zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); HttpService *httpService = makeGeneratedService("datasetContents", "/datasetContents/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveDatasetContents; @@ -199,7 +199,7 @@ void installVSAMDatasetContentsService(HttpServer *server) { zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); HttpService *httpService = makeGeneratedService("VSAMdatasetContents", "/VSAMdatasetContents/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveVSAMDatasetContents; @@ -217,7 +217,7 @@ void installDatasetMetadataService(HttpServer *server) { HttpService *httpService = makeGeneratedService("datasetMetadata", "/datasetMetadata/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveDatasetMetadata; diff --git a/c/omvsService.c b/c/omvsService.c index 1ef60832b..dff82dd29 100644 --- a/c/omvsService.c +++ b/c/omvsService.c @@ -53,7 +53,7 @@ static int issueRACFCommand(char *command, OMVSSegment *omvs); int installOMVSService(HttpServer *server) { HttpService *httpService = makeGeneratedService("OMVS_Service", "/omvs/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->serviceFunction = &serveOMVSSegment; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; diff --git a/c/securityService.c b/c/securityService.c index 8e7bb287e..fa9cea571 100644 --- a/c/securityService.c +++ b/c/securityService.c @@ -3355,7 +3355,7 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); - classMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + classMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; classMgmtService->serviceFunction = &serveClassManagement; classMgmtService->runInSubtask = TRUE; classMgmtService->doImpersonation = TRUE; @@ -3369,7 +3369,7 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); - userProfileService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + userProfileService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; userProfileService->serviceFunction = &serveUserProfile; userProfileService->runInSubtask = TRUE; userProfileService->doImpersonation = TRUE; @@ -3383,7 +3383,7 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); - groupMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + groupMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; groupMgmtService->serviceFunction = &serveGroupManagement; groupMgmtService->runInSubtask = TRUE; groupMgmtService->doImpersonation = TRUE; @@ -3396,7 +3396,7 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("count", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, NULL )); - accessService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + accessService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; accessService->serviceFunction = &serveAccessInfo; accessService->runInSubtask = TRUE; accessService->doImpersonation = TRUE; diff --git a/c/unixFileService.c b/c/unixFileService.c index e06e777c5..cd4ae6248 100644 --- a/c/unixFileService.c +++ b/c/unixFileService.c @@ -1099,7 +1099,7 @@ static int serveTableOfContents(HttpService *service, HttpResponse *response) { void installUnixFileContentsService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileContents", "/unixfile/contents/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->serviceFunction = serveUnixFileContents; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1118,7 +1118,7 @@ void installUnixFileContentsService(HttpServer *server) { void installUnixFileRenameService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileRename", "/unixfile/rename/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->serviceFunction = serveUnixFileRename; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1128,7 +1128,7 @@ void installUnixFileRenameService(HttpServer *server) { void installUnixFileCopyService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileCopy", "/unixfile/copy/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->serviceFunction = serveUnixFileCopy; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1138,7 +1138,7 @@ void installUnixFileCopyService(HttpServer *server) { void installUnixFileMakeDirectoryService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileMkdir", "/unixfile/mkdir/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->serviceFunction = serveUnixFileMakeDirectory; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1148,7 +1148,7 @@ void installUnixFileMakeDirectoryService(HttpServer *server) { void installUnixFileTouchService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileTouch", "/unixfile/touch/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->serviceFunction = serveUnixFileTouch; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1158,7 +1158,7 @@ void installUnixFileTouchService(HttpServer *server) { void installUnixFileMetadataService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/metadata/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveUnixFileMetadata; @@ -1168,7 +1168,7 @@ void installUnixFileMetadataService(HttpServer *server) { void installUnixFileChangeOwnerService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/chown/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveUnixFileChangeOwner; @@ -1178,7 +1178,7 @@ void installUnixFileChangeOwnerService(HttpServer *server) { void installUnixFileChangeTagService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileChtag", "/unixfile/chtag/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->serviceFunction = serveUnixFileChangeTag; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1188,7 +1188,7 @@ void installUnixFileChangeTagService(HttpServer *server) { void installUnixFileChangeModeService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileChmod", "/unixfile/chmod/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->serviceFunction = serveUnixFileChangeMode; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1198,7 +1198,7 @@ void installUnixFileChangeModeService(HttpServer *server) { void installUnixFileTableOfContentsService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveTableOfContents; From 21b1496c7137f499edc18fab34d98cf36e1e0f38 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Fri, 18 Jun 2021 00:33:01 -0400 Subject: [PATCH 32/68] Removed comments + clean up unused variables Signed-off-by: Leanid Astrakou --- c/authService.c | 63 +++++++++++-------------------------------------- 1 file changed, 14 insertions(+), 49 deletions(-) diff --git a/c/authService.c b/c/authService.c index e0f24fa25..171e6bc66 100644 --- a/c/authService.c +++ b/c/authService.c @@ -231,24 +231,18 @@ const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, char scope[STRING_BUFFER_SIZE]; char placeHolder1[STRING_BUFFER_SIZE], pluginID[STRING_BUFFER_SIZE], placeHolder2[STRING_BUFFER_SIZE], serviceName[STRING_BUFFER_SIZE], placeHolder3[STRING_BUFFER_SIZE]; - char url[STRING_BUFFER_SIZE]; char urlSegment[STRING_BUFFER_SIZE]; - char upperSegment[STRING_BUFFER_SIZE]; int subUrlIndex = 0; - snprintf(url, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, subUrlIndex, 1000, "/", 0)); snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, 1, 1, "/", 0)); StringListElt *pathSegment = firstStringListElt(parsedFile); - // TODO: Remove printf's (not ready for merge) - printf("\n\n\nURI, METHOD, PROFILENAME PRE CONVERSION: %s - %s - %s -%s\n\n", url, method, profileName, pathSegment->string); - + if (profileName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_SEVERE, "safeMalloc failed. Not enough memory"); respondWithError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Not enough memory"); return NULL; } - strupcase(url); strupcase(urlSegment); if (instanceID < 0) { // Set instanceID instanceID = 0; @@ -258,14 +252,14 @@ const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, "parsedFile urlSegment check didn't match."); subUrlIndex = -1; while (pathSegment != NULL) { - snprintf(upperSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); - strupcase(upperSegment); + snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); + strupcase(urlSegment); if (rootServiceName == NULL) { - snprintf(rootServiceName, STRING_BUFFER_SIZE, upperSegment); + snprintf(rootServiceName, STRING_BUFFER_SIZE, urlSegment); } else { if (subUrlIndex < SAF_SUB_URL_SIZE) { - snprintf(subUrl[subUrlIndex], STRING_BUFFER_SIZE, upperSegment); + snprintf(subUrl[subUrlIndex], STRING_BUFFER_SIZE, urlSegment); } } subUrlIndex++; @@ -277,61 +271,34 @@ const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, subUrlIndex = 0; while (pathSegment != NULL) { - snprintf(upperSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); - strupcase(upperSegment); + snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); + strupcase(urlSegment); switch(subUrlIndex) { case 0: - snprintf(productCode, STRING_BUFFER_SIZE, upperSegment); + snprintf(productCode, STRING_BUFFER_SIZE, urlSegment); break; case 1: - snprintf(placeHolder1, STRING_BUFFER_SIZE, upperSegment); + snprintf(placeHolder1, STRING_BUFFER_SIZE, urlSegment); break; case 2: - snprintf(pluginID, STRING_BUFFER_SIZE, upperSegment); + snprintf(pluginID, STRING_BUFFER_SIZE, urlSegment); break; case 3: - snprintf(placeHolder2, STRING_BUFFER_SIZE, upperSegment); + snprintf(placeHolder2, STRING_BUFFER_SIZE, urlSegment); break; case 4: - snprintf(serviceName, STRING_BUFFER_SIZE, upperSegment); + snprintf(serviceName, STRING_BUFFER_SIZE, urlSegment); break; case 5: - snprintf(placeHolder3, STRING_BUFFER_SIZE, upperSegment); + snprintf(placeHolder3, STRING_BUFFER_SIZE, urlSegment); break; default: - snprintf(subUrl[subUrlIndex-6], STRING_BUFFER_SIZE, upperSegment); // subtract 6 from maximum index to begin init subUrl array at 0 + snprintf(subUrl[subUrlIndex-6], STRING_BUFFER_SIZE, urlSegment); // subtract 6 from maximum index to begin init subUrl array at 0 } subUrlIndex++; pathSegment = pathSegment->next; } - // while( token != NULL ) { - // switch(subUrlIndex) { - // case 0: - // snprintf(productCode, STRING_BUFFER_SIZE, token); - // break; - // case 1: - // snprintf(placeHolder1, STRING_BUFFER_SIZE, token); - // break; - // case 2: - // snprintf(pluginID, STRING_BUFFER_SIZE, token); - // break; - // case 3: - // snprintf(placeHolder2, STRING_BUFFER_SIZE, token); - // break; - // case 4: - // snprintf(serviceName, STRING_BUFFER_SIZE, token); - // break; - // case 5: - // snprintf(placeHolder3, STRING_BUFFER_SIZE, token); - // break; - // default: - // snprintf(subUrl[subUrlIndex-6], STRING_BUFFER_SIZE, token); // subtract 6 from maximum index to begin init subUrl array at 0 - // } - - // subUrlIndex++; - // token = strtok_r(NULL, "/", &context); - // } setProfileNameAttribs(pluginID, serviceName, type, scope, subUrl); char* ch; char* chReplace; @@ -358,8 +325,6 @@ const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, scope, subUrl)); - printf("\n\n\nURI, METHOD, PROFILENAME POST CONVERSION %s - %s - %s\n\n", url, method, profileName); - return profileName; } From 970cd237ab10adf44893bf7a2798b3e39bbb8240 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Sun, 20 Jun 2021 20:04:48 +0500 Subject: [PATCH 33/68] Some code cleanup Signed-off-by: Leonty Chudinov --- c/authService.c | 104 ++++++++++++++++++++---------------------------- c/zss.c | 21 +++------- h/authService.h | 6 ++- 3 files changed, 53 insertions(+), 78 deletions(-) diff --git a/c/authService.c b/c/authService.c index 171e6bc66..3f8b18af0 100644 --- a/c/authService.c +++ b/c/authService.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "authService.h" #include "zowetypes.h" @@ -69,11 +68,10 @@ static int serveAuthCheck(HttpService *service, HttpResponse *response); -int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char* entity, int access); +int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char* entity, int access); -const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response); - -static const char* makeProfileName( +static int makeProfileName( + char *profileName, const char *type, const char *productCode, int instanceID, @@ -208,7 +206,7 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { return 0; } -int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access) { +int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char *entity, int access) { int rc = 0; JsonObject *dataserviceAuth = jsonObjectGetObject(service->server->sharedServiceMem, "dataserviceAuthentication"); int rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); @@ -218,31 +216,25 @@ int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, ch if (!rbacParm) { return rc; // When rbac isn't enabled, we don't try to check the auth query } - rc = zisCheckEntity(privilegedServerName, userName, Class, entity, access, + rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); return rc; } -const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response) { - char type[8]; // core || config || service +int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response) { + char type[STRING_BUFFER_SIZE]; // core || config || service char productCode[STRING_BUFFER_SIZE]; char rootServiceName[STRING_BUFFER_SIZE]; - char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]; + char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE] = {0}; char scope[STRING_BUFFER_SIZE]; - char placeHolder1[STRING_BUFFER_SIZE], pluginID[STRING_BUFFER_SIZE], placeHolder2[STRING_BUFFER_SIZE], - serviceName[STRING_BUFFER_SIZE], placeHolder3[STRING_BUFFER_SIZE]; + char pluginID[STRING_BUFFER_SIZE]; + char serviceName[STRING_BUFFER_SIZE]; char urlSegment[STRING_BUFFER_SIZE]; int subUrlIndex = 0; snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, 1, 1, "/", 0)); StringListElt *pathSegment = firstStringListElt(parsedFile); - if (profileName == NULL) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_SEVERE, - "safeMalloc failed. Not enough memory"); - respondWithError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Not enough memory"); - return NULL; - } strupcase(urlSegment); if (instanceID < 0) { // Set instanceID instanceID = 0; @@ -278,44 +270,39 @@ const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, snprintf(productCode, STRING_BUFFER_SIZE, urlSegment); break; case 1: - snprintf(placeHolder1, STRING_BUFFER_SIZE, urlSegment); break; case 2: snprintf(pluginID, STRING_BUFFER_SIZE, urlSegment); break; case 3: - snprintf(placeHolder2, STRING_BUFFER_SIZE, urlSegment); break; case 4: snprintf(serviceName, STRING_BUFFER_SIZE, urlSegment); break; case 5: - snprintf(placeHolder3, STRING_BUFFER_SIZE, urlSegment); break; - default: - snprintf(subUrl[subUrlIndex-6], STRING_BUFFER_SIZE, urlSegment); // subtract 6 from maximum index to begin init subUrl array at 0 + default: { + int adjustedSubUrlIndex = subUrlIndex - 6; // subtract 6 from maximum index to begin init subUrl array at 0 + if (adjustedSubUrlIndex < SAF_SUB_URL_SIZE) { + snprintf(subUrl[adjustedSubUrlIndex], STRING_BUFFER_SIZE, urlSegment); + } + } } subUrlIndex++; pathSegment = pathSegment->next; } setProfileNameAttribs(pluginID, serviceName, type, scope, subUrl); - char* ch; - char* chReplace; - ch = "."; - chReplace = "_"; - int index = 0; - for (index = 0; index <= strlen(pluginID); index++) - { - if (pluginID[index] == *ch) - { - pluginID[index] = *chReplace; + int pluginIDLen = strlen(pluginID); + for (int index = 0; index < pluginIDLen; index++) { + if (pluginID[index] == '.') { + pluginID[index] = '_'; } } zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, "parsedFile urlSegment check OK."); } - snprintf(profileName, STRING_BUFFER_SIZE, makeProfileName(type, + return makeProfileName(profileName, type, productCode, instanceID, pluginID, @@ -323,9 +310,7 @@ const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, serviceName, method, scope, - subUrl)); - - return profileName; + subUrl); } static void setProfileNameAttribs( @@ -345,7 +330,8 @@ static void setProfileNameAttribs( } } -static const char* makeProfileName( +static int makeProfileName( + char *profileName, const char *type, const char *productCode, int instanceID, @@ -355,67 +341,63 @@ static const char* makeProfileName( const char *method, const char *scope, char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { - char *profileName = safeMalloc(STRING_BUFFER_SIZE, "profileNameInner"); - if (profileName == NULL) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_SEVERE, - "safeMalloc failed. Not enough memory"); - return NULL; - } - if (productCode == NULL) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing product code."); - return NULL; - } if (instanceID == -1) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing instance ID."); - return NULL; + return -1; } if (method == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing method."); - return NULL; + return -1; } // char someString[STRING_BUFFER_SIZE] = { snprintf(*someString, STRING_BUFFER_SIZE, type) }; if (strcmp(type, "service") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing plugin ID."); - return NULL; + return -1; } if (serviceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing service name."); - return NULL; + return -1; } - snprintf(profileName, STRING_BUFFER_SIZE, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); + snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); } else if (strcmp(type, "config") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing plugin ID."); - return NULL; + return -1; } if (scope == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing scope."); - return NULL; + return -1; } - snprintf(profileName, STRING_BUFFER_SIZE, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); + snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); } else if (strcmp(type, "core") == 0) { if (rootServiceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing root service name."); - return NULL; + return -1; } - snprintf(profileName, STRING_BUFFER_SIZE, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); } // Child endpoints housed via subUrl int index = 0; + int pos = strlen(profileName); while (index < SAF_SUB_URL_SIZE && strcmp(subUrl[index], "") != 0) { - snprintf(profileName, STRING_BUFFER_SIZE, "%s.%s", profileName, subUrl[index]); + if (pos > ZOWE_PROFILE_NAME_LEN) { + char errMsg[256]; + snprintf(errMsg, sizeof(errMsg), "Generated SAF query longer than %d", ZOWE_PROFILE_NAME_LEN); + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, errMsg); + return -1; + } + pos += snprintf(profileName + pos, ZOWE_PROFILE_NAME_LEN + 1 - pos, ".%s", subUrl[index]); index++; } - return profileName; + return 0; } void respondWithJsonStatus(HttpResponse *response, const char *status, int statusCode, const char *statusMessage) { diff --git a/c/zss.c b/c/zss.c index 5cd10adfd..4737741eb 100644 --- a/c/zss.c +++ b/c/zss.c @@ -102,8 +102,6 @@ static int traceLevel = 0; #define JSON_ERROR_BUFFER_SIZE 1024 #define STRING_BUFFER_SIZE 1024 -#define ZOWE_PROFILE_NAME_LEN 246 - #define DEFAULT_TLS_CIPHERS \ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 \ @@ -330,23 +328,16 @@ static void setPrivilegedServerName(HttpServer *server, JsonObject *mvdSettings, static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpRequest *request, HttpService *service, HttpResponse *response) { if (conversation->parser) { + int rc = 0; HttpRequestParser *parser = conversation->parser; - char *method = safeMalloc(STRING_BUFFER_SIZE, "method"); - char *username = safeMalloc(STRING_BUFFER_SIZE, "username"); - snprintf(method, STRING_BUFFER_SIZE, "%s", request->method); - destructivelyNativize(method); - char *profileName = safeMalloc(STRING_BUFFER_SIZE, "profileName"); - getProfileNameFromRequest(profileName, request->parsedFile, method, -1, response); - if (strlen(profileName) > ZOWE_PROFILE_NAME_LEN) { - char *errMsg = safeMalloc(JSON_ERROR_BUFFER_SIZE, "errMsg"); - snprintf(errMsg, STRING_BUFFER_SIZE, "Generated SAF query longer than %d", ZOWE_PROFILE_NAME_LEN); - respondWithError(response, HTTP_STATUS_BAD_REQUEST, errMsg); - return -2; + char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; + rc = getProfileNameFromRequest(profileName, request->parsedFile, request->method, -1, response); + if (rc != 0) { + return -1; } - int rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2); + rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2); return rc; } - respondWithError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Conversation object corrupt"); return -1; } diff --git a/h/authService.h b/h/authService.h index d4cdb05d3..90c4f5636 100644 --- a/h/authService.h +++ b/h/authService.h @@ -26,6 +26,8 @@ #include "httpserver.h" #include "dataservice.h" +#define ZOWE_PROFILE_NAME_LEN 246 + int installAuthCheckService(HttpServer *server); void installZosPasswordService(HttpServer *server); @@ -36,9 +38,9 @@ void installZosPasswordService(HttpServer *server); * @param instanceID Refers to instanceID for query. If none specified, or negative, then 0 * @param HttpResponse Describes the HttpResponse object to return if error encountered * - * @return Return generated profile name or NULL if error + * @return Return non-zero if error */ -const char* getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response); +int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response); /** * @brief The function satisfies RBAC, by first checking if RBAC is enabled, then executing From 8a7ad43e6663f4a72ac448ab7d56068261eb5ee4 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Tue, 22 Jun 2021 07:34:22 +0500 Subject: [PATCH 34/68] Address code review Signed-off-by: Leonty Chudinov --- c/authService.c | 20 +++++++++++--------- c/zss.c | 5 ++++- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/c/authService.c b/c/authService.c index 3f8b18af0..1afc9525f 100644 --- a/c/authService.c +++ b/c/authService.c @@ -351,7 +351,7 @@ static int makeProfileName( "Broken SAF query. Missing method."); return -1; } - // char someString[STRING_BUFFER_SIZE] = { snprintf(*someString, STRING_BUFFER_SIZE, type) }; + int pos = 0; if (strcmp(type, "service") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, @@ -363,7 +363,7 @@ static int makeProfileName( "Broken SAF query. Missing service name."); return -1; } - snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); + pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); } else if (strcmp(type, "config") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, @@ -375,28 +375,30 @@ static int makeProfileName( "Broken SAF query. Missing scope."); return -1; } - snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); + pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); } else if (strcmp(type, "core") == 0) { if (rootServiceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing root service name."); return -1; } - snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); } // Child endpoints housed via subUrl int index = 0; - int pos = strlen(profileName); while (index < SAF_SUB_URL_SIZE && strcmp(subUrl[index], "") != 0) { if (pos > ZOWE_PROFILE_NAME_LEN) { - char errMsg[256]; - snprintf(errMsg, sizeof(errMsg), "Generated SAF query longer than %d", ZOWE_PROFILE_NAME_LEN); - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, errMsg); - return -1; + break; } pos += snprintf(profileName + pos, ZOWE_PROFILE_NAME_LEN + 1 - pos, ".%s", subUrl[index]); index++; } + if (pos > ZOWE_PROFILE_NAME_LEN) { + char errMsg[256]; + snprintf(errMsg, sizeof(errMsg), "Generated SAF query longer than %d\n", ZOWE_PROFILE_NAME_LEN); + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, errMsg); + return -1; + } return 0; } diff --git a/c/zss.c b/c/zss.c index 4737741eb..94227cde3 100644 --- a/c/zss.c +++ b/c/zss.c @@ -331,7 +331,10 @@ static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpReques int rc = 0; HttpRequestParser *parser = conversation->parser; char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; - rc = getProfileNameFromRequest(profileName, request->parsedFile, request->method, -1, response); + char method[16]; + snprintf(method, sizeof(method), "%s", request->method); + destructivelyNativize(method); + rc = getProfileNameFromRequest(profileName, request->parsedFile, method, -1, response); if (rc != 0) { return -1; } From 60f1e4ca825d5d625ec279fe306a3d6bad295617 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Wed, 23 Jun 2021 10:28:00 +0500 Subject: [PATCH 35/68] More code cleanup Signed-off-by: Leonty Chudinov --- c/zss.c | 30 ++- deps/zowe-common-c | 2 +- tmp/c/authService.c | 537 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 552 insertions(+), 17 deletions(-) create mode 100644 tmp/c/authService.c diff --git a/c/zss.c b/c/zss.c index 94227cde3..437db8745 100644 --- a/c/zss.c +++ b/c/zss.c @@ -129,7 +129,6 @@ static hashtable *getServerTimeoutsHt(ShortLivedHeap *slh, Json *serverTimeouts, static InternalAPIMap *makeInternalAPIMap(void); static bool readGatewaySettings(JsonObject *serverConfig, JsonObject *envConfig, char **outGatewayHost, int *outGatewayPort); static bool isCachingServiceEnabled(JsonObject *serverConfig, JsonObject *envConfig); -static int authHandlerFunction(); static int servePluginDefinitions(HttpService *service, HttpResponse *response){ zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); @@ -326,22 +325,21 @@ static void setPrivilegedServerName(HttpServer *server, JsonObject *mvdSettings, } #endif /* __ZOWE_OS_ZOS */ -static int nativeWithSessionTokenAuth(HttpConversation *conversation, HttpRequest *request, HttpService *service, HttpResponse *response) { - if (conversation->parser) { - int rc = 0; - HttpRequestParser *parser = conversation->parser; - char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; - char method[16]; - snprintf(method, sizeof(method), "%s", request->method); - destructivelyNativize(method); - rc = getProfileNameFromRequest(profileName, request->parsedFile, method, -1, response); - if (rc != 0) { - return -1; - } - rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2); - return rc; +static int nativeWithSessionTokenAuth(HttpService *service, HttpRequest *request, HttpResponse *response) { + int rc = 0; + char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; + char method[16]; + snprintf(method, sizeof(method), "%s", request->method); + destructivelyNativize(method); + rc = getProfileNameFromRequest(profileName, request->parsedFile, method, -1, response); + if (rc != 0) { + return FALSE; + } + rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2); + if (rc != 0) { + return FALSE; } - return -1; + return TRUE; } /* Future custom ZSS authorization handlers go here */ diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 1673b5f82..632cb11bd 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 1673b5f825570481e3452e68e90be8e6e0279227 +Subproject commit 632cb11bdc6ca44251a84ff8c7ceaa5e2c029812 diff --git a/tmp/c/authService.c b/tmp/c/authService.c new file mode 100644 index 000000000..1afc9525f --- /dev/null +++ b/tmp/c/authService.c @@ -0,0 +1,537 @@ + + +/* + This program and the accompanying materials are + made available under the terms of the Eclipse Public License v2.0 which accompanies + this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html + + SPDX-License-Identifier: EPL-2.0 + + Copyright Contributors to the Zowe Project. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "authService.h" +#include "zowetypes.h" +#include "alloc.h" +#include "utils.h" +#ifdef __ZOWE_OS_ZOS +#include "zos.h" +#endif +#include "logging.h" +#include "json.h" +#include "bpxnet.h" +#include "socketmgmt.h" +#include "zis/client.h" +#include "httpserver.h" +#include "zssLogging.h" + +#define SAF_CLASS "ZOWE" +#define JSON_ERROR_BUFFER_SIZE 1024 +#define STRING_BUFFER_SIZE 1024 +#define SAF_SUB_URL_SIZE 16 + +#define SAF_PASSWORD_RESET_RC_OK 0 +#define SAF_PASSWORD_RESET_RC_WRONG_PASSWORD 111 +#define SAF_PASSWORD_RESET_RC_WRONG_USER 143 +#define SAF_PASSWORD_RESET_RC_TOO_MANY_ATTEMPTS 163 +#define SAF_PASSWORD_RESET_RC_NO_NEW_PASSSWORD 168 +#define SAF_PASSWORD_RESET_RC_WRONG_FORMAT 169 + +#define RESPONSE_MESSAGE_LENGTH 100 + +/* + * A handler performing the SAF_AUTH check: checks if the user has the + * specified access to the specified entity in the specified class + * + * URL format: + * GET .../saf-auth//// + * Example: /saf-auth/PDUSR/FACILITY/CQM.CAE.ADMINISTRATOR/READ + * + * Response examples: + * - The user is authorized: { "authorized": true } + * - Not authorized: { "authorized": false, message: "..." } + * - Error: { + * "error": true, + * "message": "..." + * } + */ + +static int serveAuthCheck(HttpService *service, HttpResponse *response); + +int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char* entity, int access); + +static int makeProfileName( + char *profileName, + const char *type, + const char *productCode, + int instanceID, + const char *pluginID, + const char *rootServiceName, + const char *serviceName, + const char *method, + const char *scope, + char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]); + +static void setProfileNameAttribs( + char *pluginID, + char *serviceName, + char *type, + char *scope, + char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]); + +int installAuthCheckService(HttpServer *server) { +// zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "begin %s\n", +// __FUNCTION__); + HttpService *httpService = makeGeneratedService("SAF_AUTH service", + "/saf-auth/**"); + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->serviceFunction = &serveAuthCheck; + httpService->runInSubtask = FALSE; + registerHttpService(server, httpService); +// zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "end %s\n", +// __FUNCTION__); + return 0; +} + +static int extractQuery(StringList *path, char **entity, char **access) { + const StringListElt *pathElt; + +#define TEST_NEXT_AND_SET($ptr) do { \ + pathElt = pathElt->next; \ + if (pathElt == NULL) { \ + return -1; \ + } \ + *$ptr = pathElt->string; \ +} while (0) + + pathElt = firstStringListElt(path); + while (pathElt && (strcmp(pathElt->string, "saf-auth") != 0)) { + pathElt = pathElt->next; + } + if (pathElt == NULL) { + return -1; + } + TEST_NEXT_AND_SET(entity); + TEST_NEXT_AND_SET(access); + return 0; +#undef TEST_NEXT_AND_SET +} + +static int parseAcess(const char inStr[], int *outNum) { + int rc; + + if (strcasecmp("ALTER", inStr) == 0) { + *outNum = SAF_AUTH_ATTR_ALTER; + } else if (strcasecmp("CONTROL", inStr) == 0) { + *outNum = SAF_AUTH_ATTR_CONTROL; + } else if (strcasecmp("UPDATE", inStr) == 0) { + *outNum = SAF_AUTH_ATTR_UPDATE; + } else if (strcasecmp("READ", inStr) == 0) { + *outNum = SAF_AUTH_ATTR_READ; + } else { + return -1; + } + return 0; +} + +static void respond(HttpResponse *res, int rc, const ZISAuthServiceStatus + *reqStatus) { + jsonPrinter* p = respondWithJsonPrinter(res); + + setResponseStatus(res, HTTP_STATUS_OK, "OK"); + setDefaultJSONRESTHeaders(res); + writeHeader(res); + if (rc == RC_ZIS_SRVC_OK) { + jsonStart(p); { + jsonAddBoolean(p, "authorized", true); + } + jsonEnd(p); + } else { + char errBuf[0x100]; + +#define FORMAT_ERROR($fmt, ...) snprintf(errBuf, sizeof (errBuf), $fmt, \ + ##__VA_ARGS__) + + ZIS_FORMAT_AUTH_CALL_STATUS(rc, reqStatus, FORMAT_ERROR); +#undef FORMAT_ERROR + jsonStart(p); { + if (rc == RC_ZIS_SRVC_SERVICE_FAILED + && reqStatus->safStatus.safRC != 0) { + jsonAddBoolean(p, "authorized", false); + } else { + jsonAddBoolean(p, "error", true); + } + jsonAddString(p, "message", errBuf); + } + jsonEnd(p); + } + finishResponse(res); +} + +static int serveAuthCheck(HttpService *service, HttpResponse *res) { + HttpRequest *req = res->request; + char *entity, *accessStr; + int access = 0; + int rc = 0, rsn = 0, safStatus = 0; + ZISAuthServiceStatus reqStatus = {0}; + CrossMemoryServerName *privilegedServerName; + const char *userName = req->username, *class = SAF_CLASS; + rc = extractQuery(req->parsedFile, &entity, &accessStr); + if (rc != 0) { + respondWithError(res, HTTP_STATUS_BAD_REQUEST, "Broken auth query"); + return 0; + } + rc = parseAcess(accessStr, &access); + if (rc != 0) { + respondWithError(res, HTTP_STATUS_BAD_REQUEST, "Unexpected access level"); + return 0; + } + + privilegedServerName = getConfiguredProperty(service->server, + HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); + rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, + &reqStatus); + + respond(res, rc, &reqStatus); + return 0; +} + +int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char *entity, int access) { + int rc = 0; + JsonObject *dataserviceAuth = jsonObjectGetObject(service->server->sharedServiceMem, "dataserviceAuthentication"); + int rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); + CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, + HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); + ZISAuthServiceStatus reqStatus = {0}; + if (!rbacParm) { + return rc; // When rbac isn't enabled, we don't try to check the auth query + } + rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, + &reqStatus); + return rc; +} + +int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response) { + char type[STRING_BUFFER_SIZE]; // core || config || service + char productCode[STRING_BUFFER_SIZE]; + char rootServiceName[STRING_BUFFER_SIZE]; + char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE] = {0}; + char scope[STRING_BUFFER_SIZE]; + char pluginID[STRING_BUFFER_SIZE]; + char serviceName[STRING_BUFFER_SIZE]; + char urlSegment[STRING_BUFFER_SIZE]; + int subUrlIndex = 0; + + snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, 1, 1, "/", 0)); + StringListElt *pathSegment = firstStringListElt(parsedFile); + + strupcase(urlSegment); + if (instanceID < 0) { // Set instanceID + instanceID = 0; + } + if (strcmp(urlSegment, "PLUGINS") != 0) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, + "parsedFile urlSegment check didn't match."); + subUrlIndex = -1; + while (pathSegment != NULL) { + snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); + strupcase(urlSegment); + if (rootServiceName == NULL) + { + snprintf(rootServiceName, STRING_BUFFER_SIZE, urlSegment); + } else { + if (subUrlIndex < SAF_SUB_URL_SIZE) { + snprintf(subUrl[subUrlIndex], STRING_BUFFER_SIZE, urlSegment); + } + } + subUrlIndex++; + pathSegment = pathSegment->next; + } + snprintf(productCode, STRING_BUFFER_SIZE, "ZLUX"); + snprintf(type, STRING_BUFFER_SIZE, "core"); + } else { + subUrlIndex = 0; + + while (pathSegment != NULL) { + snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); + strupcase(urlSegment); + switch(subUrlIndex) { + case 0: + snprintf(productCode, STRING_BUFFER_SIZE, urlSegment); + break; + case 1: + break; + case 2: + snprintf(pluginID, STRING_BUFFER_SIZE, urlSegment); + break; + case 3: + break; + case 4: + snprintf(serviceName, STRING_BUFFER_SIZE, urlSegment); + break; + case 5: + break; + default: { + int adjustedSubUrlIndex = subUrlIndex - 6; // subtract 6 from maximum index to begin init subUrl array at 0 + if (adjustedSubUrlIndex < SAF_SUB_URL_SIZE) { + snprintf(subUrl[adjustedSubUrlIndex], STRING_BUFFER_SIZE, urlSegment); + } + } + } + subUrlIndex++; + pathSegment = pathSegment->next; + } + + setProfileNameAttribs(pluginID, serviceName, type, scope, subUrl); + int pluginIDLen = strlen(pluginID); + for (int index = 0; index < pluginIDLen; index++) { + if (pluginID[index] == '.') { + pluginID[index] = '_'; + } + } + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, + "parsedFile urlSegment check OK."); + } + return makeProfileName(profileName, type, + productCode, + instanceID, + pluginID, + rootServiceName, + serviceName, + method, + scope, + subUrl); +} + +static void setProfileNameAttribs( + char *pluginID, + char *serviceName, + char *type, + char *scope, + char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { + if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) + { + snprintf(type, STRING_BUFFER_SIZE, "config"); + snprintf(pluginID, STRING_BUFFER_SIZE, subUrl[0]); + snprintf(scope, STRING_BUFFER_SIZE, subUrl[1]); + + } else { + snprintf(type, STRING_BUFFER_SIZE, "service"); + } +} + +static int makeProfileName( + char *profileName, + const char *type, + const char *productCode, + int instanceID, + const char *pluginID, + const char *rootServiceName, + const char *serviceName, + const char *method, + const char *scope, + char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { + if (instanceID == -1) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing instance ID."); + return -1; + } + if (method == NULL) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing method."); + return -1; + } + int pos = 0; + if (strcmp(type, "service") == 0) { + if (pluginID == NULL) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing plugin ID."); + return -1; + } + if (serviceName == NULL) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing service name."); + return -1; + } + pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); + } else if (strcmp(type, "config") == 0) { + if (pluginID == NULL) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing plugin ID."); + return -1; + } + if (scope == NULL) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing scope."); + return -1; + } + pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); + } else if (strcmp(type, "core") == 0) { + if (rootServiceName == NULL) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Broken SAF query. Missing root service name."); + return -1; + } + pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + } + // Child endpoints housed via subUrl + int index = 0; + while (index < SAF_SUB_URL_SIZE && strcmp(subUrl[index], "") != 0) { + if (pos > ZOWE_PROFILE_NAME_LEN) { + break; + } + pos += snprintf(profileName + pos, ZOWE_PROFILE_NAME_LEN + 1 - pos, ".%s", subUrl[index]); + index++; + } + if (pos > ZOWE_PROFILE_NAME_LEN) { + char errMsg[256]; + snprintf(errMsg, sizeof(errMsg), "Generated SAF query longer than %d\n", ZOWE_PROFILE_NAME_LEN); + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, errMsg); + return -1; + } + return 0; +} + +void respondWithJsonStatus(HttpResponse *response, const char *status, int statusCode, const char *statusMessage) { + jsonPrinter *out = respondWithJsonPrinter(response); + setResponseStatus(response,statusCode,(char *)statusMessage); + setDefaultJSONRESTHeaders(response); + writeHeader(response); + + jsonStart(out); + jsonAddString(out, "status", (char *)status); + jsonEnd(out); + + finishResponse(response); +} + +static int resetPassword(HttpService *service, HttpResponse *response) { + int returnCode = 0, reasonCode = 0; + HttpRequest *request = response->request; + + if (!strcmp(request->method, methodPOST)) { + char *inPtr = request->contentBody; + char *nativeBody = copyStringToNative(request->slh, inPtr, strlen(inPtr)); + int inLen = nativeBody == NULL ? 0 : strlen(nativeBody); + char errBuf[JSON_ERROR_BUFFER_SIZE]; + char responseString[RESPONSE_MESSAGE_LENGTH]; + + if (nativeBody == NULL) { + respondWithJsonStatus(response, "No body found", HTTP_STATUS_BAD_REQUEST, "Bad Request"); + return HTTP_SERVICE_FAILED; + } + + Json *body = jsonParseUnterminatedString(request->slh, nativeBody, inLen, errBuf, JSON_ERROR_BUFFER_SIZE); + + if (body == NULL) { + respondWithJsonStatus(response, "No body found", HTTP_STATUS_BAD_REQUEST, "Bad Request"); + return HTTP_SERVICE_FAILED; + } + + JsonObject *inputMessage = jsonAsObject(body); + Json *username = jsonObjectGetPropertyValue(inputMessage,"username"); + Json *password = jsonObjectGetPropertyValue(inputMessage,"password"); + Json *newPassword = jsonObjectGetPropertyValue(inputMessage,"newPassword"); + int usernameLength = 0; + int passwordLength = 0; + int newPasswordLength = 0; + if (username != NULL) { + if (jsonAsString(username) != NULL) { + usernameLength = strlen(jsonAsString(username)); + } + } + if (password != NULL) { + if (jsonAsString(password) != NULL) { + passwordLength = strlen(jsonAsString(password)); + } + } + if (newPassword != NULL) { + if (jsonAsString(newPassword) != NULL) { + newPasswordLength = strlen(jsonAsString(newPassword)); + } + } + if (usernameLength == 0) { + respondWithJsonStatus(response, "No username provided", + HTTP_STATUS_BAD_REQUEST, "Bad Request"); + return HTTP_SERVICE_FAILED; + } + if (passwordLength == 0) { + respondWithJsonStatus(response, "No password provided", + HTTP_STATUS_BAD_REQUEST, "Bad Request"); + return HTTP_SERVICE_FAILED; + } + if (newPasswordLength == 0) { + respondWithJsonStatus(response, "No new password provided", + HTTP_STATUS_BAD_REQUEST, "Bad Request"); + return HTTP_SERVICE_FAILED; + } + resetZosUserPassword(jsonAsString(username), jsonAsString(password), jsonAsString(newPassword), &returnCode, &reasonCode); + + switch (returnCode) { + case SAF_PASSWORD_RESET_RC_OK: + respondWithJsonStatus(response, "Password Successfully Reset", HTTP_STATUS_OK, "OK"); + return HTTP_SERVICE_SUCCESS; + case SAF_PASSWORD_RESET_RC_WRONG_PASSWORD: + respondWithJsonStatus(response, "Username or password is incorrect. Please try again.", + HTTP_STATUS_UNAUTHORIZED, "Unauthorized"); + return HTTP_SERVICE_FAILED; + case SAF_PASSWORD_RESET_RC_WRONG_USER: + respondWithJsonStatus(response, "Username or password is incorrect. Please try again.", + HTTP_STATUS_UNAUTHORIZED, "Unauthorized"); + return HTTP_SERVICE_FAILED; + case SAF_PASSWORD_RESET_RC_NO_NEW_PASSSWORD: + respondWithJsonStatus(response, "No new password provided", + HTTP_STATUS_BAD_REQUEST, "Bad Request"); + return HTTP_SERVICE_FAILED; + case SAF_PASSWORD_RESET_RC_WRONG_FORMAT: + respondWithJsonStatus(response, "The new password format is incorrect. Please try again.", + HTTP_STATUS_BAD_REQUEST, "Bad Request"); + return HTTP_SERVICE_FAILED; + case SAF_PASSWORD_RESET_RC_TOO_MANY_ATTEMPTS: + respondWithJsonStatus(response, + "Incorrect password or account is locked. Please contact your administrator.", + HTTP_STATUS_TOO_MANY_REQUESTS, "Bad Request"); + return HTTP_SERVICE_FAILED; + default: + snprintf(responseString, RESPONSE_MESSAGE_LENGTH, "Password reset FAILED with return code: %d reason code: %d", returnCode, reasonCode); + respondWithJsonStatus(response, responseString, HTTP_STATUS_BAD_REQUEST, "Bad Request"); + return HTTP_SERVICE_FAILED; + } + } else { + respondWithJsonStatus(response, "Method Not Allowed", + HTTP_STATUS_METHOD_NOT_FOUND, "Method Not Allowed"); + return HTTP_SERVICE_FAILED; + } +} + +void installZosPasswordService(HttpServer *server) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); + + HttpService *httpService = makeGeneratedService("password service", "/password/**"); + httpService->authType = SERVICE_AUTH_NONE; + httpService->runInSubtask = TRUE; + httpService->serviceFunction = resetPassword; + registerHttpService(server, httpService); + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "end %s\n", __FUNCTION__); +} + +/* + This program and the accompanying materials are + made available under the terms of the Eclipse Public License v2.0 which accompanies + this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html + + SPDX-License-Identifier: EPL-2.0 + + Copyright Contributors to the Zowe Project. +*/ + From 4beeca27e809edfaf232a61161befaa4eff6a9cd Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Thu, 24 Jun 2021 21:27:03 -0400 Subject: [PATCH 36/68] Respect env variable for RBAC too Signed-off-by: Leanid Astrakou --- c/authService.c | 15 +++++++++++---- c/zss.c | 4 +++- h/authService.h | 3 ++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/c/authService.c b/c/authService.c index 1afc9525f..1934a15f8 100644 --- a/c/authService.c +++ b/c/authService.c @@ -68,7 +68,7 @@ static int serveAuthCheck(HttpService *service, HttpResponse *response); -int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char* entity, int access); +int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char* entity, int access, JsonObject *envSettings); static int makeProfileName( char *profileName, @@ -206,10 +206,17 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { return 0; } -int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char *entity, int access) { +int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char *entity, int access, JsonObject *envSettings) { int rc = 0; - JsonObject *dataserviceAuth = jsonObjectGetObject(service->server->sharedServiceMem, "dataserviceAuthentication"); - int rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); + int rbacParm; + Json *rbacObj = jsonObjectGetPropertyValue(envSettings, "ZWED_dataserviceAuthentication_rbac"); + if (rbacObj == NULL) { // Env variable doesn't exist, so check server config + JsonObject *dataserviceAuth = jsonObjectGetObject(service->server->sharedServiceMem, "dataserviceAuthentication"); + rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); + } else { // Use env variable value + rbacParm = jsonAsBoolean(rbacObj); + } + CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); ZISAuthServiceStatus reqStatus = {0}; diff --git a/c/zss.c b/c/zss.c index 437db8745..c486e12cc 100644 --- a/c/zss.c +++ b/c/zss.c @@ -98,6 +98,7 @@ char productVersion[40]; static JsonObject *MVD_SETTINGS = NULL; +static JsonObject *ENV_SETTINGS = NULL; static int traceLevel = 0; #define JSON_ERROR_BUFFER_SIZE 1024 @@ -335,7 +336,7 @@ static int nativeWithSessionTokenAuth(HttpService *service, HttpRequest *request if (rc != 0) { return FALSE; } - rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2); + rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2, ENV_SETTINGS); if (rc != 0) { return FALSE; } @@ -356,6 +357,7 @@ static void loadWebServerConfig(HttpServer *server, JsonObject *mvdSettings, JsonObject *envSettings, hashtable *htUsers, hashtable *htGroups, int defaultSessionTimeout){ MVD_SETTINGS = mvdSettings; + ENV_SETTINGS = envSettings; /* Disabled because this server is not being used by end users, but called by other servers * HttpService *mainService = makeGeneratedService("main", "/"); * mainService->serviceFunction = serveMainPage; diff --git a/h/authService.h b/h/authService.h index 90c4f5636..55e5f9fb4 100644 --- a/h/authService.h +++ b/h/authService.h @@ -50,10 +50,11 @@ int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *m * @param Class Class to use in ZIS check i.e. "ZOWE" * @param entity Describes the SAF query itself i.e. "ZLUX.0.COR.GET.SERVER.AGENT.CONFIG" * @param access Describes the access type i.e. "READ" + * @param envSettings JSON object that holds environment variables, if any * * @return Return code where != 0 is a failed RBAC check */ -int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access); +int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access, JsonObject *envSettings); #endif From c5372016529de0933fad1a89dc607d0eb54ff31d Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Thu, 24 Jun 2021 21:42:05 -0400 Subject: [PATCH 37/68] Added some useful debug logging Signed-off-by: Leanid Astrakou --- c/authService.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/c/authService.c b/c/authService.c index 1934a15f8..62a834651 100644 --- a/c/authService.c +++ b/c/authService.c @@ -225,6 +225,8 @@ int serveAuthCheckByParams(HttpService *service, char *userName, char *class, ch } rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, + "RBAC check occurred for entity '%s' class '%s' access '%d' , rc: %d", entity, class, access, rc); return rc; } @@ -406,6 +408,8 @@ static int makeProfileName( zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, errMsg); return -1; } + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, + "Finished generating profileName: %s", profileName); return 0; } From a9f1ed13ffe13e4c73d7e74fb4c6c456b861b20d Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Thu, 1 Jul 2021 09:10:51 +0500 Subject: [PATCH 38/68] Remove mistakenly added file Signed-off-by: Leonty Chudinov --- tmp/c/authService.c | 537 -------------------------------------------- 1 file changed, 537 deletions(-) delete mode 100644 tmp/c/authService.c diff --git a/tmp/c/authService.c b/tmp/c/authService.c deleted file mode 100644 index 1afc9525f..000000000 --- a/tmp/c/authService.c +++ /dev/null @@ -1,537 +0,0 @@ - - -/* - This program and the accompanying materials are - made available under the terms of the Eclipse Public License v2.0 which accompanies - this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html - - SPDX-License-Identifier: EPL-2.0 - - Copyright Contributors to the Zowe Project. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "authService.h" -#include "zowetypes.h" -#include "alloc.h" -#include "utils.h" -#ifdef __ZOWE_OS_ZOS -#include "zos.h" -#endif -#include "logging.h" -#include "json.h" -#include "bpxnet.h" -#include "socketmgmt.h" -#include "zis/client.h" -#include "httpserver.h" -#include "zssLogging.h" - -#define SAF_CLASS "ZOWE" -#define JSON_ERROR_BUFFER_SIZE 1024 -#define STRING_BUFFER_SIZE 1024 -#define SAF_SUB_URL_SIZE 16 - -#define SAF_PASSWORD_RESET_RC_OK 0 -#define SAF_PASSWORD_RESET_RC_WRONG_PASSWORD 111 -#define SAF_PASSWORD_RESET_RC_WRONG_USER 143 -#define SAF_PASSWORD_RESET_RC_TOO_MANY_ATTEMPTS 163 -#define SAF_PASSWORD_RESET_RC_NO_NEW_PASSSWORD 168 -#define SAF_PASSWORD_RESET_RC_WRONG_FORMAT 169 - -#define RESPONSE_MESSAGE_LENGTH 100 - -/* - * A handler performing the SAF_AUTH check: checks if the user has the - * specified access to the specified entity in the specified class - * - * URL format: - * GET .../saf-auth//// - * Example: /saf-auth/PDUSR/FACILITY/CQM.CAE.ADMINISTRATOR/READ - * - * Response examples: - * - The user is authorized: { "authorized": true } - * - Not authorized: { "authorized": false, message: "..." } - * - Error: { - * "error": true, - * "message": "..." - * } - */ - -static int serveAuthCheck(HttpService *service, HttpResponse *response); - -int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char* entity, int access); - -static int makeProfileName( - char *profileName, - const char *type, - const char *productCode, - int instanceID, - const char *pluginID, - const char *rootServiceName, - const char *serviceName, - const char *method, - const char *scope, - char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]); - -static void setProfileNameAttribs( - char *pluginID, - char *serviceName, - char *type, - char *scope, - char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]); - -int installAuthCheckService(HttpServer *server) { -// zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "begin %s\n", -// __FUNCTION__); - HttpService *httpService = makeGeneratedService("SAF_AUTH service", - "/saf-auth/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->serviceFunction = &serveAuthCheck; - httpService->runInSubtask = FALSE; - registerHttpService(server, httpService); -// zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "end %s\n", -// __FUNCTION__); - return 0; -} - -static int extractQuery(StringList *path, char **entity, char **access) { - const StringListElt *pathElt; - -#define TEST_NEXT_AND_SET($ptr) do { \ - pathElt = pathElt->next; \ - if (pathElt == NULL) { \ - return -1; \ - } \ - *$ptr = pathElt->string; \ -} while (0) - - pathElt = firstStringListElt(path); - while (pathElt && (strcmp(pathElt->string, "saf-auth") != 0)) { - pathElt = pathElt->next; - } - if (pathElt == NULL) { - return -1; - } - TEST_NEXT_AND_SET(entity); - TEST_NEXT_AND_SET(access); - return 0; -#undef TEST_NEXT_AND_SET -} - -static int parseAcess(const char inStr[], int *outNum) { - int rc; - - if (strcasecmp("ALTER", inStr) == 0) { - *outNum = SAF_AUTH_ATTR_ALTER; - } else if (strcasecmp("CONTROL", inStr) == 0) { - *outNum = SAF_AUTH_ATTR_CONTROL; - } else if (strcasecmp("UPDATE", inStr) == 0) { - *outNum = SAF_AUTH_ATTR_UPDATE; - } else if (strcasecmp("READ", inStr) == 0) { - *outNum = SAF_AUTH_ATTR_READ; - } else { - return -1; - } - return 0; -} - -static void respond(HttpResponse *res, int rc, const ZISAuthServiceStatus - *reqStatus) { - jsonPrinter* p = respondWithJsonPrinter(res); - - setResponseStatus(res, HTTP_STATUS_OK, "OK"); - setDefaultJSONRESTHeaders(res); - writeHeader(res); - if (rc == RC_ZIS_SRVC_OK) { - jsonStart(p); { - jsonAddBoolean(p, "authorized", true); - } - jsonEnd(p); - } else { - char errBuf[0x100]; - -#define FORMAT_ERROR($fmt, ...) snprintf(errBuf, sizeof (errBuf), $fmt, \ - ##__VA_ARGS__) - - ZIS_FORMAT_AUTH_CALL_STATUS(rc, reqStatus, FORMAT_ERROR); -#undef FORMAT_ERROR - jsonStart(p); { - if (rc == RC_ZIS_SRVC_SERVICE_FAILED - && reqStatus->safStatus.safRC != 0) { - jsonAddBoolean(p, "authorized", false); - } else { - jsonAddBoolean(p, "error", true); - } - jsonAddString(p, "message", errBuf); - } - jsonEnd(p); - } - finishResponse(res); -} - -static int serveAuthCheck(HttpService *service, HttpResponse *res) { - HttpRequest *req = res->request; - char *entity, *accessStr; - int access = 0; - int rc = 0, rsn = 0, safStatus = 0; - ZISAuthServiceStatus reqStatus = {0}; - CrossMemoryServerName *privilegedServerName; - const char *userName = req->username, *class = SAF_CLASS; - rc = extractQuery(req->parsedFile, &entity, &accessStr); - if (rc != 0) { - respondWithError(res, HTTP_STATUS_BAD_REQUEST, "Broken auth query"); - return 0; - } - rc = parseAcess(accessStr, &access); - if (rc != 0) { - respondWithError(res, HTTP_STATUS_BAD_REQUEST, "Unexpected access level"); - return 0; - } - - privilegedServerName = getConfiguredProperty(service->server, - HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); - rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, - &reqStatus); - - respond(res, rc, &reqStatus); - return 0; -} - -int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char *entity, int access) { - int rc = 0; - JsonObject *dataserviceAuth = jsonObjectGetObject(service->server->sharedServiceMem, "dataserviceAuthentication"); - int rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); - CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, - HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); - ZISAuthServiceStatus reqStatus = {0}; - if (!rbacParm) { - return rc; // When rbac isn't enabled, we don't try to check the auth query - } - rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, - &reqStatus); - return rc; -} - -int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response) { - char type[STRING_BUFFER_SIZE]; // core || config || service - char productCode[STRING_BUFFER_SIZE]; - char rootServiceName[STRING_BUFFER_SIZE]; - char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE] = {0}; - char scope[STRING_BUFFER_SIZE]; - char pluginID[STRING_BUFFER_SIZE]; - char serviceName[STRING_BUFFER_SIZE]; - char urlSegment[STRING_BUFFER_SIZE]; - int subUrlIndex = 0; - - snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, 1, 1, "/", 0)); - StringListElt *pathSegment = firstStringListElt(parsedFile); - - strupcase(urlSegment); - if (instanceID < 0) { // Set instanceID - instanceID = 0; - } - if (strcmp(urlSegment, "PLUGINS") != 0) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "parsedFile urlSegment check didn't match."); - subUrlIndex = -1; - while (pathSegment != NULL) { - snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); - strupcase(urlSegment); - if (rootServiceName == NULL) - { - snprintf(rootServiceName, STRING_BUFFER_SIZE, urlSegment); - } else { - if (subUrlIndex < SAF_SUB_URL_SIZE) { - snprintf(subUrl[subUrlIndex], STRING_BUFFER_SIZE, urlSegment); - } - } - subUrlIndex++; - pathSegment = pathSegment->next; - } - snprintf(productCode, STRING_BUFFER_SIZE, "ZLUX"); - snprintf(type, STRING_BUFFER_SIZE, "core"); - } else { - subUrlIndex = 0; - - while (pathSegment != NULL) { - snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); - strupcase(urlSegment); - switch(subUrlIndex) { - case 0: - snprintf(productCode, STRING_BUFFER_SIZE, urlSegment); - break; - case 1: - break; - case 2: - snprintf(pluginID, STRING_BUFFER_SIZE, urlSegment); - break; - case 3: - break; - case 4: - snprintf(serviceName, STRING_BUFFER_SIZE, urlSegment); - break; - case 5: - break; - default: { - int adjustedSubUrlIndex = subUrlIndex - 6; // subtract 6 from maximum index to begin init subUrl array at 0 - if (adjustedSubUrlIndex < SAF_SUB_URL_SIZE) { - snprintf(subUrl[adjustedSubUrlIndex], STRING_BUFFER_SIZE, urlSegment); - } - } - } - subUrlIndex++; - pathSegment = pathSegment->next; - } - - setProfileNameAttribs(pluginID, serviceName, type, scope, subUrl); - int pluginIDLen = strlen(pluginID); - for (int index = 0; index < pluginIDLen; index++) { - if (pluginID[index] == '.') { - pluginID[index] = '_'; - } - } - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "parsedFile urlSegment check OK."); - } - return makeProfileName(profileName, type, - productCode, - instanceID, - pluginID, - rootServiceName, - serviceName, - method, - scope, - subUrl); -} - -static void setProfileNameAttribs( - char *pluginID, - char *serviceName, - char *type, - char *scope, - char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { - if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) - { - snprintf(type, STRING_BUFFER_SIZE, "config"); - snprintf(pluginID, STRING_BUFFER_SIZE, subUrl[0]); - snprintf(scope, STRING_BUFFER_SIZE, subUrl[1]); - - } else { - snprintf(type, STRING_BUFFER_SIZE, "service"); - } -} - -static int makeProfileName( - char *profileName, - const char *type, - const char *productCode, - int instanceID, - const char *pluginID, - const char *rootServiceName, - const char *serviceName, - const char *method, - const char *scope, - char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { - if (instanceID == -1) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing instance ID."); - return -1; - } - if (method == NULL) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing method."); - return -1; - } - int pos = 0; - if (strcmp(type, "service") == 0) { - if (pluginID == NULL) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing plugin ID."); - return -1; - } - if (serviceName == NULL) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing service name."); - return -1; - } - pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); - } else if (strcmp(type, "config") == 0) { - if (pluginID == NULL) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing plugin ID."); - return -1; - } - if (scope == NULL) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing scope."); - return -1; - } - pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); - } else if (strcmp(type, "core") == 0) { - if (rootServiceName == NULL) { - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing root service name."); - return -1; - } - pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); - } - // Child endpoints housed via subUrl - int index = 0; - while (index < SAF_SUB_URL_SIZE && strcmp(subUrl[index], "") != 0) { - if (pos > ZOWE_PROFILE_NAME_LEN) { - break; - } - pos += snprintf(profileName + pos, ZOWE_PROFILE_NAME_LEN + 1 - pos, ".%s", subUrl[index]); - index++; - } - if (pos > ZOWE_PROFILE_NAME_LEN) { - char errMsg[256]; - snprintf(errMsg, sizeof(errMsg), "Generated SAF query longer than %d\n", ZOWE_PROFILE_NAME_LEN); - zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, errMsg); - return -1; - } - return 0; -} - -void respondWithJsonStatus(HttpResponse *response, const char *status, int statusCode, const char *statusMessage) { - jsonPrinter *out = respondWithJsonPrinter(response); - setResponseStatus(response,statusCode,(char *)statusMessage); - setDefaultJSONRESTHeaders(response); - writeHeader(response); - - jsonStart(out); - jsonAddString(out, "status", (char *)status); - jsonEnd(out); - - finishResponse(response); -} - -static int resetPassword(HttpService *service, HttpResponse *response) { - int returnCode = 0, reasonCode = 0; - HttpRequest *request = response->request; - - if (!strcmp(request->method, methodPOST)) { - char *inPtr = request->contentBody; - char *nativeBody = copyStringToNative(request->slh, inPtr, strlen(inPtr)); - int inLen = nativeBody == NULL ? 0 : strlen(nativeBody); - char errBuf[JSON_ERROR_BUFFER_SIZE]; - char responseString[RESPONSE_MESSAGE_LENGTH]; - - if (nativeBody == NULL) { - respondWithJsonStatus(response, "No body found", HTTP_STATUS_BAD_REQUEST, "Bad Request"); - return HTTP_SERVICE_FAILED; - } - - Json *body = jsonParseUnterminatedString(request->slh, nativeBody, inLen, errBuf, JSON_ERROR_BUFFER_SIZE); - - if (body == NULL) { - respondWithJsonStatus(response, "No body found", HTTP_STATUS_BAD_REQUEST, "Bad Request"); - return HTTP_SERVICE_FAILED; - } - - JsonObject *inputMessage = jsonAsObject(body); - Json *username = jsonObjectGetPropertyValue(inputMessage,"username"); - Json *password = jsonObjectGetPropertyValue(inputMessage,"password"); - Json *newPassword = jsonObjectGetPropertyValue(inputMessage,"newPassword"); - int usernameLength = 0; - int passwordLength = 0; - int newPasswordLength = 0; - if (username != NULL) { - if (jsonAsString(username) != NULL) { - usernameLength = strlen(jsonAsString(username)); - } - } - if (password != NULL) { - if (jsonAsString(password) != NULL) { - passwordLength = strlen(jsonAsString(password)); - } - } - if (newPassword != NULL) { - if (jsonAsString(newPassword) != NULL) { - newPasswordLength = strlen(jsonAsString(newPassword)); - } - } - if (usernameLength == 0) { - respondWithJsonStatus(response, "No username provided", - HTTP_STATUS_BAD_REQUEST, "Bad Request"); - return HTTP_SERVICE_FAILED; - } - if (passwordLength == 0) { - respondWithJsonStatus(response, "No password provided", - HTTP_STATUS_BAD_REQUEST, "Bad Request"); - return HTTP_SERVICE_FAILED; - } - if (newPasswordLength == 0) { - respondWithJsonStatus(response, "No new password provided", - HTTP_STATUS_BAD_REQUEST, "Bad Request"); - return HTTP_SERVICE_FAILED; - } - resetZosUserPassword(jsonAsString(username), jsonAsString(password), jsonAsString(newPassword), &returnCode, &reasonCode); - - switch (returnCode) { - case SAF_PASSWORD_RESET_RC_OK: - respondWithJsonStatus(response, "Password Successfully Reset", HTTP_STATUS_OK, "OK"); - return HTTP_SERVICE_SUCCESS; - case SAF_PASSWORD_RESET_RC_WRONG_PASSWORD: - respondWithJsonStatus(response, "Username or password is incorrect. Please try again.", - HTTP_STATUS_UNAUTHORIZED, "Unauthorized"); - return HTTP_SERVICE_FAILED; - case SAF_PASSWORD_RESET_RC_WRONG_USER: - respondWithJsonStatus(response, "Username or password is incorrect. Please try again.", - HTTP_STATUS_UNAUTHORIZED, "Unauthorized"); - return HTTP_SERVICE_FAILED; - case SAF_PASSWORD_RESET_RC_NO_NEW_PASSSWORD: - respondWithJsonStatus(response, "No new password provided", - HTTP_STATUS_BAD_REQUEST, "Bad Request"); - return HTTP_SERVICE_FAILED; - case SAF_PASSWORD_RESET_RC_WRONG_FORMAT: - respondWithJsonStatus(response, "The new password format is incorrect. Please try again.", - HTTP_STATUS_BAD_REQUEST, "Bad Request"); - return HTTP_SERVICE_FAILED; - case SAF_PASSWORD_RESET_RC_TOO_MANY_ATTEMPTS: - respondWithJsonStatus(response, - "Incorrect password or account is locked. Please contact your administrator.", - HTTP_STATUS_TOO_MANY_REQUESTS, "Bad Request"); - return HTTP_SERVICE_FAILED; - default: - snprintf(responseString, RESPONSE_MESSAGE_LENGTH, "Password reset FAILED with return code: %d reason code: %d", returnCode, reasonCode); - respondWithJsonStatus(response, responseString, HTTP_STATUS_BAD_REQUEST, "Bad Request"); - return HTTP_SERVICE_FAILED; - } - } else { - respondWithJsonStatus(response, "Method Not Allowed", - HTTP_STATUS_METHOD_NOT_FOUND, "Method Not Allowed"); - return HTTP_SERVICE_FAILED; - } -} - -void installZosPasswordService(HttpServer *server) { - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); - - HttpService *httpService = makeGeneratedService("password service", "/password/**"); - httpService->authType = SERVICE_AUTH_NONE; - httpService->runInSubtask = TRUE; - httpService->serviceFunction = resetPassword; - registerHttpService(server, httpService); - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "end %s\n", __FUNCTION__); -} - -/* - This program and the accompanying materials are - made available under the terms of the Eclipse Public License v2.0 which accompanies - this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html - - SPDX-License-Identifier: EPL-2.0 - - Copyright Contributors to the Zowe Project. -*/ - From 784031863de921dfd03f9fac3823a5b66e5361c5 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Thu, 1 Jul 2021 10:13:19 +0500 Subject: [PATCH 39/68] Update pointer to zowe-common-c Signed-off-by: Leonty Chudinov --- deps/zowe-common-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 632cb11bd..517679b97 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 632cb11bdc6ca44251a84ff8c7ceaa5e2c029812 +Subproject commit 517679b97184f0c0ccacefa9cf6d8d31e26d6bf4 From 954f921786f43bf3153001024d8e0602f3de6753 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Thu, 1 Jul 2021 10:55:18 +0500 Subject: [PATCH 40/68] Remove SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC Signed-off-by: Leonty Chudinov --- c/datasetService.c | 9 ++++++--- c/omvsService.c | 3 ++- c/securityService.c | 12 ++++++++---- c/unixFileService.c | 30 ++++++++++++++++++++---------- c/zss.c | 7 ++++--- deps/zowe-common-c | 2 +- 6 files changed, 41 insertions(+), 22 deletions(-) diff --git a/c/datasetService.c b/c/datasetService.c index e99c65d6d..5670cd5df 100644 --- a/c/datasetService.c +++ b/c/datasetService.c @@ -187,7 +187,8 @@ void installDatasetContentsService(HttpServer *server) { zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); HttpService *httpService = makeGeneratedService("datasetContents", "/datasetContents/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveDatasetContents; @@ -199,7 +200,8 @@ void installVSAMDatasetContentsService(HttpServer *server) { zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); HttpService *httpService = makeGeneratedService("VSAMdatasetContents", "/VSAMdatasetContents/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveVSAMDatasetContents; @@ -217,7 +219,8 @@ void installDatasetMetadataService(HttpServer *server) { HttpService *httpService = makeGeneratedService("datasetMetadata", "/datasetMetadata/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveDatasetMetadata; diff --git a/c/omvsService.c b/c/omvsService.c index dff82dd29..e5c2a5f87 100644 --- a/c/omvsService.c +++ b/c/omvsService.c @@ -53,7 +53,8 @@ static int issueRACFCommand(char *command, OMVSSegment *omvs); int installOMVSService(HttpServer *server) { HttpService *httpService = makeGeneratedService("OMVS_Service", "/omvs/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->serviceFunction = &serveOMVSSegment; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; diff --git a/c/securityService.c b/c/securityService.c index fa9cea571..dbef33186 100644 --- a/c/securityService.c +++ b/c/securityService.c @@ -3355,7 +3355,8 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); - classMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + classMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + classMgmtService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; classMgmtService->serviceFunction = &serveClassManagement; classMgmtService->runInSubtask = TRUE; classMgmtService->doImpersonation = TRUE; @@ -3369,7 +3370,8 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); - userProfileService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + userProfileService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + userProfileService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; userProfileService->serviceFunction = &serveUserProfile; userProfileService->runInSubtask = TRUE; userProfileService->doImpersonation = TRUE; @@ -3383,7 +3385,8 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); - groupMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + groupMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + groupMgmtService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; groupMgmtService->serviceFunction = &serveGroupManagement; groupMgmtService->runInSubtask = TRUE; groupMgmtService->doImpersonation = TRUE; @@ -3396,7 +3399,8 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("count", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, NULL )); - accessService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + accessService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + accessService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; accessService->serviceFunction = &serveAccessInfo; accessService->runInSubtask = TRUE; accessService->doImpersonation = TRUE; diff --git a/c/unixFileService.c b/c/unixFileService.c index cd4ae6248..e70af6e50 100644 --- a/c/unixFileService.c +++ b/c/unixFileService.c @@ -1099,7 +1099,8 @@ static int serveTableOfContents(HttpService *service, HttpResponse *response) { void installUnixFileContentsService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileContents", "/unixfile/contents/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->serviceFunction = serveUnixFileContents; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1118,7 +1119,8 @@ void installUnixFileContentsService(HttpServer *server) { void installUnixFileRenameService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileRename", "/unixfile/rename/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->serviceFunction = serveUnixFileRename; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1128,7 +1130,8 @@ void installUnixFileRenameService(HttpServer *server) { void installUnixFileCopyService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileCopy", "/unixfile/copy/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->serviceFunction = serveUnixFileCopy; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1138,7 +1141,8 @@ void installUnixFileCopyService(HttpServer *server) { void installUnixFileMakeDirectoryService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileMkdir", "/unixfile/mkdir/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->serviceFunction = serveUnixFileMakeDirectory; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1148,7 +1152,8 @@ void installUnixFileMakeDirectoryService(HttpServer *server) { void installUnixFileTouchService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileTouch", "/unixfile/touch/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->serviceFunction = serveUnixFileTouch; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1158,7 +1163,8 @@ void installUnixFileTouchService(HttpServer *server) { void installUnixFileMetadataService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/metadata/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveUnixFileMetadata; @@ -1168,7 +1174,8 @@ void installUnixFileMetadataService(HttpServer *server) { void installUnixFileChangeOwnerService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/chown/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveUnixFileChangeOwner; @@ -1178,7 +1185,8 @@ void installUnixFileChangeOwnerService(HttpServer *server) { void installUnixFileChangeTagService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileChtag", "/unixfile/chtag/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->serviceFunction = serveUnixFileChangeTag; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1188,7 +1196,8 @@ void installUnixFileChangeTagService(HttpServer *server) { void installUnixFileChangeModeService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileChmod", "/unixfile/chmod/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->serviceFunction = serveUnixFileChangeMode; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1198,7 +1207,8 @@ void installUnixFileChangeModeService(HttpServer *server) { void installUnixFileTableOfContentsService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveTableOfContents; diff --git a/c/zss.c b/c/zss.c index d475deebb..5f340880e 100644 --- a/c/zss.c +++ b/c/zss.c @@ -319,7 +319,7 @@ static void setPrivilegedServerName(HttpServer *server, JsonObject *mvdSettings, } #endif /* __ZOWE_OS_ZOS */ -static int nativeWithSessionTokenAuth(HttpService *service, HttpRequest *request, HttpResponse *response) { +static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpResponse *response) { int rc = 0; char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; char method[16]; @@ -342,7 +342,7 @@ static void initializeAuthHandlers(HttpServer *server) { /* NATIVE_WITH_SESSION_TOKEN */ server->authHandler[0] = (HttpAuthHandler*)safeMalloc31(sizeof(HttpAuthHandler),"HttpAuthHandler"); server->authHandler[0]->type = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - server->authHandler[0]->authFunction = &nativeWithSessionTokenAuth; + server->authHandler[0]->authFunction = &rbacAuthorization; } @@ -698,7 +698,8 @@ static void installLoginService(HttpServer *server) { zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); HttpService *httpService = makeGeneratedService("com.rs.mvd.login", "/login/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; httpService->serviceFunction = serveLoginWithSessionToken; httpService->authExtractionFunction = extractAuthorizationFromJson; registerHttpService(server, httpService); diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 517679b97..305ab94ff 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 517679b97184f0c0ccacefa9cf6d8d31e26d6bf4 +Subproject commit 305ab94ff6c7e0cc66b3066608b8e5637a81ad0e From 11ff99f2c60622d04c2de599e7d0a32bfc79776e Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Thu, 1 Jul 2021 16:47:11 +0500 Subject: [PATCH 41/68] Refactor authorization code Signed-off-by: Leonty Chudinov --- c/datasetService.c | 6 +++--- c/omvsService.c | 2 +- c/securityService.c | 8 ++++---- c/unixFileService.c | 20 ++++++++++---------- c/zss.c | 9 ++------- deps/zowe-common-c | 2 +- 6 files changed, 21 insertions(+), 26 deletions(-) diff --git a/c/datasetService.c b/c/datasetService.c index 5670cd5df..5b27995c4 100644 --- a/c/datasetService.c +++ b/c/datasetService.c @@ -188,7 +188,7 @@ void installDatasetContentsService(HttpServer *server) { HttpService *httpService = makeGeneratedService("datasetContents", "/datasetContents/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveDatasetContents; @@ -201,7 +201,7 @@ void installVSAMDatasetContentsService(HttpServer *server) { HttpService *httpService = makeGeneratedService("VSAMdatasetContents", "/VSAMdatasetContents/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveVSAMDatasetContents; @@ -220,7 +220,7 @@ void installDatasetMetadataService(HttpServer *server) { HttpService *httpService = makeGeneratedService("datasetMetadata", "/datasetMetadata/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveDatasetMetadata; diff --git a/c/omvsService.c b/c/omvsService.c index e5c2a5f87..98b297c9b 100644 --- a/c/omvsService.c +++ b/c/omvsService.c @@ -54,7 +54,7 @@ int installOMVSService(HttpServer *server) { HttpService *httpService = makeGeneratedService("OMVS_Service", "/omvs/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = &serveOMVSSegment; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; diff --git a/c/securityService.c b/c/securityService.c index dbef33186..8cf0d0906 100644 --- a/c/securityService.c +++ b/c/securityService.c @@ -3356,7 +3356,7 @@ void installSecurityManagementServices(HttpServer *server) { makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); classMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - classMgmtService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + classMgmtService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; classMgmtService->serviceFunction = &serveClassManagement; classMgmtService->runInSubtask = TRUE; classMgmtService->doImpersonation = TRUE; @@ -3371,7 +3371,7 @@ void installSecurityManagementServices(HttpServer *server) { makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); userProfileService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - userProfileService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + userProfileService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; userProfileService->serviceFunction = &serveUserProfile; userProfileService->runInSubtask = TRUE; userProfileService->doImpersonation = TRUE; @@ -3386,7 +3386,7 @@ void installSecurityManagementServices(HttpServer *server) { makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); groupMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - groupMgmtService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + groupMgmtService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; groupMgmtService->serviceFunction = &serveGroupManagement; groupMgmtService->runInSubtask = TRUE; groupMgmtService->doImpersonation = TRUE; @@ -3400,7 +3400,7 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, NULL )); accessService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - accessService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + accessService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; accessService->serviceFunction = &serveAccessInfo; accessService->runInSubtask = TRUE; accessService->doImpersonation = TRUE; diff --git a/c/unixFileService.c b/c/unixFileService.c index e70af6e50..938946406 100644 --- a/c/unixFileService.c +++ b/c/unixFileService.c @@ -1100,7 +1100,7 @@ void installUnixFileContentsService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileContents", "/unixfile/contents/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileContents; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1120,7 +1120,7 @@ void installUnixFileRenameService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileRename", "/unixfile/rename/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileRename; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1131,7 +1131,7 @@ void installUnixFileCopyService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileCopy", "/unixfile/copy/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileCopy; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1142,7 +1142,7 @@ void installUnixFileMakeDirectoryService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileMkdir", "/unixfile/mkdir/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileMakeDirectory; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1153,7 +1153,7 @@ void installUnixFileTouchService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileTouch", "/unixfile/touch/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileTouch; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1164,7 +1164,7 @@ void installUnixFileMetadataService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/metadata/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveUnixFileMetadata; @@ -1175,7 +1175,7 @@ void installUnixFileChangeOwnerService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/chown/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveUnixFileChangeOwner; @@ -1186,7 +1186,7 @@ void installUnixFileChangeTagService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileChtag", "/unixfile/chtag/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileChangeTag; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1197,7 +1197,7 @@ void installUnixFileChangeModeService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileChmod", "/unixfile/chmod/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileChangeMode; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1208,7 +1208,7 @@ void installUnixFileTableOfContentsService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveTableOfContents; diff --git a/c/zss.c b/c/zss.c index 5f340880e..60207abb3 100644 --- a/c/zss.c +++ b/c/zss.c @@ -338,12 +338,7 @@ static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpRes /* Future custom ZSS authorization handlers go here */ static void initializeAuthHandlers(HttpServer *server) { - - /* NATIVE_WITH_SESSION_TOKEN */ - server->authHandler[0] = (HttpAuthHandler*)safeMalloc31(sizeof(HttpAuthHandler),"HttpAuthHandler"); - server->authHandler[0]->type = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - server->authHandler[0]->authFunction = &rbacAuthorization; - + registerHttpAuthorizationHandler(server, SERVICE_AUTHORIZATION_TYPE_DEFAULT, rbacAuthorization); } static void loadWebServerConfig(HttpServer *server, JsonObject *mvdSettings, @@ -699,7 +694,7 @@ static void installLoginService(HttpServer *server) { HttpService *httpService = makeGeneratedService("com.rs.mvd.login", "/login/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - httpService->authFlags = SERVICE_AUTH_FLAG_SKIP_AUTHORIZATION; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveLoginWithSessionToken; httpService->authExtractionFunction = extractAuthorizationFromJson; registerHttpService(server, httpService); diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 305ab94ff..be35a3605 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 305ab94ff6c7e0cc66b3066608b8e5637a81ad0e +Subproject commit be35a3605b13da78edc4e7bc5e1633b3338def95 From 9590ce178d5d8979a4c6affd91901a30e4abc458 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Thu, 1 Jul 2021 17:35:57 +0500 Subject: [PATCH 42/68] Register RBAC handler only if RBAC enabled Signed-off-by: Leonty Chudinov --- c/authService.c | 11 ----------- c/zss.c | 18 +++++++++++++++--- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/c/authService.c b/c/authService.c index 62a834651..ba939d1fa 100644 --- a/c/authService.c +++ b/c/authService.c @@ -208,21 +208,10 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char *entity, int access, JsonObject *envSettings) { int rc = 0; - int rbacParm; - Json *rbacObj = jsonObjectGetPropertyValue(envSettings, "ZWED_dataserviceAuthentication_rbac"); - if (rbacObj == NULL) { // Env variable doesn't exist, so check server config - JsonObject *dataserviceAuth = jsonObjectGetObject(service->server->sharedServiceMem, "dataserviceAuthentication"); - rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); - } else { // Use env variable value - rbacParm = jsonAsBoolean(rbacObj); - } CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); ZISAuthServiceStatus reqStatus = {0}; - if (!rbacParm) { - return rc; // When rbac isn't enabled, we don't try to check the auth query - } rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, diff --git a/c/zss.c b/c/zss.c index 60207abb3..c0fbbb87e 100644 --- a/c/zss.c +++ b/c/zss.c @@ -337,8 +337,20 @@ static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpRes } /* Future custom ZSS authorization handlers go here */ -static void initializeAuthHandlers(HttpServer *server) { - registerHttpAuthorizationHandler(server, SERVICE_AUTHORIZATION_TYPE_DEFAULT, rbacAuthorization); +static void registerAuthorizationHandlers(HttpServer *server, JsonObject *mvdSettings, JsonObject *envSettings) { + int rbacParm = FALSE; + Json *rbacObj = jsonObjectGetPropertyValue(envSettings, "ZWED_dataserviceAuthentication_rbac"); + if (rbacObj == NULL) { + JsonObject *dataserviceAuth = jsonObjectGetObject(mvdSettings, "dataserviceAuthentication"); + if (dataserviceAuth) { + rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); + } + } else { + rbacParm = jsonAsBoolean(rbacObj); + } + if (rbacParm) { + registerHttpAuthorizationHandler(server, SERVICE_AUTHORIZATION_TYPE_DEFAULT, rbacAuthorization); + } } static void loadWebServerConfig(HttpServer *server, JsonObject *mvdSettings, @@ -1614,7 +1626,7 @@ int main(int argc, char **argv){ ApimlStorageSettings *apimlStorageSettings = readApimlStorageSettings(slh, mvdSettings, envSettings, tlsEnv); server->defaultProductURLPrefix = PRODUCT; initializePluginIDHashTable(server); - initializeAuthHandlers(server); + registerAuthorizationHandlers(server, mvdSettings, envSettings); loadWebServerConfig(server, mvdSettings, envSettings, htUsers, htGroups, defaultSeconds); readWebPluginDefinitions(server, slh, pluginsDir, serverConfigFile, apimlStorageSettings); installCertificateService(server); From ac967f250087c824cbdc1659cee98e2f44cc88c3 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Fri, 2 Jul 2021 08:54:26 +0500 Subject: [PATCH 43/68] Refactoring + use rbacAuthorization only when username is on request Signed-off-by: Leonty Chudinov --- c/authService.c | 6 ++---- c/zss.c | 15 +++++++++++---- h/authService.h | 5 ++--- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/c/authService.c b/c/authService.c index ba939d1fa..32f819839 100644 --- a/c/authService.c +++ b/c/authService.c @@ -68,8 +68,6 @@ static int serveAuthCheck(HttpService *service, HttpResponse *response); -int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char* entity, int access, JsonObject *envSettings); - static int makeProfileName( char *profileName, const char *type, @@ -206,7 +204,7 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { return 0; } -int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char *entity, int access, JsonObject *envSettings) { +int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char *entity, int access) { int rc = 0; CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, @@ -219,7 +217,7 @@ int serveAuthCheckByParams(HttpService *service, char *userName, char *class, ch return rc; } -int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response) { +int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID) { char type[STRING_BUFFER_SIZE]; // core || config || service char productCode[STRING_BUFFER_SIZE]; char rootServiceName[STRING_BUFFER_SIZE]; diff --git a/c/zss.c b/c/zss.c index c0fbbb87e..81c2ef053 100644 --- a/c/zss.c +++ b/c/zss.c @@ -320,19 +320,26 @@ static void setPrivilegedServerName(HttpServer *server, JsonObject *mvdSettings, #endif /* __ZOWE_OS_ZOS */ static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpResponse *response) { - int rc = 0; - char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; + if (request->username != NULL) { + // would a check for (service->authType != SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN) be better? + return TRUE; + } + char method[16]; snprintf(method, sizeof(method), "%s", request->method); destructivelyNativize(method); - rc = getProfileNameFromRequest(profileName, request->parsedFile, method, -1, response); + + char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; + int rc = getProfileNameFromRequest(profileName, request->parsedFile, method, -1); if (rc != 0) { return FALSE; } - rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2, ENV_SETTINGS); + + rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2); if (rc != 0) { return FALSE; } + return TRUE; } diff --git a/h/authService.h b/h/authService.h index 55e5f9fb4..ea1820761 100644 --- a/h/authService.h +++ b/h/authService.h @@ -36,11 +36,10 @@ void installZosPasswordService(HttpServer *server); * @param profileName Generated profile name goes here * @param parsedFile Refers to the StringList object which contains URL stripped of args * @param instanceID Refers to instanceID for query. If none specified, or negative, then 0 - * @param HttpResponse Describes the HttpResponse object to return if error encountered * * @return Return non-zero if error */ -int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response); +int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID); /** * @brief The function satisfies RBAC, by first checking if RBAC is enabled, then executing @@ -54,7 +53,7 @@ int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *m * * @return Return code where != 0 is a failed RBAC check */ -int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access, JsonObject *envSettings); +int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access); #endif From 5ade5c92894e3c4993e5cca6ad50becacf0bcf37 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Fri, 2 Jul 2021 09:37:03 +0500 Subject: [PATCH 44/68] Detect ZOWE_INSTANCE Signed-off-by: Leonty Chudinov --- c/zss.c | 37 +++++++++++++++++++++++++++++++------ deps/zowe-common-c | 2 +- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/c/zss.c b/c/zss.c index 81c2ef053..4243baf00 100644 --- a/c/zss.c +++ b/c/zss.c @@ -319,18 +319,25 @@ static void setPrivilegedServerName(HttpServer *server, JsonObject *mvdSettings, } #endif /* __ZOWE_OS_ZOS */ -static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpResponse *response) { +typedef struct RbacAuthorizationData_t { + int instanceId; +} RbacAuthorizationData; + +static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpResponse *response, void *userData) { if (request->username != NULL) { // would a check for (service->authType != SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN) be better? return TRUE; } + RbacAuthorizationData *rbacData = userData; + char method[16]; snprintf(method, sizeof(method), "%s", request->method); destructivelyNativize(method); + char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; - int rc = getProfileNameFromRequest(profileName, request->parsedFile, method, -1); + int rc = getProfileNameFromRequest(profileName, request->parsedFile, method, rbacData->instanceId); if (rc != 0) { return FALSE; } @@ -343,8 +350,7 @@ static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpRes return TRUE; } -/* Future custom ZSS authorization handlers go here */ -static void registerAuthorizationHandlers(HttpServer *server, JsonObject *mvdSettings, JsonObject *envSettings) { +static bool isRbacEnabled(JsonObject *mvdSettings, JsonObject *envSettings) { int rbacParm = FALSE; Json *rbacObj = jsonObjectGetPropertyValue(envSettings, "ZWED_dataserviceAuthentication_rbac"); if (rbacObj == NULL) { @@ -355,8 +361,27 @@ static void registerAuthorizationHandlers(HttpServer *server, JsonObject *mvdSet } else { rbacParm = jsonAsBoolean(rbacObj); } - if (rbacParm) { - registerHttpAuthorizationHandler(server, SERVICE_AUTHORIZATION_TYPE_DEFAULT, rbacAuthorization); + return rbacParm; +} + +static int getZoweInstanceId() { + char *instance = getenv("ZOWE_INSTANCE"); + if (!instance) { + return 0; + } + return atoi(instance); +} + +/* Future custom ZSS authorization handlers go here */ +static void registerAuthorizationHandlers(HttpServer *server, JsonObject *mvdSettings, JsonObject *envSettings) { + bool rbacEnabled = isRbacEnabled(mvdSettings, envSettings); + if (!rbacEnabled) { + return; + } + RbacAuthorizationData *rbacData = (RbacAuthorizationData*) safeMalloc(sizeof(*rbacData), "Rbac Authorization Data"); + if (rbacData) { + rbacData->instanceId = getZoweInstanceId(); + registerHttpAuthorizationHandler(server, SERVICE_AUTHORIZATION_TYPE_DEFAULT, rbacAuthorization, rbacData); } } diff --git a/deps/zowe-common-c b/deps/zowe-common-c index be35a3605..166c71520 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit be35a3605b13da78edc4e7bc5e1633b3338def95 +Subproject commit 166c715201ecce6c4cd2ce2fd6e952f18e728ee2 From ef8b441bcc5f8697082cc3847e53cf7cf3910b37 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Fri, 2 Jul 2021 09:40:14 +0500 Subject: [PATCH 45/68] Fix username check Signed-off-by: Leonty Chudinov --- c/zss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/c/zss.c b/c/zss.c index 4243baf00..803a749b6 100644 --- a/c/zss.c +++ b/c/zss.c @@ -324,7 +324,8 @@ typedef struct RbacAuthorizationData_t { } RbacAuthorizationData; static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpResponse *response, void *userData) { - if (request->username != NULL) { + if (request->username == NULL) { + // username is required to perform RBAC check // would a check for (service->authType != SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN) be better? return TRUE; } From ef78692497d4c3cd23c6251324029b61d4badb96 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Fri, 2 Jul 2021 10:34:28 +0500 Subject: [PATCH 46/68] Rafactor SAF profile check Signed-off-by: Leonty Chudinov --- c/authService.c | 6 ++---- c/zss.c | 4 ++-- h/authService.h | 12 ++++++------ 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/c/authService.c b/c/authService.c index 32f819839..e01f711eb 100644 --- a/c/authService.c +++ b/c/authService.c @@ -35,7 +35,6 @@ #include "httpserver.h" #include "zssLogging.h" -#define SAF_CLASS "ZOWE" #define JSON_ERROR_BUFFER_SIZE 1024 #define STRING_BUFFER_SIZE 1024 #define SAF_SUB_URL_SIZE 16 @@ -204,11 +203,10 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { return 0; } -int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char *entity, int access) { +int verifyAccessToSafProfile(HttpServer *server, char *userName, char *class, char *entity, int access) { int rc = 0; - CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, - HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); + CrossMemoryServerName *privilegedServerName = getConfiguredProperty(server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); ZISAuthServiceStatus reqStatus = {0}; rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); diff --git a/c/zss.c b/c/zss.c index 803a749b6..86768e0ac 100644 --- a/c/zss.c +++ b/c/zss.c @@ -343,8 +343,8 @@ static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpRes return FALSE; } - rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2); - if (rc != 0) { + rc = verifyAccessToSafProfile(service->server, request->username, SAF_CLASS, profileName, SAF_AUTH_ATTR_READ); + if (rc != RC_ZIS_SRVC_OK) { return FALSE; } diff --git a/h/authService.h b/h/authService.h index ea1820761..baaace1f2 100644 --- a/h/authService.h +++ b/h/authService.h @@ -26,6 +26,7 @@ #include "httpserver.h" #include "dataservice.h" +#define SAF_CLASS "ZOWE" #define ZOWE_PROFILE_NAME_LEN 246 int installAuthCheckService(HttpServer *server); @@ -42,18 +43,17 @@ void installZosPasswordService(HttpServer *server); int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID); /** - * @brief The function satisfies RBAC, by first checking if RBAC is enabled, then executing - * a ZIS check. - * @param service The calling HttpService + * @brief The function verifies access to a SAF profile. + * @param server HTTP Server * @param userName Username to use in ZIS check - * @param Class Class to use in ZIS check i.e. "ZOWE" + * @param class Class to use in ZIS check i.e. "ZOWE" * @param entity Describes the SAF query itself i.e. "ZLUX.0.COR.GET.SERVER.AGENT.CONFIG" * @param access Describes the access type i.e. "READ" * @param envSettings JSON object that holds environment variables, if any * - * @return Return code where != 0 is a failed RBAC check + * @return Return code where != 0 if failed */ -int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access); +int verifyAccessToSafProfile(HttpServer *server, char *userName, char *class, char *entity, int access); #endif From 894bc65fee60b286df6f7bbedfbc994e437a55fa Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Fri, 2 Jul 2021 17:05:50 +0500 Subject: [PATCH 47/68] ServerStatusServer has respect ZWED_dataserviceAuthentication_rbac env var Signed-off-by: Leonty Chudinov --- c/serverStatusService.c | 11 ++++++----- c/zss.c | 8 ++++---- h/serverStatusService.h | 3 ++- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/c/serverStatusService.c b/c/serverStatusService.c index 10633237d..45985abab 100644 --- a/c/serverStatusService.c +++ b/c/serverStatusService.c @@ -39,6 +39,7 @@ #include "httpserver.h" #include "logging.h" #include "zssLogging.h" +#include "serviceUtils.h" #include "serverStatusService.h" #ifdef __ZOWE_OS_ZOS @@ -49,7 +50,7 @@ static inline bool strne(const char *a, const char *b) { return a != NULL && b != NULL && strcmp(a, b) != 0; } -void installServerStatusService(HttpServer *server, JsonObject *serverSettings, char* productVer) { +void installServerStatusService(HttpServer *server, JsonObject *serverSettings, bool rbacEnabled, char* productVer) { HttpService *httpService = makeGeneratedService("Server_Status_Service", "/server/agent/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; httpService->authFlags |= SERVICE_AUTH_FLAG_OPTIONAL; @@ -61,6 +62,7 @@ void installServerStatusService(HttpServer *server, JsonObject *serverSettings, context->serverConfig = serverSettings; context->productVersion[sizeof(context->productVersion) - 1] = '\0'; strncpy(context->productVersion, productVer, sizeof(context->productVersion) - 1); + context->rbacEnabled = rbacEnabled; } httpService->userPointer = context; registerHttpService(server, httpService); @@ -243,10 +245,9 @@ static int serveStatus(HttpService *service, HttpResponse *response) { ServerAgentContext *context = service->userPointer; //This service is conditional on RBAC being enabled because it is a //sensitive URL that only RBAC authorized users should be able to get full access - JsonObject *dataserviceAuth = jsonObjectGetObject(context->serverConfig, "dataserviceAuthentication"); - int rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); + bool rbacEnabled = context->rbacEnabled; int isAuthenticated = response->request->authenticated; - bool allowFullAccess = isAuthenticated && rbacParm; + bool allowFullAccess = isAuthenticated && rbacEnabled; if (!strcmp(request->method, methodGET)) { char *l1 = stringListPrint(request->parsedFile, 2, 1, "/", 0); if (!allowFullAccess && statusEndPointRequireAuthAndRBAC(l1)) { @@ -254,7 +255,7 @@ static int serveStatus(HttpService *service, HttpResponse *response) { respondWithError(response, HTTP_STATUS_UNAUTHORIZED, "Not Authorized"); return -1; } - if (!rbacParm) { + if (!rbacEnabled) { respondWithError(response, HTTP_STATUS_BAD_REQUEST, "Set dataserviceAuthentication.rbac to true in server configuration"); return -1; } diff --git a/c/zss.c b/c/zss.c index 86768e0ac..f885f55e5 100644 --- a/c/zss.c +++ b/c/zss.c @@ -374,8 +374,7 @@ static int getZoweInstanceId() { } /* Future custom ZSS authorization handlers go here */ -static void registerAuthorizationHandlers(HttpServer *server, JsonObject *mvdSettings, JsonObject *envSettings) { - bool rbacEnabled = isRbacEnabled(mvdSettings, envSettings); +static void registerAuthorizationHandlers(HttpServer *server, bool rbacEnabled) { if (!rbacEnabled) { return; } @@ -1659,7 +1658,8 @@ int main(int argc, char **argv){ ApimlStorageSettings *apimlStorageSettings = readApimlStorageSettings(slh, mvdSettings, envSettings, tlsEnv); server->defaultProductURLPrefix = PRODUCT; initializePluginIDHashTable(server); - registerAuthorizationHandlers(server, mvdSettings, envSettings); + bool rbacEnabled = isRbacEnabled(mvdSettings, envSettings); + registerAuthorizationHandlers(server, rbacEnabled); loadWebServerConfig(server, mvdSettings, envSettings, htUsers, htGroups, defaultSeconds); readWebPluginDefinitions(server, slh, pluginsDir, serverConfigFile, apimlStorageSettings); installCertificateService(server); @@ -1682,7 +1682,7 @@ int main(int argc, char **argv){ installAuthCheckService(server); installSecurityManagementServices(server); installOMVSService(server); - installServerStatusService(server, MVD_SETTINGS, productVersion); + installServerStatusService(server, MVD_SETTINGS, rbacEnabled, productVer); installZosPasswordService(server); installRASService(server); #endif diff --git a/h/serverStatusService.h b/h/serverStatusService.h index 59649842b..55d95b804 100644 --- a/h/serverStatusService.h +++ b/h/serverStatusService.h @@ -16,9 +16,10 @@ typedef struct ServerAgentContext_tag{ char productVersion[40]; JsonObject *serverConfig; + bool rbacEnabled; } ServerAgentContext; -void installServerStatusService(HttpServer *server, JsonObject* serverSettings, char* productVer); +void installServerStatusService(HttpServer *server, JsonObject* serverSettings, bool rbacEnabled, char* productVer); #endif /* __SERVER_STATUS_H__ */ From f0d839a510c6596dc3f11e824cce4e76046a637b Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Mon, 5 Jul 2021 08:55:36 +0500 Subject: [PATCH 48/68] Minor fixes Signed-off-by: Leonty Chudinov --- c/authService.c | 31 +++++++++++++++---------------- c/zss.c | 3 +-- h/authService.h | 2 +- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/c/authService.c b/c/authService.c index e01f711eb..a8d846d44 100644 --- a/c/authService.c +++ b/c/authService.c @@ -204,15 +204,14 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { } int verifyAccessToSafProfile(HttpServer *server, char *userName, char *class, char *entity, int access) { - int rc = 0; - CrossMemoryServerName *privilegedServerName = getConfiguredProperty(server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); ZISAuthServiceStatus reqStatus = {0}; - rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, - &reqStatus); + + int rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "RBAC check occurred for entity '%s' class '%s' access '%d' , rc: %d", entity, class, access, rc); - return rc; + "verifyAccessToSafProfile entity '%s' class '%s' access '%d' , rc: %d\n", entity, class, access, rc); + + return (rc != RC_ZIS_SRVC_OK) ? -1 : 0; } int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID) { @@ -235,7 +234,7 @@ int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *m } if (strcmp(urlSegment, "PLUGINS") != 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "parsedFile urlSegment check didn't match."); + "parsedFile urlSegment check didn't match.\n"); subUrlIndex = -1; while (pathSegment != NULL) { snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); @@ -294,7 +293,7 @@ int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *m } } zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "parsedFile urlSegment check OK."); + "parsedFile urlSegment check OK.\n"); } return makeProfileName(profileName, type, productCode, @@ -337,43 +336,43 @@ static int makeProfileName( char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { if (instanceID == -1) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing instance ID."); + "Broken SAF query. Missing instance ID.\n"); return -1; } if (method == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing method."); + "Broken SAF query. Missing method.\n"); return -1; } int pos = 0; if (strcmp(type, "service") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing plugin ID."); + "Broken SAF query. Missing plugin ID.\n"); return -1; } if (serviceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing service name."); + "Broken SAF query. Missing service name.\n"); return -1; } pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); } else if (strcmp(type, "config") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing plugin ID."); + "Broken SAF query. Missing plugin ID.\n"); return -1; } if (scope == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing scope."); + "Broken SAF query. Missing scope.\n"); return -1; } pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); } else if (strcmp(type, "core") == 0) { if (rootServiceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing root service name."); + "Broken SAF query. Missing root service name.\n"); return -1; } pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); @@ -394,7 +393,7 @@ static int makeProfileName( return -1; } zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "Finished generating profileName: %s", profileName); + "Finished generating profileName: %s\n", profileName); return 0; } diff --git a/c/zss.c b/c/zss.c index f885f55e5..afc8b74b7 100644 --- a/c/zss.c +++ b/c/zss.c @@ -336,7 +336,6 @@ static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpRes snprintf(method, sizeof(method), "%s", request->method); destructivelyNativize(method); - char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; int rc = getProfileNameFromRequest(profileName, request->parsedFile, method, rbacData->instanceId); if (rc != 0) { @@ -344,7 +343,7 @@ static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpRes } rc = verifyAccessToSafProfile(service->server, request->username, SAF_CLASS, profileName, SAF_AUTH_ATTR_READ); - if (rc != RC_ZIS_SRVC_OK) { + if (rc != 0) { return FALSE; } diff --git a/h/authService.h b/h/authService.h index baaace1f2..2dd894e3f 100644 --- a/h/authService.h +++ b/h/authService.h @@ -51,7 +51,7 @@ int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *m * @param access Describes the access type i.e. "READ" * @param envSettings JSON object that holds environment variables, if any * - * @return Return code where != 0 if failed + * @return Return non-zero if failed */ int verifyAccessToSafProfile(HttpServer *server, char *userName, char *class, char *entity, int access); From 5f4f553535a8d713b57f0985615acf3cf6d7df91 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Mon, 5 Jul 2021 10:47:30 +0500 Subject: [PATCH 49/68] Update pointer to zowe-common-c Signed-off-by: Leonty Chudinov --- deps/zowe-common-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 166c71520..be5f0e544 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 166c715201ecce6c4cd2ce2fd6e952f18e728ee2 +Subproject commit be5f0e544f4f094afc0a022d54bcd174f0d67aef From f9e437dd01a00e28e08ebf8c79fcca8428403081 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Wed, 7 Jul 2021 10:51:50 +0500 Subject: [PATCH 50/68] Add const for getProfileNameFromRequest args Signed-off-by: Leonty Chudinov --- c/authService.c | 4 ++-- h/authService.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/c/authService.c b/c/authService.c index a8d846d44..6afd4eec7 100644 --- a/c/authService.c +++ b/c/authService.c @@ -214,7 +214,7 @@ int verifyAccessToSafProfile(HttpServer *server, char *userName, char *class, ch return (rc != RC_ZIS_SRVC_OK) ? -1 : 0; } -int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID) { +int getProfileNameFromRequest(char *profileName, StringList *parsedFile, const char *method, int instanceID) { char type[STRING_BUFFER_SIZE]; // core || config || service char productCode[STRING_BUFFER_SIZE]; char rootServiceName[STRING_BUFFER_SIZE]; @@ -225,7 +225,7 @@ int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *m char urlSegment[STRING_BUFFER_SIZE]; int subUrlIndex = 0; - snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, 1, 1, "/", 0)); + snprintf(urlSegment, sizeof(urlSegment), "%s", stringListPrint(parsedFile, 1, 1, "/", 0)); StringListElt *pathSegment = firstStringListElt(parsedFile); strupcase(urlSegment); diff --git a/h/authService.h b/h/authService.h index 2dd894e3f..692d29275 100644 --- a/h/authService.h +++ b/h/authService.h @@ -40,7 +40,7 @@ void installZosPasswordService(HttpServer *server); * * @return Return non-zero if error */ -int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID); +int getProfileNameFromRequest(char *profileName, StringList *parsedFile, const char *method, int instanceID); /** * @brief The function verifies access to a SAF profile. From 1a6367461db4dca02031ee8380f9f319b326c5cc Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Wed, 7 Jul 2021 11:14:03 +0500 Subject: [PATCH 51/68] Add profileNameBufSize arg Signed-off-by: Leonty Chudinov --- c/authService.c | 21 ++++++++++++--------- c/zss.c | 2 +- h/authService.h | 3 ++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/c/authService.c b/c/authService.c index 6afd4eec7..c82904939 100644 --- a/c/authService.c +++ b/c/authService.c @@ -69,6 +69,7 @@ static int serveAuthCheck(HttpService *service, HttpResponse *response); static int makeProfileName( char *profileName, + int profileNameBufSize, const char *type, const char *productCode, int instanceID, @@ -214,7 +215,7 @@ int verifyAccessToSafProfile(HttpServer *server, char *userName, char *class, ch return (rc != RC_ZIS_SRVC_OK) ? -1 : 0; } -int getProfileNameFromRequest(char *profileName, StringList *parsedFile, const char *method, int instanceID) { +int getProfileNameFromRequest(char *profileName, int profileNameBufSize, StringList *parsedFile, const char *method, int instanceID) { char type[STRING_BUFFER_SIZE]; // core || config || service char productCode[STRING_BUFFER_SIZE]; char rootServiceName[STRING_BUFFER_SIZE]; @@ -295,7 +296,8 @@ int getProfileNameFromRequest(char *profileName, StringList *parsedFile, const c zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, "parsedFile urlSegment check OK.\n"); } - return makeProfileName(profileName, type, + return makeProfileName(profileName, profileNameBufSize, + type, productCode, instanceID, pluginID, @@ -325,6 +327,7 @@ static void setProfileNameAttribs( static int makeProfileName( char *profileName, + int profileNameBufSize, const char *type, const char *productCode, int instanceID, @@ -356,7 +359,7 @@ static int makeProfileName( "Broken SAF query. Missing service name.\n"); return -1; } - pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); + pos = snprintf(profileName, profileNameBufSize, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); } else if (strcmp(type, "config") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, @@ -368,27 +371,27 @@ static int makeProfileName( "Broken SAF query. Missing scope.\n"); return -1; } - pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); + pos = snprintf(profileName, profileNameBufSize, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); } else if (strcmp(type, "core") == 0) { if (rootServiceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, "Broken SAF query. Missing root service name.\n"); return -1; } - pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + pos = snprintf(profileName, profileNameBufSize, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); } // Child endpoints housed via subUrl int index = 0; while (index < SAF_SUB_URL_SIZE && strcmp(subUrl[index], "") != 0) { - if (pos > ZOWE_PROFILE_NAME_LEN) { + if (pos >= profileNameBufSize) { break; } - pos += snprintf(profileName + pos, ZOWE_PROFILE_NAME_LEN + 1 - pos, ".%s", subUrl[index]); + pos += snprintf(profileName + pos, profileNameBufSize - pos, ".%s", subUrl[index]); index++; } - if (pos > ZOWE_PROFILE_NAME_LEN) { + if (pos >= profileNameBufSize) { char errMsg[256]; - snprintf(errMsg, sizeof(errMsg), "Generated SAF query longer than %d\n", ZOWE_PROFILE_NAME_LEN); + snprintf(errMsg, sizeof(errMsg), "Generated SAF query longer than %d\n", profileNameBufSize - 1); zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, errMsg); return -1; } diff --git a/c/zss.c b/c/zss.c index afc8b74b7..27fcc5f03 100644 --- a/c/zss.c +++ b/c/zss.c @@ -337,7 +337,7 @@ static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpRes destructivelyNativize(method); char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; - int rc = getProfileNameFromRequest(profileName, request->parsedFile, method, rbacData->instanceId); + int rc = getProfileNameFromRequest(profileName, sizeof(profileName), request->parsedFile, method, rbacData->instanceId); if (rc != 0) { return FALSE; } diff --git a/h/authService.h b/h/authService.h index 692d29275..61c05ff2d 100644 --- a/h/authService.h +++ b/h/authService.h @@ -35,12 +35,13 @@ void installZosPasswordService(HttpServer *server); /** * @brief The function uses makeProfileName function to generate profile name for SAF query * @param profileName Generated profile name goes here + * @param profileNameBufSize Size of profileName buffer including terminating '\0' * @param parsedFile Refers to the StringList object which contains URL stripped of args * @param instanceID Refers to instanceID for query. If none specified, or negative, then 0 * * @return Return non-zero if error */ -int getProfileNameFromRequest(char *profileName, StringList *parsedFile, const char *method, int instanceID); +int getProfileNameFromRequest(char *profileName, int profileNameBufSize, StringList *parsedFile, const char *method, int instanceID); /** * @brief The function verifies access to a SAF profile. From 961b7a7ecdc1ad92d1d986b84463c360284ba71c Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Wed, 7 Jul 2021 15:24:45 +0500 Subject: [PATCH 52/68] Add const for arguments Signed-off-by: Leonty Chudinov --- c/authService.c | 4 ++-- h/authService.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/c/authService.c b/c/authService.c index c82904939..27cde4bb2 100644 --- a/c/authService.c +++ b/c/authService.c @@ -204,7 +204,7 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { return 0; } -int verifyAccessToSafProfile(HttpServer *server, char *userName, char *class, char *entity, int access) { +int verifyAccessToSafProfile(HttpServer *server, const char *userName, const char *class, const char *entity, int access) { CrossMemoryServerName *privilegedServerName = getConfiguredProperty(server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); ZISAuthServiceStatus reqStatus = {0}; @@ -310,7 +310,7 @@ int getProfileNameFromRequest(char *profileName, int profileNameBufSize, StringL static void setProfileNameAttribs( char *pluginID, - char *serviceName, + const char *serviceName, char *type, char *scope, char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { diff --git a/h/authService.h b/h/authService.h index 61c05ff2d..5c9b48099 100644 --- a/h/authService.h +++ b/h/authService.h @@ -54,7 +54,7 @@ int getProfileNameFromRequest(char *profileName, int profileNameBufSize, StringL * * @return Return non-zero if failed */ -int verifyAccessToSafProfile(HttpServer *server, char *userName, char *class, char *entity, int access); +int verifyAccessToSafProfile(HttpServer *server, const char *userName, const char *class, const char *entity, int access); #endif From f3b8d91829e019f1f24c36c1cf2f4bb7e6f2df95 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Mon, 23 Aug 2021 19:58:22 -0400 Subject: [PATCH 53/68] Updated with more of Irek's suggested code changes Signed-off-by: Leanid Astrakou --- c/authService.c | 123 +++++++++++++++++++--------------------- c/datasetService.c | 9 ++- c/omvsService.c | 3 +- c/securityService.c | 12 ++-- c/serverStatusService.c | 11 ++-- c/unixFileService.c | 30 ++++++---- c/zss.c | 70 ++++++++++++++++++----- deps/zowe-common-c | 2 +- h/authService.h | 16 +++--- h/serverStatusService.h | 3 +- 10 files changed, 167 insertions(+), 112 deletions(-) diff --git a/c/authService.c b/c/authService.c index 62a834651..dfdea7147 100644 --- a/c/authService.c +++ b/c/authService.c @@ -35,10 +35,9 @@ #include "httpserver.h" #include "zssLogging.h" -#define SAF_CLASS "ZOWE" -#define JSON_ERROR_BUFFER_SIZE 1024 -#define STRING_BUFFER_SIZE 1024 -#define SAF_SUB_URL_SIZE 16 +#define JSON_ERROR_BUFFER_SIZE 1024 +#define STRING_BUFFER_SIZE 1024 +#define SAF_SUB_URL_SIZE 32 #define SAF_PASSWORD_RESET_RC_OK 0 #define SAF_PASSWORD_RESET_RC_WRONG_PASSWORD 111 @@ -47,7 +46,10 @@ #define SAF_PASSWORD_RESET_RC_NO_NEW_PASSSWORD 168 #define SAF_PASSWORD_RESET_RC_WRONG_FORMAT 169 -#define RESPONSE_MESSAGE_LENGTH 100 +#define RESPONSE_MESSAGE_LENGTH 100 + +#define SAF_PLUGIN_ID "ORG.ZOWE.CONFIGJS" +#define SAF_SERVICE_NAME "DATA" /* * A handler performing the SAF_AUTH check: checks if the user has the @@ -68,10 +70,9 @@ static int serveAuthCheck(HttpService *service, HttpResponse *response); -int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char* entity, int access, JsonObject *envSettings); - static int makeProfileName( char *profileName, + int profileNameBufSize, const char *type, const char *productCode, int instanceID, @@ -206,31 +207,18 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { return 0; } -int serveAuthCheckByParams(HttpService *service, char *userName, char *class, char *entity, int access, JsonObject *envSettings) { - int rc = 0; - int rbacParm; - Json *rbacObj = jsonObjectGetPropertyValue(envSettings, "ZWED_dataserviceAuthentication_rbac"); - if (rbacObj == NULL) { // Env variable doesn't exist, so check server config - JsonObject *dataserviceAuth = jsonObjectGetObject(service->server->sharedServiceMem, "dataserviceAuthentication"); - rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); - } else { // Use env variable value - rbacParm = jsonAsBoolean(rbacObj); - } - - CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, - HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); +int verifyAccessToSafProfile(HttpServer *server, const char *userName, const char *class, const char *entity, const int access) { + CrossMemoryServerName *privilegedServerName = getConfiguredProperty(server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); ZISAuthServiceStatus reqStatus = {0}; - if (!rbacParm) { - return rc; // When rbac isn't enabled, we don't try to check the auth query - } - rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, - &reqStatus); + + int rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "RBAC check occurred for entity '%s' class '%s' access '%d' , rc: %d", entity, class, access, rc); - return rc; + "verifyAccessToSafProfile entity '%s' class '%s' access '%d' , rc: %d\n", entity, class, access, rc); + + return (rc != RC_ZIS_SRVC_OK) ? -1 : 0; } -int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response) { +int getProfileNameFromRequest(char *profileName, const int profileNameBufSize, StringList *parsedFile, const char *method, int instanceID) { char type[STRING_BUFFER_SIZE]; // core || config || service char productCode[STRING_BUFFER_SIZE]; char rootServiceName[STRING_BUFFER_SIZE]; @@ -241,7 +229,7 @@ int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *m char urlSegment[STRING_BUFFER_SIZE]; int subUrlIndex = 0; - snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", stringListPrint(parsedFile, 1, 1, "/", 0)); + snprintf(urlSegment, sizeof(urlSegment), "%s", stringListPrint(parsedFile, 1, 1, "/", 0)); StringListElt *pathSegment = firstStringListElt(parsedFile); strupcase(urlSegment); @@ -250,50 +238,50 @@ int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *m } if (strcmp(urlSegment, "PLUGINS") != 0) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "parsedFile urlSegment check didn't match."); + "parsedFile urlSegment check didn't match.\n"); subUrlIndex = -1; while (pathSegment != NULL) { - snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); + snprintf(urlSegment, sizeof(urlSegment), "%s", pathSegment->string); strupcase(urlSegment); if (rootServiceName == NULL) { - snprintf(rootServiceName, STRING_BUFFER_SIZE, urlSegment); - } else { + snprintf(rootServiceName, sizeof(rootServiceName), urlSegment); + } else { //If URL subsections > SAF_SUB_URL_SIZE, we trim them from profile name (by not appending them) if (subUrlIndex < SAF_SUB_URL_SIZE) { - snprintf(subUrl[subUrlIndex], STRING_BUFFER_SIZE, urlSegment); + snprintf(subUrl[subUrlIndex], sizeof(subUrl), urlSegment); } } subUrlIndex++; pathSegment = pathSegment->next; } - snprintf(productCode, STRING_BUFFER_SIZE, "ZLUX"); - snprintf(type, STRING_BUFFER_SIZE, "core"); + snprintf(productCode, sizeof(productCode), "ZLUX"); + snprintf(type, sizeof(type), "core"); } else { subUrlIndex = 0; while (pathSegment != NULL) { - snprintf(urlSegment, STRING_BUFFER_SIZE, "%s", pathSegment->string); + snprintf(urlSegment, sizeof(urlSegment), "%s", pathSegment->string); strupcase(urlSegment); switch(subUrlIndex) { case 0: - snprintf(productCode, STRING_BUFFER_SIZE, urlSegment); + snprintf(productCode, sizeof(productCode), urlSegment); break; case 1: break; case 2: - snprintf(pluginID, STRING_BUFFER_SIZE, urlSegment); + snprintf(pluginID, sizeof(pluginID), urlSegment); break; case 3: break; case 4: - snprintf(serviceName, STRING_BUFFER_SIZE, urlSegment); + snprintf(serviceName, sizeof(serviceName), urlSegment); break; case 5: break; default: { int adjustedSubUrlIndex = subUrlIndex - 6; // subtract 6 from maximum index to begin init subUrl array at 0 if (adjustedSubUrlIndex < SAF_SUB_URL_SIZE) { - snprintf(subUrl[adjustedSubUrlIndex], STRING_BUFFER_SIZE, urlSegment); + snprintf(subUrl[adjustedSubUrlIndex], sizeof(subUrl), urlSegment); } } } @@ -309,9 +297,10 @@ int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *m } } zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "parsedFile urlSegment check OK."); + "parsedFile urlSegment check OK.\n"); } - return makeProfileName(profileName, type, + return makeProfileName(profileName, profileNameBufSize, + type, productCode, instanceID, pluginID, @@ -324,23 +313,24 @@ int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *m static void setProfileNameAttribs( char *pluginID, - char *serviceName, + const char *serviceName, char *type, char *scope, char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { - if ((strcmp(pluginID, "ORG.ZOWE.CONFIGJS") == 0) && (strcmp(serviceName, "DATA") == 0)) + if ((strcmp(pluginID, SAF_PLUGIN_ID) == 0) && (strcmp(serviceName, SAF_SERVICE_NAME) == 0)) { - snprintf(type, STRING_BUFFER_SIZE, "config"); - snprintf(pluginID, STRING_BUFFER_SIZE, subUrl[0]); - snprintf(scope, STRING_BUFFER_SIZE, subUrl[1]); + snprintf(type, sizeof(type), "config"); + snprintf(pluginID, sizeof(pluginID), subUrl[0]); + snprintf(scope, sizeof(scope), subUrl[1]); } else { - snprintf(type, STRING_BUFFER_SIZE, "service"); + snprintf(type, sizeof(type), "service"); } } static int makeProfileName( char *profileName, + const int profileNameBufSize, const char *type, const char *productCode, int instanceID, @@ -352,64 +342,69 @@ static int makeProfileName( char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { if (instanceID == -1) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing instance ID."); + "Broken SAF query. Missing instance ID.\n"); return -1; } if (method == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing method."); + "Broken SAF query. Missing method.\n"); return -1; } int pos = 0; if (strcmp(type, "service") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing plugin ID."); + "Broken SAF query. Missing plugin ID.\n"); return -1; } if (serviceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing service name."); + "Broken SAF query. Missing service name.\n"); return -1; } - pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); + pos = snprintf(profileName, profileNameBufSize, "%s.%d.SVC.%s.%s.%s", productCode, instanceID, pluginID, serviceName, method); } else if (strcmp(type, "config") == 0) { if (pluginID == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing plugin ID."); + "Broken SAF query. Missing plugin ID.\n"); return -1; } if (scope == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing scope."); + "Broken SAF query. Missing scope.\n"); return -1; } - pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); + pos = snprintf(profileName, profileNameBufSize, "%s.%d.CFG.%s.%s.%s", productCode, instanceID, pluginID, method, scope); } else if (strcmp(type, "core") == 0) { if (rootServiceName == NULL) { zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, - "Broken SAF query. Missing root service name."); + "Broken SAF query. Missing root service name.\n"); return -1; } - pos = snprintf(profileName, ZOWE_PROFILE_NAME_LEN + 1, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + pos = snprintf(profileName, profileNameBufSize, "%s.%d.COR.%s.%s", productCode, instanceID, method, rootServiceName); + } else if (pos < 0) { + zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, + "Internal string encoding error.\n"); + return -1; } // Child endpoints housed via subUrl int index = 0; while (index < SAF_SUB_URL_SIZE && strcmp(subUrl[index], "") != 0) { - if (pos > ZOWE_PROFILE_NAME_LEN) { + if (pos >= profileNameBufSize) { break; } - pos += snprintf(profileName + pos, ZOWE_PROFILE_NAME_LEN + 1 - pos, ".%s", subUrl[index]); + pos += snprintf(profileName + pos, profileNameBufSize - pos, ".%s", subUrl[index]); index++; } - if (pos > ZOWE_PROFILE_NAME_LEN) { + if (pos >= profileNameBufSize) { char errMsg[256]; - snprintf(errMsg, sizeof(errMsg), "Generated SAF query longer than %d\n", ZOWE_PROFILE_NAME_LEN); + snprintf(errMsg, sizeof(errMsg), "Generated SAF query longer than %d\n", profileNameBufSize - 1); zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_WARNING, errMsg); return -1; } zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, - "Finished generating profileName: %s", profileName); + "Finished generating profileName: %s\n", profileName); + printf("\n\n\n\n GENERATED NAME: %s \n\n\n\n", profileName); return 0; } diff --git a/c/datasetService.c b/c/datasetService.c index e99c65d6d..5b27995c4 100644 --- a/c/datasetService.c +++ b/c/datasetService.c @@ -187,7 +187,8 @@ void installDatasetContentsService(HttpServer *server) { zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); HttpService *httpService = makeGeneratedService("datasetContents", "/datasetContents/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveDatasetContents; @@ -199,7 +200,8 @@ void installVSAMDatasetContentsService(HttpServer *server) { zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); HttpService *httpService = makeGeneratedService("VSAMdatasetContents", "/VSAMdatasetContents/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveVSAMDatasetContents; @@ -217,7 +219,8 @@ void installDatasetMetadataService(HttpServer *server) { HttpService *httpService = makeGeneratedService("datasetMetadata", "/datasetMetadata/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveDatasetMetadata; diff --git a/c/omvsService.c b/c/omvsService.c index adc8aee5d..348d58238 100644 --- a/c/omvsService.c +++ b/c/omvsService.c @@ -53,7 +53,8 @@ static int issueRACFCommand(char *command, OMVSSegment *omvs); int installOMVSService(HttpServer *server) { HttpService *httpService = makeGeneratedService("OMVS_Service", "/omvs/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = &serveOMVSSegment; httpService->runInSubtask = FALSE; httpService->doImpersonation = FALSE; diff --git a/c/securityService.c b/c/securityService.c index fa9cea571..8cf0d0906 100644 --- a/c/securityService.c +++ b/c/securityService.c @@ -3355,7 +3355,8 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); - classMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + classMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + classMgmtService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; classMgmtService->serviceFunction = &serveClassManagement; classMgmtService->runInSubtask = TRUE; classMgmtService->doImpersonation = TRUE; @@ -3369,7 +3370,8 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); - userProfileService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + userProfileService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + userProfileService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; userProfileService->serviceFunction = &serveUserProfile; userProfileService->runInSubtask = TRUE; userProfileService->doImpersonation = TRUE; @@ -3383,7 +3385,8 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeStringParamSpec("dryRun", SERVICE_ARG_OPTIONAL, NULL ))); - groupMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + groupMgmtService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + groupMgmtService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; groupMgmtService->serviceFunction = &serveGroupManagement; groupMgmtService->runInSubtask = TRUE; groupMgmtService->doImpersonation = TRUE; @@ -3396,7 +3399,8 @@ void installSecurityManagementServices(HttpServer *server) { makeIntParamSpec("count", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, makeIntParamSpec("traceLevel", SERVICE_ARG_OPTIONAL, 0, 0, 0, 0, NULL )); - accessService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + accessService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + accessService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; accessService->serviceFunction = &serveAccessInfo; accessService->runInSubtask = TRUE; accessService->doImpersonation = TRUE; diff --git a/c/serverStatusService.c b/c/serverStatusService.c index 10633237d..45985abab 100644 --- a/c/serverStatusService.c +++ b/c/serverStatusService.c @@ -39,6 +39,7 @@ #include "httpserver.h" #include "logging.h" #include "zssLogging.h" +#include "serviceUtils.h" #include "serverStatusService.h" #ifdef __ZOWE_OS_ZOS @@ -49,7 +50,7 @@ static inline bool strne(const char *a, const char *b) { return a != NULL && b != NULL && strcmp(a, b) != 0; } -void installServerStatusService(HttpServer *server, JsonObject *serverSettings, char* productVer) { +void installServerStatusService(HttpServer *server, JsonObject *serverSettings, bool rbacEnabled, char* productVer) { HttpService *httpService = makeGeneratedService("Server_Status_Service", "/server/agent/**"); httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; httpService->authFlags |= SERVICE_AUTH_FLAG_OPTIONAL; @@ -61,6 +62,7 @@ void installServerStatusService(HttpServer *server, JsonObject *serverSettings, context->serverConfig = serverSettings; context->productVersion[sizeof(context->productVersion) - 1] = '\0'; strncpy(context->productVersion, productVer, sizeof(context->productVersion) - 1); + context->rbacEnabled = rbacEnabled; } httpService->userPointer = context; registerHttpService(server, httpService); @@ -243,10 +245,9 @@ static int serveStatus(HttpService *service, HttpResponse *response) { ServerAgentContext *context = service->userPointer; //This service is conditional on RBAC being enabled because it is a //sensitive URL that only RBAC authorized users should be able to get full access - JsonObject *dataserviceAuth = jsonObjectGetObject(context->serverConfig, "dataserviceAuthentication"); - int rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); + bool rbacEnabled = context->rbacEnabled; int isAuthenticated = response->request->authenticated; - bool allowFullAccess = isAuthenticated && rbacParm; + bool allowFullAccess = isAuthenticated && rbacEnabled; if (!strcmp(request->method, methodGET)) { char *l1 = stringListPrint(request->parsedFile, 2, 1, "/", 0); if (!allowFullAccess && statusEndPointRequireAuthAndRBAC(l1)) { @@ -254,7 +255,7 @@ static int serveStatus(HttpService *service, HttpResponse *response) { respondWithError(response, HTTP_STATUS_UNAUTHORIZED, "Not Authorized"); return -1; } - if (!rbacParm) { + if (!rbacEnabled) { respondWithError(response, HTTP_STATUS_BAD_REQUEST, "Set dataserviceAuthentication.rbac to true in server configuration"); return -1; } diff --git a/c/unixFileService.c b/c/unixFileService.c index cd4ae6248..938946406 100644 --- a/c/unixFileService.c +++ b/c/unixFileService.c @@ -1099,7 +1099,8 @@ static int serveTableOfContents(HttpService *service, HttpResponse *response) { void installUnixFileContentsService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileContents", "/unixfile/contents/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileContents; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1118,7 +1119,8 @@ void installUnixFileContentsService(HttpServer *server) { void installUnixFileRenameService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileRename", "/unixfile/rename/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileRename; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1128,7 +1130,8 @@ void installUnixFileRenameService(HttpServer *server) { void installUnixFileCopyService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileCopy", "/unixfile/copy/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileCopy; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1138,7 +1141,8 @@ void installUnixFileCopyService(HttpServer *server) { void installUnixFileMakeDirectoryService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileMkdir", "/unixfile/mkdir/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileMakeDirectory; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1148,7 +1152,8 @@ void installUnixFileMakeDirectoryService(HttpServer *server) { void installUnixFileTouchService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileTouch", "/unixfile/touch/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileTouch; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1158,7 +1163,8 @@ void installUnixFileTouchService(HttpServer *server) { void installUnixFileMetadataService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/metadata/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveUnixFileMetadata; @@ -1168,7 +1174,8 @@ void installUnixFileMetadataService(HttpServer *server) { void installUnixFileChangeOwnerService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/chown/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveUnixFileChangeOwner; @@ -1178,7 +1185,8 @@ void installUnixFileChangeOwnerService(HttpServer *server) { void installUnixFileChangeTagService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileChtag", "/unixfile/chtag/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileChangeTag; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1188,7 +1196,8 @@ void installUnixFileChangeTagService(HttpServer *server) { void installUnixFileChangeModeService(HttpServer *server) { HttpService *httpService = makeGeneratedService("UnixFileChmod", "/unixfile/chmod/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveUnixFileChangeMode; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; @@ -1198,7 +1207,8 @@ void installUnixFileChangeModeService(HttpServer *server) { void installUnixFileTableOfContentsService(HttpServer *server) { HttpService *httpService = makeGeneratedService("unixFileMetadata", "/unixfile/"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->runInSubtask = TRUE; httpService->doImpersonation = TRUE; httpService->serviceFunction = serveTableOfContents; diff --git a/c/zss.c b/c/zss.c index d475deebb..27fcc5f03 100644 --- a/c/zss.c +++ b/c/zss.c @@ -319,31 +319,69 @@ static void setPrivilegedServerName(HttpServer *server, JsonObject *mvdSettings, } #endif /* __ZOWE_OS_ZOS */ -static int nativeWithSessionTokenAuth(HttpService *service, HttpRequest *request, HttpResponse *response) { - int rc = 0; - char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; +typedef struct RbacAuthorizationData_t { + int instanceId; +} RbacAuthorizationData; + +static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpResponse *response, void *userData) { + if (request->username == NULL) { + // username is required to perform RBAC check + // would a check for (service->authType != SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN) be better? + return TRUE; + } + + RbacAuthorizationData *rbacData = userData; + char method[16]; snprintf(method, sizeof(method), "%s", request->method); destructivelyNativize(method); - rc = getProfileNameFromRequest(profileName, request->parsedFile, method, -1, response); + + char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; + int rc = getProfileNameFromRequest(profileName, sizeof(profileName), request->parsedFile, method, rbacData->instanceId); if (rc != 0) { return FALSE; } - rc = serveAuthCheckByParams(service, request->username, "ZOWE", profileName, 2, ENV_SETTINGS); + + rc = verifyAccessToSafProfile(service->server, request->username, SAF_CLASS, profileName, SAF_AUTH_ATTR_READ); if (rc != 0) { return FALSE; } + return TRUE; } -/* Future custom ZSS authorization handlers go here */ -static void initializeAuthHandlers(HttpServer *server) { - - /* NATIVE_WITH_SESSION_TOKEN */ - server->authHandler[0] = (HttpAuthHandler*)safeMalloc31(sizeof(HttpAuthHandler),"HttpAuthHandler"); - server->authHandler[0]->type = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; - server->authHandler[0]->authFunction = &nativeWithSessionTokenAuth; +static bool isRbacEnabled(JsonObject *mvdSettings, JsonObject *envSettings) { + int rbacParm = FALSE; + Json *rbacObj = jsonObjectGetPropertyValue(envSettings, "ZWED_dataserviceAuthentication_rbac"); + if (rbacObj == NULL) { + JsonObject *dataserviceAuth = jsonObjectGetObject(mvdSettings, "dataserviceAuthentication"); + if (dataserviceAuth) { + rbacParm = jsonObjectGetBoolean(dataserviceAuth, "rbac"); + } + } else { + rbacParm = jsonAsBoolean(rbacObj); + } + return rbacParm; +} + +static int getZoweInstanceId() { + char *instance = getenv("ZOWE_INSTANCE"); + if (!instance) { + return 0; + } + return atoi(instance); +} +/* Future custom ZSS authorization handlers go here */ +static void registerAuthorizationHandlers(HttpServer *server, bool rbacEnabled) { + if (!rbacEnabled) { + return; + } + RbacAuthorizationData *rbacData = (RbacAuthorizationData*) safeMalloc(sizeof(*rbacData), "Rbac Authorization Data"); + if (rbacData) { + rbacData->instanceId = getZoweInstanceId(); + registerHttpAuthorizationHandler(server, SERVICE_AUTHORIZATION_TYPE_DEFAULT, rbacAuthorization, rbacData); + } } static void loadWebServerConfig(HttpServer *server, JsonObject *mvdSettings, @@ -698,7 +736,8 @@ static void installLoginService(HttpServer *server) { zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "begin %s\n", __FUNCTION__); HttpService *httpService = makeGeneratedService("com.rs.mvd.login", "/login/**"); - httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN_NO_RBAC; + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; httpService->serviceFunction = serveLoginWithSessionToken; httpService->authExtractionFunction = extractAuthorizationFromJson; registerHttpService(server, httpService); @@ -1618,7 +1657,8 @@ int main(int argc, char **argv){ ApimlStorageSettings *apimlStorageSettings = readApimlStorageSettings(slh, mvdSettings, envSettings, tlsEnv); server->defaultProductURLPrefix = PRODUCT; initializePluginIDHashTable(server); - initializeAuthHandlers(server); + bool rbacEnabled = isRbacEnabled(mvdSettings, envSettings); + registerAuthorizationHandlers(server, rbacEnabled); loadWebServerConfig(server, mvdSettings, envSettings, htUsers, htGroups, defaultSeconds); readWebPluginDefinitions(server, slh, pluginsDir, serverConfigFile, apimlStorageSettings); installCertificateService(server); @@ -1641,7 +1681,7 @@ int main(int argc, char **argv){ installAuthCheckService(server); installSecurityManagementServices(server); installOMVSService(server); - installServerStatusService(server, MVD_SETTINGS, productVersion); + installServerStatusService(server, MVD_SETTINGS, rbacEnabled, productVer); installZosPasswordService(server); installRASService(server); #endif diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 59fc275c1..16b4ef9da 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 59fc275c18fc6f040b4380474ac9a3465af56842 +Subproject commit 16b4ef9da74d61bc3977277782c07952ac0fb32b diff --git a/h/authService.h b/h/authService.h index 55e5f9fb4..5c9b48099 100644 --- a/h/authService.h +++ b/h/authService.h @@ -26,6 +26,7 @@ #include "httpserver.h" #include "dataservice.h" +#define SAF_CLASS "ZOWE" #define ZOWE_PROFILE_NAME_LEN 246 int installAuthCheckService(HttpServer *server); @@ -34,27 +35,26 @@ void installZosPasswordService(HttpServer *server); /** * @brief The function uses makeProfileName function to generate profile name for SAF query * @param profileName Generated profile name goes here + * @param profileNameBufSize Size of profileName buffer including terminating '\0' * @param parsedFile Refers to the StringList object which contains URL stripped of args * @param instanceID Refers to instanceID for query. If none specified, or negative, then 0 - * @param HttpResponse Describes the HttpResponse object to return if error encountered * * @return Return non-zero if error */ -int getProfileNameFromRequest(char *profileName, StringList *parsedFile, char *method, int instanceID, HttpResponse *response); +int getProfileNameFromRequest(char *profileName, int profileNameBufSize, StringList *parsedFile, const char *method, int instanceID); /** - * @brief The function satisfies RBAC, by first checking if RBAC is enabled, then executing - * a ZIS check. - * @param service The calling HttpService + * @brief The function verifies access to a SAF profile. + * @param server HTTP Server * @param userName Username to use in ZIS check - * @param Class Class to use in ZIS check i.e. "ZOWE" + * @param class Class to use in ZIS check i.e. "ZOWE" * @param entity Describes the SAF query itself i.e. "ZLUX.0.COR.GET.SERVER.AGENT.CONFIG" * @param access Describes the access type i.e. "READ" * @param envSettings JSON object that holds environment variables, if any * - * @return Return code where != 0 is a failed RBAC check + * @return Return non-zero if failed */ -int serveAuthCheckByParams(HttpService *service, char *userName, char *Class, char *entity, int access, JsonObject *envSettings); +int verifyAccessToSafProfile(HttpServer *server, const char *userName, const char *class, const char *entity, int access); #endif diff --git a/h/serverStatusService.h b/h/serverStatusService.h index 59649842b..55d95b804 100644 --- a/h/serverStatusService.h +++ b/h/serverStatusService.h @@ -16,9 +16,10 @@ typedef struct ServerAgentContext_tag{ char productVersion[40]; JsonObject *serverConfig; + bool rbacEnabled; } ServerAgentContext; -void installServerStatusService(HttpServer *server, JsonObject* serverSettings, char* productVer); +void installServerStatusService(HttpServer *server, JsonObject* serverSettings, bool rbacEnabled, char* productVer); #endif /* __SERVER_STATUS_H__ */ From e2ed56ed79bff4012f8d86ef0982d539371f7430 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Thu, 26 Aug 2021 10:39:47 -0400 Subject: [PATCH 54/68] Removed 'class' as an arg Signed-off-by: Leanid Astrakou --- c/authService.c | 3 ++- c/zss.c | 2 +- h/authService.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/c/authService.c b/c/authService.c index 57cf7f007..5e25e83ec 100644 --- a/c/authService.c +++ b/c/authService.c @@ -207,9 +207,10 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { return 0; } -int verifyAccessToSafProfile(HttpServer *server, const char *userName, const char *class, const char *entity, const int access) { +int verifyAccessToSafProfile(HttpServer *server, const char *userName, const char *entity, const int access) { CrossMemoryServerName *privilegedServerName = getConfiguredProperty(server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); ZISAuthServiceStatus reqStatus = {0}; + const char *class = SAF_CLASS; int rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, diff --git a/c/zss.c b/c/zss.c index 27fcc5f03..2e4f03b41 100644 --- a/c/zss.c +++ b/c/zss.c @@ -342,7 +342,7 @@ static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpRes return FALSE; } - rc = verifyAccessToSafProfile(service->server, request->username, SAF_CLASS, profileName, SAF_AUTH_ATTR_READ); + rc = verifyAccessToSafProfile(service->server, request->username, profileName, SAF_AUTH_ATTR_READ); if (rc != 0) { return FALSE; } diff --git a/h/authService.h b/h/authService.h index 5c9b48099..3e9d5f0cf 100644 --- a/h/authService.h +++ b/h/authService.h @@ -54,7 +54,7 @@ int getProfileNameFromRequest(char *profileName, int profileNameBufSize, StringL * * @return Return non-zero if failed */ -int verifyAccessToSafProfile(HttpServer *server, const char *userName, const char *class, const char *entity, int access); +int verifyAccessToSafProfile(HttpServer *server, const char *userName, const char *entity, int access); #endif From 4fc145c394b217ac1cd19e494763740973780982 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Fri, 6 Aug 2021 17:12:25 +0500 Subject: [PATCH 55/68] PassTicket REST API skeleton Signed-off-by: Leonty Chudinov --- c/passTicketService.c | 173 ++++++++++++++++++++++++++++++++++++++++++ c/zss.c | 2 + h/passTicketService.h | 43 +++++++++++ 3 files changed, 218 insertions(+) create mode 100644 c/passTicketService.c create mode 100644 h/passTicketService.h diff --git a/c/passTicketService.c b/c/passTicketService.c new file mode 100644 index 000000000..2ab7c2c07 --- /dev/null +++ b/c/passTicketService.c @@ -0,0 +1,173 @@ +/* + This program and the accompanying materials are + made available under the terms of the Eclipse Public License v2.0 which accompanies + this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html + + SPDX-License-Identifier: EPL-2.0 + + Copyright Contributors to the Zowe Project. +*/ + +#include +#include +#include +#include +#include + +#include "zowetypes.h" +#include "alloc.h" +#include "utils.h" +#include "charsets.h" +#include "bpxnet.h" +#include "socketmgmt.h" +#include "httpserver.h" +#include "json.h" + +#include "passTicketService.h" +#include "serviceUtils.h" + +#define TICKET_LEN 8 +#define APPLICATION_NAME_KEY "applicationName" +#define APPLICATION_NAME_LEN 8 + +static int servePassTicket(HttpService *service, HttpResponse *response); +static void respondWithPassTicket(HttpResponse *response, const char *applicationName, const char *ticket); +static int generatePassTicket(const char *applicationName, const char *userId, char *ticketBuf, size_t ticketBufSize, char *errorBuf, size_t errorBufSize); +static void respondWithPassTicketError(HttpResponse *response, int code, const char *status, const char *fmt, ...); + +int installPassTicketService(HttpServer *server) { + HttpService *httpService = makeGeneratedService("PassTicket_Service", "/passticket"); + httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; + httpService->serviceFunction = &servePassTicket; + httpService->runInSubtask = FALSE; + httpService->doImpersonation = FALSE; + registerHttpService(server, httpService); + + return 0; +} + +static int servePassTicket(HttpService *service, HttpResponse *response) { + HttpRequest *request = response->request; + char applicationName[APPLICATION_NAME_LEN + 1] = {0}; + char ticket[TICKET_LEN + 1] = {0}; + char errorBuf[1024] = {0}; + + if (0 != strcmp(request->method, methodPOST)) { + respondWithPassTicketError(response, HTTP_STATUS_METHOD_NOT_FOUND, "Method Not Allowed", "Only POST method allowed"); + return 0; + } + + if (0 != extractApplicationName(request, applicationName, sizeof(applicationName), errorBuf, sizeof(errorBuf))) { + respondWithPassTicketError(response, HTTP_STATUS_BAD_REQUEST, "Bad Request", "Failed to get %s - %s", APPLICATION_NAME_KEY, errorBuf); + return 0; + } + + if (0 != generatePassTicket(applicationName, request->username, ticket, sizeof(ticket), errorBuf, sizeof(errorBuf))) { + respondWithPassTicketError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Internal Server Error", "Failed to generate PassTicket - %s", errorBuf); + return 0; + } + + respondWithPassTicket(response, applicationName, ticket); + return 0; +} + +static void respondWithPassTicket(HttpResponse *response, const char *applicationName, const char *ticket) { + HttpRequest *request = response->request; + jsonPrinter *p = respondWithJsonPrinter(response); + setResponseStatus(response, 200, "OK"); + setDefaultJSONRESTHeaders(response); + writeHeader(response); + jsonStart(p); + jsonAddString(p, "userId", request->username); + jsonAddString(p, APPLICATION_NAME_KEY, (char*)applicationName); + jsonAddString(p, "ticket", (char*)ticket); + jsonEnd(p); + finishResponse(response); +} + +static int generatePassTicket(const char *applicationName, const char *userId, char *ticketBuf, size_t ticketBufSize, char *errorBuf, size_t errorBufSize) { + snprintf (ticketBuf, ticketBufSize, "%s", "LZTKEEDQ"); + return 0; +} + +static void respondWithPassTicketError(HttpResponse *response, int code, const char *status, const char *fmt, ...) { + HttpRequest *request = response->request; + jsonPrinter *p = respondWithJsonPrinter(response); + char buffer[4096]; + + setResponseStatus(response, code, (char*)status); + setDefaultJSONRESTHeaders(response); + writeHeader(response); + + va_list args; + va_start (args, fmt); + vsnprintf (buffer, sizeof(buffer), fmt, args); + va_end (args); + + jsonStart(p); + jsonAddString(p, "error", buffer); + jsonEnd(p); + finishResponse(response); +} + +static int extractApplicationName(HttpRequest *request, char *applicationNameBuf, size_t applicationNameBufSize, char *errorBuf, size_t errorBufSize) { + char *body = request->contentBody; + int len = body ? strlen(body) : 0; + if (len == 0) { + snprintf (errorBuf, errorBufSize, "POST body is empty"); + return -1; + } + + char *nativeBody = copyStringToNative(request->slh, body, strlen(body)); + len = nativeBody ? strlen(nativeBody) : 0; + if (len == 0) { + snprintf (errorBuf, errorBufSize, "Failed to convert POST body to EBCDIC"); + return -1; + } + + char errBuf[512]; + Json *jsonBody = jsonParseUnterminatedString(request->slh, nativeBody, len, errBuf, sizeof(errBuf)); + if (!jsonBody) { + snprintf (errorBuf, errorBufSize, "Failed to parse POST body JSON - %s", errBuf); + return -1; + } + + JsonObject *jsonBodyObject = jsonAsObject(jsonBody); + if (!jsonBodyObject) { + snprintf (errorBuf, errorBufSize, "POST body is not a JSON object"); + return -1; + } + + char *appName = jsonObjectGetString(jsonBodyObject, APPLICATION_NAME_KEY); + if (!appName) { + snprintf (errorBuf, errorBufSize, "%s key not found in JSON POST body", APPLICATION_NAME_KEY); + return -1; + } + + size_t appNameLen = strlen(appName); + + if (appNameLen > APPLICATION_NAME_LEN) { + snprintf (errorBuf, errorBufSize, "%s is too long", APPLICATION_NAME_KEY); + return -1; + } + + if (appNameLen == 0) { + snprintf (errorBuf, errorBufSize, "%s is empty", APPLICATION_NAME_KEY); + return -1; + } + + snprintf (applicationNameBuf, applicationNameBufSize, "%s", appName); + + return 0; +} + + +/* + This program and the accompanying materials are + made available under the terms of the Eclipse Public License v2.0 which accompanies + this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html + + SPDX-License-Identifier: EPL-2.0 + + Copyright Contributors to the Zowe Project. +*/ \ No newline at end of file diff --git a/c/zss.c b/c/zss.c index 2c043bfd0..0ffcb88ff 100644 --- a/c/zss.c +++ b/c/zss.c @@ -80,6 +80,7 @@ #endif // USE_ZOWE_TLS #include "storage.h" #include "storageApiml.h" +#include "passTicketService.h" #define PRODUCT "ZLUX" #ifndef PRODUCT_MAJOR_VERSION @@ -1613,6 +1614,7 @@ int main(int argc, char **argv){ installServerStatusService(server, MVD_SETTINGS, productVersion); installZosPasswordService(server); installRASService(server); + installPassTicketService(server); #endif installLoginService(server); installLogoutService(server); diff --git a/h/passTicketService.h b/h/passTicketService.h new file mode 100644 index 000000000..502070289 --- /dev/null +++ b/h/passTicketService.h @@ -0,0 +1,43 @@ + + +/* + This program and the accompanying materials are + made available under the terms of the Eclipse Public License v2.0 which accompanies + this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html + + SPDX-License-Identifier: EPL-2.0 + + Copyright Contributors to the Zowe Project. +*/ + +#ifndef __PASS_TICKET_SERVICE_H__ +#define __PASS_TICKET_SERVICE_H__ + +#include "zowetypes.h" +#include "alloc.h" +#include "utils.h" +#ifdef __ZOWE_OS_ZOS +#include "zos.h" +#endif +#include "logging.h" +#include "json.h" +#include "bpxnet.h" +#include "socketmgmt.h" +#include "httpserver.h" +#include "dataservice.h" + +int installPassTicketService(HttpServer *server); + +#endif // __PASS_TICKET_SERVICE_H__ + + +/* + This program and the accompanying materials are + made available under the terms of the Eclipse Public License v2.0 which accompanies + this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html + + SPDX-License-Identifier: EPL-2.0 + + Copyright Contributors to the Zowe Project. +*/ + From 542f458b1200fab95b4faf82af0f2e785ff4c478 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Mon, 9 Aug 2021 16:55:22 +0500 Subject: [PATCH 56/68] Implement PassTicket generation Signed-off-by: Leonty Chudinov --- c/passTicketService.c | 123 ++++++++++++++++++++++++++++++++++++------ h/zssLogging.h | 7 +++ 2 files changed, 114 insertions(+), 16 deletions(-) diff --git a/c/passTicketService.c b/c/passTicketService.c index 2ab7c2c07..5fd11272b 100644 --- a/c/passTicketService.c +++ b/c/passTicketService.c @@ -13,16 +13,15 @@ #include #include #include +#include #include "zowetypes.h" #include "alloc.h" #include "utils.h" #include "charsets.h" -#include "bpxnet.h" -#include "socketmgmt.h" #include "httpserver.h" #include "json.h" - +#include "zssLogging.h" #include "passTicketService.h" #include "serviceUtils.h" @@ -30,10 +29,30 @@ #define APPLICATION_NAME_KEY "applicationName" #define APPLICATION_NAME_LEN 8 +#ifdef _LP64 +#pragma linkage(IRRSGS64, OS) +#define IRRSGS IRRSGS64 +#else +#pragma linkage(IRRSGS00, OS) +#define IRRSGS IRRSGS00 +#endif + +typedef struct PassTicketAPIStatus_tag { + uint32_t safRC; + uint32_t racfRC; + uint32_t racfRSN; +} PassTicketAPIStatus; + +typedef struct PassTicketResult_tag { + char ticket[TICKET_LEN+1]; + PassTicketAPIStatus status; +} PassTicketResult; + static int servePassTicket(HttpService *service, HttpResponse *response); static void respondWithPassTicket(HttpResponse *response, const char *applicationName, const char *ticket); -static int generatePassTicket(const char *applicationName, const char *userId, char *ticketBuf, size_t ticketBufSize, char *errorBuf, size_t errorBufSize); +static int generatePassTicket(const char *applicationName, const char *userId, PassTicketResult *result); static void respondWithPassTicketError(HttpResponse *response, int code, const char *status, const char *fmt, ...); +static void stringifyPassTicketAPIStatus(PassTicketAPIStatus *status, char *buffer, size_t bufferSize); int installPassTicketService(HttpServer *server) { HttpService *httpService = makeGeneratedService("PassTicket_Service", "/passticket"); @@ -49,7 +68,7 @@ int installPassTicketService(HttpServer *server) { static int servePassTicket(HttpService *service, HttpResponse *response) { HttpRequest *request = response->request; char applicationName[APPLICATION_NAME_LEN + 1] = {0}; - char ticket[TICKET_LEN + 1] = {0}; + PassTicketResult passTicketResult = {0}; char errorBuf[1024] = {0}; if (0 != strcmp(request->method, methodPOST)) { @@ -57,17 +76,19 @@ static int servePassTicket(HttpService *service, HttpResponse *response) { return 0; } - if (0 != extractApplicationName(request, applicationName, sizeof(applicationName), errorBuf, sizeof(errorBuf))) { + if (0 != getApplicationName(request, applicationName, sizeof(applicationName), errorBuf, sizeof(errorBuf))) { respondWithPassTicketError(response, HTTP_STATUS_BAD_REQUEST, "Bad Request", "Failed to get %s - %s", APPLICATION_NAME_KEY, errorBuf); return 0; } - if (0 != generatePassTicket(applicationName, request->username, ticket, sizeof(ticket), errorBuf, sizeof(errorBuf))) { - respondWithPassTicketError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Internal Server Error", "Failed to generate PassTicket - %s", errorBuf); + if (0 != generatePassTicket(applicationName, request->username, &passTicketResult)) { + stringifyPassTicketAPIStatus(&passTicketResult.status, errorBuf, sizeof(errorBuf)); + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_SEVERE, ZSS_LOG_PASSTICKET_GEN_FAILED_MSG, request->username, applicationName, errorBuf); + respondWithPassTicketError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Internal Server Error", "Failed to generate PassTicket"); return 0; } - respondWithPassTicket(response, applicationName, ticket); + respondWithPassTicket(response, applicationName, passTicketResult.ticket); return 0; } @@ -85,9 +106,68 @@ static void respondWithPassTicket(HttpResponse *response, const char *applicatio finishResponse(response); } -static int generatePassTicket(const char *applicationName, const char *userId, char *ticketBuf, size_t ticketBufSize, char *errorBuf, size_t errorBufSize) { - snprintf (ticketBuf, ticketBufSize, "%s", "LZTKEEDQ"); - return 0; +typedef struct StringBlock_tag { + uint32_t length; +#ifdef _LP64 + uint32_t zeros; +#endif + void *address; +} StringBlock; + +static int generatePassTicket(const char *applicationName, const char *userId, PassTicketResult *result) { + uint8_t workArea[1024]; + void *fnParm[4]; + StringBlock userBlock = {0}; + StringBlock applBlock = {0}; + StringBlock ticketBlock = {0}; + + userBlock.length = strlen(userId); + userBlock.address = (void*)userId; + applBlock.length = strlen(applicationName); + applBlock.address = (void*)applicationName; + ticketBlock.length = TICKET_LEN; + ticketBlock.address = result->ticket; + + uint32_t nParms = 12; + uint32_t alet1 = 0; + uint32_t alet2 = 0; + uint32_t alet3 = 0; + uint32_t optionWord = 0; /* reserved */ + uint16_t fnCode = 3; /* Passticket function */ + uint32_t subFnCode = 1; /* Generate passticket */ + uint32_t fnParmCount = 4; + fnParm[0] = &subFnCode; + fnParm[1] = &ticketBlock; + fnParm[2] = &userBlock; + fnParm[3] = &applBlock; + +#ifdef _LP64 +#define PASS_AS_DOUBLE_WORD(x) (x) // 64-bit pointer is already a double word +#else +#define PASS_AS_DOUBLE_WORD(x) NULL, x // pass as two parameters, first word filled with zeros and the second word filled with the 31 bit address +#endif + IRRSGS(PASS_AS_DOUBLE_WORD(&nParms), + PASS_AS_DOUBLE_WORD(workArea), + PASS_AS_DOUBLE_WORD(&alet1), + PASS_AS_DOUBLE_WORD(&result->status.safRC), + PASS_AS_DOUBLE_WORD(&alet2), + PASS_AS_DOUBLE_WORD(&result->status.racfRC), + PASS_AS_DOUBLE_WORD(&alet3), + PASS_AS_DOUBLE_WORD(&result->status.racfRSN), + PASS_AS_DOUBLE_WORD(&optionWord), + PASS_AS_DOUBLE_WORD(&fnCode), + PASS_AS_DOUBLE_WORD(&fnParmCount), + PASS_AS_DOUBLE_WORD(fnParm) +#ifndef _LP64 + , PASS_AS_DOUBLE_WORD(NULL) // finish the list for safety in 31bit mode +#endif + ); + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "passticket generation safRc=%d, racfRc=%d, racfReason=%d\n", result->status.safRC, result->status.racfRC, result->status.racfRSN); + int rc = (0 == result->status.safRC) ? 0 : -1; + if (rc == 0) { + result->ticket[TICKET_LEN] = '\0'; + } + return rc; } static void respondWithPassTicketError(HttpResponse *response, int code, const char *status, const char *fmt, ...) { @@ -110,9 +190,22 @@ static void respondWithPassTicketError(HttpResponse *response, int code, const c finishResponse(response); } -static int extractApplicationName(HttpRequest *request, char *applicationNameBuf, size_t applicationNameBufSize, char *errorBuf, size_t errorBufSize) { +static void stringifyPassTicketAPIStatus(PassTicketAPIStatus *status, char *buffer, size_t bufferSize) { + const char *errorMessage = NULL; + uint32_t safRC = status->safRC; + uint32_t racfRC = status->racfRC; + uint32_t racfRSN = status->racfRSN; + if (safRC == 8 && racfRC == 8 && racfRSN == 16) { + errorMessage = "Not authorized to generate PassTicket"; + } else if (safRC == 8 && racfRC == 16 && racfRSN == 28) { + errorMessage = "PassTicket generation failure. Verify that the secured signon (PassTicket) function and application ID is configured properly"; + } + snprintf (buffer, bufferSize, "safRc=%d, racfRc=%d, racfReason=%d %s", safRC, racfRC, racfRSN, errorMessage ? errorMessage : ""); +} + +static int getApplicationName(HttpRequest *request, char *applicationNameBuf, size_t applicationNameBufSize, char *errorBuf, size_t errorBufSize) { char *body = request->contentBody; - int len = body ? strlen(body) : 0; + size_t len = body ? strlen(body) : 0; if (len == 0) { snprintf (errorBuf, errorBufSize, "POST body is empty"); return -1; @@ -145,12 +238,10 @@ static int extractApplicationName(HttpRequest *request, char *applicationNameBuf } size_t appNameLen = strlen(appName); - if (appNameLen > APPLICATION_NAME_LEN) { snprintf (errorBuf, errorBufSize, "%s is too long", APPLICATION_NAME_KEY); return -1; } - if (appNameLen == 0) { snprintf (errorBuf, errorBufSize, "%s is empty", APPLICATION_NAME_KEY); return -1; diff --git a/h/zssLogging.h b/h/zssLogging.h index fa432a114..57736edfe 100644 --- a/h/zssLogging.h +++ b/h/zssLogging.h @@ -513,6 +513,13 @@ bool isLogLevelValid(int level); #define ZSS_LOG_GROUP_MGMT_QRY_DEL_MSG_TEXT "Group-mgmt query string is invalid, ending request...\n" #define ZSS_LOG_GROUP_MGMT_QRY_DEL_MSG ZSS_LOG_GROUP_MGMT_QRY_DEL_MSG_ID" "ZSS_LOG_GROUP_MGMT_QRY_DEL_MSG_TEXT +/* PassTicket */ +#ifndef ZSS_LOG_PASSTICKET_GEN_FAILED_MSG_ID +#define ZSS_LOG_PASSTICKET_GEN_FAILED_MSG_ID ZSS_LOG_MSG_PRFX"1500E" +#endif +#define ZSS_LOG_PASSTICKET_GEN_FAILED_MSG_TEXT "Failed to generate PassTicket - userId='%s', applId='%s', %s\n" +#define ZSS_LOG_PASSTICKET_GEN_FAILED_MSG ZSS_LOG_PASSTICKET_GEN_FAILED_MSG_ID" "ZSS_LOG_PASSTICKET_GEN_FAILED_MSG_TEXT + #endif /* MVD_H_ZSSLOGGING_H_ */ From 414466c079a38e22a376ff12d79500bc16214ac0 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Wed, 11 Aug 2021 09:59:02 +0500 Subject: [PATCH 57/68] Refactoring for PassTicket Signed-off-by: Leonty Chudinov --- c/passTicketService.c | 77 +++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/c/passTicketService.c b/c/passTicketService.c index 5fd11272b..d68a29e3d 100644 --- a/c/passTicketService.c +++ b/c/passTicketService.c @@ -26,8 +26,8 @@ #include "serviceUtils.h" #define TICKET_LEN 8 -#define APPLICATION_NAME_KEY "applicationName" -#define APPLICATION_NAME_LEN 8 +#define APP_NAME_KEY "applicationName" +#define APP_NAME_KEY_LEN 8 #ifdef _LP64 #pragma linkage(IRRSGS64, OS) @@ -49,8 +49,8 @@ typedef struct PassTicketResult_tag { } PassTicketResult; static int servePassTicket(HttpService *service, HttpResponse *response); -static void respondWithPassTicket(HttpResponse *response, const char *applicationName, const char *ticket); -static int generatePassTicket(const char *applicationName, const char *userId, PassTicketResult *result); +static void respondWithPassTicket(HttpResponse *response, const char *appName, const char *userId, const char *ticket); +static int generatePassTicket(const char *appName, const char *userId, PassTicketResult *result); static void respondWithPassTicketError(HttpResponse *response, int code, const char *status, const char *fmt, ...); static void stringifyPassTicketAPIStatus(PassTicketAPIStatus *status, char *buffer, size_t bufferSize); @@ -67,40 +67,41 @@ int installPassTicketService(HttpServer *server) { static int servePassTicket(HttpService *service, HttpResponse *response) { HttpRequest *request = response->request; - char applicationName[APPLICATION_NAME_LEN + 1] = {0}; + char appName[APP_NAME_KEY_LEN + 1] = {0}; PassTicketResult passTicketResult = {0}; char errorBuf[1024] = {0}; + const char *userId = request->username; if (0 != strcmp(request->method, methodPOST)) { respondWithPassTicketError(response, HTTP_STATUS_METHOD_NOT_FOUND, "Method Not Allowed", "Only POST method allowed"); return 0; } - if (0 != getApplicationName(request, applicationName, sizeof(applicationName), errorBuf, sizeof(errorBuf))) { - respondWithPassTicketError(response, HTTP_STATUS_BAD_REQUEST, "Bad Request", "Failed to get %s - %s", APPLICATION_NAME_KEY, errorBuf); + if (0 != getApplicationName(request, appName, sizeof(appName), errorBuf, sizeof(errorBuf))) { + respondWithPassTicketError(response, HTTP_STATUS_BAD_REQUEST, "Bad Request", "Failed to get %s - %s", APP_NAME_KEY, errorBuf); return 0; } - if (0 != generatePassTicket(applicationName, request->username, &passTicketResult)) { + if (0 != generatePassTicket(appName, userId, &passTicketResult)) { stringifyPassTicketAPIStatus(&passTicketResult.status, errorBuf, sizeof(errorBuf)); - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_SEVERE, ZSS_LOG_PASSTICKET_GEN_FAILED_MSG, request->username, applicationName, errorBuf); + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_SEVERE, ZSS_LOG_PASSTICKET_GEN_FAILED_MSG, userId, appName, errorBuf); respondWithPassTicketError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Internal Server Error", "Failed to generate PassTicket"); return 0; } - respondWithPassTicket(response, applicationName, passTicketResult.ticket); + respondWithPassTicket(response, appName, userId, passTicketResult.ticket); return 0; } -static void respondWithPassTicket(HttpResponse *response, const char *applicationName, const char *ticket) { +static void respondWithPassTicket(HttpResponse *response, const char *appName, const char *userId, const char *ticket) { HttpRequest *request = response->request; jsonPrinter *p = respondWithJsonPrinter(response); setResponseStatus(response, 200, "OK"); setDefaultJSONRESTHeaders(response); writeHeader(response); jsonStart(p); - jsonAddString(p, "userId", request->username); - jsonAddString(p, APPLICATION_NAME_KEY, (char*)applicationName); + jsonAddString(p, "userId", (char*)userId); + jsonAddString(p, APP_NAME_KEY, (char*)appName); jsonAddString(p, "ticket", (char*)ticket); jsonEnd(p); finishResponse(response); @@ -114,28 +115,28 @@ typedef struct StringBlock_tag { void *address; } StringBlock; -static int generatePassTicket(const char *applicationName, const char *userId, PassTicketResult *result) { +static int generatePassTicket(const char *appName, const char *userId, PassTicketResult *result) { uint8_t workArea[1024]; void *fnParm[4]; StringBlock userBlock = {0}; StringBlock applBlock = {0}; StringBlock ticketBlock = {0}; - userBlock.length = strlen(userId); - userBlock.address = (void*)userId; - applBlock.length = strlen(applicationName); - applBlock.address = (void*)applicationName; - ticketBlock.length = TICKET_LEN; - ticketBlock.address = result->ticket; + userBlock.length = strlen(userId); + userBlock.address = (void*)userId; + applBlock.length = strlen(appName); + applBlock.address = (void*)appName; + ticketBlock.length = TICKET_LEN; + ticketBlock.address = result->ticket; uint32_t nParms = 12; uint32_t alet1 = 0; uint32_t alet2 = 0; uint32_t alet3 = 0; uint32_t optionWord = 0; /* reserved */ - uint16_t fnCode = 3; /* Passticket function */ - uint32_t subFnCode = 1; /* Generate passticket */ - uint32_t fnParmCount = 4; + uint16_t fnCode = 3; /* PassTicket function */ + uint32_t subFnCode = 1; /* Generate PassTicket */ + uint32_t fnParmCount = 4; fnParm[0] = &subFnCode; fnParm[1] = &ticketBlock; fnParm[2] = &userBlock; @@ -162,7 +163,9 @@ static int generatePassTicket(const char *applicationName, const char *userId, P , PASS_AS_DOUBLE_WORD(NULL) // finish the list for safety in 31bit mode #endif ); - zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, "passticket generation safRc=%d, racfRc=%d, racfReason=%d\n", result->status.safRC, result->status.racfRC, result->status.racfRSN); + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG2, + "passticket generation safRc=%d, racfRc=%d, racfReason=%d\n", + result->status.safRC, result->status.racfRC, result->status.racfRSN); int rc = (0 == result->status.safRC) ? 0 : -1; if (rc == 0) { result->ticket[TICKET_LEN] = '\0'; @@ -191,19 +194,23 @@ static void respondWithPassTicketError(HttpResponse *response, int code, const c } static void stringifyPassTicketAPIStatus(PassTicketAPIStatus *status, char *buffer, size_t bufferSize) { - const char *errorMessage = NULL; + char message[512] = {0}; uint32_t safRC = status->safRC; uint32_t racfRC = status->racfRC; uint32_t racfRSN = status->racfRSN; if (safRC == 8 && racfRC == 8 && racfRSN == 16) { - errorMessage = "Not authorized to generate PassTicket"; + snprintf (message, sizeof(message), + "Server userid not authorized to generate PassTicket. " + "Check that server userid has UPDATE access to IRRPTAUTH.. profile"); } else if (safRC == 8 && racfRC == 16 && racfRSN == 28) { - errorMessage = "PassTicket generation failure. Verify that the secured signon (PassTicket) function and application ID is configured properly"; + snprintf (message, sizeof(message), + "PassTicket generation failure. " + "Verify that the secured signon (PassTicket) function and application ID is configured properly"); } - snprintf (buffer, bufferSize, "safRc=%d, racfRc=%d, racfReason=%d %s", safRC, racfRC, racfRSN, errorMessage ? errorMessage : ""); + snprintf (buffer, bufferSize, "safRc=%d, racfRc=%d, racfReason=%d %s", safRC, racfRC, racfRSN, message); } -static int getApplicationName(HttpRequest *request, char *applicationNameBuf, size_t applicationNameBufSize, char *errorBuf, size_t errorBufSize) { +static int getApplicationName(HttpRequest *request, char *appNameBuf, size_t appNameBufSize, char *errorBuf, size_t errorBufSize) { char *body = request->contentBody; size_t len = body ? strlen(body) : 0; if (len == 0) { @@ -231,23 +238,23 @@ static int getApplicationName(HttpRequest *request, char *applicationNameBuf, si return -1; } - char *appName = jsonObjectGetString(jsonBodyObject, APPLICATION_NAME_KEY); + char *appName = jsonObjectGetString(jsonBodyObject, APP_NAME_KEY); if (!appName) { - snprintf (errorBuf, errorBufSize, "%s key not found in JSON POST body", APPLICATION_NAME_KEY); + snprintf (errorBuf, errorBufSize, "%s key not found in JSON POST body", APP_NAME_KEY); return -1; } size_t appNameLen = strlen(appName); - if (appNameLen > APPLICATION_NAME_LEN) { - snprintf (errorBuf, errorBufSize, "%s is too long", APPLICATION_NAME_KEY); + if (appNameLen > APP_NAME_KEY_LEN) { + snprintf (errorBuf, errorBufSize, "%s is too long", APP_NAME_KEY); return -1; } if (appNameLen == 0) { - snprintf (errorBuf, errorBufSize, "%s is empty", APPLICATION_NAME_KEY); + snprintf (errorBuf, errorBufSize, "%s is empty", APP_NAME_KEY); return -1; } - snprintf (applicationNameBuf, applicationNameBufSize, "%s", appName); + snprintf (appNameBuf, appNameBufSize, "%s", strupcase(appName)); return 0; } From ad39d3b9677a14236f0029798d0d44fb9f0bfc11 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Wed, 11 Aug 2021 10:02:12 +0500 Subject: [PATCH 58/68] Add passTicketService.c to build_zss.sh Signed-off-by: Leonty Chudinov --- build/build_zss.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build/build_zss.sh b/build/build_zss.sh index f721e1281..227e2cd74 100755 --- a/build/build_zss.sh +++ b/build/build_zss.sh @@ -145,6 +145,7 @@ if c89 \ ${ZSS}/c/zis/client.c \ ${ZSS}/c/serverStatusService.c \ ${ZSS}/c/rasService.c \ + ${ZSS}/c/passTicketService.c \ ${GSKLIB} ; then extattr +p ${ZSS}/bin/zssServer From 3b10697903f7c99d171efb17f407c05880bb81f1 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Wed, 11 Aug 2021 12:08:36 +0500 Subject: [PATCH 59/68] Update Changelog Signed-off-by: Leonty Chudinov --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b97c751ad..fc8935f37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to the ZSS package will be documented in this file. ## `1.24.0` - Bugfix: Fix `zis-plugin-install.sh` script to properly exit on error with extended-install +- Enhancement: Add an endpoint for PassTicket generation ## `1.23.0` From 918bf9923d4d0d9bbc231da49de9262c7adc4b15 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Thu, 12 Aug 2021 09:07:00 +0500 Subject: [PATCH 60/68] Cleanup includes Signed-off-by: Leonty Chudinov --- h/passTicketService.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/h/passTicketService.h b/h/passTicketService.h index 502070289..5ad2be93a 100644 --- a/h/passTicketService.h +++ b/h/passTicketService.h @@ -13,19 +13,6 @@ #ifndef __PASS_TICKET_SERVICE_H__ #define __PASS_TICKET_SERVICE_H__ -#include "zowetypes.h" -#include "alloc.h" -#include "utils.h" -#ifdef __ZOWE_OS_ZOS -#include "zos.h" -#endif -#include "logging.h" -#include "json.h" -#include "bpxnet.h" -#include "socketmgmt.h" -#include "httpserver.h" -#include "dataservice.h" - int installPassTicketService(HttpServer *server); #endif // __PASS_TICKET_SERVICE_H__ From b83e85e3be8394818d783196428e0ee669c9d5e7 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Tue, 31 Aug 2021 10:11:11 +0500 Subject: [PATCH 61/68] Disable RBAC authorization for saf-auth service Signed-off-by: Leonty Chudinov --- c/authService.c | 1 + 1 file changed, 1 insertion(+) diff --git a/c/authService.c b/c/authService.c index 5e25e83ec..9e39e17c4 100644 --- a/c/authService.c +++ b/c/authService.c @@ -98,6 +98,7 @@ int installAuthCheckService(HttpServer *server) { httpService->authType = SERVICE_AUTH_NATIVE_WITH_SESSION_TOKEN; httpService->serviceFunction = &serveAuthCheck; httpService->runInSubtask = FALSE; + httpService->authorizationType = SERVICE_AUTHORIZATION_TYPE_NONE; registerHttpService(server, httpService); // zowelog(NULL, 0, ZOWE_LOG_DEBUG2, "end %s\n", // __FUNCTION__); From 42acd8ec68cd95928961c4e21348ce075a1b9294 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Tue, 31 Aug 2021 13:11:46 +0500 Subject: [PATCH 62/68] Update pointer to zowe-common-c Signed-off-by: Leonty Chudinov --- deps/zowe-common-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 979e105c8..2a1ab8474 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 979e105c8743a30a14fa2f0d0b0f88578f7ef803 +Subproject commit 2a1ab847433ee2b0d4d32cf3aefe15055ca6b935 From a4b56dfc269c6930ec4ff9ec3727b45d2a9f5f09 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Tue, 31 Aug 2021 14:00:19 +0500 Subject: [PATCH 63/68] Update pointer to zowe-common-c Signed-off-by: Leonty Chudinov --- deps/zowe-common-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 2a1ab8474..2f45fb2ba 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 2a1ab847433ee2b0d4d32cf3aefe15055ca6b935 +Subproject commit 2f45fb2ba8c2354ac644672d1f6e10d4f74538c8 From 0899ef7bd437a7b01f1a175b8984afc3a5504260 Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Tue, 31 Aug 2021 17:56:20 +0500 Subject: [PATCH 64/68] Fix buffer size Signed-off-by: Leonty Chudinov --- c/authService.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/c/authService.c b/c/authService.c index 9e39e17c4..7afe4e42f 100644 --- a/c/authService.c +++ b/c/authService.c @@ -321,12 +321,12 @@ static void setProfileNameAttribs( char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE]) { if ((strcmp(pluginID, SAF_PLUGIN_ID) == 0) && (strcmp(serviceName, SAF_SERVICE_NAME) == 0)) { - snprintf(type, sizeof(type), "config"); - snprintf(pluginID, sizeof(pluginID), subUrl[0]); - snprintf(scope, sizeof(scope), subUrl[1]); + snprintf(type, STRING_BUFFER_SIZE, "config"); + snprintf(pluginID, STRING_BUFFER_SIZE, subUrl[0]); + snprintf(scope, STRING_BUFFER_SIZE, subUrl[1]); } else { - snprintf(type, sizeof(type), "service"); + snprintf(type, STRING_BUFFER_SIZE, "service"); } } From acf074c8374c8f75dded9d06ca5adb4a5e9e89f2 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Fri, 24 Sep 2021 12:03:35 -0400 Subject: [PATCH 65/68] Updated zowe-common-c Signed-off-by: Leanid Astrakou --- deps/zowe-common-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 979e105c8..2f45fb2ba 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 979e105c8743a30a14fa2f0d0b0f88578f7ef803 +Subproject commit 2f45fb2ba8c2354ac644672d1f6e10d4f74538c8 From 65e909ec3999d4149315cc0dc9fa1a9d14bcaaf0 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Fri, 24 Sep 2021 12:27:01 -0400 Subject: [PATCH 66/68] Updated zowe-common-c Signed-off-by: Leanid Astrakou --- deps/zowe-common-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zowe-common-c b/deps/zowe-common-c index 2f45fb2ba..58bf017fc 160000 --- a/deps/zowe-common-c +++ b/deps/zowe-common-c @@ -1 +1 @@ -Subproject commit 2f45fb2ba8c2354ac644672d1f6e10d4f74538c8 +Subproject commit 58bf017fc32d1d84d0a4bda3e7479a273e9b63df From 6a66374241e4336859b55c84810305c7b48e0ee2 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Fri, 24 Sep 2021 12:57:00 -0400 Subject: [PATCH 67/68] Small changelog typo Signed-off-by: Leanid Astrakou --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee2669b9b..e0b5e10a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,6 @@ All notable changes to the ZSS package will be documented in this file. ## `1.24.0` - Bugfix: Fix `zis-plugin-install.sh` script to properly exit on error with extended-install -- Enhancement: Add an endpoint for PassTicket generation - Bugfix: When builtin TLS was enabled, a small leak occurred when closing sockets. ## `1.23.0` From 8160346bce9d0d00461024c4d192e1c20e4174cb Mon Sep 17 00:00:00 2001 From: Leonty Chudinov Date: Mon, 29 Nov 2021 16:26:08 +0500 Subject: [PATCH 68/68] Adderss code review Signed-off-by: Leonty Chudinov --- c/authService.c | 23 ++++++++++++----------- c/zss.c | 31 ++++++++++++++++++++++--------- h/authService.h | 2 +- h/zssLogging.h | 6 ++++++ 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/c/authService.c b/c/authService.c index 7afe4e42f..a5371905f 100644 --- a/c/authService.c +++ b/c/authService.c @@ -187,7 +187,7 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { int rc = 0, rsn = 0, safStatus = 0; ZISAuthServiceStatus reqStatus = {0}; CrossMemoryServerName *privilegedServerName; - const char *userName = req->username, *class = SAF_CLASS; + const char *userName = req->username, *class = ZOWE_SAF_CLASS; rc = extractQuery(req->parsedFile, &entity, &accessStr); if (rc != 0) { respondWithError(res, HTTP_STATUS_BAD_REQUEST, "Broken auth query"); @@ -211,7 +211,7 @@ static int serveAuthCheck(HttpService *service, HttpResponse *res) { int verifyAccessToSafProfile(HttpServer *server, const char *userName, const char *entity, const int access) { CrossMemoryServerName *privilegedServerName = getConfiguredProperty(server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); ZISAuthServiceStatus reqStatus = {0}; - const char *class = SAF_CLASS; + const char *class = ZOWE_SAF_CLASS; int rc = zisCheckEntity(privilegedServerName, userName, class, entity, access, &reqStatus); zowelog(NULL, LOG_COMP_ID_SECURITY, ZOWE_LOG_DEBUG2, @@ -221,15 +221,16 @@ int verifyAccessToSafProfile(HttpServer *server, const char *userName, const cha } int getProfileNameFromRequest(char *profileName, const int profileNameBufSize, StringList *parsedFile, const char *method, int instanceID) { - char type[STRING_BUFFER_SIZE]; // core || config || service - char productCode[STRING_BUFFER_SIZE]; - char rootServiceName[STRING_BUFFER_SIZE]; + char type[STRING_BUFFER_SIZE] = {0}; // core || config || service + char productCode[STRING_BUFFER_SIZE] = {0}; + char rootServiceName[STRING_BUFFER_SIZE] = {0}; char subUrl[SAF_SUB_URL_SIZE][STRING_BUFFER_SIZE] = {0}; - char scope[STRING_BUFFER_SIZE]; - char pluginID[STRING_BUFFER_SIZE]; - char serviceName[STRING_BUFFER_SIZE]; - char urlSegment[STRING_BUFFER_SIZE]; + char scope[STRING_BUFFER_SIZE] = {0}; + char pluginID[STRING_BUFFER_SIZE] = {0}; + char serviceName[STRING_BUFFER_SIZE] = {0}; + char urlSegment[STRING_BUFFER_SIZE] = {0}; int subUrlIndex = 0; + bool isRootServiceNameInited = false; snprintf(urlSegment, sizeof(urlSegment), "%s", stringListPrint(parsedFile, 1, 1, "/", 0)); StringListElt *pathSegment = firstStringListElt(parsedFile); @@ -245,9 +246,9 @@ int getProfileNameFromRequest(char *profileName, const int profileNameBufSize, S while (pathSegment != NULL) { snprintf(urlSegment, sizeof(urlSegment), "%s", pathSegment->string); strupcase(urlSegment); - if (rootServiceName == NULL) - { + if (!isRootServiceNameInited) { snprintf(rootServiceName, sizeof(rootServiceName), urlSegment); + isRootServiceNameInited = true; } else { //If URL subsections > SAF_SUB_URL_SIZE, we trim them from profile name (by not appending them) if (subUrlIndex < SAF_SUB_URL_SIZE) { snprintf(subUrl[subUrlIndex], sizeof(subUrl), urlSegment); diff --git a/c/zss.c b/c/zss.c index b9d1cccd8..82eab03a5 100644 --- a/c/zss.c +++ b/c/zss.c @@ -336,7 +336,10 @@ static int rbacAuthorization(HttpService *service, HttpRequest *request, HttpRes RbacAuthorizationData *rbacData = userData; char method[16]; - snprintf(method, sizeof(method), "%s", request->method); + if (snprintf(method, sizeof(method), "%s", request->method) >= sizeof(method)) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG, "HTTP method too long\n"); + return FALSE; + }; destructivelyNativize(method); char profileName[ZOWE_PROFILE_NAME_LEN+1] = {0}; @@ -367,7 +370,7 @@ static bool isRbacEnabled(JsonObject *mvdSettings, JsonObject *envSettings) { return rbacParm; } -static int getZoweInstanceId() { +static int getZoweInstanceId(void) { char *instance = getenv("ZOWE_INSTANCE"); if (!instance) { return 0; @@ -375,16 +378,22 @@ static int getZoweInstanceId() { return atoi(instance); } -/* Future custom ZSS authorization handlers go here */ -static void registerAuthorizationHandlers(HttpServer *server, bool rbacEnabled) { +/* Registers Authorization handlers, returns true on success, false on failure */ +static bool registerAuthorizationHandlers(HttpServer *server, bool rbacEnabled) { if (!rbacEnabled) { - return; + return true; } RbacAuthorizationData *rbacData = (RbacAuthorizationData*) safeMalloc(sizeof(*rbacData), "Rbac Authorization Data"); - if (rbacData) { - rbacData->instanceId = getZoweInstanceId(); - registerHttpAuthorizationHandler(server, SERVICE_AUTHORIZATION_TYPE_DEFAULT, rbacAuthorization, rbacData); + if (!rbacData) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG, "failed to allocate memory for RBAC Authorization data\n"); + return false; } + rbacData->instanceId = getZoweInstanceId(); + if (registerHttpAuthorizationHandler(server, SERVICE_AUTHORIZATION_TYPE_DEFAULT, rbacAuthorization, rbacData) == -1) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_DEBUG, "failed to register RBAC authorization handler\n"); + return false; + }; + return true; } static void loadWebServerConfig(HttpServer *server, JsonObject *mvdSettings, @@ -1720,7 +1729,11 @@ int main(int argc, char **argv){ server->defaultProductURLPrefix = PRODUCT; initializePluginIDHashTable(server); bool rbacEnabled = isRbacEnabled(mvdSettings, envSettings); - registerAuthorizationHandlers(server, rbacEnabled); + if (!registerAuthorizationHandlers(server, rbacEnabled)) { + zowelog(NULL, LOG_COMP_ID_MVD_SERVER, ZOWE_LOG_SEVERE, ZSS_LOG_AUTH_HANDLER_REG_MSG); + zssStatus = ZSS_STATUS_ERROR; + goto out_term_stcbase; + } loadWebServerConfig(server, mvdSettings, envSettings, htUsers, htGroups, defaultSeconds); readWebPluginDefinitions(server, slh, pluginsDir, mvdSettings, envSettings, apimlStorageSettings); installCertificateService(server); diff --git a/h/authService.h b/h/authService.h index 3e9d5f0cf..c687b3fc8 100644 --- a/h/authService.h +++ b/h/authService.h @@ -26,7 +26,7 @@ #include "httpserver.h" #include "dataservice.h" -#define SAF_CLASS "ZOWE" +#define ZOWE_SAF_CLASS "ZOWE" #define ZOWE_PROFILE_NAME_LEN 246 int installAuthCheckService(HttpServer *server); diff --git a/h/zssLogging.h b/h/zssLogging.h index 57736edfe..9da6949ae 100644 --- a/h/zssLogging.h +++ b/h/zssLogging.h @@ -513,6 +513,12 @@ bool isLogLevelValid(int level); #define ZSS_LOG_GROUP_MGMT_QRY_DEL_MSG_TEXT "Group-mgmt query string is invalid, ending request...\n" #define ZSS_LOG_GROUP_MGMT_QRY_DEL_MSG ZSS_LOG_GROUP_MGMT_QRY_DEL_MSG_ID" "ZSS_LOG_GROUP_MGMT_QRY_DEL_MSG_TEXT +#ifndef ZSS_LOG_AUTH_HANDLER_REG_MSG_ID +#define ZSS_LOG_AUTH_HANDLER_REG_MSG_ID ZSS_LOG_MSG_PRFX"1420E" +#endif +#define ZSS_LOG_AUTH_HANDLER_REG_MSG_TEXT "Failed to register authorization handlers\n" +#define ZSS_LOG_AUTH_HANDLER_REG_MSG ZSS_LOG_AUTH_HANDLER_REG_MSG_ID" "ZSS_LOG_AUTH_HANDLER_REG_MSG_TEXT + /* PassTicket */ #ifndef ZSS_LOG_PASSTICKET_GEN_FAILED_MSG_ID #define ZSS_LOG_PASSTICKET_GEN_FAILED_MSG_ID ZSS_LOG_MSG_PRFX"1500E"