On Sat, Mar 19, 2011 at 16:24, Tom Lane <t...@sss.pgh.pa.us> wrote: > Magnus Hagander <mag...@hagander.net> writes: >> 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. > >> Comments? > > As near as I can tell (I hate reading u-style diffs) you've documented
Ah, apologies. I made a -c diff, found a typo, remade it as -u.. pfft. > the ident and peer keywords as being mutually exclusive, ie, the docs > say that the correct keyword for the connection type *must* be used in > pg_hba.conf. Which is not how the code behaves, and shouldn't be how > the code behaves, for backwards-compatibility reasons. The docs need > to state the truth, namely that "ident" is still allowed as a synonym > for "peer" on local connections. Otherwise people will get confused > as to why their pg_hba files still work. Hmm: Good point, update attached. > The code changes look sane in a quick scan, though I didn't read them > in detail. Thx. -- Magnus Hagander Me: http://www.hagander.net/ Work: http://www.redpill-linpro.com/
*** a/doc/src/sgml/client-auth.sgml --- b/doc/src/sgml/client-auth.sgml *************** *** 457,473 **** 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. See <xref linkend="auth-ident"> for details. </para> </listitem> </varlistentry> <varlistentry> <term><literal>ldap</></term> <listitem> <para> --- 457,486 ---- <term><literal>ident</></term> <listitem> <para> ! 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. ! Ident authentication can only be used on TCP/IP ! connections. When specified for local connections, peer ! authentication will be used instead. 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,1206 **** omicron bryanh guest1 </sect2> <sect2 id="auth-ident"> ! <title>Ident-based Authentication</title> <indexterm> <primary>ident</primary> --- 1213,1219 ---- </sect2> <sect2 id="auth-ident"> ! <title>Ident Authentication</title> <indexterm> <primary>ident</primary> *************** *** 1208,1220 **** 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. </para> <para> The following configuration options are supported for <productname>ident</productname>: <variablelist> --- 1221,1239 ---- <para> The ident authentication method works by obtaining the client's ! 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> + <note> + <para> + When ident is specified for a local (non-TCP/IP) connection, + peer authentication (see <xref linkend="auth-peer">) will be + used instead. + </para> + </note> + <para> The following configuration options are supported for <productname>ident</productname>: <variablelist> *************** *** 1230,1238 **** 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 --- 1249,1254 ---- *************** *** 1275,1310 **** omicron bryanh guest1 since <productname>PostgreSQL</> does not have any way to decrypt the returned string to determine the actual user name. </para> ! </sect3> ! <sect3> ! <title>Ident Authentication Over Local Sockets</title> <para> ! 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. <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"> --- 1291,1338 ---- since <productname>PostgreSQL</> does not have any way to decrypt the returned string to determine the actual user name. </para> ! </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> ! ! <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> ! 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>). <productname>PostgreSQL</> uses <symbol>SO_PEERCRED</symbol> to find out the operating system name of the connected client process. </para> </sect2> <sect2 id="auth-ldap"> *** a/doc/src/sgml/runtime.sgml --- b/doc/src/sgml/runtime.sgml *************** *** 148,154 **** 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 or file system permissions to restrict connections. See <xref linkend="client-authentication"> for more information.) </para> --- 148,154 ---- 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>peer</literal> authentication or file system permissions to restrict connections. See <xref linkend="client-authentication"> for more information.) </para> *** 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,516 **** 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) && \ (defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \ --- 510,520 ---- #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) && \ (defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \ *************** *** 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,1152 ---- 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,1165 **** parse_hba_line(List *line, int line_num, HbaLine *parsedline) --- 1170,1186 ---- 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) --- 1224,1235 ---- 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. # *************** *** 75,81 **** # 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@ # IPv4 local connections: host all all 127.0.0.1/32 @authmethod@ # IPv6 local connections: --- 75,81 ---- # TYPE DATABASE USER ADDRESS METHOD @remove-line-for-nolocal@# "local" is for Unix domain socket connections only ! @remove-line-for-nolocal@local all all @authmethodlocal@ # IPv4 local connections: host all all 127.0.0.1/32 @authmethod@ # IPv6 local connections: *** a/src/bin/initdb/initdb.c --- b/src/bin/initdb/initdb.c *************** *** 82,87 **** static char *username = ""; --- 82,88 ---- 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,1081 **** setup_config(void) --- 1077,1085 ---- conflines = replace_token(conflines, "@authmethod@", authmethod); + conflines = replace_token(conflines, + "@authmethodlocal@", + authmethodlocal); conflines = replace_token(conflines, "@authcomment@", *************** *** 2637,2642 **** main(int argc, char *argv[]) --- 2641,2647 ---- } if (strcmp(authmethod, "md5") && + strcmp(authmethod, "peer") && strcmp(authmethod, "ident") && strcmp(authmethod, "trust") && #ifdef USE_PAM *************** *** 2666,2671 **** main(int argc, char *argv[]) --- 2671,2690 ---- 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"); *** 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