Index: configure.in =================================================================== RCS file: /projects/cvsroot/pgsql/configure.in,v retrieving revision 1.154 diff -u -r1.154 configure.in --- configure.in 2001/11/20 03:51:31 1.154 +++ configure.in 2001/11/28 05:25:19 @@ -454,7 +454,9 @@ AC_MSG_RESULT([building with Kerberos 5 support]) AC_DEFINE(KRB5, 1, [Define if you are building with Kerberos 5 support.]) - if test -d "$krb5_prefix/include"; then + if test -d "$krb5_prefix/include/krb5"; then + INCLUDES="$INCLUDES -I$krb5_prefix/include/krb5" + elif test -d "$krb5_prefix/include"; then INCLUDES="$INCLUDES -I$krb5_prefix/include" fi if test -d "$krb5_prefix/lib"; then @@ -731,11 +733,44 @@ AC_CHECK_LIB(krb, [krb_sendauth], [], [AC_MSG_ERROR([library 'krb' is required for Kerberos 4])]) fi +# +# We have to check krb5.h before we know which kerberos 5 libs to look at +# +if test "$with_krb5" = yes; then + AC_CHECK_HEADER(krb5.h, [], [AC_MSG_ERROR([header file is required for Kerberos 5])]) + AC_CHECK_HEADER(com_err.h, [], [AC_MSG_ERROR([header file is required for Kerberos 5])]) + +# Check for differences between MIT and Heimdal (KTH) releases + PGAC_CHECK_MEMBER([krb5_ticket.enc_part2], [], + [PGAC_CHECK_MEMBER([krb5_ticket.client], [], + [AC_MSG_ERROR([unable to determine how to get client name from Kerberos 5 ticket])], + [#include ])], + [#include ]) + PGAC_CHECK_MEMBER([krb5_error.text.data], [], + [PGAC_CHECK_MEMBER([krb5_error.e_data], [], + [AC_MSG_ERROR([unable to determine how to extract Kerberos 5 error messages])], + [#include ])], + [#include ]) +fi + if test "$with_krb5" = yes ; then - AC_CHECK_LIB(com_err, [com_err], [], [AC_MSG_ERROR([library 'com_err' is required for Kerberos 5])]) - AC_CHECK_LIB(crypto, [krb5_encrypt], [], - [AC_CHECK_LIB(k5crypto, [krb5_encrypt], [], [AC_MSG_ERROR([library 'crypto' or 'k5crypto' is required for Kerberos 5])])]) - AC_CHECK_LIB(krb5, [krb5_sendauth], [], [AC_MSG_ERROR([library 'krb5' is required for Kerberos 5])]) + AC_SEARCH_LIBS(com_err, [krb5 com_err], [], + [AC_MSG_ERROR([unable to find function 'com_err' required for Kerberos 5])]) + # + # Check for heimdal-specific libraries + # + if test x"$pgac_cv_member_krb5_ticket_client" = x"yes"; then + AC_SEARCH_LIBS(encode_KRB_PRIV, [asn1], [], + [AC_MSG_ERROR([unable to find function 'encode_KRB_PRIV' required for Heimdal Kerberos 5])]) + AC_SEARCH_LIBS(net_read, [roken], [], + [AC_MSG_ERROR([unable to find function 'net_read' required for Heimdal Kerberos 5])]) + AC_SEARCH_LIBS(SHA1_Init, [crypto], [], + [AC_MSG_ERROR([unable to find function 'SHA1_Init' required for Heimdal Kerberos 5])]) + fi + AC_SEARCH_LIBS(krb5_encrypt, [krb5 crypto k5crypto], [], + [AC_MSG_ERROR([unable to find function 'krb5_encrypt' required for Kerberos 5])]) + AC_SEARCH_LIBS(krb5_sendauth, [krb5], [], + [AC_MSG_ERROR([unable to find function 'krb5_sendauth' required for Kerberos 5])]) fi if test "$with_openssl" = yes ; then @@ -777,11 +812,6 @@ if test "$with_krb4" = yes ; then AC_CHECK_HEADER(krb.h, [], [AC_MSG_ERROR([header file is required for Kerberos 4])]) -fi - -if test "$with_krb5" = yes ; then - AC_CHECK_HEADER(krb5.h, [], [AC_MSG_ERROR([header file is required for Kerberos 5])]) - AC_CHECK_HEADER(com_err.h, [], [AC_MSG_ERROR([header file is required for Kerberos 5])]) fi if test "$with_openssl" = yes ; then Index: config/c-library.m4 =================================================================== RCS file: /projects/cvsroot/pgsql/config/c-library.m4,v retrieving revision 1.9 diff -u -r1.9 c-library.m4 --- config/c-library.m4 2001/09/07 19:52:53 1.9 +++ config/c-library.m4 2001/11/28 05:25:22 @@ -172,3 +172,96 @@ AC_DEFINE([STRING_H_WITH_STRINGS_H], 1, [Define if string.h and strings.h may both be included]) fi]) + + +# PGAC_CHECK_MEMBER(AGGREGATE.MEMBER, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [INCLUDES]) +# ----------------------------------------------------------- + +AC_DEFUN([PGAC_CHECK_MEMBER], +[changequote(<<, >>)dnl +dnl The name to #define. +define(<>, translit(HAVE_$1, [a-z .*], [A-Z__P]))dnl +dnl The cache variable name. +define(<>, translit(pgac_cv_member_$1, [ .*], [__p]))dnl +changequote([, ])dnl +AC_CACHE_CHECK([for $1], [pgac_cache_name], +[AC_TRY_COMPILE([$4], +[static ]patsubst([$1], [\..*])[ pgac_var; +if (pgac_var.]patsubst([$1], [^[^.]*\.])[) +return 0;], +[pgac_cache_name=yes], +[pgac_cache_name=no])]) + +if test x"[$]pgac_cache_name" = x"yes"; then + AC_DEFINE_UNQUOTED(pgac_define_name) + $2 +else + ifelse([$3], [], :, [$3]) +fi +undefine([pgac_define_name])[]dnl +undefine([pgac_cache_name])[]dnl +]) + + +# PGAC_CHECK_MEMBER(AGGREGATE.MEMBER, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [INCLUDES]) +# ----------------------------------------------------------- + +AC_DEFUN([PGAC_CHECK_MEMBER], +[changequote(<<, >>)dnl +dnl The name to #define. +define(<>, translit(HAVE_$1, [a-z .*], [A-Z__P]))dnl +dnl The cache variable name. +define(<>, translit(pgac_cv_member_$1, [ .*], [__p]))dnl +changequote([, ])dnl +AC_CACHE_CHECK([for $1], [pgac_cache_name], +[AC_TRY_COMPILE([$4], +[static ]patsubst([$1], [\..*])[ pgac_var; +if (pgac_var.]patsubst([$1], [^[^.]*\.])[) +return 0;], +[pgac_cache_name=yes], +[pgac_cache_name=no])]) + +if test x"[$]pgac_cache_name" = x"yes"; then + AC_DEFINE_UNQUOTED(pgac_define_name) + $2 +else + ifelse([$3], [], :, [$3]) +fi +undefine([pgac_define_name])[]dnl +undefine([pgac_cache_name])[]dnl +]) + + +# PGAC_CHECK_MEMBER(AGGREGATE.MEMBER, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [INCLUDES]) +# ----------------------------------------------------------- + +AC_DEFUN([PGAC_CHECK_MEMBER], +[changequote(<<, >>)dnl +dnl The name to #define. +define(<>, translit(HAVE_$1, [a-z .*], [A-Z__P]))dnl +dnl The cache variable name. +define(<>, translit(pgac_cv_member_$1, [ .*], [__p]))dnl +changequote([, ])dnl +AC_CACHE_CHECK([for $1], [pgac_cache_name], +[AC_TRY_COMPILE([$4], +[static ]patsubst([$1], [\..*])[ pgac_var; +if (pgac_var.]patsubst([$1], [^[^.]*\.])[) +return 0;], +[pgac_cache_name=yes], +[pgac_cache_name=no])]) + +if test x"[$]pgac_cache_name" = x"yes"; then + AC_DEFINE_UNQUOTED(pgac_define_name) + $2 +else + ifelse([$3], [], :, [$3]) +fi +undefine([pgac_define_name])[]dnl +undefine([pgac_cache_name])[]dnl +]) Index: src/backend/libpq/auth.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/libpq/auth.c,v retrieving revision 1.72 diff -u -r1.72 auth.c --- src/backend/libpq/auth.c 2001/11/05 17:46:25 1.72 +++ src/backend/libpq/auth.c 2001/11/28 05:25:30 @@ -43,12 +43,12 @@ char *pg_krb_server_keyfile; +static int CheckPAMAuth(Port *port, char *user, char *password); #ifdef USE_PAM #include #define PGSQL_PAM_SERVICE "postgresql" /* Service name passed to PAM */ -static int CheckPAMAuth(Port *port, char *user, char *password); static int pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg, struct pam_response ** resp, void *appdata_ptr); @@ -169,6 +169,7 @@ * krb5_an_to_ln, except that it punts if multiple components are found, * and we can't afford to punt. */ +#if 0 static char * pg_an_to_ln(char *aname) { @@ -178,6 +179,7 @@ *p = '\0'; return aname; } +#endif /* @@ -229,7 +231,7 @@ " Kerberos error %d\n", retval); com_err("postgres", retval, "while getting server principal for service %s", - pg_krb_server_keyfile); + PG_KRB_SRVNAM); krb5_kt_close(pg_krb5_context, pg_krb5_keytab); krb5_free_context(pg_krb5_context); return STATUS_ERROR; @@ -258,7 +260,7 @@ int ret; krb5_auth_context auth_context = NULL; krb5_ticket *ticket; - char *kusername; + char *localname; ret = pg_krb5_init(); if (ret != STATUS_OK) @@ -281,27 +283,46 @@ * authenticated. Use it to check the username obtained from the * postmaster startup packet. * - * I have no idea why this is considered necessary. + * For now require the kerberos username is the same as the + * PostgreSQL username. Eventually some sort of ACL scheme, a la + * ~/.k5login for telnet, would be nice. */ - retval = krb5_unparse_name(pg_krb5_context, - ticket->enc_part2->client, &kusername); + if ((localname = palloc(SM_USER)) == NULL) + { + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + "pg_krb5_recvauth: unable to allocate memory"); + com_err("postgres", 0, "while allocating memory"); + krb5_free_ticket(pg_krb5_context, ticket); + krb5_auth_con_free(pg_krb5_context, auth_context); + return STATUS_ERROR; + } + +#if defined(HAVE_KRB5_TICKET_ENC_PART2) + retval = krb5_aname_to_localname(pg_krb5_context, ticket->enc_part2->client, + SM_USER, localname); +#elif defined(HAVE_KRB5_TICKET_CLIENT) + retval = krb5_aname_to_localname(pg_krb5_context, ticket->client, + SM_USER, localname); +#else +#error "bogus configuration" +#endif if (retval) { snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb5_recvauth: krb5_unparse_name returned" + "pg_krb5_recvauth: krb5_aname_to_localname returned" " Kerberos error %d\n", retval); - com_err("postgres", retval, "while unparsing client name"); + com_err("postgres", retval, "while determining local name"); krb5_free_ticket(pg_krb5_context, ticket); krb5_auth_con_free(pg_krb5_context, auth_context); + pfree(localname); return STATUS_ERROR; } - kusername = pg_an_to_ln(kusername); - if (strncmp(port->user, kusername, SM_USER)) + if (strncmp(port->user, localname, SM_USER)) { snprintf(PQerrormsg, PQERRORMSG_LENGTH, "pg_krb5_recvauth: user name \"%s\" != krb5 name \"%s\"\n", - port->user, kusername); + port->user, localname); ret = STATUS_ERROR; } else @@ -309,7 +330,7 @@ krb5_free_ticket(pg_krb5_context, ticket); krb5_auth_con_free(pg_krb5_context, auth_context); - free(kusername); + pfree(localname); return ret; } @@ -463,11 +484,9 @@ case uaPassword: authmethod = "Password"; break; -#ifdef USE_PAM case uaPAM: authmethod = "PAM"; break; -#endif /* USE_PAM */ } elog(FATAL, "%s authentication failed for user \"%s\"", @@ -581,12 +600,12 @@ status = recv_and_check_password_packet(port); break; -#ifdef USE_PAM case uaPAM: +#ifdef USE_PAM pam_port_cludge = port; +#endif /* USE_PAM */ status = CheckPAMAuth(port, port->user, ""); break; -#endif /* USE_PAM */ case uaTrust: status = STATUS_OK; @@ -819,6 +838,17 @@ else return STATUS_ERROR; } +#else /* USE_PAM */ +static int +CheckPAMAuth(Port *port, char *user, char *password) +{ + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + "CheckPAMAuth: PAM not implemented on this server.\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + + return STATUS_ERROR; +} #endif /* USE_PAM */ @@ -918,9 +948,7 @@ case uaMD5: case uaCrypt: case uaReject: -#ifdef USE_PAM case uaPAM: -#endif /* USE_PAM */ status = STATUS_ERROR; break; Index: src/backend/libpq/hba.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/libpq/hba.c,v retrieving revision 1.78 diff -u -r1.78 hba.c --- src/backend/libpq/hba.c 2001/11/12 04:29:23 1.78 +++ src/backend/libpq/hba.c 2001/11/28 05:25:31 @@ -237,10 +237,8 @@ *userauth_p = uaMD5; else if (strcmp(token, "crypt") == 0) *userauth_p = uaCrypt; -#ifdef USE_PAM else if (strcmp(token, "pam") == 0) *userauth_p = uaPAM; -#endif else *error_p = true; line = lnext(line); Index: src/include/pg_config.h.in =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/pg_config.h.in,v retrieving revision 1.11 diff -u -r1.11 pg_config.h.in --- src/include/pg_config.h.in 2001/10/20 17:57:39 1.11 +++ src/include/pg_config.h.in 2001/11/28 05:25:41 @@ -56,9 +56,16 @@ /* Define to build with Kerberos 4 support (--with-krb4[=DIR]) */ #undef KRB4 -/* Define to build with Kerberos 5 support (--with-krb5[=DIR]) */ #undef KRB5 /* Kerberos name of the Postgres service principal (--with-krb-srvnam=NAME) */ #undef PG_KRB_SRVNAM @@ -621,6 +628,18 @@ /* Set to 1 if you have struct sockaddr_un */ #undef HAVE_STRUCT_SOCKADDR_UN + +/* Set to 1 if you have krb5_ticket.enc_part2 */ +#undef HAVE_KRB5_TICKET_ENC_PART2 + +/* Set to 1 if you have krb5_ticket.client */ +#undef HAVE_KRB5_TICKET_CLIENT + +/* Set to 1 if you have krb5_error.text.data */ +#undef HAVE_KRB5_ERROR_TEXT_DATA + +/* Set to 1 if you have krb5_ticket.e_data */ +#undef HAVE_KRB5_ERROR_E_DATA /* Set to 1 if type "long int" works and is 64 bits */ #undef HAVE_LONG_INT_64 Index: src/include/libpq/hba.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/libpq/hba.h,v retrieving revision 1.31 diff -u -r1.31 hba.h --- src/include/libpq/hba.h 2001/11/05 17:46:33 1.31 +++ src/include/libpq/hba.h 2001/11/28 05:25:42 @@ -38,10 +38,8 @@ uaIdent, uaPassword, uaCrypt, - uaMD5 -#ifdef USE_PAM - ,uaPAM -#endif /* USE_PAM */ + uaMD5, + uaPAM } UserAuth; typedef struct Port hbaPort; Index: src/interfaces/libpq/fe-auth.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v retrieving revision 1.63 diff -u -r1.63 fe-auth.c --- src/interfaces/libpq/fe-auth.c 2001/11/05 17:46:37 1.63 +++ src/interfaces/libpq/fe-auth.c 2001/11/28 05:25:48 @@ -403,9 +403,17 @@ { if (retval == KRB5_SENDAUTH_REJECTED && err_ret) { +#if defined(HAVE_KRB5_ERROR_TEXT_DATA) snprintf(PQerrormsg, PQERRORMSG_LENGTH, libpq_gettext("Kerberos 5 authentication rejected: %*s\n"), err_ret->text.length, err_ret->text.data); +#elif defined(HAVE_KRB5_ERROR_E_DATA) + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + libpq_gettext("Kerberos 5 authentication rejected: %*s\n"), + err_ret->e_data->length, err_ret->e_data->data); +#else +#error "bogus configuration" +#endif } else {