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

I have written a win32 service socket server to listen for connections and do a little authentication (this is not a security question) and issue some commands.

I don't want to have to connect with any particular telnet client ala putty or CRT etc.. so it should work for native win32 telnet.exe as well as the others.

I ask for the username and password like so..(please, I know it's plain text.. I haven't got to that yet...)

while ($new_remote = $sock->accept) { $new_remote->autoflush(1); print $new_remote "Welcome to MyListenSvc v$VERSIO +N\r\n"; print $new_remote "Please enter your username: \r\ +n"; chomp ($usrname = <$new_remote>); print $new_remote "Please enter your password: \r\ +n"; chomp ($password = <$new_remote>); while (length($password) < 8) { print $new_remote "Password is too short.(Must + be at least 8 characters).\r\n"; print $new_remote "Please enter your password: + \r\n"; chomp ($password = <$new_remote>); } unless (&AuthUser($usrname, $password)) { print $new_remote "Authentication Errors - Che +ck your username and password.\n"; &Update_Log("... Login FAILED\n"); close ($new_remote); last; } else { print $new_remote "Authenticated Successfully +"; print $new_remote "(Type help for a list of co +mmands)\r\n"; print $new_remote "Command: "; $sel->add($new_remote) if ($new_remote); last; } }
The &AuthUser sub look like so
sub AuthUser { my ($user, $pass) = @_; $user = substr($user, 0, -1); $pass = substr($pass, 0, -1); &Update_Log("Attempting to login as $usrname with $password... "); $auth_rc = 0; my $cipher = Crypt::CBC->new( { 'key' => "$pass", 'cipher' => 'Blowfish', 'iv' => '$KJh#(}q', 'regenerate_key' => 0, # default tr +ue 'padding' => 'space', 'prepend_iv' => 0 }); my $ciphertext = $cipher->encrypt("$user"); open PWD, "C:/MyListenSvc/bin/passwd" or return ($auth_rc); while (<PWD>) { if (m#\Q$ciphertext\E#) { &Update_Log("... Login OK\n"); $auth_rc = 1; last; } } close (PWD); return ($auth_rc); }
The above code works but what concerns me is the 2 lines
$user = substr($user, 0, -1); $pass = substr($pass, 0, -1);
If I don't do this the authentication never works. When I printed the username and password to a log file I saw that a little square appears after the username and password.. I think it comes from the return that is entered. I tried to chomp the username and password but that never worked. So after beating my head for far too long I just tried to remove the last character...

Can anyone tell me why this happens and also if there is a better way to rectify this than what I have in the above code.

BTW. I havent tried to telnet from any *nix boxes yet..

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

Replies are listed 'Best First'.
Re: Extra Character from telnet
by demerphq (Chancellor) on Dec 06, 2002 at 12:35 UTC
    To help you on this it would be useful if you did something like
    (my $hex_user=$user)=~s/(.)/sprintf("%02x",ord($1))/egs; print "User: '$user' = '$hex_user'\n";
    For both $user and $password. Then we could see what is up properly. Im guessing however that is due to $/ being different from what TELNET thinks is a newline. Its quite possible that your OS thinks $/ is "\x0A" and Telnet thinks that \n is "\x0D\x0A" and since chomp only removes $/ from the end of a line it doesnt get the "\x0D". If this is so then
    $user=~s/\x0D\x0A$//;
    Probably would be the solution.

    UPDATE: Oops, didnt notice that you were on Win32. In this case I suspect its a similar problem, but with different values, ie not "\x0D\x0A". Show use the hex output of what you've got for the user value eh..

    HTH

    --- demerphq
    my friends call me, usually because I'm late....

      This is running as a win32 service so I hade to output the print to a log file, this is what the code looked like...

      (my $hex_user=$user)=~s/(.)/sprintf("%02x",ord($1))/egs; &Update_Log("User: '$user' = '$hex_user'\n");
      This is what I got...
      14:46:07 - User: 'sriley ' = '7372696c65790d'
      hmmmm ... there is a little square after sriley that seems to translate to a lot of spaces..? in this node. The return should all appear on 1 line..

      Something like 14:46:07 - User: 'sriley^'= '7372696c65790d' the ^ is where that square is...

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

      Ok, I put the test before the chomp and now I no longer get the little square but what looks like a carriage return.

      15:5:52 - User: 'sriley ' = '7372696c65790d0a'

      -----
      Of all the things I've lost in my life, its my mind I miss the most.
        Ok, so there's a confusion what the end of line is here. The telnet client is sending a CRLF, and when you chomp it, you end up (for some reason) with only the CR. You could try messing with $/ to get chomp to cut off both chars. See perlvar for more details.

        -- Dan

Re: Extra Character from telnet
by demerphq (Chancellor) on Dec 06, 2002 at 14:11 UTC
    First off, im confused about the value of $/ on your machine. Are you doing this under AS perl or Cygwin perl?

    Anyway, it looks like I was right, but I go with limbic~region. Dont mess with $/ instead use

    s/[^[:graph:] ]//g foreach $user,$pass;
    Which will nuke any char that isnt in the below list
    !"#$%&'()*+,-./0123456789:;<=> ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~
    Which im guessing is about right for legal chars (at least on an english machine) (note that a space is legal, but other whitespace chars arent.)

    --- demerphq
    my friends call me, usually because I'm late....

Re: Extra Character from telnet
by Limbic~Region (Chancellor) on Dec 06, 2002 at 13:40 UTC
    I am not going to repeat what has been said before - the problem is obvious the difference between return/new line/etc between different OS's. It may be useful instead of trying to get rid of the offending character to build the regex to remove any non-allowable character from the user name & password. I know you didn't want to address security, but this may also help in people intentionally trying to put newlines in the middle by less reputable means than using an actual telnet client.