Add another AUTHTYPE for UNIX-domain connections - Mailing list pgsql-patches
From | Anton Berezin |
---|---|
Subject | Add another AUTHTYPE for UNIX-domain connections |
Date | |
Msg-id | 20011203015804.A42199@heechee.tobez.org Whole thread Raw |
Responses |
Re: Add another AUTHTYPE for UNIX-domain connections
|
List | pgsql-patches |
Hi, On some platforms, it is possible to reliably determine the effective credentials of a UNIX-domain peer. Such functionality is not to be missed from the PostgreSQL host-based authentication. Its use allows one to combine the convenience of the `trust' authmethod with a strict checking of the connectee's identity. I have chosen to re-use the existing pg_ident.conf mechanism for mapping system user names to Postgres user names; this should not present any problems since `ident' authmethod is only applicable over TCP connections, and the new `user' authmethod only works for local connections; one can always use different map names if one needs both methods to co-exist (which is in my opinion very unlikely, considering that the getpeereid() is a reliable method and that we all know how reliable ident is). The patch below implements this functionality, including necessary changes to configure.in; the only thing missing is documentation patches - something I do not feel qualified to do, since English is not my native language. The patch is against 7.1.3 tarball - though I would not be surprised if it applies fine against the current development version. I verified that it works as expected on FreeBSD 5.0-current. I gather it should work equally well on other platforms that have getpeereid(), which I believe are at this moment OpenBSD-current and NetBSD-current. Cheers, %Anton. diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/configure ./configure --- /tmp/postgresql-7.1.3/configure Thu Aug 16 20:36:31 2001 +++ ./configure Mon Dec 3 01:53:19 2001 @@ -5472,7 +5472,7 @@ EOF fi -for ac_func in fcvt getopt_long memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen fdatasync +for ac_func in fcvt getopt_long memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen fdatasync getpeereid do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:5479: checking for $ac_func" >&5 diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/configure.in ./configure.in --- /tmp/postgresql-7.1.3/configure.in Sun Dec 2 21:58:22 2001 +++ ./configure.in Mon Dec 3 01:53:20 2001 @@ -759,7 +759,7 @@ PGAC_VAR_INT_TIMEZONE AC_FUNC_ACCEPT_ARGTYPES PGAC_FUNC_GETTIMEOFDAY_1ARG -AC_CHECK_FUNCS([fcvt getopt_long memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen fdatasync]) +AC_CHECK_FUNCS([fcvt getopt_long memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen fdatasync getpeereid]) dnl Check whether <unistd.h> declares fdatasync(). AC_EGREP_HEADER(fdatasync, unistd.h, AC_DEFINE(HAVE_FDATASYNC_DECL)) diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/src/backend/libpq/auth.c ./src/backend/libpq/auth.c --- /tmp/postgresql-7.1.3/src/backend/libpq/auth.c Thu Mar 22 04:59:30 2001 +++ ./src/backend/libpq/auth.c Mon Dec 3 01:53:20 2001 @@ -439,6 +439,9 @@ auth_failed(Port *port) case uaCrypt: authmethod = "Password"; break; + case uaUser: + authmethod = "Peer eid"; + break; } sprintf(buffer, "%s authentication failed for user '%s'", @@ -536,6 +539,17 @@ be_recvauth(Port *port) break; +#ifdef HAVE_GETPEEREID + case uaUser: + if (authuser(port->sock, port->user, port->auth_arg) == STATUS_OK) + { + areq = AUTH_REQ_OK; + auth_handler = handle_done_auth; + } + + break; +#endif + case uaPassword: areq = AUTH_REQ_PASSWORD; auth_handler = handle_password_auth; @@ -762,6 +776,7 @@ map_old_to_new(Port *port, UserAuth old, { case uaCrypt: case uaReject: + case uaUser: status = STATUS_ERROR; break; diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/src/backend/libpq/hba.c ./src/backend/libpq/hba.c --- /tmp/postgresql-7.1.3/src/backend/libpq/hba.c Sat Feb 10 03:31:26 2001 +++ ./src/backend/libpq/hba.c Mon Dec 3 01:53:20 2001 @@ -125,6 +125,10 @@ read_hba_entry2(FILE *file, UserAuth *us *userauth_p = uaReject; else if (strcmp(buf, "crypt") == 0) *userauth_p = uaCrypt; +#ifdef HAVE_GETPEEREID + else if (strcmp(buf, "user") == 0) + *userauth_p = uaUser; +#endif else { *error_p = true; @@ -280,6 +284,11 @@ process_hba_record(FILE *file, hbaPort * read_hba_entry2(file, &port->auth_method, port->auth_arg, error_p); +#ifdef HAVE_GETPEEREID + if (!*error_p && port->auth_method == uaUser) + *error_p = true; +#endif + if (*error_p) goto syntax; @@ -781,8 +790,8 @@ verify_against_usermap(const char *pguse snprintf(PQerrormsg, PQERRORMSG_LENGTH, "verify_against_usermap: hba configuration file does not " "have the usermap field filled in in the entry that pertains " - "to this connection. That field is essential for Ident-based " - "authentication.\n"); + "to this connection. That field is essential for Ident- or " + "user-based authentication.\n"); fputs(PQerrormsg, stderr); pqdebug("%s", PQerrormsg); } @@ -867,6 +876,39 @@ authident(struct sockaddr_in * raddr, st return checks_out ? STATUS_OK : STATUS_ERROR; } +int +authuser(int sock, const char *postgres_username, + const char *auth_arg) +{ +/*--------------------------------------------------------------------------- + Get the effective credentials of a UNIX-domain peer. Then lookup the + local UNIX user password entry. Then look in the usermap file under + the usermap *auth_arg and see if that user is equivalent to + Postgres user *user. + + Return STATUS_OK if yes. +---------------------------------------------------------------------------*/ +#ifdef HAVE_GETPEEREID + bool checks_out; + uid_t euid; + gid_t egid; + struct passwd *pw; + + if (getpeereid(sock, &euid, &egid) != 0) + return STATUS_ERROR; + + setpwent(); + if ((pw = getpwuid(euid)) == NULL) + return STATUS_ERROR; + + verify_against_usermap(postgres_username, pw->pw_name, auth_arg, + &checks_out); + + return checks_out ? STATUS_OK : STATUS_ERROR; +#else + return STATUS_ERROR; +#endif +} #ifdef CYR_RECODE #define CHARSET_FILE "charset.conf" diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/src/backend/libpq/pg_hba.conf.sample ./src/backend/libpq/pg_hba.conf.sample --- /tmp/postgresql-7.1.3/src/backend/libpq/pg_hba.conf.sample Tue Nov 21 21:44:32 2000 +++ ./src/backend/libpq/pg_hba.conf.sample Mon Dec 3 01:53:20 2001 @@ -121,10 +121,17 @@ # # krb5: Kerberos V5 authentication is used. # +# user: The system user identity is verified using getpeereid() +# system call. This is only supported for local (UNIX +# socket) connections, and only on some platforms. The +# correspondence between local system users and the +# requested PostgreSQL username is established using the +# same method as for "ident" AUTHTYPE. +# # reject: Reject the connection. # # Local (UNIX socket) connections support only AUTHTYPEs "trust", -# "password", "crypt", and "reject". +# "password", "crypt", "user", and "reject". # Examples @@ -146,6 +153,11 @@ # host identifies him as (typically his Unix username): # # host template1 192.168.93.0 255.255.255.0 ident sameuser +# +# Allow any existing local unix user to connect to database "template1" +# using the same PostgreSQL username: +# +# local template1 user sameuser # # Allow a user from host 192.168.12.10 to connect to database "template1" # if the user's password in pg_shadow is correctly supplied: diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/src/include/config.h.in ./src/include/config.h.in --- /tmp/postgresql-7.1.3/src/include/config.h.in Sun Apr 15 00:55:02 2001 +++ ./src/include/config.h.in Mon Dec 3 01:53:20 2001 @@ -388,6 +388,9 @@ /* Define if you have the setproctitle function. */ #undef HAVE_SETPROCTITLE +/* Set to 1 if you have the getpeereid function. */ +#undef HAVE_GETPEEREID + /* Define if you have the pstat function. */ #undef HAVE_PSTAT diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/src/include/libpq/hba.h ./src/include/libpq/hba.h --- /tmp/postgresql-7.1.3/src/include/libpq/hba.h Thu Mar 22 05:00:47 2001 +++ ./src/include/libpq/hba.h Mon Dec 3 01:53:20 2001 @@ -35,7 +35,8 @@ typedef enum UserAuth uaTrust, uaIdent, uaPassword, - uaCrypt + uaCrypt, + uaUser } UserAuth; typedef struct Port hbaPort; @@ -43,5 +44,7 @@ typedef struct Port hbaPort; int hba_getauthmethod(hbaPort *port); int authident(struct sockaddr_in * raddr, struct sockaddr_in * laddr, const char *postgres_username, const char *auth_arg); +int authuser(int sock, const char *postgres_username, + const char *auth_arg); #endif -- | Anton Berezin | FreeBSD: The power to serve | | catpipe Systems ApS _ _ |_ | http://www.FreeBSD.org | | tobez@catpipe.net (_(_|| | tobez@FreeBSD.org | | +45 7021 0050 | Private: tobez@tobez.org |
pgsql-patches by date: