From c0da63b1fa1bfd2790d41b535256590a615b8ea9 Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Wed, 5 Apr 2023 11:25:46 -0500 Subject: [PATCH 01/18] testing certificate auth Signed-off-by: Jordan Filteau --- c/httpserver.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/c/httpserver.c b/c/httpserver.c index f88962e18..5c46ebbeb 100644 --- a/c/httpserver.c +++ b/c/httpserver.c @@ -3161,6 +3161,21 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * if (service->authExtractionFunction(service, request) == 0){ authDataFound = TRUE; + } else { + if (request->contentLength > 1) { + // certificate authentication + char userid[9] = {0}; + int mapReturnCode = 0, mapReasonCode = 0; + int rc = getUseridByCertificate(request->contentBody, request->contentLength, userid, &mapReturnCode, &mapReasonCode); + if (rc == 0) { + request->username = userid; + printf("Found user = %s\n", request->username); + request->password = NULL; + authDataFound = TRUE; + } else { + printf("No user found. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n"); + } + } } } } From ee4c9184e8d744d823024e678f3a8066568f1102 Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Wed, 5 Apr 2023 13:48:25 -0500 Subject: [PATCH 02/18] working certificate based authentication with R_usermap. Signed-off-by: Jordan Filteau --- c/httpserver.c | 73 +++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/c/httpserver.c b/c/httpserver.c index 5c46ebbeb..1d5280181 100644 --- a/c/httpserver.c +++ b/c/httpserver.c @@ -2653,19 +2653,23 @@ static int safAuthenticate(HttpService *service, HttpRequest *request, AuthRespo } else if (authDataFound){ ACEE *acee = NULL; strupcase(request->username); /* upfold username */ + if (request->password == NULL) { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "Password is null. Calling safAuthenticate without a password.\n"); + } else { #ifdef ENABLE_DANGEROUS_AUTH_TRACING #ifdef METTLE - printf("SAF auth for user: '%s'\n", request->username); + printf("SAF auth for user: '%s'\n", request->username); #else - printf("u: '%s' p: '%s'\n",request->username,request->password); + printf("u: '%s' p: '%s'\n",request->username,request->password); #endif #endif - if (isLowerCasePasswordAllowed() || isPassPhrase(request->password)) { - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "mixed-case system or a pass phrase, not upfolding password\n"); - /* don't upfold password */ - } else { - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "non-mixed-case system, not a pass phrase, upfolding password\n"); - strupcase(request->password); /* upfold password */ + if (isLowerCasePasswordAllowed() || isPassPhrase(request->password)) { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "mixed-case system or a pass phrase, not upfolding password\n"); + /* don't upfold password */ + } else { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "non-mixed-case system, not a pass phrase, upfolding password\n"); + strupcase(request->password); /* upfold password */ + } } #if APF_AUTHORIZED @@ -2675,10 +2679,17 @@ static int safAuthenticate(HttpService *service, HttpRequest *request, AuthRespo CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); int pwdCheckRC = 0, pwdCheckRSN = 0; - pwdCheckRC = zisCheckUsernameAndPassword(privilegedServerName, - request->username, request->password, &status); - authResponse->type = AUTH_TYPE_RACF; - authResponse->responseDetails.safStatus = status.safStatus; + if (request->password != NULL) { + pwdCheckRC = zisCheckUsernameAndPassword(privilegedServerName, + request->username, request->password, &status); + authResponse->type = AUTH_TYPE_RACF; + authResponse->responseDetails.safStatus = status.safStatus; + } else { + pwdCheckRC = zisCheckUsername(privilegedServerName, + request->username, &status); + authResponse->type = AUTH_TYPE_RACF; + authResponse->responseDetails.safStatus = status.safStatus; + } if (pwdCheckRC != 0) { #ifdef DEBUG_AUTH @@ -3142,7 +3153,7 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * int authDataFound = FALSE; HttpHeader *authenticationHeader = getHeader(request,"Authorization"); char *tokenCookieText = getCookieValue(request,getSessionTokenCookieName(service)); - + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "serviceAuthNativeWithSessionToken: authenticationHeader 0x%p\n", "extractFunction 0x%p\n", @@ -3161,22 +3172,30 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * if (service->authExtractionFunction(service, request) == 0){ authDataFound = TRUE; + } + } + } + + char userid[9] = {0}; + int mapReturnCode = 0, mapReasonCode = 0; + int rc = 0; + + if (authDataFound == FALSE) { + if (request->contentLength > 1) { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There was no token found or credentials in the request. Attempting certificate authentication.\n"); + int rc = getUseridByCertificate(request->contentBody, request->contentLength, userid, &mapReturnCode, &mapReasonCode); + if (rc == 0) { + request->username = userid; + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "Found user = %s\n", request->username); + request->password = NULL; + // null password with a valid user tells the server we authenticated with a certificate + authDataFound = TRUE; } else { - if (request->contentLength > 1) { - // certificate authentication - char userid[9] = {0}; - int mapReturnCode = 0, mapReasonCode = 0; - int rc = getUseridByCertificate(request->contentBody, request->contentLength, userid, &mapReturnCode, &mapReasonCode); - if (rc == 0) { - request->username = userid; - printf("Found user = %s\n", request->username); - request->password = NULL; - authDataFound = TRUE; - } else { - printf("No user found. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n"); - } - } + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, + "No user found. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n", rc, mapReturnCode, mapReasonCode); } + } else { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There is no certificate in the request body. Not attempting certificate authentication.\n"); } } From 0d82a1c4ff6fd7e1fe6b2f7b2eff9c0bbd96e41f Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Mon, 10 Apr 2023 15:47:22 -0500 Subject: [PATCH 03/18] grabbing cert from tls handshake Signed-off-by: Jordan Filteau --- c/httpserver.c | 47 ++++++++++++++++++++++++----------- c/tls.c | 67 +++++++++++++++++++++++++++++++++++++++++++++----- h/tls.h | 1 + 3 files changed, 95 insertions(+), 20 deletions(-) diff --git a/c/httpserver.c b/c/httpserver.c index 1d5280181..ef4fba1c2 100644 --- a/c/httpserver.c +++ b/c/httpserver.c @@ -3172,33 +3172,52 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * if (service->authExtractionFunction(service, request) == 0){ authDataFound = TRUE; - } + } } } - char userid[9] = {0}; - int mapReturnCode = 0, mapReasonCode = 0; - int rc = 0; + /* Doubtful that it would be greater than 8k... */ + +#define TLS_CLIENT_CERTIFICATE_MAX_LENGTH 8000 + + char clientCertificate[TLS_CLIENT_CERTIFICATE_MAX_LENGTH] = {0}; + unsigned int clientCertificateLength = 0; - if (authDataFound == FALSE) { - if (request->contentLength > 1) { - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There was no token found or credentials in the request. Attempting certificate authentication.\n"); - int rc = getUseridByCertificate(request->contentBody, request->contentLength, userid, &mapReturnCode, &mapReasonCode); - if (rc == 0) { + int rc = getClientCertificate(response->socket->tlsSocket->socketHandle, clientCertificate, sizeof(clientCertificate), &clientCertificateLength); + if (rc != 0) { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "getClientCertificate - %d.\n", rc); + } + +#ifdef ENABLE_DANGEROUS_AUTH_TRACING + /* We probably don't want to dump their certificate, right? */ + dumpbuffer(clientCertificate, clientCertificateLength); +#endif + + if (rc == 0 && clientCertificateLength > 0) { + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "There is a client certificate attached to the request.\n"); + /* + * We don't want to do this if we already found authentication data. + */ + if (authDataFound == FALSE) { +#define TLS_USERID_LENGTH 9 + char userid[TLS_USERID_LENGTH] = {0}; + int racfReturnCode = 0, racfReasonCode = 0; + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There was no token or credentials found in the request. Server is attempting to map the client certificate.\n"); + int safReturnCode = getUseridByCertificate(clientCertificate, clientCertificateLength, userid, &racfReturnCode, &racfReasonCode); + if (safReturnCode == 0) { request->username = userid; - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "Found user = %s\n", request->username); + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "Found user '%s' from client certificate.\n", request->username); request->password = NULL; // null password with a valid user tells the server we authenticated with a certificate authDataFound = TRUE; } else { - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, - "No user found. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n", rc, mapReturnCode, mapReasonCode); + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "No user was found for client certificate. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n", safReturnCode, racfReturnCode, racfReasonCode); } } else { - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There is no certificate in the request body. Not attempting certificate authentication.\n"); + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "Client certificate was attached to request, but credentials are also attached. Server won't attempt to map the client certificate.\n"); } } - + response->sessionCookie = NULL; AUTH_TRACE("AUTH: tokenCookieText: %s\n",(tokenCookieText ? tokenCookieText : "")); diff --git a/c/tls.c b/c/tls.c index 44a98aec3..cedf4801c 100644 --- a/c/tls.c +++ b/c/tls.c @@ -15,6 +15,40 @@ #include "fdpoll.h" #include "tls.h" +int getClientCertificate(gsk_handle soc_handle, char *clientCertificate, unsigned int clientCertificateBufferSize, unsigned int *clientCertificateLength) { + + if (clientCertificate == NULL || clientCertificateBufferSize <= 0) { + return -1; + } + + memset(clientCertificate, 0, clientCertificateBufferSize); + *clientCertificateLength = 0; + + gsk_cert_data_elem *gskCertificateArray = NULL; + int gskCertificateArrayElementCount = 0; + + int rc = gsk_attribute_get_cert_info(soc_handle, GSK_PARTNER_CERT_INFO, &gskCertificateArray, &gskCertificateArrayElementCount); + + if (rc != 0) { + return rc; + } + + gsk_cert_data_elem *tmp = gskCertificateArray; + + for (int i = 0; i++ < gskCertificateArrayElementCount; tmp++) { + if (tmp->cert_data_id == CERT_BODY_DER) { + if (clientCertificateBufferSize >= tmp->cert_data_l) { + memcpy(clientCertificate, tmp->cert_data_p, tmp->cert_data_l); + *clientCertificateLength = tmp->cert_data_l; + } + } + } + + gsk_free_cert_data(gskCertificateArray, gskCertificateArrayElementCount); + + return 0; +} + int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { int rc = 0; TlsEnvironment *env = (TlsEnvironment *)safeMalloc(sizeof(*env), "Tls Environment"); @@ -29,6 +63,23 @@ int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_PROTOCOL_TLSV1_1, GSK_PROTOCOL_TLSV1_1_OFF); rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_PROTOCOL_TLSV1_2, GSK_PROTOCOL_TLSV1_2_ON); rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_SERVER_EPHEMERAL_DH_GROUP_SIZE, GSK_SERVER_EPHEMERAL_DH_GROUP_SIZE_2048); + + /* + * Don't validate certificates, maybe put behind a dangerous ifdef. + * + * rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_TYPE, GSK_CLIENT_AUTH_PASSTHRU_TYPE); + */ + +#ifdef DEV_DO_NOT_VALIDATE_CLIENT_CERTIFICATES + rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_TYPE, GSK_CLIENT_AUTH_PASSTHRU_TYPE); +#endif + + /* + * Only allow requests with client certificates, maybe put behind a different ifdef. + * + * rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_ALERT, GSK_CLIENT_AUTH_NOCERT_ALERT_ON); + */ + rc = rc || gsk_attribute_set_buffer(env->envHandle, GSK_KEYRING_FILE, settings->keyring, 0); if (settings->stash) { rc = rc || gsk_attribute_set_buffer(env->envHandle, GSK_KEYRING_STASH_FILE, settings->stash, 0); @@ -43,6 +94,7 @@ int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { safeFree((char*)env, sizeof(*env)); *outEnv = NULL; } + //printf("tlsInit - rc=%d\n", rc); return rc; } @@ -50,6 +102,7 @@ int tlsDestroy(TlsEnvironment *env) { int rc = 0; rc = gsk_environment_close(env->envHandle); safeFree((char*)env, sizeof(*env)); + //printf("tlsDestroy - rc=%d\n", rc); return rc; } @@ -72,6 +125,7 @@ static int secureSocketRecv(int fd, void *data, int len, char *userData) { break; } } + //printf("secureSocketRecv = %d\n", rc); return rc; } @@ -92,11 +146,12 @@ static int secureSocketSend(int fd, void *data, int len, char *userData) { break; } } + //printf("secureSocketSend = %d\n", rc); return rc; } - + int tlsSocketInit(TlsEnvironment *env, TlsSocket **outSocket, int fd, bool isServer) { - int rc = 0; + int rc = 0; gsk_iocallback ioCallbacks = {secureSocketRecv, secureSocketSend, NULL, NULL, NULL, NULL}; TlsSocket *socket = (TlsSocket*)safeMalloc(sizeof(TlsSocket), "Tls Socket"); if (!socket) { @@ -104,25 +159,25 @@ int tlsSocketInit(TlsEnvironment *env, TlsSocket **outSocket, int fd, bool isSer } char *label = env->settings->label; char *ciphers = env->settings->ciphers; - rc = rc || gsk_secure_socket_open(env->envHandle, &socket->socketHandle); + rc = gsk_secure_socket_open(env->envHandle, &socket->socketHandle); rc = rc || gsk_attribute_set_numeric_value(socket->socketHandle, GSK_FD, fd); if (label) { rc = rc || gsk_attribute_set_buffer(socket->socketHandle, GSK_KEYRING_LABEL, label, 0); } - rc = rc || gsk_attribute_set_enum(socket->socketHandle, GSK_SESSION_TYPE, - isServer ? GSK_SERVER_SESSION : GSK_CLIENT_SESSION); + rc = gsk_attribute_set_enum(socket->socketHandle, GSK_SESSION_TYPE, isServer ? GSK_SERVER_SESSION_WITH_CL_AUTH : GSK_CLIENT_SESSION); if (ciphers) { rc = rc || gsk_attribute_set_buffer(socket->socketHandle, GSK_V3_CIPHER_SPECS_EXPANDED, ciphers, 0); rc = rc || gsk_attribute_set_enum(socket->socketHandle, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4); } rc = rc || gsk_attribute_set_callback(socket->socketHandle, GSK_IO_CALLBACK, &ioCallbacks); - rc = rc || gsk_secure_socket_init(socket->socketHandle); + rc = gsk_secure_socket_init(socket->socketHandle); if (rc == 0) { *outSocket = socket; } else { safeFree((char*)socket, sizeof(*socket)); *outSocket = NULL; } + //printf("tlsSocketInit - rc=%d\n", rc); return rc; } diff --git a/h/tls.h b/h/tls.h index 47ec2935d..f1f9bd59f 100644 --- a/h/tls.h +++ b/h/tls.h @@ -140,6 +140,7 @@ int tlsSocketClose(TlsSocket *socket); int tlsRead(TlsSocket *socket, const char *buf, int size, int *outLength); int tlsWrite(TlsSocket *socket, const char *buf, int size, int *outLength); const char *tlsStrError(int rc); +int getClientCertificate(gsk_handle soc_handle, char *clientCertificate, unsigned int clientCertificateBufferSize, unsigned int *clientCertificateLength); #define TLS_ALLOC_ERROR (-1) From 31fe0d327dd4f4630dfd295726cda7e8e8f1ff68 Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Mon, 10 Apr 2023 15:52:22 -0500 Subject: [PATCH 04/18] reverting unintentional changes Signed-off-by: Jordan Filteau --- c/tls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/c/tls.c b/c/tls.c index cedf4801c..25a3ee31a 100644 --- a/c/tls.c +++ b/c/tls.c @@ -159,18 +159,18 @@ int tlsSocketInit(TlsEnvironment *env, TlsSocket **outSocket, int fd, bool isSer } char *label = env->settings->label; char *ciphers = env->settings->ciphers; - rc = gsk_secure_socket_open(env->envHandle, &socket->socketHandle); + rc = rc || gsk_secure_socket_open(env->envHandle, &socket->socketHandle); rc = rc || gsk_attribute_set_numeric_value(socket->socketHandle, GSK_FD, fd); if (label) { rc = rc || gsk_attribute_set_buffer(socket->socketHandle, GSK_KEYRING_LABEL, label, 0); } - rc = gsk_attribute_set_enum(socket->socketHandle, GSK_SESSION_TYPE, isServer ? GSK_SERVER_SESSION_WITH_CL_AUTH : GSK_CLIENT_SESSION); + rc = rc || gsk_attribute_set_enum(socket->socketHandle, GSK_SESSION_TYPE, isServer ? GSK_SERVER_SESSION_WITH_CL_AUTH : GSK_CLIENT_SESSION); if (ciphers) { rc = rc || gsk_attribute_set_buffer(socket->socketHandle, GSK_V3_CIPHER_SPECS_EXPANDED, ciphers, 0); rc = rc || gsk_attribute_set_enum(socket->socketHandle, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4); } rc = rc || gsk_attribute_set_callback(socket->socketHandle, GSK_IO_CALLBACK, &ioCallbacks); - rc = gsk_secure_socket_init(socket->socketHandle); + rc = rc || gsk_secure_socket_init(socket->socketHandle); if (rc == 0) { *outSocket = socket; } else { From eea40c9ad45962975d9edbb3a8395b490ceeeb5d Mon Sep 17 00:00:00 2001 From: James Struga Date: Wed, 3 May 2023 15:11:20 -0400 Subject: [PATCH 05/18] change LE_MAX_SUPPORTED_ZOS Signed-off-by: James Struga --- c/le.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/le.c b/c/le.c index 575dcdf77..833f8ab77 100644 --- a/c/le.c +++ b/c/le.c @@ -111,7 +111,7 @@ char *getCAA(void){ } #ifndef LE_MAX_SUPPORTED_ZOS -#define LE_MAX_SUPPORTED_ZOS 0x01020500u +#define LE_MAX_SUPPORTED_ZOS 0x01030100 #endif void abortIfUnsupportedCAA() { From 322880270331ad326bdda2c5b846c4bc596020a6 Mon Sep 17 00:00:00 2001 From: James Struga Date: Wed, 3 May 2023 15:20:40 -0400 Subject: [PATCH 06/18] missing u Signed-off-by: James Struga --- c/le.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/le.c b/c/le.c index 833f8ab77..2c658a834 100644 --- a/c/le.c +++ b/c/le.c @@ -111,7 +111,7 @@ char *getCAA(void){ } #ifndef LE_MAX_SUPPORTED_ZOS -#define LE_MAX_SUPPORTED_ZOS 0x01030100 +#define LE_MAX_SUPPORTED_ZOS 0x01030100u #endif void abortIfUnsupportedCAA() { From 2af59cc9017a49c2394105ef952fbeac554a7b25 Mon Sep 17 00:00:00 2001 From: JoeNemo Date: Thu, 27 Jul 2023 15:47:47 -0400 Subject: [PATCH 07/18] Fixed an inconsistent use of pointers in 64 bit case in dataset creation Signed-off-by: JoeNemo --- c/dynalloc.c | 10 +- tests/create1.json | 11 + tests/datasetCreate.c | 499 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 516 insertions(+), 4 deletions(-) create mode 100644 tests/create1.json create mode 100644 tests/datasetCreate.c diff --git a/c/dynalloc.c b/c/dynalloc.c index 73fcb24d1..3898e59e8 100644 --- a/c/dynalloc.c +++ b/c/dynalloc.c @@ -874,30 +874,32 @@ int setTextUnit(int type, int size, char* stringValue, int numValue, int key, } } +typedef TextUnit *__ptr32 *__ptr32 TextUnitPtrArray; + int dynallocNewDataset(TextUnit **inputTextUnit, int inputTextUnitCount, int *reasonCode) { ALLOC_STRUCT31( STRUCT31_NAME(below2G), STRUCT31_FIELDS( DynallocParms parms; - TextUnit ** __ptr32 textUnits; + TextUnitPtrArray textUnits; ) ); - below2G->textUnits = (TextUnit **)safeMalloc31(sizeof(TextUnit*) * inputTextUnitCount, "Text units array"); + below2G->textUnits = (TextUnitPtrArray)safeMalloc31(sizeof(TextUnit*__ptr32) * inputTextUnitCount, "Text units array"); if(below2G->textUnits == NULL) { return -1; } DynallocParms *parms = &below2G->parms; dynallocParmsInit(parms); - dynallocParmsSetTextUnits(parms, (TextUnit * __ptr32 *)below2G->textUnits, inputTextUnitCount); + dynallocParmsSetTextUnits(parms, (TextUnitPtrArray)below2G->textUnits, inputTextUnitCount); int rc; do { rc = 0; for (int i = 0; i < inputTextUnitCount; i++) { - below2G->textUnits[i] = inputTextUnit[i]; + below2G->textUnits[i] = (TextUnit *__ptr32)inputTextUnit[i]; if (below2G->textUnits[i] == NULL) { rc = -1; break; diff --git a/tests/create1.json b/tests/create1.json new file mode 100644 index 000000000..6f8936875 --- /dev/null +++ b/tests/create1.json @@ -0,0 +1,11 @@ +{"ndisp":"CATALOG", + "status":"NEW", + "space":"TRK", + "dsorg":"PO", + "lrecl":80, + "recfm":"FB", + "dir":20, + "prime":3, + "secnd":3, + "dsnt":"PDS", + "close":"true"} diff --git a/tests/datasetCreate.c b/tests/datasetCreate.c new file mode 100644 index 000000000..999f49dee --- /dev/null +++ b/tests/datasetCreate.c @@ -0,0 +1,499 @@ + +/* + 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. +*/ + + +#ifdef METTLE +#error Metal C not supported +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "zowetypes.h" +#include "alloc.h" +#include "utils.h" +#ifdef __ZOWE_OS_ZOS +#include "zos.h" +#endif +#include "bpxnet.h" +#include "collections.h" +#include "unixfile.h" +#include "socketmgmt.h" +#include "le.h" +#include "logging.h" +#include "scheduling.h" +#include "http.h" +#include "json.h" + +#include "dynalloc.h" + +/** + + Compiling and running this test + + 64 Bit Build + + xlclang -q64 -I ../h -D_OPEN_SYS_FILE_EXT=1 -D_XOPEN_SOURCE=600 -D_OPEN_THREADS=1 -DSUBPOOL=132 -DUSE_ZOWE_TLS=1 "-Wc,float(ieee),longname,langlvl(extc99),gonum,goff,ASM,asmlib('CEE.SCEEMAC','SYS1.MACLIB','SYS1.MODGEN')" -o datasetCreate datasetCreate.c ../c/json.c ../c/charsets.c ../c/dynalloc.c ../c/zosfile.c ../c/xlate.c ../c/timeutls.c ../c/utils.c ../c/alloc.c ../c/logging.c ../c/collections.c ../c/le.c ../c/recovery.c ../c/zos.c ../c/scheduling.c + + 31 Bit Build + + xlc -I ../h -D_OPEN_SYS_FILE_EXT=1 -D_XOPEN_SOURCE=600 -D_OPEN_THREADS=1 -DSUBPOOL=132 -DUSE_ZOWE_TLS=1 "-Wc,float(ieee),longname,langlvl(extc99),gonum,goff,ASM,asmlib('CEE.SCEEMAC','SYS1.MACLIB','SYS1.MODGEN')" -o datasetCreate31 datasetCreate.c ../c/json.c ../c/charsets.c ../c/dynalloc.c ../c/zosfile.c ../c/xlate.c ../c/timeutls.c ../c/utils.c ../c/alloc.c ../c/logging.c ../c/collections.c ../c/le.c ../c/recovery.c ../c/zos.c ../c/scheduling.c + + Running + + ./datasetCreate "//'MY.DS64.NAME'" + + ./datasetCreate31 "//'MY.DS31.NAME'" + */ + +#define DSPATH_PREFIX "//\'" +#define DSPATH_SUFFIX "\'" + +#define ERROR_DECODING_DATASET -2 +#define ERROR_CLOSING_DATASET -3 +#define ERROR_OPENING_DATASET -4 +#define ERROR_ALLOCATING_DATASET -5 +#define ERROR_DEALLOCATING_DATASET -6 +#define ERROR_UNDEFINED_LENGTH_DATASET -7 +#define ERROR_BAD_DATASET_NAME -8 +#define ERROR_INVALID_DATASET_NAME -9 +#define ERROR_INCORRECT_DATASET_TYPE -10 +#define ERROR_DATASET_NOT_EXIST -11 +#define ERROR_MEMBER_ALREADY_EXISTS -12 +#define ERROR_DATASET_ALREADY_EXIST -13 +#define ERROR_DATASET_OR_MEMBER_NOT_EXIST -14 +#define ERROR_VSAM_DATASET_DETECTED -15 +#define ERROR_DELETING_DATASET_OR_MEMBER -16 +#define ERROR_INVALID_JSON_BODY -17 +#define ERROR_COPY_NOT_SUPPORTED -18 +#define ERROR_COPYING_DATASET -19 + +#define INDEXED_DSCB 96 +#define LEN_THREE_BYTES 3 +#define LEN_ONE_BYTE 1 +#define VOLSER_SIZE 6 +#define CLASS_WRITER_SIZE 8 +#define TOTAL_TEXT_UNITS 23 + +#define IS_DAMEMBER_EMPTY($member) \ + (!memcmp(&($member), &(DynallocMemberName){" "}, sizeof($member))) + +static int bytesPerTrack=56664; +static int tracksPerCylinder=15; +static int bytesPerCylinder=849960; + + +typedef struct DatasetName_tag { + char value[44]; /* space-padded */ +} DatasetName; + +typedef struct DatasetMemberName_tag { + char value[8]; /* space-padded */ +} DatasetMemberName; + +typedef struct DDName_tag { + char value[8]; /* space-padded */ +} DDName; + +typedef struct Volser_tag { + char value[6]; /* space-padded */ +} Volser; + + +static void extractDatasetAndMemberName(const char *datasetPath, + DatasetName *dsn, + DatasetMemberName *memberName) { + + memset(&dsn->value, ' ', sizeof(dsn->value)); + memset(&memberName->value, ' ', sizeof(memberName->value)); + + size_t pathLength = strlen(datasetPath); + + const char *dsnStart = datasetPath + strlen(DSPATH_PREFIX); + const char *leftParen = strchr(datasetPath, '('); + + if (leftParen) { + memcpy(dsn->value, dsnStart, leftParen - dsnStart); + const char *rightParen = strchr(datasetPath, ')'); + memcpy(memberName->value, leftParen + 1, rightParen - leftParen - 1); + } else { + memcpy(dsn->value, dsnStart, + pathLength - strlen(DSPATH_PREFIX""DSPATH_SUFFIX)); + } + + for (int i = 0; i < sizeof(dsn->value); i++) { + dsn->value[i] = toupper(dsn->value[i]); + } + + for (int i = 0; i < sizeof(memberName->value); i++) { + memberName->value[i] = toupper(memberName->value[i]); + } + +} + +/* Returns a quantity of tracks or cylinders for dynalloc in case the user asked for bytes */ +/* Yes, these are approximations but if people really want exact numbers they should use cyl & trk */ +static int getDSSizeValueFromType(int quantity, char *spaceType) { + if (!strcmp(spaceType, "CYL")) { + return quantity; + } else if (!strcmp(spaceType, "TRK")) { + return quantity; + } else if (!strcmp(spaceType, "BYTE")) { + return quantity / bytesPerTrack; + } else if (!strcmp(spaceType, "KB")) { + return (quantity*1024) / bytesPerTrack; + } else if (!strcmp(spaceType, "MB")) { + return (quantity*1048576) / bytesPerCylinder; + } + return quantity; +} + +static int setDatasetAttributesForCreation(JsonObject *object, int *configsCount, TextUnit **inputTextUnit) { + JsonProperty *currentProp = jsonObjectGetFirstProperty(object); + Json *value = NULL; + int parmDefn = DALDSORG_NULL; + int type = TEXT_UNIT_NULL; + int rc = 0; + + parmDefn = DISP_NEW; //ONLY one for create + rc = setTextUnit(TEXT_UNIT_CHAR, 0, NULL, parmDefn, DALSTATS, configsCount, inputTextUnit); + + + // most parameters below explained here https://www.ibm.com/docs/en/zos/2.1.0?topic=dfsms-zos-using-data-sets + // or here https://www.ibm.com/docs/en/zos/2.1.0?topic=function-non-jcl-dynamic-allocation-functions + // or here https://www.ibm.com/docs/en/zos/2.1.0?topic=function-dsname-allocation-text-units + + while(currentProp != NULL){ + value = jsonPropertyGetValue(currentProp); + char *propString = jsonPropertyGetKey(currentProp); + + if(propString != NULL){ + errno = 0; + if (!strcmp(propString, "dsorg")) { + char *valueString = jsonAsString(value); + if (valueString != NULL) { + parmDefn = (!strcmp(valueString, "PS")) ? DALDSORG_PS : DALDSORG_PO; + rc = setTextUnit(TEXT_UNIT_INT16, 0, NULL, parmDefn, DALDSORG, configsCount, inputTextUnit); + } + } else if(!strcmp(propString, "blksz")) { + // https://www.ibm.com/docs/en/zos/2.1.0?topic=statement-blksize-parameter + int64_t valueInt = jsonAsInt64(value); + if(valueInt != 0){ + if (valueInt <= 0x7FF8 && valueInt >= 0) { //<-- If DASD, if tape, it can be 80000000 + type = TEXT_UNIT_INT16; + } else if (valueInt <= 0x80000000){ + type = TEXT_UNIT_LONGINT; + } + if(type != TEXT_UNIT_NULL) { + rc = setTextUnit(type, 0, NULL, valueInt, DALBLKSZ, configsCount, inputTextUnit); + } + } + } else if(!strcmp(propString, "lrecl")) { + int valueInt = jsonAsNumber(value); + if (valueInt == 0x8000 || (valueInt <= 0x7FF8 && valueInt >= 0)) { + rc = setTextUnit(TEXT_UNIT_INT16, 0, NULL, valueInt, DALLRECL, configsCount, inputTextUnit); + } + } else if(!strcmp(propString, "volser")) { + char *valueString = jsonAsString(value); + if (valueString != NULL) { + int valueStrLen = strlen(valueString); + if (valueStrLen <= VOLSER_SIZE){ + rc = setTextUnit(TEXT_UNIT_STRING, VOLSER_SIZE, &(valueString)[0], 0, DALVLSER, configsCount, inputTextUnit); + } + } + } else if(!strcmp(propString, "recfm")) { + char *valueString = jsonAsString(value); + if (valueString != NULL) { + int valueStrLen = strlen(valueString); + int setRECFM = 0; + if (indexOf(valueString, valueStrLen, 'A', 0) != -1){ + setRECFM = setRECFM | DALRECFM_A; + } + if (indexOf(valueString, valueStrLen, 'B', 0) != -1){ + setRECFM = setRECFM | DALRECFM_B; + } + if (indexOf(valueString, valueStrLen, 'V', 0) != -1){ + setRECFM = setRECFM | DALRECFM_V; + } + if (indexOf(valueString, valueStrLen, 'F', 0) != -1){ + setRECFM = setRECFM | DALRECFM_F; + } + if (indexOf(valueString, valueStrLen, 'U', 0) != -1){ + setRECFM = setRECFM | DALRECFM_U; + } + rc = setTextUnit(TEXT_UNIT_CHAR, 0, NULL, setRECFM, DALRECFM, configsCount, inputTextUnit); + } + } else if(!strcmp(propString, "blkln") + && !jsonObjectHasKey(object, "space")) { //mutually exclusive with daltrk, dalcyl + // https://www.ibm.com/docs/en/zos/2.1.0?topic=units-block-length-specification-key-0009 + int valueInt = jsonAsNumber(value); + if (valueInt <= 0xFFFF && valueInt >= 0){ + rc = setTextUnit(TEXT_UNIT_INT24, 0, NULL, valueInt, DALBLKLN, configsCount, inputTextUnit); + } + if (jsonObjectHasKey(object, "prime")) { //in tracks for blkln + int primeSize = jsonObjectGetNumber(object, "prime"); + if (primeSize <= 0xFFFFFF && primeSize >= 0) { + rc = setTextUnit(TEXT_UNIT_INT24, 0, NULL, primeSize, DALPRIME, configsCount, inputTextUnit); + } + } + if (jsonObjectHasKey(object, "secnd")) { //in tracks for blkln + int secondarySize = jsonObjectGetNumber(object, "secnd"); + if (secondarySize <= 0xFFFFFF && secondarySize >= 0) { + rc = setTextUnit(TEXT_UNIT_INT24, 0, NULL, secondarySize, DALSECND, configsCount, inputTextUnit); + } + } + } else if (!strcmp(propString, "ndisp")) { + char *valueString = jsonAsString(value); + if (valueString != NULL) { + if (!strcmp(valueString, "KEEP")){ + parmDefn = DISP_KEEP; + } else { + parmDefn = DISP_CATLG; + } + rc = setTextUnit(TEXT_UNIT_CHAR, 0, NULL, parmDefn, DALNDISP, configsCount, inputTextUnit); + } + } else if(!strcmp(propString, "strcls")) { + char *valueString = jsonAsString(value); + if (valueString != NULL) { + int valueStrLen = strlen(valueString); + if (valueStrLen <= CLASS_WRITER_SIZE){ + rc = setTextUnit(TEXT_UNIT_STRING, CLASS_WRITER_SIZE, &(valueString)[0], 0, DALSTCL, configsCount, inputTextUnit); + } + } + } else if(!strcmp(propString, "mngcls")) { + char *valueString = jsonAsString(value); + if (valueString != NULL) { + int valueStrLen = strlen(valueString); + if (valueStrLen <= CLASS_WRITER_SIZE){ + rc = setTextUnit(TEXT_UNIT_STRING, CLASS_WRITER_SIZE, &(valueString)[0], 0, DALMGCL, configsCount, inputTextUnit); + } + } + } else if(!strcmp(propString, "datacls")) { + char *valueString = jsonAsString(value); + if (valueString != NULL) { + int valueStrLen = strlen(valueString); + if (valueStrLen <= CLASS_WRITER_SIZE){ + rc = setTextUnit(TEXT_UNIT_STRING, CLASS_WRITER_SIZE, &(valueString)[0], 0, DALDACL, configsCount, inputTextUnit); + } + } + } else if(!strcmp(propString, "space")) { + char *spaceType = jsonAsString(value); + if (spaceType != NULL) { + if (!strcmp(spaceType, "CYL")) { + parmDefn = DALCYL; + } else if (!strcmp(spaceType, "TRK")) { + // https://www.ibm.com/docs/en/zos/2.1.0?topic=units-track-space-type-trk-specification-key-0007 + parmDefn = DALTRK; + } else if (!strcmp(spaceType, "BYTE")) { + parmDefn = DALTRK; + } else if (!strcmp(spaceType, "KB")) { + parmDefn = DALTRK; + } else if (!strcmp(spaceType, "MB")) { + parmDefn = DALCYL; + } + if(parmDefn != DALDSORG_NULL) { + rc = setTextUnit(TEXT_UNIT_BOOLEAN, 0, NULL, 0, parmDefn, configsCount, inputTextUnit); + } + if (jsonObjectHasKey(object, "prime")) { //in tracks for blkln + int primeSize = jsonObjectGetNumber(object, "prime"); + if (primeSize <= 0xFFFFFF && primeSize >= 0) { + rc = setTextUnit(TEXT_UNIT_INT24, 0, NULL, getDSSizeValueFromType(primeSize, spaceType), DALPRIME, configsCount, inputTextUnit); + } + } + if (jsonObjectHasKey(object, "secnd")) { //in tracks for blkln + int secondarySize = jsonObjectGetNumber(object, "secnd"); + if (secondarySize <= 0xFFFFFF && secondarySize >= 0) { + rc = setTextUnit(TEXT_UNIT_INT24, 0, NULL, getDSSizeValueFromType(secondarySize, spaceType), DALSECND, configsCount, inputTextUnit); + } + } + } + } else if(!strcmp(propString, "dir")) { + int valueInt = jsonAsNumber(value); + if (valueInt <= 0xFFFFFF && valueInt >= 0) { + rc = setTextUnit(TEXT_UNIT_INT24, 0, NULL, valueInt, DALDIR, configsCount, inputTextUnit); + } + } else if(!strcmp(propString, "avgr")) { + // https://www.ibm.com/docs/en/zos/2.1.0?topic=statement-avgrec-parameter + char *valueString = jsonAsString(value); + if (valueString != NULL) { + if (!strcmp(valueString, "M")) { + parmDefn = DALDSORG_MREC; + } else if (!strcmp(valueString, "K")) { + parmDefn = DALDSORG_KREC; + } else if (!strcmp(valueString, "U")) { + parmDefn = DALDSORG_UREC; + } + if(parmDefn != DALDSORG_NULL) { + rc = setTextUnit(TEXT_UNIT_CHAR, 0, NULL, parmDefn, DALAVGR, configsCount, inputTextUnit); + } + } + } else if(!strcmp(propString, "dsnt")) { + // https://www.ibm.com/docs/en/zos/2.3.0?topic=jcl-allocating-system-managed-data-sets + char *valueString = jsonAsString(value); + if (valueString != NULL) { + if (!strcmp(valueString, "PDSE")) { + parmDefn = DALDSORG_PDSE; + } else if (!strcmp(valueString, "PDS")) { + parmDefn = DALDSORG_PDS; + } else if (!strcmp(valueString, "HFS")) { + parmDefn = DALDSORG_HFS; + } else if (!strcmp(valueString, "EXTREQ")) { + parmDefn = DALDSORG_EXTREQ; + } else if (!strcmp(valueString, "EXTPREF")) { + parmDefn = DALDSORG_EXTPREF; + } else if (!strcmp(valueString, "BASIC")) { + parmDefn = DALDSORG_BASIC; + } else if (!strcmp(valueString, "LARGE")) { + parmDefn = DALDSORG_LARGE; + } + if(parmDefn != DALDSORG_NULL) { + rc = setTextUnit(TEXT_UNIT_CHAR, 0, NULL, parmDefn, DALDSNT, configsCount, inputTextUnit); + } + } + } + + } + if(rc == -1) { + break; + } + currentProp = jsonObjectGetNextProperty(currentProp); + parmDefn = DALDSORG_NULL; + type = TEXT_UNIT_NULL; + } + return rc; +} + +static int createDataset(char* absolutePath, Json *attributesJSON, int* reasonCode) { + #ifdef __ZOWE_OS_ZOS + DatasetName datasetName; + DatasetMemberName memberName; + extractDatasetAndMemberName(absolutePath, &datasetName, &memberName); + + DynallocDatasetName daDatasetName; + DynallocMemberName daMemberName; + memcpy(daDatasetName.name, datasetName.value, sizeof(daDatasetName.name)); + memcpy(daMemberName.name, memberName.value, sizeof(daMemberName.name)); + + DynallocDDName daDDName = {.name = "????????"}; + + int daRC = RC_DYNALLOC_OK, daSysReturnCode = 0, daSysReasonCode = 0; + + bool isMemberEmpty = IS_DAMEMBER_EMPTY(daMemberName); + + if(!isMemberEmpty){ + printf("this test does not make dataset members yet\n"); + return 12; + } + + int configsCount = 0; + char ddNameBuffer[DD_NAME_LEN+1] = "MVD00000"; + TextUnit *inputTextUnit[TOTAL_TEXT_UNITS] = {NULL}; + printf("DDNAME buffer 0x%p '%s'\n",ddNameBuffer,ddNameBuffer); + + ShortLivedHeap *slh = makeShortLivedHeap(0x10000,0x10); + char errorBuffer[2048]; + + int returnCode = 0; + if (jsonIsObject(attributesJSON)){ + JsonObject * jsonObject = jsonAsObject(attributesJSON); + returnCode = setTextUnit(TEXT_UNIT_STRING, DATASET_NAME_LEN, &datasetName.value[0], 0, DALDSNAM, &configsCount, inputTextUnit); + if(returnCode == 0) { + returnCode = setTextUnit(TEXT_UNIT_STRING, DD_NAME_LEN, ddNameBuffer, 0, DALDDNAM, &configsCount, inputTextUnit); + } + if(returnCode == 0) { + returnCode = setDatasetAttributesForCreation(jsonObject, &configsCount, inputTextUnit); + } + } + + if (returnCode == 0) { + returnCode = dynallocNewDataset(inputTextUnit, configsCount, reasonCode); + printf("dND ret=%d reason %d 0x%x\n",returnCode, *reasonCode, *reasonCode); + int ddNumber = 1; + while (*reasonCode==0x4100000 && ddNumber < 100000) { + sprintf(ddNameBuffer, "MVD%05d", ddNumber); + int ddconfig = 1; + setTextUnit(TEXT_UNIT_STRING, DD_NAME_LEN, ddNameBuffer, 0, DALDDNAM, &ddconfig, inputTextUnit); + returnCode = dynallocNewDataset(inputTextUnit, configsCount, reasonCode); + ddNumber++; + } + } + + if (returnCode) { + zowelog(NULL, LOG_COMP_DATASERVICE, ZOWE_LOG_WARNING, + "error: ds alloc dsn=\'%44.44s\' dd=\'%8.8s\', sysRC=%d, sysRSN=0x%08X\n", + daDatasetName.name, ddNameBuffer, returnCode, *reasonCode); + printf("Unable to allocate a DD for Creating New Dataset\n"); + SLHFree(slh); + return ERROR_ALLOCATING_DATASET; + } + + memcpy(daDDName.name, ddNameBuffer, DD_NAME_LEN); + daRC = dynallocUnallocDatasetByDDName(&daDDName, DYNALLOC_UNALLOC_FLAG_NONE, &returnCode, reasonCode); + if (daRC != RC_DYNALLOC_OK) { + zowelog(NULL, LOG_COMP_DATASERVICE, ZOWE_LOG_WARNING, + "error: ds unalloc dsn=\'%44.44s\' dd=\'%8.8s\', rc=%d sysRC=%d, sysRSN=0x%08X\n", + daDatasetName.name, daDDName.name, daRC, returnCode, *reasonCode); + printf("Unable to deallocate DDNAME"); + SLHFree(slh); + return ERROR_DEALLOCATING_DATASET; + } + SLHFree(slh); + return 0; + #endif +} + + +int main(int argc, char **argv){ + LoggingContext *loggingContext = makeLoggingContext(); + +#ifdef __ZOWE_OS_WINDOWS + int stdoutFD = _fileno(stdout); +#else + int stdoutFD = fileno(stdout); +#endif + + if (argc < 3){ + printf("please supply a dataset name and attributes filename\n"); + } + char *datasetName = argv[1]; + char *attributesFilename = argv[2]; + int errorBufferSize = 1024; + char *errorBuffer = safeMalloc(errorBufferSize,"ErrorBuffer"); + memset(errorBuffer,0,errorBufferSize); + + ShortLivedHeap *slh = makeShortLivedHeap(0x10000, 100); + + Json *attributes = jsonParseFile2(slh,attributesFilename,errorBuffer,errorBufferSize); + if (attributes == NULL){ + printf("Json parse fail in %s, with error '%s'\n",attributesFilename,errorBuffer); + return 12; + } else{ + printf("creation attributes parsed as:\n"); + jsonPrinter *p = makeJsonPrinter(stdoutFD); + jsonEnablePrettyPrint(p); + jsonPrint(p,attributes); + int reasonCode = 0; + int status = createDataset(datasetName, attributes, &reasonCode); + printf("create status = %d reason=%d\n",status, reasonCode); + } + + + return 0; +} From 0e83a2c84dd3468384965bab9f3061784a1f9179 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Thu, 27 Jul 2023 16:17:42 -0400 Subject: [PATCH 08/18] Allow bypassing zos version check with env var ZWE_zowe_launcher_unsafeDisableZosVersionCheck Signed-off-by: 1000TurquoisePogs --- c/le.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/c/le.c b/c/le.c index 575dcdf77..09c7dc034 100644 --- a/c/le.c +++ b/c/le.c @@ -120,9 +120,15 @@ void abortIfUnsupportedCAA() { unsigned int zosVersion = ecvt->ecvtpseq; #ifndef METTLE if (zosVersion > LE_MAX_SUPPORTED_ZOS) { - printf("error: z/OS version = 0x%08X, max supported version = 0x%08X - " - "CAA fields require verification\n", zosVersion, LE_MAX_SUPPORTED_ZOS); - abort(); + const char *continueWithWarning = getenv("ZWE_zowe_launcher_unsafeDisableZosVersionCheck"); + if (!strcmp(continueWithWarning, "true")) { + printf("warning: z/OS version = 0x%08X, max supported version = 0x%08X - " + "CAA fields require verification\n", zosVersion, LE_MAX_SUPPORTED_ZOS); + } else { + printf("error: z/OS version = 0x%08X, max supported version = 0x%08X - " + "CAA fields require verification\n", zosVersion, LE_MAX_SUPPORTED_ZOS); + abort(); + } } #else /* Metal uses its own copy of CAA, reserved fields will always be available */ From b7e38303089ea22944cc065f07750b0214cf93f1 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Thu, 3 Aug 2023 16:29:11 -0400 Subject: [PATCH 09/18] Move WTO code from metal.c to zos.c Signed-off-by: Leanid Astrakou --- c/zos.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/c/zos.c b/c/zos.c index da926e628..dbff8b321 100644 --- a/c/zos.c +++ b/c/zos.c @@ -1469,6 +1469,87 @@ int safStat(int options, char *safClass, char *copy, int copyLength, int *racfSt get current TCB AC */ +/* begin WTO SECTION + +TODO(?): This is code duplication from metalio.c but the following works for LE & metal */ + +typedef struct WTO2Common31_tag{ + char replyBufferLength; /* 31-bit WTOR only, else 0 */ + char length; /* message length +4 */ + char mcsFlags1; + char mcsFlags2; +} WTO2Common31; + +void message(char *message){ + + ALLOC_STRUCT31( + STRUCT31_NAME(below2G), + STRUCT31_FIELDS( + WTO2Common31 common; + char text[126]; /* Maximum length of WTO text is 126 - ABEND D23-xxxx0005 if longer than 126 */ + ) + ); + + int len = strlen(message); + if (len>sizeof(below2G->text)) + len=sizeof(below2G->text); + + below2G->common.length = len+sizeof(below2G->common); /* +4 for header */ + memcpy(below2G->text,message,len); + + __asm(ASM_PREFIX + " WTO MF=(E,(%[wtobuf])) \n" + : + :[wtobuf]"NR:r1"(&below2G->common) + :"r0","r1","r15"); + + FREE_STRUCT31( + STRUCT31_NAME(below2G) + ); +} + +#define WTO_MAX_SIZE 126 +void wtoPrintf(char *formatString, ...){ + char text[WTO_MAX_SIZE+1]; /* Allow for trailing null character */ + va_list argPointer; + int cnt; + + for (int pass=0; pass<2; pass++){ + + /* The resulting text string from vsnprintf is unpredictable if + there is an error in the format string or arguments. In that + case we will set the output text area to null, repeat the + vsnprintf, and then find the length of the null terminated + string. This avoids initializing the output text area prior + to every successful request. + */ + + va_start(argPointer,formatString); + cnt = vsnprintf(text,sizeof(text),formatString,argPointer); + va_end(argPointer); + + if (cnt<0){ + if (pass==0) + memset(text,0,sizeof(text)); /* Clear the text buffer before retrying the vsnprint request */ + else { + text[WTO_MAX_SIZE] = 0; /* Ensure strlen stops at the end of the text buffer */ + cnt = strlen(text); /* Find the end of the text string */ + } + } else + break; /* vsnprintf did not return an error - cnt was set */ + } + if (cnt>WTO_MAX_SIZE) /* If more data to format than the text buffer length */ + cnt = WTO_MAX_SIZE; /* Truncate the formatted length to the text buffer length */ + + /* We never want to include a final \n character in the WTO text */ + + if (cnt>0 && text[cnt-1] == '\n') /* If text ends with \n */ + text[cnt-1] = 0; /* Change it into a null character */ + + message(text); +} + +/* end WTO SECTION */ /* LOCATE/CAMLIST */ From 60382d130ce08f38e68e8cf34ff1af8d18114dbd Mon Sep 17 00:00:00 2001 From: struga0258 Date: Fri, 4 Aug 2023 14:55:16 +0000 Subject: [PATCH 10/18] v2.11.0 Signed-off-by: struga0258 --- build/configmgr.proj.env | 2 +- manifest.template.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/configmgr.proj.env b/build/configmgr.proj.env index 93945819e..06d81e370 100644 --- a/build/configmgr.proj.env +++ b/build/configmgr.proj.env @@ -1,5 +1,5 @@ PROJECT="configmgr" -VERSION=2.10.0 +VERSION=2.11.0 DEPS="QUICKJS LIBYAML" QUICKJS="quickjs" diff --git a/manifest.template.yaml b/manifest.template.yaml index 0131e2e36..4bf312223 100644 --- a/manifest.template.yaml +++ b/manifest.template.yaml @@ -1,7 +1,7 @@ --- name: zowe-common-c -version: 2.10.0 +version: 2.11.0 homepage: https://zowe.org keywords: From 52f3a4c84f5f3685d6e6ce74d17462c90f5cf21b Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Wed, 9 Aug 2023 12:38:05 -0400 Subject: [PATCH 11/18] Renaming methods Signed-off-by: Leanid Astrakou --- c/zos.c | 6 +++--- h/zos.h | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/c/zos.c b/c/zos.c index dbff8b321..9a7969012 100644 --- a/c/zos.c +++ b/c/zos.c @@ -1480,7 +1480,7 @@ typedef struct WTO2Common31_tag{ char mcsFlags2; } WTO2Common31; -void message(char *message){ +void message2(char *message){ ALLOC_STRUCT31( STRUCT31_NAME(below2G), @@ -1509,7 +1509,7 @@ void message(char *message){ } #define WTO_MAX_SIZE 126 -void wtoPrintf(char *formatString, ...){ +void wtoPrintfMetal(char *formatString, ...){ char text[WTO_MAX_SIZE+1]; /* Allow for trailing null character */ va_list argPointer; int cnt; @@ -1546,7 +1546,7 @@ void wtoPrintf(char *formatString, ...){ if (cnt>0 && text[cnt-1] == '\n') /* If text ends with \n */ text[cnt-1] = 0; /* Change it into a null character */ - message(text); + message2(text); } /* end WTO SECTION */ diff --git a/h/zos.h b/h/zos.h index b8b03a331..b43ef145e 100644 --- a/h/zos.h +++ b/h/zos.h @@ -1529,6 +1529,10 @@ DSAB *getDSAB(char *ddname); int dsabIsOMVS(DSAB *dsab); +void message2(char *message); + +void wtoPrintfMetal(char *formatString, ...); + int locate(char *dsn, int *volserCount, char *firstVolser); /* From 43802703c337b537c9f3d8d171883298fe5b9dcc Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Fri, 11 Aug 2023 15:31:41 -0500 Subject: [PATCH 12/18] using a flag to determine type of saf verify; removing dead code in tls.c; simplying logic for loop in tls.c Signed-off-by: Jordan Filteau --- c/httpserver.c | 9 +++++---- c/tls.c | 31 +++++++++---------------------- h/http.h | 1 + 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/c/httpserver.c b/c/httpserver.c index ef4fba1c2..a841f1c0b 100644 --- a/c/httpserver.c +++ b/c/httpserver.c @@ -2653,7 +2653,7 @@ static int safAuthenticate(HttpService *service, HttpRequest *request, AuthRespo } else if (authDataFound){ ACEE *acee = NULL; strupcase(request->username); /* upfold username */ - if (request->password == NULL) { + if (!(request->flags & HTTP_REQUEST_NO_PASSWORD)) { zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG3, "Password is null. Calling safAuthenticate without a password.\n"); } else { #ifdef ENABLE_DANGEROUS_AUTH_TRACING @@ -2679,7 +2679,7 @@ static int safAuthenticate(HttpService *service, HttpRequest *request, AuthRespo CrossMemoryServerName *privilegedServerName = getConfiguredProperty(service->server, HTTP_SERVER_PRIVILEGED_SERVER_PROPERTY); int pwdCheckRC = 0, pwdCheckRSN = 0; - if (request->password != NULL) { + if (!(request->flags & HTTP_REQUEST_NO_PASSWORD)) { pwdCheckRC = zisCheckUsernameAndPassword(privilegedServerName, request->username, request->password, &status); authResponse->type = AUTH_TYPE_RACF; @@ -3202,12 +3202,13 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * #define TLS_USERID_LENGTH 9 char userid[TLS_USERID_LENGTH] = {0}; int racfReturnCode = 0, racfReasonCode = 0; - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "There was no token or credentials found in the request. Server is attempting to map the client certificate.\n"); + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "There was no token or credentials found in the request. Server is attempting to map the client certificate.\n"); int safReturnCode = getUseridByCertificate(clientCertificate, clientCertificateLength, userid, &racfReturnCode, &racfReasonCode); if (safReturnCode == 0) { request->username = userid; - zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "Found user '%s' from client certificate.\n", request->username); + zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "Found user '%s' from client certificate.\n", request->username); request->password = NULL; + request->flags = HTTP_REQUEST_NO_PASSWORD; // null password with a valid user tells the server we authenticated with a certificate authDataFound = TRUE; } else { diff --git a/c/tls.c b/c/tls.c index 25a3ee31a..2264d2da2 100644 --- a/c/tls.c +++ b/c/tls.c @@ -17,6 +17,8 @@ int getClientCertificate(gsk_handle soc_handle, char *clientCertificate, unsigned int clientCertificateBufferSize, unsigned int *clientCertificateLength) { + int rc = 0; + if (clientCertificate == NULL || clientCertificateBufferSize <= 0) { return -1; } @@ -27,26 +29,28 @@ int getClientCertificate(gsk_handle soc_handle, char *clientCertificate, unsigne gsk_cert_data_elem *gskCertificateArray = NULL; int gskCertificateArrayElementCount = 0; - int rc = gsk_attribute_get_cert_info(soc_handle, GSK_PARTNER_CERT_INFO, &gskCertificateArray, &gskCertificateArrayElementCount); + rc = gsk_attribute_get_cert_info(soc_handle, GSK_PARTNER_CERT_INFO, &gskCertificateArray, &gskCertificateArrayElementCount); if (rc != 0) { return rc; } - gsk_cert_data_elem *tmp = gskCertificateArray; - - for (int i = 0; i++ < gskCertificateArrayElementCount; tmp++) { + for (int i = 0; i < gskCertificateArrayElementCount; i++) { + gsk_cert_data_elem *tmp = &gskCertificateArray[i]; if (tmp->cert_data_id == CERT_BODY_DER) { if (clientCertificateBufferSize >= tmp->cert_data_l) { memcpy(clientCertificate, tmp->cert_data_p, tmp->cert_data_l); *clientCertificateLength = tmp->cert_data_l; + } else { + rc = -1; /* tls rc are all positive */ } + break; } } gsk_free_cert_data(gskCertificateArray, gskCertificateArrayElementCount); - return 0; + return rc; } int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { @@ -64,22 +68,10 @@ int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_PROTOCOL_TLSV1_2, GSK_PROTOCOL_TLSV1_2_ON); rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_SERVER_EPHEMERAL_DH_GROUP_SIZE, GSK_SERVER_EPHEMERAL_DH_GROUP_SIZE_2048); - /* - * Don't validate certificates, maybe put behind a dangerous ifdef. - * - * rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_TYPE, GSK_CLIENT_AUTH_PASSTHRU_TYPE); - */ - #ifdef DEV_DO_NOT_VALIDATE_CLIENT_CERTIFICATES rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_TYPE, GSK_CLIENT_AUTH_PASSTHRU_TYPE); #endif - /* - * Only allow requests with client certificates, maybe put behind a different ifdef. - * - * rc = rc || gsk_attribute_set_enum(env->envHandle, GSK_CLIENT_AUTH_ALERT, GSK_CLIENT_AUTH_NOCERT_ALERT_ON); - */ - rc = rc || gsk_attribute_set_buffer(env->envHandle, GSK_KEYRING_FILE, settings->keyring, 0); if (settings->stash) { rc = rc || gsk_attribute_set_buffer(env->envHandle, GSK_KEYRING_STASH_FILE, settings->stash, 0); @@ -94,7 +86,6 @@ int tlsInit(TlsEnvironment **outEnv, TlsSettings *settings) { safeFree((char*)env, sizeof(*env)); *outEnv = NULL; } - //printf("tlsInit - rc=%d\n", rc); return rc; } @@ -102,7 +93,6 @@ int tlsDestroy(TlsEnvironment *env) { int rc = 0; rc = gsk_environment_close(env->envHandle); safeFree((char*)env, sizeof(*env)); - //printf("tlsDestroy - rc=%d\n", rc); return rc; } @@ -125,7 +115,6 @@ static int secureSocketRecv(int fd, void *data, int len, char *userData) { break; } } - //printf("secureSocketRecv = %d\n", rc); return rc; } @@ -146,7 +135,6 @@ static int secureSocketSend(int fd, void *data, int len, char *userData) { break; } } - //printf("secureSocketSend = %d\n", rc); return rc; } @@ -177,7 +165,6 @@ int tlsSocketInit(TlsEnvironment *env, TlsSocket **outSocket, int fd, bool isSer safeFree((char*)socket, sizeof(*socket)); *outSocket = NULL; } - //printf("tlsSocketInit - rc=%d\n", rc); return rc; } diff --git a/h/http.h b/h/http.h index b46114ab3..f7462c7c6 100644 --- a/h/http.h +++ b/h/http.h @@ -126,6 +126,7 @@ typedef struct HttpRequest_tag{ Socket *socket; BufferedInputStream *input; int flags; +#define HTTP_REQUEST_NO_PASSWORD 0x01 int characterEncoding; int contentLength; /* -1 if unknown */ char *contentType; From 28accacb730d50f0a431eeacc3bc5f9e4c90e7a0 Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Fri, 11 Aug 2023 15:39:08 -0500 Subject: [PATCH 13/18] using a bigger buffer for client certificate. Signed-off-by: Jordan Filteau --- c/httpserver.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/c/httpserver.c b/c/httpserver.c index a841f1c0b..729988432 100644 --- a/c/httpserver.c +++ b/c/httpserver.c @@ -3176,14 +3176,12 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * } } - /* Doubtful that it would be greater than 8k... */ +#define TLS_CLIENT_CERTIFICATE_MAX_LENGTH 65536 -#define TLS_CLIENT_CERTIFICATE_MAX_LENGTH 8000 - - char clientCertificate[TLS_CLIENT_CERTIFICATE_MAX_LENGTH] = {0}; + char *clientCertificate = safeMalloc(TLS_CLIENT_CERTIFICATE_MAX_LENGTH, "Client Certificate"); unsigned int clientCertificateLength = 0; - int rc = getClientCertificate(response->socket->tlsSocket->socketHandle, clientCertificate, sizeof(clientCertificate), &clientCertificateLength); + int rc = getClientCertificate(response->socket->tlsSocket->socketHandle, clientCertificate, TLS_CLIENT_CERTIFICATE_MAX_LENGTH, &clientCertificateLength); if (rc != 0) { zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "getClientCertificate - %d.\n", rc); } @@ -3209,7 +3207,6 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_DEBUG, "Found user '%s' from client certificate.\n", request->username); request->password = NULL; request->flags = HTTP_REQUEST_NO_PASSWORD; - // null password with a valid user tells the server we authenticated with a certificate authDataFound = TRUE; } else { zowelog(NULL, LOG_COMP_HTTPSERVER, ZOWE_LOG_INFO, "No user was found for client certificate. (rc = 0x%x racfRC = 0x%x racfRSN = 0x%x\n", safReturnCode, racfReturnCode, racfReasonCode); @@ -3219,6 +3216,11 @@ static int serviceAuthNativeWithSessionToken(HttpService *service, HttpRequest * } } + if (clientCertificate) { + safeFree(clientCertificate, TLS_CLIENT_CERTIFICATE_MAX_LENGTH); + clientCertificate = NULL; + } + response->sessionCookie = NULL; AUTH_TRACE("AUTH: tokenCookieText: %s\n",(tokenCookieText ? tokenCookieText : "")); From a887008d898f6adf50969db5467fd4aba095118a Mon Sep 17 00:00:00 2001 From: Jordan Filteau Date: Sun, 13 Aug 2023 15:03:19 -0500 Subject: [PATCH 14/18] fixing compiler warning Signed-off-by: Jordan Filteau --- c/tls.c | 1 + 1 file changed, 1 insertion(+) diff --git a/c/tls.c b/c/tls.c index 2264d2da2..377b68cc0 100644 --- a/c/tls.c +++ b/c/tls.c @@ -8,6 +8,7 @@ Copyright Contributors to the Zowe Project. */ #include +#include #include #include #include "alloc.h" From 29a5560a76c06dd288cb4381c4802fc23dbd7ab0 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Thu, 24 Aug 2023 04:54:35 -0400 Subject: [PATCH 15/18] Removed code duplication and added shim methods Signed-off-by: Leanid Astrakou --- c/metalio.c | 68 ++++++----------------------------------------------- c/zos.c | 2 +- h/zos.h | 2 +- 3 files changed, 9 insertions(+), 63 deletions(-) diff --git a/c/metalio.c b/c/metalio.c index 320651e0e..a0bc91ab8 100644 --- a/c/metalio.c +++ b/c/metalio.c @@ -378,30 +378,7 @@ SYSOUT *getSYSOUTStruct(char *ddname, SYSOUT *existingSysout, char *buffer){ */ void message(char *message){ - ALLOC_STRUCT31( - STRUCT31_NAME(below2G), - STRUCT31_FIELDS( - WTOCommon31 common; - char text[126]; /* Maximum length of WTO text is 126 - ABEND D23-xxxx0005 if longer than 126 */ - ) - ); - - int len = strlen(message); - if (len>sizeof(below2G->text)) - len=sizeof(below2G->text); - - below2G->common.length = len+sizeof(below2G->common); /* +4 for header */ - memcpy(below2G->text,message,len); - - __asm(ASM_PREFIX - " WTO MF=(E,(%[wtobuf])) \n" - : - :[wtobuf]"NR:r1"(&below2G->common) - :"r0","r1","r15"); - - FREE_STRUCT31( - STRUCT31_NAME(below2G) - ); + message2(message); } /* this can only be called from authorized callers */ @@ -485,44 +462,13 @@ void sendWTO(int descriptorCode, int routingCode, char *message, int length){ } #define WTO_MAX_SIZE 126 -void wtoPrintf(char *formatString, ...){ - char text[WTO_MAX_SIZE+1]; /* Allow for trailing null character */ +void wtoPrintf(char *formatString, ...) { va_list argPointer; - int cnt; - - for (int pass=0; pass<2; pass++){ - - /* The resulting text string from vsnprintf is unpredictable if - there is an error in the format string or arguments. In that - case we will set the output text area to null, repeat the - vsnprintf, and then find the length of the null terminated - string. This avoids initializing the output text area prior - to every successful request. - */ - - va_start(argPointer,formatString); - cnt = vsnprintf(text,sizeof(text),formatString,argPointer); - va_end(argPointer); - - if (cnt<0){ - if (pass==0) - memset(text,0,sizeof(text)); /* Clear the text buffer before retrying the vsnprint request */ - else { - text[WTO_MAX_SIZE] = 0; /* Ensure strlen stops at the end of the text buffer */ - cnt = strlen(text); /* Find the end of the text string */ - } - } else - break; /* vsnprintf did not return an error - cnt was set */ - } - if (cnt>WTO_MAX_SIZE) /* If more data to format than the text buffer length */ - cnt = WTO_MAX_SIZE; /* Truncate the formatted length to the text buffer length */ - - /* We never want to include a final \n character in the WTO text */ - - if (cnt>0 && text[cnt-1] == '\n') /* If text ends with \n */ - text[cnt-1] = 0; /* Change it into a null character */ - - message(text); + va_start(argPointer, formatString); + + wtoPrintf3(formatString, argPointer); + + va_end(argPointer); } void authWTOPrintf(char *formatString, ...){ diff --git a/c/zos.c b/c/zos.c index 9a7969012..12b631543 100644 --- a/c/zos.c +++ b/c/zos.c @@ -1509,7 +1509,7 @@ void message2(char *message){ } #define WTO_MAX_SIZE 126 -void wtoPrintfMetal(char *formatString, ...){ +void wtoPrintf3(char *formatString, ...) { char text[WTO_MAX_SIZE+1]; /* Allow for trailing null character */ va_list argPointer; int cnt; diff --git a/h/zos.h b/h/zos.h index b43ef145e..71819f9c5 100644 --- a/h/zos.h +++ b/h/zos.h @@ -1531,7 +1531,7 @@ int dsabIsOMVS(DSAB *dsab); void message2(char *message); -void wtoPrintfMetal(char *formatString, ...); +void wtoPrintf3(char *formatString, ...); int locate(char *dsn, int *volserCount, char *firstVolser); From 0d0fba4a99dbd958a076c4be545eb372fc12f010 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Thu, 24 Aug 2023 05:32:30 -0400 Subject: [PATCH 16/18] Added CHANGELOG Signed-off-by: Leanid Astrakou --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c105de66e..e669afff5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Zowe Common C Changelog +## `2.11.0` + +- WTO printing methods have been moved to zos.c to be more available as utilities (for ex: for the Launcher) + ## `2.10.0` - Feature: The configmgr can now use the 'zos' module in YAML config templates. The 'zos' module is only added when run on ZOS. For a list of available functions, see https://github.com/zowe/zowe-install-packaging/blob/v2.x/staging/build/zwe/types/%40qjstypes/zos.d.ts (#384) From 8761e59d191c4e2ae67136b984be3535920c3323 Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Mon, 28 Aug 2023 14:32:36 -0400 Subject: [PATCH 17/18] Addressed more code review Signed-off-by: Leanid Astrakou --- c/metalio.c | 1 + c/zos.c | 13 ++----------- h/metalio.h | 7 ------- h/zos.h | 7 +++++++ 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/c/metalio.c b/c/metalio.c index a0bc91ab8..8cc0bca75 100644 --- a/c/metalio.c +++ b/c/metalio.c @@ -55,6 +55,7 @@ #include "qsam.h" #include "metalio.h" #include "alloc.h" +#include "zos.h" static int isopen(void * dcbptr) { diff --git a/c/zos.c b/c/zos.c index 12b631543..74923d87f 100644 --- a/c/zos.c +++ b/c/zos.c @@ -1469,23 +1469,14 @@ int safStat(int options, char *safClass, char *copy, int copyLength, int *racfSt get current TCB AC */ -/* begin WTO SECTION - -TODO(?): This is code duplication from metalio.c but the following works for LE & metal */ - -typedef struct WTO2Common31_tag{ - char replyBufferLength; /* 31-bit WTOR only, else 0 */ - char length; /* message length +4 */ - char mcsFlags1; - char mcsFlags2; -} WTO2Common31; +/* begin WTO SECTION */ void message2(char *message){ ALLOC_STRUCT31( STRUCT31_NAME(below2G), STRUCT31_FIELDS( - WTO2Common31 common; + WTOCommon31 common; char text[126]; /* Maximum length of WTO text is 126 - ABEND D23-xxxx0005 if longer than 126 */ ) ); diff --git a/h/metalio.h b/h/metalio.h index 7429f550a..cd78cbe53 100644 --- a/h/metalio.h +++ b/h/metalio.h @@ -70,13 +70,6 @@ typedef struct WTORPrefix31_tag{ char *replayECBAddress; } WTORPrefix31; -typedef struct WTOCommon31_tag{ - char replyBufferLength; /* 31-bit WTOR only, else 0 */ - char length; /* message length +4 */ - char mcsFlags1; - char mcsFlags2; -} WTOCommon31; - #define WTO_ROUTE_CODE_OPERATOR_ACTION 1 #define WTO_ROUTE_CODE_OPERATOR_INFORMATION 2 #define WTO_ROUTE_CODE_TAPE_POOL 3 diff --git a/h/zos.h b/h/zos.h index 71819f9c5..2e9a30f67 100644 --- a/h/zos.h +++ b/h/zos.h @@ -1522,6 +1522,13 @@ typedef struct IDTA_tag { char reserved[8]; } IDTA; +typedef struct WTOCommon31_tag{ + char replyBufferLength; /* 31-bit WTOR only, else 0 */ + char length; /* message length +4 */ + char mcsFlags1; + char mcsFlags2; +} WTOCommon31; + ZOWE_PRAGMA_PACK_RESET DSAB *getDSAB(char *ddname); From d0c1ce93c2658c47ca8a772aed309f49d99ac84a Mon Sep 17 00:00:00 2001 From: Leanid Astrakou Date: Tue, 29 Aug 2023 11:06:19 -0400 Subject: [PATCH 18/18] Better method name + better const usage Signed-off-by: Leanid Astrakou --- c/metalio.c | 2 +- c/zos.c | 6 +++--- h/zos.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/c/metalio.c b/c/metalio.c index 8cc0bca75..9b6c45edf 100644 --- a/c/metalio.c +++ b/c/metalio.c @@ -379,7 +379,7 @@ SYSOUT *getSYSOUTStruct(char *ddname, SYSOUT *existingSysout, char *buffer){ */ void message(char *message){ - message2(message); + wtoMessage(message); } /* this can only be called from authorized callers */ diff --git a/c/zos.c b/c/zos.c index 74923d87f..2a5879198 100644 --- a/c/zos.c +++ b/c/zos.c @@ -1471,7 +1471,7 @@ int safStat(int options, char *safClass, char *copy, int copyLength, int *racfSt /* begin WTO SECTION */ -void message2(char *message){ +void wtoMessage(const char *message){ ALLOC_STRUCT31( STRUCT31_NAME(below2G), @@ -1500,7 +1500,7 @@ void message2(char *message){ } #define WTO_MAX_SIZE 126 -void wtoPrintf3(char *formatString, ...) { +void wtoPrintf3(const char *formatString, ...) { char text[WTO_MAX_SIZE+1]; /* Allow for trailing null character */ va_list argPointer; int cnt; @@ -1537,7 +1537,7 @@ void wtoPrintf3(char *formatString, ...) { if (cnt>0 && text[cnt-1] == '\n') /* If text ends with \n */ text[cnt-1] = 0; /* Change it into a null character */ - message2(text); + wtoMessage(text); } /* end WTO SECTION */ diff --git a/h/zos.h b/h/zos.h index 2e9a30f67..1daba3f21 100644 --- a/h/zos.h +++ b/h/zos.h @@ -1536,9 +1536,9 @@ DSAB *getDSAB(char *ddname); int dsabIsOMVS(DSAB *dsab); -void message2(char *message); +void wtoMessage(const char *message); -void wtoPrintf3(char *formatString, ...); +void wtoPrintf3(const char *formatString, ...); int locate(char *dsn, int *volserCount, char *firstVolser);