On Mon, Mar 14, 2011 at 16:26, Magnus Hagander <mag...@hagander.net> wrote:
> On Mon, Mar 14, 2011 at 16:17, Tom Lane <t...@sss.pgh.pa.us> wrote:
>> Magnus Hagander <mag...@hagander.net> writes:
>>> On Mon, Mar 14, 2011 at 14:43, Robert Haas <robertmh...@gmail.com> wrote:
>>>> Also, the text is not accurate: nothing has been automatically changed
>>>> to anything.  The pg_hba.conf file is just as it was.  You could say
>>>> something like "ident" authentication on local socket treated as
>>>> "peer", but I think a better idea would be to just remove this message
>>>> altogether.
>>
>>> The idea being to let people know it's been deprecated, nothing else.
>>> But sure, we can just remove the message - at elast for now, and maybe
>>> add it $n releases down the road when people are expected to have
>>> changed over.
>>
>> I'm with Robert on this one --- the first reaction I had to your
>> description of the patch was "why do we need a log message for that?"
>> If there were some real reason to push people away from use of the
>> non-preferred term, maybe it'd be worth nagging them to change; but
>> there isn't.
>
> Ok. fair enough, I'll take that part out.

Here's an updated patch that removes this log message, and adds a few
lines to initdb to create a combination of ident/peer rows. And
finally, adds docs.


> Are people in general in favor of making the change provided I do that, then?

Comments?

-- 
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index c05805b..3f4631e 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -457,17 +457,28 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
         <term><literal>ident</></term>
         <listitem>
          <para>
-          Obtain the operating system user name of the client (for
-          TCP/IP connections by contacting the ident server on the
-          client, for local connections by getting it from the
-          operating system) and check if it matches the requested
-          database user name.
+          Obtain the operating system user name of the client
+          by contacting the ident server on the client
+          and check if it matches the requested database user name.
+          This is only available for TCP/IP connections.
           See <xref linkend="auth-ident"> for details.
          </para>
         </listitem>
        </varlistentry>
 
        <varlistentry>
+        <term><literal>peer</></term>
+        <listitem>
+         <para>
+          Obtain the operating system user name from the operating system
+          and check if it matches the requested database user name.
+          This is only available for local connections.
+          See <xref linkend="auth-peer"> for details.
+         </para>
+        </listitem>
+       </varlistentry>
+
+       <varlistentry>
         <term><literal>ldap</></term>
         <listitem>
          <para>
@@ -1200,7 +1211,7 @@ omicron         bryanh                  guest1
   </sect2>
 
   <sect2 id="auth-ident">
-   <title>Ident-based Authentication</title>
+   <title>Ident Authentication</title>
 
    <indexterm>
     <primary>ident</primary>
@@ -1208,11 +1219,9 @@ omicron         bryanh                  guest1
 
    <para>
     The ident authentication method works by obtaining the client's
-    operating system user name and using it as the allowed database user
-    name (with an optional user name mapping).
-    The determination of the client's
-    user name is the security-critical point, and it works differently
-    depending on the connection type, as described below.
+    operating system user name from an ident server and using it as
+    the allowed database user name (with an optional user name mapping).
+    This is only supported on TCP/IP connections.
    </para>
 
    <para>
@@ -1230,9 +1239,6 @@ omicron         bryanh                  guest1
     </variablelist>
    </para>
 
-   <sect3>
-    <title>Ident Authentication Over TCP/IP</title>
-
    <para>
     The <quote>Identification Protocol</quote> is described in
     RFC 1413. Virtually every Unix-like
@@ -1275,36 +1281,48 @@ omicron         bryanh                  guest1
     since <productname>PostgreSQL</> does not have any way to decrypt the
     returned string to determine the actual user name.
    </para>
-   </sect3>
+  </sect2>
+
+  <sect2 id="auth-peer">
+   <title>Peer Authentication</title>
+
+   <indexterm>
+    <primary>peer</primary>
+   </indexterm>
+
+   <para>
+    The peer authentication method works by obtaining the client's
+    operating system user name from the kernel and using it as the
+    allowed database user name (with optional user name mapping). This
+    is only supported on local connections.
+   </para>
 
-   <sect3>
-    <title>Ident Authentication Over Local Sockets</title>
+   <para>
+    The following configuration options are supported for <productname>peer</productname>:
+    <variablelist>
+     <varlistentry>
+      <term><literal>map</literal></term>
+      <listitem>
+       <para>
+        Allows for mapping between system and database user names. See
+        <xref linkend="auth-username-maps"> for details.
+       </para>
+      </listitem>
+     </varlistentry>
+    </variablelist>
+   </para>
 
    <para>
-    On systems supporting <symbol>SO_PEERCRED</symbol> requests for
+    Peer authentication is only available on  systems supporting
+    <symbol>SO_PEERCRED</symbol> requests for
     Unix-domain sockets (currently <systemitem
     class="osname">Linux</>, <systemitem class="osname">FreeBSD</>,
     <systemitem class="osname">NetBSD</>, <systemitem class="osname">OpenBSD</>,
-    <systemitem class="osname">BSD/OS</>, and <systemitem class="osname">Solaris</systemitem>), ident authentication can also
-    be applied to local connections.
+    <systemitem class="osname">BSD/OS</>, and <systemitem class="osname">Solaris</systemitem>).
     <productname>PostgreSQL</> uses <symbol>SO_PEERCRED</symbol> to find out
     the operating system name of the connected client process.
-    In this case, no security risk is added by
-    using ident authentication; indeed it is a preferable choice for
-    local connections on such systems.
    </para>
 
-    <para>
-     On systems without <symbol>SO_PEERCRED</> requests, ident
-     authentication is only available for TCP/IP connections. As a
-     work-around, it is possible to specify the <systemitem
-     class="systemname">localhost</> address <systemitem
-     class="systemname">127.0.0.1</> and make connections to this
-     address.  This method is trustworthy to the extent that you trust
-     the local ident server.
-    </para>
-    </sect3>
-
   </sect2>
 
   <sect2 id="auth-ldap">
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index f776737..b5ad101 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -148,7 +148,7 @@ postgres$ <userinput>initdb -D /usr/local/pgsql/data</userinput>
    mode is not used; or modify the generated <filename>pg_hba.conf</filename>
    file after running <command>initdb</command>, but
    <emphasis>before</> you start the server for the first time. (Other
-   reasonable approaches include using <literal>ident</literal> authentication
+   reasonable approaches include using <literal>peer</literal> authentication
    or file system permissions to restrict connections. See <xref
    linkend="client-authentication"> for more information.)
   </para>
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index af43c2a..bc8e4ca 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -60,7 +60,8 @@ 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);
+static int	ident_inet(hbaPort *port);
+static int	auth_peer(hbaPort *port);
 
 
 /*----------------------------------------------------------------
@@ -269,6 +270,9 @@ auth_failed(Port *port, int status)
 		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,11 +510,11 @@ ClientAuthentication(Port *port)
 #endif
 			break;
 
-		case uaIdent:
+		case uaPeer:
 
 			/*
-			 * If we are doing ident on unix-domain sockets, use SCM_CREDS
-			 * only if it is defined and SO_PEERCRED isn't.
+			 * 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) && \
 	(defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \
@@ -535,7 +539,11 @@ ClientAuthentication(Port *port)
 				sendAuthRequest(port, AUTH_REQ_SCM_CREDS);
 			}
 #endif
-			status = authident(port);
+			status = auth_peer(port);
+			break;
+
+		case uaIdent:
+			status = ident_inet(port);
 			break;
 
 		case uaMD5:
@@ -1599,11 +1607,12 @@ 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)
+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,7 +1655,7 @@ 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 */
+		return STATUS_ERROR;	/* we don't expect this to happen */
 	}
 
 	hints.ai_flags = AI_NUMERICHOST;
@@ -1662,7 +1671,7 @@ ident_inet(const SockAddr remote_addr,
 	{
 		if (la)
 			pg_freeaddrinfo_all(hints.ai_family, la);
-		return false;			/* we don't expect this to happen */
+		return STATUS_ERROR;	/* we don't expect this to happen */
 	}
 
 	sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
@@ -1751,7 +1760,11 @@ 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;
+
+	if (ident_return)
+		/* Success! Check the usermap */
+		return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
+	return STATUS_ERROR;
 }
 
 /*
@@ -1763,9 +1776,12 @@ ident_inet_done:
  */
 #ifdef HAVE_UNIX_SOCKETS
 
-static bool
-ident_unix(int sock, char *ident_user)
+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,7 +1795,7 @@ ident_unix(int sock, char *ident_user)
 		ereport(LOG,
 				(errcode_for_socket_access(),
 				 errmsg("could not get peer credentials: %m")));
-		return false;
+		return STATUS_ERROR;
 	}
 
 	pass = getpwuid(uid);
@@ -1789,12 +1805,11 @@ ident_unix(int sock, char *ident_user)
 		ereport(LOG,
 				(errmsg("local user with ID %d does not exist",
 						(int) uid)));
-		return false;
+		return STATUS_ERROR;
 	}
 
 	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;
@@ -1809,7 +1824,7 @@ ident_unix(int sock, char *ident_user)
 		ereport(LOG,
 				(errcode_for_socket_access(),
 				 errmsg("could not get peer credentials: %m")));
-		return false;
+		return STATUS_ERROR;
 	}
 
 	pass = getpwuid(peercred.uid);
@@ -1819,12 +1834,11 @@ ident_unix(int sock, char *ident_user)
 		ereport(LOG,
 				(errmsg("local user with ID %d does not exist",
 						(int) peercred.uid)));
-		return false;
+		return STATUS_ERROR;
 	}
 
 	strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
 
-	return true;
 #elif defined(HAVE_GETPEERUCRED)
 	/* Solaris > 10 */
 	uid_t		uid;
@@ -1837,7 +1851,7 @@ ident_unix(int sock, char *ident_user)
 		ereport(LOG,
 				(errcode_for_socket_access(),
 				 errmsg("could not get peer credentials: %m")));
-		return false;
+		return STATUS_ERROR;
 	}
 
 	if ((uid = ucred_geteuid(ucred)) == -1)
@@ -1845,7 +1859,7 @@ 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;
+		return STATUS_ERROR;
 	}
 
 	ucred_free(ucred);
@@ -1856,12 +1870,11 @@ ident_unix(int sock, char *ident_user)
 		ereport(LOG,
 				(errmsg("local user with ID %d does not exist",
 						(int) uid)));
-		return false;
+		return STATUS_ERROR;
 	}
 
 	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;
 
@@ -1913,7 +1926,7 @@ ident_unix(int sock, char *ident_user)
 		ereport(LOG,
 				(errcode_for_socket_access(),
 				 errmsg("could not get peer credentials: %m")));
-		return false;
+		return STATUS_ERROR;
 	}
 
 	cred = (Cred *) CMSG_DATA(cmsg);
@@ -1925,59 +1938,22 @@ ident_unix(int sock, char *ident_user)
 		ereport(LOG,
 				(errmsg("local user with ID %d does not exist",
 						(int) cred->cruid)));
-		return false;
+		return STATUS_ERROR;
 	}
 
 	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;
+	return STATUS_ERROR;
 #endif
 
-		default:
-			return STATUS_ERROR;
-	}
-
 	return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
 }
+#endif   /* HAVE_UNIX_SOCKETS */
 
 
 /*----------------------------------------------------------------
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 1b3a714..2def6ce 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -1060,6 +1060,8 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
 		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,6 +1139,14 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
 		return false;
 	}
 
+	/*
+	 * XXX: When using ident on local connections, change it to peer, for
+	 * backwards compatibility.
+	 */
+	if (parsedline->conntype == ctLocal &&
+		parsedline->auth_method == uaIdent)
+		parsedline->auth_method = uaPeer;
+
 	/* Invalid authentication combinations */
 	if (parsedline->conntype == ctLocal &&
 		parsedline->auth_method == uaKrb5)
@@ -1160,6 +1170,17 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
 		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,11 +1224,12 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
 			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, krb5, gssapi, sspi and cert"));
+					INVALID_AUTH_OPTION("map", gettext_noop("ident, peer, krb5, gssapi, sspi and cert"));
 				parsedline->usermap = pstrdup(c);
 			}
 			else if (strcmp(token, "clientcert") == 0)
diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample
index 87f8499..0a90b68 100644
--- a/src/backend/libpq/pg_hba.conf.sample
+++ b/src/backend/libpq/pg_hba.conf.sample
@@ -41,7 +41,7 @@
 # directly connected to.
 #
 # METHOD can be "trust", "reject", "md5", "password", "gss", "sspi",
-# "krb5", "ident", "pam", "ldap", "radius" or "cert".  Note that
+# "krb5", "ident", "peer", "pam", "ldap", "radius" or "cert".  Note that
 # "password" sends passwords in clear text; "md5" is preferred since
 # it sends encrypted passwords.
 #
@@ -75,7 +75,7 @@
 # TYPE  DATABASE        USER            ADDRESS                 METHOD
 
 @remove-line-for-nolocal@# "local" is for Unix domain socket connections only
-@remove-line-for-nolocal@local   all             all                                     @authmethod@
+@remove-line-for-nolocal@local   all             all                                     @authmethodlocal@
 # IPv4 local connections:
 host    all             all             127.0.0.1/32            @authmethod@
 # IPv6 local connections:
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 7a4b698..d509b13 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -82,6 +82,7 @@ static char *username = "";
 static bool pwprompt = false;
 static char *pwfilename = NULL;
 static char *authmethod = "";
+static char *authmethodlocal = "";
 static bool debug = false;
 static bool noclean = false;
 static bool show_setting = false;
@@ -1076,6 +1077,9 @@ setup_config(void)
 	conflines = replace_token(conflines,
 							  "@authmethod@",
 							  authmethod);
+	conflines = replace_token(conflines,
+							  "@authmethodlocal@",
+							  authmethodlocal);
 
 	conflines = replace_token(conflines,
 							  "@authcomment@",
@@ -2637,6 +2641,7 @@ main(int argc, char *argv[])
 	}
 
 	if (strcmp(authmethod, "md5") &&
+		strcmp(authmethod, "peer") &&
 		strcmp(authmethod, "ident") &&
 		strcmp(authmethod, "trust") &&
 #ifdef USE_PAM
@@ -2666,6 +2671,20 @@ main(int argc, char *argv[])
 		exit(1);
 	}
 
+	/*
+	 * When ident is specified, use peer for local connections. Mirrored, when
+	 * peer is specified, use ident for TCP connections.
+	 */
+	if (strcmp(authmethod, "ident") == 0)
+		authmethodlocal = "peer";
+	else if (strcmp(authmethod, "peer") == 0)
+	{
+		authmethodlocal = "peer";
+		authmethod = "ident";
+	}
+	else
+		authmethodlocal = authmethod;
+
 	if (strlen(pg_data) == 0)
 	{
 		pgdenv = getenv("PGDATA");
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
index aa60d8d..b92dc0d 100644
--- a/src/include/libpq/hba.h
+++ b/src/include/libpq/hba.h
@@ -29,7 +29,8 @@ typedef enum UserAuth
 	uaPAM,
 	uaLDAP,
 	uaCert,
-	uaRADIUS
+	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

Reply via email to