From 7ff0482903157deedadc2718622fdde75a70f498 Mon Sep 17 00:00:00 2001 From: "Bart Jablonski (yabwon)" Date: Fri, 30 Sep 2022 18:48:42 +0200 Subject: [PATCH] The GSM package [ver. 0.20] Initial commit of the package. --- gsm.md | 322 ++++++++++++++++++++++++++++++++++++++++++++++ gsm.zip | Bin 0 -> 16662 bytes hist/0.20/gsm.zip | Bin 0 -> 16662 bytes 3 files changed, 322 insertions(+) create mode 100644 gsm.md create mode 100644 gsm.zip create mode 100644 hist/0.20/gsm.zip diff --git a/gsm.md b/gsm.md new file mode 100644 index 0000000..85736d7 --- /dev/null +++ b/gsm.md @@ -0,0 +1,322 @@ +- [The GSM package](#gsm-package) +- [Content description](#content-description) + * [`%GSM()` macro](#gsm-macro) + * [`%GSMpck_makeFCMPcode()` macro](#gsmpck-makefcmpcode-macro) + + * [License](#license) + +--- + + +# The GSM package [ver. 0.20] ############################################### + +The **GSM** (a.k.a. *Generate Secure Macros*) package allows +to create secured macros stored in SAS Proc FCMP functions. +The dataset with functions can be shared and allows to generate +macros without showing their code. + +The GSM package is basically an automated version of the following: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +proc fcmp outlib = work.gsm.secure ENCRYPT; + function generateMacro() $; + rc = RESOLVE(' + %macro secretMacro(x) / SECURE; + data test; + a = "&x."; + run; + %mend; + '); + return (rc); + endsub; +run; + +/* share work.gsm dataset */ +options cmplib = work.gsm; +data _null_; + rc = generateMacro(); + put rc=; +run; + +/* enjoy */ +%secretMacro(42) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +See examples for more details. + +Recording of presentation with "how it works" description, in Polish, is avaliable [here](https://www.youtube.com/watch?v=LtaWPe2sgRY&t=1s). + +*How to use it:* + - Copy all files with your secured macros code into a directory. + Best approach is to have one file for one macro. + - Copy a path to the directory. + - Run the following code: + ``` + %GSM(, cmplib=) + ``` + - Share generated `ZIP` file (unzip and run the code). + +**Limitations:** + - Single macro file cannot be longer than 32760 bytes. + + - Multiline text variable. Consider the following code text file: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +%macro~test()/SECURE;~#@ +data~test;~#@ +a~=~"abc~#@ +~#@ +def";~#@ +put~a~hex20.;~#@ +run;~#@ +%mend~test;~#@ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +where `~` symbols the space character, +`#` symbols the carriage return (`0D`), +and `@` symbols the line feed (`0A`). +The code file is scanned and inserted into +the `resolve()` function argument in a "byte by byte" +fashion hence also the "end of line" characters are included. +As the result value of variable `a` will be: + +`a = "abc~#@~#@def"`. + +If you want to use the `GSM` package avoid +such "style" of coding in your macros. + + +--- + +Package contains: + 1. macro gsm + 2. macro gsmpck_makefcmpcode + +Required SAS Components: + `Base SAS Software` + +* SAS package generated by generatePackage, version 20220830 * + +The SHA256 hash digest for package GSM: +`2AEBC150FBA99A4AAB0265A21C57E89200BFD96B633B898F32743D1C8831A159` + + +## >>> `%GSM()` macro: <<< ####################### + +The `%GSM()` macro is the main macro of +the **GSM** (a.k.a. *Generate Secure Macros*) package. + +It converts a list of macros provided by the user into +a data set of the Proc FCMP functions. The macros are stored +in functions are encrypted which allow to share them without +showing their code. *Important* thing is that macros provided +by the user *has* to be "secure", i.e. the `secure` option has to +be added to the macro definition. See the example: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%macro secretMacro(x) / SECURE; /* <- the secure option */ + <... some code ...> +%mend secretMacro; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +As a result a zip file, containing dataset with functions and +code to be executed on site, is generated. + +Since encrypted code is stored in a SAS dataset it has +no limitation in sharing between operating systems (like catalogs have). + +*Limitation:* Due to the `Resolve()` function limitations + a single macro file cannot be longer than 32760 bytes. + +*Notes:* +- All macros have to have the `secure` option added, i.e. `%macro aMacroname(...) / SECURE ;`. +- During the execution a test macro, named `%GSMpck_dummyMacroForTests()`, is generated. +- The `%GSM()` macro calls the `%GSMpck_makeFCMPcode(...)` macro internally. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%GSM( + path + <,trim=0> + <,cmplib=work.generateMacros> + <,source2=> + <,outpath=> + <,encodingRestricted=> + <,secret=> + <,lineEnd=> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `path` - *Required*, indicates a directory which contains files with macros. + Only files with `sas` extension are used. + +* `cmplib=` - *Optional*, the default value is `work.generateMacros`. + Names the dataset which will contain generated functions. + +* `source2=` - *Optional*, the default value is null. + Indicate if `%includ`-ed files are printed out. + Any value other than null enables printing. + +* `outpath=` - *Optional*, the default value is set the same as the `path`. + Points a directory in which a result (a zip file) is generated. + +* `encodingRestricted=` - *Optional*, the default value is `0`. + If set to 1 then if User session encoding is different from + encoding of the session which generates the dataset then + the generateMacros() function will not execute macro code. + +* `secret=` - *Optional*, the default value is null, in such case the + secret is generated from the `sha256(datetime(), hex32.)` function + and is printed in the log. When not null then should be + alphanumerical constant. Non-alphanumerical characters are removed. + Required to execute the `resolve()` function. + User who do not know the value will not be able + to run the `_maxro_XX_()` function. + +* `lineEnd=` - *Optional*, the default value is `0D0A`, indicates which of: + line feed, carriage return, or both, or a space be inserted + at the end of line in the intermediate code file that is generated. + Value has to be hexadecimal code (_NOT_ null), + since the value is resolved as `"&lineEnd."x`, so use e.g. + `0A` for line feed, `0D` for carriage return, + `0D0A` for both, and `20` for space. + +* `trim=` - *Deprecated*, the default value is `0`. + *Kept for backward compatibility.* + + +--- + +### Example: ################################################################### + +Example 1. Prepare 2 files: `f1.sas` and `f2.sas` and use the `%GSM()` macro. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%let path = %sysfunc(pathname(work))/path2files; + +%put &=path.; +options dlcreatedir; +libname path "&path."; +filename path "&path."; + +data _null_; + file path(f1.sas); + input; + put _infile_; +cards4; +%macro abc(x) / SECURE; + data test; + do i = 1 to &x.; + put i=; + end; + run; +%mend; +;;;; +run; + +data _null_; + file path(f2.sas); + input; + put _infile_; +cards4; +%macro xyz(x) / SECURE; + %do i = 1 %to &x.; + %put &=i; + %end; +%mend; +;;;; +run; + +%GSM(&path., cmplib=work.myMacros) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## >>> `%GSMpck_makeFCMPcode()` macro: <<< ####################### + +The `%GSMpck_makeFCMPcode()` macro is an internal macro of +the **GSM** (a.k.a. *Generate Secure Macros*) package. + +It executes a process of converting +a macro provided by the user into +a Proc FCMP function. + +Since encrypted code is stored in a SAS dataset it has +no limitation in sharing between operating systems (like catalogs have). + +*Limitation:* Single macro file cannot be longer than 32760 bytes. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%GSMpck_makeFCMPcode( + path + ,number + <,outlib=work.generateMacros.secure> + <,source2=> + <,fileNameCode=FNC> + <,secret=123456789> + <,lineEnd=0A> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `path` - *Required*, indicates a directory which contains files with macros. + Only files with `sas` extension are used. + +2. `number` - *Required*, a sequential number. + + +* `cmplib=` - *Optional*, the default value is `work.generateMacros`. + Names the dataset which will contain generated functions. + +* `source2=` - *Optional*, the default value is null. + Indicate if `%includ`-ed files are printed out. + Any value other than null enables printing. + +* `fileNameCode=` - *Optional*, the default value is `FNC`. + Internal fileref. + +* `secret=` - *Optional*, internal, the default value is `1234567890`. + Alphanumerical constant required to execute the `resolve()` + function. User who do not know the value will not be able + to run the `_maxro_XX_()` function. + +* `lineEnd=` - *Optional*, the default value is `0D0A`, indicates which of: + line feed, carriage return, or both, or a space be inserted + at the end of line in the intermediate code file that is generated. + Value has to be hexadecimal code (_NOT_ null), + since the value is resolved as `"&lineEnd."x`, so use e.g. + `0A` for line feed, `0D` for carriage return, + `0D0A` for both, and `20` for space. + +* `trim=` - *Deprecated*, the default value is `0`. + *Kept for backward compatibility.* + +--- + + +## License #################################################################### + +Copyright (c) Bartosz Jablonski, since 2021 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- diff --git a/gsm.zip b/gsm.zip new file mode 100644 index 0000000000000000000000000000000000000000..df3bf538e355c72124d640135a3b5fe9ec8bdbfc GIT binary patch literal 16662 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 V&-wpH1qlPl`=e4f;{VUD{{=!L?*RY+ literal 0 HcmV?d00001 diff --git a/hist/0.20/gsm.zip b/hist/0.20/gsm.zip new file mode 100644 index 0000000000000000000000000000000000000000..df3bf538e355c72124d640135a3b5fe9ec8bdbfc GIT binary patch literal 16662 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 V&-wpH1qlPl`=e4f;{VUD{{=!L?*RY+ literal 0 HcmV?d00001