Can't use an undefined value as a symbol reference - perl

I'm trying to use an API for a Palo Alto Networks software. The code is supposed to submit username and ipaddress of user network logins to a web interface.
When I try using PANs' API with their sample code for a windows machine the following exception is thrown:
Can't use an undefined value as a symbol reference at
C:/Perl/lib/PAN/API.pm line 179 (#1)
PAN::API::UID::login('PAN::API::UID=HASH(0x7fd113828598)', 'SCU-DSM22/pmmertens', 172.16.6.117) called at API_events.pl line 12
This is the code-example that comes with the API documentation:
#!/usr/bin/perl -w
use strict;
use PAN::API;
my $useridagent = '10.0.0.99'; #I changed this to our PAN server address
my $useridapi = PAN::API::UID->new($useridagent);
my $user = $ENV{USERDOMAIN}.'/'.$ENV{USERNAME};
my $ipaddress = unpack('W4',gethostbyname($ENV{COMPUTERNAME}));
$useridapi->login($user,$ipaddress);
I've ensure that all variables are retrieved correctly. Substituting literal values did not help either. Googling this error turned up references about hard and soft references but I don't see any infractions of these rules in the code below.
This is the codeblock from PAN/Api.pm. Line 179 is where the print starts.
sub submit () {
my $self = shift;
use IO::Socket::INET;
use IO::Socket::SSL;
my $socket = IO::Socket::INET->new(PeerAddr => $self->{server},
PeerPort => $self->{port},
Proto => 'tcp');
my $socketssl = IO::Socket::SSL->start_SSL( $socket,
SSL_version =>'TLSv1');
print $socketssl $self->xml;
$socketssl->close;
$socketssl->stop_SSL;
}

Both the IO::Socket::INET and IO::Socket::SSL lines should have error checking. Something like:
my $socket = IO::Socket::INET->new(....)
or die "Failed to create socket: $!"
And:
my $socketssl = IO::Socket::SSL->start_SSL(...)
or die "Failed to start SSL: ".IO::Socket::SSL::errstr();
Although instead of die I might go with Carp::confess.

Related

Thrift::TException=HASH(0x25d18e0) error

I am trying to connect to Hive via Perl module Thrift::API::HiveClient and below is the code to connect to Hadoop hive and retrieve the data
#!/usr/bin/perl
use DBI;
use DBI::DBD;
use Data::Dumper;
use List::MoreUtils qw(uniq);
use DateTime;
#use warnings 'all';
use POSIX qw(strftime);
use LWP::Simple;
use Thrift;
use Thrift::API::HiveClient;
use Data::Dumper;
my $latest_return;
# Database connection
my $client = Thrift::API::HiveClient->new(
host => 'localhost',
port => '10000',
);
$client->connect or die "Could not connect";
my $rh = $client->execute('select * from devtest.users');
my $return = [];
while ($latest_return = $client->fetch($rh)) { # will die with an error if it fails
print $latest_return;
}
When I execute the above script it throws below message
Thrift::TException=HASH(0x25d18e0)
I also tried Dumper to print the result nothing got printed.
any help is much appreciated.
OK, so the problem here is - you're doing something that's failing.
The module you import - Thrift::API::Hiveclient warns:
THIS CODE IS ALPHA-QUALITY, EXPERIMENTAL, AND LIKELY FLAMMABLE
Having said that - what is happening here, is for some the action is failing, and it's dieing with an error object.
That error object has status code and message with it. (I don't think this is idomatic perl though, it's more like Java :)).
So in the connect there's an error, that's not being handled properly so your code is dying.
A Thrift::TException is a fairly simple sort of object:
package Thrift::TException;
sub new {
my $classname = shift;
my $self = {message => shift, code => shift || 0};
return bless($self,$classname);
}
1;
Literally just a message and a code.
To get at that message, you'll need to dereference your object, and that's what doesn't seem to be happening.
My best guess is the _open method in Thrift::Socket is returning an error, and the HiveClient isn't actually trapping/handling it.
It should be doing an eval and trapping the error, and then unpacking the TException.
Somewhere here:
sub connect {
my ($self) = #_;
$self->_transport->open;
}
Maybe. I'm not 100% sure, because Moo might do something cute with die, but I can't find or see where that is.
So short answer - you're probably failing to connect, to be sure you'd need to grab that error message - to do that you'll need to hack the Hiveclient to eval the operation. This is what you signed up for by using a module that's "Alpha quality".

Cannot connect to SQLite database file using Perl CGI program

My problem is that: the outputs are different, when I run the program on the linux machine, and on a web browser of another machine.
When I run the program on the linux machine, the output is:
Content-type: text/plain
11
22
username password
But when I put the program on an Apache Server, and access it using a browser on another machine, the output is simply:
11
It is probably because the program fails to connect to the database file. As I have set all the files to mode 777, that I do not have the permission is unlikely a reason.
Anyone know what the problem is and how to fix it?
#!/usr/bin/perl -w
use DBI;
print ("Content-type: text/plain\n\n");
print "11\n";
my $dbh = DBI->connect("dbi:SQLite:dbname=4140.db","","",{RaiseError => 1},) or die $DBI::errstr;
print "22\n";
my $sth = $dbh -> prepare("SELECT * FROM Credential");
$sth -> execute();
($usrname, $password) = $sth -> fetchrow();
$sth -> finish();
$dbh->disconnect();
print "$usrname $password\n";
The die strings are sent to STDERR and so won't appear in the HTTP message that is sent. You can solve this several ways, one of the simplest being to write an error handler for DBI errors that prints the error message to STDOUT.
You should also always use strict and use warnings. That way Perl will highlight many simple errors that you could otherwise easily overlook. use warnings is far superior to -w on the command line.
Take a look at this code as an example. Note that if you enable RaiseError as well as providing an error handler then DBI will raise an exception only if your error handler returns a false value.
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
print ("Content-type: text/plain\n\n");
print "11\n";
my $dbh = DBI->connect('dbi:SQLite:dbname=4140.db','','',
{RaiseError => 1, PrintError => 0, HandleError => \&handle_error});
print "22\n";
my $sth = $dbh->prepare('SELECT * FROM Credential');
$sth->execute;
my ($usrname, $password) = $sth -> fetchrow();
print "$usrname $password\n";
sub handle_error {
my ($msg, $dbh, $rv) = #_;
print "DB Error: $msg\n";
0;
}
Yo should specify the complete path to your database file in order to avoid this kind of problems. Try this (if your database is at the same path as your script):
use FindBin '$Bin';
my $dbfile = "$Bin/4140.db";
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","","",{RaiseError => 1},) or die $DBI::errstr;
#...
Check your error log. You'll surely find that SQLite is failing to create 4140.db because of a permission error. You've made incorrect assumptions about the current directory.

Perl socket connection

Is it possible to create a socket connection to an open port on an end device.
If the connection drops print something?
I have seen a few examples but they require a server type script and a client, just looking for a client.
Thanks
Perl has sockets built right into it. You just need to load the standard Socket.pm module to get the constants you need.
The perlipc manpage tells you all about this. There are many higher-level modules that get at this more easily than the builtins, however. Some are even standard.
Here’s a CLI example:
% perl -MIO::Socket::INET -E '$him = new IO::Socket::INET "localhost:daytime" // die; print while <$him>'
Tue Jun 28 08:17:13 2011
Consider using the module IO::Socket::INET, http://www.thegeekstuff.com/2010/07/perl-tcp-udp-socket-programming/
A variation of this might fit your need:
use strict;
use warnings;
use constant
{ SOCKET_ERROR_MESSAGE => 'Some socket error message right here!'
, YOU_WANT_TO => 1
};
use IO::Select;
use IO::Socket::INET;
#ARGV = qw<server.domain.tld 8080> unless #ARGV;
sub handle_server_message {
...
}
my $sel
= IO::Select->new(
IO::Socket::INET->new(
PeerAddr => shift
, PeerPort => shift
));
# block until the server sends something that can be read.
while ( my ( $sock ) = $sel->can_read ) {
# you could just do this with $sock->eof...
if ( $sock->error and $sock->eof ) {
die MY_ERROR_MESSAGE if YOU_WANT_TO;
print MY_ERROR_MESSAGE;
}
else {
handle_server_message( $sock );
}
}

Can't create socket using IO::Socket

when I run the following code, the execution is just hanging there, No response at all.
does any of you can tell me what's wrong with the sample code?
use strict;
use warnings;
use IO::Select;
use IO::Socket;
my $s = new IO::Socket (
LocalPort => 8889,
Proto => 'tcp',
Listen => 16,
Reuse => 1
);
die "could not create socket $!\n" unless $s;
If you provide arguments to the IO::Socket constructor it demands a Domain argument. Check out the full source here, specifically the configure subroutine which gets called from the constructor if you've provided arguments.
sub new {
...
return scalar(%arg) ? $sock->configure(\%arg)
: $sock;
}
sub configure {
my($sock,$arg) = #_;
my $domain = delete $arg->{Domain};
croak 'IO::Socket: Cannot configure a generic socket' unless defined $domain;
....
}
Perhaps you're thinking of IO::Socket::INET?
what's wrong with the sample code?
IO::Socket is a generic super class for Perl sockets.
You need to replace the IO::Socket with IO::Socket::INET.

How do I authenticate into Gmail using Perl?

I've installed this module to gain access and controls within a Gmail inbox. However, when I try to connect through a small Perl script and test the functionality, I get this error message.
Error: Could not login with those credentials - could not find final URL
Additionally, HTTP error: 200 OK
This is an error built within the Gmail.pm module.
I can ping the URL in question ( https://www.google.com/accounts/ServiceLoginBoxAuth ) so I feel that the trouble isn't finding the URL. Furthermore, I know the credentials are correct and work at that URL because I have tried them manually.
I'm using this script for testing. I have supplied my credentials in the appropriate places.
I've also installed this module with the same type of error.
Any idea why I'm getting blocked?
Use Mail::IMAPClient as shown below. To get pass SSL authentication through Mail::IMAPClient, you should have IO::Socket::SSL from Net::SSLeay installed. If so this works like a charm.
#!/usr/bin/env perl
use strict; use warnings;
use Mail::IMAPClient;
# Connect to IMAP server
my $client = Mail::IMAPClient->new(
Server => 'imap.gmail.com',
User => 'yourusername',
Password => 'yourp4a55w0r&',
Port => 993,
Ssl => 1,
)
or die "Cannot connect through IMAPClient: $!";
# List folders on remote server (see if all is ok)
if ( $client->IsAuthenticated() ) {
print "Folders:\n";
print "- ", $_, "\n" for #{ $client->folders() };
};
# Say so long
$client->logout();
I am successfully accessing a gmail account (google apps account to be precise) using Mail::POP3Client
If you cannot access gmail through normal POP3 or IMAP either, then you have a configuration problem rather than a programming problem.
I fetch my mail from gmail (actually Google Apps, which uses the same interface), using configuration details described here: http://download.gna.org/hpr/fetchmail/FAQ/gmail-pop-howto.html
(This answer is far more appropriate for Super User though!)
You can tried with the following module
Mail::Webmail::Gmail
You can use the following code also
use warnings;
use strict;
use Mail::POP3Client;
use IO::Socket::SSL;
use CGI qw(:standard);
my $cgi = new CGI;
my $LOG ;
open $LOG , ">>filename" ;
my $username = 'name#gmail.com';
my $password = '*******' ;
chomp($password);
my $mailhost = 'pop.gmail.com';
my $port = '995';
$cgi->header();
my $pop = new Mail::POP3Client(
USER => $username,
PASSWORD => $password,
HOST => $mailhost,
PORT => $port,
USESSL => 'true',
DEBUG => 0,
);
if (($pop->Count()) < 1) {
exit;
}
print $pop->Count() . " messages found!:$!\n";
for(my $i = 1; $i <= $pop->Count(); $i++) {
foreach($pop->Head($i)) {
/^(From|Subject|Email):\s+/i && print $_, "\n";
}
$pop->BodyToFile($LOG,$i);
}
$pop->Close();
exit;