Skip to content

Commit a660eb8

Browse files
authored
Merge pull request #175 from Mainframe-Renewal-Project/dev
2 parents a77a807 + 229dc63 commit a660eb8

File tree

9 files changed

+110
-32
lines changed

9 files changed

+110
-32
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
cmake_minimum_required(VERSION 3.24)
4444

4545
project(sear C CXX ASM)
46-
set(CXX_STANDARD 14)
46+
set(CXX_STANDARD 17)
4747

4848
# This option is used when building the Python wheel
4949
option(SEAR_ENABLE_PYTHON "Enables building the Python language module." OFF)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ from sear import sear
5050

5151
result = sear(
5252
{
53-
"operation": "extract",
53+
"operation": "add",
5454
"admin_type": "user",
5555
"userid": "FDEGILIO",
5656
"traits": {

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[build-system]
2-
requires = ["setuptools >= 78.1.0", "setuptools-scm >= 8.2"]
2+
requires = ["setuptools >= 80.9.0", "setuptools-scm >= 9.2"]
33
build-backend = "setuptools.build_meta"
44

55
[project]
@@ -33,6 +33,7 @@ classifiers = [
3333
"Programming Language :: Python :: 3",
3434
"Programming Language :: Python :: 3.12",
3535
"Programming Language :: Python :: 3.13",
36+
"Programming Language :: Python :: 3.14",
3637
'Programming Language :: Python :: 3 :: Only',
3738
"Programming Language :: Python :: Implementation :: CPython",
3839
"Programming Language :: Python :: Implementation :: PyPy",
@@ -44,7 +45,7 @@ dynamic = ["version"]
4445

4546
[project.optional-dependencies]
4647
dev = [
47-
"pytest>=8.4.0",
48+
"pytest>=8.4.2",
4849
"pytest-md>=0.2.0",
4950
]
5051

python_tests/test_user.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,18 @@ def test_extract_user(create_user):
220220
assert "errors" not in str(extract_result.result)
221221
assert extract_result.result["return_codes"] == successful_return_codes
222222

223+
def test_extract_user_empty_string():
224+
"""This test is supposed to fail"""
225+
extract_result = sear(
226+
{
227+
"operation": "extract",
228+
"admin_type": "user",
229+
"userid": "",
230+
},
231+
)
232+
assert "errors" in str(extract_result.result)
233+
assert extract_result.result["return_codes"] != successful_return_codes
234+
223235
def test_user_extract_not_found():
224236
"""This test is supposed to fail"""
225237
user_not_found_result = sear(

sear/irrseq00/irrseq00.hpp

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ const uint32_t RRSF_PRIVILEGED_ATTRIBUTE = 0x00040000;
276276

277277
typedef struct {
278278
uint32_t length;
279-
} offset_field_t;
279+
char data[];
280+
} racf_rrsf_offset_field_t;
280281

281282
typedef struct {
282283
char rrsf_node_name[8];
@@ -291,43 +292,43 @@ typedef struct {
291292
uint32_t partner_node_os_version;
292293
uint32_t binary_partner_node_template_release_level;
293294
uint32_t binary_partner_node_template_service_level;
294-
offset_field_t offset_partner_node_parse_level;
295-
offset_field_t offset_rrsf_node_description;
296-
offset_field_t offset_rrsf_node_workspace_dataset_prefix;
297-
offset_field_t offset_rrsf_workspace_sms_management_class;
298-
offset_field_t offset_rrsf_workspace_sms_storage_class;
299-
offset_field_t offset_rrsf_workspace_data_class;
300-
offset_field_t offset_rrsf_workspace_dataset_volume;
295+
uint32_t offset_partner_node_parse_level;
296+
uint32_t offset_rrsf_node_description;
297+
uint32_t offset_rrsf_node_workspace_dataset_prefix;
298+
uint32_t offset_rrsf_workspace_sms_management_class;
299+
uint32_t offset_rrsf_workspace_sms_storage_class;
300+
uint32_t offset_rrsf_workspace_data_class;
301+
uint32_t offset_rrsf_workspace_dataset_volume;
301302
uint32_t rrsf_workspace_file_size;
302-
offset_field_t offset_workspace_dataset_wdsqual;
303+
uint32_t offset_workspace_dataset_wdsqual;
303304
uint32_t bit_flags;
304-
offset_field_t offset_inmsg_dataset_name;
305+
uint32_t offset_inmsg_dataset_name;
305306
uint32_t inmsg_records;
306307
uint32_t inmsg_extents;
307-
offset_field_t offset_outmsg_dataset_name;
308+
uint32_t offset_outmsg_dataset_name;
308309
uint32_t outmsg_records;
309310
uint32_t outmsg_extents;
310-
offset_field_t offset_inmsg2_dataset_name;
311+
uint32_t offset_inmsg2_dataset_name;
311312
uint32_t inmsg2_records;
312313
uint32_t inmsg2_extents;
313-
offset_field_t offset_outmsg2_dataset_name;
314+
uint32_t offset_outmsg2_dataset_name;
314315
uint32_t outmsg2_records;
315316
uint32_t outmsg2_extents;
316317
uint32_t node_requests_denied;
317-
offset_field_t offset_tcpip_address_target_command;
318-
offset_field_t offset_tcpip_address_resolved_by_system;
319-
offset_field_t offset_tcpip_port;
320-
offset_field_t offset_tcpip_tls_rule;
321-
offset_field_t offset_tcpip_cipher_policy;
322-
offset_field_t offset_tcpip_certificate_user;
318+
uint32_t offset_tcpip_address_target_command;
319+
uint32_t offset_tcpip_address_resolved_by_system;
320+
uint32_t offset_tcpip_port;
321+
uint32_t offset_tcpip_tls_rule;
322+
uint32_t offset_tcpip_cipher_policy;
323+
uint32_t offset_tcpip_certificate_user;
323324
uint8_t offset_tcpip_client_authentication;
324325
uint8_t tcpip_listener_status;
325326
uint16_t appc_listener_status;
326327
uint16_t reserved[2];
327-
offset_field_t offset_appc_lu_name;
328-
offset_field_t offset_appc_modename;
329-
offset_field_t offset_appc_tp_name;
330-
offset_field_t offset_appc_netname;
328+
uint32_t offset_appc_lu_name;
329+
uint32_t offset_appc_modename;
330+
uint32_t offset_appc_tp_name;
331+
uint32_t offset_appc_netname;
331332
uint32_t reserved2[4];
332333
} racf_rrsf_node_definitions_t;
333334

sear/irrseq00/profile_post_processor.cpp

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,13 @@ void ProfilePostProcessor::postProcessSearchGeneric(SecurityRequest &request) {
117117

118118
for (int i = 0; i < found_profiles.size(); i++) {
119119
int len = std::strlen(found_profiles[i]);
120-
std::string profile_name =
121-
ProfilePostProcessor::decodeEBCDICBytes(found_profiles[i], len);
122-
repeat_group_profiles.push_back(profile_name);
120+
if (len > 0) {
121+
std::string profile_name =
122+
ProfilePostProcessor::decodeEBCDICBytes(found_profiles[i], len);
123+
if (profile_name != " " && profile_name != "") {
124+
repeat_group_profiles.push_back(profile_name);
125+
}
126+
}
123127
free(found_profiles[i]);
124128
}
125129

@@ -208,6 +212,18 @@ void ProfilePostProcessor::postProcessRACFOptions(SecurityRequest &request) {
208212
request.setIntermediateResultJSON(profile);
209213
}
210214

215+
// There are a bunch of these weird offset fields
216+
// This function allow offset fields to easily be processed
217+
void ProfilePostProcessor::postprocessRRSFOffsetField(nlohmann::json &profile, const std::string &key, const char *p_profile, int offset) {
218+
const racf_rrsf_offset_field_t *p_field =
219+
reinterpret_cast<const racf_rrsf_offset_field_t *>(p_profile + offset);
220+
221+
// Only create the key if there actually is any data in the offset field, avoids empty quotes
222+
if (p_field->length > 0) {
223+
profile[key] = ProfilePostProcessor::decodeEBCDICBytes(p_field->data,p_field->length);
224+
}
225+
}
226+
211227
//////////////////////////////////////////////////////////////////////////
212228
// RRSF post processing //
213229
//////////////////////////////////////////////////////////////////////////
@@ -262,6 +278,35 @@ void ProfilePostProcessor::postProcessRACFRRSF(SecurityRequest &request) {
262278
node_definition["base:time_of_last_sent_work"] = ProfilePostProcessor::decodeEBCDICBytes(p_nodes->time_of_last_sent_work,8);
263279
node_definition["base:node_state"] = p_nodes->rrsf_node_state;
264280

281+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:node_description", p_profile, p_nodes->offset_rrsf_node_description);
282+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:partner_node_dynamic_parse_level",p_profile, p_nodes->offset_partner_node_parse_level);
283+
284+
// Workspace dataset information
285+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:workspace_dataset_prefix", p_profile, p_nodes->offset_rrsf_node_workspace_dataset_prefix);
286+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:workspace_dataset_name", p_profile, p_nodes->offset_workspace_dataset_wdsqual);
287+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:workspace_dataset_sms_management_class", p_profile, p_nodes->offset_rrsf_workspace_sms_management_class);
288+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:workspace_dataset_sms_storage_class", p_profile, p_nodes->offset_rrsf_workspace_sms_storage_class);
289+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:workspace_dataset_sms_data_class", p_profile, p_nodes->offset_rrsf_workspace_data_class);
290+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:workspace_dataset_volume", p_profile, p_nodes->offset_rrsf_workspace_dataset_volume);
291+
292+
node_definition["base:workspace_file_size"] = p_nodes->rrsf_workspace_file_size;
293+
294+
// inmsg and outmsg dataset information
295+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:in_message_dataset_name", p_profile, p_nodes->offset_inmsg_dataset_name);
296+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:out_message_dataset_name", p_profile, p_nodes->offset_outmsg_dataset_name);
297+
298+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:temporary_in_message_dataset_name", p_profile, p_nodes->offset_inmsg2_dataset_name);
299+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:temporary_out_message_dataset_name", p_profile, p_nodes->offset_outmsg2_dataset_name);
300+
301+
node_definition["base:in_message_records"] = p_nodes->inmsg_records;
302+
node_definition["base:out_message_records"] = p_nodes->outmsg_records;
303+
node_definition["base:temporary_in_message_records"] = p_nodes->inmsg2_records;
304+
node_definition["base:temporary_out_message_records"] = p_nodes->outmsg2_records;
305+
node_definition["base:in_message_extents"] = p_nodes->inmsg_extents;
306+
node_definition["base:out_message_extents"] = p_nodes->outmsg_extents;
307+
node_definition["base:in_message2_extents"] = p_nodes->inmsg2_extents;
308+
node_definition["base:out_message2_extents"] = p_nodes->outmsg2_extents;
309+
265310
// Partner node information
266311
node_definition["base:partner_node_operating_system_version"] = p_nodes->partner_node_os_version;
267312
node_definition["base:partner_node_template_release_level"] = p_nodes->binary_partner_node_template_release_level;
@@ -282,8 +327,22 @@ void ProfilePostProcessor::postProcessRACFRRSF(SecurityRequest &request) {
282327
// Determines which protocol the RRSF node is using and adds it to the result JSON
283328
if (p_nodes->rrsf_protocol == 01) {
284329
node_definition["base:node_protocol"] = "appc";
330+
331+
// These are only relevant if system is using APPC, instead of the modern TCP/IP
332+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:appc_modename", p_profile, p_nodes->offset_appc_modename);
333+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:appc_lu_name", p_profile, p_nodes->offset_appc_lu_name);
334+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:appc_tp_name", p_profile, p_nodes->offset_appc_tp_name);
335+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:appc_netname", p_profile, p_nodes->offset_appc_netname);
285336
} else if (p_nodes->rrsf_protocol == 02) {
286337
node_definition["base:node_protocol"] = "tcpip";
338+
339+
// These are only relevant if system is using TCPIP for RRSF
340+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:resolved_tcpip_address", p_profile, p_nodes->offset_tcpip_address_resolved_by_system);
341+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:target_tcpip_address", p_profile, p_nodes->offset_tcpip_address_target_command);
342+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:tcpip_port", p_profile, p_nodes->offset_tcpip_port);
343+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:tcpip_attls_rule", p_profile, p_nodes->offset_tcpip_tls_rule);
344+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:tcpip_attls_cipher", p_profile, p_nodes->offset_tcpip_cipher_policy);
345+
ProfilePostProcessor::postprocessRRSFOffsetField(node_definition, "base:tcpip_attls_certificate_user", p_profile, p_nodes->offset_tcpip_certificate_user);
287346
} else {
288347
node_definition["base:node_protocol"] = "none";
289348
}

sear/irrseq00/profile_post_processor.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class ProfilePostProcessor {
1717
static void postProcessRACFRRSF(SecurityRequest &request);
1818

1919
private:
20+
static void postprocessRRSFOffsetField(nlohmann::json &profile, const std::string &key, const char *p_profile, int offset);
2021
static void processGenericField(nlohmann::json &json_field,
2122
const generic_field_descriptor_t *p_field,
2223
const char *p_profile,

sear/security_request.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,10 +328,14 @@ void SecurityRequest::load(const nlohmann::json& request) {
328328
}
329329

330330
if (request.contains("run_as_userid")) {
331-
std::string surrogate_userid_string = request.get<std::string>();
331+
std::string surrogate_userid_string = request["run_as_userid"].get<std::string>();
332332
surrogate_userid_string = fromUTF8(surrogate_userid_string);
333333
Logger::getInstance().debug("Running under the authority of user: " +
334334
surrogate_userid_string);
335+
const int userid_length = surrogate_userid_string.length();
336+
std::strncpy(surrogate_userid_,
337+
surrogate_userid_string.c_str(),
338+
userid_length );
335339
}
336340
}
337341

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def run(self):
7171
os.environ["CC"] = "ibm-clang64"
7272
os.environ["CFLAGS"] = "-std=c99"
7373
os.environ["CXX"] = "ibm-clang++64"
74-
os.environ["CXXFLAGS"] = "-std=c++14"
74+
os.environ["CXXFLAGS"] = "-std=c++17"
7575
sear_source_path = Path("sear")
7676
assemble("irrseq00.s", sear_source_path / "irrseq00")
7777
super().run()

0 commit comments

Comments
 (0)