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

Hi Fellow Monks, After spending the last few weeks developing a client/server to handle requests for my program I have covered both encryption and message integrity via CBC::Blowfish_PP and Digex::MD5. This seems to work very well for client command that only require one response from the server, such as a true or false. However, one of the functions I am now trying to complete is one that enables the server to send several responses to one query via an array. I run into trouble when I have the client verify the integrity of the responses - it seems that when one does not match and the client requests a resend the resend works as it should, but the next response that gets received by the client is a duplicate of the one that was originally sent even though debug on the server shows that the correct response is being sent. I can only figure this is a problem with STDIO buffering the input from the server on the client-side and what I would like to do is once the client verifies the servers md5 checksum reset the STDIN if possible. If not possible, does anyone know a better way to do what I want? The code for the server follows:
foreach $confline (@domconf) { chomp($confline); my $resend2 = "no"; my $waitforok2 = "yes"; while ($waitforok2 eq "yes") { my $checkhash2 = GenerateMD5("confline: $confline"); if (defined($resend2) && $resend2 eq "yes") { print "$verify - Rebuilding Encryption Table: "; $cipher = new Crypt::CBC("$verify", 'Blowfish_PP'); } my $response2 = $cipher->encrypt("confline: $confline"); print $client "$checkhash2 $response2\n"; ($waitforok2, $resend2) = FinishUp2($client); } }
FinishUp2 is a function that receives either "OK" or "Resend" from the client...if OK it returns "no, no" and if Resend it returns "yes, no". Now here is the client code:
UNF: while ($waitforit eq "yes") { $cipher = new Crypt::CBC("$cipherkey", 'Blowfish_PP'); $ciphertext = $cipher->encrypt("$msg"); $hash = GenerateMD5("$msg"); print $client "$hash $ciphertext\n"; my ($argh) =0; while (<$client>) { my ($line) = $_; chomp($line); $argh++; if ($line =~ /Resend/) { next UNF; $resend = "yes";} $inhash = substr($line, 0, 32); $encrypted = substr($line, 33, length($_)-33); $plaintext = $cipher->decrypt($encrypted); $checkhash = GenerateMD5($plaintext); if ($inhash eq $checkhash) { if ($plaintext =~ /!!beginresponse/) { print $client "OK\n"; @data +=(); next; } if ($plaintext =~ /!!endresponse/) { print $client "Finished\n"; print "Number: $argh\n"; return @data; } if ($plaintext =~ /confline:\s+(.*)/) { print $client "OK\n"; push(@data, $1); } } else { $plaintext = ""; $inhash=""; $encrypted=""; $checkhash=""; print $client "Resend\n"; } } }
Let me know if you need any other info - I'll be glad to post it. -Adam Stanley Nethosters, Inc.

Replies are listed 'Best First'.
(tye)Re: problems with STDIO buffer?
by tye (Sage) on Mar 05, 2001 at 20:49 UTC

    Since noone has responded yet, I'll suggest you add the following two lines where appropriate:

    use IO::Handle; $client->autoflush(1);

    (and "where appropriate" probably means they won't be adjacent and the second one may appear more than once). Put the second one directly after you create the $client socket in both the client and the server.

            - tye (but my friends call me "Tye")