diff options
Diffstat (limited to 'src/backend/libpq/auth.c')
-rw-r--r-- | src/backend/libpq/auth.c | 112 |
1 files changed, 47 insertions, 65 deletions
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index af43c2a7cbc..5f56020cc76 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -60,7 +60,10 @@ 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); +#ifdef HAVE_UNIX_SOCKETS +static int auth_peer(hbaPort *port); +#endif /*---------------------------------------------------------------- @@ -269,6 +272,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 +512,12 @@ ClientAuthentication(Port *port) #endif break; - case uaIdent: + case uaPeer: +#ifdef HAVE_UNIX_SOCKETS /* - * 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 +542,14 @@ ClientAuthentication(Port *port) sendAuthRequest(port, AUTH_REQ_SCM_CREDS); } #endif - status = authident(port); + status = auth_peer(port); +#else /* HAVE_UNIX_SOCKETS */ + Assert(false); +#endif + break; + + case uaIdent: + status = ident_inet(port); break; case uaMD5: @@ -1599,11 +1613,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 +1661,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 +1677,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 +1766,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 +1782,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 +1801,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 +1811,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 +1830,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 +1840,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 +1857,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 +1865,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 +1876,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 +1932,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 +1944,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: + return STATUS_ERROR; #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); } +#endif /* HAVE_UNIX_SOCKETS */ /*---------------------------------------------------------------- |