Cannot get any results with Net::SSLeay for openssl - perl

I am trying to create a script that looks at the data for my certs in my ~/ssl/certs folder and displays the issuer information to me.
It's written in perl and it would be easy to just say:
$data = `/usr/bin/openssl x509 -in $file -noout -issuer`
However that is not very portable. I am trying to use Net::SSLeay instead to get the same output, however all I can seem to manage are checksum numbers, what am I missing? Here is what I got
#!/usr/bin/perl
use 5.10.1;
use strict;
use warnings;
use Net::SSLeay qw(die_now die_if_ssl_error);
Net::SSLeay::load_error_strings();
Net::SSLeay::SSLeay_add_ssl_algorithms(); # Important!
Net::SSLeay::ENGINE_load_builtin_engines(); # If you want built-in engines
Net::SSLeay::ENGINE_register_all_complete(); # If you want built-in engines
Net::SSLeay::randomize();
Net::SSLeay::library_init();
Net::SSLeay::OpenSSL_add_all_algorithms();
my $file = '~/ssl/certs/certificate.crt';
my $x509 = Net::SSLeay::X509_new();
Net::SSLeay::X509_free($x509);
my $type = Net::SSLeay::X509_certificate_type($x509);
my $ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLSv1_method());
my $test = Net::SSLeay::X509_load_cert_file( $ctx, $file, $type );
my $info = Net::SSLeay::X509_issuer_name_hash($x509);
say "\nInfo = $info \nX509 = $x509\nTest= $test\nType = $type\nCTX = $ctx";
This is my output:
Info = 4003674586
X509 = 16119648
Test= 0
Type = 0
CTX = 16137888
I've read through all the source code and the documentation, none of it makes any sense.

You don't need all this context etc. After you've initialized the SSL library you can simply do:
my $bio = Net::SSLeay::BIO_new_file($file,'r') or die $!;
my $cert = Net::SSLeay::PEM_read_bio_X509($bio);
Net::SSLeay::BIO_free($bio);
$cert or die "cannot parse $file as PEM X509 cert: ".
Net::SSLeay::ERR_error_string(Net::SSLeay::ERR_get_error());
my $issuer = Net::SSLeay::X509_NAME_oneline(
Net::SSLeay::X509_get_issuer_name($cert));

This example may be able to get you started:
https://metacpan.org/source/MIKEM/Net-SSLeay-1.68/examples/x509_cert_details.pl
I've snipped the relevant bits from it to just get the issuer:
#!/usr/bin/perl
use strict;
use warnings;
use Net::SSLeay qw/XN_FLAG_RFC2253 ASN1_STRFLGS_ESC_MSB/;
Net::SSLeay::randomize();
Net::SSLeay::load_error_strings();
Net::SSLeay::ERR_load_crypto_strings();
Net::SSLeay::SSLeay_add_ssl_algorithms();
my $file = shift;
chomp($file);
my $bio = Net::SSLeay::BIO_new_file($file, 'rb') or die "ERROR: BIO_new_file failed";
my $x509 = Net::SSLeay::PEM_read_bio_X509($bio) or die "ERROR: PEM_read_bio_X509 failed";
my $issuer_name = Net::SSLeay::X509_get_issuer_name($x509);
print Net::SSLeay::X509_NAME_print_ex($issuer_name) . "\n";
So then:
$ perl ssl.pl /usr/share/ca-certificates/mozilla/XRamp_Global_CA_Root.crt
CN=XRamp Global Certification Authority,O=XRamp Security Services Inc,OU=www.xrampsecurity.com,C=US

Related

Zipping file in perl

I have been trying to zip files on remote windows server but not getting success by whatever i tried. Below is the small peice of code. Please tell me where m going wrong. This code is not producing any error but just not generating the zip file.
use strict;
use warnings;
# before running check perl module is installed in your PC.
use Archive::Zip;
use File::Basename 'basename';
my #files = ('D:\Scripts\Testing\abc.txt');
# if it is more than one file add it by using comma as separator
my $zip = Archive::Zip->new;
foreach my $file (#files) {
my $member = basename $file;
printf qq{Adding file "%s" as archive member "%s"\n}, $file, $member;
$zip->addFile( $file, $member );
printf "Member added\n";
}
printf "Writing to zip\n";
$zip->writeToFileNamed('zippedFolders.zip');
#zip file name change it as u want
Could you please:
use Cwd;
use strict;
use warnings;
# before running check perl module is installed in your PC.
use Archive::Zip;
use File::Basename;
my (#files,$dirname,$bsename) = "";
my $inFile = "D:\\Scripts\\Testing\\abc.txt"; # if it is more than one file add it by using comma as separator
my $curdir = getcwd();
#Need to open file here and to be read the file
open(IN, $inFile) || die "Cant \n";
while(<IN>) {
my $sngfile = $_;
chomp($sngfile);
push(#files, $sngfile);
}
my $zip = Archive::Zip->new();
foreach my $file (#files)
{
$dirname = dirname($file);
$bsename = basename($file);
#Check file exist here your code
if($dirname!~m/\.$/) {
print "$dirname\t$bsename\n";
#printf qq{Adding file "%s" as archive member "%s"\n}, $dirname, $bsename;
$zip->addFile("$dirname/$bsename"); }
}
printf "$curdir\\Writing to zip\n";
$zip->writeToFileNamed("$curdir/zippedFolders.zip"); #zip file name change it as u want

Can't find error "Global symbol #xx requires explicit package name"

I have checked the questions that may already have an answer and none of them have helped.
This is for my semester project for Unix Programming. I have created a script that compares HTML files to one other from a website.
The script worked perfectly as expected until I tried to implement the second website, so in turn I deleted the added code for the second website and now I get the errors
Global symbol "#master" requires explicit package name
Global symbol "#child" requires explicit package name
within the csite_md5 subroutine. I have gone through the code many times over and cannot see the problem.
I am looking for another set of eyes to see if I'm just missing something simple, which usually is the case.
Also I am new to Perl as this is my first time using the language.
#!/usr/bin/perl
use strict;
use warnings;
use Digest::MD5 qw(md5_hex);
use File::Basename;
# Path to the c-site download root directory
my $csite_dir = '/root/websites/c-site/wget/';
opendir my $dh, $csite_dir or die $!;
# Finds the sub directories c-site_'date +%F' where the c-site download is located
my #wget_subdir_csite = sort grep /^[^.]/, readdir $dh;
# Creates the absolute path to the c-site download
my $csite_master_dir = "$csite_dir$wget_subdir_csite[0]/dayzunderground.webs.com";
my $csite_child_dir = "$csite_dir$wget_subdir_csite[1]/dayzunderground.webs.com";
# Call to subroutine to append the .html file name to the absolute path
my #master_csite = &gethtml_master_csite($csite_master_dir);
my #child_csite = &gethtml_child_csite($csite_child_dir);
&csite_md5(\#master_csite, \#child_csite);
sub gethtml_master_csite{
my ($master_path) = #_;
opendir (DIR, $master_path) or die $!;
# Ends with .html and is a file
my #html_master = sort grep {m/\.html$/i && -f "$master_path/$_"} readdir(DIR);
my #files_master = ("$master_path/$html_master[0]","$master_path/$html_master[1]","$master_path/$html_master[2]","$master_path/$html_master[3]");
return #files_master
}
sub gethtml_child_csite{
my ($child_path) = #_;
opendir (DIR, $child_path) or die $!;
# Ends with .html and is a file
my #html_child = sort grep {m/\.html$/i && -f "$child_path/$_"} readdir(DIR);
my #files_child = ("$child_path/$html_child[0]","$child_path/$html_child[1]","$child_path/$html_child[2]","$child_path/$html_child[3]");
return #files_child
}
sub csite_md5{
my ($master, $child) = #_;
if(&md5sum($master[0]) ne &md5sum($child[0])){
my $filename = basename($master[0]);
system("diff -u -d -t --width=100 $master[0] $child[0] > ~/websites/c-site/diff/c-site-$filename-`date +%F`");
#print "1"
}
if(&md5sum($master[1]) ne &md5sum($child[1])){
my $filename2 = basename($master[1]);
system("diff -u -d -t --width=100 $master[1] $child[1] > ~/websites/c-site/diff/c-site-$filename2-`date +%F`");
#print "2"
}
if(&md5sum($master[2]) ne &md5sum($child[2])){
my $filename3 = basename($master[2]);
system("diff -u -d -t --width=100 $master[2] $child[2] > ~/websites/c-site/diff/c-site-$filename3-`date +%F`");
#print "3"
}
if(&md5sum($master[3]) ne &md5sum($child[3])){
my $filename4 = basename($master[3]);
system("diff -u -d -t --width=100 $master[3] $child[3] > ~/websites/c-site/diff/c-site-$filename4-`date +%F`");
#print "4"
}
}
sub md5sum{
my $file = shift;
my $digest = "";
eval{
open(FILE, $file) or die "Can't find file $file\n";
my $ctx = Digest::MD5->new;
$ctx->addfile(*FILE);
$digest = $ctx->hexdigest;
close(FILE);
};
if($#){
print $#;
return "";
}
return $digest
}
$master and $child are array references; use them like $master->[0]. $master[0] uses the array #master, which is a completely separate variable.
I thought it may help to go through your program and point out some practices that are less than optimal
You shouldn't use an ampersand & when calling a Perl subroutine. That was required in Perl 4 which was superseded about 22 years ago
It is preferable to use the File::Spec module to manipulate file paths, both to handle cases like multiple path separators and for portability. File::Spec will also do the job of File::BaseName
It is unnecessary to use the shell to create a date string. Use the Time::Piece module and localtime->ymd generates the same string as date +%F
It is neater and more concise to use map where appropriate instead of writing multiple identical assignments
The gethtml_master_csite and gethtml_child_csite subroutines are identical except that they use different variable names internally. They can be replaced by a single gethtml_csite subroutine
You should use lexical file and directory handles throughout, as you have done with the first opendir. You should also use the three-parameter form of open (with the open mode as the second parameter)
If an open fails then you should include the variable $! in the die string so that you know why it failed. Also, if you end the string with a newline then Perl won't append the source file and line number to the string when it is printed
As you have read, the csite_md5 attempts to use arrays #master and #child which don't exist. You have array references $master and $child instead. Also, the subroutine lends itself to a loop structure instead of writing the four comparisons explicitly
In md5sum you have used an eval to catch the die when the open call fails. It is nicer to check for this explicitly
The standard way of returning a false value from a subroutine is a bare return. If you return '' then it will evaluate as true in list context
With those chnages in place your code looks like this. Please ask if you have any problem understanding it. Note that I haven't been able to test it but it does compile
#!/usr/bin/perl
use strict;
use warnings;
use Digest::MD5 qw(md5_hex);
use File::Spec::Functions qw/ catdir catfile splitpath /;
use Time::Piece 'localtime';
my $csite_dir = '/root/websites/c-site/wget/';
opendir my $dh, $csite_dir or die qq{Unable to open "$csite_dir": $!};
my #wget_subdir_csite = sort grep /^[^.]/, readdir $dh;
my ($csite_master_dir, $csite_child_dir) = map
catdir($csite_dir, $_, 'dayzunderground.webs.com'),
#wget_subdir_csite[0,1];
my #master_csite = gethtml_csite($csite_master_dir);
my #child_csite = gethtml_csite($csite_child_dir);
csite_md5(\#master_csite, \#child_csite);
sub gethtml_csite {
my ($path) = #_;
opendir my $dh, $path or die qq{Unable to open "$path": $!};
my #files = sort grep { /\.html$/i and -f } map catfile($path, $_), readdir $dh;
return #files;
}
sub csite_md5 {
my ($master_list, $child_list) = #_;
for my $i ( 0 .. $#$master_list ) {
my ($master, $child) = ($master_list->[$i], $child_list->[$i]);
if ( md5sum($master) ne md5sum($child) ) {
my $filename = (splitpath($master))[-1]; # Returns (volume, path, file)
my $date = localtime->ymd;
system("diff -u -d -t --width=100 $master $child > ~/websites/c-site/diff/c-site-$filename-$date");
}
}
}
sub md5sum {
my ($file) = #_;
my $digest = "";
open my $fh, '<', $file or do {
warn qq{Can't open file "$file": $!}; # '
return;
};
my $ctx = Digest::MD5->new;
$ctx->addfile($fh);
return $ctx->hexdigest;
}

perl to move outlook emails to another folder

Hi I have a script that reads thru an email folder and if the subject line starts with 'test' it extracts the mail body to a txt file. I would like it to then move all 6 emails to another folder. but while the script extracts from all 6 emails in the folder, when i add the line ( $message->Move($tofolder); ) i can only get it to move 3 emails at once, not all of them!
I get warning: Use of uninitialized value in pattern match (m//) on ~ /^test /) ..... line
#!/usr/bin/perl
use strict;
use warnings;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Outlook';
my $filename = 'c:\\net.txt' ;
open(FH,"> $filename")
or die ("cannot open $filename");
my $outlook = Win32::OLE->new('Outlook.Application')
or die "Failed Opening Outlook.";
my $namespace = $outlook->GetNamespace("MAPI");
my $folder = $namespace->Folders("test")->Folders("test1");#->Folders; ("Junk Mail")->Folders("Bad");
my $tofolder = $namespace->Folders("test")->Folders("test1");#->Folders; ("Junk Mail")->Folders("Bad");
my $items = $folder->Items;
for my $itemIndex (1..$items->Count)
{
my $message = $items->item($itemIndex);
if ($message->{Subject} =~ /^test/){
print $message->{Subject}."\n";
print FH $message->{Body};
$message->Move($tofolder);
}
}
close(FH);
I'm afraid I'm not quite sure what's up - from the comments, an error on line 24 suggests that the thing you're accessing as a message doesn't have a 'Subject' field.
So it might actually not be a message at all.
I've tried something a bit like this (paraphrased a little) which seems to work:
#!/usr/bin/perl
use strict;
use warnings;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Outlook';
my $filename = 'c:\\net.txt';
open( my $output_fh, ">", $filename ) or die $!;
my $outlook = Win32::OLE->new('Outlook.Application')
or die "Failed Opening Outlook.";
my $namespace = $outlook->GetNamespace("MAPI");
my $archive = $namespace->GetDefaultFolder(6)->Folders('Archive');
my $deletedItems = $namespace->GetDefaultFolder(3);
my $items = $archive->Items;
foreach my $msg ( $items->in ) {
if ( $msg->{Subject} =~ m/^test/ ) {
print $msg ->{Subject}, "\n";
print {$output_fh} $msg->{Body};
$msg->Move($deletedItems);
}
}
close($output_fh);
This moves things from 'Archive' subfolder of 'Inbox' to Deleted Items. And extracts to a file as we go. Note that it just splurges 'body' to the output file, without any separators, so you probably want to do something more complicated. (I've taken to using $msg -> SaveAs so I can preserve the whole message object).

Incorrect File Download using mechanize response in Perl

I created a script which access a URL with basic authentication. Once I've passed the credentials, it will download the file in my local folder. The problem is I got an incorrect filename. Here's my sample code:
#!/usr/bin/env perl
use strict;
use warnings;
use WWW::Mechanize;
use HTTP::Cookies;
my $url = "http://sampleurl.com";
my $dir = 'C:\\pl';
my $mech = WWW::Mechanize->new();
$mech->cookie_jar(HTTP::Cookies->new());
$mech ->credentials("sampleurl.com:80", "sampleurl.com", "username", "password");
$mech->get($url);
my $res = $mech->res();
if($res->is_success){
my $filename = $res->filename();
print $filename;
$mech->save_content( $dir.'\\'.$filename, binmode => ':raw', decoded_by_headers => 1 );
print $mech->status;
}else{
print "Error";
}
exit 0;
Instead of downloading sample_url.DOC, it only downloaded sample with no file extension. can you help with my problem? I want to download the whole file.
There's no guarantee that $res->filename(); will produce a file extension or anything at all for that matter. The page you're currently reading doesn't have a filename extension for example.
You will have to guess a filename extension from the media type.
use MIME::Types qw(by_mediatype);
...
my $filename = $r->filename();
if(!$filename) { $filename = 'untitled'; }
if($filename !~ /\.[a-zA-Z0-9]{1,4}$/) {
my $type = $res->header('Content-Type');
my $ext = 'txt';
if($type) {
my #types = by_mediatype($type);
if($#types > -1) {
$ext = $types[0][0];
}
}
$filename .= '.' . $ext;
}
print $filename;

Perl download from url to local drive

I want to offer my visitors a file for download to their local machine (e.g. the Download directory in case of Windows7).
The code below works perfectly well, but only if the file is located on the same machine as the script:
#!/usr/bin/perl
my $path = "samples/10000.mp3"; ##PATH_TO_FILE
my $file = "10000.mp3";
print "Content-Type:application/octet-stream; name=\"$file\"\r\n";
print "Content-Disposition: attachment; filename=\"$file\"\r\n\n";
open( FILE, $path );
while(read(FILE, $buffer, 100) ){
print("$buffer");
}
The problem is that the file in question is located on another machine, so I have to get the url for download. I thought the coding below would do the trick, but no matter what I try, I end up with a downloaded file of 0 bytes. Can someone please tell me what I am doing wrong?
#!/usr/bin/perl
use LWP::Simple;
my $url = 'http://<sampleurl>.com';
my $file = '10000.mp3';
my $path = get($url);
print "Content-Type:application/octet-stream; name=\"$file\"\r\n";
print "Content-Disposition: attachment; filename=\"$file\"\r\n\n";
open my $fh, '+>', $path;
while(read($fh, $buffer, 100) ){
print("$buffer");
}
The get method in LWP::Simple returns the content, not the path to a file containing the content.
Once you have the content bits, write them to the standard output along with the header. Change your second program to
#! /usr/bin/perl
use LWP::Simple;
my $url = 'http://<sampleurl>.com';
my $file = '10000.mp3';
my $bits = get($url);
die "$0: get $url failed" unless defined $bits;
binmode STDOUT or die "$0: binmode: $!";
print qq[Content-Type:application/octet-stream; name="$file"\r\n],
qq[Content-Disposition: attachment; filename="$file"\r\n],
qq[\r\n],
$bits;