Authen::PAM login doesn't work after Vintela flush - perl

I have a perl script that gets the username and password from an external process and then does user authentication using Vintela. Everything works perfectly until someone forces Vintela to flush it's cache. After the cache is flushed, the Authen::PAM module returns code 10, which means that it couldn't find the username.
If I run the "id $username" command in the shell and then run the script then everything returns to normal for that user. Or if the user SSH's into the system then Authen::PAM works perfectly.
On the production server user's don't SSH into the server and hence after Vintela flush, user's can't login anymore. I don't want to run the "id" command for every user before I authenticate them. Is there a way I can force the script or PAM module to look for user and then authenticate them ?
Script --
BEGIN {
unshift(#INC, "..", "/usr/local/staf/bin", "/usr/local/staf/lib", "C:/STAF/Bin");
}
use strict;
use PLSTAF;
require Authen::PAM;
my $GlobalUserName = <STDIN>;
my $GlobalPasswd = <STDIN>;
my $result = -1;
$GlobalPasswd = STAF::RemovePrivacyDelimiters($GlobalPasswd);
my $pamHandle = Authen::PAM->new("login", $GlobalUserName, \&conversionFunction);
$result = $pamHandle->pam_authenticate();
# force the destructor execution for PAM
$pamHandle = 0;
# When $result is 0 then user has been authenticated
if ($result == 0) {
print $result;
exit $result;
}
else {
exit $result;
}
sub conversionFunction {
my #response = ();
# PAM constants
my $pamEchoOn = Authen::PAM->PAM_PROMPT_ECHO_ON();
my $pamEchoOff = Authen::PAM->PAM_PROMPT_ECHO_OFF();
my $pamSuccess = Authen::PAM->PAM_SUCCESS();
while ( #_ ) {
my $code = shift;
my $msg = shift;
my $answer = "";
if ($code == $pamEchoOn) {
$answer = $GlobalUserName;
}
if ($code == $pamEchoOff) {
$answer = $GlobalPasswd;
}
# response is always in pairs, response code and the actual answer
push(#response, $pamSuccess, $answer);
}
push(#response, $pamSuccess);
return #response;
}

Related

perl LDAP entry not recognised

We are writing a Perl code (to be run from Unix) which will reset the password of a Windows AD User. (We are not using powershell as we have been asked not to use Windows scripts).
With the following Perl code, we are able to connect to the AD User directory and query the correct user.
#!/usr/bin/perl -w
#########################
#This script resets the password in active user directory
#########################
use strict;
use warnings;
use DBI;
use Net::LDAP;
use Net::LDAPS;
use Authen::SASL qw(Perl);
use Net::LDAP::Control::Paged;
use Time::Local;
my $CERTDIR = "<cert path>";
my $AD_PASS = "$CERTDIR/.VDIAD_pass";
my $sAN = "vahmed";
### Generate Random Password ###
my $randompass = askPasswd();
my $uninewpass;
my $mail;
my $fullname;
my $name;
my $distName;
my $finalresult;
my #AD_passwords = get_domain_pass();
my $result = reset_AD_Password();
#Reset AD user password
sub reset_AD_Password {
my $ad = Net::LDAP->new($AD_passwords[0]);
my $msg = $ad->bind(dn => "cn=$AD_passwords[2],$AD_passwords[1]",
password => $AD_passwords[3],
version => 3);
if ($msg->code)
{
print "Error :" . $msg->error() . "\n";
exit 2;
}
my $acc_name = 'sAMAccountName';
my $acc_fullname = 'displayName';
my $acc_base = 'manager';
my $acc_distName = 'distinguishedName';
my $acc_mail = 'mail';
my $act = $ad->search(
base => "$AD_passwords[1]",
filter => "(&(objectCategory=person)(sAMAccountName=$sAN))",
attrs => [$acc_name, $acc_fullname, $acc_distName, $acc_mail]);
die 1 if ($act->count() !=1 );
my $samdn = $act->entry(0)->dn;
$fullname = $samdn->get_value($acc_fullname);
$mail = $samdn->get_value($acc_mail);
}
}
However we get an error on the line:
$fullname = $samdn->get_value($acc_fullname);
$mail = $samdn->get_value($acc_mail);
The error states "Can't locate object method "get_value" via package (distinguished Name) (perhaps you forgot to load (distinguished Name))"
However the code works correctly when we replace $samdn with the following code:
foreach my $entry ($act->entries){
$name = $entry->get_value($acc_name);
$fullname = $entry->get_value($acc_fullname);
$distName = $entry->get_value($acc_distName);
$mail = $entry->get_value($acc_mail);
}
It would appear that the code is unable to identify $samdn as a Net::LDAP::Entry record.
We have tried typecasting $samdn but got the same error.
Could someone help in resolving this issue as we would not prefer to use the for loop just in case more that one record is returned by the search? Thanks in advance.
You are not assigning a Net::LDAP::Entry to $samdn. You are assigning the dn of the first entry.
# VVVV
my $samdn = $act->entry(0)->dn;
Get rid of that ->dn and it should work, if $act->entry(0) returns a Net::LDAP::Entry.

using Net::LDAPs with Net::LDAP::Control::Paged

I'm trying to use Net::LDAPs with Net::LDAP::CONTROL::PAGED to return many records via a privlidged bind, but so far I have failed, miserably. I've used this Net::LDAPs extensively in the past, but I've never been able to find any documentation suggesting that it is compatible with Net::LDAP:Control::Paged. Everything I find is related to Net::LDAP.
The error message I get is: Undefined subroutine &main::process_entry called at /usr/local/share/perl/5.20.2/Net/LDAP/Search.pm line 55, line 755
Here is my code:
sub Ldap636{
my ($filter) = $_[0];
my $USERNAME = 'username';
my $PASSWORD = 'password';
my $LDAP_SERVER = 'directory.domain.edu';
my $LDAP_SSL_PORT = '636';
my $LDAP_BASE = 'ou=people,dc=domain,dc=edu';
my $userDN = "uid=$USERNAME,ou=identities,ou=special,dc=domain,dc=edu";
my $ldap = Net::LDAPS->new($LDAP_SERVER, port => $LDAP_SSL_PORT) or die "Could not create LDAP object because:\n$!";
my $ldapMsg = $ldap->bind($userDN, password => $PASSWORD);
die $ldapMsg->error if $ldapMsg->is_error;
my $page = Net::LDAP::Control::Paged->new( size => 100 );
#args = (base => "$LDAP_BASE",
callback => \&process_entry,
filter => $filter,
control => [ $page ],
);
my $cookie;
while (1) {
my $result = $ldap->search(#args);
"LDAP error: server says ",$result->error,"\n" if $result->code;
foreach my $entry ($result->entries ) {
my $cn = $entry->get_value('cn');
my $desc = $entry->get_value('description');
print "$cn - $desc\n";
}
# Get cookie from paged control
my($resp) = $result->control( LDAP_CONTROL_PAGED ) or last;
$cookie = $resp->cookie or last;
$page->cookie($cookie);
}
$ldap->unbind;
}
The error message I get is: Undefined subroutine &main::process_entry
called at /usr/local/share/perl/5.20.2/Net/LDAP/Search.pm line 55,
line 755
You have written process_entry as a callback but you didn't write that subroutine. That's why you are getting the above error.

handle firebird events asynchronously with perl

I'm creating an info board app with data taken from firebird 1.5 database.
I would like not to use polling but events.
I've created sample trigger which fires up an event in firebird database.
Now I need a client to listen for and handle the event.
I've decided to go with perl.
Here is the doc DBD::Firebird.
I'm trying to go with async events.
Here's the code, I give the skeleton which won't work anyway.
The event won't fire up in perl. What am I doing wrong. Please help, thanks!
#!/usr/bin/perl
use DBI;
$dsn =<< "DSN";
dbi:Firebird:dbname=/home/firebird/dev/db.gdb;
host=localhost;
port=3050;
ib_dialect=3;
DSN
$dbh = DBI->connect($dsn, "user", "password");
# events of interest
#event_names = ("schedule_event");
$evh = $dbh->func(#event_names, 'ib_init_event');
my $cb = sub {.
print "got event";
};
$dbh->func($evh, $cb, 'ib_register_callback');
while (1) {
}
UPDATE:
ok here's the php script I'm going with right now, just leave it here maybe it helps someone:
<?php
declare(ticks = 1);
$username = "user";
$password = "password";
$host = 'localhost:/home/firebird/base/base.gdb';
$sockets = array();
$dbh = ibase_connect($host, $username, $password);
function event_handler($event_name, $link) {
echo $event_name . "\n";
send_message($event_name);
}
# we need to unregister event in firebird before exit
function terminate($signal) {
global $event;
if (is_null($event)) {
die ( "no event has been registered yet, exiting" );
} else {
ibase_free_event_handler($event);
die ( "unregistered evented and exiting\n" );
}
}
function send_message($msg)
{
$localsocket = 'tcp://127.0.0.1:8010';
$instance = stream_socket_client ($localsocket, $errno, $errstr);
fwrite($instance, json_encode(['message' => $msg, 'userId' => 824]) . \n");
}
$event = ibase_set_event_handler($dbh, "event_handler", "schedule_update");
pcntl_signal(SIGTERM, "terminate");
while (true) {
sleep(1);
}
?>

Mojolicious, redirects, session and trying to create an authentication system

I'm trying to get away from Basic Auth in my Mojolicious application. I am able to detect the absence of a session key and redirect to a login page. The login page then posts to my application and I authenticate to a back end process. That back end process is returning success and then my mojo app sets the session like thus:
$self->session( user => $name, groups => $groups );
in debugging this, $name and $group are both defined and valid. I then wish to redirect into the "protected" space of my app. The redirect lands in the right place but then fails to detect the $self->session('user') (is undef when debugging) I end up redirecting back to login repeatedly.
I'll include snippets of the setup below. What am I missing?
MyApp.pm
my $r = $self->routes;
$r->route('/verify')->via('post')->to('util-auth#verify')->name('verify');
$r->route('/login')->via('get')->to('util-auth#login')->name('login');
my $app = $r->under('/myapp')->to('util-auth#check');
$app->route('/foo')->via('get')->to('controller-api#foo')->name('foo');
MyApp::Util::Auth
sub verify {
my $self = shift;
my $name = $self->param('username');
my $pass = $self->param('password');
my $dest = "/myapp/foo"; # in the protected area
if ( $self->authenticate($name, $pass) ) {
my $groups = $self->get_groups($name);
$self->session(
user => $name,
groups => $groups,
);
}
else {
$self->flash( message => "invalid login..." );
}
$self->redirect_to($dest);
}
sub login {
my $self = shift;
$self->render(); # renders the login form
}
sub check {
my $self = shift;
my $user = $self->session('user');
return 1 if defined $user;
$self->redirect_to('/login');
return 0;
}
I was having a similar problem and I ended up putting these in stash. I think session is string based, mainly because a cookie is set with session info.
Why your verify function accept name, pass via #_ variable?
May be need to use $self->param('name') and $self->param('pass')?
See working example here:
https://gist.github.com/Logioniz/bdf6f22c00fc51798c43

Does any one have a working script of LoadRunner Automation API?

Currently I am writing Perl script that creates LoadRunner scenario, execute the test, collect the result, recover the environment and repeat the cycle again with different scenario variables.
I don't have a problem creating new scenario, adding generator, adding 2 groups + script + the run-time settings. But I am having a problem with:
Setting scenario schedule from "Scenario" to "Group".
Setting schedule per group
This the snippet of the code:
use strict;
use v5.10;
use Win32::OLE;
use Win32::OLE::Enum;
use Win32::OLE::Variant;
use Data::Dumper;
use Win32::OLE::Const 'LoadRunner Automation Library';
use constant False => Variant(VT_BOOL,'');
use constant True => Variant(VT_BOOL,1);
my $lrEngine = Win32::OLE->new('wlrun.LrEngine') or die "oops\n";
my $lrScenario = $lrEngine->Scenario();
my $rc = $lrScenario->new(0, 1); # do not save previous, Regular vusers based scenario
if ($rc != 0) {
print "Win32::OLE::LastError: ".Win32::OLE::LastError()."\n";
print "lrScenario->new(0, 1):rc: $rc\n";
}
# snip-snipped - add generator
# snip-snipped - add #groups definition
foreach my $group (#groups) {
print "scriptName: $group->{scriptName}\n";
my $scriptLocation = $group->{scriptLocation};
my $scriptName = Variant(VT_BSTR|VT_BYREF, $group->{scriptName});
{ # add $group->{scriptName} script
$rc = $lrScenario->Scripts->Add($scriptLocation, $scriptName);
if ($rc != 0) {
print "Win32::OLE::LastError: ".Win32::OLE::LastError()."\n";
print "lrScenario->Scripts->Add($scriptLocation, $scriptName):rc: $rc\n";
}
}
#############################################################################
my $groupName = Variant(VT_BSTR|VT_BYREF, $group->{groupName});
{ # add $group->{groupName} group
$rc = $lrScenario->Groups->Add($groupName);
if ($rc != 0) {
print "Win32::OLE::LastError: ".Win32::OLE::LastError()."\n";
print "lrScenario->Groups->Add:rc: $rc\n";
}
$rc = $lrScenario->Groups->Item($groupName)->AddVusers($scriptName, $hostname, 3);
if ($rc != 0) {
print "Win32::OLE::LastError: ".Win32::OLE::LastError()."\n";
print "lrScenario->Groups->Item($groupName)->AddVusers:rc: $rc\n";
}
}
#############################################################################
# snip-snipped - change group script run time setting
}
my $scheduleName = Variant(VT_BSTR|VT_BYREF, 'Schedule123');
my $lrManualScheduleData = $lrScenario->ManualScheduler->AddSchedule($scheduleName, lrGroupSchedule); # Scenario schedule mode
if (!$lrManualScheduleData) {
say "Win32::OLE::LastError: ".Win32::OLE::LastError();
say "lrScenario->ManualScheduler->AddSchedule:rc: $rc";
}
$rc = $lrScenario->ManualScheduler->SetCurrentSchedule($scheduleName);
if ($rc != 0) {
say "Win32::OLE::LastError: ".Win32::OLE::LastError();
say "lrScenario->ManualScheduler->SetCurrentSchedule:rc: $rc";
}
print "\$lrScenario->ManualScheduler->SetScheduleMode($scheduleName, lrGroupSchedule):";
$lrScenario->ManualScheduler->SetScheduleMode($scheduleName, lrGroupSchedule);
#LrManualScheduleMode -> lrGroupSchedule = 1, lrScenarioSchedule = 0
say "Win32::OLE::LastError: ".Win32::OLE::LastError();
$lrManualScheduleData->{'InitAllBeforeRun'} = 'True';
$lrManualScheduleData->{'DurationMode'} = 1;
$lrManualScheduleData->{'Duration'} = 60 * 60;
$lrManualScheduleData->{'RampupBatchSize'} = 1;
$lrManualScheduleData->{'RampupMode'} = lrRampupByGroupBatches;
$lrManualScheduleData->{'RampupTimeInterval'} = 5;
$lrManualScheduleData->{'RampdownBatchSize'} = 1;
$lrManualScheduleData->{'RampdownMode'} = lrRampupByGroupBatches;
$lrManualScheduleData->{'RampdownTimeInterval'} = 5;
$rc = $lrScenario->ManualScheduler->{'ScenarioStartTimeMode'} = 0; # Start scenario without delay
#test
say "$scheduleName: ".$lrScenario->ManualScheduler->Schedule($scheduleName)->{'Duration'}; # returns 300
I have the same problem. Setting those properties and then calling either setschedulemode or setcurrentschedule doesn't seem to work. The only workaround I have found is to use the setscheduledata method passing in xml. You will need to get the current xml for the scheduledata and then change the xml, passing in the modified xml to the setscheduledata method. Hopefully this helps
lrManualScheduleData data = engine.Scenario.ManualScheduler.get_Schedule("Schedule 1");
String scheduleXML,errStr;
int returncode = data.getScheduleData(out scheduleXML, out errStr);
// Manipulate the XML to set whatever schedule you want
data.SetScheduleData(scheduleXML, out errStr);