The wrapper is DC specific and sits alongside mpe_assert_abort, so the mpe_ prefix marks which layer it belongs to. File, macro name, %mend and all seven callers updated; no dc_execute reference remains in the tree.
101 lines
2.5 KiB
SAS
101 lines
2.5 KiB
SAS
/**
|
|
@file
|
|
@brief testing getcols service - input validation (security)
|
|
@details The libds in the IWANT input table must be a well-formed
|
|
LIBREF.DATASET. An invalid value aborts the service before it
|
|
reaches proc contents. The abort shows up as a canceled child job
|
|
(an aborted service registers no webout).
|
|
|
|
The payload in test 1 resolves to a REAL table when the request
|
|
content is executed as macro code, so on a vulnerable service the
|
|
job completes, and only the validating service cancels it - the
|
|
assertion cannot pass against a service that does not validate.
|
|
|
|
<h4> SAS Macros </h4>
|
|
@li mpe_assert_abort.sas
|
|
@li mp_assert.sas
|
|
@li mpe_execute.sas
|
|
@li mf_getuniquefileref.sas
|
|
|
|
**/
|
|
|
|
%let _program=&appLoc/services/public/getcols;
|
|
|
|
/**
|
|
* Test 1 - macro content in libds must abort the service
|
|
*/
|
|
%let f1=%mf_getuniquefileref();
|
|
data _null_;
|
|
file &f1 termstr=crlf;
|
|
put 'LIBDS:$41.';
|
|
put '%sysfunc(coalescec(&dclib..MPE_X_TEST,))';
|
|
run;
|
|
|
|
%mpe_execute(&_program,
|
|
viyacontext=&defaultcontext,
|
|
inputfiles=&f1:iwant,
|
|
outref=web1,
|
|
outstatus=work.ab1,
|
|
failfast=0,
|
|
viyaresult=WEBOUT_TXT
|
|
)
|
|
|
|
%mpe_assert_abort(
|
|
desc=Macro content in libds aborts the service,
|
|
outref=web1,
|
|
msg=Invalid libds
|
|
)
|
|
|
|
/**
|
|
* Test 2 - valid libds still returns columns
|
|
*/
|
|
%let f2=%mf_getuniquefileref();
|
|
data _null_;
|
|
file &f2 termstr=crlf;
|
|
put 'LIBDS:$41.';
|
|
put "&dclib..MPE_X_TEST";
|
|
run;
|
|
|
|
%mpe_execute(&_program,
|
|
viyacontext=&defaultcontext,
|
|
inputfiles=&f2:iwant,
|
|
outlib=web2
|
|
)
|
|
|
|
%let nobs=0;
|
|
%let nbad=0;
|
|
proc sql noprint;
|
|
select count(*) into: nobs from web2.cols;
|
|
/**
|
|
* The service keeps the SAS vocabulary this public contract has always used:
|
|
* TYPE is C/N, and DDTYPE separates the date and time types. The client maps
|
|
* TYPE to its own num/char vocabulary in sas-store.getCols, so a change here
|
|
* that silently switched vocabulary would not be caught by the client suite.
|
|
* Every column must be C or N, and the two must agree with ddtype.
|
|
*/
|
|
select count(*) into: nbad from web2.cols
|
|
where type not in ('C','N')
|
|
or (ddtype='C' and type ne 'C')
|
|
or (ddtype in ('N','DATE','DATETIME','TIME') and type ne 'N');
|
|
quit;
|
|
|
|
%mp_assert(
|
|
iftrue=(&nobs>0),
|
|
desc=Valid libds returns columns,
|
|
outds=work.test_results
|
|
)
|
|
|
|
%mp_assert(
|
|
iftrue=(&nbad=0),
|
|
desc=%str(TYPE stays in the SAS C/N vocabulary and agrees with ddtype),
|
|
outds=work.test_results
|
|
)
|
|
|
|
/**
|
|
* dump results to the log for offline inspection
|
|
*/
|
|
data _null_;
|
|
set work.test_results;
|
|
putlog 'TEST_RESULT_LINE: ' test_result ' - ' test_description;
|
|
run;
|