Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit04c1f72

Browse files
committed
PAM authentication:
> pam_strerror() should be used a few more times, rather than just saying> "Error!". Also, the configure.in snippet seems wrong. You add> -I$pam_prefix/include/security to $INCLUDES and then you #include> <security/pam_appl.h>. This whole thing is probably unnecessary, since> PAM is a system library on the systems where it exists, so the headers> and libraries are found automatically, unlike OpenSSL and> Kerberos.See attached revised patch. (I'm sure the configure.in stuff can be doneright/better, I'm just not enough of a autoconf guru to know what tochange it to.)Dominic J. Eidson
1 parent2a34134 commit04c1f72

File tree

7 files changed

+290
-17
lines changed

7 files changed

+290
-17
lines changed

‎configure.in

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,6 @@ PGAC_ARG_BOOL(with, perl, no, [ --with-perl build Perl interface an
432432
AC_MSG_RESULT([$with_perl])
433433
AC_SUBST(with_perl)
434434

435-
436435
#
437436
# Optionally build Python interface module
438437
#
@@ -529,6 +528,23 @@ AC_DEFINE_UNQUOTED([PG_KRB_SRVNAM], ["$with_krb_srvnam"],
529528
[The name of the PostgreSQL service principal in Kerberos])
530529

531530

531+
#
532+
# PAM
533+
#
534+
AC_MSG_CHECKING([whether to build with PAM support])
535+
PGAC_ARG_OPTARG(with, pam,
536+
[ --with-pam[=DIR] build with PAM support [/usr]],
537+
[pam_prefix=/usr],
538+
[pam_prefix=$withval],
539+
[
540+
AC_MSG_RESULT([yes])
541+
AC_DEFINE([USE_PAM], 1, [Define to build with PAM support])
542+
543+
],
544+
[AC_MSG_RESULT(no)])
545+
546+
AC_SUBST(with_pam)
547+
532548

533549
#
534550
# OpenSSL
@@ -752,11 +768,14 @@ if test "$with_openssl" = yes ; then
752768
AC_CHECK_LIB(ssl, [SSL_library_init], [], [AC_MSG_ERROR([library 'ssl' is required for OpenSSL])])
753769
fi
754770

771+
if test "$with_pam" = yes ; then
772+
AC_CHECK_LIB(pam, [pam_start], [], [AC_MSG_ERROR([library 'pam' is required for PAM])])
773+
fi
774+
755775
if test "$enable_nls" = yes ; then
756776
PGAC_CHECK_GETTEXT
757777
fi
758778

759-
760779
##
761780
## Header files
762781
##
@@ -794,6 +813,10 @@ if test "$with_openssl" = yes ; then
794813
AC_CHECK_HEADER([openssl/err.h], [], [AC_MSG_ERROR([header file <openssl/err.h> is required for OpenSSL])])
795814
fi
796815

816+
if test "$with_pam" = yes ; then
817+
AC_CHECK_HEADER([security/pam_appl.h], [], [AC_MSG_ERROR([header file <security/pam_appl.h> is required for PAM])])
818+
fi
819+
797820

798821
##
799822
## Types, structures, compiler characteristics

‎doc/src/sgml/client-auth.sgml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.17 2001/08/16 16:24:15 momjian Exp $ -->
1+
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.18 2001/09/06 03:23:38 momjian Exp $ -->
22

33
<chapter id="client-authentication">
44
<title>Client Authentication</title>
@@ -278,6 +278,27 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
278278
</para>
279279
</listitem>
280280
</varlistentry>
281+
282+
<varlistentry>
283+
<term>pam</term>
284+
<listitem>
285+
<para>
286+
This authentication type operates similar to
287+
<firstterm>password</firstterm>, with the main difference that
288+
it will use PAM (Pluggable Authentication Modules) as the
289+
authentication mechanism. The <replaceable>authentication
290+
option</replaceable> following the <literal>pam</> keyword
291+
specifies the service name that will be passed to PAM. The
292+
default service name is <firstterm>postgresql</firstterm>.
293+
For more information about PAM, please read <ulink
294+
url="http://www.kernel.org/pub/linux/libs/pam/">Linux-PAM
295+
Page</ulink> and <ulink
296+
url="http://www.sun.com/software/solaris/pam/">Solaris-PAM
297+
Page</ulink>.
298+
</para>
299+
</listitem>
300+
</varlistentry>
301+
281302
</variablelist>
282303

283304
</para>

‎src/backend/libpq/auth.c

Lines changed: 224 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.64 2001/08/21 15:21:25 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.65 2001/09/06 03:23:38 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -43,6 +43,24 @@ static intrecv_and_check_passwordv0(Port *port);
4343

4444
char*pg_krb_server_keyfile;
4545

46+
#ifdefUSE_PAM
47+
#include<security/pam_appl.h>
48+
49+
#definePGSQL_PAM_SERVICE "postgresql"/* Service name passed to PAM */
50+
51+
staticintCheckPAMAuth(Port*port,char*user,char*password);
52+
staticintpam_passwd_conv_proc(intnum_msg,conststructpam_message**msg,
53+
structpam_response**resp,void*appdata_ptr);
54+
55+
staticstructpam_convpam_passw_conv= {
56+
&pam_passwd_conv_proc,
57+
NULL
58+
};
59+
60+
staticchar*pam_passwd=NULL;/* Workaround for Solaris 2.6 brokenness */
61+
staticPort*pam_port_cludge;/* Workaround for passing "Port
62+
* *port" into pam_passwd_conv_proc */
63+
#endif/* USE_PAM */
4664

4765
#ifdefKRB4
4866
/*----------------------------------------------------------------
@@ -428,6 +446,11 @@ auth_failed(Port *port)
428446
caseuaPassword:
429447
authmethod="Password";
430448
break;
449+
#ifdefUSE_PAM
450+
caseuaPAM:
451+
authmethod="PAM";
452+
break;
453+
#endif/* USE_PAM */
431454
}
432455

433456
elog(FATAL,"%s authentication failed for user \"%s\"",
@@ -525,15 +548,21 @@ ClientAuthentication(Port *port)
525548
status=recv_and_check_password_packet(port);
526549
break;
527550

528-
caseuaCrypt:
529-
sendAuthRequest(port,AUTH_REQ_CRYPT);
530-
status=recv_and_check_password_packet(port);
531-
break;
532-
533-
caseuaPassword:
534-
sendAuthRequest(port,AUTH_REQ_PASSWORD);
535-
status=recv_and_check_password_packet(port);
551+
caseuaCrypt:
552+
sendAuthRequest(port,AUTH_REQ_CRYPT);
553+
status=recv_and_check_password_packet(port);
554+
break;
555+
556+
caseuaPassword:
557+
sendAuthRequest(port,AUTH_REQ_PASSWORD);
558+
status=recv_and_check_password_packet(port);
559+
break;
560+
#ifdefUSE_PAM
561+
caseuaPAM:
562+
pam_port_cludge=port;
563+
status=CheckPAMAuth(port,port->user,"");
536564
break;
565+
#endif/* USE_PAM */
537566

538567
caseuaTrust:
539568
status=STATUS_OK;
@@ -577,7 +606,190 @@ sendAuthRequest(Port *port, AuthRequest areq)
577606
pq_flush();
578607
}
579608

609+
#ifdefUSE_PAM
610+
611+
/*
612+
* PAM conversation function
613+
*/
614+
615+
staticint
616+
pam_passwd_conv_proc (intnum_msg,conststructpam_message**msg,structpam_response**resp,void*appdata_ptr)
617+
{
618+
StringInfoDatabuf;
619+
int32len;
620+
621+
if (num_msg!=1||msg[0]->msg_style!=PAM_PROMPT_ECHO_OFF) {
622+
switch(msg[0]->msg_style) {
623+
casePAM_ERROR_MSG:
624+
snprintf(PQerrormsg,PQERRORMSG_LENGTH,
625+
"pam_passwd_conv_proc: Error from underlying PAM layer: '%s'\n",msg[0]->msg);
626+
fputs(PQerrormsg,stderr);
627+
pqdebug("%s",PQerrormsg);
628+
returnPAM_CONV_ERR;
629+
default:
630+
snprintf(PQerrormsg,PQERRORMSG_LENGTH,
631+
"pam_passwd_conv_proc: Unexpected PAM conversation %d/'%s'\n",
632+
msg[0]->msg_style,msg[0]->msg);
633+
fputs(PQerrormsg,stderr);
634+
pqdebug("%s",PQerrormsg);
635+
returnPAM_CONV_ERR;
636+
}
637+
}
638+
639+
if (!appdata_ptr) {
640+
/* Workaround for Solaris 2.6 where the PAM library is broken
641+
* and does not pass appdata_ptr to the conversation routine
642+
*/
643+
appdata_ptr=pam_passwd;
644+
}
645+
646+
/* Password wasn't passed to PAM the first time around - let's go
647+
* ask the client to send a password, which we then stuff into
648+
* PAM.
649+
*/
650+
if(strlen(appdata_ptr)==0) {
651+
sendAuthRequest(pam_port_cludge,AUTH_REQ_PASSWORD);
652+
if (pq_eof()==EOF||pq_getint(&len,4)==EOF) {
653+
returnPAM_CONV_ERR;/* client didn't want to send password */
654+
}
655+
656+
initStringInfo(&buf);
657+
pq_getstr(&buf);
658+
if (DebugLvl)
659+
fprintf(stderr,"received PAM packet with len=%d, pw=%s\n",
660+
len,buf.data);
661+
662+
if(strlen(buf.data)==0) {
663+
snprintf(PQerrormsg,PQERRORMSG_LENGTH,"pam_passwd_conv_proc: no password\n");
664+
fputs(PQerrormsg,stderr);
665+
returnPAM_CONV_ERR;
666+
}
667+
appdata_ptr=buf.data;
668+
}
669+
670+
/* Explicitly not using palloc here - PAM will free this memory in
671+
* pam_end()
672+
*/
673+
*resp=calloc(num_msg,sizeof(structpam_response));
674+
if (!*resp) {
675+
snprintf(PQerrormsg,PQERRORMSG_LENGTH,"pam_passwd_conv_proc: Out of memory!\n");
676+
fputs(PQerrormsg,stderr);
677+
pqdebug("%s",PQerrormsg);
678+
if(buf.data)
679+
pfree(buf.data);
680+
returnPAM_CONV_ERR;
681+
}
682+
683+
(*resp)[0].resp=strdup((char*)appdata_ptr);
684+
(*resp)[0].resp_retcode=0;
685+
686+
return ((*resp)[0].resp ?PAM_SUCCESS :PAM_CONV_ERR);
687+
}
688+
689+
690+
/*
691+
* Check authentication against PAM.
692+
*/
693+
staticint
694+
CheckPAMAuth(Port*port,char*user,char*password)
695+
{
696+
intretval;
697+
pam_handle_t*pamh=NULL;
698+
699+
/*
700+
* Apparently, Solaris 2.6 is broken, and needs ugly static
701+
* variable workaround
702+
*/
703+
pam_passwd=password;
704+
705+
/* Set the application data portion of the conversation struct
706+
* This is later used inside the PAM conversation to pass the
707+
* password to the authentication module.
708+
*/
709+
pam_passw_conv.appdata_ptr= (char*)password;/* from password above, not allocated */
710+
711+
/* Optionally, one can set the service name in pg_hba.conf */
712+
if(port->auth_arg[0]=='\0') {
713+
retval=pam_start(PGSQL_PAM_SERVICE,"pgsql@",&pam_passw_conv,&pamh);
714+
}else {
715+
retval=pam_start(port->auth_arg,"pgsql@",&pam_passw_conv,&pamh);
716+
}
717+
718+
if (retval!=PAM_SUCCESS) {
719+
snprintf(PQerrormsg,PQERRORMSG_LENGTH,
720+
"CheckPAMAuth: Failed to create PAM authenticator: '%s'\n",
721+
pam_strerror(pamh,retval));
722+
fputs(PQerrormsg,stderr);
723+
pqdebug("%s",PQerrormsg);
724+
pam_passwd=NULL;/* Unset pam_passwd */
725+
returnSTATUS_ERROR;
726+
}
727+
728+
if (retval==PAM_SUCCESS) {
729+
retval=pam_set_item(pamh,PAM_USER,user);
730+
}else {
731+
snprintf(PQerrormsg,PQERRORMSG_LENGTH,
732+
"CheckPAMAuth: pam_set_item(PAM_USER) failed: '%s'\n",
733+
pam_strerror(pamh,retval));
734+
fputs(PQerrormsg,stderr);
735+
pqdebug("%s",PQerrormsg);
736+
pam_passwd=NULL;/* Unset pam_passwd */
737+
returnSTATUS_ERROR;
738+
}
739+
if (retval==PAM_SUCCESS) {
740+
retval=pam_set_item(pamh,PAM_CONV,&pam_passw_conv);
741+
}else {
742+
snprintf(PQerrormsg,PQERRORMSG_LENGTH,
743+
"CheckPAMAuth: pam_set_item(PAM_CONV) failed: '%s'\n",
744+
pam_strerror(pamh,retval));
745+
fputs(PQerrormsg,stderr);
746+
pqdebug("%s",PQerrormsg);
747+
pam_passwd=NULL;/* Unset pam_passwd */
748+
returnSTATUS_ERROR;
749+
}
750+
if (retval==PAM_SUCCESS) {
751+
retval=pam_authenticate(pamh,0);
752+
}else {
753+
snprintf(PQerrormsg,PQERRORMSG_LENGTH,
754+
"CheckPAMAuth: pam_authenticate failed: '%s'\n",
755+
pam_strerror(pamh,retval));
756+
fputs(PQerrormsg,stderr);
757+
pqdebug("%s",PQerrormsg);
758+
pam_passwd=NULL;/* Unset pam_passwd */
759+
returnSTATUS_ERROR;
760+
}
761+
if (retval==PAM_SUCCESS) {
762+
retval=pam_acct_mgmt(pamh,0);
763+
}else {
764+
snprintf(PQerrormsg,PQERRORMSG_LENGTH,
765+
"CheckPAMAuth: pam_acct_mgmt failed: '%s'\n",
766+
pam_strerror(pamh,retval));
767+
fputs(PQerrormsg,stderr);
768+
pqdebug("%s",PQerrormsg);
769+
pam_passwd=NULL;/* Unset pam_passwd */
770+
returnSTATUS_ERROR;
771+
}
772+
if (retval==PAM_SUCCESS) {
773+
retval=pam_end(pamh,retval);
774+
if(retval!=PAM_SUCCESS) {
775+
snprintf(PQerrormsg,PQERRORMSG_LENGTH,
776+
"CheckPAMAuth: Failed to release PAM authenticator: '%s'\n",
777+
pam_strerror(pamh,retval));
778+
fputs(PQerrormsg,stderr);
779+
pqdebug("%s",PQerrormsg);
780+
}
781+
782+
pam_passwd=NULL;/* Unset pam_passwd */
783+
784+
return (retval==PAM_SUCCESS ?STATUS_OK :STATUS_ERROR);
785+
}else {
786+
returnSTATUS_ERROR;
787+
}
788+
}
789+
790+
580791

792+
#endif/* USE_PAM */
581793

582794
/*
583795
* Called when we have received the password packet.
@@ -670,6 +882,9 @@ map_old_to_new(Port *port, UserAuth old, int status)
670882
caseuaMD5:
671883
caseuaCrypt:
672884
caseuaReject:
885+
#ifdefUSE_PAM
886+
caseuaPAM:
887+
#endif/* USE_PAM */
673888
status=STATUS_ERROR;
674889
break;
675890

‎src/backend/libpq/hba.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.68 2001/08/21 15:49:17 momjian Exp $
13+
* $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.69 2001/09/06 03:23:38 momjian Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -235,6 +235,10 @@ parse_hba_auth(List *line, ProtocolVersion proto, UserAuth *userauth_p,
235235
*userauth_p=uaMD5;
236236
elseif (strcmp(token,"crypt")==0)
237237
*userauth_p=uaCrypt;
238+
#ifdefUSE_PAM
239+
elseif (strcmp(token, "pam")==0)
240+
*userauth_p=uaPAM;
241+
#endif
238242
else
239243
*error_p= true;
240244
line=lnext(line);
@@ -277,7 +281,6 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
277281
line_number=lfirsti(line);
278282
line=lnext(line);
279283
Assert(line!=NIL);
280-
281284
/* Check the record type. */
282285
token=lfirst(line);
283286
if (strcmp(token,"local")==0)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp