Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mk9wA-0002yD-DP for pgsql-hackers@arkaria.postgresql.org; Mon, 08 Nov 2021 19:04:10 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1mk9w9-00032A-8D for pgsql-hackers@arkaria.postgresql.org; Mon, 08 Nov 2021 19:04:09 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mk9w8-00031l-Uo for pgsql-hackers@lists.postgresql.org; Mon, 08 Nov 2021 19:04:08 +0000 Received: from tamriel.snowman.net ([2001:470:e38f::11]) by magus.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1mk9w6-0004St-Gw for pgsql-hackers@lists.postgresql.org; Mon, 08 Nov 2021 19:04:08 +0000 Received: by tamriel.snowman.net (Postfix, from userid 1000) id EC8965F7A2; Mon, 8 Nov 2021 14:04:05 -0500 (EST) Date: Mon, 8 Nov 2021 14:04:05 -0500 From: Stephen Frost To: David Steele Cc: PostgreSQL Developers Subject: Re: Allow root ownership of client certificate key Message-ID: <20211108190405.GL20998@tamriel.snowman.net> References: MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="lCpo7U56l67/NwrH" Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.24 (2015-08-30) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --lCpo7U56l67/NwrH Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Greetings, * David Steele (david@pgmasters.net) wrote: > I noticed recently that permissions checking is done differently for the > server certificate key than the client key. Specifically, on the server t= he > key can have 640 perms if it is owned by root. Yeah, that strikes me as odd too, particularly given that many many cases of client-side certificates are application servers and not actual end users. If we can justify having a looser check on the PG server side then it surely makes sense that an app server could also be justified in having such a permission setup (and it definitely happens often in Kubernetes/OpenShift and such places where secrets are mounted =66rom somewhere else). > On the server side this change was made in 9a83564c and I think the same > rational applies equally well to the client key. At the time managed keys= on > the client may not have been common but they are now. Agreed. > Attached is a patch to make this change. >=20 > I was able to this this manually by hacking 001_ssltests.pl like so: >=20 > - chmod 0640, "ssl/${key}_tmp.key" > + chmod 0600, "ssl/${key}_tmp.key" > or die "failed to change permissions on ssl/${key}_tmp.key: $!"; > - system_or_bail("sudo chown root ssl/${key}_tmp.key"); >=20 > But this is clearly not going to work for general purpose testing. The > server keys also not tested for root ownership so perhaps we do not need > that here either. Makes sense to me. > I looked at trying to make this code common between the server and client > but due to the differences in error reporting it seemed like more trouble > than it was worth. Maybe we should at least have the comments refer to each other though, to hopefully encourage future hackers in this area to maintain consistency between the two and avoid what happened before..? > diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/li= bpq/fe-secure-openssl.c > index 3a7cc8f774..285e772170 100644 > --- a/src/interfaces/libpq/fe-secure-openssl.c > +++ b/src/interfaces/libpq/fe-secure-openssl.c > @@ -1234,11 +1234,38 @@ initialize_SSL(PGconn *conn) > fnbuf); > return -1; > } > + > + /* > + * Refuse to load key files owned by users other than us or root. > + * > + * XXX surely we can check this on Windows somehow, too. > + */ Not really sure if there's actually much point in having this marked in this way as it's not apparently something we're going to actually fix in the near term. Maybe instead something like "Would be nice to find a way to do this on Windows somehow, too, but it isn't clear today how to." > +#ifndef WIN32 > + if (buf.st_uid !=3D geteuid() && buf.st_uid !=3D 0) > + { > + appendPQExpBuffer(&conn->errorMessage, > + libpq_gettext("private key file \"%s\" must be owned by the cur= rent user or root\n"), > + fnbuf); > + return -1; > + } > +#endif Basically the same check as what is done on the server side, so this looks good to me. > + /* > + * Require no public access to key file. If the file is owned by us, > + * require mode 0600 or less. If owned by root, require 0640 or less to > + * allow read access through our gid, or a supplementary gid that allows > + * to read system-wide certificates. > + * > + * XXX temporarily suppress check when on Windows, because there may not > + * be proper support for Unix-y file permissions. Need to think of a > + * reasonable check to apply on Windows. > + */ On the server-side, we also include a reference to postmaster.c. Not sure if we need to do that or not but just figured I'd mention it. > #ifndef WIN32 > - if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO)) > + if ((buf.st_uid =3D=3D geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO))= || > + (buf.st_uid =3D=3D 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO))) > { > appendPQExpBuffer(&conn->errorMessage, > - libpq_gettext("private key file \"%s\" has group or world acces= s; permissions should be u=3Drw (0600) or less\n"), > + libpq_gettext("private key file \"%s\" has group or world acces= s; file must have permissions u=3Drw (0600) or less if owned by the current= user, or permissions u=3Drw,g=3Dr (0640) or less if owned by root.\n"), > fnbuf); > return -1; > } Do we really want to remove the S_ISREG() check? We have that check (although a bit earlier) on the server side and we've had it for a very long time, so I don't think that we want to drop it, certainly not without some additional discussion as to why we should (and why it would make sense to have that be different between the client side and the server side). Thanks, Stephen --lCpo7U56l67/NwrH Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBCgAGBQJhiXSlAAoJEO1sijiDR2RVti4P/AgiVJ8g/q5Uu1FtV+iRVUH3 gJXyhG5BAvYbLm+8JbD20BcnfuqfUP1uwFFdMCaJ5J5PD+VjClc89CNoazt15aPC C6TRaI0uemzqhOYJEDTRNTn2ErdVhinRBPMwZcGQE8BQI+JrVWq9iBfa29fFaTjP CpCPKw+mQaGqpj6cmo+4pAH1Nnh1k1Yqm+v3xh+SHI8aCwNyr3U5gTGU7K8nLt7c g4qDuFEBLRMd2Qd5P3FHbEVpTcyqwB1MTgpbhWad6zD10LbLzP4TC+/pUgsJ2p2m W/VAYw2fe6DZzJCpbwZmHU6u6rLKK2+WAImp71Mdeiwifgqjspx34T45t7DvPGjq 6MeYnlVOoXExsVepyqAlT6mzdGBVHX+C1c4K+moGqwbfq6n9F8SB6hX4NidvbuVW yzEFxRgXIX03njN3PSxxqDou8L4pFY5z7hsjB2rpZelMPnOubDyfPKyfyflovWdS ddugDAaOx+L7dkVpkmALqAK6OcJL1UEeyUftUmCXOIgjMgBhi3Xrvki+W5bRMT8i jEZTYfvYkFkVxEgEuZ/1HOrKFn5nuafmm++8rztog7SXxUpFUK7DQuQKakEnwu7H HiYAlkxUG5KN9eJrHQkIiRYwoNKGQvJ27kR6uJ4hASXtZZgQuAwMAbMos01Hg85E pxs7xhK75DJlucwT6/Dr =uQwp -----END PGP SIGNATURE----- --lCpo7U56l67/NwrH--