Perl's TieRegistry and Windows Server 2008 R2 - perl

We have a Perl program that ran well on all Windows platforms so far.
When we tried it on the newly released Windows Server 2008 R2, it stopped working. Investigation revealed that the problem is that calls to read registry values using TieRegistry returned undefined values.
Is this a known problem? Did anyone run into a problem accessing the registry on Windows Server 2008 R2 using TieRegistry?
I'm running the program as administrator, so I don't think it is permission problems. The program works great and read the registry correctly on Windows 7 and Vista.
A sample script I wrote to access the registry also fail:
use Win32::TieRegistry(Delimiter=>'\\');
my $reg = "HKEY_LOCAL_MACHINE\\SOFTWARE\\TEST\\Value1";
my $val = $Registry->{$reg};
print "val: ".$val."\n";
Any help would be appreciated.
Thanks,
splintor

Since google likes to come up with this when people are looking for the solution I figured I'd drop a little note.
You do not have to modify TieRegistry.pm to get this to work. All you have to do is add the "Access" parameter to the call. here is an example:
my $rk = Win32::TieRegistry->new('LMachine\Software\Microsoft\Microsoft SQL Server\Instance Names\SQL', {Access=> 0x20019|0x0200});
There are two flags above ORd together:
0x20019 -- Read access to keys
0x0200 -- Access the 64 bit version of registry (ignored on 32 bit systems)
You can also use 0x0100 to access the 32 bit redirect version of the registry (also ignored on 32 bit systems)
This way you don't have to modify the library AND a single program can access BOTH versions of the registry.

I found the source of my problem.
In order to make TieRegistry work well on 64-bit Windows, and access the correct registry hive, we used the solution suggested by Tony B. Okusanya (also quoted here). However, this solution adds both KEY_WOW64_64KEY and KEY_WOW64_32KEY to the access parameter, which is not logical – either you want to access the 64-bit registry and use KEY_WOW64_64KEY or you want the 32-bit registry and use KEY_WOW64_32KEY. Using both doesn’t really make any sense.
Nevertheless, in previous versions of Windows, as well as Windows 7, it seems that when RegOpenKeyEx notices that the KEY_WOW64_64KEY flag is set in the access parameter, it uses the 64-bit registry, and ignores the KEY_WOW64_32KEY flag. Windows Server 2008 R2, on the other hand, doesn’t ignore the KEY_WOW64_32KEY flag, and if both flags are set, opening the registry key fail, and Win32API::Registry.regLastError returns the error The parameter is incorrect.
Removing |KEY_WOW64_32KEY from our changed TieRegistry.pm solved the problem and caused our application to work again.
Regards,
splintor

This my first time posting here. Here was the solution I came up with and an example of its use:
use Win32::TieRegistry( Delimiter=>"#", ArrayValues=>0 );
my $pound = $Registry->Delimiter("/");
my $fileSep = "\\";
my $path = "";
my $PerlBin = "";
my $PerlInstallDir = "";
my $PerlInstallDrive = "";
my $SybaseInstallDir = "";
my $SybaseInstallDrive = "";
# Standard syntax for access to 32-bit registry
my $regKey = $Registry->{"HKEY_LOCAL_MACHINE/SOFTWARE/Perl"};
print "\n\n\n" . "Accessing 32 bit registry for Perl Info:" ."\n\n\n";
foreach $key (keys %$regKey){
print"$key: " . $regKey->{"$key"} . "\n";
}
$path = $regKey->{"/"};
$PerlInstallDir = Win32::GetShortPathName($path);
$path = $regKey->{"/BinDir"};
$PerlBin = Win32::GetShortPathName($path);
$PerlInstallDrive = substr($PerlInstallDir, 0, 2) . $fileSep;
print "\n\n\n" . "Accessing 64 bit registry for Sybase Info:" ."\n\n\n";
# This syntax passes the HEX flag to access the 64 bit registry
$regKey = $Registry->Open("HKEY_LOCAL_MACHINE/SOFTWARE/SYBASE/Setup", {Access=> 0x20019|0x0100});
foreach $key (keys %$regKey){
print"$key: " . $regKey->{"$key"} . "\n";
}
$path = $regKey->{"/SYBASE"};
$SybaseInstallDir = Win32::GetShortPathName($path);
$SybaseInstallDrive = substr($SybaseInstallDir, 0, 2) . $fileSep;
print "\n\n\nFinished retrieving registry info:" . "\n";
print "Perl executable Location == $PerlBin" . "\n";
print "Perl Install Drive == $PerlInstallDrive" . "\n";
print "Perl Install Directory == $PerlInstallDir" . "\n";
print "Sybase Install Drive == $SybaseInstallDrive" . "\n";
print "Sybase Install Directory == $SybaseInstallDir" . "\n";

This works for me
use Win32::TieRegistry (
ArrayValues => 0,
SplitMultis => 1, AllowLoad => 1,
qw(:KEY_), Delimiter => '/', FixSzNulls => 1
);
use constant KEY_WOW => (uc($ENV{PROCESSOR_ARCHITECTURE}) eq "AMD64" || uc($ENV{PROCESSOR_ARCHITEW6432}) eq "AMD64") ? 0x100 : 0x200;
$Registry->Open('LMachine/Software/Microsoft/',{Access => KEY_READ | KEY_WOW});

Related

How to Retrive multiple sequences from a database in Bioperl?

I have installed Bioperl1.6 via ppm and have placed .pl file in cgi-bin folder of my localhost. When I run this via url
http://localhost/cgi-bin/bio2.pl
it says "Internal Server Error"
While if run any of the bioperl file either in CGI or .pl it complain same as Internal server error.
#!C:/Perl64/bin/perl.exe
use Bio::SeqIO;
use Bio::DB::GenBank;
use Bio::DB::Query::GenBank;
$query = "Arabidopsis[ORGN] AND topoisomerase[TITL] and 0:3000[SLEN]";
$query_obj = Bio::DB::Query::GenBank->new(-db => 'nucleotide', -query => $query );
$gb_obj = Bio::DB::GenBank->new;
$stream_obj = $gb_obj->get_Stream_by_query($query_obj);
while ($seq_obj = $stream_obj->next_seq) {
# do something with the sequence object
print $seq_obj->display_id, "\t", $seq_obj->length, "\n";
}
if I run this code via cmd then it says genebank cant be found excptn.
Please guide me how to run bioperl in perl cgi.

perl script to access sec edgar master files returns file not found when file exists on ftp server

It would be great if someone can help. I really am stuck.
I am downloading the master files from SEC edgar and I got the script from—http://brage.bibsys.no/bi/bitstream/URN:NBN:no-bibsys_brage_38213/1/Norli_SRFE_2012.pdf (page 14..published now)
I get the error 404 master.gz not found
While debugging i made it paste the url and when i use the same in browser I can download the file. It is parsing the url correctly till QTR1 but after that it is not able to find the file when it actually exists ..please help.
1) for debugging reasons now I changed the code to 1995 (but later plan to add years 1995 to 2012)
2) It did not work for any file. When I said QTR1 abovr - I meant that the same code without the file name (just for testing ) -- ....full-index/1995/QTR1/ (without the file name) returns a status code OK but ...ftp.sec.gov/edgar/full-index/1995/QTR1/master.gz returns 404 file not found error. It does not work for any quarter.
I wasted so much time on this seemingly simple thing which is supposed to work but it is just not working.... could you copy past this and run..is it working for you?
The code below gets the master files from QTR folders. Pasting my code ::
—————-
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
$ua->timeout(250);
$ua->env_proxy;
for($year=1995; $year<1996; $year=$year+1){
for($i=1; $i<5; $i=$i+1){
$quarter = “QTR” . $i;
$filegrag = “ftp://ftp.sec.gov/edgar/full-index/” . $year . “/” . $quarter . “/master.gz”;
print $filegrag;
# This command gets the file from EDGAR
my $response = $ua->get($filegrag);
print $response;
print $response->status_line;
# Now just pipe the output to a file named appropriately
$filename = $year . $quarter . “master”;
open(MYOUTFILE, “>” . $filename);
if ($response->is_success) {
print MYOUTFILE $response->decoded_content;
}
else {
die $response->status_line;
}
close(MYOUTFILE);
}
}
I realized that there were some firewall issues that were causing the problem I had. Now things are fine.

Perl WWW::Mechanize methods not working in AIX

I have a simple requirement of screen scraping a web-page (simple URL based reports) and direct the HTML response to an output file. The URL will however redirect to an authentication (HTTPS Login) page with "form based" authentication (no javascript) and upon authentication the report I am trying to view should show up in the $response (as HTML). Interestingly, my code is working just fine in a Windows machine, however the same code below is not working in AIX machine and it looks like the click_button() function call does nothing. I have tried click(), submit(), but none is working so instead of getting the actual report all I get is the logon screen in the HTML output file. Any ideas, what can be wrong?
use WWW::Mechanize;
use strict;
my $username = "admin";
my $password = "welcome1";
my $outpath = "/home/data/output";
my $fromday = 7;
my $url = "https://www.myreports.com/tax_report.php";
my $name = "tax_report";
my $outfile = "$outpath/$name.html";
my $mech = WWW::Mechanize->new(noproxy =>'0');
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year += 1900;
$mon++; # since it will start from 0
$mday--; # yesterdays date (to day)
$fromday = $mday - $days; #(from day)
#Create URL extension for generating report with previous date
my $dt_range = "?Y&dc_date1=$mon%2F$fromday%2F$year&dc_date2=$mon%2F$mday%2F$year";
my $url = $url . $dt_range;
$mech->get($url);
$mech->field(login => "$username");
$mech->field(passwd => "$password");
$mech->add_handler("request_send", sub { shift->dump; return });
$mech->add_handler("response_done", sub { shift->dump; return });
$mech->click_button(value=>"Login now");
my $response = $mech->content();
print "Generating report: $name...\n";
open (OUT, ">>$outfile")|| die "Cannot create report file $outfile";
print OUT "$response";
close OUT;
The WWW::Mechanize version in both the Machines are same i.e. 1.54 but the Win machine perl version is 5.10.1 whereas the AIX machine's Perl version is 5.8.8.
Other Alternatives Used -
my $inputobject=$mech->current_form()->find_input( undef,'submit' );
print $inputobject->value . "\n";
$mech->click_button(input => $inputobject);
print $mech->status() . "\n";
The $inputobject shows the correct button element as in the HTML source and the second print returns a status of 200 which apparently stands for OK. But its still not working in the AIX machine.
UPDATE- It seems that the site I am trying to connect to has an un-trusted SSL certificate. I tried the program on three different machines Windows PC, Mac and AIX. On the Windows Machine the program works and I was able to login to the website through the browsers (Chrome, Firefox,IE). However in Mac, the login just won't work (through the browsers) and it shows an un-trusted certificate error (or warning!) this probably means the proxy settings are not set up, the Perl program won't work either. And lastly the AIX where the Perl is not working as well. Not sure how to bypass this un-trusted SSL certificate issue here. Any help will be appreciated.
UPDATE2: Included below lines of code in the script to see logging details and found that I was being re-directed (HTTP 302) since my IP was filtered by the server Firewall. Once the AIX ip was added to the server's firewall exception the script worked perfectly. The two lines below were the life saver-
$mech->add_handler("request_send", sub { shift->dump; return });
$mech->add_handler("response_done", sub { shift->dump; return });
Can you use the following line before my $mech = WWW::Mechanize->new(noproxy =>'0'); of your perl code and try again ?
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;

SNMP v3 with NET::SNMP working, but snmpwalk/snmpget not?

I have the following (working) perl script:
use Net::SNMP;
# create session to the host
my ($session, $error) = Net::SNMP->session(
-hostname => $hostname,
-version => 'snmpv3',
-username => 'my_user_name',
-authkey => 'my_authkey',#actually, here stands the real authkey as configured on the switch
-privkey => 'my_privkey',#same as on switch
-authprotocol => 'sha',
-privProtocol => 'des'
);
if (!defined($session)) {
print $error . "\n";
last;
}
# retrieve a table from the remote agent
my $result = $session->get_table(
-baseoid => $MAC_OID
);
if (!defined($result)) {
print $session->error . "\n";
$session->close;
last;
}
#print out the result of the snmp query
#....
Now I wanted to use snmpwalk or snmpget with the same keys. For that, I created a snmp.conf file in .snmp of my home directory with the following content:
defSecurityName my_user_name
defContext ""
defAuthType SHA
defSecurityLevel authPriv
defAuthPassphrase my_auth_key here
defVersion 3
defPrivPassphrase my_privkey here
defPrivType DES
As I see it, I use the same credentials in the script and for snmpget. Why do I get snmpget: Authentication failure (incorrect password, community or key) ?
That depends on the version of snmpget and snmpset you use. When I tested an older version of net-snmp against my C# based SNMP agent http://sharpsnmplib.codeplex.com I noticed that for SHA authen mode + DES privacy mode a bug prevented the net-snmp command line tools from generating the correct message bytes (the encryption is wrong so that no agent can decrypt it).
My suggestion is that you try to use Net::SNMP instead, as like you found out, it is not affected by the same bug.
Your problem is that you're using an authentication key for Net::SNMP and a password for the command-line net-snmp tools. Based on your Net::SNMP usage you're actually using 'localized' keys. Which means the right tokens for your snmp.conf file are:
defAuthLocalizedKey 0xHEXSTRING
defPrivLocalizedKey 0xHEXSTRING
See the snmp.conf manual page for further details.

Why can't I connect to my CAS server with Perl's AuthCAS?

I'm attempting to use an existing CAS server to authenticate login for a Perl CGI web script and am using the AuthCAS Perl module (v 1.3.1). I can connect to the CAS server to get the service ticket but when I try to connect to validate the ticket my script returns with the following error from the IO::Socket::SSL module:
500 Can't connect to [CAS Server]:443 (Bad hostname '[CAS Server]')
([CAS Server] substituted for real server name)
Symptoms/Tests:
If I type the generated URL for the authentication into the web browser's location bar it returns just fine with the expected XML snippet. So it is not a bad host name.
If I generate a script without using the AuthCAS module but using the IO::Socket::SSL module directly to query the CAS server for validation on the generated service ticket the Perl script will run fine from the command line but not in the browser.
If I add the AuthCAS module into the script in item 2, the script no longer works on the command line and still doesn't work in the browser.
Here is the bare-bones script that produces the error:
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use AuthCAS;
use CGI::Carp qw( fatalsToBrowser );
my $id = $ENV{QUERY_STRING};
my $q = new CGI;
my $target = "http://localhost/cgi-bin/testCAS.cgi";
my $cas = new AuthCAS(casUrl => 'https://cas_server/cas');
if ($id eq ""){
my $login_url = $cas->getServerLoginURL($target);
printf "Location: $login_url\n\n";
exit 0;
} else {
print $q->header();
print "CAS TEST<br>\n";
## When coming back from the CAS server a ticket is provided in the QUERY_STRING
print "QUERY_STRING = " . $id . "</br>\n";
## $ST should contain the received Service Ticket
my $ST = $q->param('ticket');
my $user = $cas->validateST($target, $ST); #### This is what fails
printf "Error: %s\n", &AuthCAS::get_errors() unless (defined $user);
}
Any ideas on where the conflict might be?
The error is coming from the line directly above the snippet Cebjyre quoted namely
$ssl_socket = new IO::Socket::SSL(%ssl_options);
namely the socket creation. All of the input parameters are correct. I had edited the module to put in debug statements and print out all the parameters just before that call and they are all fine. Looks like I'm going to have to dive deeper into the IO::Socket::SSL module.
As usually happens when I post questions like this, I found the problem. It turns out the Crypt::SSLeay module was not installed or at least not up to date. Of course the error messages didn't give me any clues. Updating it and all the problems go away and things are working fine now.
Well, from the module source it looks like that IO::Socket error is coming from get_https2
[...]
unless ($ssl_socket) {
$errors = sprintf "error %s unable to connect https://%s:%s/\n",&IO::Socket::SSL::errstr,$host,$port;
return undef;
}
[...]
which is called by callCAS, which is called by validateST.
One option is to temporarily edit the module file to put some debug statements in if you can, but if I had to guess, I'd say the casUrl you are supplying isn't matching up to the _parse_url regex properly - maybe you have three slashes after the https?