From c32b99c2cc2c4b7bb423d3236a0989a917eb5bc6 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 26 Dec 2019 15:31:18 +0100 Subject: [PATCH] localowner authentication --- doc/src/sgml/client-auth.sgml | 27 +++++++++++++++++++-- src/backend/libpq/auth.c | 2 +- src/backend/libpq/hba.c | 35 +++++++++++++++++++++++----- src/backend/libpq/pg_hba.conf.sample | 17 ++++++++------ src/include/libpq/hba.h | 1 + 5 files changed, 66 insertions(+), 16 deletions(-) diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 5f1eec78fb..3ed0a1cf66 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -102,6 +102,7 @@ The <filename>pg_hba.conf</filename> File A record can have one of the seven formats local database user auth-method auth-options +localowner database user auth-method auth-options host database user address auth-method auth-options hostssl database user address auth-method auth-options hostnossl database user address auth-method auth-options @@ -119,8 +120,30 @@ The <filename>pg_hba.conf</filename> File This record matches connection attempts using Unix-domain - sockets. Without a record of this type, Unix-domain socket - connections are disallowed. + sockets. + + + + + + localowner + + + This record matches connection attempts using Unix-domain sockets if + the user on the client side is the same as the user of the PostgreSQL + serve process. In other words, this applies if a user connects to + their own server over a Unix-domain socket. + + + + This record type works only on operating systems providing the + getpeereid() function, the + SO_PEERCRED socket parameter, or similar mechanisms. + Currently that includes Linux, + most flavors of BSD including + macOS, and Solaris. Otherwise, this record will never + match. diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 5399144c20..7dbfc56f64 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -2197,7 +2197,7 @@ CheckPAMAuth(Port *port, const char *user, const char *password) return STATUS_ERROR; } - if (port->hba->conntype != ctLocal) + if (port->hba->conntype != ctLocal && port->hba->conntype != ctLocalOwner) { char hostinfo[NI_MAXHOST]; int flags; diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index b6de92783a..97ca3fa3ad 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -978,10 +978,14 @@ parse_hba_line(TokenizedLine *tok_line, int elevel) return NULL; } token = linitial(tokens); - if (strcmp(token->string, "local") == 0) + if (strcmp(token->string, "local") == 0 || + strcmp(token->string, "localowner") == 0) { #ifdef HAVE_UNIX_SOCKETS - parsedline->conntype = ctLocal; + if (token->string[5] == 'o') + parsedline->conntype = ctLocalOwner; + else + parsedline->conntype = ctLocal; #else ereport(elevel, (errcode(ERRCODE_CONFIG_FILE_ERROR), @@ -1099,7 +1103,7 @@ parse_hba_line(TokenizedLine *tok_line, int elevel) copy_hba_token(lfirst(tokencell))); } - if (parsedline->conntype != ctLocal) + if (parsedline->conntype != ctLocal && parsedline->conntype != ctLocalOwner) { /* Read the IP address field. (with or without CIDR netmask) */ field = lnext(tok_line->fields, field); @@ -1403,12 +1407,14 @@ parse_hba_line(TokenizedLine *tok_line, int elevel) * XXX: When using ident on local connections, change it to peer, for * backwards compatibility. */ - if (parsedline->conntype == ctLocal && + if ((parsedline->conntype == ctLocal || + parsedline->conntype == ctLocalOwner) && parsedline->auth_method == uaIdent) parsedline->auth_method = uaPeer; /* Invalid authentication combinations */ - if (parsedline->conntype == ctLocal && + if ((parsedline->conntype == ctLocal || + parsedline->conntype == ctLocalOwner) && parsedline->auth_method == uaGSS) { ereport(elevel, @@ -1433,7 +1439,8 @@ parse_hba_line(TokenizedLine *tok_line, int elevel) return NULL; } - if (parsedline->conntype != ctLocal && + if ((parsedline->conntype != ctLocal && + parsedline->conntype != ctLocalOwner) && parsedline->auth_method == uaPeer) { ereport(elevel, @@ -2087,6 +2094,19 @@ check_hba(hbaPort *port) if (!IS_AF_UNIX(port->raddr.addr.ss_family)) continue; } + else if (hba->conntype == ctLocalOwner) + { + uid_t peer_uid = -1; + gid_t peer_gid = -1; + int res; + + if (!IS_AF_UNIX(port->raddr.addr.ss_family)) + continue; + + res = getpeereid(port->sock, &peer_uid, &peer_gid); + if (!(res == 0 && peer_uid == geteuid())) + continue; + } else { if (IS_AF_UNIX(port->raddr.addr.ss_family)) @@ -2444,6 +2464,9 @@ fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc, case ctLocal: typestr = "local"; break; + case ctLocalOwner: + typestr = "localowner"; + break; case ctHost: typestr = "host"; break; diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample index c853e36232..dee1dc45c8 100644 --- a/src/backend/libpq/pg_hba.conf.sample +++ b/src/backend/libpq/pg_hba.conf.sample @@ -9,17 +9,19 @@ # are authenticated, which PostgreSQL user names they can use, which # databases they can access. Records take one of these forms: # -# local DATABASE USER METHOD [OPTIONS] -# host DATABASE USER ADDRESS METHOD [OPTIONS] -# hostssl DATABASE USER ADDRESS METHOD [OPTIONS] -# hostnossl DATABASE USER ADDRESS METHOD [OPTIONS] +# local DATABASE USER METHOD [OPTIONS] +# localowner DATABASE USER METHOD [OPTIONS] +# host DATABASE USER ADDRESS METHOD [OPTIONS] +# hostssl DATABASE USER ADDRESS METHOD [OPTIONS] +# hostnossl DATABASE USER ADDRESS METHOD [OPTIONS] # # (The uppercase items must be replaced by actual values.) # # The first field is the connection type: "local" is a Unix-domain -# socket, "host" is either a plain or SSL-encrypted TCP/IP socket, -# "hostssl" is an SSL-encrypted TCP/IP socket, and "hostnossl" is a -# plain TCP/IP socket. +# socket, "localowner" is a Unix-domain socket from the same user has +# the owner of the PostgreSQL server process, "host" is either a plain +# or SSL-encrypted TCP/IP socket, "hostssl" is an SSL-encrypted TCP/IP +# socket, and "hostnossl" is a plain TCP/IP socket. # # DATABASE can be "all", "sameuser", "samerole", "replication", a # database name, or a comma-separated list thereof. The "all" @@ -76,6 +78,7 @@ # TYPE DATABASE USER ADDRESS METHOD +@remove-line-for-nolocal@localowner all all trust @remove-line-for-nolocal@# "local" is for Unix domain socket connections only @remove-line-for-nolocal@local all all @authmethodlocal@ # IPv4 local connections: diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h index d638479d88..5bd7da54f6 100644 --- a/src/include/libpq/hba.h +++ b/src/include/libpq/hba.h @@ -53,6 +53,7 @@ typedef enum IPCompareMethod typedef enum ConnType { ctLocal, + ctLocalOwner, ctHost, ctHostSSL, ctHostNoSSL, -- 2.24.1