88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.68 2001/09/26 19:54:12 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.69 2001/10/18 22:44:37 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -37,7 +37,7 @@ static void sendAuthRequest(Port *port, AuthRequest areq);
3737static int checkPassword (Port * port ,char * user ,char * password );
3838static int old_be_recvauth (Port * port );
3939static int map_old_to_new (Port * port ,UserAuth old ,int status );
40- static void auth_failed (Port * port );
40+ static void auth_failed (Port * port , int status );
4141static int recv_and_check_password_packet (Port * port );
4242static int recv_and_check_passwordv0 (Port * port );
4343
@@ -341,17 +341,23 @@ recv_and_check_passwordv0(Port *port)
341341* password ,
342342* cp ,
343343* start ;
344+ int status ;
344345
345- pq_getint (& len ,4 );
346+ if (pq_getint (& len ,4 )== EOF )
347+ return STATUS_EOF ;
346348len -= 4 ;
347349buf = palloc (len );
348- pq_getbytes (buf ,len );
350+ if (pq_getbytes (buf ,len )== EOF )
351+ {
352+ pfree (buf );
353+ return STATUS_EOF ;
354+ }
349355
350356pp = (PasswordPacketV0 * )buf ;
351357
352358/*
353359 * The packet is supposed to comprise the user name and the password
354- * as C strings. Be carefulthe check that this is the case.
360+ * as C strings. Be carefulto check that this is the case.
355361 */
356362user = password = NULL ;
357363
@@ -379,13 +385,10 @@ recv_and_check_passwordv0(Port *port)
379385"pg_password_recvauth: badly formed password packet.\n" );
380386fputs (PQerrormsg ,stderr );
381387pqdebug ("%s" ,PQerrormsg );
382-
383- pfree (buf );
384- auth_failed (port );
388+ status = STATUS_ERROR ;
385389}
386390else
387391{
388- int status ;
389392UserAuth saved ;
390393
391394/* Check the password. */
@@ -395,15 +398,16 @@ recv_and_check_passwordv0(Port *port)
395398
396399status = checkPassword (port ,user ,password );
397400
398- pfree (buf );
399401port -> auth_method = saved ;
400402
401403/* Adjust the result if necessary. */
402404if (map_old_to_new (port ,uaPassword ,status )!= STATUS_OK )
403- auth_failed ( port ) ;
405+ status = STATUS_ERROR ;
404406}
405407
406- return STATUS_OK ;
408+ pfree (buf );
409+
410+ return status ;
407411}
408412
409413
@@ -420,10 +424,23 @@ recv_and_check_passwordv0(Port *port)
420424 * postmaster log, which we hope is only readable by good guys.
421425 */
422426static void
423- auth_failed (Port * port )
427+ auth_failed (Port * port , int status )
424428{
425429const char * authmethod = "Unknown auth method:" ;
426430
431+ /*
432+ * If we failed due to EOF from client, just quit; there's no point
433+ * in trying to send a message to the client, and not much point in
434+ * logging the failure in the postmaster log. (Logging the failure
435+ * might be desirable, were it not for the fact that libpq closes the
436+ * connection unceremoniously if challenged for a password when it
437+ * hasn't got one to send. We'll get a useless log entry for
438+ * every psql connection under password auth, even if it's perfectly
439+ * successful, if we log STATUS_EOF events.)
440+ */
441+ if (status == STATUS_EOF )
442+ proc_exit (0 );
443+
427444switch (port -> auth_method )
428445{
429446case uaReject :
@@ -455,6 +472,7 @@ auth_failed(Port *port)
455472
456473elog (FATAL ,"%s authentication failed for user \"%s\"" ,
457474authmethod ,port -> user );
475+ /* doesn't return */
458476}
459477
460478
@@ -477,10 +495,11 @@ ClientAuthentication(Port *port)
477495elog (FATAL ,"Missing or erroneous pg_hba.conf file, see postmaster log for details" );
478496
479497/* Handle old style authentication. */
480- else if (PG_PROTOCOL_MAJOR (port -> proto )== 0 )
498+ if (PG_PROTOCOL_MAJOR (port -> proto )== 0 )
481499{
482- if (old_be_recvauth (port )!= STATUS_OK )
483- auth_failed (port );
500+ status = old_be_recvauth (port );
501+ if (status != STATUS_OK )
502+ auth_failed (port ,status );
484503return ;
485504}
486505
@@ -505,9 +524,8 @@ ClientAuthentication(Port *port)
505524elog (FATAL ,
506525"No pg_hba.conf entry for host %s, user %s, database %s" ,
507526hostinfo ,port -> user ,port -> database );
508- return ;
527+ break ;
509528}
510- break ;
511529
512530case uaKrb4 :
513531sendAuthRequest (port ,AUTH_REQ_KRB4 );
@@ -533,11 +551,8 @@ ClientAuthentication(Port *port)
533551{
534552int on = 1 ;
535553if (setsockopt (port -> sock ,0 ,LOCAL_CREDS ,& on ,sizeof (on ))< 0 )
536- {
537554elog (FATAL ,
538555"pg_local_sendauth: can't do setsockopt: %s\n" ,strerror (errno ));
539- return ;
540- }
541556}
542557#endif
543558if (port -> raddr .sa .sa_family == AF_UNIX )
@@ -551,15 +566,16 @@ ClientAuthentication(Port *port)
551566status = recv_and_check_password_packet (port );
552567break ;
553568
554- case uaCrypt :
555- sendAuthRequest (port ,AUTH_REQ_CRYPT );
556- status = recv_and_check_password_packet (port );
557- break ;
569+ case uaCrypt :
570+ sendAuthRequest (port ,AUTH_REQ_CRYPT );
571+ status = recv_and_check_password_packet (port );
572+ break ;
558573
559- case uaPassword :
560- sendAuthRequest (port ,AUTH_REQ_PASSWORD );
561- status = recv_and_check_password_packet (port );
562- break ;
574+ case uaPassword :
575+ sendAuthRequest (port ,AUTH_REQ_PASSWORD );
576+ status = recv_and_check_password_packet (port );
577+ break ;
578+
563579#ifdef USE_PAM
564580case uaPAM :
565581pam_port_cludge = port ;
@@ -575,7 +591,7 @@ ClientAuthentication(Port *port)
575591if (status == STATUS_OK )
576592sendAuthRequest (port ,AUTH_REQ_OK );
577593else
578- auth_failed (port );
594+ auth_failed (port , status );
579595}
580596
581597
@@ -654,7 +670,7 @@ pam_passwd_conv_proc (int num_msg, const struct pam_message **msg, struct pam_re
654670
655671initStringInfo (& buf );
656672pq_getstr (& buf );
657- if (DebugLvl )
673+ if (DebugLvl > 5 )
658674fprintf (stderr ,"received PAM packet with len=%d, pw=%s\n" ,
659675len ,buf .data );
660676
@@ -786,10 +802,9 @@ CheckPAMAuth(Port *port, char *user, char *password)
786802}
787803}
788804
789-
790-
791805#endif /* USE_PAM */
792806
807+
793808/*
794809 * Called when we have received the password packet.
795810 */
@@ -801,11 +816,16 @@ recv_and_check_password_packet(Port *port)
801816int result ;
802817
803818if (pq_eof ()== EOF || pq_getint (& len ,4 )== EOF )
804- return STATUS_ERROR ;/* client didn't want to send password */
819+ return STATUS_EOF ;/* client didn't want to send password */
820+
805821initStringInfo (& buf );
806- pq_getstr (& buf );/* receive password */
822+ if (pq_getstr (& buf )== EOF )/* receive password */
823+ {
824+ pfree (buf .data );
825+ return STATUS_EOF ;
826+ }
807827
808- if (DebugLvl )
828+ if (DebugLvl > 5 ) /* this is probably a BAD idea... */
809829fprintf (stderr ,"received password packet with len=%d, pw=%s\n" ,
810830len ,buf .data );
811831
@@ -861,7 +881,7 @@ old_be_recvauth(Port *port)
861881default :
862882fprintf (stderr ,"Invalid startup message type: %u\n" ,msgtype );
863883
864- return STATUS_OK ;
884+ return STATUS_ERROR ;
865885}
866886
867887return status ;
@@ -914,4 +934,3 @@ map_old_to_new(Port *port, UserAuth old, int status)
914934
915935return status ;
916936}
917-