On Fri, Mar 11, 2011 at 15:36, Peter Eisentraut <pete...@gmx.net> wrote: > On tor, 2011-03-10 at 22:45 +0100, Magnus Hagander wrote: >> On Thu, Mar 10, 2011 at 22:22, Bruce Momjian <br...@momjian.us> wrote: >> > >> > Added to TODO: >> > >> > Rename unix domain socket 'ident' connections to 'peer', to avoid >> > confusion with TCP 'ident' >> >> Should we consider adding "peer" as an alias for "ident" already in >> 9.1 (and change the default pg_hba.conf template), and then deprecate >> ident for 9.2 and remove it in 9.3 or something? By adding the alias >> now (yes, I know it's not in the last CF :P), we can move what's going >> to be a long process up one release... > > Might as well, if you can get it done soon. The documentation might > need more extensive adjustments.
The code itself is pretty easy and localized, AFAICT. Attached is a patch taht implements "peer" for local connections, and automatically maps "ident" on local sockets to that (with a log message saying it did). If people want this to go in, I'll go over the documentation as well - as you say, that might need some more changes, but we're not as time-critical on that (meaning we can keep polishing it through beta). Also, I'd like to get around to making "initdb -A ident" automatically put "peer" for local sockets as well, which is not included in this patch but should be a very simple change. So. Thoughts? -- Magnus Hagander Me: http://www.hagander.net/ Work: http://www.redpill-linpro.com/
*** a/src/backend/libpq/auth.c --- b/src/backend/libpq/auth.c *************** *** 60,66 **** static int recv_and_check_password_packet(Port *port); /* Standard TCP port number for Ident service. Assigned by IANA */ #define IDENT_PORT 113 ! static int authident(hbaPort *port); /*---------------------------------------------------------------- --- 60,67 ---- /* Standard TCP port number for Ident service. Assigned by IANA */ #define IDENT_PORT 113 ! static int ident_inet(hbaPort *port); ! static int auth_peer(hbaPort *port); /*---------------------------------------------------------------- *************** *** 269,274 **** auth_failed(Port *port, int status) --- 270,278 ---- case uaIdent: errstr = gettext_noop("Ident authentication failed for user \"%s\""); break; + case uaPeer: + errstr = gettext_noop("Peer authentication failed for user \"%s\""); + break; case uaPassword: case uaMD5: errstr = gettext_noop("password authentication failed for user \"%s\""); *************** *** 506,515 **** ClientAuthentication(Port *port) #endif break; ! case uaIdent: /* ! * If we are doing ident on unix-domain sockets, use SCM_CREDS * only if it is defined and SO_PEERCRED isn't. */ #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && \ --- 510,519 ---- #endif break; ! case uaPeer: /* ! * If we are doing peer on unix-domain sockets, use SCM_CREDS * only if it is defined and SO_PEERCRED isn't. */ #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && \ *************** *** 535,541 **** ClientAuthentication(Port *port) sendAuthRequest(port, AUTH_REQ_SCM_CREDS); } #endif ! status = authident(port); break; case uaMD5: --- 539,549 ---- sendAuthRequest(port, AUTH_REQ_SCM_CREDS); } #endif ! status = auth_peer(port); ! break; ! ! case uaIdent: ! status = ident_inet(port); break; case uaMD5: *************** *** 1599,1609 **** interpret_ident_response(const char *ident_response, * * But iff we're unable to get the information from ident, return false. */ ! static bool ! ident_inet(const SockAddr remote_addr, ! const SockAddr local_addr, ! char *ident_user) { pgsocket sock_fd, /* File descriptor for socket on which we talk * to Ident */ rc; /* Return code from a locally called function */ --- 1607,1618 ---- * * But iff we're unable to get the information from ident, return false. */ ! static int ! ident_inet(hbaPort *port) { + const SockAddr remote_addr = port->raddr; + const SockAddr local_addr = port->laddr; + char ident_user[IDENT_USERNAME_MAX + 1]; pgsocket sock_fd, /* File descriptor for socket on which we talk * to Ident */ rc; /* Return code from a locally called function */ *************** *** 1646,1652 **** ident_inet(const SockAddr remote_addr, { if (ident_serv) pg_freeaddrinfo_all(hints.ai_family, ident_serv); ! return false; /* we don't expect this to happen */ } hints.ai_flags = AI_NUMERICHOST; --- 1655,1661 ---- { if (ident_serv) pg_freeaddrinfo_all(hints.ai_family, ident_serv); ! return STATUS_ERROR; /* we don't expect this to happen */ } hints.ai_flags = AI_NUMERICHOST; *************** *** 1662,1668 **** ident_inet(const SockAddr remote_addr, { if (la) pg_freeaddrinfo_all(hints.ai_family, la); ! return false; /* we don't expect this to happen */ } sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype, --- 1671,1677 ---- { if (la) pg_freeaddrinfo_all(hints.ai_family, la); ! return STATUS_ERROR; /* we don't expect this to happen */ } sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype, *************** *** 1751,1757 **** ident_inet_done: closesocket(sock_fd); pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv); pg_freeaddrinfo_all(local_addr.addr.ss_family, la); ! return ident_return; } /* --- 1760,1770 ---- closesocket(sock_fd); pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv); pg_freeaddrinfo_all(local_addr.addr.ss_family, la); ! ! if (ident_return) ! /* Success! Check the usermap */ ! return check_usermap(port->hba->usermap, port->user_name, ident_user, false); ! return STATUS_ERROR; } /* *************** *** 1763,1771 **** ident_inet_done: */ #ifdef HAVE_UNIX_SOCKETS ! static bool ! ident_unix(int sock, char *ident_user) { #if defined(HAVE_GETPEEREID) /* OpenBSD style: */ uid_t uid; --- 1776,1787 ---- */ #ifdef HAVE_UNIX_SOCKETS ! static int ! auth_peer(hbaPort *port) { + int sock = port->sock; + char ident_user[IDENT_USERNAME_MAX + 1]; + #if defined(HAVE_GETPEEREID) /* OpenBSD style: */ uid_t uid; *************** *** 1779,1785 **** ident_unix(int sock, char *ident_user) ereport(LOG, (errcode_for_socket_access(), errmsg("could not get peer credentials: %m"))); ! return false; } pass = getpwuid(uid); --- 1795,1801 ---- ereport(LOG, (errcode_for_socket_access(), errmsg("could not get peer credentials: %m"))); ! return STATUS_ERROR; } pass = getpwuid(uid); *************** *** 1789,1800 **** ident_unix(int sock, char *ident_user) ereport(LOG, (errmsg("local user with ID %d does not exist", (int) uid))); ! return false; } strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1); - return true; #elif defined(SO_PEERCRED) /* Linux style: use getsockopt(SO_PEERCRED) */ struct ucred peercred; --- 1805,1815 ---- ereport(LOG, (errmsg("local user with ID %d does not exist", (int) uid))); ! return STATUS_ERROR; } strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1); #elif defined(SO_PEERCRED) /* Linux style: use getsockopt(SO_PEERCRED) */ struct ucred peercred; *************** *** 1809,1815 **** ident_unix(int sock, char *ident_user) ereport(LOG, (errcode_for_socket_access(), errmsg("could not get peer credentials: %m"))); ! return false; } pass = getpwuid(peercred.uid); --- 1824,1830 ---- ereport(LOG, (errcode_for_socket_access(), errmsg("could not get peer credentials: %m"))); ! return STATUS_ERROR; } pass = getpwuid(peercred.uid); *************** *** 1819,1830 **** ident_unix(int sock, char *ident_user) ereport(LOG, (errmsg("local user with ID %d does not exist", (int) peercred.uid))); ! return false; } strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1); - return true; #elif defined(HAVE_GETPEERUCRED) /* Solaris > 10 */ uid_t uid; --- 1834,1844 ---- ereport(LOG, (errmsg("local user with ID %d does not exist", (int) peercred.uid))); ! return STATUS_ERROR; } strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1); #elif defined(HAVE_GETPEERUCRED) /* Solaris > 10 */ uid_t uid; *************** *** 1837,1843 **** ident_unix(int sock, char *ident_user) ereport(LOG, (errcode_for_socket_access(), errmsg("could not get peer credentials: %m"))); ! return false; } if ((uid = ucred_geteuid(ucred)) == -1) --- 1851,1857 ---- ereport(LOG, (errcode_for_socket_access(), errmsg("could not get peer credentials: %m"))); ! return STATUS_ERROR; } if ((uid = ucred_geteuid(ucred)) == -1) *************** *** 1845,1851 **** ident_unix(int sock, char *ident_user) ereport(LOG, (errcode_for_socket_access(), errmsg("could not get effective UID from peer credentials: %m"))); ! return false; } ucred_free(ucred); --- 1859,1865 ---- ereport(LOG, (errcode_for_socket_access(), errmsg("could not get effective UID from peer credentials: %m"))); ! return STATUS_ERROR; } ucred_free(ucred); *************** *** 1856,1867 **** ident_unix(int sock, char *ident_user) ereport(LOG, (errmsg("local user with ID %d does not exist", (int) uid))); ! return false; } strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1); - return true; #elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS)) struct msghdr msg; --- 1870,1880 ---- ereport(LOG, (errmsg("local user with ID %d does not exist", (int) uid))); ! return STATUS_ERROR; } strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1); #elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS)) struct msghdr msg; *************** *** 1913,1919 **** ident_unix(int sock, char *ident_user) ereport(LOG, (errcode_for_socket_access(), errmsg("could not get peer credentials: %m"))); ! return false; } cred = (Cred *) CMSG_DATA(cmsg); --- 1926,1932 ---- ereport(LOG, (errcode_for_socket_access(), errmsg("could not get peer credentials: %m"))); ! return STATUS_ERROR; } cred = (Cred *) CMSG_DATA(cmsg); *************** *** 1925,1983 **** ident_unix(int sock, char *ident_user) ereport(LOG, (errmsg("local user with ID %d does not exist", (int) cred->cruid))); ! return false; } strlcpy(ident_user, pw->pw_name, IDENT_USERNAME_MAX + 1); - return true; #else ereport(LOG, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Ident authentication is not supported on local connections on this platform"))); ! return false; ! #endif ! } ! #endif /* HAVE_UNIX_SOCKETS */ ! ! ! /* ! * Determine the username of the initiator of the connection described ! * by "port". Then look in the usermap file under the usermap ! * port->hba->usermap and see if that user is equivalent to Postgres user ! * port->user. ! * ! * Return STATUS_OK if yes, STATUS_ERROR if no match (or couldn't get info). ! */ ! static int ! authident(hbaPort *port) ! { ! char ident_user[IDENT_USERNAME_MAX + 1]; ! ! switch (port->raddr.addr.ss_family) ! { ! case AF_INET: ! #ifdef HAVE_IPV6 ! case AF_INET6: ! #endif ! if (!ident_inet(port->raddr, port->laddr, ident_user)) ! return STATUS_ERROR; ! break; ! ! #ifdef HAVE_UNIX_SOCKETS ! case AF_UNIX: ! if (!ident_unix(port->sock, ident_user)) ! return STATUS_ERROR; ! break; #endif - default: - return STATUS_ERROR; - } - return check_usermap(port->hba->usermap, port->user_name, ident_user, false); } /*---------------------------------------------------------------- --- 1938,1959 ---- ereport(LOG, (errmsg("local user with ID %d does not exist", (int) cred->cruid))); ! return STATUS_ERROR; } strlcpy(ident_user, pw->pw_name, IDENT_USERNAME_MAX + 1); #else ereport(LOG, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Ident authentication is not supported on local connections on this platform"))); ! return STATUS_ERROR; #endif return check_usermap(port->hba->usermap, port->user_name, ident_user, false); } + #endif /* HAVE_UNIX_SOCKETS */ /*---------------------------------------------------------------- *** a/src/backend/libpq/hba.c --- b/src/backend/libpq/hba.c *************** *** 1060,1065 **** parse_hba_line(List *line, int line_num, HbaLine *parsedline) --- 1060,1067 ---- parsedline->auth_method = uaTrust; else if (strcmp(token, "ident") == 0) parsedline->auth_method = uaIdent; + else if (strcmp(token, "peer") == 0) + parsedline->auth_method = uaPeer; else if (strcmp(token, "password") == 0) parsedline->auth_method = uaPassword; else if (strcmp(token, "krb5") == 0) *************** *** 1137,1142 **** parse_hba_line(List *line, int line_num, HbaLine *parsedline) --- 1139,1158 ---- return false; } + /* + * XXX: When using ident on local connections, change it to peer, + * for backwards compatibility. + */ + if (parsedline->conntype == ctLocal && + parsedline->auth_method == uaIdent) + { + ereport(LOG, + (errmsg("\"ident\" authentication on local socket automatically changed to \"peer\""), + errcontext("line %d of configuration file \"%s\"", + line_num, HbaFileName))); + parsedline->auth_method = uaPeer; + } + /* Invalid authentication combinations */ if (parsedline->conntype == ctLocal && parsedline->auth_method == uaKrb5) *************** *** 1160,1165 **** parse_hba_line(List *line, int line_num, HbaLine *parsedline) --- 1176,1192 ---- return false; } + if (parsedline->conntype != ctLocal && + parsedline->auth_method == uaPeer) + { + ereport(LOG, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("peer authentication is only supported on local sockets"), + errcontext("line %d of configuration file \"%s\"", + line_num, HbaFileName))); + return false; + } + /* * SSPI authentication can never be enabled on ctLocal connections, * because it's only supported on Windows, where ctLocal isn't supported. *************** *** 1203,1213 **** parse_hba_line(List *line, int line_num, HbaLine *parsedline) if (strcmp(token, "map") == 0) { if (parsedline->auth_method != uaIdent && parsedline->auth_method != uaKrb5 && parsedline->auth_method != uaGSS && parsedline->auth_method != uaSSPI && parsedline->auth_method != uaCert) ! INVALID_AUTH_OPTION("map", gettext_noop("ident, krb5, gssapi, sspi and cert")); parsedline->usermap = pstrdup(c); } else if (strcmp(token, "clientcert") == 0) --- 1230,1241 ---- if (strcmp(token, "map") == 0) { if (parsedline->auth_method != uaIdent && + parsedline->auth_method != uaPeer && parsedline->auth_method != uaKrb5 && parsedline->auth_method != uaGSS && parsedline->auth_method != uaSSPI && parsedline->auth_method != uaCert) ! INVALID_AUTH_OPTION("map", gettext_noop("ident, peer, krb5, gssapi, sspi and cert")); parsedline->usermap = pstrdup(c); } else if (strcmp(token, "clientcert") == 0) *** a/src/backend/libpq/pg_hba.conf.sample --- b/src/backend/libpq/pg_hba.conf.sample *************** *** 41,47 **** # directly connected to. # # METHOD can be "trust", "reject", "md5", "password", "gss", "sspi", ! # "krb5", "ident", "pam", "ldap", "radius" or "cert". Note that # "password" sends passwords in clear text; "md5" is preferred since # it sends encrypted passwords. # --- 41,47 ---- # directly connected to. # # METHOD can be "trust", "reject", "md5", "password", "gss", "sspi", ! # "krb5", "ident", "peer", "pam", "ldap", "radius" or "cert". Note that # "password" sends passwords in clear text; "md5" is preferred since # it sends encrypted passwords. # *** a/src/include/libpq/hba.h --- b/src/include/libpq/hba.h *************** *** 29,35 **** typedef enum UserAuth uaPAM, uaLDAP, uaCert, ! uaRADIUS } UserAuth; typedef enum IPCompareMethod --- 29,36 ---- uaPAM, uaLDAP, uaCert, ! uaRADIUS, ! uaPeer } UserAuth; typedef enum IPCompareMethod
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers