diff -ur postgresql-snapshot/configure.in postgresql-snapshot-ident-local/configure.in --- postgresql-snapshot/configure.in Tue Jul 31 10:00:07 2001 +++ postgresql-snapshot-ident-local/configure.in Wed Aug 1 01:16:03 2001 @@ -899,6 +899,19 @@ AC_DEFINE(HAVE_CBRT), AC_CHECK_LIB(m, cbrt, AC_DEFINE(HAVE_CBRT))) +AC_MSG_CHECKING([for SO_PEERCRED]) +AC_EGREP_CPP(yes, +#include +#ifdef SO_PEERCRED +yes +#endif +], +[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SO_PEERCRED) +], +[AC_MSG_RESULT(no)]) + # On HPUX 9, rint() is not in regular libm.a but in /lib/pa1.1/libm.a; # this hackery with HPUXMATHLIB allows us to cope. HPUXMATHLIB="" diff -ur postgresql-snapshot/doc/src/sgml/client-auth.sgml postgresql-snapshot-ident-local/doc/src/sgml/client-auth.sgml --- postgresql-snapshot/doc/src/sgml/client-auth.sgml Fri Jul 13 10:00:28 2001 +++ postgresql-snapshot-ident-local/doc/src/sgml/client-auth.sgml Wed Aug 1 01:37:45 2001 @@ -237,14 +237,21 @@ ident - - The ident server on the client host is asked for the identity - of the connecting user. Postgres - then verifies whether the so identified operating system user + + The identity of the user as determined on login to the + operating system is used by Postgres is allowed to connect as the database user that is requested. - This is only available for TCP/IP connections. It can be used - on the local machine by specifying the localhost address 127.0.0.1. - + For TCP/IP connections the identity is determined by contacting + the ident server on the client host. On operating systems + supporting SO_PEERCRED (only Linux at the time of this writing) + it is also possible to determine the identity of local users + connecting via unix domain sockets, and this keyword can + be used for both local and TCP/IP connections. On systems + without this capability it can only be specified for + TCP/IP connections; as a work-around it is possible to + specify the localhost address 127.0.0.1 and make connections + to this address. + The authentication option following the ident keyword specifies the name of an diff -ur postgresql-snapshot/src/backend/libpq/auth.c postgresql-snapshot-ident-local/src/backend/libpq/auth.c --- postgresql-snapshot/src/backend/libpq/auth.c Sat Jul 21 10:00:09 2001 +++ postgresql-snapshot-ident-local/src/backend/libpq/auth.c Wed Aug 1 00:51:04 2001 @@ -494,8 +494,7 @@ break; case uaIdent: - status = authident(&port->raddr.in, &port->laddr.in, - port->user, port->auth_arg); + status = authident(port); break; case uaPassword: @@ -654,8 +653,7 @@ break; case uaIdent: - status = authident(&port->raddr.in, &port->laddr.in, - port->user, port->auth_arg); + status = authident(port); break; case uaPassword: diff -ur postgresql-snapshot/src/backend/libpq/hba.c postgresql-snapshot-ident-local/src/backend/libpq/hba.c --- postgresql-snapshot/src/backend/libpq/hba.c Tue Jul 31 10:00:09 2001 +++ postgresql-snapshot-ident-local/src/backend/libpq/hba.c Wed Aug 1 02:14:09 2001 @@ -216,6 +216,7 @@ auth_arg[0] = '\0'; else { + token = lfirst(line); StrNCpy(auth_arg, token, MAX_AUTH_ARG - 1); /* If there is more on the line, it is an error */ if (lnext(line)) @@ -262,9 +263,13 @@ /* * For now, disallow methods that need AF_INET sockets to work. + * Allow "ident" if we can get the identity of the connection + * peer on unix domain sockets from the OS. */ - if (!*error_p && - (port->auth_method == uaIdent || + if (!*error_p && ( +#ifndef HAVE_SO_PEERCRED + port->auth_method == uaIdent || +#endif port->auth_method == uaKrb4 || port->auth_method == uaKrb5)) goto hba_syntax; @@ -526,7 +531,7 @@ { List *line; bool found_entry = false, error = false; - + if (usermap_name[0] == '\0') { snprintf(PQerrormsg, PQERRORMSG_LENGTH, @@ -700,7 +705,7 @@ * false. */ static int -ident(const struct in_addr remote_ip_addr, +ident_inet(const struct in_addr remote_ip_addr, const struct in_addr local_ip_addr, const ushort remote_port, const ushort local_port, @@ -815,28 +820,68 @@ return ident_return; } +#ifdef HAVE_SO_PEERCRED +/* + * Ask kernel about the credentials of the connecting process and + * determine the symbolic name of the corresponding user. + * + * Returns either true and the username put into "ident_user", + * or false if we were unable to determine the username. + */ +static int +ident_unix(int sock, char *ident_user) +{ + struct ucred creds; /* numeric peer credentials */ + struct passwd *pw; /* map uid to name */ + int rc, size; + + size=sizeof(creds); + rc=getsockopt(sock, SOL_SOCKET, SO_PEERCRED, + &creds, &size); + if (rc || (size!=sizeof(creds))) return false; + + pw=getpwuid(creds.uid); + if (!pw) return false; + + strncpy(ident_user, pw->pw_name, IDENT_USERNAME_MAX); + return true; +} +#endif /* - * Talk to the ident server on the remote host and find out who owns the - * connection described by "port". Then look in the usermap file under - * the usermap *auth_arg and see if that user is equivalent to - * Postgres user *user. + * Determine the username of the initiator of the connection described + * by "port". Then look in the usermap file under the usermap + * port->auth_arg and see if that user is equivalent to Postgres user + * port->user. * * Return STATUS_OK if yes. */ int -authident(struct sockaddr_in *raddr, struct sockaddr_in *laddr, - const char *pg_user, const char *auth_arg) +authident(struct Port *port) { /* We were unable to get ident to give us a username */ char ident_user[IDENT_USERNAME_MAX + 1]; + switch(port->raddr.sa.sa_family) { + case AF_INET: + if (!ident_inet(port->raddr.in.sin_addr, + port->laddr.in.sin_addr, + port->raddr.in.sin_port, + port->laddr.in.sin_port, ident_user)) + return STATUS_ERROR; + break; +#ifdef HAVE_SO_PEERCRED + case AF_UNIX: + if (!ident_unix(port->sock, ident_user)) + return STATUS_ERROR; + break; +#endif + default: + return STATUS_ERROR; + } /* The username returned by ident */ - if (!ident(raddr->sin_addr, laddr->sin_addr, - raddr->sin_port, laddr->sin_port, ident_user)) - return STATUS_ERROR; - if (check_ident_usermap(auth_arg, pg_user, ident_user)) + if (check_ident_usermap(port->auth_arg, port->user, ident_user)) return STATUS_OK; else return STATUS_ERROR; diff -ur postgresql-snapshot/src/include/config.h.in postgresql-snapshot-ident-local/src/include/config.h.in --- postgresql-snapshot/src/include/config.h.in Mon Jul 16 10:01:51 2001 +++ postgresql-snapshot-ident-local/src/include/config.h.in Wed Aug 1 01:15:30 2001 @@ -685,6 +685,9 @@ /* Define if you have on_exit() */ #undef HAVE_ON_EXIT +/* Define if you have SO_PEERCRED */ +#undef HAVE_SO_PEERCRED + /* *------------------------------------------------------------------------ * Part 4: pull in system-specific declarations. diff -ur postgresql-snapshot/src/include/libpq/hba.h postgresql-snapshot-ident-local/src/include/libpq/hba.h --- postgresql-snapshot/src/include/libpq/hba.h Tue Jul 31 10:00:09 2001 +++ postgresql-snapshot-ident-local/src/include/libpq/hba.h Wed Aug 1 00:50:35 2001 @@ -41,8 +41,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 authident(struct Port *port); void load_hba_and_ident(void); #endif