AcidHawk has asked for the wisdom of the Perl Monks concerning the following question:

Please excuse the long post but I thought that the code may help in making the question clear. Super Search did not turn up much to go on when I searched for "Win32 authentication". I have a W2k server that is NOT part of a domain. I can connect to it using

net use \\server\ips$ /user:me pass
'me' being a local user on the server and 'pass' being that users password. I am then able to control the services via Win32::Service. I came up with the following to connect and control the services but this that it is untidy... or is it..?
use strict; use warnings; use Win32::Service; my (%list, %status); my %STATE = ( 0 => 'unknown', 1 => 'stopped', 2 => 'starting', 3 => 'stopping', 4 => 'running', 5 => 'resuming', 6 => 'pausing', 7 => 'paused', ); my $display_name = shift @ARGV || die "usage: $0 ServiceName MachineNa +me\n"; my $machine = shift @ARGV || die "usage: $0 ServiceName MachineName\n" +; $machine = "\\\\$machine"; $machine =~ s/^\\{2}/\\\\/; print "Please enter the username to connect as:\n"; chomp (my $usr = <STDIN>); print "Please enter your Password:\n"; chomp (my $pwd = <STDIN>); my $cmd = "net use $machine\\ipc\$ /user:$usr $pwd"; print "$cmd\n"; system ("$cmd"); if (Win32::Service::GetServices($machine, \%list)) { if (defined $list{$display_name}) { if (Win32::Service::GetStatus($machine, $list{$display_name}, +\%status)) { print "=================================================== +==============================================\n"; print "The $display_name service on $machine is " . $STATE +{$status{CurrentState}} . "\n"; print "=================================================== +==============================================\n\n"; } else { print "Could not find the '$display_name' service.\n"; print "Names are case sensitive.\n"; } } } else { print "Could Not connect to $machine: "; print Win32::FormatMessage(Win32::GetLastError()), "\n"; } system ("net use $machine\\ipc\$ /d");

I have tried changing the authentication to use AdminMisc instead of the net use bit. like so...

use strict; use warnings; use Win32::AdminMisc; my $machine = shift @ARGV or die "Usage: $0 ServerName\n"; #$machine = Win32::NodeName() unless($machine = shift @ARGV); $machine = "\\\\$machine"; $machine =~ s/^\\{2}/\\\\/; print "Machine Name: $machine\n"; print "Please enter the username to connect as:\n"; chomp (my $usr = <STDIN>); print "Please enter your Password:\n"; chomp (my $pwd = <STDIN>); my $LogonUser = Win32::AdminMisc::GetLogonName(); print "Logon User: $LogonUser\n"; if (Win32::AdminMisc::UserCheckPassword($machine, $usr, $pwd)) { print "$pwd is correct password for $usr on $machine\n"; } else { print "Bad Username or Password\n"; } print "==============================================================\ +n\n"; if (Win32::AdminMisc::LogonAsUser("$machine", "$usr", "$pwd", LOGON32_ +LOGON_BATCH)){ print "Successfully logged on.\n"; } else { print "Failed to logon.\n\tError: ", Error(), "\n"; }

The UserCheckPassword works and I get "pwd is the correct password for me on \\server" and it fails if the pwd is incorrect. However the LogonAsUser always fails and the error that I get is "Error: The operation completed successfully." Is there a module that I can use to logon to another server without authenticating to a domain and instead use the remote servers local user account?


-----
Of all the things I've lost in my life, its my mind I miss the most.

Title edit by tye

Replies are listed 'Best First'.
Re: Win32 User Authentication
by mce (Curate) on Oct 28, 2002 at 15:40 UTC
    Hi,

    I think you encounders the LogonAsUser bug that incorrectly returns 1.

    You should use this routine to check the LogonAsUser routine

    Win32::AdminMisc::LogonAsUser( $Domain, $User, $Password); $UserName=Win32::AdminMisc::GetLoginName(); print "Failed to logon" if ( lc $User ne lc $UserName);
    (cf: Win32 Perl Programming, You should really buy this book).
    On windows, each workstation has it's own little SAM database. You can therefore prefectly connect to it using the accounts from it's local domain.

    At least, this is how I understood it from my NT courses.
    ---------------------------
    Dr. Mark Ceulemans
    Senior Consultant
    IT Masters, Belgium

      Thank you for drawing my attention to the fact that a LoginAsUser success returns a 1 as opposed to a 0.. I did read this but didn't pay attention to it.

      With this in mind though I still can't logon to a remote machine. The action fails.. I will be printing out more errors to try and track down the issue though.

      BTW - I batteled with this line for a bit $UserName=Win32::AdminMisc::GetLoginName(); only to find GetLoginName should be GetLogonName.

      I have ordered the book you mentioned. Look forward to finding out more.

      Thanks again.
      -----
      Of all the things I've lost in my life, its my mind I miss the most.
Re: Remote Win32 User Authentication
by TacoVendor (Pilgrim) on Oct 28, 2002 at 23:34 UTC

    I will not throw code out because I do not use anything other than dropping a command line 'net use' statement in my scripts like you do.

    You asked if using 'net use' was untidy. For people that know and understand the Win32::AdminMisc module at better than an intermediate level then untidy may be a correct word. For myself, I use the Win32::AdminMisc module for a few things, but not to login. I didn't want to have to research all of the error codes and deal with those when writing my code. I set my code that logs into workstations and servers to look for the success message that comes up when authenticated. If anything else pops up, that message is popped up on the screen in either a gui pop-up box, in the command window, or in a logfile (all depending on which OS I am scripting from, etc.).

    The other portion of your post I will try and give a hand with relates to logging into a remote workstation/server. The command line option that you pass the username with has a couple of ways it can be sent. Sending it like '/username:username' first checks the local machine you are running the script from for a matching username to send across. If a match is found, the credentials of that local account are sent across (domain name membership, unique identifying number from the SAM database, and password from the account the script is running under if no password is specified on the command line).

    The other piece you can add to it is '/username:domain\username'. This will specify an account belonging to the domain you specify. If no such user is found in that domain, an error will tell you so. If a password is not specified, it will send the one used by the account the script is running under.

    To use a local workstation account to authenticate, replace the domain bit from the last example with the worstation name as shown: '/username:workstation name\username'. Password passing falls under the same rules as above.

    I sure hope this helps. I can hold my own against most anyone with administration and real management of Win32 systems, but I am not quite the expert on making perl run perfectly on them. If you need more help, or if I am just way off base in what you are asking, then reply and I will do my best.

    -TV

Re: Remote Win32 User Authentication
by AcidHawk (Vicar) on Oct 29, 2002 at 05:53 UTC

    The AdminMisc docs says

    "This will log the current account on under a different account."

    The issue I have is that I want to authenticate to a machine where I am not currently loggen on. (I.e. I am logged onto my local machine as Admin and want to be able to list the services on a remote server that is not part of the domain (I.e.stand-alone) and is not aware of the user I am curently logged in as.)

    I am starting to think that I cannot do this with anything other than a 'net use'. If there is a module out there hiding somewhere, I would love to know about it.. otherwise I am going to have to stay with what I have.

    -----
    Of all the things I've lost in my life, its my mind I miss the most.
      Hello , May be using the win32API::Net package helps. I havent tried but seems likely. Regards, ananda