see attached
=head1 NAME BZS::License - Perl extension to examine a license file. =head1 USEAGE There are two modes of operation: use BZS::License;1; __END__ encrypted module here... The calling routine should define an anonymous hash pointed to by the variable $ptr2_License. i.e. use vars qw( $ptr2_License ); $ptr2_License = { 'private' => 'name1, name2,...', # use private key # module name 'path' => 'path to License file', }; require licensed_module_name; Or, for nested modules, a reference pointer to point back to the originating module containing the License information. use vars qw( $ptr2_License ); $ptr2_License = { 'next' => 'any value will do', }; require licensed_module_name; Seconds remaining until License expiration are returned in $ptr2_License{expires} unless there is no expiration Warnings if any will be in $ptr2_License->{warn} It is important the 'require' instead of 'use' loads the module so that $ptr2_License is visible to the loader and not forgotton in the case of mod-perl so don't enclose a in BEGIN{} block. Version checking is not supported via 'use' like statement. It can be done by examining the module contents. More automated setup can be accomplished with the BZS::License::Util tools. use BZS::License::Util; See BZS::License::Util documentation for complete description The second module mode is for development use and just loads the module so its objects can be accessed; use BZS::License; $time = BZS::License::date2time(date string); @file_text = BZS::License::get_file(file_path); $first_tag_number = BZS::License::extract(\@file_text,\%parms); BZS::License::get_vals(\%parms); =head1 DESCRIPTION See the documentation for BZS::Loader for details of License loading operation. Only the differences are covered here. BZS::License performs a similar load operation to BZS::Loader. First, however it looks for a hash pointer in the caller program called $ptr2_License. The hash contains the path to the License file and an optional 'private' key list of modules which will decrypt only with the 'private' key. B<OR>, a hash key of 'next' with no particular value that indicates to look to the next caller on the stack for the License pointer. If the pointer is not present or the License file is not found successfully, then no further action is taken. If the License file is successfully opened, and the contents validated then the attached encrypted module is loaded and the seconds remaining until License expiration are returned or now() in the case of no expiration. Undef is returned for an expired license (module fails to load). =over 4 =item This is what is in a certificate License Text followed by: ID: :unique licensee identifier, date code is fine NAME: :company or entity name ADD1: :address line 1 ADD2: :address line 2 CITY: :city STATE: :state or province ZIP: :postal code CTRY: :country TEL: :telephone number FAX: fax number CONT: :contact person MAIL: :email addy of contact ---------------------------------- SERV: :http server name * optional HOST: :hostname * optional USER: :calling user * optional GROUP: :calling group * optional HOME: :called from withing this path * optional ---------------------------------- DATE: :creation date, mm-dd-yy | yyyy or mmm dd yy | yyyy EXP: :expiration * optional KEY: :hex key PKEY: :hex public key ---------------------------------- =item $time = BZS::License::date2time(date string) Converts a string into a numeric time value as returned by the perl function 'time' else 0; * acceptable date formats mm/dd/yy mm-dd-yy mm dd yy month day year month = text or digits month day, year actually any combination of separators [/- ] will work commas are always deleted, white space compressed, etc... =item @file_text = BZS::License::get_file(file_path) Takes the file path/name as its argument. Returns the stripped file contents suitable for MAC calculation in an array. On failure, returns an empty array. =item MAC calculation The MAC signature is created by taking the MD5 sum of the file less MAC the line (if present). Leading blank lines are removed, all tabs are converted to single spaces and trailing white space is snipped to avoid complications caused by cut and paste operations. MAC calculation is only done on the text portion of the file. =item $first_tag_num = BZS::License::extract(\@file_text,\%parms) B<extract> takes an input array consisting of the lines of text in the License and returns the \%parms hash filled with the values present in the License file. The return value is the pointer to the first tag of the array. MAC calculation described above will only be done on the text portion of the array. =item BZS::License::get_vals(\%parms,\%chk_vals) The following fields are returned to the %chk_vals hash from the host platform unless the fields are not present in the License file: SERV: :http server name HOST: :hostname USER: :user GROUP: :user HOME: :server document root EXP: :time since epcoch time ins seconds =back =head1 TARGET MODULE PREPARATION The target module distribution for License encryption should be modified as follows: =over 4 =item Copy makePOD.pl, makeCrypt.pl, mod_parser.pl, and TestCert.license from the License distribution to the target distribution and include in the target distribution MANIFEST. =item Modify the t/test.t and/or test.pl scripts to include a $ptr2_License hash. =item Rename the target distribution XXXXX.pm file to XXXXX.PM and separate the pod documentation into a separate file. makePOD.pl XXXXX.PM will create XXXXX.pod, XXXXX.PM.nopod =item Modify the Makefile.PL file as follows to include 'make crypt' and 'make cryptdist' functions. use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. my $name = 'Some::ModuleName'; @_ = split('::',$name); my $src = $_[$#_] . '.PM'; my $target = $_[$#_] . '.pm'; my $pod = $name . '.3'; sub MY::top_targets { package MY; # add dependencies for .pm and xs files ####>>> TABS required below, not spaces !!! my $inherited = " $target : $src /bin/cp -p $src $target " . shift->SUPER::top_targets(@_) . " crypt :: ./makeCrypt.pl $src $name " . q|$(INST_LIB) cryptdist : $(DISTVNAME).bin.tar$(SUFFIX) $(DISTVNAME).bin.tar$(SUFFIX) :: all crypt $(RM_RF) $(DISTVNAME).bin find blib -type f > delete.me~ echo -e "Makefile\nMakefile.PL" >>delete.me~ CRYPTIME=$(/bin/date +%Y%m%d%H%M.%S) $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=manicopy,maniread \ -e "manicopy(maniread('delete.me~'),'$(DISTVNAME).bin', '$(DIST_CP)');" cp | . $target . q| $(DISTVNAME).bin/| . $src . q| cp | . $target . q| $(DISTVNAME).bin/| . $target . q| touch +$(CRYPTIME) $(DISTVNAME).bin/| . $src . q| touch +$(CRYPTIME) $(DISTVNAME).bin/| . $target . q| $(TAR) $(TARFLAGS) $(DISTVNAME).bin.tar $(DISTVNAME).bin $(COMPRESS) $(DISTVNAME).bin.tar $(RM_RF) $(DISTVNAME).bin |; } WriteMakefile( 'NAME' => $name, 'VERSION_FROM' => $src, # finds $VERSION 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1 'PM' => {$target => '$(INST_LIBDIR)/'.$target}, 'MAN3PODS' => {$pod => {$pod => '$(INST_MAN3DIR)/'.$pod}, 'pm_to_blib' => {$target => '$(INST_LIBDIR)/'.$target}, 'clean' => {FILES => $target}, 'dist' => {COMPRESS => 'gzip', SUFFIX=>'gz'} ); # NOTE: remove the MAN3PODS section if not applicable =item Make the module as follows: For the development environment. perl Makefile.PL make make test make crypt make test --- again to verify it works crypted make install make dist make cryptdist For the client environment: tar -xzvf BZS-Whatever.bin.tar.gz cd BZS-Whatever.bin make install =back =head1 HINTS For installation with programs called by B<apache> that are installed using PerlModule or PerlRequire commands, there are several requirements. =over 4 =item 1 The server will need a License with a public key. The License needs to be loaded in the startup.pl script. =item 2 The handlers loaded from the PerlRequire or PerlModule directives need a B<next> $ptr2_License so that on startup they will decrypt and when called from user space will point back to the user License. =item 3 Any routine which calls handler directives needs a B<next> $ptr2_License even if the module is not actually loaded in the routine. i.e. some handlers, like Apache::AuthCookie, force the loading of the user's handlers so the call to 'use UserHandler' is unnecessary. =item 4 Specifically for modules like Apache::AuthCookie, this module calls Licensed modules by virtue of the PerlRequire or PerlModule directives in the users config file. B<BECAUSE of this>, the AuthCookie module B<MUST> have a B<next> $ptr2_License inserted in the beginning statements. =item 5 With all this accomplished, all modules should load and de-crypt without problem. =back =head1 EXPORT None by default. =head1 TOOLS makeCert.pl makes a License document makeLicenseMod.pl makes only unsplit Licensed modules makeCrypt.pl makes a split Licensed module makePOD.pl separates POD from mixed module mod_parser.pl used by makeCrypt, makePOD, makeLicenseMod =head1 AUTHOR Michael Robinton, [EMAIL PROTECTED] =head1 COPYRIGHT Copyright 2000 Michael Robinton, BizSystems. All rights reserved. =head1 SEE ALSO L<BZS::License::Notice(3)>, L<BZS::License::Util(3)> =cut
=head1 NAME BZS::License::Notice -- perl extension for License =head1 SYNOPSIS require BZS::License::Notice; BZS::License::Notice->check($input_hash) =head1 DESCRIPTION =over 4 =item BZS::License::Notice->check($input_data_ptr) $input_hash_ptr = { # optional parameters 'ACTION' => 'default /usr/lib/sendmail -t -oi', 'TMPDIR' => 'default /tmp', 'INTERVALS' => 'default 5d,30d,60d', 'TO' => 'default [EMAIL PROTECTED]', # mandatory parameters 'path' => 'path to LICENSE', 'expires' => 'seconds until expiration', }; The B<check> routine will send a notice message at the requested or default intervals IF the temporary directory exists and is writeable AND if the B<expires> parameter exists and is positive AND the LICENSE file exists and is readable. Substitutes can be made for the default values for ACTION, TMPDIR, TO, and INTERVALS. Valid suffixes for INTERVALS are w=weeks, d=days, h=hours, m=minutes, s=seconds (default if no suffix). B<check> returns an empty array on any error or if B<expires> does not exist. It returns an array of the INTERVALS values in in seconds, highest to lowest, if a check is performed. Note that the b<Notice.pm> hash can be combined with the hash used for the B<License.pm> module and that they share common variables B<path> and B<expires>. All other B<License.pm> hash keys are lower while B<Notice.pm> hash keys are upper case. =back =head1 COPYRIGHT This Library is proprietary software and may be used only with the permission of the author. Copyright 2001 Michael Robinton, BizSystems =head1 AUTHOR Michael Robinton, BizSystems <[EMAIL PROTECTED]>