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 1l5TKq-0006rP-DQ for pgsql-hackers@arkaria.postgresql.org; Fri, 29 Jan 2021 12:57:13 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1l5TKp-0004rS-AM for pgsql-hackers@arkaria.postgresql.org; Fri, 29 Jan 2021 12:57:11 +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 1l5TKo-0004qo-Rg for pgsql-hackers@lists.postgresql.org; Fri, 29 Jan 2021 12:57:11 +0000 Received: from smtp.outgoing.loopia.se ([93.188.3.37]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1l5TKm-0004x9-LS for pgsql-hackers@lists.postgresql.org; Fri, 29 Jan 2021 12:57:10 +0000 Received: from s807.loopia.se (localhost [127.0.0.1]) by s807.loopia.se (Postfix) with ESMTP id BD5371A92BEE for ; Fri, 29 Jan 2021 13:57:05 +0100 (CET) Received: from s645.loopia.se (unknown [172.22.191.6]) by s807.loopia.se (Postfix) with ESMTP id 9BEC82E326D8; Fri, 29 Jan 2021 13:57:05 +0100 (CET) Received: from s475.loopia.se (unknown [172.22.191.6]) by s645.loopia.se (Postfix) with ESMTP id 530421579FE1; Fri, 29 Jan 2021 13:57:05 +0100 (CET) X-Virus-Scanned: amavisd-new at amavis.loopia.se X-Spam-Flag: NO X-Spam-Score: -1 X-Spam-Level: X-Spam-Status: No, score=-1 tagged_above=-999 required=6.2 tests=[ALL_TRUSTED=-1] autolearn=disabled Received: from s499.loopia.se ([172.22.191.6]) by s475.loopia.se (s475.loopia.se [172.22.190.15]) (amavisd-new, port 10024) with LMTP id CdHS9vj5kMAm; Fri, 29 Jan 2021 13:57:03 +0100 (CET) X-Loopia-Auth: user X-Loopia-User: daniel@yesql.se X-Loopia-Originating-IP: 89.255.232.193 Received: from [192.168.72.43] (customer-89-255-232-193.stosn.net [89.255.232.193]) (Authenticated sender: daniel@yesql.se) by s499.loopia.se (Postfix) with ESMTPSA id 66D721CE6029; Fri, 29 Jan 2021 13:57:03 +0100 (CET) From: Daniel Gustafsson Message-Id: <60DFB11D-2466-4286-84DC-F8F965DA675C@yesql.se> Content-Type: multipart/mixed; boundary="Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2" Mime-Version: 1.0 (Mac OS X Mail 12.4 \(3445.104.17\)) Subject: Re: Support for NSS as a libpq TLS backend Date: Fri, 29 Jan 2021 13:57:02 +0100 In-Reply-To: Cc: Jacob Champion , Heikki Linnakangas , Andres Freund , Postgres hackers , Andrew Dunstan , Stephen Frost , Thomas Munro To: Michael Paquier References: <1B0B31E4-AD37-475C-9374-7E24AA808479@vmware.com> <5C27CF6F-5BD3-4639-AAA6-73465595B6DF@vmware.com> <7B5A88DF-863A-4B00-B841-0285C1FF70DF@yesql.se> <5F24348B-10BA-4AA1-999B-1E2AB22B4997@vmware.com> <94E22878-6289-43D5-A674-804F6CB23782@yesql.se> X-Mailer: Apple Mail (2.3445.104.17) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii > On 21 Jan 2021, at 06:21, Michael Paquier wrote: >=20 > On Tue, Jan 19, 2021 at 09:21:41PM +0100, Daniel Gustafsson wrote: >>> In order to >>> move on with this set, I would suggest to extract some parts of the >>> patch set independently of the others and have two buildfarm members >>> for the MSVC and non-MSVC cases to stress the parts that can be >>> committed. Just seeing the size, we could move on with: >>> - The ./configure set, with the change to introduce = --with-ssl=3Dopenssl.=20 >>> - 0004 for strong randoms. >>> - Support for cryptohashes. >>=20 >> I will leave it to others to decide the feasibility of this, I'm = happy to slice >> and dice the commits into smaller bits to for example separate out = the >> --with-ssl autoconf change into a non NSS dependent commit, if that's = wanted. >=20 > IMO it makes sense to extract the independent pieces and build on top > of them. The bulk of the changes is likely going to have a bunch of > comments if reviewed deeply, so I think that we had better remove from > the stack the small-ish problems to ease the next moves. The > ./configure part and replacement of with_openssl by with_ssl is mixed > in 0001 and 0002, which is actually confusing. And, FWIW, I would be > fine with applying a patch that introduces a --with-ssl with a > compatibility kept for --with-openssl. This is what 0001 is doing, > actually, similarly to the past switches for --with-uuid. This has been discussed elsewhere in the thread, so let's continue that = there. The attached v23 does however split off --with-ssl for OpenSSL in 0001, = adding the nss option in 0002. > A point that has been mentioned offline by you, but not mentioned on > this list. The structure of the modules in src/test/ssl/ could be > refactored to help with an easier integration of more SSL libraries. > This makes sense taken independently. This has been submitted in = F513E66A-E693-4802-9F8A-A74C1D0E3D10@yesql.se. >> Based on an offlist discussion I believe this was a misunderstanding, = but if I >> instead misunderstood that feel free to correct me with how you think = this >> should be done. >=20 > The point would be to rename BITS_PER_BYTE to PG_BITS_PER_BYTE in the > code and avoid conflicts. I am not completely sure if others would > agree here, but this would remove quite some ifdef/undef stuff from > the code dedicated to NSS. Aha, now I see what you mean, sorry for the confusion. That can = certainly be done (and done so outside of this patchset), but it admittedly feels a = bit intrusive. If there is consensus that we should namespace our version = like this I'll go ahead and do that. >>> src/sgml/libpq.sgml needs to document PQdefaultSSLKeyPassHook_nss, = no? >>=20 >> Good point, fixed. >=20 > Please note that patch 0001 is failing to apply after the recent > commit b663a41. There are conflicts in postgres_fdw.out. Fixed. > Patch 0006 has three trailing whitespaces (git diff --check = complains). Fixed. > Running the regression tests of pgcrypto, I think that > the SHA2 implementation is not completely right. Some SHA2 encoding > reports results from already-freed data. =20 I've been unable to reproduce, can you shed some light on this? > I have spotted a second > issue within scram_HMAC_init(), where pg_cryptohash_create() remains > stuck inside NSS_InitContext(), freezing the regression tests where > password hashed for SCRAM are created. I think the freezing you saw comes from opening and closing NSS contexts = per cryptohash op (some patience on my part runs the test Ok in ~30s which = is clearly not in the wheelhouse of acceptable), more on that below. > + ResourceOwnerEnlargeCryptoHash(CurrentResourceOwner); > + ctx =3D MemoryContextAlloc(TopMemoryContext, = sizeof(pg_cryptohash_ctx)); > +#else > + ctx =3D pg_malloc(sizeof(pg_cryptohash_ctx)); > +#endif > cryptohash_nss.c cannot use pg_malloc() for frontend allocations. On > OOM, your patch would call exit() directly, even within libpq. But > shared library callers need to know about the OOM failure. Of course, fixed. > + status =3D PK11_DigestBegin(ctx->pk11_context); > + > + if (status !=3D SECSuccess) > + return 1; > + return 0; > This needs to return -1 on failure, not 1. Doh, fixed. > I really need to study more the choide of the options chosen for > NSS_InitContext()... But based on the docs I can read on the matter I > think that saving nsscontext in pg_cryptohash_ctx is right for each > cryptohash built. It's a safe but slow option, NSS wasn't really made for running a single = crypto operation. Since we are opening a context which isn't backed by an NSS database we could have a static context, which indeed speeds up = processing a lot. The problem with that is that there is no good callsite for = closing the context as the backend is closing down. Since you are kneedeep in the cryptohash code, do you have any thoughts on this? I've included 0008 = which implements this, with a commented out dummy stub for cleaning up. Making nss_context static in cryptohash_nss.c is appealing but there is no good option for closing it there. Any = thoughts on how to handle global contexts like this? > src/tools/msvc/ is missing an update for cryptohash_nss.c. Fixed. -- Daniel Gustafsson https://vmware.com/ --Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2 Content-Disposition: attachment; filename=v23-0008-NSS-Make-the-cryptohash-NSSInitContext-static-as.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v23-0008-NSS-Make-the-cryptohash-NSSInitContext-static-as.patch" Content-Transfer-Encoding: quoted-printable =46rom=206d9b00b3b6d309d3374cfdb16bda3b95196285b4=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Thu,=2028=20Jan=202021=2022:44:46=20+0100=0ASubject:=20[PATCH=20= v23=208/8]=20NSS=20Make=20the=20cryptohash=20NSSInitContext=20static=20= as=20an=0A=20experiment=0A=0AWe=20only=20need=20a=20static=20reference=20= tot=20the=20NSS=20context,=20and=20opening=20one=0Aper=20cryptohash=20= operation=20is=20incredibly=20wasteful=20given=20that=20it=20wasn't=0A= how=20NSS=20was=20designed=20to=20operate.=20This=20commit=20lacks=20the=20= infrastructure=0Afor=20closing=20the=20context=20on=20backend=20exit=20= though,=20hence=20experimental.=0A---=0A=20src/common/cryptohash_nss.c=20= |=2036=20++++++++++++++++++++++++++----------=0A=201=20file=20changed,=20= 26=20insertions(+),=2010=20deletions(-)=0A=0Adiff=20--git=20= a/src/common/cryptohash_nss.c=20b/src/common/cryptohash_nss.c=0Aindex=20= d4fd2e0008..6b7e48a1b4=20100644=0A---=20a/src/common/cryptohash_nss.c=0A= +++=20b/src/common/cryptohash_nss.c=0A@@=20-71,6=20+71,8=20@@=0A=20= #define=20FREE(ptr)=20free(ptr)=0A=20#endif=0A=20=0A+static=20= NSSInitContext=20*nss_context=20=3D=20NULL;=0A+=0A=20/*=0A=20=20*=20= Internal=20pg_cryptohash_ctx=20structure.=0A=20=20*/=0A@@=20-78,7=20= +80,6=20@@=20struct=20pg_cryptohash_ctx=0A=20{=0A=20=09= pg_cryptohash_type=20type;=0A=20=0A-=09NSSInitContext=20*nss_context;=0A=20= =09PK11Context=20*pk11_context;=0A=20=09HASH_HashType=20hash_type;=0A=20=0A= @@=20-141,16=20+142,20=20@@=20pg_cryptohash_create(pg_cryptohash_type=20= type)=0A=20=09=20*/=0A=20=09memset(¶ms,=200,=20sizeof(params));=0A=20= =09params.length=20=3D=20sizeof(params);=0A-=09ctx->nss_context=20=3D=20= NSS_InitContext("",=20"",=20"",=20"",=20¶ms,=0A-=09=09=09=09=09=09=09= =09=09=20=20=20NSS_INIT_READONLY=20|=20NSS_INIT_NOCERTDB=20|=0A-=09=09=09= =09=09=09=09=09=09=20=20=20NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A= -=09=09=09=09=09=09=09=09=09=20=20=20NSS_INIT_NOROOTINIT=20|=20= NSS_INIT_PK11RELOAD);=0A-=09if=20(!ctx->nss_context)=0A+=09if=20= (!nss_context)=0A=20=09{=0A-=09=09explicit_bzero(ctx,=20= sizeof(pg_cryptohash_ctx));=0A-=09=09FREE(ctx);=0A-=09=09goto=20error;=0A= +=09=09nss_context=20=3D=20NSS_InitContext("",=20"",=20"",=20"",=20= ¶ms,=0A+=09=09=09=09=09=09=09=09=09=20=20NSS_INIT_READONLY=20|=20= NSS_INIT_NOCERTDB=20|=0A+=09=09=09=09=09=09=09=09=09=20=20= NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A+=09=09=09=09=09=09=09=09= =09=20=20NSS_INIT_NOROOTINIT=20|=20NSS_INIT_PK11RELOAD);=0A+=09=09if=20= (!nss_context)=0A+=09=09{=0A+=09=09=09explicit_bzero(ctx,=20= sizeof(pg_cryptohash_ctx));=0A+=09=09=09FREE(ctx);=0A+=09=09=09goto=20= error;=0A+=09=09}=0A=20=09}=0A+=0A=20=09ctx->type=20=3D=20type;=0A=20=09= hash=20=3D=20SECOID_FindOIDByTag(ctx->hash_type);=0A=20=09= ctx->pk11_context=20=3D=20PK11_CreateDigestContext(hash->offset);=0A@@=20= -252,7=20+257,18=20@@=20pg_cryptohash_free(pg_cryptohash_ctx=20*ctx)=0A=20= #ifndef=20FRONTEND=0A=20=09ResourceOwnerForgetCryptoHash(ctx->resowner,=20= PointerGetDatum(ctx));=0A=20#endif=0A-=09= NSS_ShutdownContext(ctx->nss_context);=0A=20=09explicit_bzero(ctx,=20= sizeof(pg_cryptohash_ctx));=0A=20=09FREE(ctx);=0A=20}=0A+=0A+/*=0A+=20*=20= TODO:=20We=20need=20a=20way=20to=20close=20the=20static=20NSS=20context=20= when=20the=20backend=20is=0A+=20*=20terminated.=0A+=20*=0A+void=0A= +pg_cryptohash_teardown(void)=0A+{=0A+=09if=20(nss_context)=0A+=09=09= NSS_ShutdownContext(ctx->nss_context);=0A+}=0A+=20*/=0A--=20=0A2.21.1=20= (Apple=20Git-122.3)=0A=0A= --Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2 Content-Disposition: attachment; filename=v23-0007-NSS-cryptohash-support.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v23-0007-NSS-cryptohash-support.patch" Content-Transfer-Encoding: quoted-printable =46rom=20313148be7d99d8ad7c0bf97abd9c6bee37169422=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=2018=20Jan=202021=2013:04:49=20+0100=0ASubject:=20[PATCH=20= v23=207/8]=20NSS=20cryptohash=20support=0A=0A---=0A=20= src/common/cryptohash_nss.c=20|=20258=20= ++++++++++++++++++++++++++++++++++++=0A=20src/tools/msvc/Mkvcbuild.pm=20= |=20=20=204=20+=0A=202=20files=20changed,=20262=20insertions(+)=0A=20= create=20mode=20100644=20src/common/cryptohash_nss.c=0A=0Adiff=20--git=20= a/src/common/cryptohash_nss.c=20b/src/common/cryptohash_nss.c=0Anew=20= file=20mode=20100644=0Aindex=200000000000..d4fd2e0008=0A---=20/dev/null=0A= +++=20b/src/common/cryptohash_nss.c=0A@@=20-0,0=20+1,258=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20cryptohash_nss.c=0A+=20*=09=20=20Set=20of=20wrapper=20= routines=20on=20top=20of=20NSS=20to=20support=20cryptographic=0A+=20*=09=20= =20hash=20functions.=0A+=20*=0A+=20*=20This=20should=20only=20be=20used=20= if=20code=20is=20compiled=20with=20NSS=20support.=0A+=20*=0A+=20*=20= Portions=20Copyright=20(c)=201996-2020,=20PostgreSQL=20Global=20= Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=201994,=20= Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=09=09=20=20src/common/cryptohash_nss.c=0A+=20*=0A= +=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#ifndef=20FRONTEND=0A+#include=20"postgres.h"=0A+#else=0A= +#include=20"postgres_fe.h"=0A+#endif=0A+=0A+/*=0A+=20*=20BITS_PER_BYTE=20= is=20also=20defined=20in=20the=20NSPR=20header=20files,=20so=20we=20need=20= to=20undef=0A+=20*=20our=20version=20to=20avoid=20compiler=20warnings=20= on=20redefinition.=0A+=20*/=0A+#define=20pg_BITS_PER_BYTE=20= BITS_PER_BYTE=0A+#undef=20BITS_PER_BYTE=0A+=0A+#include=20=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+=0A+/*=0A+=20*=20Ensure=20that=20the=20colliding=20= definitions=20match,=20else=20throw=20an=20error.=20In=20case=0A+=20*=20= NSPR=20has=20removed=20the=20definition=20for=20some=20reason,=20make=20= sure=20to=20put=20ours=0A+=20*=20back=20again.=0A+=20*/=0A+#if=20= defined(BITS_PER_BYTE)=0A+#if=20BITS_PER_BYTE=20!=3D=20pg_BITS_PER_BYTE=0A= +#error=20"incompatible=20byte=20widths=20between=20NSPR=20and=20= postgres"=0A+#endif=0A+#else=0A+#define=20BITS_PER_BYTE=20= pg_BITS_PER_BYTE=0A+#endif=0A+#undef=20pg_BITS_PER_BYTE=0A+=0A+#include=20= "common/cryptohash.h"=0A+#ifndef=20FRONTEND=0A+#include=20= "utils/memutils.h"=0A+#include=20"utils/resowner.h"=0A+#include=20= "utils/resowner_private.h"=0A+#endif=0A+=0A+/*=0A+=20*=20In=20the=20= backend,=20use=20an=20allocation=20in=20TopMemoryContext=20to=20count=20= for=0A+=20*=20resowner=20cleanup=20handling.=20=20In=20the=20frontend,=20= use=20malloc=20to=20be=20able=0A+=20*=20to=20return=20a=20failure=20= status=20back=20to=20the=20caller.=0A+=20*/=0A+#ifndef=20FRONTEND=0A= +#define=20ALLOC(size)=20MemoryContextAlloc(TopMemoryContext,=20size)=0A= +#define=20FREE(ptr)=20pfree(ptr)=0A+#else=0A+#define=20ALLOC(size)=20= malloc(size)=0A+#define=20FREE(ptr)=20free(ptr)=0A+#endif=0A+=0A+/*=0A+=20= *=20Internal=20pg_cryptohash_ctx=20structure.=0A+=20*/=0A+struct=20= pg_cryptohash_ctx=0A+{=0A+=09pg_cryptohash_type=20type;=0A+=0A+=09= NSSInitContext=20*nss_context;=0A+=09PK11Context=20*pk11_context;=0A+=09= HASH_HashType=20hash_type;=0A+=0A+#ifndef=20FRONTEND=0A+=09ResourceOwner=20= resowner;=0A+#endif=0A+};=0A+=0A+/*=0A+=20*=20pg_cryptohash_create=0A+=20= *=0A+=20*=20Create=20and=20allocate=20a=20new=20hash=20context.=20= Returns=20NULL=20on=20failure=20in=20the=0A+=20*=20frontend,=20and=20= raise=20error=20without=20returning=20in=20the=20backend.=0A+=20*/=0A= +pg_cryptohash_ctx=20*=0A+pg_cryptohash_create(pg_cryptohash_type=20= type)=0A+{=0A+=09NSSInitParameters=20params;=0A+=09pg_cryptohash_ctx=20= *ctx;=0A+=09SECOidData=20*hash;=0A+=0A+#ifndef=20FRONTEND=0A+=09/*=0A+=09= =20*=20Make=20sure=20that=20the=20resource=20owner=20has=20space=20to=20= remember=20this=20reference.=0A+=09=20*=20This=20can=20error=20out=20= with=20"out=20of=20memory",=20so=20do=20this=20before=20any=20other=0A+=09= =20*=20allocation=20to=20avoid=20leaking.=0A+=09=20*/=0A+=09= ResourceOwnerEnlargeCryptoHash(CurrentResourceOwner);=0A+#endif=0A+=0A+=09= ctx=20=3D=20ALLOC(sizeof(pg_cryptohash_ctx));=0A+=0A+=09if=20(!ctx)=0A+=09= =09goto=20error;=0A+=0A+=09switch(type)=0A+=09{=0A+=09=09case=20PG_SHA1:=0A= +=09=09=09ctx->hash_type=20=3D=20SEC_OID_SHA1;=0A+=09=09=09break;=0A+=09=09= case=20PG_MD5:=0A+=09=09=09ctx->hash_type=20=3D=20SEC_OID_MD5;=0A+=09=09=09= break;=0A+=09=09case=20PG_SHA224:=0A+=09=09=09ctx->hash_type=20=3D=20= SEC_OID_SHA224;=0A+=09=09=09break;=0A+=09=09case=20PG_SHA256:=0A+=09=09=09= ctx->hash_type=20=3D=20SEC_OID_SHA256;=0A+=09=09=09break;=0A+=09=09case=20= PG_SHA384:=0A+=09=09=09ctx->hash_type=20=3D=20SEC_OID_SHA384;=0A+=09=09=09= break;=0A+=09=09case=20PG_SHA512:=0A+=09=09=09ctx->hash_type=20=3D=20= SEC_OID_SHA512;=0A+=09=09=09break;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20= Initialize=20our=20own=20NSS=20context=20without=20a=20database=20= backing=20it.=0A+=09=20*/=0A+=09memset(¶ms,=200,=20sizeof(params));=0A= +=09params.length=20=3D=20sizeof(params);=0A+=09ctx->nss_context=20=3D=20= NSS_InitContext("",=20"",=20"",=20"",=20¶ms,=0A+=09=09=09=09=09=09=09= =09=09=20=20=20NSS_INIT_READONLY=20|=20NSS_INIT_NOCERTDB=20|=0A+=09=09=09= =09=09=09=09=09=09=20=20=20NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A= +=09=09=09=09=09=09=09=09=09=20=20=20NSS_INIT_NOROOTINIT=20|=20= NSS_INIT_PK11RELOAD);=0A+=09if=20(!ctx->nss_context)=0A+=09{=0A+=09=09= explicit_bzero(ctx,=20sizeof(pg_cryptohash_ctx));=0A+=09=09FREE(ctx);=0A= +=09=09goto=20error;=0A+=09}=0A+=09ctx->type=20=3D=20type;=0A+=09hash=20= =3D=20SECOID_FindOIDByTag(ctx->hash_type);=0A+=09ctx->pk11_context=20=3D=20= PK11_CreateDigestContext(hash->offset);=0A+=09if=20(!ctx->pk11_context)=0A= +=09{=0A+=09=09explicit_bzero(ctx,=20sizeof(pg_cryptohash_ctx));=0A+=09=09= FREE(ctx);=0A+=09=09goto=20error;=0A+=09}=0A+=0A+#ifndef=20FRONTEND=0A+=09= ctx->resowner=20=3D=20CurrentResourceOwner;=0A+=09= ResourceOwnerRememberCryptoHash(CurrentResourceOwner,=0A+=09=09=09=09=09=09= =09=09=09PointerGetDatum(ctx));=0A+#endif=0A+=0A+=09return=20ctx;=0A+=0A= +error:=0A+#ifndef=20FRONTEND=0A+=09ereport(ERROR,=0A+=09=09=09= (errcode(ERRCODE_OUT_OF_MEMORY),=0A+=09=09=09=20errmsg("out=20of=20= memory")));=0A+#endif=0A+=09return=20NULL;=0A+}=0A+=0A+/*=0A+=20*=20= pg_cryptohash_init=0A+=20*=09=09=09Initialize=20the=20passed=20hash=20= context=0A+=20*=0A+=20*=20Returns=200=20on=20success,=20-1=20on=20= failure.=0A+=20*/=0A+int=0A+pg_cryptohash_init(pg_cryptohash_ctx=20*ctx)=0A= +{=0A+=09SECStatus=09=09status;=0A+=0A+=09status=20=3D=20= PK11_DigestBegin(ctx->pk11_context);=0A+=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09=09return=20-1;=0A+=09return=200;=0A+}=0A+=0A+/*=0A+=20= *=20pg_cryptohash_update=0A+=20*=0A+=20*=20Update=20a=20hash=20context.=20= =20Returns=200=20on=20success,=20-1=20on=20failure.=0A+=20*/=0A+int=0A= +pg_cryptohash_update(pg_cryptohash_ctx=20*ctx,=20const=20uint8=20*data,=20= size_t=20len)=0A+{=0A+=09SECStatus=09status;=0A+=0A+=09if=20(ctx=20=3D=3D=20= NULL)=0A+=09=09return=20-1;=0A+=0A+=09status=20=3D=20= PK11_DigestOp(ctx->pk11_context,=20data,=20len);=0A+=09if=20(status=20!=3D= =20SECSuccess)=0A+=09=09return=20-1;=0A+=0A+=09return=200;=0A+}=0A+=0A= +/*=0A+=20*=20pg_cryptohash_final=0A+=20*=0A+=20*=20Finalize=20a=20hash=20= context.=20=20Returns=200=20on=20success,=20-1=20on=20failure.=0A+=20*/=0A= +int=0A+pg_cryptohash_final(pg_cryptohash_ctx=20*ctx,=20uint8=20*dest)=0A= +{=0A+=09SECStatus=09status;=0A+=09unsigned=20int=20outlen;=0A+=09const=20= SECHashObject=20*object;=0A+=0A+=09object=20=3D=20= HASH_GetHashObject(ctx->hash_type);=0A+=09status=20=3D=20= PK11_DigestFinal(ctx->pk11_context,=20dest,=20&outlen,=20= object->length);=0A+=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09= return=20-1;=0A+=09return=200;=0A+}=0A+=0A+/*=0A+=20*=20= pg_cryptohash_free=0A+=20*=0A+=20*=20Free=20a=20hash=20context=20and=20= the=20associated=20NSS=20context.=0A+=20*/=0A+void=0A= +pg_cryptohash_free(pg_cryptohash_ctx=20*ctx)=0A+{=0A+=09PRBool=09=09= free_context=20=3D=20PR_TRUE;=0A+=09if=20(!ctx)=0A+=09=09return;=0A+=0A+=09= PK11_DestroyContext(ctx->pk11_context,=20free_context);=0A+#ifndef=20= FRONTEND=0A+=09ResourceOwnerForgetCryptoHash(ctx->resowner,=20= PointerGetDatum(ctx));=0A+#endif=0A+=09= NSS_ShutdownContext(ctx->nss_context);=0A+=09explicit_bzero(ctx,=20= sizeof(pg_cryptohash_ctx));=0A+=09FREE(ctx);=0A+}=0Adiff=20--git=20= a/src/tools/msvc/Mkvcbuild.pm=20b/src/tools/msvc/Mkvcbuild.pm=0Aindex=20= 660387d0e8..180eb0aa3f=20100644=0A---=20a/src/tools/msvc/Mkvcbuild.pm=0A= +++=20b/src/tools/msvc/Mkvcbuild.pm=0A@@=20-132,6=20+132,10=20@@=20sub=20= mkvcbuild=0A=20=09=09push(@pgcommonallfiles,=20'cryptohash_openssl.c');=0A= =20=09=09push(@pgcommonallfiles,=20'protocol_openssl.c');=0A=20=09}=0A+=09= elsif=20($solution->{options}->{nss})=0A+=09{=0A+=09=09= push(@pgcommonallfiles,=20'cryptohash_nss.c');=0A+=09}=0A=20=09else=0A=20= =09{=0A=20=09=09push(@pgcommonallfiles,=20'cryptohash.c');=0A--=20=0A= 2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2 Content-Disposition: attachment; filename=v23-0006-NSS-contrib-modules.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v23-0006-NSS-contrib-modules.patch" Content-Transfer-Encoding: quoted-printable =46rom=200d0a2152f1ff936af9ae9040388edc3484b6b757=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2028=20Oct=202020=2011:34:37=20+0100=0ASubject:=20[PATCH=20= v23=206/8]=20NSS=20contrib=20modules=0A=0A---=0A=20= contrib/pgcrypto/Makefile=20=20=20|=20=20=207=20+-=0A=20= contrib/pgcrypto/nss.c=20=20=20=20=20=20|=20773=20= ++++++++++++++++++++++++++++++++++++=0A=20contrib/sslinfo/sslinfo.c=20=20= =20|=20=2032=20++=0A=20doc/src/sgml/pgcrypto.sgml=20=20|=20=2038=20+-=0A=20= doc/src/sgml/sslinfo.sgml=20=20=20|=20=2012=20+-=0A=20= src/tools/msvc/Install.pm=20=20=20|=20=20=203=20+-=0A=20= src/tools/msvc/Mkvcbuild.pm=20|=20=2012=20+-=0A=207=20files=20changed,=20= 863=20insertions(+),=2014=20deletions(-)=0A=20create=20mode=20100644=20= contrib/pgcrypto/nss.c=0A=0Adiff=20--git=20a/contrib/pgcrypto/Makefile=20= b/contrib/pgcrypto/Makefile=0Aindex=203500bd4c72..ede7a78146=20100644=0A= ---=20a/contrib/pgcrypto/Makefile=0A+++=20b/contrib/pgcrypto/Makefile=0A= @@=20-7,11=20+7,14=20@@=20INT_TESTS=20=3D=20sha2=0A=20OSSL_SRCS=20=3D=20= openssl.c=20pgp-mpi-openssl.c=0A=20OSSL_TESTS=20=3D=20sha2=20des=203des=20= cast5=0A=20=0A+NSS_SRCS=20=3D=20nss.c=20pgp-mpi-internal.c=20imath.c=20= blf.c=0A+NSS_TESTS=20=3D=20sha2=20des=203des=0A+=0A=20ZLIB_TST=20=3D=20= pgp-compression=0A=20ZLIB_OFF_TST=20=3D=20pgp-zlib-DISABLED=0A=20=0A= -CF_SRCS=20=3D=20$(if=20$(subst=20openssl,,$(with_ssl)),=20$(OSSL_SRCS),=20= $(INT_SRCS))=0A-CF_TESTS=20=3D=20$(if=20$(subst=20openssl,,$(with_ssl)),=20= $(OSSL_TESTS),=20$(INT_TESTS))=0A+CF_SRCS=20=3D=20$(if=20$(findstring=20= openssl,=20$(with_ssl)),=20$(OSSL_SRCS),=20$(if=20$(findstring=20nss,=20= $(with_ssl)),=20$(NSS_SRCS),=20$(INT_SRCS)))=0A+CF_TESTS=20=3D=20$(if=20= $(findstring=20openssl,=20$(with_ssl)),=20$(OSSL_TESTS),=20$(if=20= $(findstring=20nss,=20$(with_ssl)),=20$(NSS_TESTS),=20$(INT_TESTS)))=0A=20= CF_PGP_TESTS=20=3D=20$(if=20$(subst=20no,,$(with_zlib)),=20$(ZLIB_TST),=20= $(ZLIB_OFF_TST))=0A=20=0A=20SRCS=20=3D=20\=0Adiff=20--git=20= a/contrib/pgcrypto/nss.c=20b/contrib/pgcrypto/nss.c=0Anew=20file=20mode=20= 100644=0Aindex=200000000000..da66152d65=0A---=20/dev/null=0A+++=20= b/contrib/pgcrypto/nss.c=0A@@=20-0,0=20+1,773=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20nss.c=0A+=20*=09=20=20Wrapper=20for=20using=20NSS=20= as=20a=20backend=20for=20pgcrypto=20PX=0A+=20*=0A+=20*=0A+=20*=20= Portions=20Copyright=20(c)=201996-2020,=20PostgreSQL=20Global=20= Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=201994,=20= Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=09=20=20contrib/pgcrypto/nss.c=0A+=20*=0A+=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#include=20"postgres.h"=0A+=0A+#include=20"px.h"=0A= +#include=20"blf.h"=0A+#include=20"utils/memutils.h"=0A+=0A+/*=0A+=20*=20= BITS_PER_BYTE=20is=20also=20defined=20in=20the=20NSPR=20header=20files,=20= so=20we=20need=20to=20undef=0A+=20*=20our=20version=20to=20avoid=20= compiler=20warnings=20on=20redefinition.=0A+=20*/=0A+#define=20= pg_BITS_PER_BYTE=20BITS_PER_BYTE=0A+#undef=20BITS_PER_BYTE=0A+=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+=0A+/*=0A+=20*=20Ensure=20= that=20the=20colliding=20definitions=20match,=20else=20throw=20an=20= error.=20In=20case=0A+=20*=20NSPR=20has=20removed=20the=20definition=20= for=20some=20reason,=20make=20sure=20to=20put=20ours=0A+=20*=20back=20= again.=0A+=20*/=0A+#if=20defined(BITS_PER_BYTE)=0A+#if=20BITS_PER_BYTE=20= !=3D=20pg_BITS_PER_BYTE=0A+#error=20"incompatible=20byte=20widths=20= between=20NSPR=20and=20postgres"=0A+#endif=0A+#else=0A+#define=20= BITS_PER_BYTE=20pg_BITS_PER_BYTE=0A+#endif=0A+#undef=20pg_BITS_PER_BYTE=0A= +=0A+/*=0A+=20*=20Define=20our=20own=20mechanisms=20for=20Blowfish=20as=20= it's=20not=20implemented=20by=20NSS.=0A+=20*/=0A+#define=20BLOWFISH_CBC=09= (1)=0A+#define=20BLOWFISH_ECB=09(2)=0A+=0A+/*=0A+=20*=20Data=20= structures=20for=20recording=20cipher=20implementations=20as=20well=20as=20= ongoing=0A+=20*=20cipher=20operations.=0A+=20*/=0A+typedef=20struct=20= nss_digest=0A+{=0A+=09NSSInitContext=20*context;=0A+=09PK11Context=20= *hash_context;=0A+=09HASH_HashType=20hash_type;=0A+}=09=09=09nss_digest;=0A= +=0A+typedef=20struct=20cipher_implementation=0A+{=0A+=09/*=20Function=20= pointers=20to=20cipher=20operations=20*/=0A+=09int=09=09=09(*init)=20= (PX_Cipher=20*pxc,=20const=20uint8=20*key,=20unsigned=20klen,=20const=20= uint8=20*iv);=0A+=09unsigned=09(*get_block_size)=20(PX_Cipher=20*pxc);=0A= +=09unsigned=09(*get_key_size)=20(PX_Cipher=20*pxc);=0A+=09unsigned=09= (*get_iv_size)=20(PX_Cipher=20*pxc);=0A+=09int=09=09=09(*encrypt)=20= (PX_Cipher=20*pxc,=20const=20uint8=20*data,=20unsigned=20dlen,=20uint8=20= *res);=0A+=09int=09=09=09(*decrypt)=20(PX_Cipher=20*pxc,=20const=20uint8=20= *data,=20unsigned=20dlen,=20uint8=20*res);=0A+=09void=09=09(*free)=20= (PX_Cipher=20*pxc);=0A+=0A+=09/*=20The=20mechanism=20describing=20the=20= cipher=20used=20*/=0A+=09union=0A+=09{=0A+=09=09CK_MECHANISM_TYPE=20nss;=0A= +=09=09CK_ULONG=09internal;=0A+=09}=09=09=09mechanism;=0A+=09int=09=09=09= keylen;=0A+=09bool=09=09is_nss;=0A+}=09=09=09cipher_implementation;=0A+=0A= +typedef=20struct=20nss_cipher=0A+{=0A+=09const=20cipher_implementation=20= *impl;=0A+=09NSSInitContext=20*context;=0A+=09PK11Context=20= *crypt_context;=0A+=09SECItem=20=20=20=20*params;=0A+=0A+=09PK11SymKey=20= *encrypt_key;=0A+=09PK11SymKey=20*decrypt_key;=0A+}=09=09=09nss_cipher;=0A= +=0A+typedef=20struct=20internal_cipher=0A+{=0A+=09const=20= cipher_implementation=20*impl;=0A+=09BlowfishContext=20context;=0A+}=09=09= =09internal_cipher;=0A+=0A+typedef=20struct=20nss_cipher_ref=0A+{=0A+=09= const=20char=20*name;=0A+=09const=20cipher_implementation=20*impl;=0A+}=09= =09=09nss_cipher_ref;=0A+=0A+/*=0A+=20*=20Prototypes=0A+=20*/=0A+static=20= unsigned=20nss_get_iv_size(PX_Cipher=20*pxc);=0A+static=20unsigned=20= nss_get_block_size(PX_Cipher=20*pxc);=0A+=0A+/*=0A+=20*=20= nss_GetHashOidTagByHashType=0A+=20*=0A+=20*=20Returns=20the=20= corresponding=20SECOidTag=20for=20the=20passed=20hash=20type.=20NSS=20= 3.43=0A+=20*=20includes=20HASH_GetHashOidTagByHashType=20for=20this=20= purpose,=20but=20at=20the=20time=20of=0A+=20*=20writing=20is=20not=20= commonly=20available=20so=20we=20need=20our=20own=20version=20till=20= then.=0A+=20*/=0A+static=20SECOidTag=0A= +nss_GetHashOidTagByHashType(HASH_HashType=20type)=0A+{=0A+=09if=20(type=20= =3D=3D=20HASH_AlgMD2)=0A+=09=09return=20SEC_OID_MD2;=0A+=09if=20(type=20= =3D=3D=20HASH_AlgMD5)=0A+=09=09return=20SEC_OID_MD5;=0A+=09if=20(type=20= =3D=3D=20HASH_AlgSHA1)=0A+=09=09return=20SEC_OID_SHA1;=0A+=09if=20(type=20= =3D=3D=20HASH_AlgSHA224)=0A+=09=09return=20SEC_OID_SHA224;=0A+=09if=20= (type=20=3D=3D=20HASH_AlgSHA256)=0A+=09=09return=20SEC_OID_SHA256;=0A+=09= if=20(type=20=3D=3D=20HASH_AlgSHA384)=0A+=09=09return=20SEC_OID_SHA384;=0A= +=09if=20(type=20=3D=3D=20HASH_AlgSHA512)=0A+=09=09return=20= SEC_OID_SHA512;=0A+=0A+=09return=20SEC_OID_UNKNOWN;=0A+}=0A+=0A+static=20= unsigned=0A+nss_digest_block_size(PX_MD=20*pxmd)=0A+{=0A+=09nss_digest=20= *digest=20=3D=20(nss_digest=20*)=20pxmd->p.ptr;=0A+=09const=20= SECHashObject=20*object;=0A+=0A+=09object=20=3D=20= HASH_GetHashObject(digest->hash_type);=0A+=09return=20= object->blocklength;=0A+}=0A+=0A+static=20unsigned=0A= +nss_digest_result_size(PX_MD=20*pxmd)=0A+{=0A+=09nss_digest=20*digest=20= =3D=20(nss_digest=20*)=20pxmd->p.ptr;=0A+=09const=20SECHashObject=20= *object;=0A+=0A+=09object=20=3D=20HASH_GetHashObject(digest->hash_type);=0A= +=09return=20object->length;=0A+}=0A+=0A+static=20void=0A= +nss_digest_free(PX_MD=20*pxmd)=0A+{=0A+=09nss_digest=20*digest=20=3D=20= (nss_digest=20*)=20pxmd->p.ptr;=0A+=09PRBool=09=09free_ctx=20=3D=20= PR_TRUE;=0A+=0A+=09PK11_DestroyContext(digest->hash_context,=20= free_ctx);=0A+=09NSS_ShutdownContext(digest->context);=0A+}=0A+=0A= +static=20void=0A+nss_digest_update(PX_MD=20*pxmd,=20const=20uint8=20= *data,=20unsigned=20dlen)=0A+{=0A+=09nss_digest=20*digest=20=3D=20= (nss_digest=20*)=20pxmd->p.ptr;=0A+=0A+=09= PK11_DigestOp(digest->hash_context,=20data,=20dlen);=0A+}=0A+=0A+static=20= void=0A+nss_digest_reset(PX_MD=20*pxmd)=0A+{=0A+=09nss_digest=20*digest=20= =3D=20(nss_digest=20*)=20pxmd->p.ptr;=0A+=0A+=09= PK11_DigestBegin(digest->hash_context);=0A+}=0A+=0A+static=20void=0A= +nss_digest_finish(PX_MD=20*pxmd,=20uint8=20*dst)=0A+{=0A+=09unsigned=20= int=20outlen;=0A+=09nss_digest=20*digest=20=3D=20(nss_digest=20*)=20= pxmd->p.ptr;=0A+=09const=20SECHashObject=20*object;=0A+=0A+=09object=20=3D= =20HASH_GetHashObject(digest->hash_type);=0A+=09= PK11_DigestFinal(digest->hash_context,=20dst,=20&outlen,=20= object->length);=0A+}=0A+=0A+int=0A+px_find_digest(const=20char=20*name,=20= PX_MD=20**res)=0A+{=0A+=09PX_MD=09=20=20=20*pxmd;=0A+=09= NSSInitParameters=20params;=0A+=09NSSInitContext=20*nss_context;=0A+=09= bool=09=09found=20=3D=20false;=0A+=09nss_digest=20*digest;=0A+=09= SECStatus=09status;=0A+=09SECOidData=20*hash;=0A+=09HASH_HashType=20t;=0A= +=0A+=09/*=0A+=09=20*=20Initialize=20our=20own=20NSS=20context=20without=20= a=20database=20backing=20it.=0A+=09=20*/=0A+=09memset(¶ms,=200,=20= sizeof(params));=0A+=09params.length=20=3D=20sizeof(params);=0A+=09= nss_context=20=3D=20NSS_InitContext("",=20"",=20"",=20"",=20¶ms,=0A+=09= =09=09=09=09=09=09=09=20=20NSS_INIT_READONLY=20|=20NSS_INIT_NOCERTDB=20|=0A= +=09=09=09=09=09=09=09=09=20=20NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20= |=0A+=09=09=09=09=09=09=09=09=20=20NSS_INIT_NOROOTINIT=20|=20= NSS_INIT_PK11RELOAD);=0A+=0A+=09/*=0A+=09=20*=20There=20is=20no=20API=20= function=20for=20looking=20up=20a=20digest=20algorithm=20from=20a=20name=0A= +=09=20*=20string,=20but=20there=20is=20a=20publicly=20accessible=20= array=20which=20can=20be=20scanned=0A+=09=20*=20for=20the=20name.=0A+=09=20= */=0A+=09for=20(t=20=3D=20HASH_AlgNULL=20+=201;=20t=20<=20HASH_AlgTOTAL;=20= t++)=0A+=09{=0A+=09=09SECOidTag=09hash_oid;=0A+=09=09char=09=20=20=20*p;=0A= +=0A+=09=09hash_oid=20=3D=20nss_GetHashOidTagByHashType(t);=0A+=0A+=09=09= if=20(hash_oid=20=3D=3D=20SEC_OID_UNKNOWN)=0A+=09=09=09return=20= PXE_NO_HASH;=0A+=0A+=09=09hash=20=3D=20SECOID_FindOIDByTag(hash_oid);=0A= +=09=09if=20(pg_strcasecmp(hash->desc,=20name)=20=3D=3D=200)=0A+=09=09{=0A= +=09=09=09found=20=3D=20true;=0A+=09=09=09break;=0A+=09=09}=0A+=0A+=09=09= /*=0A+=09=09=20*=20NSS=20saves=20the=20algorithm=20names=20using=20= SHA-xxx=20notation=20whereas=0A+=09=09=20*=20OpenSSL=20use=20SHAxxx.=20= To=20make=20sure=20the=20user=20finds=20the=20requested=0A+=09=09=20*=20= algorithm=20let's=20remove=20the=20dash=20and=20compare=20that=20= spelling=20as=20well.=0A+=09=09=20*/=0A+=09=09if=20((p=20=3D=20= strchr(hash->desc,=20'-'))=20!=3D=20NULL)=0A+=09=09{=0A+=09=09=09char=09=09= tmp[12];=0A+=0A+=09=09=09memcpy(tmp,=20hash->desc,=20p=20-=20= hash->desc);=0A+=09=09=09memcpy(tmp=20+=20(p=20-=20hash->desc),=20p=20+=20= 1,=20strlen(hash->desc)=20-=20(p=20-=20hash->desc)=20+=201);=0A+=09=09=09= if=20(pg_strcasecmp(tmp,=20name)=20=3D=3D=200)=0A+=09=09=09{=0A+=09=09=09= =09found=20=3D=20true;=0A+=09=09=09=09break;=0A+=09=09=09}=0A+=09=09}=0A= +=09}=0A+=0A+=09if=20(!found)=0A+=09=09return=20PXE_NO_HASH;=0A+=0A+=09= digest=20=3D=20palloc(sizeof(*digest));=0A+=0A+=09digest->context=20=3D=20= nss_context;=0A+=09digest->hash_context=20=3D=20= PK11_CreateDigestContext(hash->offset);=0A+=09digest->hash_type=20=3D=20= t;=0A+=09if=20(digest->hash_context=20=3D=3D=20NULL)=0A+=09{=0A+=09=09= pfree(digest);=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09status=20=3D=20= PK11_DigestBegin(digest->hash_context);=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09PK11_DestroyContext(digest->hash_context,=20= PR_TRUE);=0A+=09=09pfree(digest);=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09= pxmd=20=3D=20palloc(sizeof(*pxmd));=0A+=09pxmd->result_size=20=3D=20= nss_digest_result_size;=0A+=09pxmd->block_size=20=3D=20= nss_digest_block_size;=0A+=09pxmd->reset=20=3D=20nss_digest_reset;=0A+=09= pxmd->update=20=3D=20nss_digest_update;=0A+=09pxmd->finish=20=3D=20= nss_digest_finish;=0A+=09pxmd->free=20=3D=20nss_digest_free;=0A+=09= pxmd->p.ptr=20=3D=20(void=20*)=20digest;=0A+=0A+=09*res=20=3D=20pxmd;=0A= +=0A+=09return=200;=0A+}=0A+=0A+static=20int=0A+bf_init(PX_Cipher=20= *pxc,=20const=20uint8=20*key,=20unsigned=20klen,=20const=20uint8=20*iv)=0A= +{=0A+=09internal_cipher=20*cipher=20=3D=20(internal_cipher=20*)=20= pxc->ptr;=0A+=0A+=09blowfish_setkey(&cipher->context,=20key,=20klen);=0A= +=09if=20(iv)=0A+=09=09blowfish_setiv(&cipher->context,=20iv);=0A+=0A+=09= return=200;=0A+}=0A+=0A+static=20int=0A+bf_encrypt(PX_Cipher=20*pxc,=20= const=20uint8=20*data,=20unsigned=20dlen,=20uint8=20*res)=0A+{=0A+=09= internal_cipher=20*cipher=20=3D=20(internal_cipher=20*)=20pxc->ptr;=0A+=09= uint8=09=20=20=20*buf;=0A+=0A+=09if=20(dlen=20=3D=3D=200)=0A+=09=09= return=200;=0A+=0A+=09if=20(dlen=20&=207)=0A+=09=09return=20= PXE_NOTBLOCKSIZE;=0A+=0A+=09buf=20=3D=20palloc(dlen);=0A+=09memcpy(buf,=20= data,=20dlen);=0A+=0A+=09if=20(cipher->impl->mechanism.internal=20=3D=3D=20= BLOWFISH_ECB)=0A+=09=09blowfish_encrypt_ecb(buf,=20dlen,=20= &cipher->context);=0A+=09else=0A+=09=09blowfish_encrypt_cbc(buf,=20dlen,=20= &cipher->context);=0A+=0A+=09memcpy(res,=20buf,=20dlen);=0A+=09= pfree(buf);=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20int=0A= +bf_decrypt(PX_Cipher=20*pxc,=20const=20uint8=20*data,=20unsigned=20= dlen,=20uint8=20*res)=0A+{=0A+=09internal_cipher=20*cipher=20=3D=20= (internal_cipher=20*)=20pxc->ptr;=0A+=0A+=09if=20(dlen=20=3D=3D=200)=0A+=09= =09return=200;=0A+=0A+=09if=20(dlen=20&=207)=0A+=09=09return=20= PXE_NOTBLOCKSIZE;=0A+=0A+=09memcpy(res,=20data,=20dlen);=0A+=09if=20= (cipher->impl->mechanism.internal=20=3D=3D=20BLOWFISH_ECB)=0A+=09=09= blowfish_decrypt_ecb(res,=20dlen,=20&cipher->context);=0A+=09else=0A+=09=09= blowfish_decrypt_cbc(res,=20dlen,=20&cipher->context);=0A+=0A+=09return=20= 0;=0A+}=0A+=0A+static=20void=0A+bf_free(PX_Cipher=20*pxc)=0A+{=0A+=09= internal_cipher=20*cipher=20=3D=20(internal_cipher=20*)=20pxc->ptr;=0A+=0A= +=09pfree(cipher);=0A+=09pfree(pxc);=0A+}=0A+=0A+static=20int=0A= +nss_symkey_blockcipher_init(PX_Cipher=20*pxc,=20const=20uint8=20*key,=20= unsigned=20klen,=0A+=09=09=09=09=09=09=09const=20uint8=20*iv)=0A+{=0A+=09= nss_cipher=20*cipher=20=3D=20(nss_cipher=20*)=20pxc->ptr;=0A+=09SECItem=09= =09iv_item;=0A+=09unsigned=20char=20*iv_item_data;=0A+=09SECItem=09=09= key_item;=0A+=09int=09=09=09keylen;=0A+=09PK11SlotInfo=20*slot;=0A+=0A+=09= if=20(cipher->impl->mechanism.nss=20=3D=3D=20CKM_AES_CBC=20||=0A+=09=09= cipher->impl->mechanism.nss=20=3D=3D=20CKM_AES_ECB)=0A+=09{=0A+=09=09if=20= (klen=20<=3D=20128=20/=208)=0A+=09=09=09keylen=20=3D=20128=20/=208;=0A+=09= =09else=20if=20(klen=20<=3D=20192=20/=208)=0A+=09=09=09keylen=20=3D=20= 192=20/=208;=0A+=09=09else=20if=20(klen=20<=3D=20256=20/=208)=0A+=09=09=09= keylen=20=3D=20256=20/=208;=0A+=09=09else=0A+=09=09=09return=20= PXE_CIPHER_INIT;=0A+=09}=0A+=09else=0A+=09=09keylen=20=3D=20= cipher->impl->keylen;=0A+=0A+=09key_item.type=20=3D=20siBuffer;=0A+=09= key_item.data=20=3D=20(unsigned=20char=20*)=20key;=0A+=09key_item.len=20= =3D=20keylen;=0A+=0A+=09/*=0A+=09=20*=20If=20hardware=20acceleration=20= is=20configured=20in=20NSS=20one=20can=20theoretically=20get=0A+=09=20*=20= a=20better=20slot=20by=20calling=20PK11_GetBestSlot()=20with=20the=20= mechanism=20passed=0A+=09=20*=20to=20it.=20Unless=20there=20are=20= complaints,=20using=20the=20simpler=20API=20will=20make=0A+=09=20*=20= error=20handling=20easier=20though.=0A+=09=20*/=0A+=09slot=20=3D=20= PK11_GetInternalSlot();=0A+=09if=20(!slot)=0A+=09=09return=20= PXE_CIPHER_INIT;=0A+=0A+=09/*=0A+=09=20*=20The=20key=20must=20be=20set=20= up=20for=20the=20operation,=20and=20since=20we=20don't=20know=20at=0A+=09= =20*=20this=20point=20whether=20we=20are=20asked=20to=20encrypt=20or=20= decrypt=20we=20need=20to=20store=0A+=09=20*=20both=20versions.=0A+=09=20= */=0A+=09cipher->decrypt_key=20=3D=20PK11_ImportSymKey(slot,=20= cipher->impl->mechanism.nss,=0A+=09=09=09=09=09=09=09=09=09=09=09= PK11_OriginUnwrap,=0A+=09=09=09=09=09=09=09=09=09=09=09CKA_DECRYPT,=20= &key_item,=0A+=09=09=09=09=09=09=09=09=09=09=09NULL);=0A+=09= cipher->encrypt_key=20=3D=20PK11_ImportSymKey(slot,=20= cipher->impl->mechanism.nss,=0A+=09=09=09=09=09=09=09=09=09=09=09= PK11_OriginUnwrap,=0A+=09=09=09=09=09=09=09=09=09=09=09CKA_ENCRYPT,=20= &key_item,=0A+=09=09=09=09=09=09=09=09=09=09=09NULL);=0A+=09= PK11_FreeSlot(slot);=0A+=0A+=09if=20(!cipher->decrypt_key=20||=20= !cipher->encrypt_key)=0A+=09=09return=20PXE_CIPHER_INIT;=0A+=0A+=09if=20= (iv)=0A+=09{=0A+=09=09iv_item.type=20=3D=20siBuffer;=0A+=09=09= iv_item.data=20=3D=20(unsigned=20char=20*)=20iv;=0A+=09=09iv_item.len=20= =3D=20nss_get_iv_size(pxc);=0A+=09}=0A+=09else=0A+=09{=0A+=09=09/*=0A+=09= =09=20*=20The=20documentation=20states=20that=20either=20passing=20.data=20= =3D=200;=20.len=20=3D=200;=0A+=09=09=20*=20in=20the=20iv_item,=20or=20= NULL=20as=20iv_item,=20to=20PK11_ParamFromIV=20should=20be=0A+=09=09=20*=20= done=20when=20IV=20is=20missing.=20That=20however=20leads=20to=20= segfaults=20in=20the=0A+=09=09=20*=20library,=20the=20workaround=20that=20= works=20in=20modern=20=20library=20versions=20is=0A+=09=09=20*=20to=20= pass=20in=20a=20keysized=20zeroed=20out=20IV.=0A+=09=09=20*/=0A+=09=09= iv_item_data=20=3D=20palloc0(nss_get_iv_size(pxc));=0A+=09=09= iv_item.type=20=3D=20siBuffer;=0A+=09=09iv_item.data=20=3D=20= iv_item_data;=0A+=09=09iv_item.len=20=3D=20nss_get_iv_size(pxc);=0A+=09}=0A= +=0A+=09cipher->params=20=3D=20= PK11_ParamFromIV(cipher->impl->mechanism.nss,=20&iv_item);=0A+=0A+=09/*=20= If=20we=20had=20to=20make=20a=20mock=20IV,=20free=20it=20once=20made=20= into=20a=20param=20*/=0A+=09if=20(!iv)=0A+=09=09pfree(iv_item_data);=0A+=0A= +=09if=20(cipher->params=20=3D=3D=20NULL)=0A+=09=09return=20= PXE_CIPHER_INIT;=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20int=0A= +nss_decrypt(PX_Cipher=20*pxc,=20const=20uint8=20*data,=20unsigned=20= dlen,=20uint8=20*res)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= (nss_cipher=20*)=20pxc->ptr;=0A+=09SECStatus=09status;=0A+=09int=09=09=09= outlen;=0A+=0A+=09if=20(!cipher->crypt_context)=0A+=09{=0A+=09=09= cipher->crypt_context=20=3D=0A+=09=09=09= PK11_CreateContextBySymKey(cipher->impl->mechanism.nss,=20CKA_DECRYPT,=0A= +=09=09=09=09=09=09=09=09=09=20=20=20cipher->decrypt_key,=20= cipher->params);=0A+=09}=0A+=0A+=09status=20=3D=20= PK11_CipherOp(cipher->crypt_context,=20res,=20&outlen,=20dlen,=20data,=20= dlen);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20= PXE_DECRYPT_FAILED;=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20int=0A= +nss_encrypt(PX_Cipher=20*pxc,=20const=20uint8=20*data,=20unsigned=20= dlen,=20uint8=20*res)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= (nss_cipher=20*)=20pxc->ptr;=0A+=09SECStatus=09status;=0A+=09int=09=09=09= outlen;=0A+=0A+=09if=20(!cipher->crypt_context)=0A+=09{=0A+=09=09= cipher->crypt_context=20=3D=0A+=09=09=09= PK11_CreateContextBySymKey(cipher->impl->mechanism.nss,=20CKA_ENCRYPT,=0A= +=09=09=09=09=09=09=09=09=09=20=20=20cipher->decrypt_key,=20= cipher->params);=0A+=09}=0A+=0A+=09status=20=3D=20= PK11_CipherOp(cipher->crypt_context,=20res,=20&outlen,=20dlen,=20data,=20= dlen);=0A+=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20= PXE_DECRYPT_FAILED;=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20void=0A= +nss_free(PX_Cipher=20*pxc)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= pxc->ptr;=0A+=09PRBool=09=09free_ctx=20=3D=20PR_TRUE;=0A+=0A+=09= PK11_FreeSymKey(cipher->encrypt_key);=0A+=09= PK11_FreeSymKey(cipher->decrypt_key);=0A+=09= PK11_DestroyContext(cipher->crypt_context,=20free_ctx);=0A+=09= NSS_ShutdownContext(cipher->context);=0A+=09pfree(cipher);=0A+=0A+=09= pfree(pxc);=0A+}=0A+=0A+static=20unsigned=0A= +nss_get_block_size(PX_Cipher=20*pxc)=0A+{=0A+=09nss_cipher=20*cipher=20= =3D=20pxc->ptr;=0A+=0A+=09return=20= PK11_GetBlockSize(cipher->impl->mechanism.nss,=20NULL);=0A+}=0A+=0A= +static=20unsigned=0A+nss_get_key_size(PX_Cipher=20*pxc)=0A+{=0A+=09= nss_cipher=20*cipher=20=3D=20pxc->ptr;=0A+=0A+=09return=20= cipher->impl->keylen;=0A+}=0A+=0A+static=20unsigned=0A= +nss_get_iv_size(PX_Cipher=20*pxc)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= pxc->ptr;=0A+=0A+=09return=20= PK11_GetIVLength(cipher->impl->mechanism.nss);=0A+}=0A+=0A+static=20= unsigned=0A+bf_get_block_size(PX_Cipher=20*pxc)=0A+{=0A+=09return=208;=0A= +}=0A+=0A+static=20unsigned=0A+bf_get_key_size(PX_Cipher=20*pxc)=0A+{=0A= +=09return=20448=20/=208;=0A+}=0A+=0A+static=20unsigned=0A= +bf_get_iv_size(PX_Cipher=20*pxc)=0A+{=0A+=09return=208;=0A+}=0A+=0A+/*=0A= +=20*=20Cipher=20Implementations=0A+=20*/=0A+static=20const=20= cipher_implementation=20nss_des_cbc=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES_CBC,=0A+=09.keylen=20=3D=20= 8,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_des_ecb=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES_ECB,=0A+=09.keylen=20=3D=20= 8,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_des3_cbc=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES3_CBC,=0A+=09.keylen=20=3D=20= 24,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_des3_ecb=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES3_ECB,=0A+=09.keylen=20=3D=20= 24,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_aes_cbc=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_AES_CBC,=0A+=09.keylen=20=3D=20= 32,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_aes_ecb=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_AES_ECB,=0A+=09.keylen=20=3D=20= 32,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_bf_ecb=20=3D=20{=0A+=09.init=20=3D=20= bf_init,=0A+=09.get_block_size=20=3D=20bf_get_block_size,=0A+=09= .get_key_size=20=3D=20bf_get_key_size,=0A+=09.get_iv_size=20=3D=20= bf_get_iv_size,=0A+=09.encrypt=20=3D=20bf_encrypt,=0A+=09.decrypt=20=3D=20= bf_decrypt,=0A+=09.free=20=3D=20bf_free,=0A+=09.mechanism.internal=20=3D=20= BLOWFISH_ECB,=0A+=09.keylen=20=3D=2056,=0A+=09.is_nss=20=3D=20false=0A= +};=0A+=0A+static=20const=20cipher_implementation=20nss_bf_cbc=20=3D=20{=0A= +=09.init=20=3D=20bf_init,=0A+=09.get_block_size=20=3D=20= bf_get_block_size,=0A+=09.get_key_size=20=3D=20bf_get_key_size,=0A+=09= .get_iv_size=20=3D=20bf_get_iv_size,=0A+=09.encrypt=20=3D=20bf_encrypt,=0A= +=09.decrypt=20=3D=20bf_decrypt,=0A+=09.free=20=3D=20bf_free,=0A+=09= .mechanism.internal=20=3D=20BLOWFISH_CBC,=0A+=09.keylen=20=3D=2056,=0A+=09= .is_nss=20=3D=20false=0A+};=0A+=0A+/*=0A+=20*=20Lookup=20table=20for=20= finding=20the=20implementation=20based=20on=20a=20name.=20CAST5=20as=20= well=0A+=20*=20as=20BLOWFISH=20are=20defined=20as=20cipher=20mechanisms=20= in=20NSS=20but=20error=20out=20with=0A+=20*=20= SEC_ERROR_INVALID_ALGORITHM.=20Blowfish=20is=20implemented=20using=20the=20= internal=0A+=20*=20implementation=20while=20CAST5=20isn't=20supported=20= at=20all=20at=20this=20time,=0A+=20*/=0A+static=20const=20nss_cipher_ref=20= nss_cipher_lookup[]=20=3D=20{=0A+=09{"des",=20&nss_des_cbc},=0A+=09= {"des-cbc",=20&nss_des_cbc},=0A+=09{"des-ecb",=20&nss_des_ecb},=0A+=09= {"des3-cbc",=20&nss_des3_cbc},=0A+=09{"3des",=20&nss_des3_cbc},=0A+=09= {"3des-cbc",=20&nss_des3_cbc},=0A+=09{"des3-ecb",=20&nss_des3_ecb},=0A+=09= {"3des-ecb",=20&nss_des3_ecb},=0A+=09{"aes",=20&nss_aes_cbc},=0A+=09= {"aes-cbc",=20&nss_aes_cbc},=0A+=09{"aes-ecb",=20&nss_aes_ecb},=0A+=09= {"rijndael",=20&nss_aes_cbc},=0A+=09{"rijndael-cbc",=20&nss_aes_cbc},=0A= +=09{"rijndael-ecb",=20&nss_aes_ecb},=0A+=09{"blowfish",=20&nss_bf_cbc},=0A= +=09{"blowfish-cbc",=20&nss_bf_cbc},=0A+=09{"blowfish-ecb",=20= &nss_bf_ecb},=0A+=09{"bf",=20&nss_bf_cbc},=0A+=09{"bf-cbc",=20= &nss_bf_cbc},=0A+=09{"bf-ecb",=20&nss_bf_ecb},=0A+=09{NULL}=0A+};=0A+=0A= +/*=0A+=20*=20px_find_cipher=0A+=20*=0A+=20*=20Search=20for=20the=20= requested=20cipher=20and=20see=20if=20there=20is=20support=20for=20it,=20= and=20if=0A+=20*=20so=20return=20an=20allocated=20object=20containing=20= the=20playbook=20for=20how=20to=20encrypt=0A+=20*=20and=20decrypt=20= using=20the=20cipher.=0A+=20*/=0A+int=0A+px_find_cipher(const=20char=20= *alias,=20PX_Cipher=20**res)=0A+{=0A+=09const=20nss_cipher_ref=20= *cipher_ref;=0A+=09PX_Cipher=20=20*px_cipher;=0A+=09NSSInitParameters=20= params;=0A+=09NSSInitContext=20*nss_context;=0A+=09nss_cipher=20*cipher;=0A= +=09internal_cipher=20*int_cipher;=0A+=0A+=09for=20(cipher_ref=20=3D=20= nss_cipher_lookup;=20cipher_ref->name;=20cipher_ref++)=0A+=09{=0A+=09=09= if=20(strcmp(cipher_ref->name,=20alias)=20=3D=3D=200)=0A+=09=09=09break;=0A= +=09}=0A+=0A+=09if=20(!cipher_ref->name)=0A+=09=09return=20= PXE_NO_CIPHER;=0A+=0A+=09/*=0A+=09=20*=20Fill=20in=20the=20PX_Cipher=20= to=20pass=20back=20to=20PX=20describing=20the=20operations=20to=0A+=09=20= *=20perform=20in=20order=20to=20use=20the=20cipher.=0A+=09=20*/=0A+=09= px_cipher=20=3D=20palloc(sizeof(*px_cipher));=0A+=09= px_cipher->block_size=20=3D=20cipher_ref->impl->get_block_size;=0A+=09= px_cipher->key_size=20=3D=20cipher_ref->impl->get_key_size;=0A+=09= px_cipher->iv_size=20=3D=20cipher_ref->impl->get_iv_size;=0A+=09= px_cipher->free=20=3D=20cipher_ref->impl->free;=0A+=09px_cipher->init=20= =3D=20cipher_ref->impl->init;=0A+=09px_cipher->encrypt=20=3D=20= cipher_ref->impl->encrypt;=0A+=09px_cipher->decrypt=20=3D=20= cipher_ref->impl->decrypt;=0A+=0A+=09/*=0A+=09=20*=20Set=20the=20private=20= data,=20which=20is=20different=20for=20NSS=20and=20internal=20ciphers=0A= +=09=20*/=0A+=09if=20(cipher_ref->impl->is_nss)=0A+=09{=0A+=09=09/*=0A+=09= =09=20*=20Initialize=20our=20own=20NSS=20context=20without=20a=20= database=20backing=20it.=20At=0A+=09=09=20*=20some=20point=20we=20might=20= want=20to=20allow=20users=20to=20use=20stored=20keys=20in=20the=0A+=09=09= =20*=20database=20rather=20than=20passing=20them=20via=20SELECT=20= encrypt(),=20and=20then=0A+=09=09=20*=20this=20need=20to=20be=20changed=20= to=20open=20a=20user=20specified=20database.=0A+=09=09=20*/=0A+=09=09= memset(¶ms,=200,=20sizeof(params));=0A+=09=09params.length=20=3D=20= sizeof(params);=0A+=09=09nss_context=20=3D=20NSS_InitContext("",=20"",=20= "",=20"",=20¶ms,=0A+=09=09=09=09=09=09=09=09=09=20=20= NSS_INIT_READONLY=20|=20NSS_INIT_NOCERTDB=20|=0A+=09=09=09=09=09=09=09=09= =09=20=20NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A+=09=09=09=09=09= =09=09=09=09=20=20NSS_INIT_NOROOTINIT=20|=20NSS_INIT_PK11RELOAD);=0A+=0A= +=09=09/*=20nss_cipher=20is=20the=20private=20state=20struct=20for=20the=20= operation=20*/=0A+=09=09cipher=20=3D=20palloc(sizeof(*cipher));=0A+=09=09= cipher->context=20=3D=20nss_context;=0A+=09=09cipher->impl=20=3D=20= cipher_ref->impl;=0A+=09=09cipher->crypt_context=20=3D=20NULL;=0A+=0A+=09= =09px_cipher->ptr=20=3D=20cipher;=0A+=09}=0A+=09else=0A+=09{=0A+=09=09= int_cipher=20=3D=20palloc0(sizeof(*int_cipher));=0A+=0A+=09=09= int_cipher->impl=20=3D=20cipher_ref->impl;=0A+=09=09px_cipher->ptr=20=3D=20= int_cipher;=0A+=09}=0A+=0A+=09*res=20=3D=20px_cipher;=0A+=09return=200;=0A= +}=0Adiff=20--git=20a/contrib/sslinfo/sslinfo.c=20= b/contrib/sslinfo/sslinfo.c=0Aindex=2030cae0bb98..3aadd90aa6=20100644=0A= ---=20a/contrib/sslinfo/sslinfo.c=0A+++=20b/contrib/sslinfo/sslinfo.c=0A= @@=20-9,9=20+9,11=20@@=0A=20=0A=20#include=20"postgres.h"=0A=20=0A= +#ifdef=20USE_OPENSSL=0A=20#include=20=0A=20#include=20= =0A=20#include=20=0A+#endif=0A=20=0A=20= #include=20"access/htup_details.h"=0A=20#include=20"funcapi.h"=0A@@=20= -21,6=20+23,7=20@@=0A=20=0A=20PG_MODULE_MAGIC;=0A=20=0A+#ifdef=20= USE_OPENSSL=0A=20static=20Datum=20X509_NAME_field_to_text(X509_NAME=20= *name,=20text=20*fieldName);=0A=20static=20Datum=20= ASN1_STRING_to_text(ASN1_STRING=20*str);=0A=20=0A@@=20-31,6=20+34,7=20@@=20= typedef=20struct=0A=20{=0A=20=09TupleDesc=09tupdesc;=0A=20}=20= SSLExtensionInfoContext;=0A+#endif=0A=20=0A=20/*=0A=20=20*=20Indicates=20= whether=20current=20session=20uses=20SSL=0A@@=20-131,6=20+135,7=20@@=20= ssl_client_serial(PG_FUNCTION_ARGS)=0A=20}=0A=20=0A=20=0A+#ifdef=20= USE_OPENSSL=0A=20/*=0A=20=20*=20Converts=20OpenSSL=20ASN1_STRING=20= structure=20into=20text=0A=20=20*=0A@@=20-282,7=20+287,23=20@@=20= ssl_issuer_field(PG_FUNCTION_ARGS)=0A=20=09else=0A=20=09=09return=20= result;=0A=20}=0A+#endif=09=09=09=09=09=09=09/*=20USE_OPENSSL=20*/=0A=20=0A= +#ifdef=20USE_NSS=0A+PG_FUNCTION_INFO_V1(ssl_client_dn_field);=0A+Datum=0A= +ssl_client_dn_field(PG_FUNCTION_ARGS)=0A+{=0A+=09PG_RETURN_NULL();=0A+}=0A= +=0A+PG_FUNCTION_INFO_V1(ssl_issuer_field);=0A+Datum=0A= +ssl_issuer_field(PG_FUNCTION_ARGS)=0A+{=0A+=09PG_RETURN_NULL();=0A+}=0A= +#endif=09=09=09=09=09=09=09/*=20USE_NSS=20*/=0A=20=0A=20/*=0A=20=20*=20= Returns=20current=20client=20certificate=20subject=20as=20one=20string=0A= @@=20-338,6=20+359,7=20@@=20ssl_issuer_dn(PG_FUNCTION_ARGS)=0A=20}=0A=20=0A= =20=0A+#ifdef=20USE_OPENSSL=0A=20/*=0A=20=20*=20Returns=20information=20= about=20available=20SSL=20extensions.=0A=20=20*=0A@@=20-471,3=20+493,13=20= @@=20ssl_extension_info(PG_FUNCTION_ARGS)=0A=20=09/*=20All=20done=20*/=0A= =20=09SRF_RETURN_DONE(funcctx);=0A=20}=0A+#endif=09=09=09=09=09=09=09/*=20= USE_OPENSSL=20*/=0A+=0A+#ifdef=20USE_NSS=0A= +PG_FUNCTION_INFO_V1(ssl_extension_info);=0A+Datum=0A= +ssl_extension_info(PG_FUNCTION_ARGS)=0A+{=0A+=09PG_RETURN_NULL();=0A+}=0A= +#endif=09=09=09=09=09=09=09/*=20USE_NSS=20*/=0Adiff=20--git=20= a/doc/src/sgml/pgcrypto.sgml=20b/doc/src/sgml/pgcrypto.sgml=0Aindex=20= 3d74e15ec9..bf486f0c07=20100644=0A---=20a/doc/src/sgml/pgcrypto.sgml=0A= +++=20b/doc/src/sgml/pgcrypto.sgml=0A@@=20-45,8=20+45,9=20@@=20= digest(data=20bytea,=20type=20text)=20returns=20bytea=0A=20=20=20=20=20= sha224,=20sha256,=0A=20=20=20=20=20= sha384=20and=20sha512.=0A=20=20=20=20= =20If=20pgcrypto=20was=20built=20with=0A-=20=20=20=20= OpenSSL,=20more=20algorithms=20are=20= available,=20as=0A-=20=20=20=20detailed=20in=20.=0A+=20=20=20=20= OpenSSL=20or=20= NSS,=0A+=20=20=20=20more=20algorithms=20are=20= available,=20as=0A+=20=20=20=20detailed=20in=20.=0A=20=20=20=20=0A= =20=0A=20=20=20=20=0A@@=20-764,7=20+765,7=20@@=20= pgp_sym_encrypt(data,=20psw,=20'compress-algo=3D1,=20= cipher-algo=3Daes256')=0A=20=20=20=20=20Which=20cipher=20algorithm=20to=20= use.=0A=20=20=20=20=0A=20=0A-Values:=20bf,=20= aes128,=20aes192,=20aes256=20(OpenSSL-only:=203des,=20= cast5)=0A+Values:=20bf,=20aes128,=20aes192,=20aes256=20= (OpenSSL-only:=203des,=20cast5;=20= NSS-only:=203des)=0A=20Default:=20aes128=0A=20Applies=20= to:=20pgp_sym_encrypt,=20pgp_pub_encrypt=0A=20=0A@@=20= -1153,8=20+1154,8=20@@=20gen_random_uuid()=20returns=20uuid=0A=20=20=20=20= =0A=20=20=20=20=20pgcrypto=20configures=20= itself=20according=20to=20the=20findings=20of=20the=0A=20=20=20=20=20= main=20PostgreSQL=20configure=20script.=20=20The=20= options=20that=0A-=20=20=20=20affect=20it=20are=20= --with-zlib=20and=0A-=20=20=20=20= --with-openssl.=0A+=20=20=20=20affect=20it=20are=20= --with-zlib,=0A+=20=20=20=20= --with-ssl=3Dopenssl=20and=20= --with-ssl=3Dnss.=0A=20=20=20=20=0A=20=0A=20=20= =20=20=0A@@=20-1169,14=20+1170,16=20@@=20gen_random_uuid()=20= returns=20uuid=0A=20=20=20=20=20BIGNUM=20functions.=0A=20=20=20=20= =0A=20=0A-=20=20=20=0A= -=20=20=20=20Summary=20of=20Functionality=20with=20and=20without=20= OpenSSL=0A-=20=20=20=20=0A+=20=20=20=0A+=20=20=20=20Summary=20= of=20Functionality=20with=20and=20without=20external=20cryptographic=0A+=20= =20=20=20=20=20library=0A+=20=20=20=20=0A=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20= =20Functionality=0A=20=20=20=20=20=20=20=20= Built-in=0A=20=20=20=20=20=20=20=20With=20= OpenSSL=0A+=20=20=20=20=20=20=20With=20NSS=0A=20=20= =20=20=20=20=20=0A=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A@@=20-1184,51=20+1187,67=20@@=20gen_random_uuid()=20returns=20= uuid=0A=20=20=20=20=20=20=20=20MD5=0A=20=20=20=20=20=20=20= =20yes=0A=20=20=20=20=20=20=20=20yes=0A+=20= =20=20=20=20=20=20yes=0A=20=20=20=20=20=20=20=0A=20=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20=20SHA1=0A=20=20= =20=20=20=20=20=20yes=0A=20=20=20=20=20=20=20=20= yes=0A+=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20= SHA224/256/384/512=0A=20=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=20yes=0A+=20=20= =20=20=20=20=20yes=0A=20=20=20=20=20=20=20=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=20Other=20digest=20= algorithms=0A=20=20=20=20=20=20=20=20no=0A=20=20=20= =20=20=20=20=20yes=20(Note=201)=0A+=20=20=20=20=20=20=20= yes=20(Note=201)=0A=20=20=20=20=20=20=20=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=20Blowfish=0A=20= =20=20=20=20=20=20=20yes=0A=20=20=20=20=20=20=20=20= yes=0A+=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20= AES=0A=20=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=20yes=0A+=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20DES/3DES/CAST5=0A=20=20=20= =20=20=20=20=20no=0A=20=20=20=20=20=20=20=20= yes=0A+=20=20=20=20=20=20=20yes=0A+=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= CAST5=0A+=20=20=20=20=20=20=20no=0A+=20=20=20= =20=20=20=20yes=0A+=20=20=20=20=20=20=20no=0A= =20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20= =20=20=20Raw=20encryption=0A=20=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=20yes=0A+=20=20= =20=20=20=20=20yes=0A=20=20=20=20=20=20=20=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=20PGP=20Symmetric=20= encryption=0A=20=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=20yes=0A+=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20PGP=20Public-Key=20= encryption=0A=20=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=20yes=0A+=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A=20=20=20=20=20=0A@@=20-1241,7=20+1260,8=20@@=20= gen_random_uuid()=20returns=20uuid=0A=20=20=20=20=0A=20=20=20= =20=20=0A=20=20=20=20=20=20=0A-=20=20=20=20=20=20Any=20= digest=20algorithm=20OpenSSL=20supports=0A+=20= =20=20=20=20=20Any=20digest=20algorithm=20= OpenSSL=20and=0A+=20=20=20=20=20=20= NSS=20supports=0A=20=20=20=20=20=20=20is=20= automatically=20picked=20up.=0A=20=20=20=20=20=20=20This=20is=20not=20= possible=20with=20ciphers,=20which=20need=20to=20be=20supported=0A=20=20=20= =20=20=20=20explicitly.=0Adiff=20--git=20a/doc/src/sgml/sslinfo.sgml=20= b/doc/src/sgml/sslinfo.sgml=0Aindex=203213c039ca..f3ae2fc3b8=20100644=0A= ---=20a/doc/src/sgml/sslinfo.sgml=0A+++=20b/doc/src/sgml/sslinfo.sgml=0A= @@=20-22,7=20+22,8=20@@=0A=20=0A=20=20=0A=20=20=20This=20extension=20= won't=20build=20at=20all=20unless=20the=20installation=20was=0A-=20=20= configured=20with=20--with-openssl.=0A+=20=20= configured=20with=20SSL=20support,=20such=20as=20= --with-ssl=3Dopenssl=0A+=20=20or=20= --with-ssl=3Dnss.=0A=20=20=0A=20=0A=20=20= =0A@@=20-208,6=20+209,9=20@@=20emailAddress=0A=20=20=20=20=20=20= the=20X.500=20and=20X.509=20standards,=20so=20you=20cannot=20just=20= assign=20arbitrary=0A=20=20=20=20=20=20meaning=20to=20them.=0A=20=20=20=20= =20=0A+=20=20=20=20=0A+=20=20=20=20=20This=20function=20is=20= only=20available=20when=20using=20OpenSSL.=0A= +=20=20=20=20=0A=20=20=20=20=20=0A=20=20=20=20= =0A=20=0A@@=20-223,6=20+227,9=20@@=20emailAddress=0A=20=20= =20=20=20=20Same=20as=20ssl_client_dn_field,=20but=20= for=20the=20certificate=20issuer=0A=20=20=20=20=20=20rather=20than=20the=20= certificate=20subject.=0A=20=20=20=20=20=0A+=20=20=20=20=0A= +=20=20=20=20=20This=20function=20is=20only=20available=20when=20using=20= OpenSSL.=0A+=20=20=20=20=0A=20=20=20=20= =20=0A=20=20=20=20=0A=20=0A@@=20-238,6=20= +245,9=20@@=20emailAddress=0A=20=20=20=20=20=20Provide=20information=20= about=20extensions=20of=20client=20certificate:=20extension=20name,=0A=20= =20=20=20=20=20extension=20value,=20and=20if=20it=20is=20a=20critical=20= extension.=0A=20=20=20=20=20=0A+=20=20=20=20=0A+=20=20=20=20= =20This=20function=20is=20only=20available=20when=20using=20= OpenSSL.=0A+=20=20=20=20=0A=20=20=20=20= =20=0A=20=20=20=20=0A=20=20=20=0A= diff=20--git=20a/src/tools/msvc/Install.pm=20b/src/tools/msvc/Install.pm=0A= index=20ea3af48777..afe72a7e97=20100644=0A---=20= a/src/tools/msvc/Install.pm=0A+++=20b/src/tools/msvc/Install.pm=0A@@=20= -438,7=20+438,8=20@@=20sub=20CopyContribFiles=0A=20=09=09{=0A=20=09=09=09= #=20These=20configuration-based=20exclusions=20must=20match=20= vcregress.pl=0A=20=09=09=09next=20if=20($d=20eq=20"uuid-ossp"=20=20&&=20= !defined($config->{uuid}));=0A-=09=09=09next=20if=20($d=20eq=20"sslinfo"=20= =20=20=20&&=20!defined($config->{openssl}));=0A+=09=09=09next=20if=20($d=20= eq=20"sslinfo"=20=20=20=20&&=20!defined($config->{openssl})=0A+=09=09=09=20= =20&&=20!defined($config->{nss}));=0A=20=09=09=09next=20if=20($d=20eq=20= "xml2"=20=20=20=20=20=20=20&&=20!defined($config->{xml}));=0A=20=09=09=09= next=20if=20($d=20=3D~=20/_plperl$/=20=20=20&&=20= !defined($config->{perl}));=0A=20=09=09=09next=20if=20($d=20=3D~=20= /_plpython$/=20&&=20!defined($config->{python}));=0Adiff=20--git=20= a/src/tools/msvc/Mkvcbuild.pm=20b/src/tools/msvc/Mkvcbuild.pm=0Aindex=20= ff01acf3f6..660387d0e8=20100644=0A---=20a/src/tools/msvc/Mkvcbuild.pm=0A= +++=20b/src/tools/msvc/Mkvcbuild.pm=0A@@=20-445,9=20+445,14=20@@=20sub=20= mkvcbuild=0A=20=09=09push=20@contrib_excludes,=20'xml2';=0A=20=09}=0A=20=0A= +=09if=20(!$solution->{options}->{openssl}=20&&=20= !$solution->{options}->{nss})=0A+=09{=0A+=09=09push=20@contrib_excludes,=20= 'sslinfo';=0A+=09}=0A+=0A=20=09if=20(!$solution->{options}->{openssl})=0A= =20=09{=0A-=09=09push=20@contrib_excludes,=20'sslinfo',=20= 'ssl_passphrase_callback';=0A+=09=09push=20@contrib_excludes,=20= 'ssl_passphrase_callback';=0A=20=09}=0A=20=0A=20=09if=20= (!$solution->{options}->{uuid})=0A@@=20-477,6=20+482,11=20@@=20sub=20= mkvcbuild=0A=20=09=09$pgcrypto->AddFiles('contrib/pgcrypto',=20= 'openssl.c',=0A=20=09=09=09'pgp-mpi-openssl.c');=0A=20=09}=0A+=09elsif=20= ($solution->{options}->{nss})=0A+=09{=0A+=09=09= $pgcrypto->AddFiles('contrib/pgcrypto',=20'nss.c',=0A+=09=09=09= 'pgp-mpi-internal.c',=20'imath.c',=20'blf.c');=0A+=09}=0A=20=09else=0A=20= =09{=0A=20=09=09$pgcrypto->AddFiles(=0A--=20=0A2.21.1=20(Apple=20= Git-122.3)=0A=0A= --Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2 Content-Disposition: attachment; filename=v23-0005-NSS-Documentation.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v23-0005-NSS-Documentation.patch" Content-Transfer-Encoding: quoted-printable =46rom=20c78e286bcab3bed4a5f5739981c1b0c4d69d44c3=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2028=20Oct=202020=2011:26:31=20+0100=0ASubject:=20[PATCH=20= v23=205/8]=20NSS=20Documentation=0A=0A---=0A=20= doc/src/sgml/acronyms.sgml=20=20=20=20=20|=20=2043=20++++++++++++=0A=20= doc/src/sgml/config.sgml=20=20=20=20=20=20=20|=20=2028=20+++++++-=0A=20= doc/src/sgml/installation.sgml=20|=20=2044=20++++++++++--=0A=20= doc/src/sgml/libpq.sgml=20=20=20=20=20=20=20=20|=20=2099=20= +++++++++++++++++++++++++-=0A=20doc/src/sgml/runtime.sgml=20=20=20=20=20=20= |=20123=20+++++++++++++++++++++++++++++++--=0A=205=20files=20changed,=20= 319=20insertions(+),=2018=20deletions(-)=0A=0Adiff=20--git=20= a/doc/src/sgml/acronyms.sgml=20b/doc/src/sgml/acronyms.sgml=0Aindex=20= 4e5ec983c0..7b02c8a622=20100644=0A---=20a/doc/src/sgml/acronyms.sgml=0A= +++=20b/doc/src/sgml/acronyms.sgml=0A@@=20-441,6=20+441,28=20@@=0A=20=20=20= =20=20=0A=20=20=20=20=0A=20=0A+=20=20=20= =0A+=20=20=20=20NSPR=0A+=20= =20=20=20=0A+=20=20=20=20=20=0A+=20=20=20=20=20=20=0A= +=20=20=20=20=20=20Netscape=20Portable=20Runtime=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A+=20= =20=20=0A+=20=20=20=20NSS=0A= +=20=20=20=20=0A+=20=20=20=20=20=0A+=20=20=20=20=20=20= =0A= +=20=20=20=20=20=20Network=20Security=20Services=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A=20=20= =20=20=0A=20=20=20=20=20= ODBC=0A=20=20=20=20=20=0A@@=20= -539,6=20+561,17=20@@=0A=20=20=20=20=20=0A=20=20=20=20= =0A=20=0A+=20=20=20=0A+=20=20=20=20= PKCS#12=0A+=20=20=20=20=0A+=20=20= =20=20=20=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20= Public-Key=20Cryptography=20Standards=20#12=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A=20=20= =20=20=0A=20=20=20=20=20PL=0A= =20=20=20=20=20=0A@@=20-684,6=20+717,16=20@@=0A=20=20=20=20=20= =0A=20=20=20=20=0A=20=0A+=20=20=20= =0A+=20=20=20=20TLS=0A+=20=20= =20=20=0A+=20=20=20=20=20=0A+=20=20=20=20=20=20=0A+=20=20= =20=20=20=20Transport=20Layer=20Security=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A=20=20= =20=20=0A=20=20=20=20=20= TOAST=0A=20=20=20=20=20=0Adiff=20= --git=20a/doc/src/sgml/config.sgml=20b/doc/src/sgml/config.sgml=0Aindex=20= f1037df5a9..00ad1553ae=20100644=0A---=20a/doc/src/sgml/config.sgml=0A+++=20= b/doc/src/sgml/config.sgml=0A@@=20-1236,6=20+1236,23=20@@=20include_dir=20= 'conf.d'=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A=20=0A+=20=20=20=20=20=0A+=20=20=20=20=20=20= ssl_database=20(string)=0A+=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20= ssl_database=20configuration=20= parameter=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=0A= +=20=20=20=20=20=20=20=20Specifies=20the=20name=20of=20the=20file=20= containing=20the=20server=20certificates=20and=0A+=20=20=20=20=20=20=20=20= keys=20when=20using=20NSS=20for=20= SSL=0A+=20=20=20=20=20=20=20=20connections.=20This=20= parameter=20can=20only=20be=20set=20in=20the=0A+=20=20=20=20=20=20=20=20= postgresql.conf=20file=20or=20on=20the=20server=20= command=0A+=20=20=20=20=20=20=20=20line.=0A+=20=20=20=20=20=20=20=0A= +=20=20=20=20=20=20=0A+=20=20=20=20=20=0A+=0A=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20= ssl_ciphers=20(string)=0A=20=20=20=20= =20=20=20=0A@@=20-1252,7=20+1269,9=20@@=20include_dir=20= 'conf.d'=0A=20=20=20=20=20=20=20=20=20connections=20using=20TLS=20= version=201.2=20and=20lower=20are=20affected.=20=20There=20is=0A=20=20=20= =20=20=20=20=20=20currently=20no=20setting=20that=20controls=20the=20= cipher=20choices=20used=20by=20TLS=0A=20=20=20=20=20=20=20=20=20version=20= 1.3=20connections.=20=20The=20default=20value=20is=0A-=20=20=20=20=20=20=20= =20HIGH:MEDIUM:+3DES:!aNULL.=20=20The=20default=20is=20= usually=20a=0A+=20=20=20=20=20=20=20=20= HIGH:MEDIUM:+3DES:!aNULL=20for=20servers=20which=20= have=0A+=20=20=20=20=20=20=20=20been=20built=20with=20= OpenSSL=20as=20the=0A+=20=20=20=20=20=20=20=20= SSL=20library.=20=20The=20default=20is=20usually=20a=0A= =20=20=20=20=20=20=20=20=20reasonable=20choice=20unless=20you=20have=20= specific=20security=20requirements.=0A=20=20=20=20=20=20=20=20=0A=20= =0A@@=20-1454,8=20+1473,11=20@@=20include_dir=20'conf.d'=0A=20=20=20=20=20= =20=20=20=0A=20=20=20=20=20=20=20=20=20Sets=20an=20external=20= command=20to=20be=20invoked=20when=20a=20passphrase=20for=0A=20=20=20=20=20= =20=20=20=20decrypting=20an=20SSL=20file=20such=20as=20a=20private=20key=20= needs=20to=20be=20obtained.=20=20By=0A-=20=20=20=20=20=20=20=20default,=20= this=20parameter=20is=20empty,=20which=20means=20the=20built-in=20= prompting=0A-=20=20=20=20=20=20=20=20mechanism=20is=20used.=0A+=20=20=20=20= =20=20=20=20default,=20this=20parameter=20is=20empty.=20When=20the=20= server=20is=20using=0A+=20=20=20=20=20=20=20=20= OpenSSL,=20this=20means=20the=20built-in=20= prompting=0A+=20=20=20=20=20=20=20=20mechanism=20is=20used.=20When=20= using=20NSS,=20there=20is=0A+=20=20=20=20=20=20= =20=20no=20default=20prompting=20so=20a=20blank=20callback=20will=20be=20= used=20returning=20an=0A+=20=20=20=20=20=20=20=20empty=20password.=0A=20=20= =20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20=0A=20=20=20=20= =20=20=20=20=20The=20command=20must=20print=20the=20passphrase=20to=20= the=20standard=20output=20and=20exit=0Adiff=20--git=20= a/doc/src/sgml/installation.sgml=20b/doc/src/sgml/installation.sgml=0A= index=20a53389b728..bcfe6ad10c=20100644=0A---=20= a/doc/src/sgml/installation.sgml=0A+++=20= b/doc/src/sgml/installation.sgml=0A@@=20-250,7=20+250,7=20@@=20su=20-=20= postgres=0A=20=0A=20=20=20=20=20=0A=20=20=20=20=20=20=0A= -=20=20=20=20=20=20You=20need=20OpenSSL,=20if=20= you=20want=20to=20support=0A+=20=20=20=20=20=20You=20need=20a=20= supported=20SSL=20library,=20if=20you=20want=20to=20= support=0A=20=20=20=20=20=20=20encrypted=20client=20connections.=20=20= OpenSSL=20is=0A=20=20=20=20=20=20=20also=20= required=20for=20random=20number=20generation=20on=20platforms=20that=20= do=20not=0A=20=20=20=20=20=20=20have=20/dev/urandom=20= (except=20Windows).=20=20The=20minimum=0A@@=20-966,6=20+966,41=20@@=20= build-postgresql:=0A=20=20=20=20=20=20=20=20=0A=20=20=20=20=20= =20=20=0A=20=0A+=20=20=20=20=20=20=0A+=20=20= =20=20=20=20=20= =0A= +=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= SSL=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=20=20Build=20with=20support=20for=20= SSL=20(encrypted)=0A+=20=20=20=20=20=20=20=20=20= connections.=20LIBRARY=20must=20be=20one=20= of:=0A+=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= =20to=20build=20with=20= OpenSSL=20support.=0A+=20=20=20=20=20=20=20=20= =20=20=20=20This=20requires=20the=20OpenSSL=0A= +=20=20=20=20=20=20=20=20=20=20=20=20package=20to=20be=20installed.=20=20= configure=20will=20check=0A+=20=20=20=20=20=20=20=20= =20=20=20=20for=20the=20required=20header=20files=20and=20libraries=20to=20= make=20sure=20that=0A+=20=20=20=20=20=20=20=20=20=20=20=20your=20= OpenSSL=20installation=20is=20sufficient=0A+=20= =20=20=20=20=20=20=20=20=20=20=20before=20proceeding.=0A+=20=20=20=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=20=20=20=20=20to=20build=20with=20= libnss=20support.=0A+=20=20=20=20=20=20=20=20=20= =20=20=20This=20requires=20the=20NSS=20= package=20to=20be=20installed.=20Additionally,=0A+=20=20=20=20=20=20=20=20= =20=20=20=20NSS=20requires=20= NSPR=0A+=20=20=20=20=20=20=20=20=20=20=20=20= to=20be=20installed.=20configure=20will=20check=20= for=20the=0A+=20=20=20=20=20=20=20=20=20=20=20=20required=20header=20= files=20and=20libraries=20to=20make=20sure=20that=20your=0A+=20=20=20=20=20= =20=20=20=20=20=20=20NSS=20installation=20is=20= sufficient=20before=0A+=20=20=20=20=20=20=20=20=20=20=20=20proceeding.=0A= +=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=0A+=0A=20=20=20=20=20=20= =20=0A=20=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20= =0A@@=20-975,12=20+1010,7=20@@=20build-postgresql:=0A=20=20=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20=20=0A=20=20=20=20= =20=20=20=20=20=0A-=20=20=20=20=20=20=20=20=20Build=20with=20= support=20for=20SSL=20(encrypted)=0A-=20=20=20=20=20=20= =20=20=20connections.=20This=20requires=20the=20= OpenSSL=0A-=20=20=20=20=20=20=20=20=20package=20= to=20be=20installed.=20=20configure=20will=20check=0A= -=20=20=20=20=20=20=20=20=20for=20the=20required=20header=20files=20and=20= libraries=20to=20make=20sure=20that=0A-=20=20=20=20=20=20=20=20=20your=20= OpenSSL=20installation=20is=20sufficient=0A-=20= =20=20=20=20=20=20=20=20before=20proceeding.=0A+=20=20=20=20=20=20=20=20=20= Obsolete=20equivalent=20of=20--with-ssl=3Dopenssl.=0A=20= =20=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20=0A=20= =20=20=20=20=20=20=0Adiff=20--git=20= a/doc/src/sgml/libpq.sgml=20b/doc/src/sgml/libpq.sgml=0Aindex=20= b7a82453f0..89796de168=20100644=0A---=20a/doc/src/sgml/libpq.sgml=0A+++=20= b/doc/src/sgml/libpq.sgml=0A@@=20-830,6=20+830,12=20@@=20int=20= callback_fn(char=20*buf,=20int=20size,=20PGconn=20*conn);=0A=20=20=20=20=20= =20=20=20longjmp(...),=20etc.=20It=20must=20return=20= normally.=0A=20=20=20=20=20=20=20=0A=20=0A+=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20= PQsetSSLKeyPassHook_OpenSSL=20is=20only=20available=0A= +=20=20=20=20=20=20=20=20when=20the=20server=20was=20compiled=20with=20= OpenSSL=0A+=20=20=20=20=20=20=20=20support.=0A= +=20=20=20=20=20=20=0A+=0A=20=20=20=20=20=20=0A=20=20=20= =20=20=0A=20=0A@@=20-846,6=20+852,72=20@@=20= PQsslKeyPassHook_OpenSSL_type=20PQgetSSLKeyPassHook_OpenSSL(void);=0A=20= =0A=20=20=20=20=20=20=20=0A=20=0A+=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20= PQgetSSLKeyPassHook_OpenSSL=20is=20only=20available=0A= +=20=20=20=20=20=20=20=20when=20the=20server=20was=20compiled=20with=20= OpenSSL=0A+=20=20=20=20=20=20=20=20support.=0A= +=20=20=20=20=20=20=0A+=0A+=20=20=20=20=20=0A+=20=20=20= =20=0A+=0A+=20=20=20=20=0A+=20=20=20=20=20= PQsetSSLKeyPassHook_nssPQse= tSSLKeyPassHook_nss=0A+=20=20=20=20=20= =0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= PQsetSSLKeyPassHook_nss=20lets=20an=20application=20= override=0A+=20=20=20=20=20=20=20libpq's=20= default=20handling=20of=20password=20protected=0A+=20=20=20=20=20=20=20= objects=20in=20the=20NSS=20database=20using=0A= +=20=20=20=20=20=20=20=20= or=20interactive=20prompting.=0A+=0A+=0A+void=20= PQsetSSLKeyPassHook_nss(PQsslKeyPassHook_nss_type=20hook);=0A= +=0A+=0A+=20=20=20=20=20=20=20The=20application=20passes=20a=20= pointer=20to=20a=20callback=20function=20with=20signature:=0A= +=0A+char=20*callback_fn(PK11SlotInfo=20*slot,=20PRBool=20= retry,=20void=20*arg);=0A+=0A+=20=20=20=20=20=20=20= which=20libpq=20will=20call=0A+=20=20=20=20=20= =20=20instead=20of=20its=20default=0A+=20=20=20=20=20= =20=20PQdefaultSSLKeyPassHook_nss=20password=20= handler.=20The=0A+=20=20=20=20=20=20=20callback=20should=20determine=20= the=20password=20for=20the=20token=20and=20return=20a=0A+=20=20=20=20=20=20= =20pointer=20to=20it.=20The=20returned=20pointer=20should=20be=20= allocated=20with=20the=20NSS=0A+=20=20=20=20=20=20=20= PORT_Strdup=20function.=20The=20token=20for=20which=20= the=0A+=20=20=20=20=20=20=20password=20is=20requested=20is=20recorded=20= in=20the=20slot=20anc=20can=20be=20identified=20by=0A+=20=20=20=20=20=20=20= calling=20PK11_GetTokenName.=20If=20no=20password=20= is=0A+=20=20=20=20=20=20=20known,=20the=20callback=20should=20return=20= NULL.=20The=20memory=0A+=20=20=20=20=20=20=20will=20= be=20owned=20by=20NSS=20and=20should=20not=20= be=0A+=20=20=20=20=20=20=20freed.=0A+=20=20=20=20=20=20=0A+=0A+=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= PQsetSSLKeyPassHook_nss=20is=20only=20available=0A+=20= =20=20=20=20=20=20=20when=20the=20server=20was=20compiled=20with=20= NSS=0A+=20=20=20=20=20=20=20=20support.=0A+=20= =20=20=20=20=20=0A+=20=20=20=20=20=0A+=20=20=20=20= =0A+=0A+=20=20=20=20=0A+=20=20=20=20=20= PQgetSSLKeyPassHook_nssPQge= tSSLKeyPassHook_nss=0A+=20=20=20=20=20= =0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= PQgetSSLKeyPassHook_nss=20returns=20the=20current=0A= +=20=20=20=20=20=20=20NSS=20password=20hook,=20= or=20NULL=0A+=20=20=20=20=20=20=20if=20none=20has=20= been=20set.=0A+=0A+=0A+PQsslKeyPassHook_nss_type=20= PQgetSSLKeyPassHook_nss(void);=0A+=0A+=20=20=20=20=20=20= =0A+=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= PQgetSSLKeyPassHook_nss=20is=20only=20available=0A+=20= =20=20=20=20=20=20=20when=20the=20server=20was=20compiled=20with=20= nss=0A+=20=20=20=20=20=20=20=20support.=0A+=20= =20=20=20=20=20=0A+=0A=20=20=20=20=20=20=0A=20=20=20=20= =20=0A=20=0A@@=20-2497,6=20+2569,8=20@@=20void=20= *PQsslStruct(const=20PGconn=20*conn,=20const=20char=20*struct_name);=0A=20= =20=20=20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20= =20=20=20The=20struct(s)=20available=20depend=20on=20the=20SSL=20= implementation=20in=20use.=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=0A=20=20=20=20=20=20=20=20For=20= OpenSSL,=20there=20is=20one=20struct,=0A=20=20= =20=20=20=20=20=20available=20under=20the=20name=20"OpenSSL",=20and=20it=20= returns=20a=20pointer=20to=20the=0A=20=20=20=20=20=20=20=20= OpenSSL=20SSL=20struct.=0A= @@=20-2520,9=20+2594,14=20@@=20void=20*PQsslStruct(const=20PGconn=20= *conn,=20const=20char=20*struct_name);=0A=20]]>=0A=20=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20= =20This=20structure=20can=20be=20used=20to=20verify=20encryption=20= levels,=20check=20server=0A-=20=20=20=20=20=20=20certificates,=20and=20= more.=20Refer=20to=20the=20OpenSSL=0A-=20=20=20= =20=20=20=20documentation=20for=20information=20about=20this=20= structure.=0A+=20=20=20=20=20=20=20For=20NSS,=20= there=20is=20one=20struct=20available=20under=0A+=20=20=20=20=20=20=20= the=20name=20"NSS",=20and=20it=20returns=20a=20pointer=20to=20the=0A+=20=20= =20=20=20=20=20NSS=20= PRFileDesc.=0A+=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20These=20structures=20can=20be=20= used=20to=20verify=20encryption=20levels,=20check=20server=0A+=20=20=20=20= =20=20=20certificates,=20and=20more.=20Refer=20to=20the=20= SSL=20library=0A+=20=20=20=20=20=20=20documentation=20= for=20information=20about=20these=20structures.=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=0A=20=20=20=20=20=0A= @@=20-2549,6=20+2628,10=20@@=20void=20*PQgetssl(const=20PGconn=20*conn);=0A= =20=20=20=20=20=20=20=20=20= instead,=20and=20for=20more=20details=20about=20the=0A=20=20=20=20=20=20=20= =20connection,=20use=20.=0A=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= This=20function=20returns=20NULL=20when=20= SSL=0A+=20=20=20=20=20=20=20librariaes=20other=20than=20= OpenSSL=20are=20used.=0A+=20=20=20=20=20=20= =0A=20=20=20=20=20=20=0A=20=20=20=20=20=0A= =20=0A@@=20-7982,6=20+8065,11=20@@=20void=20PQinitOpenSSL(int=20do_ssl,=20= int=20do_crypto);=0A=20=20=20=20=20=20=20=20before=20first=20opening=20a=20= database=20connection.=20=20Also=20be=20sure=20that=20you=0A=20=20=20=20=20= =20=20=20have=20done=20that=20initialization=20before=20opening=20a=20= database=20connection.=0A=20=20=20=20=20=20=20=0A+=0A+=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20This=20function=20does=20nothing=20= when=20using=20NSS=20as=0A+=20=20=20=20=20=20=20= the=20SSL=20library.=0A+=20=20=20=20=20=20=0A=20= =20=20=20=20=20=0A=20=20=20=20=20=0A=20=0A@@=20= -8008,6=20+8096,11=20@@=20void=20PQinitSSL(int=20do_ssl);=0A=20=20=20=20=20= =20=20=20might=20be=20preferable=20for=20applications=20that=20need=20to=20= work=20with=20older=0A=20=20=20=20=20=20=20=20versions=20of=20= libpq.=0A=20=20=20=20=20=20=20=0A+=0A+=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20This=20function=20does=20= nothing=20when=20using=20NSS=20as=0A+=20=20=20= =20=20=20=20the=20SSL=20library.=0A+=20=20=20=20=20=20= =0A=20=20=20=20=20=20=0A=20=20=20=20=20=0A= =20=20=20=20=0Adiff=20--git=20a/doc/src/sgml/runtime.sgml=20= b/doc/src/sgml/runtime.sgml=0Aindex=20bf877c0e0c..2578ee8c06=20100644=0A= ---=20a/doc/src/sgml/runtime.sgml=0A+++=20b/doc/src/sgml/runtime.sgml=0A= @@=20-2185,15=20+2185,21=20@@=20pg_dumpall=20-p=205432=20|=20psql=20-d=20= postgres=20-p=205433=0A=20=0A=20=20=20=0A=20= =20=20=20SSL=0A+=20=20=20TLS=0A= =20=20=20=0A=20=0A=20=20=20=0A=20=20=20=20= PostgreSQL=20has=20native=20support=20for=20= using=0A=20=20=20=20SSL=20connections=20to=20encrypt=20= client/server=20communications=0A=20=20=20=20for=20increased=20security.=20= This=20requires=20that=0A-=20=20=20OpenSSL=20= is=20installed=20on=20both=20client=20and=0A+=20=20=20a=20supported=20= TLS=20library=20is=20installed=20on=20both=20client=20and=0A=20=20=20=20= server=20systems=20and=20that=20support=20in=20= PostgreSQL=20is=0A=20=20=20=20enabled=20at=20= build=20time=20(see=20).=0A+=20=20=20= Supported=20libraries=20are=20OpenSSL=20and=0A= +=20=20=20NSS.=20The=20terms=20= SSL=20and=0A+=20=20=20TLS=20are=20= often=20used=20interchangeably=20to=20mean=20a=20secure=0A+=20=20=20= connection=20using=20a=20TLS=20protocol,=20even=20= though=0A+=20=20=20SSL=20protocols=20are=20no=20= longer=20supported.=0A=20=20=20=0A=20=0A=20=20=20=0A@@=20-2213,8=20+2219,13=20@@=20pg_dumpall=20-p=20= 5432=20|=20psql=20-d=20postgres=20-p=205433=0A=20=20=20=0A=20=0A=20= =20=20=0A-=20=20=20To=20start=20in=20SSL=20= mode,=20files=20containing=20the=20server=20certificate=0A-=20=20=20and=20= private=20key=20must=20exist.=20=20By=20default,=20these=20files=20are=20= expected=20to=20be=0A+=20=20=20To=20start=20in=20SSL=20= mode,=20a=20server=20certificate=0A+=20=20=20and=20private=20key=20must=20= exist.=20The=20below=20sections=20on=20the=20different=20libraries=0A+=20= =20=20will=20discuss=20how=20to=20configure=20these.=0A+=20=20=0A= +=20=20=20=0A+=20=20=0A+=20=20=20By=20default,=20these=20files=20= are=20expected=20to=20be=0A=20=20=20=20named=20= server.crt=20and=20server.key,=20= respectively,=20in=0A=20=20=20=20the=20server's=20data=20directory,=20= but=20other=20names=20and=20locations=20can=20be=20specified=0A=20=20=20=20= using=20the=20configuration=20parameters=20=0A@@=20-2304,6=20+2315,18=20@@=20= pg_dumpall=20-p=205432=20|=20psql=20-d=20postgres=20-p=205433=0A=20=20=20= =0A=20=20=20=0A=20=0A+=20=20= =0A+=20=20=20NSS=20Configuration=0A+=0A+=20=20=0A+=20= =20=20PostgreSQL=20will=20look=20for=20= certificates=20and=20keys=0A+=20=20=20in=20the=20= NSS=20database=20specified=20by=20the=20= parameter=0A+=20=20=20=20in=20= postgresql.conf.=0A+=20=20=20The=20parameters=20for=20= certificate=20and=20key=20filenames=20are=20used=20to=20identify=20the=0A= +=20=20=20nicknames=20in=20the=20database.=0A+=20=20=0A+=20=20= =0A+=0A=20=20=20=0A=20=20= =20=20Using=20Client=20Certificates=0A=20=0A@@=20-2378,7=20= +2401,7=20@@=20pg_dumpall=20-p=205432=20|=20psql=20-d=20postgres=20-p=20= 5433=0A=20=20=20=0A=20=0A=20=20=20=0A-=20=20=20SSL=20Server=20File=20= Usage=0A+=20=20=20SSL=20Server=20File=20Parameter=20= Usage=0A=20=0A=20=20=20=20=0A=20=20=20=20=20=20summarizes=20the=20files=20that=20are=0A= @@=20-2425,6=20+2448,14=20@@=20pg_dumpall=20-p=205432=20|=20psql=20-d=20= postgres=20-p=205433=0A=20=20=20=20=20=20=20client=20certificate=20= must=20not=20be=20on=20this=20list=0A=20=20=20=20=20=20=0A=20= =0A+=20=20=20=20=20=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20= certificate=20database=0A+=20=20=20=20=20=20= contains=20server=20certificates,=20keys=20and=20revocation=20= lists;=20only=0A+=20=20=20=20=20=20used=20when=20= PostgreSQL=20is=20built=20with=20support=0A+=20= =20=20=20=20=20for=20NSS.=0A+=20=20=20= =20=20=0A+=0A=20=20=20=20=20=0A=20=20=20=20=0A=20=20= =20=0A@@=20-2448,7=20+2479,7=20@@=20pg_dumpall=20-p=205432=20|=20= psql=20-d=20postgres=20-p=205433=0A=20=20=20=0A=20=0A=20=20=20= =0A-=20=20=20Creating=20= Certificates=0A+=20=20=20Creating=20Certificates=20with=20= OpenSSL=0A=20=0A=20=20=20=20=0A=20=20=20=20=20=20To=20= create=20a=20simple=20self-signed=20certificate=20for=20the=20server,=20= valid=20for=20365=0A@@=20-2552,6=20+2583,88=20@@=20openssl=20x509=20-req=20= -in=20server.csr=20-text=20-days=20365=20\=0A=20=20=20=20=0A=20=20= =20=0A=20=0A+=20=20=0A+=20= =20=20NSS=20Certificate=20Databases=0A+=0A+=20=20=20= =0A+=20=20=20=20When=20using=20NSS,=20= all=20certificates=20and=20keys=20must=0A+=20=20=20=20be=20loaded=20into=20= an=20NSS=20certificate=20database.=0A+=20=20=20= =0A+=0A+=20=20=20=0A+=20=20=20=20To=20create=20a=20new=20= NSS=20certificate=20database=20and=0A+=20=20=20= =20load=20the=20certificates=20created=20in=20,=0A+=20=20=20=20use=20the=20= following=20NSS=20commands:=0A= +=0A+certutil=20-d=20"sql:server.db"=20-N=20= --empty-password=0A+certutil=20-d=20"sql:server.db"=20-A=20-n=20= server.crt=20-i=20server.crt=20-t=20"CT,C,C"=0A+certutil=20-d=20= "sql:server.db"=20-A=20-n=20root.crt=20-i=20root.crt=20-t=20"CT,C,C"=0A= +=0A+=20=20=20=20This=20will=20give=20the=20certificate=20= the=20filename=20as=20the=20nickname=20identifier=20in=0A+=20=20=20=20= the=20database=20which=20is=20created=20as=20= server.db.=0A+=20=20=20=0A+=20=20=20=0A= +=20=20=20=20Then=20load=20the=20server=20key,=20which=20require=20= converting=20it=20to=0A+=20=20=20=20PKCS#12=20format=20= using=20the=0A+=20=20=20=20OpenSSL=20tools:=0A= +=0A+openssl=20pkcs12=20-export=20-out=20server.pfx=20= -inkey=20server.key=20-in=20server.crt=20\=0A+=20=20-certfile=20root.crt=20= -passout=20pass:=0A+pk12util=20-i=20server.pfx=20-d=20server.db=20-W=20= ''=0A+=0A+=20=20=20=0A+=20=20=20=0A+=20=20=20= =20Finally=20a=20certificate=20revocation=20list=20can=20be=20loaded=20= with=20the=20following=0A+=20=20=20=20commands:=0A+=0A= +crlutil=20-I=20-i=20server.crl=20-d=20server.db=20-B=0A= +=0A+=20=20=20=0A+=20=20=0A+=0A+=20=20= =0A+=20=20=20= Creating=20Certificates=20with=20NSS=0A+=0A+=20=20=20= =0A+=20=20=20=20To=20create=20a=20simple=20self-signed=20CA=20and=20= certificate=20for=20the=20server,=20use=20the=0A+=20=20=20=20following=20= NSS=20commands.=20Replace=0A+=20=20=20=20= *.yourdomain.com=20with=20the=20server's=20= host=0A+=20=20=20=20name.=20Remove=20= --empty-password=20in=20order=20to=20set=0A+=20= =20=20=20a=20password=20protecting=20the=20databases.=20The=20password=20= can=20be=20passed=20to=0A+=20=20=20=20certutil=20= with=20the=20-f=20parameter.=0A+=20=20=20=20First=20= create=20a=20self-signed=20CA.=20To=20use=20a=20different=20certificate=20= validity=0A+=20=20=20=20time=20than=20the=20default,=20use=20= -v=20to=20specify=20the=0A+=20=20=20=20number=20= of=20months=20of=20validity.=0A+=0A+mkdir=20root_ca.db=0A= +certutil=20-N=20-d=20"sql:root_ca.db/"=20--empty-password=0A+certutil=20= -S=20-d=20"sql:root_ca.db/"=20-n=20root_ca=20-s=20= "CN=3Dca.yourdomain.com"=20\=0A+=20=20-x=20-k=20= rsa=20-g=202048=20-m=205432=20-t=20= CTu,CTu,CTu=20\=0A+=20=20--keyUsage=20certSigning=20-2=20--nsCertType=20= sslCA,smimeCA,objectSigningCA=20\=0A+=20=20-Z=20SHA256=0A+certutil=20-L=20= -d=20"sql:root_ca.db/"=20-n=20root_ca=20-a=20>=20root_ca.pem=0A= +=0A+=20=20=20=20Now=20create=20a=20server=20= certificate=20database,=20and=20create=20a=20certificate=20signing=0A+=20= =20=20=20request=20for=20the=20CA.=20Then=20sign=20the=20request=20with=20= the=20already=20created=20CA=20and=0A+=20=20=20=20insert=20the=20= certificate=20chain=20into=20the=20certificate=20database.=0A= +=0A+mkdir=20server_cert.db=0A+certutil=20-N=20-d=20= "sql:server_cert.db/"=20--empty-password=0A+certutil=20-R=20-d=20= "sql:server_cert.db/"=20-s=20"CN=3Ddbhost.yourdomain.com"=20\=0A+=20=20= -o=20server_cert.csr=20-g=202048=20-Z=20SHA256=0A+=0A+certutil=20-C=20-d=20= "sql:root_ca.db/"=20-c=20root_ca=20-i=20server_cert.csr=20\=0A+=20=20-o=20= server_cert.der=20-m=205433=20\=0A+=20=20= --keyUsage=20keyEncipherment,dataEncipherment,digitalSignature=20\=0A+=20= =20--nsCertType=20sslServer=20-Z=20SHA256=0A+=0A+certutil=20-A=20-d=20= "sql:server_cert.db/"=20-n=20root_ca=20-t=20CTu,CTu,CTu=20-a=20-i=20= root_ca.pem=0A+certutil=20-A=20-d=20"sql:server_cert.db/"=20-n=20= server_cert=20-t=20CTu,CTu,CTu=20-i=20server_cert.der=0A= +=0A+=20=20=20=20The=20server=20certificate=20is=20= loaded=20into=20the=20certificate=20database=20as=20well=20as=0A+=20=20=20= =20the=20CA=20certificate=20in=20order=20to=20provide=20the=20chain=20of=20= certificates.=0A+=20=20=0A+=0A=20=20=0A=20=0A=20=20= =0A--=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2 Content-Disposition: attachment; filename=v23-0004-NSS-pg_strong_random-support.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v23-0004-NSS-pg_strong_random-support.patch" Content-Transfer-Encoding: quoted-printable =46rom=20e985581373ed8f7e925c3721bff5d24b307124ac=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2028=20Oct=202020=2011:24:02=20+0100=0ASubject:=20[PATCH=20= v23=204/8]=20NSS=20pg_strong_random=20support=0A=0A---=0A=20configure=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=201=20+=0A=20= configure.ac=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=201=20+=0A= =20src/include/pg_config.h.in=20=20|=20=203=20+++=0A=20= src/port/pg_strong_random.c=20|=2050=20= ++++++++++++++++++++++++++++++++++++-=0A=204=20files=20changed,=2054=20= insertions(+),=201=20deletion(-)=0A=0Adiff=20--git=20a/configure=20= b/configure=0Aindex=20143726c79c..2b83914289=20100755=0A---=20= a/configure=0A+++=20b/configure=0A@@=20-18422,6=20+18422,7=20@@=20= $as_echo=20"NSS"=20>&6;=20}=0A=20elif=20test=20x"$PORTNAME"=20=3D=20= x"win32"=20;=20then=0A=20=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20Windows=20native"=20>&5=0A=20= $as_echo=20"Windows=20native"=20>&6;=20}=0A+=0A=20else=0A=20=20=20{=20= $as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20/dev/urandom"=20>&5=0A= =20$as_echo=20"/dev/urandom"=20>&6;=20}=0Adiff=20--git=20a/configure.ac=20= b/configure.ac=0Aindex=2059657a6010..6533e10ffd=20100644=0A---=20= a/configure.ac=0A+++=20b/configure.ac=0A@@=20-2197,6=20+2197,7=20@@=20= elif=20test=20x"$with_ssl"=20=3D=20x"nss"=20;=20then=0A=20=20=20= AC_MSG_RESULT([NSS])=0A=20elif=20test=20x"$PORTNAME"=20=3D=20x"win32"=20= ;=20then=0A=20=20=20AC_MSG_RESULT([Windows=20native])=0A+=0A=20else=0A=20= =20=20AC_MSG_RESULT([/dev/urandom])=0A=20=20=20= AC_CHECK_FILE([/dev/urandom],=20[],=20[])=0Adiff=20--git=20= a/src/include/pg_config.h.in=20b/src/include/pg_config.h.in=0Aindex=20= 8856a33590..fa5a977617=20100644=0A---=20a/src/include/pg_config.h.in=0A= +++=20b/src/include/pg_config.h.in=0A@@=20-908,6=20+908,9=20@@=0A=20/*=20= Define=20to=20build=20with=20NSS=20support=20(--with-ssl=3Dnss)=20*/=0A=20= #undef=20USE_NSS=0A=20=0A+/*=20Define=20to=20use=20NSS=20for=20random=20= number=20generation=20*/=0A+#undef=20USE_NSS_RANDOM=0A+=0A=20/*=20Define=20= to=201=20to=20use=20software=20CRC-32C=20implementation=20= (slicing-by-8).=20*/=0A=20#undef=20USE_SLICING_BY_8_CRC32C=0A=20=0Adiff=20= --git=20a/src/port/pg_strong_random.c=20b/src/port/pg_strong_random.c=0A= index=2007f24c0089..40de237628=20100644=0A---=20= a/src/port/pg_strong_random.c=0A+++=20b/src/port/pg_strong_random.c=0A@@=20= -137,7=20+137,55=20@@=20pg_strong_random(void=20*buf,=20size_t=20len)=0A=20= =09return=20false;=0A=20}=0A=20=0A-#else=09=09=09=09=09=09=09/*=20not=20= USE_OPENSSL=20or=20WIN32=20*/=0A+#elif=20defined(USE_NSS)=0A+=0A+#define=20= pg_BITS_PER_BYTE=20BITS_PER_BYTE=0A+#undef=20BITS_PER_BYTE=0A+#define=20= NO_NSPR_10_SUPPORT=0A+#include=20=0A+#include=20= =0A+#if=20defined(BITS_PER_BYTE)=0A+#if=20BITS_PER_BYTE=20= !=3D=20pg_BITS_PER_BYTE=0A+#error=20"incompatible=20byte=20widths=20= between=20NSPR=20and=20postgres"=0A+#endif=0A+#else=0A+#define=20= BITS_PER_BYTE=20pg_BITS_PER_BYTE=0A+#endif=0A+#undef=20pg_BITS_PER_BYTE=0A= +=0A+void=0A+pg_strong_random_init(void)=0A+{=0A+=09/*=20No=20= initialization=20needed=20on=20NSS=20*/=0A+}=0A+=0A+bool=0A= +pg_strong_random(void=20*buf,=20size_t=20len)=0A+{=0A+=09= NSSInitParameters=20params;=0A+=09NSSInitContext=20*nss_context;=0A+=09= SECStatus=09status;=0A+=0A+=09memset(¶ms,=200,=20sizeof(params));=0A= +=09params.length=20=3D=20sizeof(params);=0A+=09nss_context=20=3D=20= NSS_InitContext("",=20"",=20"",=20"",=20¶ms,=0A+=09=09=09=09=09=09=09= =09=20=20NSS_INIT_READONLY=20|=20NSS_INIT_NOCERTDB=20|=0A+=09=09=09=09=09= =09=09=09=20=20NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A+=09=09=09= =09=09=09=09=09=20=20NSS_INIT_NOROOTINIT=20|=20NSS_INIT_PK11RELOAD);=0A+=0A= +=09if=20(!nss_context)=0A+=09=09return=20false;=0A+=0A+=09status=20=3D=20= PK11_GenerateRandom(buf,=20len);=0A+=09NSS_ShutdownContext(nss_context);=0A= +=0A+=09if=20(status=20=3D=3D=20SECSuccess)=0A+=09=09return=20true;=0A+=0A= +=09return=20false;=0A+}=0A+=0A+#else=09=09=09=09=09=09=09/*=20not=20= USE_OPENSSL,=20USE_NSS=20or=20WIN32=20*/=0A=20=0A=20/*=0A=20=20*=20= Without=20OpenSSL=20or=20Win32=20support,=20just=20read=20/dev/urandom=20= ourselves.=0A--=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2 Content-Disposition: attachment; filename=v23-0003-NSS-Testharness-updates.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v23-0003-NSS-Testharness-updates.patch" Content-Transfer-Encoding: quoted-printable =46rom=20411ac43db0dff3c2e138afc8cb18828992000810=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2028=20Oct=202020=2011:22:26=20+0100=0ASubject:=20[PATCH=20= v23=203/8]=20NSS=20Testharness=20updates=0A=0ATODO:=0A=09*=20Generate=20= certificate/keys=20with=20NSS=20tooling=20for=20NSS=20specific=20test=0A=09= *=20Add=20test=20for=20certificate=20with=20embedded=20nulls=0A=09*=20= Fix=20SCRAM=20tests=20when=20channel=20binding=20works=0A---=0A=20= src/test/ssl/Makefile=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20|=20233=20++++++++++++=0A=20= src/test/ssl/t/001_ssltests.pl=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20|=20346=20+++++++++++-------=0A=20src/test/ssl/t/002_scram.pl=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=2097=20+++--=0A=20= src/test/ssl/t/SSL/Backend/NSS.pm=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=2073=20++++=0A=20src/test/ssl/t/SSL/Backend/OpenSSL.pm=20=20=20=20=20= =20=20=20=20|=20103=20++++++=0A=20.../ssl/t/{SSLServer.pm=20=3D>=20= SSL/Server.pm}=20=20=20=20=20|=20=2080=20+++-=0A=206=20files=20changed,=20= 743=20insertions(+),=20189=20deletions(-)=0A=20create=20mode=20100644=20= src/test/ssl/t/SSL/Backend/NSS.pm=0A=20create=20mode=20100644=20= src/test/ssl/t/SSL/Backend/OpenSSL.pm=0A=20rename=20= src/test/ssl/t/{SSLServer.pm=20=3D>=20SSL/Server.pm}=20(78%)=0A=0Adiff=20= --git=20a/src/test/ssl/Makefile=20b/src/test/ssl/Makefile=0Aindex=20= d545382eea..d275c89672=20100644=0A---=20a/src/test/ssl/Makefile=0A+++=20= b/src/test/ssl/Makefile=0A@@=20-30,6=20+30,35=20@@=20SSLFILES=20:=3D=20= $(CERTIFICATES:%=3Dssl/%.key)=20$(CERTIFICATES:%=3Dssl/%.crt)=20\=0A=20=09= ssl/client+client_ca.crt=20ssl/client-der.key=20\=0A=20=09= ssl/client-encrypted-pem.key=20ssl/client-encrypted-der.key=0A=20=0A+#=20= Even=20though=20we=20in=20practice=20could=20get=20away=20with=20far=20= fewer=20NSS=20databases,=20they=0A+#=20are=20generated=20to=20mimic=20= the=20setup=20for=20the=20OpenSSL=20tests=20in=20order=20to=20ensure=0A= +#=20we=20isolate=20the=20same=20behavior=20between=20the=20backends.=20= The=20database=20name=20should=0A+#=20contain=20the=20files=20included=20= for=20easier=20test=20suite=20code=20reading.=0A+NSSFILES=20:=3D=20= ssl/nss/client_ca.crt.db=20\=0A+=09ssl/nss/server_ca.crt.db=20\=0A+=09= ssl/nss/root+server_ca.crt.db=20\=0A+=09ssl/nss/root+client_ca.crt.db=20= \=0A+=09ssl/nss/client.crt__client.key.db=20\=0A+=09= ssl/nss/client-revoked.crt__client-revoked.key.db=20\=0A+=09= ssl/nss/server-cn-only.crt__server-password.key.db=20\=0A+=09= ssl/nss/server-cn-only.crt__server-cn-only.key.db=20\=0A+=09= ssl/nss/root.crl=20\=0A+=09ssl/nss/server.crl=20\=0A+=09= ssl/nss/client.crl=20\=0A+=09= ssl/nss/server-multiple-alt-names.crt__server-multiple-alt-names.key.db=20= \=0A+=09= ssl/nss/server-single-alt-name.crt__server-single-alt-name.key.db=20\=0A= +=09ssl/nss/server-cn-and-alt-names.crt__server-cn-and-alt-names.key.db=20= \=0A+=09ssl/nss/server-no-names.crt__server-no-names.key.db=20\=0A+=09= ssl/nss/server-revoked.crt__server-revoked.key.db=20\=0A+=09= ssl/nss/root+client.crl=20\=0A+=09= ssl/nss/client+client_ca.crt__client.key.db=20\=0A+=09= ssl/nss/client.crt__client-encrypted-pem.key.db=20\=0A+=09= ssl/nss/root+server_ca.crt__server.crl.db=20\=0A+=09= ssl/nss/root+server_ca.crt__root+server.crl.db=20\=0A+=09= ssl/nss/native_ca-root.db=20\=0A+=09ssl/nss/native_server-root.db=20\=0A= +=09ssl/nss/native_client-root.db=0A+=0A=20#=20This=20target=20= re-generates=20all=20the=20key=20and=20certificate=20files.=20Usually=20= we=20just=0A=20#=20use=20the=20ones=20that=20are=20committed=20to=20the=20= tree=20without=20rebuilding=20them.=0A=20#=0A@@=20-37,6=20+66,10=20@@=20= SSLFILES=20:=3D=20$(CERTIFICATES:%=3Dssl/%.key)=20= $(CERTIFICATES:%=3Dssl/%.crt)=20\=0A=20#=0A=20sslfiles:=20$(SSLFILES)=0A=20= =0A+#=20Generate=20NSS=20certificate=20databases=20corresponding=20to=20= the=20OpenSSL=20certificates.=0A+#=20This=20target=20will=20fail=20= unless=20preceded=20by=20nssfiles-clean.=0A+nssfiles:=20$(NSSFILES)=0A+=0A= =20#=20OpenSSL=20requires=20a=20directory=20to=20put=20all=20generated=20= certificates=20in.=20We=20don't=0A=20#=20use=20this=20for=20anything,=20= but=20we=20need=20a=20location.=0A=20ssl/new_certs_dir:=0A@@=20-64,6=20= +97,24=20@@=20ssl/%_ca.crt:=20ssl/%_ca.key=20%_ca.config=20= ssl/root_ca.crt=20ssl/new_certs_dir=0A=20=09rm=20ssl/temp_ca.crt=20= ssl/temp_ca_signed.crt=0A=20=09echo=20"01"=20>=20ssl/$*_ca.srl=0A=20=0A= +ssl/nss/%_ca.crt.db:=20ssl/%_ca.crt=0A+=09$(MKDIR_P)=20$@=0A+=09= certutil=20-d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20$*_ca.crt=20-i=20ssl/$*_ca.crt=20-t=20"CT,C,C"=0A+=0A= +ssl/nss/root+server_ca.crt__server.crl.db:=20ssl/root+server_ca.crt=20= ssl/nss/server.crl=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20"sql:$@"=20= -N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= ssl/root+server_ca.crt=20-i=20ssl/root+server_ca.crt=20-t=20"CT,C,C"=0A+=09= crlutil=20-I=20-i=20ssl/nss/server.crl=20-d=20$@=20-B=0A+=0A= +ssl/nss/root+server_ca.crt__root+server.crl.db:=20= ssl/root+server_ca.crt=20ssl/nss/root.crl=20ssl/nss/server.crl=0A+=09= $(MKDIR_P)=20$@=0A+=09certutil=20-d=20"sql:$@"=20-N=20--empty-password=0A= +=09certutil=20-d=20"sql:$@"=20-A=20-n=20ssl/root+server_ca.crt=20-i=20= ssl/root+server_ca.crt=20-t=20"CT,C,C"=0A+=09crlutil=20-I=20-i=20= ssl/nss/root.crl=20-d=20$@=20-B=0A+=09crlutil=20-I=20-i=20= ssl/nss/server.crl=20-d=20$@=20-B=0A+=0A=20#=20Server=20certificates,=20= signed=20by=20server=20CA:=0A=20ssl/server-%.crt:=20ssl/server-%.key=20= ssl/server_ca.crt=20server-%.config=0A=20=09openssl=20req=20-new=20-key=20= ssl/server-$*.key=20-out=20ssl/server-$*.csr=20-config=20= server-$*.config=0A@@=20-77,6=20+128,78=20@@=20ssl/server-ss.crt:=20= ssl/server-cn-only.key=20ssl/server-cn-only.crt=20server-cn-only.=0A=20=09= openssl=20x509=20-req=20-days=2010000=20-in=20ssl/server-ss.csr=20= -signkey=20ssl/server-cn-only.key=20-out=20ssl/server-ss.crt=20=20= -extensions=20v3_req=20-extfile=20server-cn-only.config=0A=20=09rm=20= ssl/server-ss.csr=0A=20=0A+#=20pk12util=20won't=20preserve=20the=20= password=20when=20importing=20the=20password=20protected=0A+#=20key,=20= the=20password=20must=20be=20set=20on=20the=20database=20*before*=20= importing=20it=20as=20the=0A+#=20password=20in=20the=20pkcs12=20envelope=20= will=20be=20dropped.=0A= +ssl/nss/server-cn-only.crt__server-password.key.db:=20= ssl/server-cn-only.crt=0A+=09$(MKDIR_P)=20$@=0A+=09echo=20"secret1"=20>=20= password.txt=0A+=09certutil=20-d=20"sql:$@"=20-N=20-f=20password.txt=0A+=09= certutil=20-d=20"sql:$@"=20-A=20-n=20ssl/server-cn-only.crt=20-i=20= ssl/server-cn-only.crt=20-t=20"CT,C,C"=20-f=20password.txt=0A+=09= certutil=20-d=20"sql:$@"=20-A=20-n=20server_ca.crt=20-i=20= ssl/server_ca.crt=20-t=20"CT,C,C"=20-f=20password.txt=0A+=09certutil=20= -d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20ssl/root_ca.crt=20-t=20= "CT,C,C"=20-f=20password.txt=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20"CT,C,C"=20-f=20= password.txt=0A+=09openssl=20pkcs12=20-export=20-out=20= ssl/nss/server-password.pfx=20-inkey=20ssl/server-password.key=20-in=20= ssl/server-cn-only.crt=20-certfile=20ssl/server_ca.crt=20-passin=20= 'pass:secret1'=20-passout=20'pass:secret1'=0A+=09pk12util=20-i=20= ssl/nss/server-password.pfx=20-d=20"sql:$@"=20-W=20'secret1'=20-K=20= 'secret1'=0A+=0A+ssl/nss/server-cn-only.crt__server-cn-only.key.db:=20= ssl/server-cn-only.crt=20ssl/server-cn-only.key=0A+=09$(MKDIR_P)=20$@=0A= +=09certutil=20-d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20ssl/server-cn-only.crt=20-i=20= ssl/server-cn-only.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20= -A=20-n=20server_ca.crt=20-i=20ssl/server_ca.crt=20-t=20"CT,C,C"=0A+=09= openssl=20pkcs12=20-export=20-out=20ssl/nss/server-cn-only.pfx=20-inkey=20= ssl/server-cn-only.key=20-in=20ssl/server-cn-only.crt=20-certfile=20= ssl/server_ca.crt=20-passout=20pass:=0A+=09pk12util=20-i=20= ssl/nss/server-cn-only.pfx=20-d=20"sql:$@"=20-W=20''=0A+=0A= +ssl/nss/server-multiple-alt-names.crt__server-multiple-alt-names.key.db:=20= ssl/server-multiple-alt-names.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20= -d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20= -A=20-n=20ssl/server-multiple-alt-names.crt=20-i=20= ssl/server-multiple-alt-names.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20server_ca.crt=20-i=20ssl/server_ca.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20= ssl/root_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20= pkcs12=20-export=20-out=20ssl/nss/server-multiple-alt-names.pfx=20-inkey=20= ssl/server-multiple-alt-names.key=20-in=20= ssl/server-multiple-alt-names.crt=20-certfile=20= ssl/server-multiple-alt-names.crt=20-passout=20pass:=0A+=09pk12util=20-i=20= ssl/nss/server-multiple-alt-names.pfx=20-d=20"sql:$@"=20-W=20''=0A+=0A= +ssl/nss/server-single-alt-name.crt__server-single-alt-name.key.db:=20= ssl/server-single-alt-name.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/server-single-alt-name.crt=20-i=20= ssl/server-single-alt-name.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20server_ca.crt=20-i=20ssl/server_ca.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20= ssl/root_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20= pkcs12=20-export=20-out=20ssl/nss/server-single-alt-name.pfx=20-inkey=20= ssl/server-single-alt-name.key=20-in=20ssl/server-single-alt-name.crt=20= -certfile=20ssl/server-single-alt-name.crt=20-passout=20pass:=0A+=09= pk12util=20-i=20ssl/nss/server-single-alt-name.pfx=20-d=20"sql:$@"=20-W=20= ''=0A+=0A= +ssl/nss/server-cn-and-alt-names.crt__server-cn-and-alt-names.key.db:=20= ssl/server-cn-and-alt-names.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20= -d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20= -A=20-n=20ssl/server-cn-and-alt-names.crt=20-i=20= ssl/server-cn-and-alt-names.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20server_ca.crt=20-i=20ssl/server_ca.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20= ssl/root_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20= pkcs12=20-export=20-out=20ssl/nss/server-cn-and-alt-names.pfx=20-inkey=20= ssl/server-cn-and-alt-names.key=20-in=20ssl/server-cn-and-alt-names.crt=20= -certfile=20ssl/server-cn-and-alt-names.crt=20-passout=20pass:=0A+=09= pk12util=20-i=20ssl/nss/server-cn-and-alt-names.pfx=20-d=20$@=20-W=20''=0A= +=0A+ssl/nss/server-no-names.crt__server-no-names.key.db:=20= ssl/server-no-names.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/server-no-names.crt=20-i=20ssl/server-no-names.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20server_ca.crt=20-i=20= ssl/server_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20root_ca.crt=20-i=20ssl/root_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20= -d=20"sql:$@"=20-A=20-n=20client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20= "CT,C,C"=0A+=09openssl=20pkcs12=20-export=20-out=20= ssl/nss/server-no-names.pfx=20-inkey=20ssl/server-no-names.key=20-in=20= ssl/server-no-names.crt=20-certfile=20ssl/server-no-names.crt=20-passout=20= pass:=0A+=09pk12util=20-i=20ssl/nss/server-no-names.pfx=20-d=20"sql:$@"=20= -W=20''=0A+=0A+ssl/nss/server-revoked.crt__server-revoked.key.db:=20= ssl/server-revoked.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/server-revoked.crt=20-i=20ssl/server-revoked.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20server_ca.crt=20-i=20= ssl/server_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20root_ca.crt=20-i=20ssl/root_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20= -d=20"sql:$@"=20-A=20-n=20client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20= "CT,C,C"=0A+=09openssl=20pkcs12=20-export=20-out=20= ssl/nss/server-revoked.pfx=20-inkey=20ssl/server-revoked.key=20-in=20= ssl/server-revoked.crt=20-certfile=20ssl/server-revoked.crt=20-passout=20= pass:=0A+=09pk12util=20-i=20ssl/nss/server-revoked.pfx=20-d=20"sql:$@"=20= -W=20''=0A+=0A=20#=20Password-protected=20version=20of=20= server-cn-only.key=0A=20ssl/server-password.key:=20= ssl/server-cn-only.key=0A=20=09openssl=20rsa=20-aes256=20-in=20$<=20-out=20= $@=20-passout=20'pass:secret1'=0A@@=20-88,6=20+211,27=20@@=20= ssl/client.crt:=20ssl/client.key=20ssl/client_ca.crt=0A=20=09openssl=20= x509=20-in=20ssl/temp.crt=20-out=20ssl/client.crt=20#=20to=20keep=20just=20= the=20PEM=20cert=0A=20=09rm=20ssl/client.csr=20ssl/temp.crt=0A=20=0A+#=20= Client=20certificate,=20signed=20by=20client=20CA=0A= +ssl/nss/client.crt__client.key.db:=20ssl/client.crt=0A+=09$(MKDIR_P)=20= $@=0A+=09certutil=20-d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20= -d=20"sql:$@"=20-A=20-n=20ssl/client.crt=20-i=20ssl/client.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20client_ca.crt=20-i=20= ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20root+client_ca.crt=20-i=20ssl/root+client_ca.crt=20-t=20"CT,C,C"=0A= +=09openssl=20pkcs12=20-export=20-out=20ssl/nss/client.pfx=20-inkey=20= ssl/client.key=20-in=20ssl/client.crt=20-certfile=20ssl/client_ca.crt=20= -passout=20pass:=0A+=09pk12util=20-i=20ssl/nss/client.pfx=20-d=20= "sql:$@"=20-W=20''=0A+=0A+#=20Client=20certificate=20with=20encrypted=20= key,=20signed=20by=20client=20CA=0A= +ssl/nss/client.crt__client-encrypted-pem.key.db:=20ssl/client.crt=0A+=09= $(MKDIR_P)=20$@=0A+=09echo=20'dUmmyP^#+'=20>=20$@.pass=0A+=09certutil=20= -d=20"sql:$@"=20-N=20-f=20$@.pass=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -f=20$@.pass=20-n=20ssl/client.crt=20-i=20ssl/client.crt=20-t=20"CT,C,C"=0A= +=09certutil=20-d=20"sql:$@"=20-A=20-f=20$@.pass=20-n=20client_ca.crt=20= -i=20ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20= -A=20-f=20$@.pass=20-n=20root+server_ca.crt=20-i=20= ssl/root+server_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20pkcs12=20-export=20= -out=20ssl/nss/client-encrypted-pem.pfx=20-inkey=20= ssl/client-encrypted-pem.key=20-in=20ssl/client.crt=20-certfile=20= ssl/client_ca.crt=20-passin=20pass:'dUmmyP^#+'=20-passout=20= pass:'dUmmyP^#+'=0A+=09pk12util=20-i=20ssl/nss/client-encrypted-pem.pfx=20= -d=20"sql:$@"=20-W=20'dUmmyP^#+'=20-k=20$@.pass=0A+=0A=20#=20Another=20= client=20certificate,=20signed=20by=20the=20client=20CA.=20This=20one=20= is=20revoked.=0A=20ssl/client-revoked.crt:=20ssl/client-revoked.key=20= ssl/client_ca.crt=20client.config=0A=20=09openssl=20req=20-new=20-key=20= ssl/client-revoked.key=20-out=20ssl/client-revoked.csr=20-config=20= client.config=0A@@=20-95,6=20+239,14=20@@=20ssl/client-revoked.crt:=20= ssl/client-revoked.key=20ssl/client_ca.crt=20client.config=0A=20=09= openssl=20x509=20-in=20ssl/temp.crt=20-out=20ssl/client-revoked.crt=20#=20= to=20keep=20just=20the=20PEM=20cert=0A=20=09rm=20ssl/client-revoked.csr=20= ssl/temp.crt=0A=20=0A+ssl/nss/client-revoked.crt__client-revoked.key.db:=20= ssl/client-revoked.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/client-revoked.crt=20-i=20ssl/client-revoked.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20client_ca.crt=20-i=20= ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20pkcs12=20-export=20= -out=20ssl/nss/client-revoked.pfx=20-inkey=20ssl/client-revoked.key=20= -in=20ssl/client-revoked.crt=20-certfile=20ssl/client_ca.crt=20-passout=20= pass:=0A+=09pk12util=20-i=20ssl/nss/client-revoked.pfx=20-d=20"sql:$@"=20= -W=20''=0A+=0A=20#=20Convert=20the=20key=20to=20DER,=20to=20test=20our=20= behaviour=20there=20too=0A=20ssl/client-der.key:=20ssl/client.key=0A=20=09= openssl=20rsa=20-in=20ssl/client.key=20-outform=20DER=20-out=20= ssl/client-der.key=0A@@=20-127,19=20+279,40=20@@=20= ssl/root+client_ca.crt:=20ssl/root_ca.crt=20ssl/client_ca.crt=0A=20= ssl/client+client_ca.crt:=20ssl/client.crt=20ssl/client_ca.crt=0A=20=09= cat=20$^=20>=20$@=0A=20=0A+#=20Client=20certificate,=20signed=20by=20= client=20CA=0A+ssl/nss/client+client_ca.crt__client.key.db:=20= ssl/client+client_ca.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/client+client_ca.crt=20-i=20ssl/client+client_ca.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= ssl/root+server_ca.crt=20-i=20ssl/root+server_ca.crt=20-t=20"CT,C,C"=0A+=09= openssl=20pkcs12=20-export=20-out=20ssl/nss/client.pfx=20-inkey=20= ssl/client.key=20-in=20ssl/client.crt=20-certfile=20ssl/client_ca.crt=20= -passout=20pass:=0A+=09pk12util=20-i=20ssl/nss/client.pfx=20-d=20= "sql:$@"=20-W=20''=0A+=0A=20####=20CRLs=0A=20=0A=20ssl/client.crl:=20= ssl/client-revoked.crt=0A=20=09openssl=20ca=20-config=20cas.config=20= -name=20client_ca=20-revoke=20ssl/client-revoked.crt=0A=20=09openssl=20= ca=20-config=20cas.config=20-name=20client_ca=20-gencrl=20-out=20= ssl/client.crl=0A=20=0A+ssl/nss/client.crl:=20ssl/client.crl=0A+=09= openssl=20crl=20-in=20$^=20-outform=20der=20-out=20$@=0A+=0A=20= ssl/server.crl:=20ssl/server-revoked.crt=0A=20=09openssl=20ca=20-config=20= cas.config=20-name=20server_ca=20-revoke=20ssl/server-revoked.crt=0A=20=09= openssl=20ca=20-config=20cas.config=20-name=20server_ca=20-gencrl=20-out=20= ssl/server.crl=0A=20=0A+ssl/nss/server.crl:=20ssl/server.crl=0A+=09= openssl=20crl=20-in=20$^=20-outform=20der=20-out=20$@=0A+=0A=20= ssl/root.crl:=20ssl/root_ca.crt=0A=20=09openssl=20ca=20-config=20= cas.config=20-name=20root_ca=20-gencrl=20-out=20ssl/root.crl=0A=20=0A= +ssl/nss/root.crl:=20ssl/root.crl=0A+=09openssl=20crl=20-in=20$^=20= -outform=20der=20-out=20$@=0A+=0A+ssl/nss/root+client.crl:=20= ssl/root+client.crl=0A+=09openssl=20crl=20-in=20$^=20-outform=20der=20= -out=20$@=0A+=0A=20#=20If=20a=20CRL=20is=20used,=20OpenSSL=20requires=20= a=20CRL=20file=20for=20*all*=20the=20CAs=20in=20the=0A=20#=20chain,=20= even=20if=20some=20of=20them=20are=20empty.=0A=20ssl/root+server.crl:=20= ssl/root.crl=20ssl/server.crl=0A@@=20-147,13=20+320,73=20@@=20= ssl/root+server.crl:=20ssl/root.crl=20ssl/server.crl=0A=20= ssl/root+client.crl:=20ssl/root.crl=20ssl/client.crl=0A=20=09cat=20$^=20= >=20$@=0A=20=0A+####=20NSS=20specific=20certificates=20and=20keys=0A+=0A= +#NSSFILES2=20:=3D=20ssl/nss/native_ca-root.db=20\=0A+#=09= ssl/nss/native_server-root.db=20\=0A+#=09ssl/nss/native_client-root.db=0A= +=0A+#nssfiles2:=20$(NSSFILES2)=0A+=0A+ssl/nss/native_ca-%.db:=0A+=09= $(MKDIR_P)=20ssl/nss/native_ca-$*.db=0A+=09certutil=20-N=20-d=20= "sql:ssl/nss/native_ca-$*.db/"=20--empty-password=0A+=09echo=20y=20>=20= nss_ca_params.txt=0A+=09echo=2010=20>>=20nss_ca_params.txt=0A+=09echo=20= y=20>>=20nss_ca_params.txt=0A+=09cat=20nss_ca_params.txt=20|=20certutil=20= -S=20-d=20"sql:ssl/nss/native_ca-$*.db/"=20-n=20ca-$*=20\=0A+=09-s=20= "CN=3DTest=20CA=20for=20PostgreSQL=20SSL=20regression=20= tests,OU=3DPostgreSQL=20test=20suite"=20\=0A+=09-x=20-k=20rsa=20-g=20= 2048=20-m=205432=20-t=20CTu,CTu,CTu=20\=0A+=09--keyUsage=20certSigning=20= -2=20--nsCertType=20sslCA,smimeCA,objectSigningCA=20\=0A+=09-z=20= Makefile=20-Z=20SHA256=0A+=09rm=20nss_ca_params.txt=0A+=0A= +ssl/nss/native_ca-%.pem:=20ssl/nss/native_ca-%.db=0A+=09certutil=20-L=20= -d=20"sql:ssl/nss/native_ca-$*.db/"=20-n=20ca-$*=20-a=20>=20= ssl/nss/native_ca-$*.pem=0A+=0A+#=20Create=20and=20sign=20a=20server=20= certificate=0A+ssl/nss/native_server-%.db:=20ssl/nss/native_ca-%.pem=0A+=09= $(MKDIR_P)=20ssl/nss/native_server-$*.db=0A+=09certutil=20-N=20-d=20= "sql:ssl/nss/native_server-$*.db/"=20--empty-password=0A+=09certutil=20= -R=20-d=20"sql:ssl/nss/native_server-$*.db/"=20\=0A+=09=09-s=20= "CN=3Dcommon-name.pg-ssltest.test,OU=3DPostgreSQL=20test=20suite"=20\=0A= +=09=09-o=20ssl/nss/native_server-$*.csr=20-g=202048=20-Z=20SHA256=20-z=20= Makefile=0A+=09echo=201=20>=20nss_server_params.txt=0A+=09echo=209=20>>=20= nss_server_params.txt=0A+=09cat=20nss_server_params.txt=20|=20certutil=20= -C=20-d=20"sql:ssl/nss/native_ca-$*.db/"=20-c=20ca-root=20-i=20= ssl/nss/native_server-$*.csr=20\=0A+=09=09-o=20= ssl/nss/native_server_$*.der=20-m=205433=20--keyUsage=20= dataEncipherment,digitalSignature,keyEncipherment=20\=0A+=09=09= --nsCertType=20sslServer=20--certVersion=201=20-Z=20SHA256=0A+=09= certutil=20-A=20-d=20"sql:ssl/nss/native_server-$*.db/"=20-n=20ca-$*=20= -t=20CTu,CTu,CTu=20-a=20-i=20ssl/nss/native_ca-$*.pem=0A+=09certutil=20= -A=20-d=20"sql:ssl/nss/native_server-$*.db/"=20-n=20= ssl/native_server-$*.crt=20-t=20CTu,CTu,CTu=20-i=20= ssl/nss/native_server_$*.der=0A+=09rm=20nss_server_params.txt=0A+=0A+#=20= Create=20and=20sign=20a=20client=20certificate=0A= +ssl/nss/native_client-%.db:=20ssl/nss/native_ca-%.pem=0A+=09$(MKDIR_P)=20= ssl/nss/native_client-$*.db=0A+=09certutil=20-N=20-d=20= "sql:ssl/nss/native_client-$*.db/"=20--empty-password=0A+=09certutil=20= -R=20-d=20"sql:ssl/nss/native_client-$*.db/"=20-s=20= "CN=3Dssltestuser,OU=3DPostgreSQL=20test=20suite"=20\=0A+=09=09-o=20= ssl/nss/native_client-$*.csr=20-g=202048=20-Z=20SHA256=20-z=20Makefile=0A= +=09certutil=20-C=20-d=20"sql:ssl/nss/native_ca-$*.db/"=20-c=20ca-$*=20= -i=20ssl/nss/native_client-$*.csr=20-o=20ssl/nss/native_client-$*.der=20= \=0A+=09=09-m=205434=20--keyUsage=20= keyEncipherment,dataEncipherment,digitalSignature=20--nsCertType=20= sslClient=20\=0A+=09=09--certVersion=201=20-Z=20SHA256=0A+=09certutil=20= -A=20-d=20"sql:ssl/nss/native_client-$*.db"=20-n=20ca-$*=20-t=20= CTu,CTu,CTu=20-a=20-i=20ssl/nss/native_ca-$*.pem=0A+=09certutil=20-A=20= -d=20"sql:ssl/nss/native_client-$*.db"=20-n=20native_client-$*=20-t=20= CTu,CTu,CTu=20-i=20ssl/nss/native_client-$*.der=0A+=0A+nssfiles2clean:=0A= +=09rm=20-rf=20ssl/nss=0A+=0A=20.PHONY:=20sslfiles-clean=0A=20= sslfiles-clean:=0A=20=09rm=20-f=20$(SSLFILES)=20ssl/client_ca.srl=20= ssl/server_ca.srl=20ssl/client_ca-certindex*=20ssl/server_ca-certindex*=20= ssl/root_ca-certindex*=20ssl/root_ca.srl=20ssl/temp_ca.crt=20= ssl/temp_ca_signed.crt=0A=20=0A+.PHONY:=20nssfiles-clean=0A= +nssfiles-clean:=0A+=09rm=20-rf=20ssl/nss=0A+=0A=20clean=20distclean=20= maintainer-clean:=0A=20=09rm=20-rf=20tmp_check=0A=20=09rm=20-rf=20= ssl/*.old=20ssl/new_certs_dir=20ssl/client*_tmp.key=0A+=09rm=20-rf=20= ssl/nss=0A=20=0A=20#=20Doesn't=20depend=20on=20$(SSLFILES)=20because=20= we=20don't=20rebuild=20them=20by=20default=0A=20check:=0Adiff=20--git=20= a/src/test/ssl/t/001_ssltests.pl=20b/src/test/ssl/t/001_ssltests.pl=0A= index=20fd2727b568..6b8bca2846=20100644=0A---=20= a/src/test/ssl/t/001_ssltests.pl=0A+++=20= b/src/test/ssl/t/001_ssltests.pl=0A@@=20-4,17=20+4,24=20@@=20use=20= PostgresNode;=0A=20use=20TestLib;=0A=20use=20Test::More;=0A=20=0A-use=20= File::Copy;=0A-=0A=20use=20FindBin;=0A=20use=20lib=20$FindBin::RealBin;=0A= =20=0A-use=20SSLServer;=0A+use=20SSL::Server;=0A+=0A+my=20$openssl;=0A= +my=20$nss;=0A=20=0A-if=20($ENV{with_openssl}=20eq=20'yes')=0A+if=20= ($ENV{with_ssl}=20eq=20'openssl')=0A=20{=0A+=09$openssl=20=3D=201;=0A=20=09= plan=20tests=20=3D>=2093;=0A=20}=0A+elsif=20($ENV{with_ssl}=20eq=20= 'nss')=0A+{=0A+=09$nss=20=3D=201;=0A+=09plan=20tests=20=3D>=2099;=0A+}=0A= =20else=0A=20{=0A=20=09plan=20skip_all=20=3D>=20'SSL=20not=20supported=20= by=20this=20build';=0A@@=20-32,32=20+39,6=20@@=20my=20$SERVERHOSTCIDR=20= =3D=20'127.0.0.1/32';=0A=20#=20Allocation=20of=20base=20connection=20= string=20shared=20among=20multiple=20tests.=0A=20my=20$common_connstr;=0A= =20=0A-#=20The=20client's=20private=20key=20must=20not=20be=20= world-readable,=20so=20take=20a=20copy=0A-#=20of=20the=20key=20stored=20= in=20the=20code=20tree=20and=20update=20its=20permissions.=0A-#=0A-#=20= This=20changes=20ssl/client.key=20to=20ssl/client_tmp.key=20etc=20for=20= the=20rest=0A-#=20of=20the=20tests.=0A-my=20@keys=20=3D=20(=0A-=09= "client",=20=20=20=20=20"client-revoked",=0A-=09"client-der",=20= "client-encrypted-pem",=0A-=09"client-encrypted-der");=0A-foreach=20my=20= $key=20(@keys)=0A-{=0A-=09copy("ssl/${key}.key",=20"ssl/${key}_tmp.key")=0A= -=09=20=20or=20die=0A-=09=20=20"couldn't=20copy=20ssl/${key}.key=20to=20= ssl/${key}_tmp.key=20for=20permissions=20change:=20$!";=0A-=09chmod=20= 0600,=20"ssl/${key}_tmp.key"=0A-=09=20=20or=20die=20"failed=20to=20= change=20permissions=20on=20ssl/${key}_tmp.key:=20$!";=0A-}=0A-=0A-#=20= Also=20make=20a=20copy=20of=20that=20explicitly=20world-readable.=20=20= We=20can't=0A-#=20necessarily=20rely=20on=20the=20file=20in=20the=20= source=20tree=20having=20those=0A-#=20permissions.=20=20Add=20it=20to=20= @keys=20to=20include=20it=20in=20the=20final=20clean=0A-#=20up=20phase.=0A= -copy("ssl/client.key",=20"ssl/client_wrongperms_tmp.key");=0A-chmod=20= 0644,=20"ssl/client_wrongperms_tmp.key";=0A-push=20@keys,=20= 'client_wrongperms';=0A-=0A=20####=20Set=20up=20the=20server.=0A=20=0A=20= note=20"setting=20up=20data=20directory";=0A@@=20-72,36=20+53,65=20@@=20= $node->start;=0A=20=0A=20#=20Run=20this=20before=20we=20lock=20down=20= access=20below.=0A=20my=20$result=20=3D=20$node->safe_psql('postgres',=20= "SHOW=20ssl_library");=0A-is($result,=20'OpenSSL',=20'ssl_library=20= parameter');=0A+is($result,=20SSL::Server::ssl_library(),=20'ssl_library=20= parameter');=0A=20=0A=20configure_test_server_for_ssl($node,=20= $SERVERHOSTADDR,=20$SERVERHOSTCIDR,=0A=20=09'trust');=0A=20=0A=20note=20= "testing=20password-protected=20keys";=0A=20=0A-open=20my=20$sslconf,=20= '>',=20$node->data_dir=20.=20"/sslconfig.conf";=0A-print=20$sslconf=20= "ssl=3Don\n";=0A-print=20$sslconf=20= "ssl_cert_file=3D'server-cn-only.crt'\n";=0A-print=20$sslconf=20= "ssl_key_file=3D'server-password.key'\n";=0A-print=20$sslconf=20= "ssl_passphrase_command=3D'echo=20wrongpassword'\n";=0A-close=20= $sslconf;=0A+#=20Since=20the=20passphrase=20callbacks=20operate=20at=20= different=20stages=20in=20OpenSSL=20and=0A+#=20NSS=20we=20have=20two=20= separate=20blocks=20for=20them.=0A+SKIP:=0A+{=0A+=09skip=20"Certificate=20= passphrases=20aren't=20checked=20on=20server=20restart=20in=20NSS",=202=0A= +=09=20=20if=20($nss);=0A+=0A+=09set_server_cert($node,=20= 'server-cn-only',=20'root+client_ca',=0A+=09=09=09=09=09=20=20=20= 'server-password',=20'echo=20wrongpassword');=0A+=09command_fails(=0A+=09= =09[=20'pg_ctl',=20'-D',=20$node->data_dir,=20'-l',=20$node->logfile,=20= 'restart'=20],=0A+=09=09'restart=20fails=20with=20password-protected=20= key=20file=20with=20wrong=20password');=0A+=09$node->_update_pid(0);=0A+=0A= +=09set_server_cert($node,=20'server-cn-only',=20'root+client_ca',=0A+=09= =09=09=09=09'server-password',=20'echo=20secret1');=0A+=09command_ok(=0A= +=09=09[=20'pg_ctl',=20'-D',=20$node->data_dir,=20'-l',=20= $node->logfile,=20'restart'=20],=0A+=09=09'restart=20succeeds=20with=20= password-protected=20key=20file');=0A+=09$node->_update_pid(1);=0A+}=0A=20= =0A-command_fails(=0A-=09[=20'pg_ctl',=20'-D',=20$node->data_dir,=20= '-l',=20$node->logfile,=20'restart'=20],=0A-=09'restart=20fails=20with=20= password-protected=20key=20file=20with=20wrong=20password');=0A= -$node->_update_pid(0);=0A+SKIP:=0A+{=0A+=09skip=20"Certificate=20= passphrases=20are=20checked=20on=20connection=20in=20NSS",=205=0A+=09=20=20= if=20($openssl);=0A=20=0A-open=20$sslconf,=20'>',=20$node->data_dir=20.=20= "/sslconfig.conf";=0A-print=20$sslconf=20"ssl=3Don\n";=0A-print=20= $sslconf=20"ssl_cert_file=3D'server-cn-only.crt'\n";=0A-print=20$sslconf=20= "ssl_key_file=3D'server-password.key'\n";=0A-print=20$sslconf=20= "ssl_passphrase_command=3D'echo=20secret1'\n";=0A-close=20$sslconf;=0A+=09= set_server_cert($node,=20'server-cn-only',=20'root+client_ca',=0A+=09=09=09= =09=09=20=20=20'server-password',=20'echo=20wrongpassword');=0A+=09= command_ok(=0A+=09=09[=20'pg_ctl',=20'-D',=20$node->data_dir,=20'-l',=20= $node->logfile,=20'restart'=20],=0A+=09=09'restart=20fails=20with=20= password-protected=20key=20file=20with=20wrong=20password');=0A+=09= $node->_update_pid(1);=0A=20=0A-command_ok(=0A-=09[=20'pg_ctl',=20'-D',=20= $node->data_dir,=20'-l',=20$node->logfile,=20'restart'=20],=0A-=09= 'restart=20succeeds=20with=20password-protected=20key=20file');=0A= -$node->_update_pid(1);=0A+=09test_connect_fails(=0A+=09=09= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= hostaddr=3D$SERVERHOSTADDR=20host=3Dcommon-name.pg-ssltest.test",=0A+=09=09= "sslrootcert=3Dinvalid=20sslmode=3Drequire",=0A+=09=09qr/\QSSL=20= error\E/,=0A+=09=09"connect=20to=20server=20with=20incorrect=20key=20= password=20configured");=0A+=0A+=09set_server_cert($node,=20= 'server-cn-only',=20'root+client_ca',=0A+=09=09=09=09=09=20=20=20= 'server-password',=20'echo=20secret1');=0A+=09command_ok(=0A+=09=09[=20= 'pg_ctl',=20'-D',=20$node->data_dir,=20'-l',=20$node->logfile,=20= 'restart'=20],=0A+=09=09'restart=20fails=20with=20password-protected=20= key=20file=20with=20wrong=20password');=0A+=09$node->_update_pid(1);=0A+=0A= +=09test_connect_ok(=0A+=09=09"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20hostaddr=3D$SERVERHOSTADDR=20= host=3Dcommon-name.pg-ssltest.test",=0A+=09=09"sslrootcert=3Dinvalid=20= sslmode=3Drequire",=0A+=09=09"connect=20to=20server=20with=20correct=20= key=20password=20configured");=0A+}=0A=20=0A=20#=20Test=20compatibility=20= of=20SSL=20protocols.=0A=20#=20TLSv1.1=20is=20lower=20than=20TLSv1.2,=20= so=20it=20won't=20work.=0A@@=20-149,82=20+159,105=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "sslrootcert=3Dinvalid=20sslmode=3Dverify-ca",=0A-=09qr/root=20= certificate=20file=20"invalid"=20does=20not=20exist/,=0A+=09qr/root=20= certificate=20file=20"invalid"=20does=20not=20exist|Peer's=20Certificate=20= issuer=20is=20not=20recognized/,=0A=20=09"connect=20without=20server=20= root=20cert=20sslmode=3Dverify-ca");=0A=20test_connect_fails(=0A=20=09= $common_connstr,=0A=20=09"sslrootcert=3Dinvalid=20sslmode=3Dverify-full",=0A= -=09qr/root=20certificate=20file=20"invalid"=20does=20not=20exist/,=0A+=09= qr/root=20certificate=20file=20"invalid"=20does=20not=20exist|Peer's=20= Certificate=20issuer=20is=20not=20recognized/,=0A=20=09"connect=20= without=20server=20root=20cert=20sslmode=3Dverify-full");=0A=20=0A=20#=20= Try=20with=20wrong=20root=20cert,=20should=20fail.=20(We're=20using=20= the=20client=20CA=20as=20the=0A=20#=20root,=20but=20the=20server's=20key=20= is=20signed=20by=20the=20server=20CA.)=0A= -test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Drequire",=0A-=09qr/SSL=20= error/,=20"connect=20with=20wrong=20server=20root=20cert=20= sslmode=3Drequire");=0A-test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-ca",=0A-=09qr/SSL=20= error/,=20"connect=20with=20wrong=20server=20root=20cert=20= sslmode=3Dverify-ca");=0A-test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-full",=0A-=09qr/SSL=20= error/,=20"connect=20with=20wrong=20server=20root=20cert=20= sslmode=3Dverify-full");=0A-=0A-#=20Try=20with=20just=20the=20server=20= CA's=20cert.=20This=20fails=20because=20the=20root=20file=0A-#=20must=20= contain=20the=20whole=20chain=20up=20to=20the=20root=20CA.=0A= -test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/server_ca.crt=20sslmode=3Dverify-ca",=0A-=09qr/SSL=20= error/,=20"connect=20with=20server=20CA=20cert,=20without=20root=20CA");=0A= +test_connect_fails(=0A+=09$common_connstr,=0A+=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Drequire=20= cert_database=3Dssl/nss/client_ca.crt.db",=0A+=09qr/SSL=20error/,=0A+=09= "connect=20with=20wrong=20server=20root=20cert=20sslmode=3Drequire");=0A= +test_connect_fails(=0A+=09$common_connstr,=0A+=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-ca=20= cert_database=3Dssl/nss/client_ca.crt.db",=0A+=09qr/SSL=20error/,=0A+=09= "connect=20with=20wrong=20server=20root=20cert=20sslmode=3Dverify-ca");=0A= +test_connect_fails(=0A+=09$common_connstr,=0A+=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-full=20= cert_database=3Dssl/nss/client_ca.crt.db",=0A+=09qr/SSL=20error/,=0A+=09= "connect=20with=20wrong=20server=20root=20cert=20sslmode=3Dverify-full");=0A= +=0A+SKIP:=0A+{=0A+=09#=20NSS=20supports=20partial=20chain=20validation,=20= so=20this=20test=20doesn't=20work=20there.=0A+=09#=20This=20is=20similar=20= to=20the=20OpenSSL=20option=20X509_V_FLAG_PARTIAL_CHAIN=20which=0A+=09#=20= we=20don't=20allow.=0A+=09skip=20"NSS=20support=20partial=20chain=20= validation",=202=20if=20($nss);=0A+=09#=20Try=20with=20just=20the=20= server=20CA's=20cert.=20This=20fails=20because=20the=20root=20file=0A+=09= #=20must=20contain=20the=20whole=20chain=20up=20to=20the=20root=20CA.=0A= +=09test_connect_fails($common_connstr,=0A+=09=09= "sslrootcert=3Dssl/server_ca.crt=20sslmode=3Dverify-ca",=0A+=09=09qr/SSL=20= error/,=20"connect=20with=20server=20CA=20cert,=20without=20root=20CA");=0A= +}=0A=20=0A=20#=20And=20finally,=20with=20the=20correct=20root=20cert.=0A= =20test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connect=20with=20= correct=20server=20CA=20cert=20file=20sslmode=3Drequire");=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connect=20with=20= correct=20server=20CA=20cert=20file=20sslmode=3Dverify-ca");=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-full",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-full=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connect=20with=20= correct=20server=20CA=20cert=20file=20sslmode=3Dverify-full");=0A=20=0A= -#=20Test=20with=20cert=20root=20file=20that=20contains=20two=20= certificates.=20The=20client=20should=0A-#=20be=20able=20to=20pick=20the=20= right=20one,=20regardless=20of=20the=20order=20in=20the=20file.=0A= -test_connect_ok(=0A-=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/both-cas-1.crt=20sslmode=3Dverify-ca",=0A-=09"cert=20= root=20file=20that=20contains=20two=20certificates,=20order=201");=0A= -test_connect_ok(=0A-=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/both-cas-2.crt=20sslmode=3Dverify-ca",=0A-=09"cert=20= root=20file=20that=20contains=20two=20certificates,=20order=202");=0A= +SKIP:=0A+{=0A+=09skip=20"CA=20ordering=20is=20irrelevant=20in=20NSS=20= databases",=202=20if=20($nss);=0A=20=0A+=09#=20Test=20with=20cert=20root=20= file=20that=20contains=20two=20certificates.=20The=20client=20should=0A+=09= #=20be=20able=20to=20pick=20the=20right=20one,=20regardless=20of=20the=20= order=20in=20the=20file.=0A+=09test_connect_ok(=0A+=09=09= $common_connstr,=0A+=09=09"sslrootcert=3Dssl/both-cas-1.crt=20= sslmode=3Dverify-ca",=0A+=09=09"cert=20root=20file=20that=20contains=20= two=20certificates,=20order=201");=0A+=0A+=09#=20How=20about=20import=20= the=20both-file=20into=20a=20database?=0A+=09test_connect_ok(=0A+=09=09= $common_connstr,=0A+=09=09"sslrootcert=3Dssl/both-cas-2.crt=20= sslmode=3Dverify-ca",=0A+=09=09"cert=20root=20file=20that=20contains=20= two=20certificates,=20order=202");=0A+}=0A=20#=20CRL=20tests=0A=20=0A=20= #=20Invalid=20CRL=20filename=20is=20the=20same=20as=20no=20CRL,=20= succeeds=0A=20test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dinvalid",=0A+=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dinvalid=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"sslcrl=20option=20= with=20invalid=20file=20name");=0A=20=0A-#=20A=20CRL=20belonging=20to=20= a=20different=20CA=20is=20not=20accepted,=20fails=0A-test_connect_fails(=0A= -=09$common_connstr,=0A-=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dssl/client.crl",=0A-=09qr/SSL=20error/,=0A= -=09"CRL=20belonging=20to=20a=20different=20CA");=0A+SKIP:=0A+{=0A+=09= skip=20"CRL's=20are=20verified=20when=20adding=20to=20NSS=20database",=20= 2=20if=20($nss);=0A+=09#=20A=20CRL=20belonging=20to=20a=20different=20CA=20= is=20not=20accepted,=20fails=0A+=09test_connect_fails(=0A+=09=09= $common_connstr,=0A+=09=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dssl/client.crl",=0A+=09=09qr/SSL=20= error/,=0A+=09=09"CRL=20belonging=20to=20a=20different=20CA");=0A+}=0A=20= =0A=20#=20With=20the=20correct=20CRL,=20succeeds=20(this=20cert=20is=20= not=20revoked)=0A=20test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dssl/root+server.crl",=0A+=09"sslrootcert=3Dssl/root+server_ca.crt= =20sslmode=3Dverify-ca=20sslcrl=3Dssl/root+server.crl=20= cert_database=3Dssl/nss/root+server_ca.crt__root+server.crl.db",=0A=20=09= "CRL=20with=20a=20non-revoked=20cert");=0A=20=0A=20#=20Check=20that=20= connecting=20with=20verify-full=20fails,=20when=20the=20hostname=20= doesn't=0A=20#=20match=20the=20hostname=20in=20the=20server's=20= certificate.=0A=20$common_connstr=20=3D=0A-=20=20"user=3Dssltestuser=20= dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR";=0A+=20= =20"user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-237,14=20+270,14=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "sslmode=3Dverify-full=20host=3Dwronghost.test",=0A-=09qr/\Qserver=20= certificate=20for=20"common-name.pg-ssltest.test"=20does=20not=20match=20= host=20name=20"wronghost.test"\E/,=0A+=09qr/\Qserver=20certificate=20for=20= "common-name.pg-ssltest.test"=20does=20not=20match=20host=20name=20= "wronghost.test"\E|requested=20domain=20name=20does=20not=20match=20the=20= server's=20certificate/,=0A=20=09"mismatch=20between=20host=20name=20and=20= server=20certificate=20sslmode=3Dverify-full");=0A=20=0A=20#=20Test=20= Subject=20Alternative=20Names.=0A=20switch_server_cert($node,=20= 'server-multiple-alt-names');=0A=20=0A=20$common_connstr=20=3D=0A-=20=20= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= sslmode=3Dverify-full";=0A+=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR=20sslmode=3Dverify-full=20= cert_database=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-262,12=20+295,12=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "host=3Dwronghost.alt-name.pg-ssltest.test",=0A-=09qr/\Qserver=20= certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20= names)=20does=20not=20match=20host=20name=20= "wronghost.alt-name.pg-ssltest.test"\E/,=0A+=09qr/\Qserver=20certificate=20= for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20names)=20does=20= not=20match=20host=20name=20= "wronghost.alt-name.pg-ssltest.test"\E|requested=20domain=20name=20does=20= not=20match=20the=20server's=20certificate/,=0A=20=09"host=20name=20not=20= matching=20with=20X.509=20Subject=20Alternative=20Names");=0A=20= test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "host=3Ddeep.subdomain.wildcard.pg-ssltest.test",=0A-=09qr/\Qserver=20= certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20= names)=20does=20not=20match=20host=20name=20= "deep.subdomain.wildcard.pg-ssltest.test"\E/,=0A+=09qr/\Qserver=20= certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20= names)=20does=20not=20match=20host=20name=20= "deep.subdomain.wildcard.pg-ssltest.test"\E|requested=20domain=20name=20= does=20not=20match=20the=20server's=20certificate/,=0A=20=09"host=20name=20= not=20matching=20with=20X.509=20Subject=20Alternative=20Names=20= wildcard");=0A=20=0A=20#=20Test=20certificate=20with=20a=20single=20= Subject=20Alternative=20Name.=20(this=20gives=20a=0A@@=20-275,7=20+308,7=20= @@=20test_connect_fails(=0A=20switch_server_cert($node,=20= 'server-single-alt-name');=0A=20=0A=20$common_connstr=20=3D=0A-=20=20= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= sslmode=3Dverify-full";=0A+=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR=20sslmode=3Dverify-full=20= cert_database=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-285,12=20+318,12=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "host=3Dwronghost.alt-name.pg-ssltest.test",=0A-=09qr/\Qserver=20= certificate=20for=20"single.alt-name.pg-ssltest.test"=20does=20not=20= match=20host=20name=20"wronghost.alt-name.pg-ssltest.test"\E/,=0A+=09= qr/\Qserver=20certificate=20for=20"single.alt-name.pg-ssltest.test"=20= does=20not=20match=20host=20name=20= "wronghost.alt-name.pg-ssltest.test"\E|requested=20domain=20name=20does=20= not=20match=20the=20server's=20certificate/,=0A=20=09"host=20name=20not=20= matching=20with=20a=20single=20X.509=20Subject=20Alternative=20Name");=0A= =20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "host=3Ddeep.subdomain.wildcard.pg-ssltest.test",=0A-=09qr/\Qserver=20= certificate=20for=20"single.alt-name.pg-ssltest.test"=20does=20not=20= match=20host=20name=20"deep.subdomain.wildcard.pg-ssltest.test"\E/,=0A+=09= qr/\Qserver=20certificate=20for=20"single.alt-name.pg-ssltest.test"=20= does=20not=20match=20host=20name=20= "deep.subdomain.wildcard.pg-ssltest.test"\E|requested=20domain=20name=20= does=20not=20match=20the=20server's=20certificate/,=0A=20=09"host=20name=20= not=20matching=20with=20a=20single=20X.509=20Subject=20Alternative=20= Name=20wildcard"=0A=20);=0A=20=0A@@=20-299,7=20+332,7=20@@=20= test_connect_fails(=0A=20switch_server_cert($node,=20= 'server-cn-and-alt-names');=0A=20=0A=20$common_connstr=20=3D=0A-=20=20= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= sslmode=3Dverify-full";=0A+=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR=20sslmode=3Dverify-full=20= cert_database=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-312,14=20+345,14=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "host=3Dcommon-name.pg-ssltest.test",=0A-=09qr/\Qserver=20certificate=20= for=20"dns1.alt-name.pg-ssltest.test"=20(and=201=20other=20name)=20does=20= not=20match=20host=20name=20"common-name.pg-ssltest.test"\E/,=0A+=09= qr/\Qserver=20certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=20= 1=20other=20name)=20does=20not=20match=20host=20name=20= "common-name.pg-ssltest.test"\E|requested=20domain=20name=20does=20not=20= match=20the=20server's=20certificate/,=0A=20=09"certificate=20with=20= both=20a=20CN=20and=20SANs=20ignores=20CN");=0A=20=0A=20#=20Finally,=20= test=20a=20server=20certificate=20that=20has=20no=20CN=20or=20SANs.=20Of=20= course,=20that's=0A=20#=20not=20a=20very=20sensible=20certificate,=20but=20= libpq=20should=20handle=20it=20gracefully.=0A=20= switch_server_cert($node,=20'server-no-names');=0A=20$common_connstr=20=3D= =0A-=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR";=0A+=20= =20"user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-328,7=20+361,7=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "sslmode=3Dverify-full=20host=3Dcommon-name.pg-ssltest.test",=0A-=09= qr/could=20not=20get=20server's=20host=20name=20from=20server=20= certificate/,=0A+=09qr/could=20not=20get=20server's=20host=20name=20from=20= server=20certificate|requested=20domain=20name=20does=20not=20match=20= the=20server's=20certificate./,=0A=20=09"server=20certificate=20without=20= CN=20or=20SANs=20sslmode=3Dverify-full");=0A=20=0A=20#=20Test=20that=20= the=20CRL=20works=0A@@=20-340,11=20+373,11=20@@=20$common_connstr=20=3D=0A= =20#=20Without=20the=20CRL,=20succeeds.=20With=20it,=20fails.=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connects=20= without=20client-side=20CRL");=0A=20test_connect_fails(=0A=20=09= $common_connstr,=0A-=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dssl/root+server.crl",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dssl/server.crl=20= cert_database=3Dssl/nss/root+server_ca.crt__server.crl.db",=0A=20=09= qr/SSL=20error/,=0A=20=09"does=20not=20connect=20with=20client-side=20= CRL");=0A=20=0A@@=20-365,32=20+398,50=20@@=20command_like(=0A=20#=20Test=20= min/max=20SSL=20protocol=20versions.=0A=20test_connect_ok(=0A=20=09= $common_connstr,=0A-=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Drequire=20ssl_min_protocol_version=3DTLSv1.2=20= ssl_max_protocol_version=3DTLSv1.2",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3DTLSv1.2=20ssl_max_protocol_version=3DTLSv1.2=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connection=20= success=20with=20correct=20range=20of=20TLS=20protocol=20versions");=0A=20= test_connect_fails(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3DTLSv1.2=20ssl_max_protocol_version=3DTLSv1.1",=0A= +=09"sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3DTLSv1.2=20ssl_max_protocol_version=3DTLSv1.1=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09qr/invalid=20SSL=20= protocol=20version=20range/,=0A=20=09"connection=20failure=20with=20= incorrect=20range=20of=20TLS=20protocol=20versions");=0A=20= test_connect_fails(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3Dincorrect_tls",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3Dincorrect_tls=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09qr/invalid=20= ssl_min_protocol_version=20value/,=0A=20=09"connection=20failure=20with=20= an=20incorrect=20SSL=20protocol=20minimum=20bound");=0A=20= test_connect_fails(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_max_protocol_version=3Dincorrect_tls",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_max_protocol_version=3Dincorrect_tls=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09qr/invalid=20= ssl_max_protocol_version=20value/,=0A=20=09"connection=20failure=20with=20= an=20incorrect=20SSL=20protocol=20maximum=20bound");=0A=20=0A+#=20tests=20= of=20NSS=20generated=20certificates/keys=0A+SKIP:=0A+{=0A+=09skip=20"NSS=20= specific=20tests",=20=20=20=20=20=20=20=20=20=20=20=201=20if=20= ($openssl);=0A+=0A+=09switch_server_cert($node,=20'native_server-root',=20= 'native_ca-root');=0A+=09$common_connstr=20=3D=0A+=09=20=20= "user=3Dssltestuser=20dbname=3Dtrustdb=20hostaddr=3D$SERVERHOSTADDR=20= host=3Dcommon-name.pg-ssltest.test";=0A+=0A+=09test_connect_ok(=0A+=09=09= $common_connstr,=0A+=09=09"sslmode=3Drequire=20user=3Dssltestuser",=0A+=09= =09"NSS=20generated=20certificates"=0A+=09);=0A+}=0A+=0A=20###=20= Server-side=20tests.=0A=20###=0A=20###=20Test=20certificate=20= authorization.=0A=20=0A+switch_server_cert($node,=20'server-revoked');=0A= +=0A=20note=20"running=20server=20tests";=0A=20=0A=20$common_connstr=20=3D= =0A-=20=20"sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= dbname=3Dcertdb=20hostaddr=3D$SERVERHOSTADDR";=0A+=20=20= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= dbname=3Dcertdb=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/client.crt__client.key.db";=0A=20=0A=20#=20no=20= client=20cert=0A=20test_connect_fails(=0A@@=20-406,32=20+457,43=20@@=20= test_connect_ok(=0A=20=09"certificate=20authorization=20succeeds=20with=20= correct=20client=20cert=20in=20PEM=20format"=0A=20);=0A=20=0A-#=20= correct=20client=20cert=20in=20unencrypted=20DER=0A-test_connect_ok(=0A-=09= $common_connstr,=0A-=09"user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-der_tmp.key",=0A-=09"certificate=20authorization=20= succeeds=20with=20correct=20client=20cert=20in=20DER=20format"=0A-);=0A= +$common_connstr=20=3D=0A+=20=20"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Drequire=20dbname=3Dcertdb=20hostaddr=3D$SERVERHOSTADDR";=0A+=0A= +SKIP:=0A+{=0A+=09skip=20"NSS=20database=20not=20implemented=20in=20the=20= Makefile",=201=20if=20($nss);=0A+=09#=20correct=20client=20cert=20in=20= unencrypted=20DER=0A+=09test_connect_ok(=0A+=09=09$common_connstr,=0A+=09= =09"user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-der_tmp.key",=0A+=09=09"certificate=20authorization=20= succeeds=20with=20correct=20client=20cert=20in=20DER=20format"=0A+=09);=0A= +}=0A=20=0A=20#=20correct=20client=20cert=20in=20encrypted=20PEM=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A-=09"user=3Dssltestuser=20= sslcert=3Dssl/client.crt=20sslkey=3Dssl/client-encrypted-pem_tmp.key=20= sslpassword=3D'dUmmyP^#+'",=0A+=09"user=3Dssltestuser=20= sslcert=3Dssl/client.crt=20sslkey=3Dssl/client-encrypted-pem_tmp.key=20= sslpassword=3D'dUmmyP^#+'=20= cert_database=3Dssl/nss/client.crt__client-encrypted-pem.key.db",=0A=20=09= "certificate=20authorization=20succeeds=20with=20correct=20client=20cert=20= in=20encrypted=20PEM=20format"=0A=20);=0A=20=0A-#=20correct=20client=20= cert=20in=20encrypted=20DER=0A-test_connect_ok(=0A-=09$common_connstr,=0A= -=09"user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-encrypted-der_tmp.key=20sslpassword=3D'dUmmyP^#+'",=0A= -=09"certificate=20authorization=20succeeds=20with=20correct=20client=20= cert=20in=20encrypted=20DER=20format"=0A-);=0A+SKIP:=0A+{=0A+=09skip=20= "NSS=20database=20not=20implemented=20in=20the=20Makefile",=201=20if=20= ($nss);=0A+=09#=20correct=20client=20cert=20in=20encrypted=20DER=0A+=09= test_connect_ok(=0A+=09=09$common_connstr,=0A+=09=09"user=3Dssltestuser=20= sslcert=3Dssl/client.crt=20sslkey=3Dssl/client-encrypted-der_tmp.key=20= sslpassword=3D'dUmmyP^#+'",=0A+=09=09"certificate=20authorization=20= succeeds=20with=20correct=20client=20cert=20in=20encrypted=20DER=20= format"=0A+=09);=0A+}=0A=20=0A=20#=20correct=20client=20cert=20in=20= encrypted=20PEM=20with=20wrong=20password=0A=20test_connect_fails(=0A=20=09= $common_connstr,=0A-=09"user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-encrypted-pem_tmp.key=20sslpassword=3D'wrong'",=0A-=09= qr!\Qprivate=20key=20file=20"ssl/client-encrypted-pem_tmp.key":=20bad=20= decrypt\E!,=0A+=09"user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-encrypted-pem_tmp.key=20sslpassword=3D'wrong'=20= cert_database=3Dssl/nss/client.crt__client-encrypted-pem.key.db",=0A+=09= qr!connection=20requires=20a=20valid=20client=20certificate|\Qprivate=20= key=20file=20"ssl/client-encrypted-pem_tmp.key":=20bad=20decrypt\E!,=0A=20= =09"certificate=20authorization=20fails=20with=20correct=20client=20cert=20= and=20wrong=20password=20in=20encrypted=20PEM=20format"=0A=20);=0A=20=0A= @@=20-471,18=20+533,19=20@@=20command_like(=0A=20=09=09'-P',=0A=20=09=09= 'null=3D_null_',=0A=20=09=09'-d',=0A-=09=09"$common_connstr=20= user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client_tmp.key",=0A+=09=09"$common_connstr=20= user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client_tmp.key=20= cert_database=3Dssl/nss/client.crt__client.key.db",=0A=20=09=09'-c',=0A=20= =09=09"SELECT=20*=20FROM=20pg_stat_ssl=20WHERE=20pid=20=3D=20= pg_backend_pid()"=0A=20=09],=0A=20=09= qr{^pid,ssl,version,cipher,bits,compression,client_dn,client_serial,issuer= _dn\r?\n=0A-=09=09=09=09= ^\d+,t,TLSv[\d.]+,[\w-]+,\d+,f,/CN=3Dssltestuser,1,\Q/CN=3DTest=20CA=20= for=20PostgreSQL=20SSL=20regression=20test=20client=20certs\E\r?$}mx,=0A= +=09=09=09=09= ^\d+,t,TLSv[\d.]+,[\w-]+,\d+,f,/?CN=3Dssltestuser,1,/?\QCN=3DTest=20CA=20= for=20PostgreSQL=20SSL=20regression=20test=20client=20certs\E\r?$}mx,=0A=20= =09'pg_stat_ssl=20with=20client=20certificate');=0A=20=0A=20#=20client=20= key=20with=20wrong=20permissions=0A=20SKIP:=0A=20{=0A=20=09skip=20= "Permissions=20check=20not=20enforced=20on=20Windows",=202=20if=20= ($windows_os);=0A+=09skip=20"Key=20not=20on=20filesystem=20with=20NSS",=20= =20=20=20=20=20=20=20=20=20=20=202=20if=20($nss);=0A=20=0A=20=09= test_connect_fails(=0A=20=09=09$common_connstr,=0A@@=20-495,10=20+558,13=20= @@=20SKIP:=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "user=3Danotheruser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client_tmp.key",=0A-=09qr/certificate=20authentication=20= failed=20for=20user=20"anotheruser"/,=0A+=09qr/unable=20to=20verify=20= certificate|certificate=20authentication=20failed=20for=20user=20= "anotheruser"/,=0A=20=09"certificate=20authorization=20fails=20with=20= client=20cert=20belonging=20to=20another=20user"=0A=20);=0A=20=0A= +$common_connstr=20=3D=0A+=20=20"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Drequire=20dbname=3Dcertdb=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/client-revoked.crt__client-revoked.key.db";=0A+=0A= =20#=20revoked=20client=20cert=0A=20test_connect_fails(=0A=20=09= $common_connstr,=0A@@=20-510,7=20+576,7=20@@=20test_connect_fails(=0A=20= #=20works,=20iff=20username=20matches=20Common=20Name=0A=20#=20fails,=20= iff=20username=20doesn't=20match=20Common=20Name.=0A=20$common_connstr=20= =3D=0A-=20=20"sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= dbname=3Dverifydb=20hostaddr=3D$SERVERHOSTADDR";=0A+=20=20= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= dbname=3Dverifydb=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/client.crt__client.key.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-536,17=20+602,23=20@@=20= test_connect_ok(=0A=20#=20intermediate=20client_ca.crt=20is=20provided=20= by=20client,=20and=20isn't=20in=20server's=20ssl_ca_file=0A=20= switch_server_cert($node,=20'server-cn-only',=20'root_ca');=0A=20= $common_connstr=20=3D=0A-=20=20"user=3Dssltestuser=20dbname=3Dcertdb=20= sslkey=3Dssl/client_tmp.key=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR";=0A+=20=20"user=3Dssltestuser=20= dbname=3Dcertdb=20sslkey=3Dssl/client_tmp.key=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/client+client_ca.crt__client.key.db";=0A=20=0A= -test_connect_ok(=0A+TODO:=0A+{=0A+=09local=20$TODO=20=3D=20"WIP=20= failure=20cause=20currently=20unknown";=0A+=09test_connect_ok(=0A+=09=09= $common_connstr,=0A+=09=09"sslmode=3Drequire=20= sslcert=3Dssl/client+client_ca.crt",=0A+=09=09"intermediate=20client=20= certificate=20is=20provided=20by=20client");=0A+}=0A+=0A= +test_connect_fails(=0A=20=09$common_connstr,=0A-=09"sslmode=3Drequire=20= sslcert=3Dssl/client+client_ca.crt",=0A-=09"intermediate=20client=20= certificate=20is=20provided=20by=20client");=0A= -test_connect_fails($common_connstr,=20"sslmode=3Drequire=20= sslcert=3Dssl/client.crt",=0A-=09qr/SSL=20error/,=20"intermediate=20= client=20certificate=20is=20missing");=0A+=09"sslmode=3Drequire=20= sslcert=3Dssl/client.crt",=0A+=09qr/connection=20requires=20a=20valid=20= client=20certificate|SSL=20error/,=0A+=09"intermediate=20client=20= certificate=20is=20missing");=0A=20=0A=20#=20clean=20up=0A-foreach=20my=20= $key=20(@keys)=0A-{=0A-=09unlink("ssl/${key}_tmp.key");=0A-}=0A+=0A= +SSL::Server::cleanup();=0Adiff=20--git=20a/src/test/ssl/t/002_scram.pl=20= b/src/test/ssl/t/002_scram.pl=0Aindex=20a088f71a1a..cf5714e544=20100644=0A= ---=20a/src/test/ssl/t/002_scram.pl=0A+++=20= b/src/test/ssl/t/002_scram.pl=0A@@=20-11,24=20+11,39=20@@=20use=20= File::Copy;=0A=20use=20FindBin;=0A=20use=20lib=20$FindBin::RealBin;=0A=20= =0A-use=20SSLServer;=0A+use=20SSL::Server;=0A=20=0A-if=20= ($ENV{with_openssl}=20ne=20'yes')=0A+my=20$openssl;=0A+my=20$nss;=0A+=0A= +my=20$supports_tls_server_end_point;=0A+=0A+if=20($ENV{with_ssl}=20eq=20= 'no')=0A=20{=0A=20=09plan=20skip_all=20=3D>=20'SSL=20not=20supported=20= by=20this=20build';=0A=20}=0A+else=0A+{=0A+=09if=20($ENV{with_ssl}=20eq=20= 'openssl')=0A+=09{=0A+=09=09$openssl=20=3D=201;=0A+=09=09#=20Determine=20= whether=20build=20supports=20tls-server-end-point.=0A+=09=09= $supports_tls_server_end_point=20=3D=0A+=09=09=09= check_pg_config("#define=20HAVE_X509_GET_SIGNATURE_NID=201");=0A+=09=09= plan=20tests=20=3D>=20$supports_tls_server_end_point=20?=209=20:=2010;=0A= +=09}=0A+=09elsif=20($ENV{with_ssl}=20eq=20'nss')=0A+=09{=0A+=09=09$nss=20= =3D=201;=0A+=09=09plan=20tests=20=3D>=208;=0A+=09}=0A+}=0A=20=0A=20#=20= This=20is=20the=20hostname=20used=20to=20connect=20to=20the=20server.=0A=20= my=20$SERVERHOSTADDR=20=3D=20'127.0.0.1';=0A=20#=20This=20is=20the=20= pattern=20to=20use=20in=20pg_hba.conf=20to=20match=20incoming=20= connections.=0A=20my=20$SERVERHOSTCIDR=20=3D=20'127.0.0.1/32';=0A=20=0A= -#=20Determine=20whether=20build=20supports=20tls-server-end-point.=0A= -my=20$supports_tls_server_end_point=20=3D=0A-=20=20= check_pg_config("#define=20HAVE_X509_GET_SIGNATURE_NID=201");=0A-=0A-my=20= $number_of_tests=20=3D=20$supports_tls_server_end_point=20?=209=20:=20= 10;=0A-=0A=20#=20Allocation=20of=20base=20connection=20string=20shared=20= among=20multiple=20tests.=0A=20my=20$common_connstr;=0A=20=0A@@=20-66,20=20= +81,25=20@@=20test_connect_ok(=0A=20=09$common_connstr,=0A=20=09= "user=3Dssltestuser=20channel_binding=3Ddisable",=0A=20=09"SCRAM=20with=20= SSL=20and=20channel_binding=3Ddisable");=0A-if=20= ($supports_tls_server_end_point)=0A-{=0A-=09test_connect_ok(=0A-=09=09= $common_connstr,=0A-=09=09"user=3Dssltestuser=20= channel_binding=3Drequire",=0A-=09=09"SCRAM=20with=20SSL=20and=20= channel_binding=3Drequire");=0A-}=0A-else=0A+=0A+SKIP:=0A=20{=0A-=09= test_connect_fails(=0A-=09=09$common_connstr,=0A-=09=09"user=3Dssltestuser= =20channel_binding=3Drequire",=0A-=09=09qr/channel=20binding=20is=20= required,=20but=20server=20did=20not=20offer=20an=20authentication=20= method=20that=20supports=20channel=20binding/,=0A-=09=09"SCRAM=20with=20= SSL=20and=20channel_binding=3Drequire");=0A+=09skip=20"NSS=20support=20= for=20TLS=20server=20endpoing=20is=20not=20implemented",=201=20if=20= ($nss);=0A+=09if=20($supports_tls_server_end_point)=0A+=09{=0A+=09=09= test_connect_ok(=0A+=09=09=09$common_connstr,=0A+=09=09=09= "user=3Dssltestuser=20channel_binding=3Drequire",=0A+=09=09=09"SCRAM=20= with=20SSL=20and=20channel_binding=3Drequire");=0A+=09}=0A+=09else=0A+=09= {=0A+=09=09test_connect_fails(=0A+=09=09=09$common_connstr,=0A+=09=09=09= "user=3Dssltestuser=20channel_binding=3Drequire",=0A+=09=09=09qr/channel=20= binding=20is=20required,=20but=20server=20did=20not=20offer=20an=20= authentication=20method=20that=20supports=20channel=20binding/,=0A+=09=09= =09"SCRAM=20with=20SSL=20and=20channel_binding=3Drequire");=0A+=09}=0A=20= }=0A=20=0A=20#=20Now=20test=20when=20the=20user=20has=20an=20= MD5-encrypted=20password;=20should=20fail=0A@@=20-89,20=20+109,21=20@@=20= test_connect_fails(=0A=20=09qr/channel=20binding=20required=20but=20not=20= supported=20by=20server's=20authentication=20request/,=0A=20=09"MD5=20= with=20SSL=20and=20channel_binding=3Drequire");=0A=20=0A-#=20Now=20test=20= with=20auth=20method=20'cert'=20by=20connecting=20to=20'certdb'.=20= Should=20fail,=0A-#=20because=20channel=20binding=20is=20not=20= performed.=20=20Note=20that=20ssl/client.key=20may=0A-#=20be=20used=20in=20= a=20different=20test,=20so=20the=20name=20of=20this=20temporary=20client=20= key=0A-#=20is=20chosen=20here=20to=20be=20unique.=0A-my=20= $client_tmp_key=20=3D=20"ssl/client_scram_tmp.key";=0A= -copy("ssl/client.key",=20$client_tmp_key);=0A-chmod=200600,=20= $client_tmp_key;=0A-test_connect_fails(=0A-=09"sslcert=3Dssl/client.crt=20= sslkey=3D$client_tmp_key=20sslrootcert=3Dinvalid=20= hostaddr=3D$SERVERHOSTADDR",=0A-=09"dbname=3Dcertdb=20user=3Dssltestuser=20= channel_binding=3Drequire",=0A-=09qr/channel=20binding=20required,=20but=20= server=20authenticated=20client=20without=20channel=20binding/,=0A-=09= "Cert=20authentication=20and=20channel_binding=3Drequire");=0A-=0A-#=20= clean=20up=0A-unlink($client_tmp_key);=0A-=0A= -done_testing($number_of_tests);=0A+SKIP:=0A+{=0A+=09skip=20"NSS=20= support=20not=20implemented=20yet",=201=20if=20($nss);=0A+=09#=20Now=20= test=20with=20auth=20method=20'cert'=20by=20connecting=20to=20'certdb'.=20= Should=20fail,=0A+=09#=20because=20channel=20binding=20is=20not=20= performed.=20=20Note=20that=20ssl/client.key=20may=0A+=09#=20be=20used=20= in=20a=20different=20test,=20so=20the=20name=20of=20this=20temporary=20= client=20key=0A+=09#=20is=20chosen=20here=20to=20be=20unique.=0A+=09my=20= $client_tmp_key=20=3D=20"ssl/client_scram_tmp.key";=0A+=09= copy("ssl/client.key",=20$client_tmp_key);=0A+=09chmod=200600,=20= $client_tmp_key;=0A+=09test_connect_fails(=0A+=09=09= "sslcert=3Dssl/client.crt=20sslkey=3D$client_tmp_key=20= sslrootcert=3Dinvalid=20hostaddr=3D$SERVERHOSTADDR",=0A+=09=09= "dbname=3Dcertdb=20user=3Dssltestuser=20channel_binding=3Drequire",=0A+=09= =09qr/channel=20binding=20required,=20but=20server=20authenticated=20= client=20without=20channel=20binding/,=0A+=09=09"Cert=20authentication=20= and=20channel_binding=3Drequire");=0A+=09#=20clean=20up=0A+=09= unlink($client_tmp_key);=0A+}=0Adiff=20--git=20= a/src/test/ssl/t/SSL/Backend/NSS.pm=20= b/src/test/ssl/t/SSL/Backend/NSS.pm=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..c5b31e584a=0A---=20/dev/null=0A+++=20= b/src/test/ssl/t/SSL/Backend/NSS.pm=0A@@=20-0,0=20+1,73=20@@=0A+package=20= SSL::Backend::NSS;=0A+=0A+use=20strict;=0A+use=20warnings;=0A+use=20= Exporter;=0A+=0A+our=20@ISA=20=20=20=20=20=20=20=3D=20qw(Exporter);=0A= +our=20@EXPORT_OK=20=3D=20qw(get_new_nss_backend);=0A+=0A+sub=20new=0A+{=0A= +=09my=20($class)=20=3D=20@_;=0A+=0A+=09my=20$self=20=3D=20{=20_library=20= =3D>=20'NSS'=20};=0A+=0A+=09bless=20$self,=20$class;=0A+=0A+=09return=20= $self;=0A+}=0A+=0A+sub=20get_new_nss_backend=0A+{=0A+=09my=20$class=20=3D=20= 'SSL::Backend::NSS';=0A+=0A+=09return=20$class->new();=0A+}=0A+=0A+sub=20= init=0A+{=0A+=09#=20Make=20sure=20the=20certificate=20databases=20are=20= in=20place?=0A+}=0A+=0A+sub=20get_library=0A+{=0A+=09my=20($self)=20=3D=20= @_;=0A+=0A+=09return=20$self->{_library};=0A+}=0A+=0A+sub=20= set_server_cert=0A+{=0A+=09my=20$self=20=20=20=20=20=3D=20$_[0];=0A+=09= my=20$certfile=20=3D=20$_[1];=0A+=09my=20$cafile=20=20=20=3D=20$_[2];=0A= +=09my=20$keyfile=20=20=3D=20$_[3];=0A+=0A+=09my=20$cert_nickname;=0A+=0A= +=09if=20($certfile=20=3D~=20/native/)=0A+=09{=0A+=09=09$cert_nickname=20= =3D=20$certfile;=0A+=09}=0A+=09else=0A+=09{=0A+=09=09$cert_nickname=20=3D=20= $certfile=20.=20'.crt__'=20.=20$keyfile=20.=20'.key';=0A+=09}=0A+=09my=20= $cert_database=20=3D=20$cert_nickname=20.=20'.db';=0A+=0A+=09my=20= $sslconf=20=3D=0A+=09=20=20=20=20"ssl_ca_file=3D'$cafile.crt'\n"=0A+=09=20= =20.=20"ssl_cert_file=3D'ssl/$certfile.crt'\n"=0A+=09=20=20.=20= "ssl_crl_file=3D''\n"=0A+=09=20=20.=20= "ssl_database=3D'nss/$cert_database'\n";=0A+=0A+=09return=20$sslconf;=0A= +}=0A+=0A+sub=20cleanup=0A+{=0A+=09#=20Something?=0A+}=0A+=0A+1;=0Adiff=20= --git=20a/src/test/ssl/t/SSL/Backend/OpenSSL.pm=20= b/src/test/ssl/t/SSL/Backend/OpenSSL.pm=0Anew=20file=20mode=20100644=0A= index=200000000000..62b11b7632=0A---=20/dev/null=0A+++=20= b/src/test/ssl/t/SSL/Backend/OpenSSL.pm=0A@@=20-0,0=20+1,103=20@@=0A= +package=20SSL::Backend::OpenSSL;=0A+=0A+use=20strict;=0A+use=20= warnings;=0A+use=20Exporter;=0A+use=20File::Copy;=0A+=0A+our=20@ISA=20=20= =20=20=20=20=20=3D=20qw(Exporter);=0A+our=20@EXPORT_OK=20=3D=20= qw(get_new_openssl_backend);=0A+=0A+our=20(@keys);=0A+=0A+INIT=0A+{=0A+=09= @keys=20=3D=20(=0A+=09=09"client",=20=20=20=20=20"client-revoked",=0A+=09= =09"client-der",=20"client-encrypted-pem",=0A+=09=09= "client-encrypted-der");=0A+}=0A+=0A+sub=20new=0A+{=0A+=09my=20($class)=20= =3D=20@_;=0A+=0A+=09my=20$self=20=3D=20{=20_library=20=3D>=20'OpenSSL'=20= };=0A+=0A+=09bless=20$self,=20$class;=0A+=0A+=09return=20$self;=0A+}=0A+=0A= +sub=20get_new_openssl_backend=0A+{=0A+=09my=20$class=20=3D=20= 'SSL::Backend::OpenSSL';=0A+=0A+=09my=20$backend=20=3D=20$class->new();=0A= +=0A+=09return=20$backend;=0A+}=0A+=0A+sub=20init=0A+{=0A+=09#=20The=20= client's=20private=20key=20must=20not=20be=20world-readable,=20so=20take=20= a=20copy=0A+=09#=20of=20the=20key=20stored=20in=20the=20code=20tree=20= and=20update=20its=20permissions.=0A+=09#=0A+=09#=20This=20changes=20= ssl/client.key=20to=20ssl/client_tmp.key=20etc=20for=20the=20rest=0A+=09= #=20of=20the=20tests.=0A+=09foreach=20my=20$key=20(@keys)=0A+=09{=0A+=09=09= copy("ssl/${key}.key",=20"ssl/${key}_tmp.key")=0A+=09=09=20=20or=20die=0A= +=09=09=20=20"couldn't=20copy=20ssl/${key}.key=20to=20ssl/${key}_tmp.key=20= for=20permissions=20change:=20$!";=0A+=09=09chmod=200600,=20= "ssl/${key}_tmp.key"=0A+=09=09=20=20or=20die=20"failed=20to=20change=20= permissions=20on=20ssl/${key}_tmp.key:=20$!";=0A+=09}=0A+=0A+=09#=20Also=20= make=20a=20copy=20of=20that=20explicitly=20world-readable.=20=20We=20= can't=0A+=09#=20necessarily=20rely=20on=20the=20file=20in=20the=20source=20= tree=20having=20those=0A+=09#=20permissions.=20Add=20it=20to=20@keys=20= to=20include=20it=20in=20the=20final=20clean=0A+=09#=20up=20phase.=0A+=09= copy("ssl/client.key",=20"ssl/client_wrongperms_tmp.key")=0A+=09=20=20or=20= die=0A+=09=20=20"couldn't=20copy=20ssl/client.key=20to=20= ssl/client_wrongperms_tmp.key:=20$!";=0A+=09chmod=200644,=20= "ssl/client_wrongperms_tmp.key"=0A+=09=20=20or=20die=0A+=09=20=20"failed=20= to=20change=20permissions=20on=20ssl/client_wrongperms_tmp.key:=20$!";=0A= +=09push=20@keys,=20'client_wrongperms';=0A+}=0A+=0A+#=20Change=20the=20= configuration=20to=20use=20given=20server=20cert=20file,=20and=20reload=0A= +#=20the=20server=20so=20that=20the=20configuration=20takes=20effect.=0A= +sub=20set_server_cert=0A+{=0A+=09my=20$self=20=20=20=20=20=3D=20$_[0];=0A= +=09my=20$certfile=20=3D=20$_[1];=0A+=09my=20$cafile=20=20=20=3D=20$_[2]=20= ||=20"root+client_ca";=0A+=09my=20$keyfile=20=20=3D=20$_[3]=20||=20= $certfile;=0A+=0A+=09my=20$sslconf=20=3D=0A+=09=20=20=20=20= "ssl_ca_file=3D'$cafile.crt'\n"=0A+=09=20=20.=20= "ssl_cert_file=3D'$certfile.crt'\n"=0A+=09=20=20.=20= "ssl_key_file=3D'$keyfile.key'\n"=0A+=09=20=20.=20= "ssl_crl_file=3D'root+client.crl'\n";=0A+=0A+=09return=20$sslconf;=0A+}=0A= +=0A+sub=20get_library=0A+{=0A+=09my=20($self)=20=3D=20@_;=0A+=0A+=09= return=20$self->{_library};=0A+}=0A+=0A+sub=20cleanup=0A+{=0A+=09foreach=20= my=20$key=20(@keys)=0A+=09{=0A+=09=09unlink("ssl/${key}_tmp.key");=0A+=09= }=0A+}=0A+=0A+1;=0Adiff=20--git=20a/src/test/ssl/t/SSLServer.pm=20= b/src/test/ssl/t/SSL/Server.pm=0Asimilarity=20index=2078%=0Arename=20= from=20src/test/ssl/t/SSLServer.pm=0Arename=20to=20= src/test/ssl/t/SSL/Server.pm=0Aindex=20f5987a003e..ee901855b5=20100644=0A= ---=20a/src/test/ssl/t/SSLServer.pm=0A+++=20= b/src/test/ssl/t/SSL/Server.pm=0A@@=20-23,19=20+23,39=20@@=0A=20#=20= explicitly=20because=20an=20invalid=20sslcert=20or=20sslrootcert,=20= respectively,=0A=20#=20causes=20those=20to=20be=20ignored.)=0A=20=0A= -package=20SSLServer;=0A+package=20SSL::Server;=0A=20=0A=20use=20strict;=0A= =20use=20warnings;=0A=20use=20PostgresNode;=0A+use=20RecursiveCopy;=0A=20= use=20TestLib;=0A=20use=20File::Basename;=0A=20use=20File::Copy;=0A=20= use=20Test::More;=0A+use=20SSL::Backend::OpenSSL=20= qw(get_new_openssl_backend);=0A+use=20SSL::Backend::NSS=20= qw(get_new_nss_backend);=0A+=0A+our=20($openssl,=20$nss,=20$backend);=0A= +=0A+#=20The=20TLS=20backend=20which=20the=20server=20is=20using=20= should=20be=20mostly=20transparent=20for=0A+#=20the=20user,=20apart=20= from=20individual=20configuration=20settings,=20so=20keep=20the=20= backend=0A+#=20specific=20things=20abstracted=20behind=20SSL::Server.=0A= +if=20($ENV{with_ssl}=20eq=20'openssl')=0A+{=0A+=09$backend=20=3D=20= get_new_openssl_backend();=0A+=09$openssl=20=3D=201;=0A+}=0A+elsif=20= ($ENV{with_ssl}=20eq=20'nss')=0A+{=0A+=09$backend=20=3D=20= get_new_nss_backend();=0A+=09$nss=20=20=20=20=20=3D=201;=0A+}=0A=20=0A=20= use=20Exporter=20'import';=0A=20our=20@EXPORT=20=3D=20qw(=0A=20=20=20= configure_test_server_for_ssl=0A+=20=20set_server_cert=0A=20=20=20= switch_server_cert=0A=20=20=20test_connect_fails=0A=20=20=20= test_connect_ok=0A@@=20-144,12=20+164,19=20@@=20sub=20= configure_test_server_for_ssl=0A=20=09close=20$sslconf;=0A=20=0A=20=09#=20= Copy=20all=20server=20certificates=20and=20keys,=20and=20client=20root=20= cert,=20to=20the=20data=20dir=0A-=09copy_files("ssl/server-*.crt",=20= $pgdata);=0A-=09copy_files("ssl/server-*.key",=20$pgdata);=0A-=09= chmod(0600,=20glob=20"$pgdata/server-*.key")=20or=20die=20$!;=0A-=09= copy_files("ssl/root+client_ca.crt",=20$pgdata);=0A-=09= copy_files("ssl/root_ca.crt",=20=20=20=20=20=20=20=20$pgdata);=0A-=09= copy_files("ssl/root+client.crl",=20=20=20=20$pgdata);=0A+=09if=20= (defined($openssl))=0A+=09{=0A+=09=09copy_files("ssl/server-*.crt",=20= $pgdata);=0A+=09=09copy_files("ssl/server-*.key",=20$pgdata);=0A+=09=09= chmod(0600,=20glob=20"$pgdata/server-*.key")=20or=20die=20$!;=0A+=09=09= copy_files("ssl/root+client_ca.crt",=20$pgdata);=0A+=09=09= copy_files("ssl/root_ca.crt",=20=20=20=20=20=20=20=20$pgdata);=0A+=09=09= copy_files("ssl/root+client.crl",=20=20=20=20$pgdata);=0A+=09}=0A+=09= elsif=20(defined($nss))=0A+=09{=0A+=09=09= RecursiveCopy::copypath("ssl/nss",=20$pgdata=20.=20"/nss")=20if=20-e=20= "ssl/nss";=0A+=09}=0A=20=0A=20=09#=20Stop=20and=20restart=20server=20to=20= load=20new=20listen_addresses.=0A=20=09$node->restart;=0A@@=20-157,26=20= +184,51=20@@=20sub=20configure_test_server_for_ssl=0A=20=09#=20Change=20= pg_hba=20after=20restart=20because=20hostssl=20requires=20ssl=3Don=0A=20=09= configure_hba_for_ssl($node,=20$servercidr,=20$authmethod);=0A=20=0A+=09= #=20Finally,=20perform=20backend=20specific=20configuration=0A+=09= $backend->init();=0A+=0A=20=09return;=0A=20}=0A=20=0A-#=20Change=20the=20= configuration=20to=20use=20given=20server=20cert=20file,=20and=20reload=0A= -#=20the=20server=20so=20that=20the=20configuration=20takes=20effect.=0A= -sub=20switch_server_cert=0A+sub=20ssl_library=0A+{=0A+=09return=20= $backend->get_library();=0A+}=0A+=0A+sub=20cleanup=0A+{=0A+=09= $backend->cleanup();=0A+}=0A+=0A+#=20Change=20the=20configuration=20to=20= use=20given=20server=20cert=20file,=0A+sub=20set_server_cert=0A=20{=0A=20= =09my=20$node=20=20=20=20=20=3D=20$_[0];=0A=20=09my=20$certfile=20=3D=20= $_[1];=0A=20=09my=20$cafile=20=20=20=3D=20$_[2]=20||=20"root+client_ca";=0A= +=09my=20$keyfile=20=20=3D=20$_[3]=20||=20'';=0A+=09my=20$pwcmd=20=20=20=20= =3D=20$_[4]=20||=20'';=0A=20=09my=20$pgdata=20=20=20=3D=20= $node->data_dir;=0A=20=0A+=09$keyfile=20=3D=20$certfile=20if=20$keyfile=20= eq=20'';=0A+=0A=20=09open=20my=20$sslconf,=20'>',=20= "$pgdata/sslconfig.conf";=0A=20=09print=20$sslconf=20"ssl=3Don\n";=0A-=09= print=20$sslconf=20"ssl_ca_file=3D'$cafile.crt'\n";=0A-=09print=20= $sslconf=20"ssl_cert_file=3D'$certfile.crt'\n";=0A-=09print=20$sslconf=20= "ssl_key_file=3D'$certfile.key'\n";=0A-=09print=20$sslconf=20= "ssl_crl_file=3D'root+client.crl'\n";=0A+=09print=20$sslconf=20= $backend->set_server_cert($certfile,=20$cafile,=20$keyfile);=0A+=09print=20= $sslconf=20"ssl_passphrase_command=3D'$pwcmd'\n"=0A+=09=20=20unless=20= $pwcmd=20eq=20'';=0A=20=09close=20$sslconf;=0A+=09return;=0A+}=0A=20=0A= +#=20Change=20the=20configuration=20to=20use=20given=20server=20cert=20= file,=20and=20reload=0A+#=20the=20server=20so=20that=20the=20= configuration=20takes=20effect.=0A+#=20Takes=20the=20same=20arguments=20= as=20set_server_cert,=20which=20it=20calls=20to=20do=20that=0A+#=20piece=20= of=20the=20work.=0A+sub=20switch_server_cert=0A+{=0A+=09my=20$node=20=3D=20= $_[0];=0A+=09set_server_cert(@_);=0A=20=09$node->restart;=0A=20=09= return;=0A=20}=0A--=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2 Content-Disposition: attachment; filename=v23-0002-NSS-Frontend-Backend-and-build-infrastructure.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v23-0002-NSS-Frontend-Backend-and-build-infrastructure.patch" Content-Transfer-Encoding: quoted-printable =46rom=20b266bc01d09ed8bb600c058a2d6a0e615f364c43=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2028=20Oct=202020=2011:18:42=20+0100=0ASubject:=20[PATCH=20= v23=202/8]=20NSS=20Frontend,=20Backend=20and=20build=20infrastructure=0A=0A= TODO:=0A=09*=20SCRAM=20channel=20binding=20is=20implemented=20but=20= doesn't=20work=0A=09*=20Frontend=20CRL=20configuration=20handling=0A=09*=20= Settle=20on=20a=20required=20version=20in=20autoconf=0A=09*=20Move=20= pg_nss.h=20to=20a=20.c=20file=20for=20both=20frontend=20and=20backend=0A=0A= Daniel=20Gustafsson,=20Andrew=20Dunstan,=20Jacob=20Champion=0A---=0A=20= configure=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20294=20+++-=0A=20= configure.ac=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=2031=20+-=0A=20= .../postgres_fdw/expected/postgres_fdw.out=20=20=20=20|=20=20=20=202=20= +-=0A=20src/backend/libpq/Makefile=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20|=20=20=20=204=20+=0A=20src/backend/libpq/auth.c=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=20=20= 7=20+=0A=20src/backend/libpq/be-secure-nss.c=20=20=20=20=20=20=20=20=20=20= =20=20=20|=201265=20+++++++++++++++++=0A=20src/backend/libpq/be-secure.c=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=20=203=20+=0A=20= src/backend/libpq/hba.c=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20|=20=20=20=202=20+-=0A=20src/backend/utils/misc/guc.c=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=2020=20+-=0A=20= src/common/Makefile=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20=20=20=205=20+=0A=20= src/include/common/pg_nss.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20|=20=20175=20+++=0A=20src/include/libpq/libpq-be.h=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=2015=20+-=0A=20= src/include/libpq/libpq.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20|=20=20=20=203=20+=0A=20src/include/pg_config.h.in=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=20=205=20+-=0A= =20src/include/pg_config_manual.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20|=20=20=20=205=20+-=0A=20src/interfaces/libpq/Makefile=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20|=20=20=20=205=20+=0A=20= src/interfaces/libpq/fe-connect.c=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=20=204=20+=0A=20src/interfaces/libpq/fe-secure-nss.c=20=20=20=20=20= =20=20=20=20=20|=201112=20+++++++++++++++=0A=20= src/interfaces/libpq/fe-secure.c=20=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=20=205=20+-=0A=20src/interfaces/libpq/libpq-fe.h=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20=20=2013=20+-=0A=20= src/interfaces/libpq/libpq-int.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=2020=20+-=0A=20src/tools/msvc/Mkvcbuild.pm=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20|=20=20=2022=20+-=0A=20= src/tools/msvc/Solution.pm=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20|=20=20=2020=20+=0A=20src/tools/msvc/config_default.pl=20=20=20= =20=20=20=20=20=20=20=20=20=20=20|=20=20=20=201=20+=0A=2024=20files=20= changed,=203015=20insertions(+),=2023=20deletions(-)=0A=20create=20mode=20= 100644=20src/backend/libpq/be-secure-nss.c=0A=20create=20mode=20100644=20= src/include/common/pg_nss.h=0A=20create=20mode=20100644=20= src/interfaces/libpq/fe-secure-nss.c=0A=0Adiff=20--git=20a/configure=20= b/configure=0Aindex=20ce9ea36999..143726c79c=20100755=0A---=20= a/configure=0A+++=20b/configure=0A@@=20-654,6=20+654,8=20@@=20UUID_LIBS=0A= =20LDAP_LIBS_BE=0A=20LDAP_LIBS_FE=0A=20with_ssl=0A+NSPR_CONFIG=0A= +NSS_CONFIG=0A=20PTHREAD_CFLAGS=0A=20PTHREAD_LIBS=0A=20PTHREAD_CC=0A@@=20= -1570,7=20+1572,7=20@@=20Optional=20Packages:=0A=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20use=20system=20= time=20zone=20data=20in=20DIR=0A=20=20=20--without-zlib=20=20=20=20=20=20= =20=20=20=20do=20not=20use=20Zlib=0A=20=20=20--with-gnu-ld=20=20=20=20=20= =20=20=20=20=20=20assume=20the=20C=20compiler=20uses=20GNU=20ld=20= [default=3Dno]=0A-=20=20--with-ssl=3DLIB=20=20=20=20=20=20=20=20=20=20= use=20LIB=20for=20SSL/TLS=20support=20(openssl)=0A+=20=20--with-ssl=3DLIB=20= =20=20=20=20=20=20=20=20=20use=20LIB=20for=20SSL/TLS=20support=20= (openssl,=20nss)=0A=20=20=20--with-openssl=20=20=20=20=20=20=20=20=20=20= obsolete=20spelling=20of=20--with-ssl=3Dopenssl=0A=20=0A=20Some=20= influential=20environment=20variables:=0A@@=20-12462,8=20+12464,274=20@@=20= done=0A=20=0A=20$as_echo=20"#define=20USE_OPENSSL=201"=20>>confdefs.h=0A=20= =0A+elif=20test=20"$with_ssl"=20=3D=20nss=20;=20then=0A+=20=20#=20TODO:=20= fallback=20in=20case=20nss-config/nspr-config=20aren't=20found.=0A+=20=20= if=20test=20-z=20"$NSS_CONFIG";=20then=0A+=20=20for=20ac_prog=20in=20= nss-config=0A+do=0A+=20=20#=20Extract=20the=20first=20word=20of=20= "$ac_prog",=20so=20it=20can=20be=20a=20program=20name=20with=20args.=0A= +set=20dummy=20$ac_prog;=20ac_word=3D$2=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20$ac_word"=20>&5=0A= +$as_echo_n=20"checking=20for=20$ac_word...=20"=20>&6;=20}=0A+if=20= ${ac_cv_path_NSS_CONFIG+:}=20false;=20then=20:=0A+=20=20$as_echo_n=20= "(cached)=20"=20>&6=0A+else=0A+=20=20case=20$NSS_CONFIG=20in=0A+=20=20= [\\/]*=20|=20?:[\\/]*)=0A+=20=20ac_cv_path_NSS_CONFIG=3D"$NSS_CONFIG"=20= #=20Let=20the=20user=20override=20the=20test=20with=20a=20path.=0A+=20=20= ;;=0A+=20=20*)=0A+=20=20as_save_IFS=3D$IFS;=20IFS=3D$PATH_SEPARATOR=0A= +for=20as_dir=20in=20$PATH=0A+do=0A+=20=20IFS=3D$as_save_IFS=0A+=20=20= test=20-z=20"$as_dir"=20&&=20as_dir=3D.=0A+=20=20=20=20for=20ac_exec_ext=20= in=20''=20$ac_executable_extensions;=20do=0A+=20=20if=20= as_fn_executable_p=20"$as_dir/$ac_word$ac_exec_ext";=20then=0A+=20=20=20=20= ac_cv_path_NSS_CONFIG=3D"$as_dir/$ac_word$ac_exec_ext"=0A+=20=20=20=20= $as_echo=20"$as_me:${as_lineno-$LINENO}:=20found=20= $as_dir/$ac_word$ac_exec_ext"=20>&5=0A+=20=20=20=20break=202=0A+=20=20fi=0A= +done=0A+=20=20done=0A+IFS=3D$as_save_IFS=0A+=0A+=20=20;;=0A+esac=0A+fi=0A= +NSS_CONFIG=3D$ac_cv_path_NSS_CONFIG=0A+if=20test=20-n=20"$NSS_CONFIG";=20= then=0A+=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20= $NSS_CONFIG"=20>&5=0A+$as_echo=20"$NSS_CONFIG"=20>&6;=20}=0A+else=0A+=20=20= {=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20no"=20>&5=0A= +$as_echo=20"no"=20>&6;=20}=0A+fi=0A+=0A+=0A+=20=20test=20-n=20= "$NSS_CONFIG"=20&&=20break=0A+done=0A+=0A+else=0A+=20=20#=20Report=20the=20= value=20of=20NSS_CONFIG=20in=20configure's=20output=20in=20all=20cases.=0A= +=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20checking=20for=20= NSS_CONFIG"=20>&5=0A+$as_echo_n=20"checking=20for=20NSS_CONFIG...=20"=20= >&6;=20}=0A+=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20= $NSS_CONFIG"=20>&5=0A+$as_echo=20"$NSS_CONFIG"=20>&6;=20}=0A+fi=0A+=0A+=20= =20if=20test=20-z=20"$NSPR_CONFIG";=20then=0A+=20=20for=20ac_prog=20in=20= nspr-config=0A+do=0A+=20=20#=20Extract=20the=20first=20word=20of=20= "$ac_prog",=20so=20it=20can=20be=20a=20program=20name=20with=20args.=0A= +set=20dummy=20$ac_prog;=20ac_word=3D$2=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20$ac_word"=20>&5=0A= +$as_echo_n=20"checking=20for=20$ac_word...=20"=20>&6;=20}=0A+if=20= ${ac_cv_path_NSPR_CONFIG+:}=20false;=20then=20:=0A+=20=20$as_echo_n=20= "(cached)=20"=20>&6=0A+else=0A+=20=20case=20$NSPR_CONFIG=20in=0A+=20=20= [\\/]*=20|=20?:[\\/]*)=0A+=20=20ac_cv_path_NSPR_CONFIG=3D"$NSPR_CONFIG"=20= #=20Let=20the=20user=20override=20the=20test=20with=20a=20path.=0A+=20=20= ;;=0A+=20=20*)=0A+=20=20as_save_IFS=3D$IFS;=20IFS=3D$PATH_SEPARATOR=0A= +for=20as_dir=20in=20$PATH=0A+do=0A+=20=20IFS=3D$as_save_IFS=0A+=20=20= test=20-z=20"$as_dir"=20&&=20as_dir=3D.=0A+=20=20=20=20for=20ac_exec_ext=20= in=20''=20$ac_executable_extensions;=20do=0A+=20=20if=20= as_fn_executable_p=20"$as_dir/$ac_word$ac_exec_ext";=20then=0A+=20=20=20=20= ac_cv_path_NSPR_CONFIG=3D"$as_dir/$ac_word$ac_exec_ext"=0A+=20=20=20=20= $as_echo=20"$as_me:${as_lineno-$LINENO}:=20found=20= $as_dir/$ac_word$ac_exec_ext"=20>&5=0A+=20=20=20=20break=202=0A+=20=20fi=0A= +done=0A+=20=20done=0A+IFS=3D$as_save_IFS=0A+=0A+=20=20;;=0A+esac=0A+fi=0A= +NSPR_CONFIG=3D$ac_cv_path_NSPR_CONFIG=0A+if=20test=20-n=20= "$NSPR_CONFIG";=20then=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20$NSPR_CONFIG"=20>&5=0A= +$as_echo=20"$NSPR_CONFIG"=20>&6;=20}=0A+else=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20no"=20>&5=0A+$as_echo=20"no"=20= >&6;=20}=0A+fi=0A+=0A+=0A+=20=20test=20-n=20"$NSPR_CONFIG"=20&&=20break=0A= +done=0A+=0A+else=0A+=20=20#=20Report=20the=20value=20of=20NSPR_CONFIG=20= in=20configure's=20output=20in=20all=20cases.=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20NSPR_CONFIG"=20>&5=0A= +$as_echo_n=20"checking=20for=20NSPR_CONFIG...=20"=20>&6;=20}=0A+=20=20{=20= $as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20$NSPR_CONFIG"=20>&5=0A= +$as_echo=20"$NSPR_CONFIG"=20>&6;=20}=0A+fi=0A+=0A+=20=20if=20test=20-n=20= "$NSS_CONFIG";=20then=0A+=20=20=20=20NSS_LIBS=3D`$NSS_CONFIG=20--libs`=0A= +=09NSS_CFLAGS=3D`$NSS_CONFIG=20--cflags`=0A+=20=20fi=0A+=20=20if=20test=20= -n=20"$NSPR_CONFIG";=20then=0A+=09NSPR_LIBS=3D`$NSPR_CONFIG=20--libs`=0A= +=09NSPR_CFLAGS=3D`$NSPR_CONFIG=20--cflags`=0A+=20=20fi=0A+=0A+=20=20= LDFLAGS=3D"$LDFLAGS=20$NSS_LIBS=20$NSPR_LIBS"=0A+=20=20CFLAGS=3D"$CFLAGS=20= $NSS_CFLAGS=20$NSPR_CFLAGS"=0A+=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20NSS_InitContext=20in=20= -lnss3"=20>&5=0A+$as_echo_n=20"checking=20for=20NSS_InitContext=20in=20= -lnss3...=20"=20>&6;=20}=0A+if=20${ac_cv_lib_nss3_NSS_InitContext+:}=20= false;=20then=20:=0A+=20=20$as_echo_n=20"(cached)=20"=20>&6=0A+else=0A+=20= =20ac_check_lib_save_LIBS=3D$LIBS=0A+LIBS=3D"-lnss3=20=20$LIBS"=0A+cat=20= confdefs.h=20-=20<<_ACEOF=20>conftest.$ac_ext=0A+/*=20end=20confdefs.h.=20= =20*/=0A+=0A+/*=20Override=20any=20GCC=20internal=20prototype=20to=20= avoid=20an=20error.=0A+=20=20=20Use=20char=20because=20int=20might=20= match=20the=20return=20type=20of=20a=20GCC=0A+=20=20=20builtin=20and=20= then=20its=20argument=20prototype=20would=20still=20apply.=20=20*/=0A= +#ifdef=20__cplusplus=0A+extern=20"C"=0A+#endif=0A+char=20= NSS_InitContext=20();=0A+int=0A+main=20()=0A+{=0A+return=20= NSS_InitContext=20();=0A+=20=20;=0A+=20=20return=200;=0A+}=0A+_ACEOF=0A= +if=20ac_fn_c_try_link=20"$LINENO";=20then=20:=0A+=20=20= ac_cv_lib_nss3_NSS_InitContext=3Dyes=0A+else=0A+=20=20= ac_cv_lib_nss3_NSS_InitContext=3Dno=0A+fi=0A+rm=20-f=20core=20= conftest.err=20conftest.$ac_objext=20\=0A+=20=20=20=20conftest$ac_exeext=20= conftest.$ac_ext=0A+LIBS=3D$ac_check_lib_save_LIBS=0A+fi=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20= $ac_cv_lib_nss3_NSS_InitContext"=20>&5=0A+$as_echo=20= "$ac_cv_lib_nss3_NSS_InitContext"=20>&6;=20}=0A+if=20test=20= "x$ac_cv_lib_nss3_NSS_InitContext"=20=3D=20xyes;=20then=20:=0A+=20=20cat=20= >>confdefs.h=20<<_ACEOF=0A+#define=20HAVE_LIBNSS3=201=0A+_ACEOF=0A+=0A+=20= =20LIBS=3D"-lnss3=20$LIBS"=0A+=0A+else=0A+=20=20as_fn_error=20$?=20= "library=20'nss3'=20is=20required=20for=20NSS"=20"$LINENO"=205=0A+fi=0A+=0A= +=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20checking=20for=20= PR_GetDefaultIOMethods=20in=20-lnspr4"=20>&5=0A+$as_echo_n=20"checking=20= for=20PR_GetDefaultIOMethods=20in=20-lnspr4...=20"=20>&6;=20}=0A+if=20= ${ac_cv_lib_nspr4_PR_GetDefaultIOMethods+:}=20false;=20then=20:=0A+=20=20= $as_echo_n=20"(cached)=20"=20>&6=0A+else=0A+=20=20= ac_check_lib_save_LIBS=3D$LIBS=0A+LIBS=3D"-lnspr4=20=20$LIBS"=0A+cat=20= confdefs.h=20-=20<<_ACEOF=20>conftest.$ac_ext=0A+/*=20end=20confdefs.h.=20= =20*/=0A+=0A+/*=20Override=20any=20GCC=20internal=20prototype=20to=20= avoid=20an=20error.=0A+=20=20=20Use=20char=20because=20int=20might=20= match=20the=20return=20type=20of=20a=20GCC=0A+=20=20=20builtin=20and=20= then=20its=20argument=20prototype=20would=20still=20apply.=20=20*/=0A= +#ifdef=20__cplusplus=0A+extern=20"C"=0A+#endif=0A+char=20= PR_GetDefaultIOMethods=20();=0A+int=0A+main=20()=0A+{=0A+return=20= PR_GetDefaultIOMethods=20();=0A+=20=20;=0A+=20=20return=200;=0A+}=0A= +_ACEOF=0A+if=20ac_fn_c_try_link=20"$LINENO";=20then=20:=0A+=20=20= ac_cv_lib_nspr4_PR_GetDefaultIOMethods=3Dyes=0A+else=0A+=20=20= ac_cv_lib_nspr4_PR_GetDefaultIOMethods=3Dno=0A+fi=0A+rm=20-f=20core=20= conftest.err=20conftest.$ac_objext=20\=0A+=20=20=20=20conftest$ac_exeext=20= conftest.$ac_ext=0A+LIBS=3D$ac_check_lib_save_LIBS=0A+fi=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20= $ac_cv_lib_nspr4_PR_GetDefaultIOMethods"=20>&5=0A+$as_echo=20= "$ac_cv_lib_nspr4_PR_GetDefaultIOMethods"=20>&6;=20}=0A+if=20test=20= "x$ac_cv_lib_nspr4_PR_GetDefaultIOMethods"=20=3D=20xyes;=20then=20:=0A+=20= =20cat=20>>confdefs.h=20<<_ACEOF=0A+#define=20HAVE_LIBNSPR4=201=0A= +_ACEOF=0A+=0A+=20=20LIBS=3D"-lnspr4=20$LIBS"=0A+=0A+else=0A+=20=20= as_fn_error=20$?=20"library=20'nspr4'=20is=20required=20for=20NSS"=20= "$LINENO"=205=0A+fi=0A+=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20= SSL_GetImplementedCiphers=20in=20-lssl3"=20>&5=0A+$as_echo_n=20"checking=20= for=20SSL_GetImplementedCiphers=20in=20-lssl3...=20"=20>&6;=20}=0A+if=20= ${ac_cv_lib_ssl3_SSL_GetImplementedCiphers+:}=20false;=20then=20:=0A+=20=20= $as_echo_n=20"(cached)=20"=20>&6=0A+else=0A+=20=20= ac_check_lib_save_LIBS=3D$LIBS=0A+LIBS=3D"-lssl3=20=20$LIBS"=0A+cat=20= confdefs.h=20-=20<<_ACEOF=20>conftest.$ac_ext=0A+/*=20end=20confdefs.h.=20= =20*/=0A+=0A+/*=20Override=20any=20GCC=20internal=20prototype=20to=20= avoid=20an=20error.=0A+=20=20=20Use=20char=20because=20int=20might=20= match=20the=20return=20type=20of=20a=20GCC=0A+=20=20=20builtin=20and=20= then=20its=20argument=20prototype=20would=20still=20apply.=20=20*/=0A= +#ifdef=20__cplusplus=0A+extern=20"C"=0A+#endif=0A+char=20= SSL_GetImplementedCiphers=20();=0A+int=0A+main=20()=0A+{=0A+return=20= SSL_GetImplementedCiphers=20();=0A+=20=20;=0A+=20=20return=200;=0A+}=0A= +_ACEOF=0A+if=20ac_fn_c_try_link=20"$LINENO";=20then=20:=0A+=20=20= ac_cv_lib_ssl3_SSL_GetImplementedCiphers=3Dyes=0A+else=0A+=20=20= ac_cv_lib_ssl3_SSL_GetImplementedCiphers=3Dno=0A+fi=0A+rm=20-f=20core=20= conftest.err=20conftest.$ac_objext=20\=0A+=20=20=20=20conftest$ac_exeext=20= conftest.$ac_ext=0A+LIBS=3D$ac_check_lib_save_LIBS=0A+fi=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20= $ac_cv_lib_ssl3_SSL_GetImplementedCiphers"=20>&5=0A+$as_echo=20= "$ac_cv_lib_ssl3_SSL_GetImplementedCiphers"=20>&6;=20}=0A+if=20test=20= "x$ac_cv_lib_ssl3_SSL_GetImplementedCiphers"=20=3D=20xyes;=20then=20:=0A= +=20=20cat=20>>confdefs.h=20<<_ACEOF=0A+#define=20HAVE_LIBSSL3=201=0A= +_ACEOF=0A+=0A+=20=20LIBS=3D"-lssl3=20$LIBS"=0A+=0A+else=0A+=20=20= as_fn_error=20$?=20"library=20'ssl3'=20is=20required=20for=20NSS"=20= "$LINENO"=205=0A+fi=0A+=0A+=0A+$as_echo=20"#define=20USE_NSS=201"=20= >>confdefs.h=0A+=0A=20elif=20test=20"$with_ssl"=20!=3D=20no=20;=20then=0A= -=20=20as_fn_error=20$?=20"--with-ssl=20must=20specify=20openssl"=20= "$LINENO"=205=0A+=20=20as_fn_error=20$?=20"--with-ssl=20must=20specify=20= one=20of=20openssl=20or=20nss"=20"$LINENO"=205=0A=20fi=0A=20=0A=20=0A@@=20= -13369,6=20+13637,23=20@@=20else=0A=20fi=0A=20=0A=20=0A+elif=20test=20= "$with_ssl"=20=3D=20nss=20;=20then=0A+=20=20ac_fn_c_check_header_mongrel=20= "$LINENO"=20"nss/ssl.h"=20"ac_cv_header_nss_ssl_h"=20= "$ac_includes_default"=0A+if=20test=20"x$ac_cv_header_nss_ssl_h"=20=3D=20= xyes;=20then=20:=0A+=0A+else=0A+=20=20as_fn_error=20$?=20"header=20file=20= =20is=20required=20for=20NSS"=20"$LINENO"=205=0A+fi=0A+=0A+=0A= +=20=20ac_fn_c_check_header_mongrel=20"$LINENO"=20"nss/nss.h"=20= "ac_cv_header_nss_nss_h"=20"$ac_includes_default"=0A+if=20test=20= "x$ac_cv_header_nss_nss_h"=20=3D=20xyes;=20then=20:=0A+=0A+else=0A+=20=20= as_fn_error=20$?=20"header=20file=20=20is=20required=20for=20= NSS"=20"$LINENO"=205=0A+fi=0A+=0A+=0A=20fi=0A=20=0A=20if=20test=20= "$with_pam"=20=3D=20yes=20;=20then=0A@@=20-18131,6=20+18416,9=20@@=20= $as_echo_n=20"checking=20which=20random=20number=20source=20to=20use...=20= "=20>&6;=20}=0A=20if=20test=20x"$with_ssl"=20=3D=20x"openssl"=20;=20then=0A= =20=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20= OpenSSL"=20>&5=0A=20$as_echo=20"OpenSSL"=20>&6;=20}=0A+elif=20test=20= x"$with_ssl"=20=3D=20x"nss"=20;=20then=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20NSS"=20>&5=0A+$as_echo=20"NSS"=20= >&6;=20}=0A=20elif=20test=20x"$PORTNAME"=20=3D=20x"win32"=20;=20then=0A=20= =20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20Windows=20= native"=20>&5=0A=20$as_echo=20"Windows=20native"=20>&6;=20}=0A@@=20= -18160,7=20+18448,7=20@@=20fi=0A=20=20=20if=20test=20= x"$ac_cv_file__dev_urandom"=20=3D=20x"no"=20;=20then=0A=20=20=20=20=20= as_fn_error=20$?=20"=0A=20no=20source=20of=20strong=20random=20numbers=20= was=20found=0A-PostgreSQL=20can=20use=20OpenSSL,=20native=20Windows=20= API=20or=20/dev/urandom=20as=20a=20source=20of=20random=20numbers."=20= "$LINENO"=205=0A+PostgreSQL=20can=20use=20OpenSSL,=20NSS,=20native=20= Windows=20API=20or=20/dev/urandom=20as=20a=20source=20of=20random=20= numbers."=20"$LINENO"=205=0A=20=20=20fi=0A=20fi=0A=20=0Adiff=20--git=20= a/configure.ac=20b/configure.ac=0Aindex=2007da84d401..59657a6010=20= 100644=0A---=20a/configure.ac=0A+++=20b/configure.ac=0A@@=20-1201,7=20= +1201,7=20@@=20fi=0A=20#=0A=20#=20There=20is=20currently=20only=20one=20= supported=20SSL/TLS=20library:=20OpenSSL.=0A=20#=0A-PGAC_ARG_REQ(with,=20= ssl,=20[LIB],=20[use=20LIB=20for=20SSL/TLS=20support=20(openssl)])=0A= +PGAC_ARG_REQ(with,=20ssl,=20[LIB],=20[use=20LIB=20for=20SSL/TLS=20= support=20(openssl,=20nss)])=0A=20if=20test=20x"$with_ssl"=20=3D=20x""=20= ;=20then=0A=20=20=20with_ssl=3Dno=0A=20fi=0A@@=20-1235,8=20+1235,28=20@@=20= if=20test=20"$with_ssl"=20=3D=20openssl=20;=20then=0A=20=20=20#=20= function=20was=20removed.=0A=20=20=20AC_CHECK_FUNCS([CRYPTO_lock])=0A=20=20= =20AC_DEFINE([USE_OPENSSL],=201,=20[Define=20to=201=20if=20you=20have=20= OpenSSL=20support.])=0A+elif=20test=20"$with_ssl"=20=3D=20nss=20;=20then=0A= +=20=20#=20TODO:=20fallback=20in=20case=20nss-config/nspr-config=20= aren't=20found.=0A+=20=20PGAC_PATH_PROGS(NSS_CONFIG,=20nss-config)=0A+=20= =20PGAC_PATH_PROGS(NSPR_CONFIG,=20nspr-config)=0A+=20=20if=20test=20-n=20= "$NSS_CONFIG";=20then=0A+=20=20=20=20NSS_LIBS=3D`$NSS_CONFIG=20--libs`=0A= +=09NSS_CFLAGS=3D`$NSS_CONFIG=20--cflags`=0A+=20=20fi=0A+=20=20if=20test=20= -n=20"$NSPR_CONFIG";=20then=0A+=09NSPR_LIBS=3D`$NSPR_CONFIG=20--libs`=0A= +=09NSPR_CFLAGS=3D`$NSPR_CONFIG=20--cflags`=0A+=20=20fi=0A+=0A+=20=20= LDFLAGS=3D"$LDFLAGS=20$NSS_LIBS=20$NSPR_LIBS"=0A+=20=20CFLAGS=3D"$CFLAGS=20= $NSS_CFLAGS=20$NSPR_CFLAGS"=0A+=0A+=20=20AC_CHECK_LIB(nss3,=20= NSS_InitContext,=20[],=20[AC_MSG_ERROR([library=20'nss3'=20is=20required=20= for=20NSS])])=0A+=20=20AC_CHECK_LIB(nspr4,=20PR_GetDefaultIOMethods,=20= [],=20[AC_MSG_ERROR([library=20'nspr4'=20is=20required=20for=20NSS])])=0A= +=20=20AC_CHECK_LIB(ssl3,=20SSL_GetImplementedCiphers,=20[],=20= [AC_MSG_ERROR([library=20'ssl3'=20is=20required=20for=20NSS])])=0A+=20=20= AC_DEFINE([USE_NSS],=201,=20[Define=20to=201=20if=20you=20have=20NSS=20= support,])=0A=20elif=20test=20"$with_ssl"=20!=3D=20no=20;=20then=0A-=20=20= AC_MSG_ERROR([--with-ssl=20must=20specify=20openssl])=0A+=20=20= AC_MSG_ERROR([--with-ssl=20must=20specify=20one=20of=20openssl=20or=20= nss])=0A=20fi=0A=20AC_SUBST(with_ssl)=0A=20=0A@@=20-1414,6=20+1434,9=20= @@=20fi=0A=20if=20test=20"$with_ssl"=20=3D=20openssl=20;=20then=0A=20=20=20= AC_CHECK_HEADER(openssl/ssl.h,=20[],=20[AC_MSG_ERROR([header=20file=20= =20is=20required=20for=20OpenSSL])])=0A=20=20=20= AC_CHECK_HEADER(openssl/err.h,=20[],=20[AC_MSG_ERROR([header=20file=20= =20is=20required=20for=20OpenSSL])])=0A+elif=20test=20= "$with_ssl"=20=3D=20nss=20;=20then=0A+=20=20AC_CHECK_HEADER(nss/ssl.h,=20= [],=20[AC_MSG_ERROR([header=20file=20=20is=20required=20for=20= NSS])])=0A+=20=20AC_CHECK_HEADER(nss/nss.h,=20[],=20= [AC_MSG_ERROR([header=20file=20=20is=20required=20for=20= NSS])])=0A=20fi=0A=20=0A=20if=20test=20"$with_pam"=20=3D=20yes=20;=20= then=0A@@=20-2170,6=20+2193,8=20@@=20fi=0A=20AC_MSG_CHECKING([which=20= random=20number=20source=20to=20use])=0A=20if=20test=20x"$with_ssl"=20=3D=20= x"openssl"=20;=20then=0A=20=20=20AC_MSG_RESULT([OpenSSL])=0A+elif=20test=20= x"$with_ssl"=20=3D=20x"nss"=20;=20then=0A+=20=20AC_MSG_RESULT([NSS])=0A=20= elif=20test=20x"$PORTNAME"=20=3D=20x"win32"=20;=20then=0A=20=20=20= AC_MSG_RESULT([Windows=20native])=0A=20else=0A@@=20-2179,7=20+2204,7=20= @@=20else=0A=20=20=20if=20test=20x"$ac_cv_file__dev_urandom"=20=3D=20= x"no"=20;=20then=0A=20=20=20=20=20AC_MSG_ERROR([=0A=20no=20source=20of=20= strong=20random=20numbers=20was=20found=0A-PostgreSQL=20can=20use=20= OpenSSL,=20native=20Windows=20API=20or=20/dev/urandom=20as=20a=20source=20= of=20random=20numbers.])=0A+PostgreSQL=20can=20use=20OpenSSL,=20NSS,=20= native=20Windows=20API=20or=20/dev/urandom=20as=20a=20source=20of=20= random=20numbers.])=0A=20=20=20fi=0A=20fi=0A=20=0Adiff=20--git=20= a/contrib/postgres_fdw/expected/postgres_fdw.out=20= b/contrib/postgres_fdw/expected/postgres_fdw.out=0Aindex=20= 07e06e5bf7..751ce081d7=20100644=0A---=20= a/contrib/postgres_fdw/expected/postgres_fdw.out=0A+++=20= b/contrib/postgres_fdw/expected/postgres_fdw.out=0A@@=20-8939,7=20= +8939,7=20@@=20DO=20$d$=0A=20=20=20=20=20END;=0A=20$d$;=0A=20ERROR:=20=20= invalid=20option=20"password"=0A-HINT:=20=20Valid=20options=20in=20this=20= context=20are:=20service,=20passfile,=20channel_binding,=20= connect_timeout,=20dbname,=20host,=20hostaddr,=20port,=20options,=20= application_name,=20keepalives,=20keepalives_idle,=20= keepalives_interval,=20keepalives_count,=20tcp_user_timeout,=20sslmode,=20= sslcompression,=20sslcert,=20sslkey,=20sslrootcert,=20sslcrl,=20= requirepeer,=20ssl_min_protocol_version,=20ssl_max_protocol_version,=20= gssencmode,=20krbsrvname,=20gsslib,=20target_session_attrs,=20= use_remote_estimate,=20fdw_startup_cost,=20fdw_tuple_cost,=20extensions,=20= updatable,=20fetch_size,=20batch_size=0A+HINT:=20=20Valid=20options=20in=20= this=20context=20are:=20service,=20passfile,=20channel_binding,=20= connect_timeout,=20dbname,=20host,=20hostaddr,=20port,=20options,=20= application_name,=20keepalives,=20keepalives_idle,=20= keepalives_interval,=20keepalives_count,=20tcp_user_timeout,=20sslmode,=20= sslcompression,=20sslcert,=20sslkey,=20sslrootcert,=20sslcrl,=20= requirepeer,=20ssl_min_protocol_version,=20ssl_max_protocol_version,=20= gssencmode,=20krbsrvname,=20gsslib,=20target_session_attrs,=20= cert_database,=20use_remote_estimate,=20fdw_startup_cost,=20= fdw_tuple_cost,=20extensions,=20updatable,=20fetch_size,=20batch_size=0A=20= CONTEXT:=20=20SQL=20statement=20"ALTER=20SERVER=20loopback_nopw=20= OPTIONS=20(ADD=20password=20'dummypw')"=0A=20PL/pgSQL=20function=20= inline_code_block=20line=203=20at=20EXECUTE=0A=20--=20If=20we=20add=20a=20= password=20for=20our=20user=20mapping=20instead,=20we=20should=20get=20a=20= different=0Adiff=20--git=20a/src/backend/libpq/Makefile=20= b/src/backend/libpq/Makefile=0Aindex=208d1d16b0fc..045d2c2f6b=20100644=0A= ---=20a/src/backend/libpq/Makefile=0A+++=20b/src/backend/libpq/Makefile=0A= @@=20-30,6=20+30,10=20@@=20OBJS=20=3D=20\=0A=20=0A=20ifeq=20= ($(with_ssl),openssl)=0A=20OBJS=20+=3D=20be-secure-openssl.o=0A+else=0A= +ifeq=20($(with_ssl),nss)=0A+OBJS=20+=3D=20be-secure-nss.o=0A+endif=0A=20= endif=0A=20=0A=20ifeq=20($(with_gssapi),yes)=0Adiff=20--git=20= a/src/backend/libpq/auth.c=20b/src/backend/libpq/auth.c=0Aindex=20= 545635f41a..09ad2ad063=20100644=0A---=20a/src/backend/libpq/auth.c=0A+++=20= b/src/backend/libpq/auth.c=0A@@=20-2849,7=20+2849,14=20@@=20= CheckCertAuth(Port=20*port)=0A=20{=0A=20=09int=09=09=09= status_check_usermap=20=3D=20STATUS_ERROR;=0A=20=0A+#if=20= defined(USE_OPENSSL)=0A=20=09Assert(port->ssl);=0A+#elif=20= defined(USE_NSS)=0A+=09/*=20TODO:=20should=20we=20rename=20pr_fd=20to=20= ssl,=20to=20keep=20consistency?=20*/=0A+=09Assert(port->pr_fd);=0A+#else=0A= +=09Assert(false);=0A+#endif=0A=20=0A=20=09/*=20Make=20sure=20we=20have=20= received=20a=20username=20in=20the=20certificate=20*/=0A=20=09if=20= (port->peer_cn=20=3D=3D=20NULL=20||=0Adiff=20--git=20= a/src/backend/libpq/be-secure-nss.c=20= b/src/backend/libpq/be-secure-nss.c=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..111b46dea8=0A---=20/dev/null=0A+++=20= b/src/backend/libpq/be-secure-nss.c=0A@@=20-0,0=20+1,1265=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20be-secure-nss.c=0A+=20*=09=20=20functions=20for=20= supporting=20NSS=20as=20a=20TLS=20backend=0A+=20*=0A+=20*=0A+=20*=20= Portions=20Copyright=20(c)=201996-2020,=20PostgreSQL=20Global=20= Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=201994,=20= Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=09=20=20src/backend/libpq/be-secure-nss.c=0A+=20*=0A= +=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#include=20"postgres.h"=0A+=0A+#include=20=0A= +=0A+/*=0A+=20*=20BITS_PER_BYTE=20is=20also=20defined=20in=20the=20NSPR=20= header=20files,=20so=20we=20need=20to=20undef=0A+=20*=20our=20version=20= to=20avoid=20compiler=20warnings=20on=20redefinition.=0A+=20*/=0A= +#define=20pg_BITS_PER_BYTE=20BITS_PER_BYTE=0A+#undef=20BITS_PER_BYTE=0A= +=0A+/*=0A+=20*=20The=20nspr/obsolete/protypes.h=20NSPR=20header=20= typedefs=20uint64=20and=20int64=20with=0A+=20*=20colliding=20definitions=20= from=20ours,=20causing=20a=20much=20expected=20compiler=20error.=0A+=20*=20= Remove=20backwards=20compatibility=20with=20ancient=20NSPR=20versions=20= to=20avoid=20this.=0A+=20*/=0A+#define=20NO_NSPR_10_SUPPORT=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+#include=20=0A+=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+=0A+/*=0A+=20*=20Ensure=20that=20the=20= colliding=20definitions=20match,=20else=20throw=20an=20error.=20In=20= case=0A+=20*=20NSPR=20has=20removed=20the=20definition=20for=20some=20= reason,=20make=20sure=20to=20put=20ours=0A+=20*=20back=20again.=0A+=20*/=0A= +#if=20defined(BITS_PER_BYTE)=0A+#if=20BITS_PER_BYTE=20!=3D=20= pg_BITS_PER_BYTE=0A+#error=20"incompatible=20byte=20widths=20between=20= NSPR=20and=20postgres"=0A+#endif=0A+#else=0A+#define=20BITS_PER_BYTE=20= pg_BITS_PER_BYTE=0A+#endif=0A+#undef=20pg_BITS_PER_BYTE=0A+=0A+#include=20= "common/pg_nss.h"=0A+#include=20"lib/stringinfo.h"=0A+#include=20= "libpq/libpq.h"=0A+#include=20"nodes/pg_list.h"=0A+#include=20= "miscadmin.h"=0A+#include=20"storage/fd.h"=0A+#include=20"utils/guc.h"=0A= +#include=20"utils/memutils.h"=0A+=0A+=0A+/*=20default=20init=20hook=20= can=20be=20overridden=20by=20a=20shared=20library=20*/=0A+static=20void=20= default_nss_tls_init(bool=20isServerStart);=0A+nss_tls_init_hook_type=20= nss_tls_init_hook=20=3D=20default_nss_tls_init;=0A+=0A+static=20= PRDescIdentity=20pr_id;=0A+=0A+static=20PRIOMethods=20pr_iomethods;=0A= +static=20NSSInitContext=20*=20nss_context=20=3D=20NULL;=0A+static=20= SSLVersionRange=20desired_sslver;=0A+=0A+static=20char=20= *external_ssl_passphrase_cb(PK11SlotInfo=20*slot,=20PRBool=20retry,=20= void=20*arg);=0A+static=20bool=20dummy_ssl_passwd_cb_called=20=3D=20= false;=0A+static=20bool=20ssl_is_server_start;=0A+=0A+/*=0A+=20*=20= PR_ImportTCPSocket()=20is=20a=20private=20API,=20but=20very=20widely=20= used,=20as=20it's=20the=0A+=20*=20only=20way=20to=20make=20NSS=20use=20= an=20already=20set=20up=20POSIX=20file=20descriptor=20rather=0A+=20*=20= than=20opening=20one=20itself.=20To=20quote=20the=20NSS=20documentation:=0A= +=20*=0A+=20*=09=09"In=20theory,=20code=20that=20uses=20= PR_ImportTCPSocket=20may=20break=20when=20NSPR's=0A+=20*=09=09= implementation=20changes.=20In=20practice,=20this=20is=20unlikely=20to=20= happen=20because=0A+=20*=09=09NSPR's=20implementation=20has=20been=20= stable=20for=20years=20and=20because=20of=20NSPR's=0A+=20*=09=09strong=20= commitment=20to=20backward=20compatibility."=0A+=20*=0A+=20*=20= https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/P= R_ImportTCPSocket=0A+=20*=0A+=20*=20The=20function=20is=20declared=20in=20= ,=20but=20as=20it=20is=20a=20header=20marked=0A+=20*=20= private=20we=20declare=20it=20here=20rather=20than=20including=20it.=0A+=20= */=0A+NSPR_API(PRFileDesc=20*)=20PR_ImportTCPSocket(int);=0A+=0A+/*=20= NSS=20IO=20layer=20callback=20overrides=20*/=0A+static=20PRInt32=20= pg_ssl_read(PRFileDesc=20*=20fd,=20void=20*buf,=20PRInt32=20amount,=0A+=09= =09=09=09=09=09=20=20=20PRIntn=20flags,=20PRIntervalTime=20timeout);=0A= +static=20PRInt32=20pg_ssl_write(PRFileDesc=20*=20fd,=20const=20void=20= *buf,=20PRInt32=20amount,=0A+=09=09=09=09=09=09=09PRIntn=20flags,=20= PRIntervalTime=20timeout);=0A+static=20PRStatus=20= pg_ssl_close(PRFileDesc=20*=20fd);=0A+/*=20Utility=20functions=20*/=0A= +static=20PRFileDesc=20*=20init_iolayer(Port=20*port);=0A+static=20= uint16=20ssl_protocol_version_to_nss(int=20v,=20const=20char=20= *guc_name);=0A+=0A+static=20char=20*pg_SSLerrmessage(PRErrorCode=20= errcode);=0A+static=20char=20*ssl_protocol_version_to_string(int=20v);=0A= +static=20SECStatus=20pg_cert_auth_handler(void=20*arg,=20PRFileDesc=20*=20= fd,=0A+=09=09=09=09=09=09=09=09=09=20=20PRBool=20checksig,=20PRBool=20= isServer);=0A+static=20SECStatus=20pg_bad_cert_handler(void=20*arg,=20= PRFileDesc=20*=20fd);=0A+static=20char=20= *dummy_ssl_passphrase_cb(PK11SlotInfo=20*=20slot,=20PRBool=20retry,=20= void=20*arg);=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09=09=09=09=20Public=20interface=09=09=09=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +/*=0A+=20*=20be_tls_init=0A+=20*=09=09=09Initialize=20the=20nss=20TLS=20= library=20in=20the=20postmaster=0A+=20*=0A+=20*=20The=20majority=20of=20= the=20setup=20needs=20to=20happen=20in=20be_tls_open_server=20since=20= the=0A+=20*=20NSPR=20initialization=20must=20happen=20after=20the=20= forking=20of=20the=20backend.=20We=20could=0A+=20*=20potentially=20move=20= some=20parts=20in=20under=20!isServerStart,=20but=20so=20far=20this=20is=20= the=0A+=20*=20separation=20chosen.=0A+=20*/=0A+int=0A+be_tls_init(bool=20= isServerStart)=0A+{=0A+=09SECStatus=09status;=0A+=09SSLVersionRange=20= supported_sslver;=0A+=0A+=09status=20=3D=20= SSL_ConfigServerSessionIDCacheWithOpt(0,=200,=20NULL,=201,=200,=200,=20= PR_FALSE);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09= ereport(isServerStart=20?=20FATAL=20:=20LOG,=0A+=09=09=09=09= (errmsg("unable=20to=20connect=20to=20TLS=20connection=20cache:=20%s",=0A= +=09=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20= -1;=0A+=09}=0A+=0A+=09if=20(!ssl_database=20||=20strlen(ssl_database)=20= =3D=3D=200)=0A+=09{=0A+=09=09ereport(isServerStart=20?=20FATAL=20:=20= LOG,=0A+=09=09=09=09(errmsg("no=20certificate=20database=20= specified")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20= We=20check=20for=20the=20desired=20TLS=20version=20range=20here,=20even=20= though=20we=20cannot=0A+=09=20*=20set=20it=20until=20be_open_server=20= such=20that=20we=20can=20be=20compatible=20with=20how=20the=0A+=09=20*=20= OpenSSL=20backend=20reports=20errors=20for=20incompatible=20range=20= configurations.=0A+=09=20*=20Set=20either=20the=20default=20supported=20= TLS=20version=20range,=20or=20the=20configured=0A+=09=20*=20range=20from=20= ssl_min_protocol_version=20and=20ssl_max_protocol=20version.=20In=0A+=09=20= *=20case=20the=20user=20hasn't=20defined=20the=20maximum=20allowed=20= version=20we=20fall=20back=0A+=09=20*=20to=20the=20highest=20version=20= TLS=20that=20the=20library=20supports.=0A+=09=20*/=0A+=09if=20= (SSL_VersionRangeGetSupported(ssl_variant_stream,=20&supported_sslver)=20= !=3D=20SECSuccess)=0A+=09{=0A+=09=09ereport(isServerStart=20?=20FATAL=20= :=20LOG,=0A+=09=09=09=09(errmsg("unable=20to=20get=20default=20protocol=20= support=20from=20NSS")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09/*=0A+=09= =20*=20Set=20the=20fallback=20versions=20for=20the=20TLS=20protocol=20= version=20range=20to=20a=0A+=09=20*=20combination=20of=20our=20minimal=20= requirement=20and=20the=20library=20maximum.=20Error=0A+=09=20*=20= messages=20should=20be=20kept=20identical=20to=20those=20in=20= be-secure-openssl.c=20to=0A+=09=20*=20make=20translations=20easier.=0A+=09= =20*/=0A+=09desired_sslver.min=20=3D=20SSL_LIBRARY_VERSION_TLS_1_0;=0A+=09= desired_sslver.max=20=3D=20supported_sslver.max;=0A+=0A+=09if=20= (ssl_min_protocol_version)=0A+=09{=0A+=09=09int=09=09=09ver=20=3D=20= ssl_protocol_version_to_nss(ssl_min_protocol_version,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=20=20"ssl_min_protocol_version");=0A+=0A+=09=09if=20= (ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09ereport(isServerStart=20?=20= FATAL=20:=20LOG,=0A+=09=09=09=09=09(errmsg("\"%s\"=20setting=20\"%s\"=20= not=20supported=20by=20this=20build",=0A+=09=09=09=09=09=09=09= "ssl_min_protocol_version",=0A+=09=09=09=09=09=09=09= GetConfigOption("ssl_min_protocol_version",=0A+=09=09=09=09=09=09=09=09=09= =09=09false,=20false))));=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=0A+=09=09= if=20(ver=20>=200)=0A+=09=09=09desired_sslver.min=20=3D=20ver;=0A+=09}=0A= +=0A+=09if=20(ssl_max_protocol_version)=0A+=09{=0A+=09=09int=09=09=09ver=20= =3D=20ssl_protocol_version_to_nss(ssl_max_protocol_version,=0A+=09=09=09=09= =09=09=09=09=09=09=09=09=09=20=20"ssl_max_protocol_version");=0A+=0A+=09=09= if=20(ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09ereport(isServerStart=20= ?=20FATAL=20:=20LOG,=0A+=09=09=09=09=09(errmsg("\"%s\"=20setting=20= \"%s\"=20not=20supported=20by=20this=20build",=0A+=09=09=09=09=09=09=09= "ssl_max_protocol_version",=0A+=09=09=09=09=09=09=09= GetConfigOption("ssl_max_protocol_version",=0A+=09=09=09=09=09=09=09=09=09= =09=09false,=20false))));=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=09=09= if=20(ver=20>=200)=0A+=09=09=09desired_sslver.max=20=3D=20ver;=0A+=0A+=09= =09if=20(ver=20<=20desired_sslver.min)=0A+=09=09{=0A+=09=09=09= ereport(isServerStart=20?=20FATAL=20:=20LOG,=0A+=09=09=09=09=09= (errmsg("could=20not=20set=20SSL=20protocol=20version=20range"),=0A+=09=09= =09=09=09=20errdetail("\"%s\"=20cannot=20be=20higher=20than=20\"%s\"",=0A= +=09=09=09=09=09=09=09=20=20=20"ssl_min_protocol_version",=0A+=09=09=09=09= =09=09=09=20=20=20"ssl_max_protocol_version")));=0A+=09=09=09return=20= -1;=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Set=20the=20passphrase=20= callback=20which=20will=20be=20used=20both=20to=20obtain=20the=0A+=09=20= *=20passphrase=20from=20the=20user,=20as=20well=20as=20by=20NSS=20to=20= obtain=20the=20phrase=0A+=09=20*=20repeatedly.=0A+=09=20*/=0A+=09= ssl_is_server_start=20=3D=20isServerStart;=0A+=09(*nss_tls_init_hook)=20= (isServerStart);=0A+=0A+=09return=200;=0A+}=0A+=0A+int=0A= +be_tls_open_server(Port=20*port)=0A+{=0A+=09SECStatus=09status;=0A+=09= PRFileDesc=20*model;=0A+=09PRFileDesc=20*pr_fd;=0A+=09PRFileDesc=20= *layer;=0A+=09CERTCertificate=20*server_cert;=0A+=09SECKEYPrivateKey=20= *private_key;=0A+=09CERTSignedCrl=20*crl;=0A+=09SECItem=09=09crlname;=0A= +=09char=09=20=20=20*cert_database;=0A+=09NSSInitParameters=20params;=0A= +=0A+=09/*=0A+=09=20*=20The=20NSPR=20documentation=20states=20that=20= runtime=20initialization=20via=20PR_Init=0A+=09=20*=20is=20no=20longer=20= required,=20as=20the=20first=20caller=20into=20NSPR=20will=20perform=20= the=0A+=09=20*=20initialization=20implicitly.=20The=20documentation=20= doesn't=20however=20clarify=0A+=09=20*=20from=20which=20version=20this=20= is=20holds=20true,=20so=20let's=20perform=20the=20potentially=0A+=09=20*=20= superfluous=20initialization=20anyways=20to=20avoid=20crashing=20on=20= older=20versions=0A+=09=20*=20of=20NSPR,=20as=20there=20is=20no=20= difference=20in=20overhead.=20=20The=20NSS=20documentation=0A+=09=20*=20= still=20states=20that=20PR_Init=20must=20be=20called=20in=20some=20way=20= (implicitly=20or=0A+=09=20*=20explicitly).=0A+=09=20*=0A+=09=20*=20The=20= below=20parameters=20are=20what=20the=20implicit=20initialization=20= would've=20done=0A+=09=20*=20for=20us,=20and=20should=20work=20even=20= for=20older=20versions=20where=20it=20might=20not=20be=0A+=09=20*=20done=20= automatically.=20The=20last=20parameter,=20maxPTDs,=20is=20set=20to=20= various=0A+=09=20*=20values=20in=20other=20codebases,=20but=20has=20been=20= unused=20since=20NSPR=202.1=20which=20was=0A+=09=20*=20released=20= sometime=20in=201998.=20In=20current=20versions=20of=20NSPR=20all=20= parameters=0A+=09=20*=20are=20ignored.=0A+=09=20*/=0A+=09= PR_Init(PR_USER_THREAD,=20PR_PRIORITY_NORMAL,=200=20/*=20maxPTDs=20*/=20= );=0A+=0A+=09/*=0A+=09=20*=20The=20certificate=20path=20(configdir)=20= must=20contain=20a=20valid=20NSS=20database.=20If=0A+=09=20*=20the=20= certificate=20path=20isn't=20a=20valid=20directory,=20NSS=20will=20fall=20= back=20on=20the=0A+=09=20*=20system=20certificate=20database.=20If=20the=20= certificate=20path=20is=20a=20directory=20but=0A+=09=20*=20is=20empty=20= then=20the=20initialization=20will=20fail.=20On=20the=20client=20side=20= this=20can=0A+=09=20*=20be=20allowed=20for=20any=20sslmode=20but=20the=20= verify-xxx=20ones.=0A+=09=20*=20= https://bugzilla.redhat.com/show_bug.cgi?id=3D728562=20For=20the=20= server=20side=0A+=09=20*=20we=20won't=20allow=20this=20to=20fail=20= however,=20as=20we=20require=20the=20certificate=20and=0A+=09=20*=20key=20= to=20exist.=0A+=09=20*=0A+=09=20*=20The=20original=20design=20of=20NSS=20= was=20for=20a=20single=20application=20to=20use=20a=20single=0A+=09=20*=20= copy=20of=20it,=20initialized=20with=20NSS_Initialize()=20which=20isn't=20= returning=20any=0A+=09=20*=20handle=20with=20which=20to=20refer=20to=20= NSS.=20NSS=20initialization=20and=20shutdown=20are=0A+=09=20*=20global=20= for=20the=20application,=20so=20a=20shutdown=20in=20another=20NSS=20= enabled=0A+=09=20*=20library=20would=20cause=20NSS=20to=20be=20stopped=20= for=20libpq=20as=20well.=20=20The=20fix=20has=0A+=09=20*=20been=20to=20= introduce=20NSS_InitContext=20which=20returns=20a=20context=20handle=20= to=0A+=09=20*=20pass=20to=20NSS_ShutdownContext.=20=20NSS_InitContext=20= was=20introduced=20in=20NSS=0A+=09=20*=203.12,=20but=20the=20use=20of=20= it=20is=20not=20very=20well=20documented.=0A+=09=20*=20= https://bugzilla.redhat.com/show_bug.cgi?id=3D738456=0A+=09=20*=0A+=09=20= *=20The=20InitParameters=20struct=20passed=20can=20be=20used=20to=20= override=20internal=0A+=09=20*=20values=20in=20NSS,=20but=20the=20usage=20= is=20not=20documented=20at=20all.=20When=20using=0A+=09=20*=20NSS_Init=20= initializations,=20the=20values=20are=20instead=20set=20via=20= PK11_Configure=0A+=09=20*=20calls=20so=20the=20PK11_Configure=20= documentation=20can=20be=20used=20to=20glean=20some=0A+=09=20*=20details=20= on=20these.=0A+=09=20*=0A+=09=20*=20= https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/PKCS11/Modul= e_Specs=0A+=09=20*/=0A+=09memset(¶ms,=20'\0',=20sizeof(params));=0A+=09= params.length=20=3D=20sizeof(params);=0A+=0A+=09if=20(!ssl_database=20||=20= strlen(ssl_database)=20=3D=3D=200)=0A+=09=09ereport(FATAL,=0A+=09=09=09=09= (errmsg("no=20certificate=20database=20specified")));=0A+=0A+=09= cert_database=20=3D=20psprintf("sql:%s",=20ssl_database);=0A+=09= nss_context=20=3D=20NSS_InitContext(cert_database,=20"",=20"",=20"",=0A+=09= =09=09=09=09=09=09=09=20=20¶ms,=0A+=09=09=09=09=09=09=09=09=20=20= NSS_INIT_READONLY=20|=20NSS_INIT_PK11RELOAD);=0A+=09= pfree(cert_database);=0A+=0A+=09if=20(!nss_context)=0A+=09=09= ereport(FATAL,=0A+=09=09=09=09(errmsg("unable=20to=20read=20certificate=20= database=20\"%s\":=20%s",=0A+=09=09=09=09=09=09ssl_database,=20= pg_SSLerrmessage(PR_GetError()))));=0A+=0A+=09/*=0A+=09=20*=20Import=20= the=20already=20opened=20socket=20as=20we=20don't=20want=20to=20use=20= NSPR=20functions=0A+=09=20*=20for=20opening=20the=20network=20socket=20= due=20to=20how=20the=20PostgreSQL=20protocol=20works=0A+=09=20*=20with=20= TLS=20connections.=20This=20function=20is=20not=20part=20of=20the=20NSPR=20= public=20API,=0A+=09=20*=20see=20the=20comment=20at=20the=20top=20of=20= the=20file=20for=20the=20rationale=20of=20still=20using=0A+=09=20*=20it.=0A= +=09=20*/=0A+=09pr_fd=20=3D=20PR_ImportTCPSocket(port->sock);=0A+=09if=20= (!pr_fd)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09= (errmsg("unable=20to=20connect=20to=20socket")));=0A+=09=09return=20-1;=0A= +=09}=0A+=0A+=09/*=0A+=09=20*=20Most=20of=20the=20documentation=20= available,=20and=20implementations=20of,=20NSS/NSPR=0A+=09=20*=20use=20= the=20PR_NewTCPSocket()=20function=20here,=20which=20has=20the=20= drawback=20that=20it=0A+=09=20*=20can=20only=20create=20IPv4=20sockets.=20= Instead=20use=20PR_OpenTCPSocket()=20which=0A+=09=20*=20copes=20with=20= IPv6=20as=20well.=0A+=09=20*=0A+=09=20*=20We=20use=20a=20model=20= filedescriptor=20here=20which=20is=20a=20construct=20in=20NSPR/NSS=20in=0A= +=09=20*=20order=20to=20create=20a=20configuration=20template=20for=20= sockets=20which=20can=20then=20be=0A+=09=20*=20applied=20to=20new=20= sockets=20created.=20This=20makes=20more=20sense=20in=20a=20server=20= which=0A+=09=20*=20accepts=20multiple=20connections=20and=20want=20to=20= perform=20the=20boilerplate=20just=0A+=09=20*=20once,=20but=20it=20does=20= provide=20a=20nice=20abstraction=20here=20as=20well=20in=20that=20we=0A+=09= =20*=20can=20error=20out=20early=20without=20having=20performed=20any=20= operation=20on=20the=20real=0A+=09=20*=20socket.=0A+=09=20*/=0A+=09model=20= =3D=20PR_OpenTCPSocket(port->laddr.addr.ss_family);=0A+=09if=20(!model)=0A= +=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= open=20socket")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20= Convert=20the=20NSPR=20socket=20to=20an=20SSL=20socket.=20Ensuring=20the=20= success=20of=20this=0A+=09=20*=20operation=20is=20critical=20as=20NSS=20= SSL_*=20functions=20may=20return=20SECSuccess=20on=0A+=09=20*=20the=20= socket=20even=20though=20SSL=20hasn't=20been=20enabled,=20which=20= introduce=20a=20risk=0A+=09=20*=20of=20silent=20downgrades.=0A+=09=20*/=0A= +=09model=20=3D=20SSL_ImportFD(NULL,=20model);=0A+=09if=20(!model)=0A+=09= {=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= enable=20TLS=20on=20socket")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09= /*=0A+=09=20*=20Configure=20basic=20settings=20for=20the=20connection=20= over=20the=20SSL=20socket=20in=0A+=09=20*=20order=20to=20set=20it=20up=20= as=20a=20server.=0A+=09=20*/=0A+=09if=20(SSL_OptionSet(model,=20= SSL_SECURITY,=20PR_TRUE)=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09= ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20configure=20TLS=20= connection")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09if=20= (SSL_OptionSet(model,=20SSL_HANDSHAKE_AS_SERVER,=20PR_TRUE)=20!=3D=20= SECSuccess=20||=0A+=09=09SSL_OptionSet(model,=20SSL_HANDSHAKE_AS_CLIENT,=20= PR_FALSE)=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09= =09=09=09(errmsg("unable=20to=20configure=20TLS=20connection=20as=20= server")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20= SSLv2=20is=20disabled=20by=20default,=20and=20SSLv3=20will=20be=20= excluded=20from=20the=20range=0A+=09=20*=20of=20allowed=20protocols=20= further=20down.=20Since=20we=20really=20don't=20want=20these=20to=0A+=09=20= *=20ever=20be=20enabled,=20let's=20use=20belts=20and=20suspenders=20and=20= explicitly=20turn=0A+=09=20*=20them=20off=20as=20well.=0A+=09=20*/=0A+=09= SSL_OptionSet(model,=20SSL_ENABLE_SSL2,=20PR_FALSE);=0A+=09= SSL_OptionSet(model,=20SSL_ENABLE_SSL3,=20PR_FALSE);=0A+=0A+#ifdef=20= SSL_CBC_RANDOM_IV=0A+=0A+=09/*=0A+=09=20*=20Enable=20protection=20= against=20the=20BEAST=20attack=20in=20case=20the=20NSS=20server=20has=0A= +=09=20*=20support=20for=20that.=20While=20SSLv3=20is=20disabled,=20we=20= may=20still=20allow=20TLSv1=0A+=09=20*=20which=20is=20affected.=20The=20= option=20isn't=20documented=20as=20an=20SSL=20option,=20but=20as=0A+=09=20= *=20an=20NSS=20environment=20variable.=0A+=09=20*/=0A+=09= SSL_OptionSet(model,=20SSL_CBC_RANDOM_IV,=20PR_TRUE);=0A+#endif=0A+=0A+=09= /*=0A+=09=20*=20Configure=20the=20allowed=20ciphers.=20If=20there=20are=20= no=20user=20preferred=20suites,=0A+=09=20*=20set=20the=20domestic=20= policy.=0A+=09=20*=0A+=09=20*=20Historically=20there=20were=20different=20= cipher=20policies=20based=20on=20export=20(and=0A+=09=20*=20import)=20= restrictions:=20Domestic,=20Export=20and=20France.=20These=20are=20since=20= long=0A+=09=20*=20removed=20with=20all=20ciphers=20being=20enabled=20by=20= default.=20Due=20to=20backwards=0A+=09=20*=20compatibility,=20the=20old=20= API=20is=20still=20used=20even=20though=20all=20three=20policies=0A+=09=20= *=20now=20do=20the=20same=20thing.=0A+=09=20*=0A+=09=20*=20If=20= SSLCipherSuites=20define=20a=20policy=20of=20the=20user,=20we=20set=20= that=20rather=20than=0A+=09=20*=20enabling=20all=20ciphers=20via=20= NSS_SetDomesticPolicy.=0A+=09=20*=0A+=09=20*=20TODO:=20while=20this=20= code=20works,=20the=20set=20of=20ciphers=20which=20can=20be=20set=20and=0A= +=09=20*=20still=20end=20up=20with=20a=20working=20socket=20is=20= woefully=20underdocumented=20for=0A+=09=20*=20anything=20more=20recent=20= than=20SSLv3=20(the=20code=20for=20TLS=20actually=20calls=20ssl3=0A+=09=20= *=20functions=20under=20the=20hood=20for=20SSL_CipherPrefSet),=20so=20= it's=20unclear=20if=0A+=09=20*=20this=20is=20helpful=20or=20not.=20Using=20= the=20policies=20works,=20but=20may=20be=20too=0A+=09=20*=20coarsely=20= grained.=0A+=09=20*=0A+=09=20*=20Another=20TODO:=20The=20= SSL_ImplementedCiphers=20table=20returned=20with=20calling=0A+=09=20*=20= SSL_GetImplementedCiphers=20is=20sorted=20in=20server=20preference=20= order.=20Sorting=0A+=09=20*=20SSLCipherSuites=20according=20to=20the=20= order=20of=20the=20ciphers=20therein=20could=20be=0A+=09=20*=20a=20way=20= to=20implement=20ssl_prefer_server_ciphers=20-=20if=20we=20at=20all=20= want=20to=20use=0A+=09=20*=20cipher=20selection=20for=20NSS=20like=20how=20= we=20do=20it=20for=20OpenSSL=20that=20is.=0A+=09=20*/=0A+=0A+=09/*=0A+=09= =20*=20If=20no=20ciphers=20are=20specified,=20enable=20them=20all.=0A+=09= =20*/=0A+=09if=20(!SSLCipherSuites=20||=20strlen(SSLCipherSuites)=20=3D=3D= =200)=0A+=09{=0A+=09=09status=20=3D=20NSS_SetDomesticPolicy();=0A+=09=09= if=20(status=20!=3D=20SECSuccess)=0A+=09=09{=0A+=09=09=09= ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("unable=20to=20set=20cipher=20= policy:=20%s",=0A+=09=09=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09=09=09return=20-1;=0A+=09=09}=0A= +=09}=0A+=09else=0A+=09{=0A+=09=09char=09=20=20=20*ciphers,=0A+=09=09=09=09= =20=20=20*c;=0A+=0A+=09=09char=09=20=20=20*sep=20=3D=20":;,=20";=0A+=09=09= PRUint16=09ciphercode;=0A+=09=09const=09=09PRUint16=20*nss_ciphers;=0A+=0A= +=09=09/*=0A+=09=09=20*=20If=20the=20user=20has=20specified=20a=20set=20= of=20preferred=20cipher=20suites=20we=20start=0A+=09=09=20*=20by=20= turning=20off=20all=20the=20existing=20suites=20to=20avoid=20the=20risk=20= of=20down-=0A+=09=09=20*=20grades=20to=20a=20weaker=20cipher=20than=20= expected.=0A+=09=09=20*/=0A+=09=09nss_ciphers=20=3D=20= SSL_GetImplementedCiphers();=0A+=09=09for=20(int=20i=20=3D=200;=20i=20<=20= SSL_GetNumImplementedCiphers();=20i++)=0A+=09=09=09= SSL_CipherPrefSet(model,=20nss_ciphers[i],=20PR_FALSE);=0A+=0A+=09=09= ciphers=20=3D=20pstrdup(SSLCipherSuites);=0A+=0A+=09=09for=20(c=20=3D=20= strtok(ciphers,=20sep);=20c;=20c=20=3D=20strtok(NULL,=20sep))=0A+=09=09{=0A= +=09=09=09ciphercode=20=3D=20pg_find_cipher(c);=0A+=09=09=09if=20= (ciphercode=20!=3D=20INVALID_CIPHER)=0A+=09=09=09{=0A+=09=09=09=09status=20= =3D=20SSL_CipherPrefSet(model,=20ciphercode,=20PR_TRUE);=0A+=09=09=09=09= if=20(status=20!=3D=20SECSuccess)=0A+=09=09=09=09{=0A+=09=09=09=09=09= ereport(COMMERROR,=0A+=09=09=09=09=09=09=09(errmsg("invalid=20= cipher-suite=20specified:=20%s",=20c)));=0A+=09=09=09=09=09return=20-1;=0A= +=09=09=09=09}=0A+=09=09=09}=0A+=09=09}=0A+=0A+=09=09pfree(ciphers);=0A+=09= }=0A+=0A+=09if=20(SSL_VersionRangeSet(model,=20&desired_sslver)=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09= (errmsg("unable=20to=20set=20requested=20SSL=20protocol=20version=20= range")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Set=20= up=20the=20custom=20IO=20layer.=0A+=09=20*/=0A+=09layer=20=3D=20= init_iolayer(port);=0A+=09if=20(!layer)=0A+=09=09return=20-1;=0A+=0A+=09= if=20(PR_PushIOLayer(pr_fd,=20PR_TOP_IO_LAYER,=20layer)=20!=3D=20= PR_SUCCESS)=0A+=09{=0A+=09=09PR_Close(layer);=0A+=09=09= ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20push=20IO=20= layer")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09server_cert=20=3D=20= PK11_FindCertFromNickname(ssl_cert_file,=20(void=20*)=20port);=0A+=09if=20= (!server_cert)=0A+=09{=0A+=09=09if=20(dummy_ssl_passwd_cb_called)=0A+=09=09= {=0A+=09=09=09ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("unable=20to=20= load=20certificate=20for=20\"%s\":=20%s",=0A+=09=09=09=09=09=09=09= ssl_cert_file,=20pg_SSLerrmessage(PR_GetError())),=0A+=09=09=09=09=09=20= errhint("The=20certificate=20requires=20a=20password.")));=0A+=09=09=09= return=20-1;=0A+=09=09}=0A+=09=09else=0A+=09=09{=0A+=09=09=09= ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("unable=20to=20find=20= certificate=20for=20\"%s\":=20%s",=0A+=09=09=09=09=09=09=09= ssl_cert_file,=20pg_SSLerrmessage(PR_GetError()))));=0A+=09=09=09return=20= -1;=0A+=09=09}=0A+=09}=0A+=0A+=09private_key=20=3D=20= PK11_FindKeyByAnyCert(server_cert,=20(void=20*)=20port);=0A+=09if=20= (!private_key)=0A+=09{=0A+=09=09if=20(dummy_ssl_passwd_cb_called)=0A+=09=09= {=0A+=09=09=09ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("unable=20to=20= load=20private=20key=20for=20\"%s\":=20%s",=0A+=09=09=09=09=09=09=09= ssl_cert_file,=20pg_SSLerrmessage(PR_GetError())),=0A+=09=09=09=09=09=20= errhint("The=20private=20key=20requires=20a=20password.")));=0A+=09=09=09= return=20-1;=0A+=09=09}=0A+=09=09else=0A+=09=09{=0A+=09=09=09= ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("unable=20to=20find=20= private=20key=20for=20\"%s\":=20%s",=0A+=09=09=09=09=09=09=09= ssl_cert_file,=20pg_SSLerrmessage(PR_GetError()))));=0A+=09=09=09return=20= -1;=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20NSS=20doesn't=20use=20= CRL=20files=20on=20disk,=20so=20we=20use=20the=20ssl_crl_file=20guc=20to=0A= +=09=20*=20contain=20the=20CRL=20nickname=20for=20the=20current=20server=20= certificate=20in=20the=20NSS=0A+=09=20*=20certificate=20database.=20The=20= main=20difference=20from=20the=20OpenSSL=20backend=20is=0A+=09=20*=20= that=20NSS=20will=20use=20the=20CRL=20regardless,=20but=20being=20able=20= to=20make=20sure=20the=0A+=09=20*=20CRL=20is=20loaded=20seems=20like=20a=20= good=20feature.=0A+=09=20*/=0A+=09if=20(ssl_crl_file[0])=0A+=09{=0A+=09=09= SECITEM_CopyItem(NULL,=20&crlname,=20&server_cert->derSubject);=0A+=09=09= crl=20=3D=20SEC_FindCrlByName(CERT_GetDefaultCertDB(),=20&crlname,=20= SEC_CRL_TYPE);=0A+=09=09if=20(!crl)=0A+=09=09{=0A+=09=09=09= ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("specified=20CRL=20not=20= found=20in=20database")));=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=09=09= SEC_DestroyCrl(crl);=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Finally=20we=20= must=20configure=20the=20socket=20for=20being=20a=20server=20by=20= setting=20the=0A+=09=20*=20certificate=20and=20key.=20The=20NULL=20= parameter=20is=20an=20SSLExtraServerCertData=0A+=09=20*=20pointer=20with=20= the=20final=20parameter=20being=20the=20size=20of=20the=20extra=20server=0A= +=09=20*=20cert=20data=20structure=20pointed=20to.=20This=20is=20= typically=20only=20used=20for=0A+=09=20*=20credential=20delegation.=0A+=09= =20*/=0A+=09status=20=3D=20SSL_ConfigServerCert(model,=20server_cert,=20= private_key,=20NULL,=200);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09= {=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= configure=20server=20for=20TLS=20server=20connections:=20%s",=0A+=09=09=09= =09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20-1;=0A+=09= }=0A+=0A+=09ssl_loaded_verify_locations=20=3D=20true;=0A+=0A+=09/*=0A+=09= =20*=20At=20this=20point,=20we=20no=20longer=20have=20use=20for=20the=20= certificate=20and=20private=0A+=09=20*=20key=20as=20they=20have=20been=20= copied=20into=20the=20context=20by=20NSS.=20Destroy=20our=0A+=09=20*=20= copies=20explicitly=20to=20clean=20out=20the=20memory=20as=20best=20we=20= can.=0A+=09=20*/=0A+=09CERT_DestroyCertificate(server_cert);=0A+=09= SECKEY_DestroyPrivateKey(private_key);=0A+=0A+=09status=20=3D=20= SSL_AuthCertificateHook(model,=20pg_cert_auth_handler,=20(void=20*)=20= port);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09= ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20install=20= authcert=20hook:=20%s",=0A+=09=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20-1;=0A+=09}=0A+=09= SSL_BadCertHook(model,=20pg_bad_cert_handler,=20(void=20*)=20port);=0A+=09= SSL_OptionSet(model,=20SSL_REQUEST_CERTIFICATE,=20PR_TRUE);=0A+=09= SSL_OptionSet(model,=20SSL_REQUIRE_CERTIFICATE,=20PR_FALSE);=0A+=0A+=09= port->pr_fd=20=3D=20SSL_ImportFD(model,=20pr_fd);=0A+=09if=20= (!port->pr_fd)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09= (errmsg("unable=20to=20initialize")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A= +=09PR_Close(model);=0A+=0A+=09/*=0A+=09=20*=20Force=20a=20handshake=20= on=20the=20next=20I/O=20request,=20the=20second=20parameter=20means=0A+=09= =20*=20that=20we=20are=20a=20server,=20PR_FALSE=20would=20indicate=20= being=20a=20client.=20NSPR=0A+=09=20*=20requires=20us=20to=20call=20= SSL_ResetHandshake=20since=20we=20imported=20an=20already=0A+=09=20*=20= established=20socket.=0A+=09=20*/=0A+=09status=20=3D=20= SSL_ResetHandshake(port->pr_fd,=20PR_TRUE);=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09= (errmsg("unable=20to=20initiate=20handshake:=20%s",=0A+=09=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20-1;=0A+=09}=0A+=09= status=20=3D=20SSL_ForceHandshake(port->pr_fd);=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09= (errmsg("unable=20to=20handshake:=20%s",=0A+=09=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20-1;=0A+=09}=0A+=0A= +=09port->ssl_in_use=20=3D=20true;=0A+=09return=200;=0A+}=0A+=0A+ssize_t=0A= +be_tls_read(Port=20*port,=20void=20*ptr,=20size_t=20len,=20int=20= *waitfor)=0A+{=0A+=09ssize_t=09=09n_read;=0A+=09PRErrorCode=20err;=0A+=0A= +=09n_read=20=3D=20PR_Read(port->pr_fd,=20ptr,=20len);=0A+=0A+=09if=20= (n_read=20<=200)=0A+=09{=0A+=09=09err=20=3D=20PR_GetError();=0A+=0A+=09=09= if=20(err=20=3D=3D=20PR_WOULD_BLOCK_ERROR)=0A+=09=09{=0A+=09=09=09= *waitfor=20=3D=20WL_SOCKET_READABLE;=0A+=09=09=09errno=20=3D=20= EWOULDBLOCK;=0A+=09=09}=0A+=09=09else=0A+=09=09=09errno=20=3D=20= ECONNRESET;=0A+=09}=0A+=0A+=09return=20n_read;=0A+}=0A+=0A+ssize_t=0A= +be_tls_write(Port=20*port,=20void=20*ptr,=20size_t=20len,=20int=20= *waitfor)=0A+{=0A+=09ssize_t=09=09n_write;=0A+=09PRErrorCode=20err;=0A+=09= PRIntn=09=09flags=20=3D=200;=0A+=0A+=09/*=0A+=09=20*=20The=20flags=20= parameter=20to=20PR_Send=20is=20no=20longer=20used=20and=20is,=20= according=20to=0A+=09=20*=20the=20documentation,=20required=20to=20be=20= zero.=0A+=09=20*/=0A+=09n_write=20=3D=20PR_Send(port->pr_fd,=20ptr,=20= len,=20flags,=20PR_INTERVAL_NO_WAIT);=0A+=0A+=09if=20(n_write=20<=200)=0A= +=09{=0A+=09=09err=20=3D=20PR_GetError();=0A+=0A+=09=09if=20(err=20=3D=3D=20= PR_WOULD_BLOCK_ERROR)=0A+=09=09{=0A+=09=09=09*waitfor=20=3D=20= WL_SOCKET_WRITEABLE;=0A+=09=09=09errno=20=3D=20EWOULDBLOCK;=0A+=09=09}=0A= +=09=09else=0A+=09=09=09errno=20=3D=20ECONNRESET;=0A+=09}=0A+=0A+=09= return=20n_write;=0A+}=0A+=0A+void=0A+be_tls_close(Port=20*port)=0A+{=0A= +=09if=20(!port)=0A+=09=09return;=0A+=0A+=09if=20(port->peer_cn)=0A+=09{=0A= +=09=09SSL_InvalidateSession(port->pr_fd);=0A+=09=09= pfree(port->peer_cn);=0A+=09=09port->peer_cn=20=3D=20NULL;=0A+=09}=0A+=0A= +=09PR_Close(port->pr_fd);=0A+=09port->pr_fd=20=3D=20NULL;=0A+=09= port->ssl_in_use=20=3D=20false;=0A+=0A+=09if=20(nss_context)=0A+=09{=0A+=09= =09NSS_ShutdownContext(nss_context);=0A+=09=09nss_context=20=3D=20NULL;=0A= +=09}=0A+}=0A+=0A+void=0A+be_tls_destroy(void)=0A+{=0A+=09/*=0A+=09=20*=20= It=20reads=20a=20bit=20odd=20to=20clear=20a=20session=20cache=20when=20= we=20are=20destroying=20the=0A+=09=20*=20context=20altogether,=20but=20= if=20the=20session=20cache=20isn't=20cleared=20before=0A+=09=20*=20= shutting=20down=20the=20context=20it=20will=20fail=20with=20= SEC_ERROR_BUSY.=0A+=09=20*/=0A+=09SSL_ClearSessionCache();=0A+}=0A+=0A= +int=0A+be_tls_get_cipher_bits(Port=20*port)=0A+{=0A+=09SECStatus=09= status;=0A+=09SSLChannelInfo=20channel;=0A+=09SSLCipherSuiteInfo=20= suite;=0A+=0A+=09status=20=3D=20SSL_GetChannelInfo(port->pr_fd,=20= &channel,=20sizeof(channel));=0A+=09if=20(status=20!=3D=20SECSuccess)=0A= +=09=09goto=20error;=0A+=0A+=09status=20=3D=20= SSL_GetCipherSuiteInfo(channel.cipherSuite,=20&suite,=20sizeof(suite));=0A= +=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09goto=20error;=0A+=0A+=09= return=20suite.effectiveKeyBits;=0A+=0A+error:=0A+=09ereport(WARNING,=0A= +=09=09=09(errmsg("unable=20to=20extract=20TLS=20session=20information:=20= %s",=0A+=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09return=20= 0;=0A+}=0A+=0A+/*=0A+=20*=20be_tls_get_compression=0A+=20*=0A+=20*=20NSS=20= disabled=20support=20for=20TLS=20compression=20in=20version=203.33=20and=20= removed=20the=0A+=20*=20code=20in=20a=20subsequent=20release.=20The=20= API=20for=20retrieving=20information=20about=0A+=20*=20compression=20as=20= well=20as=20enabling=20it=20is=20kept=20for=20backwards=20compatibility,=20= but=0A+=20*=20we=20don't=20need=20to=20consult=20it=20since=20it=20was=20= only=20available=20for=20SSLv3=20which=20we=0A+=20*=20don't=20support.=0A= +=20*=0A+=20*=20https://bugzilla.mozilla.org/show_bug.cgi?id=3D1409587=0A= +=20*/=0A+bool=0A+be_tls_get_compression(Port=20*port)=0A+{=0A+=09return=20= false;=0A+}=0A+=0A+/*=0A+=20*=20be_tls_get_version=0A+=20*=0A+=20*=20= Returns=20the=20protocol=20version=20used=20for=20the=20current=20= connection,=20or=20NULL=20in=0A+=20*=20case=20of=20errors.=0A+=20*/=0A= +const=20char=20*=0A+be_tls_get_version(Port=20*port)=0A+{=0A+=09= SECStatus=09status;=0A+=09SSLChannelInfo=20channel;=0A+=0A+=09status=20=3D= =20SSL_GetChannelInfo(port->pr_fd,=20&channel,=20sizeof(channel));=0A+=09= if=20(status=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09ereport(WARNING,=0A+=09= =09=09=09(errmsg("unable=20to=20extract=20TLS=20session=20information:=20= %s",=0A+=09=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09=09= return=20NULL;=0A+=09}=0A+=0A+=09return=20= ssl_protocol_version_to_string(channel.protocolVersion);=0A+}=0A+=0A= +const=20char=20*=0A+be_tls_get_cipher(Port=20*port)=0A+{=0A+=09= SECStatus=09status;=0A+=09SSLChannelInfo=20channel;=0A+=09= SSLCipherSuiteInfo=20suite;=0A+=0A+=09status=20=3D=20= SSL_GetChannelInfo(port->pr_fd,=20&channel,=20sizeof(channel));=0A+=09if=20= (status=20!=3D=20SECSuccess)=0A+=09=09goto=20error;=0A+=0A+=09status=20=3D= =20SSL_GetCipherSuiteInfo(channel.cipherSuite,=20&suite,=20= sizeof(suite));=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09goto=20= error;=0A+=0A+=09return=20suite.cipherSuiteName;=0A+=0A+error:=0A+=09= ereport(WARNING,=0A+=09=09=09(errmsg("unable=20to=20extract=20TLS=20= session=20information:=20%s",=0A+=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09return=20NULL;=0A+}=0A+=0A= +void=0A+be_tls_get_peer_subject_name(Port=20*port,=20char=20*ptr,=20= size_t=20len)=0A+{=0A+=09CERTCertificate=20*certificate;=0A+=0A+=09= certificate=20=3D=20SSL_PeerCertificate(port->pr_fd);=0A+=09if=20= (certificate)=0A+=09=09strlcpy(ptr,=20= CERT_NameToAscii(&certificate->subject),=20len);=0A+=09else=0A+=09=09= ptr[0]=20=3D=20'\0';=0A+}=0A+=0A+void=0A= +be_tls_get_peer_issuer_name(Port=20*port,=20char=20*ptr,=20size_t=20= len)=0A+{=0A+=09CERTCertificate=20*certificate;=0A+=0A+=09certificate=20= =3D=20SSL_PeerCertificate(port->pr_fd);=0A+=09if=20(certificate)=0A+=09=09= strlcpy(ptr,=20CERT_NameToAscii(&certificate->issuer),=20len);=0A+=09= else=0A+=09=09ptr[0]=20=3D=20'\0';=0A+}=0A+=0A+void=0A= +be_tls_get_peer_serial(Port=20*port,=20char=20*ptr,=20size_t=20len)=0A= +{=0A+=09CERTCertificate=20*certificate;=0A+=0A+=09certificate=20=3D=20= SSL_PeerCertificate(port->pr_fd);=0A+=09if=20(certificate)=0A+=09=09= snprintf(ptr,=20len,=20"%li",=20= DER_GetInteger(&(certificate->serialNumber)));=0A+=09else=0A+=09=09= ptr[0]=20=3D=20'\0';=0A+}=0A+=0A+char=20*=0A= +be_tls_get_certificate_hash(Port=20*port,=20size_t=20*len)=0A+{=0A+=09= CERTCertificate=20*certificate;=0A+=09SECOidTag=09signature_alg;=0A+=09= SECOidTag=09digest_alg;=0A+=09int=09=09=09digest_len;=0A+=09const=20= NSSSignatureAlgorithms=20*candidate;=0A+=09SECStatus=09status;=0A+=09= PLArenaPool=20*arena=20=3D=20NULL;=0A+=09SECItem=09=09digest;=0A+=09char=09= =20=20=20*ret;=0A+=0A+=09*len=20=3D=200;=0A+=09certificate=20=3D=20= SSL_LocalCertificate(port->pr_fd);=0A+=09if=20(!certificate)=0A+=09=09= return=20NULL;=0A+=0A+=09signature_alg=20=3D=20= SECOID_GetAlgorithmTag(&certificate->signature);=0A+=0A+=09candidate=20=3D= =20NSS_SCRAMDigestAlgorithm;=0A+=09while=20(candidate->signature)=0A+=09= {=0A+=09=09if=20(signature_alg=20=3D=3D=20candidate->signature)=0A+=09=09= {=0A+=09=09=09digest_alg=20=3D=20candidate->hash;=0A+=09=09=09digest_len=20= =3D=20candidate->len;=0A+=09=09=09break;=0A+=09=09}=0A+=0A+=09=09= candidate++;=0A+=09}=0A+=0A+=09if=20(!candidate->signature)=0A+=09=09= elog(ERROR,=20"could=20not=20find=20digest=20for=20OID=20'%s'",=0A+=09=09= =09=20SECOID_FindOIDTagDescription(signature_alg));=0A+=0A+=09arena=20=3D=20= PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);=0A+=09digest.data=20=3D=20= PORT_ArenaZAlloc(arena,=20sizeof(unsigned=20char)=20*=20digest_len);=0A+=09= digest.len=20=3D=20digest_len;=0A+=0A+=09status=20=3D=20= PK11_HashBuf(digest_alg,=20digest.data,=0A+=09=09=09=09=09=09=20=20= certificate->derCert.data,=0A+=09=09=09=09=09=09=20=20= certificate->derCert.len);=0A+=0A+=09if=20(status=20!=3D=20SECSuccess)=0A= +=09{=0A+=09=09PORT_FreeArena(arena,=20PR_TRUE);=0A+=09=09return=20NULL;=0A= +=09}=0A+=0A+=09ret=20=3D=20palloc(digest.len);=0A+=09memcpy(ret,=20= digest.data,=20digest.len);=0A+=09*len=20=3D=20digest_len;=0A+=09= PORT_FreeArena(arena,=20PR_TRUE);=0A+=0A+=09return=20ret;=0A+}=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09=09=09=09Internal=20functions=09=09=09=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +/*=0A+=20*=20default_nss_tls_init=0A+=20*=0A+=20*=20The=20default=20TLS=20= init=20hook=20function=20which=20users=20can=20override=20for=20= installing=0A+=20*=20their=20own=20passphrase=20callbacks=20and=20= similar=20actions.=20In=20case=20no=20callback=20has=0A+=20*=20been=20= configured,=20or=20the=20callback=20isn't=20reload=20capable=20during=20= a=20server=0A+=20*=20reload,=20the=20dummy=20callback=20will=20be=20= installed.=0A+=20*=0A+=20*=20The=20private=20data=20for=20the=20callback=20= is=20set=20differently=20depending=20on=20how=20it's=0A+=20*=20invoked.=20= For=20calls=20which=20may=20invoke=20the=20callback=20deeper=20in=20the=20= callstack=0A+=20*=20the=20private=20data=20is=20set=20with=20= SSL_SetPKCS11PinArg.=20When=20the=20call=20is=20directly=0A+=20*=20= invoking=20the=20callback,=20like=20PK11_FindCertFromNickname,=20then=20= the=20private=0A+=20*=20data=20is=20passed=20as=20a=20parameter.=20= Setting=20the=20data=20with=20SSL_SetPKCS11PinArg=20is=0A+=20*=20thus=20= not=20required=20but=20good=20practice.=0A+=20*=0A+=20*=20NSS=20doesn't=20= provide=20a=20default=20callback=20like=20OpenSSL=20does,=20but=20a=20= callback=20is=0A+=20*=20required=20to=20be=20set.=20=20The=20password=20= callback=20can=20be=20installed=20at=20any=20time,=20but=0A+=20*=20= setting=20the=20private=20data=20with=20SSL_SetPKCS11PinArg=20requires=20= a=20PR=20Filedesc.=0A+=20*/=0A+static=20void=0A= +default_nss_tls_init(bool=20isServerStart)=0A+{=0A+=09/*=0A+=09=20*=20= No=20user-defined=20callback=20has=20been=20configured,=20install=20the=20= dummy=20call-=0A+=09=20*=20back=20since=20we=20must=20set=20something.=0A= +=09=20*/=0A+=09if=20(!ssl_passphrase_command[0])=0A+=09=09= PK11_SetPasswordFunc(dummy_ssl_passphrase_cb);=0A+=09else=0A+=09{=0A+=09=09= /*=0A+=09=09=20*=20There=20is=20a=20user-defined=20callback,=20set=20it=20= unless=20we=20are=20in=20a=20restart=0A+=09=09=20*=20and=20cannot=20= handle=20restarts=20due=20to=20an=20interactive=20callback.=0A+=09=09=20= */=0A+=09=09if=20(isServerStart)=0A+=09=09=09= PK11_SetPasswordFunc(external_ssl_passphrase_cb);=0A+=09=09else=0A+=09=09= {=0A+=09=09=09if=20(ssl_passphrase_command_supports_reload)=0A+=09=09=09=09= PK11_SetPasswordFunc(external_ssl_passphrase_cb);=0A+=09=09=09else=0A+=09= =09=09=09PK11_SetPasswordFunc(dummy_ssl_passphrase_cb);=0A+=09=09}=0A+=09= }=0A+}=0A+=0A+/*=0A+=20*=20external_ssl_passphrase_cb=0A+=20*=0A+=20*=20= Runs=20the=20callback=20configured=20by=20ssl_passphrase_command=20and=20= returns=20the=0A+=20*=20captured=20password=20back=20to=20NSS.=0A+=20*/=0A= +static=20char=20*=0A+external_ssl_passphrase_cb(PK11SlotInfo=20*slot,=20= PRBool=20retry,=20void=20*arg)=0A+{=0A+=09/*=0A+=09=20*=20NSS=20use=20a=20= hardcoded=20256=20byte=20buffer=20for=20reading=20the=20password=20so=20= set=20the=0A+=09=20*=20same=20limit=20for=20our=20callback=20buffer.=0A+=09= =20*/=0A+=09char=09=09buf[256];=0A+=09int=09=09=09len;=0A+=09char=09=20=20= =20*password=20=3D=20NULL;=0A+=09char=09=20=20=20*prompt;=0A+=0A+=09/*=0A= +=09=20*=20Since=20there=20is=20no=20password=20callback=20in=20NSS=20= when=20the=20server=20starts=20up,=0A+=09=20*=20it=20makes=20little=20= sense=20to=20create=20an=20interactive=20callback.=20Thus,=20if=20this=0A= +=09=20*=20is=20a=20retry=20attempt=20then=20give=20up=20immediately.=0A= +=09=20*/=0A+=09if=20(retry)=0A+=09=09return=20NULL;=0A+=0A+=09/*=0A+=09=20= *=20Construct=20the=20same=20prompt=20that=20NSS=20uses=20internally=20= even=20though=20it=20is=0A+=09=20*=20unlikely=20to=20serve=20much=20= purpose,=20but=20we=20must=20set=20a=20prompt=20so=20we=20might=20as=0A+=09= =20*=20well=20do=20it=20right.=0A+=09=20*/=0A+=09prompt=20=3D=20= psprintf("Enter=20Password=20or=20Pin=20for=20\"%s\":",=0A+=09=09=09=09=09= =20=20PK11_GetTokenName(slot));=0A+=0A+=09len=20=3D=20= run_ssl_passphrase_command(prompt,=20ssl_is_server_start,=20buf,=20= sizeof(buf));=0A+=09pfree(prompt);=0A+=0A+=09if=20(!len)=0A+=09=09return=20= NULL;=0A+=0A+=09/*=0A+=09=20*=20At=20least=20one=20byte=20with=20= password=20content=20was=20returned,=20and=20NSS=20requires=0A+=09=20*=20= that=20we=20return=20it=20allocated=20in=20NSS=20controlled=20memory.=20= If=20we=20fail=20to=0A+=09=20*=20allocate=20then=20abort=20without=20= passing=20back=20NULL=20and=20bubble=20up=20the=20error=0A+=09=20*=20on=20= the=20PG=20side.=0A+=09=20*/=0A+=09password=20=3D=20(char=20*)=20= PR_Malloc(len=20+=201);=0A+=09if=20(!password)=0A+=09{=0A+=09=09= explicit_bzero(buf,=20sizeof(buf));=0A+=09=09ereport(ERROR,=0A+=09=09=09=09= (errcode(ERRCODE_OUT_OF_MEMORY),=0A+=09=09=09=09=20errmsg("out=20of=20= memory")));=0A+=09}=0A+=09strlcpy(password,=20buf,=20sizeof(password));=0A= +=09explicit_bzero(buf,=20sizeof(buf));=0A+=0A+=09return=20password;=0A= +}=0A+=0A+/*=0A+=20*=20dummy_ssl_passphrase_cb=0A+=20*=0A+=20*=20Return=20= unsuccessful=20if=20we=20are=20asked=20to=20provide=20the=20passphrase=20= for=20a=20cert=20or=0A+=20*=20key,=20without=20having=20a=20passphrase=20= callback=20installed.=0A+=20*/=0A+static=20char=20*=0A= +dummy_ssl_passphrase_cb(PK11SlotInfo=20*slot,=20PRBool=20retry,=20void=20= *arg)=0A+{=0A+=09dummy_ssl_passwd_cb_called=20=3D=20true;=0A+=09return=20= NULL;=0A+}=0A+=0A+static=20SECStatus=0A+pg_bad_cert_handler(void=20*arg,=20= PRFileDesc=20*=20fd)=0A+{=0A+=09Port=09=20=20=20*port=20=3D=20(Port=20*)=20= arg;=0A+=0A+=09port->peer_cert_valid=20=3D=20false;=0A+=09return=20= SECFailure;=0A+}=0A+=0A+static=20SECStatus=0A+pg_cert_auth_handler(void=20= *arg,=20PRFileDesc=20*=20fd,=20PRBool=20checksig,=20PRBool=20isServer)=0A= +{=0A+=09SECStatus=09status;=0A+=09Port=09=20=20=20*port=20=3D=20(Port=20= *)=20arg;=0A+=09CERTCertificate=20*cert;=0A+=09char=09=20=20=20*peer_cn;=0A= +=09int=09=09=09len;=0A+=0A+=09status=20=3D=20= SSL_AuthCertificate(CERT_GetDefaultCertDB(),=20port->pr_fd,=20checksig,=20= PR_TRUE);=0A+=09if=20(status=20=3D=3D=20SECSuccess)=0A+=09{=0A+=09=09= cert=20=3D=20SSL_PeerCertificate(port->pr_fd);=0A+=09=09len=20=3D=20= strlen(cert->subjectName);=0A+=09=09peer_cn=20=3D=20= MemoryContextAllocZero(TopMemoryContext,=20len=20+=201);=0A+=0A+=09=09/*=0A= +=09=09=20*=20Skip=20over=20the=20key=3D=20portion=20of=20the=20= key=3Dvalue=20containing=20the=20peer=20CN.=0A+=09=09=20*/=0A+=09=09if=20= (strncmp(cert->subjectName,=20"CN=3D",=203)=20=3D=3D=200)=0A+=09=09=09= strlcpy(peer_cn,=20cert->subjectName=20+=20strlen("CN=3D"),=20len=20+=20= 1);=0A+=09=09else=0A+=09=09=09strlcpy(peer_cn,=20cert->subjectName,=20= len=20+=201);=0A+=09=09CERT_DestroyCertificate(cert);=0A+=0A+=09=09= port->peer_cn=20=3D=20peer_cn;=0A+=09=09port->peer_cert_valid=20=3D=20= true;=0A+=09}=0A+=0A+=09return=20status;=0A+}=0A+=0A+static=20PRInt32=0A= +pg_ssl_read(PRFileDesc=20*fd,=20void=20*buf,=20PRInt32=20amount,=20= PRIntn=20flags,=0A+=09=09=09PRIntervalTime=20timeout)=0A+{=0A+=09= PRRecvFN=09read_fn;=0A+=09PRInt32=09=09n_read;=0A+=0A+=09read_fn=20=3D=20= fd->lower->methods->recv;=0A+=09n_read=20=3D=20read_fn(fd->lower,=20buf,=20= amount,=20flags,=20timeout);=0A+=0A+=09return=20n_read;=0A+}=0A+=0A= +static=20PRInt32=0A+pg_ssl_write(PRFileDesc=20*fd,=20const=20void=20= *buf,=20PRInt32=20amount,=20PRIntn=20flags,=0A+=09=09=09=20= PRIntervalTime=20timeout)=0A+{=0A+=09PRSendFN=09send_fn;=0A+=09PRInt32=09= =09n_write;=0A+=0A+=09send_fn=20=3D=20fd->lower->methods->send;=0A+=09= n_write=20=3D=20send_fn(fd->lower,=20buf,=20amount,=20flags,=20timeout);=0A= +=0A+=09return=20n_write;=0A+}=0A+=0A+static=20PRStatus=0A= +pg_ssl_close(PRFileDesc=20*fd)=0A+{=0A+=09/*=0A+=09=20*=20Disconnect=20= our=20private=20Port=20from=20the=20fd=20before=20closing=20out=20the=20= stack.=0A+=09=20*=20(Debug=20builds=20of=20NSPR=20will=20assert=20if=20= we=20do=20not.)=0A+=09=20*/=0A+=09fd->secret=20=3D=20NULL;=0A+=09return=20= PR_GetDefaultIOMethods()->close(fd);=0A+}=0A+=0A+static=20PRFileDesc=20*=0A= +init_iolayer(Port=20*port)=0A+{=0A+=09const=09=09PRIOMethods=20= *default_methods;=0A+=09PRFileDesc=20*layer;=0A+=0A+=09/*=0A+=09=20*=20= Start=20by=20initializing=20our=20layer=20with=20all=20the=20default=20= methods=20so=20that=20we=0A+=09=20*=20can=20selectively=20override=20the=20= ones=20we=20want=20while=20still=20ensuring=20that=20we=0A+=09=20*=20= have=20a=20complete=20layer=20specification.=0A+=09=20*/=0A+=09= default_methods=20=3D=20PR_GetDefaultIOMethods();=0A+=09= memcpy(&pr_iomethods,=20default_methods,=20sizeof(PRIOMethods));=0A+=0A+=09= pr_iomethods.recv=20=3D=20pg_ssl_read;=0A+=09pr_iomethods.send=20=3D=20= pg_ssl_write;=0A+=09pr_iomethods.close=20=3D=20pg_ssl_close;=0A+=0A+=09= /*=0A+=09=20*=20Each=20IO=20layer=20must=20be=20identified=20by=20a=20= unique=20name,=20where=20uniqueness=20is=0A+=09=20*=20per=20connection.=20= Each=20connection=20in=20a=20postgres=20cluster=20can=20generate=20the=0A= +=09=20*=20identity=20from=20the=20same=20string=20as=20they=20will=20= create=20their=20IO=20layers=20on=0A+=09=20*=20different=20sockets.=20= Only=20one=20layer=20per=20socket=20can=20have=20the=20same=20name.=0A+=09= =20*/=0A+=09pr_id=20=3D=20PR_GetUniqueIdentity("PostgreSQL=20Server");=0A= +=09if=20(pr_id=20=3D=3D=20PR_INVALID_IO_LAYER)=0A+=09{=0A+=09=09= ereport(ERROR,=0A+=09=09=09=09(errmsg("out=20of=20memory=20when=20= setting=20up=20TLS=20connection")));=0A+=09=09return=20NULL;=0A+=09}=0A+=0A= +=09/*=0A+=09=20*=20Create=20the=20actual=20IO=20layer=20as=20a=20stub=20= such=20that=20it=20can=20be=20pushed=20onto=0A+=09=20*=20the=20layer=20= stack.=20The=20step=20via=20a=20stub=20is=20required=20as=20we=20define=20= custom=0A+=09=20*=20callbacks.=0A+=09=20*/=0A+=09layer=20=3D=20= PR_CreateIOLayerStub(pr_id,=20&pr_iomethods);=0A+=09if=20(!layer)=0A+=09= {=0A+=09=09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20to=20create=20= NSS=20I/O=20layer")));=0A+=09=09return=20NULL;=0A+=09}=0A+=0A+=09/*=20= Store=20the=20Port=20as=20private=20data=20available=20in=20callbacks=20= */=0A+=09layer->secret=20=3D=20(void=20*)=20port;=0A+=0A+=09return=20= layer;=0A+}=0A+=0A+static=20char=20*=0A= +ssl_protocol_version_to_string(int=20v)=0A+{=0A+=09switch=20(v)=0A+=09{=0A= +=09=09=09/*=20SSL=20v2=20and=20v3=20are=20not=20supported=20*/=0A+=09=09= case=20SSL_LIBRARY_VERSION_2:=0A+=09=09case=20SSL_LIBRARY_VERSION_3_0:=0A= +=09=09=09Assert(false);=0A+=09=09=09break;=0A+=0A+=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_0:=0A+=09=09=09return=20pstrdup("TLSv1.0");=0A= +=09=09case=20SSL_LIBRARY_VERSION_TLS_1_1:=0A+=09=09=09return=20= pstrdup("TLSv1.1");=0A+=09=09case=20SSL_LIBRARY_VERSION_TLS_1_2:=0A+=09=09= =09return=20pstrdup("TLSv1.2");=0A+=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_3:=0A+=09=09=09return=20pstrdup("TLSv1.3");=0A= +=09}=0A+=0A+=09return=20pstrdup("unknown");=0A+}=0A+=0A+=0A+/*=0A+=20*=20= ssl_protocol_version_to_nss=0A+=20*=09=09=09Translate=20PostgreSQL=20TLS=20= version=20to=20NSS=20version=0A+=20*=0A+=20*=20Returns=20zero=20in=20= case=20the=20requested=20TLS=20version=20is=20undefined=20(PG_ANY)=20and=0A= +=20*=20should=20be=20set=20by=20the=20caller,=20or=20-1=20on=20failure.=0A= +=20*/=0A+static=20uint16=0A+ssl_protocol_version_to_nss(int=20v,=20= const=20char=20*guc_name)=0A+{=0A+=09switch=20(v)=0A+=09{=0A+=09=09=09/*=0A= +=09=09=09=20*=20There=20is=20no=20SSL_LIBRARY_=20macro=20defined=20in=20= NSS=20with=20the=20value=0A+=09=09=09=20*=20zero,=20so=20we=20use=20this=20= to=20signal=20the=20caller=20that=20the=20highest=0A+=09=09=09=20*=20= useful=20version=20should=20be=20set=20on=20the=20connection.=0A+=09=09=09= =20*/=0A+=09=09case=20PG_TLS_ANY:=0A+=09=09=09return=200;=0A+=0A+=09=09=09= /*=0A+=09=09=09=20*=20No=20guard=20is=20required=20here=20as=20there=20= are=20no=20versions=20of=20NSS=0A+=09=09=09=20*=20without=20support=20= for=20TLS1.=0A+=09=09=09=20*/=0A+=09=09case=20PG_TLS1_VERSION:=0A+=09=09=09= return=20SSL_LIBRARY_VERSION_TLS_1_0;=0A+=09=09case=20PG_TLS1_1_VERSION:=0A= +#ifdef=20SSL_LIBRARY_VERSION_TLS_1_1=0A+=09=09=09return=20= SSL_LIBRARY_VERSION_TLS_1_1;=0A+#else=0A+=09=09=09break;=0A+#endif=0A+=09= =09case=20PG_TLS1_2_VERSION:=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_2=0A+=09= =09=09return=20SSL_LIBRARY_VERSION_TLS_1_2;=0A+#else=0A+=09=09=09break;=0A= +#endif=0A+=09=09case=20PG_TLS1_3_VERSION:=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_3=0A+=09=09=09return=20= SSL_LIBRARY_VERSION_TLS_1_3;=0A+#else=0A+=09=09=09break;=0A+#endif=0A+=09= =09default:=0A+=09=09=09break;=0A+=09}=0A+=0A+=09return=20-1;=0A+}=0A+=0A= +/*=0A+=20*=20pg_SSLerrmessage=0A+=20*=09=09Create=20and=20return=20a=20= human=20readable=20error=20message=20given=0A+=20*=09=09the=20specified=20= error=20code=0A+=20*=0A+=20*=20PR_ErrorToName=20only=20converts=20the=20= enum=20identifier=20of=20the=20error=20to=20string,=0A+=20*=20but=20that=20= can=20be=20quite=20useful=20for=20debugging=20(and=20in=20case=20= PR_ErrorToString=20is=0A+=20*=20unable=20to=20render=20a=20message=20= then=20we=20at=20least=20have=20something).=0A+=20*/=0A+static=20char=20= *=0A+pg_SSLerrmessage(PRErrorCode=20errcode)=0A+{=0A+=09return=20= psprintf("%s=20(%s)",=0A+=09=09=09=09=09PR_ErrorToString(errcode,=20= PR_LANGUAGE_I_DEFAULT),=0A+=09=09=09=09=09PR_ErrorToName(errcode));=0A+}=0A= diff=20--git=20a/src/backend/libpq/be-secure.c=20= b/src/backend/libpq/be-secure.c=0Aindex=204cf139a223..5e0c27c134=20= 100644=0A---=20a/src/backend/libpq/be-secure.c=0A+++=20= b/src/backend/libpq/be-secure.c=0A@@=20-49,6=20+49,9=20@@=20bool=09=09= ssl_passphrase_command_supports_reload;=0A=20#ifdef=20USE_SSL=0A=20bool=09= =09ssl_loaded_verify_locations=20=3D=20false;=0A=20#endif=0A+#ifdef=20= USE_NSS=0A+char=09=20=20=20*ssl_database;=0A+#endif=0A=20=0A=20/*=20GUC=20= variable=20controlling=20SSL=20cipher=20list=20*/=0A=20char=09=20=20=20= *SSLCipherSuites=20=3D=20NULL;=0Adiff=20--git=20= a/src/backend/libpq/hba.c=20b/src/backend/libpq/hba.c=0Aindex=20= 371dccb852..9a04c093d5=20100644=0A---=20a/src/backend/libpq/hba.c=0A+++=20= b/src/backend/libpq/hba.c=0A@@=20-1041,7=20+1041,7=20@@=20= parse_hba_line(TokenizedLine=20*tok_line,=20int=20elevel)=0A=20=09=09=09= ereport(elevel,=0A=20=09=09=09=09=09(errcode(ERRCODE_CONFIG_FILE_ERROR),=0A= =20=09=09=09=09=09=20errmsg("hostssl=20record=20cannot=20match=20because=20= SSL=20is=20not=20supported=20by=20this=20build"),=0A-=09=09=09=09=09=20= errhint("Compile=20with=20--with-openssl=20to=20use=20SSL=20= connections."),=0A+=09=09=09=09=09=20errhint("Compile=20with=20= --with-ssl=20to=20use=20SSL=20connections."),=0A=20=09=09=09=09=09=20= errcontext("line=20%d=20of=20configuration=20file=20\"%s\"",=0A=20=09=09=09= =09=09=09=09=09line_num,=20HbaFileName)));=0A=20=09=09=09*err_msg=20=3D=20= "hostssl=20record=20cannot=20match=20because=20SSL=20is=20not=20= supported=20by=20this=20build";=0Adiff=20--git=20= a/src/backend/utils/misc/guc.c=20b/src/backend/utils/misc/guc.c=0Aindex=20= eafdb1118e..b023b31c46=20100644=0A---=20a/src/backend/utils/misc/guc.c=0A= +++=20b/src/backend/utils/misc/guc.c=0A@@=20-4308,7=20+4308,11=20@@=20= static=20struct=20config_string=20ConfigureNamesString[]=20=3D=0A=20=09=09= },=0A=20=09=09&ssl_library,=0A=20#ifdef=20USE_SSL=0A+#if=20= defined(USE_OPENSSL)=0A=20=09=09"OpenSSL",=0A+#elif=20defined(USE_NSS)=0A= +=09=09"NSS",=0A+#endif=0A=20#else=0A=20=09=09"",=0A=20#endif=0A@@=20= -4366,6=20+4370,18=20@@=20static=20struct=20config_string=20= ConfigureNamesString[]=20=3D=0A=20=09=09check_canonical_path,=20= assign_pgstat_temp_directory,=20NULL=0A=20=09},=0A=20=0A+#ifdef=20= USE_NSS=0A+=09{=0A+=09=09{"ssl_database",=20PGC_SIGHUP,=20CONN_AUTH_SSL,=0A= +=09=09=09gettext_noop("Location=20of=20the=20NSS=20certificate=20= database."),=0A+=09=09=09NULL=0A+=09=09},=0A+=09=09&ssl_database,=0A+=09=09= "",=0A+=09=09NULL,=20NULL,=20NULL=0A+=09},=0A+#endif=0A+=0A=20=09{=0A=20=09= =09{"synchronous_standby_names",=20PGC_SIGHUP,=20REPLICATION_PRIMARY,=0A=20= =09=09=09gettext_noop("Number=20of=20synchronous=20standbys=20and=20list=20= of=20names=20of=20potential=20synchronous=20ones."),=0A@@=20-4394,8=20= +4410,10=20@@=20static=20struct=20config_string=20ConfigureNamesString[]=20= =3D=0A=20=09=09=09GUC_SUPERUSER_ONLY=0A=20=09=09},=0A=20=09=09= &SSLCipherSuites,=0A-#ifdef=20USE_OPENSSL=0A+#if=20defined(USE_OPENSSL)=0A= =20=09=09"HIGH:MEDIUM:+3DES:!aNULL",=0A+#elif=20defined=20(USE_NSS)=0A+=09= =09"",=0A=20#else=0A=20=09=09"none",=0A=20#endif=0Adiff=20--git=20= a/src/common/Makefile=20b/src/common/Makefile=0Aindex=20= 5422579a6a..be8b2583b2=20100644=0A---=20a/src/common/Makefile=0A+++=20= b/src/common/Makefile=0A@@=20-85,12=20+85,17=20@@=20OBJS_COMMON=20+=3D=20= \=0A=20=09protocol_openssl.o=20\=0A=20=09cryptohash_openssl.o=0A=20else=0A= +ifeq=20($(with_ssl),nss)=0A+OBJS_COMMON=20+=3D=20\=0A+=09= cryptohash_nss.o=0A+else=0A=20OBJS_COMMON=20+=3D=20\=0A=20=09= cryptohash.o=20\=0A=20=09md5.o=20\=0A=20=09sha1.o=20\=0A=20=09sha2.o=0A=20= endif=0A+endif=0A=20=0A=20#=20A=20few=20files=20are=20currently=20only=20= built=20for=20frontend,=20not=20server=0A=20#=20(Mkvcbuild.pm=20has=20a=20= copy=20of=20this=20list,=20too).=20=20logging.c=20is=20excluded=0Adiff=20= --git=20a/src/include/common/pg_nss.h=20b/src/include/common/pg_nss.h=0A= new=20file=20mode=20100644=0Aindex=200000000000..008fee85f1=0A---=20= /dev/null=0A+++=20b/src/include/common/pg_nss.h=0A@@=20-0,0=20+1,175=20= @@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20pg_nss.h=0A+=20*=09=20=20Support=20for=20NSS=20as=20= a=20TLS=20backend=0A+=20*=0A+=20*=20These=20definitions=20are=20used=20= by=20both=20frontend=20and=20backend=20code.=0A+=20*=0A+=20*=20Copyright=20= (c)=202020,=20PostgreSQL=20Global=20Development=20Group=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=20=20=20=20=20=20=20=20= src/include/common/pg_nss.h=0A+=20*=0A+=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+#ifndef=20PG_NSS_H=0A+#define=20PG_NSS_H=0A+=0A+#ifdef=20= USE_NSS=0A+#define=20NO_NSPR_10_SUPPORT=0A+#include=20=0A= +#include=20=0A+#include=20=0A+=0A= +PRUint16=09pg_find_cipher(char=20*name);=0A+=0A+typedef=20struct=0A+{=0A= +=09SECOidTag=09signature;=0A+=09SECOidTag=09hash;=0A+=09int=09=09=09= len;=0A+}=09=09=09NSSSignatureAlgorithms;=0A+=0A+typedef=20struct=0A+{=0A= +=09const=20char=20*name;=0A+=09PRUint16=09number;=0A+}=09=09=09= NSSCiphers;=0A+=0A+#define=20INVALID_CIPHER=090xFFFF=0A+=0A+static=20= const=20NSSSignatureAlgorithms=20NSS_SCRAMDigestAlgorithm[]=20=3D=20{=0A= +=0A+=09{SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,=20SEC_OID_SHA256,=20= SHA256_LENGTH},=0A+=09{SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION,=20= SEC_OID_SHA256,=20SHA256_LENGTH},=0A+=09= {SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE,=20SEC_OID_SHA256,=20SHA256_LENGTH},=0A= +=09{SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE,=20SEC_OID_SHA256,=20= SHA256_LENGTH},=0A+=09{SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,=20= SEC_OID_SHA256,=20SHA256_LENGTH},=0A+=0A+=09= {SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE,=20SEC_OID_SHA224,=20= SHA224_LENGTH},=0A+=09{SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION,=20= SEC_OID_SHA224,=20SHA224_LENGTH},=0A+=09= {SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST,=20SEC_OID_SHA224,=20= SHA224_LENGTH},=0A+=0A+=09{SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE,=20= SEC_OID_SHA256,=20SHA256_LENGTH},=0A+=09= {SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION,=20SEC_OID_SHA256,=20= SHA256_LENGTH},=0A+=09{SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST,=20= SEC_OID_SHA256,=20SHA256_LENGTH},=0A+=0A+=09= {SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE,=20SEC_OID_SHA384,=20= SHA384_LENGTH},=0A+=09{SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION,=20= SEC_OID_SHA384,=20SHA384_LENGTH},=0A+=0A+=09= {SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE,=20SEC_OID_SHA512,=20= SHA512_LENGTH},=0A+=09{SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION,=20= SEC_OID_SHA512,=20SHA512_LENGTH},=0A+=0A+=09{0,=200}=0A+};=0A+=0A+/*=0A+=20= *=20This=20list=20is=20a=20partial=20copy=20of=20the=20ciphers=20in=20= NSS=20files=20lib/ssl/sslproto.h=0A+=20*=20in=20order=20to=20provide=20a=20= human=20readable=20version=20of=20the=20ciphers.=20It=20would=20be=0A+=20= *=20nice=20to=20not=20have=20to=20have=20this,=20but=20NSS=20doesn't=20= provide=20any=20API=20addressing=0A+=20*=20the=20ciphers=20by=20name.=20= TODO:=20do=20we=20want=20more=20of=20the=20ciphers,=20or=20perhaps=20= less?=0A+=20*/=0A+static=20const=20NSSCiphers=20NSS_CipherList[]=20=3D=20= {=0A+=0A+=09{"TLS_NULL_WITH_NULL_NULL",=20TLS_NULL_WITH_NULL_NULL},=0A+=0A= +=09{"TLS_RSA_WITH_NULL_MD5",=20TLS_RSA_WITH_NULL_MD5},=0A+=09= {"TLS_RSA_WITH_NULL_SHA",=20TLS_RSA_WITH_NULL_SHA},=0A+=09= {"TLS_RSA_WITH_RC4_128_MD5",=20TLS_RSA_WITH_RC4_128_MD5},=0A+=09= {"TLS_RSA_WITH_RC4_128_SHA",=20TLS_RSA_WITH_RC4_128_SHA},=0A+=09= {"TLS_RSA_WITH_IDEA_CBC_SHA",=20TLS_RSA_WITH_IDEA_CBC_SHA},=0A+=09= {"TLS_RSA_WITH_DES_CBC_SHA",=20TLS_RSA_WITH_DES_CBC_SHA},=0A+=09= {"TLS_RSA_WITH_3DES_EDE_CBC_SHA",=20TLS_RSA_WITH_3DES_EDE_CBC_SHA},=0A+=0A= +=09{"TLS_DH_DSS_WITH_DES_CBC_SHA",=20TLS_DH_DSS_WITH_DES_CBC_SHA},=0A+=09= {"TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA",=20= TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA},=0A+=09{"TLS_DH_RSA_WITH_DES_CBC_SHA",=20= TLS_DH_RSA_WITH_DES_CBC_SHA},=0A+=09{"TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA",=20= TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA},=0A+=0A+=09= {"TLS_DHE_DSS_WITH_DES_CBC_SHA",=20TLS_DHE_DSS_WITH_DES_CBC_SHA},=0A+=09= {"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",=20= TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_DES_CBC_SHA",=20TLS_DHE_RSA_WITH_DES_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",=20= TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA},=0A+=0A+=09= {"TLS_DH_anon_WITH_RC4_128_MD5",=20TLS_DH_anon_WITH_RC4_128_MD5},=0A+=09= {"TLS_DH_anon_WITH_DES_CBC_SHA",=20TLS_DH_anon_WITH_DES_CBC_SHA},=0A+=09= {"TLS_DH_anon_WITH_3DES_EDE_CBC_SHA",=20= TLS_DH_anon_WITH_3DES_EDE_CBC_SHA},=0A+=0A+=09= {"TLS_RSA_WITH_AES_128_CBC_SHA",=20TLS_RSA_WITH_AES_128_CBC_SHA},=0A+=09= {"TLS_DH_DSS_WITH_AES_128_CBC_SHA",=20TLS_DH_DSS_WITH_AES_128_CBC_SHA},=0A= +=09{"TLS_DH_RSA_WITH_AES_128_CBC_SHA",=20= TLS_DH_RSA_WITH_AES_128_CBC_SHA},=0A+=09= {"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",=20= TLS_DHE_DSS_WITH_AES_128_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",=20= TLS_DHE_RSA_WITH_AES_128_CBC_SHA},=0A+=09= {"TLS_DH_anon_WITH_AES_128_CBC_SHA",=20= TLS_DH_anon_WITH_AES_128_CBC_SHA},=0A+=0A+=09= {"TLS_RSA_WITH_AES_256_CBC_SHA",=20TLS_RSA_WITH_AES_256_CBC_SHA},=0A+=09= {"TLS_DH_DSS_WITH_AES_256_CBC_SHA",=20TLS_DH_DSS_WITH_AES_256_CBC_SHA},=0A= +=09{"TLS_DH_RSA_WITH_AES_256_CBC_SHA",=20= TLS_DH_RSA_WITH_AES_256_CBC_SHA},=0A+=09= {"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",=20= TLS_DHE_DSS_WITH_AES_256_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",=20= TLS_DHE_RSA_WITH_AES_256_CBC_SHA},=0A+=09= {"TLS_DH_anon_WITH_AES_256_CBC_SHA",=20= TLS_DH_anon_WITH_AES_256_CBC_SHA},=0A+=09{"TLS_RSA_WITH_NULL_SHA256",=20= TLS_RSA_WITH_NULL_SHA256},=0A+=09{"TLS_RSA_WITH_AES_128_CBC_SHA256",=20= TLS_RSA_WITH_AES_128_CBC_SHA256},=0A+=09= {"TLS_RSA_WITH_AES_256_CBC_SHA256",=20TLS_RSA_WITH_AES_256_CBC_SHA256},=0A= +=0A+=09{"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",=20= TLS_DHE_DSS_WITH_AES_128_CBC_SHA256},=0A+=09= {"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_RSA_WITH_CAMELLIA_128_CBC_SHA},=0A+=09= {"TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA},=0A+=09= {"TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA},=0A+=09= {"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA},=0A+=09= {"TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA},=0A+=0A+=09= {"TLS_DHE_DSS_WITH_RC4_128_SHA",=20TLS_DHE_DSS_WITH_RC4_128_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",=20= TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},=0A+=09= {"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",=20= TLS_DHE_DSS_WITH_AES_256_CBC_SHA256},=0A+=09= {"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",=20= TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},=0A+=0A+=09= {"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_RSA_WITH_CAMELLIA_256_CBC_SHA},=0A+=09= {"TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA},=0A+=09= {"TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA},=0A+=09= {"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA},=0A+=09= {"TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA},=0A+=0A+=09= {"TLS_RSA_WITH_SEED_CBC_SHA",=20TLS_RSA_WITH_SEED_CBC_SHA},=0A+=0A+=09= {"TLS_RSA_WITH_AES_128_GCM_SHA256",=20TLS_RSA_WITH_AES_128_GCM_SHA256},=0A= +=09{"TLS_RSA_WITH_AES_256_GCM_SHA384",=20= TLS_RSA_WITH_AES_256_GCM_SHA384},=0A+=09= {"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",=20= TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},=0A+=09= {"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",=20= TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},=0A+=09= {"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",=20= TLS_DHE_DSS_WITH_AES_128_GCM_SHA256},=0A+=09= {"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",=20= TLS_DHE_DSS_WITH_AES_256_GCM_SHA384},=0A+=0A+=09= {"TLS_AES_128_GCM_SHA256",=20TLS_AES_128_GCM_SHA256},=0A+=09= {"TLS_AES_256_GCM_SHA384",=20TLS_AES_256_GCM_SHA384},=0A+=09= {"TLS_CHACHA20_POLY1305_SHA256",=20TLS_CHACHA20_POLY1305_SHA256},=0A+=09= {NULL,=200}=0A+};=0A+=0A+/*=0A+=20*=20pg_find_cipher=0A+=20*=09=09=09= Translate=20an=20NSS=20ciphername=20to=20the=20cipher=20code=0A+=20*=0A+=20= *=20Searches=20the=20configured=20ciphers=20for=20the=20corresponding=20= cipher=20code=20to=20the=0A+=20*=20name.=20Search=20is=20performed=20= case=20insensitive.=0A+=20*/=0A+PRUint16=0A+pg_find_cipher(char=20*name)=0A= +{=0A+=09const=09=09NSSCiphers=20*cipher_list=20=3D=20NSS_CipherList;=0A= +=0A+=09while=20(cipher_list->name)=0A+=09{=0A+=09=09if=20= (pg_strcasecmp(cipher_list->name,=20name)=20=3D=3D=200)=0A+=09=09=09= return=20cipher_list->number;=0A+=0A+=09=09cipher_list++;=0A+=09}=0A+=0A= +=09return=200xFFFF;=0A+}=0A+=0A+#endif=09=09=09=09=09=09=09/*=20USE_NSS=20= */=0A+=0A+#endif=09=09=09=09=09=09=09/*=20PG_NSS_H=20*/=0Adiff=20--git=20= a/src/include/libpq/libpq-be.h=20b/src/include/libpq/libpq-be.h=0Aindex=20= 66a8673d93..ea373a0ae0=20100644=0A---=20a/src/include/libpq/libpq-be.h=0A= +++=20b/src/include/libpq/libpq-be.h=0A@@=20-193,13=20+193,18=20@@=20= typedef=20struct=20Port=0A=20=09bool=09=09peer_cert_valid;=0A=20=0A=20=09= /*=0A-=09=20*=20OpenSSL=20structures.=20(Keep=20these=20last=20so=20that=20= the=20locations=20of=20other=0A-=09=20*=20fields=20are=20the=20same=20= whether=20or=20not=20you=20build=20with=20OpenSSL.)=0A+=09=20*=20SSL=20= backend=20specific=20structures.=20(Keep=20these=20last=20so=20that=20= the=20locations=0A+=09=20*=20of=20other=20fields=20are=20the=20same=20= whether=20or=20not=20you=20build=20with=20SSL=0A+=09=20*=20enabled.)=0A=20= =09=20*/=0A=20#ifdef=20USE_OPENSSL=0A=20=09SSL=09=09=20=20=20*ssl;=0A=20=09= X509=09=20=20=20*peer;=0A=20#endif=0A+=0A+#ifdef=20USE_NSS=0A+=09void=09=20= =20=20*pr_fd;=0A+#endif=0A=20}=20Port;=0A=20=0A=20#ifdef=20USE_SSL=0A@@=20= -283,7=20+288,7=20@@=20extern=20void=20be_tls_get_peer_serial(Port=20= *port,=20char=20*ptr,=20size_t=20len);=0A=20=20*=20This=20is=20not=20= supported=20with=20old=20versions=20of=20OpenSSL=20that=20don't=20have=0A= =20=20*=20the=20X509_get_signature_nid()=20function.=0A=20=20*/=0A-#if=20= defined(USE_OPENSSL)=20&&=20defined(HAVE_X509_GET_SIGNATURE_NID)=0A+#if=20= defined(USE_NSS)=20||=20(defined(USE_OPENSSL)=20&&=20= defined(HAVE_X509_GET_SIGNATURE_NID))=0A=20#define=20= HAVE_BE_TLS_GET_CERTIFICATE_HASH=0A=20extern=20char=20= *be_tls_get_certificate_hash(Port=20*port,=20size_t=20*len);=0A=20#endif=0A= @@=20-293,6=20+298,10=20@@=20extern=20char=20= *be_tls_get_certificate_hash(Port=20*port,=20size_t=20*len);=0A=20= typedef=20void=20(*openssl_tls_init_hook_typ)=20(SSL_CTX=20*context,=20= bool=20isServerStart);=0A=20extern=20PGDLLIMPORT=20= openssl_tls_init_hook_typ=20openssl_tls_init_hook;=0A=20#endif=0A+#ifdef=20= USE_NSS=0A+typedef=20void=20(*nss_tls_init_hook_type)=20(bool=20= isServerStart);=0A+extern=20PGDLLIMPORT=20nss_tls_init_hook_type=20= nss_tls_init_hook;=0A+#endif=0A=20=0A=20#endif=09=09=09=09=09=09=09/*=20= USE_SSL=20*/=0A=20=0Adiff=20--git=20a/src/include/libpq/libpq.h=20= b/src/include/libpq/libpq.h=0Aindex=20a55898c85a..d2860b852f=20100644=0A= ---=20a/src/include/libpq/libpq.h=0A+++=20b/src/include/libpq/libpq.h=0A= @@=20-88,6=20+88,9=20@@=20extern=20PGDLLIMPORT=20bool=20= ssl_passphrase_command_supports_reload;=0A=20#ifdef=20USE_SSL=0A=20= extern=20bool=20ssl_loaded_verify_locations;=0A=20#endif=0A+#ifdef=20= USE_NSS=0A+extern=20char=20*ssl_database;=0A+#endif=0A=20=0A=20extern=20= int=09secure_initialize(bool=20isServerStart);=0A=20extern=20bool=20= secure_loaded_verify_locations(void);=0Adiff=20--git=20= a/src/include/pg_config.h.in=20b/src/include/pg_config.h.in=0Aindex=20= f4d9f3b408..8856a33590=20100644=0A---=20a/src/include/pg_config.h.in=0A= +++=20b/src/include/pg_config.h.in=0A@@=20-899,12=20+899,15=20@@=0A=20/*=20= Define=20to=20select=20named=20POSIX=20semaphores.=20*/=0A=20#undef=20= USE_NAMED_POSIX_SEMAPHORES=0A=20=0A-/*=20Define=20to=20build=20with=20= OpenSSL=20support.=20(--with-openssl)=20*/=0A+/*=20Define=20to=20build=20= with=20OpenSSL=20support.=20(--with-ssl=3Dopenssl)=20*/=0A=20#undef=20= USE_OPENSSL=0A=20=0A=20/*=20Define=20to=201=20to=20build=20with=20PAM=20= support.=20(--with-pam)=20*/=0A=20#undef=20USE_PAM=0A=20=0A+/*=20Define=20= to=20build=20with=20NSS=20support=20(--with-ssl=3Dnss)=20*/=0A+#undef=20= USE_NSS=0A+=0A=20/*=20Define=20to=201=20to=20use=20software=20CRC-32C=20= implementation=20(slicing-by-8).=20*/=0A=20#undef=20= USE_SLICING_BY_8_CRC32C=0A=20=0Adiff=20--git=20= a/src/include/pg_config_manual.h=20b/src/include/pg_config_manual.h=0A= index=20d27c8601fa..7861b94290=20100644=0A---=20= a/src/include/pg_config_manual.h=0A+++=20= b/src/include/pg_config_manual.h=0A@@=20-176,10=20+176,9=20@@=0A=20=0A=20= /*=0A=20=20*=20USE_SSL=20code=20should=20be=20compiled=20only=20when=20= compiling=20with=20an=20SSL=0A-=20*=20implementation.=20=20(Currently,=20= only=20OpenSSL=20is=20supported,=20but=20we=20might=20add=0A-=20*=20more=20= implementations=20in=20the=20future.)=0A+=20*=20implementation.=0A=20=20= */=0A-#ifdef=20USE_OPENSSL=0A+#if=20defined(USE_OPENSSL)=20||=20= defined(USE_NSS)=0A=20#define=20USE_SSL=0A=20#endif=0A=20=0Adiff=20--git=20= a/src/interfaces/libpq/Makefile=20b/src/interfaces/libpq/Makefile=0A= index=20c5ef0bead5..837e105ffe=20100644=0A---=20= a/src/interfaces/libpq/Makefile=0A+++=20b/src/interfaces/libpq/Makefile=0A= @@=20-55,6=20+55,11=20@@=20OBJS=20+=3D=20\=0A=20=09fe-secure-openssl.o=0A= =20endif=0A=20=0A+ifeq=20($(with_ssl),=20nss)=0A+OBJS=20+=3D=20\=0A+=09= fe-secure-nss.o=0A+endif=0A+=0A=20ifeq=20($(with_gssapi),yes)=0A=20OBJS=20= +=3D=20\=0A=20=09fe-gssapi-common.o=20\=0Adiff=20--git=20= a/src/interfaces/libpq/fe-connect.c=20= b/src/interfaces/libpq/fe-connect.c=0Aindex=208ca0583aa9..1eeeff54a8=20= 100644=0A---=20a/src/interfaces/libpq/fe-connect.c=0A+++=20= b/src/interfaces/libpq/fe-connect.c=0A@@=20-355,6=20+355,10=20@@=20= static=20const=20internalPQconninfoOption=20PQconninfoOptions[]=20=3D=20= {=0A=20=09=09"Target-Session-Attrs",=20"",=2011,=20/*=20= sizeof("read-write")=20=3D=2011=20*/=0A=20=09offsetof(struct=20pg_conn,=20= target_session_attrs)},=0A=20=0A+=09{"cert_database",=20NULL,=20NULL,=20= NULL,=0A+=09=09"CertificateDatabase",=20"",=2064,=0A+=09offsetof(struct=20= pg_conn,=20cert_database)},=0A+=0A=20=09/*=20Terminating=20entry=20---=20= MUST=20BE=20LAST=20*/=0A=20=09{NULL,=20NULL,=20NULL,=20NULL,=0A=20=09= NULL,=20NULL,=200}=0Adiff=20--git=20= a/src/interfaces/libpq/fe-secure-nss.c=20= b/src/interfaces/libpq/fe-secure-nss.c=0Anew=20file=20mode=20100644=0A= index=200000000000..dca0572e67=0A---=20/dev/null=0A+++=20= b/src/interfaces/libpq/fe-secure-nss.c=0A@@=20-0,0=20+1,1112=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20fe-secure-nss.c=0A+=20*=09=20=20functions=20for=20= supporting=20NSS=20as=20a=20TLS=20backend=20for=20frontend=20libpq=0A+=20= *=0A+=20*=20Portions=20Copyright=20(c)=201996-2020,=20PostgreSQL=20= Global=20Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=20= 1994,=20Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20= *=20IDENTIFICATION=0A+=20*=09=20=20src/interfaces/libpq/fe-secure-nss.c=0A= +=20*=0A+=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#include=20"postgres_fe.h"=0A+=0A+#include=20= "libpq-fe.h"=0A+#include=20"fe-auth.h"=0A+#include=20= "fe-secure-common.h"=0A+#include=20"libpq-int.h"=0A+#include=20= "common/pg_nss.h"=0A+=0A+/*=0A+=20*=20BITS_PER_BYTE=20is=20also=20= defined=20in=20the=20NSPR=20header=20files,=20so=20we=20need=20to=20= undef=0A+=20*=20our=20version=20to=20avoid=20compiler=20warnings=20on=20= redefinition.=0A+=20*/=0A+#define=20pg_BITS_PER_BYTE=20BITS_PER_BYTE=0A= +#undef=20BITS_PER_BYTE=0A+=0A+/*=0A+=20*=20The=20= nspr/obsolete/protypes.h=20NSPR=20header=20typedefs=20uint64=20and=20= int64=20with=0A+=20*=20colliding=20definitions=20from=20ours,=20causing=20= a=20much=20expected=20compiler=20error.=0A+=20*=20Remove=20backwards=20= compatibility=20with=20ancient=20NSPR=20versions=20to=20avoid=20this.=0A= +=20*/=0A+#define=20NO_NSPR_10_SUPPORT=0A+#include=20=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+=0A+/*=0A+=20*=20Ensure=20= that=20the=20colliding=20definitions=20match,=20else=20throw=20an=20= error.=20In=20case=0A+=20*=20NSPR=20remove=20the=20definition=20in=20a=20= future=20version=20(however=20unlikely=20that=20may=0A+=20*=20be,=20make=20= sure=20to=20put=20ours=20back=20again.=0A+=20*/=0A+#if=20= defined(BITS_PER_BYTE)=0A+#if=20BITS_PER_BYTE=20!=3D=20pg_BITS_PER_BYTE=0A= +#error=20"incompatible=20byte=20widths=20between=20NSPR=20and=20= PostgreSQL"=0A+#endif=0A+#else=0A+#define=20BITS_PER_BYTE=20= pg_BITS_PER_BYTE=0A+#endif=0A+#undef=20pg_BITS_PER_BYTE=0A+=0A+static=20= SECStatus=20pg_load_nss_module(SECMODModule=20*=20*module,=20const=20= char=20*library,=20const=20char=20*name);=0A+static=20SECStatus=20= pg_bad_cert_handler(void=20*arg,=20PRFileDesc=20*=20fd);=0A+static=20= const=20char=20*pg_SSLerrmessage(PRErrorCode=20errcode);=0A+static=20= SECStatus=20pg_client_auth_handler(void=20*arg,=20PRFileDesc=20*=20= socket,=20CERTDistNames=20*=20caNames,=0A+=09=09=09=09=09=09=09=09=09=09= CERTCertificate=20*=20*pRetCert,=20SECKEYPrivateKey=20*=20*pRetKey);=0A= +static=20SECStatus=20pg_cert_auth_handler(void=20*arg,=20PRFileDesc=20*=20= fd,=20PRBool=20checksig,=20PRBool=20isServer);=0A+static=20int=09= ssl_protocol_version_to_nss(const=20char=20*protocol);=0A+static=20bool=20= cert_database_has_CA(PGconn=20*conn);=0A+=0A+static=20char=20= *PQssl_passwd_cb(PK11SlotInfo=20*=20slot,=20PRBool=20retry,=20void=20= *arg);=0A+=0A+/*=0A+=20*=20PR_ImportTCPSocket()=20is=20a=20private=20= API,=20but=20very=20widely=20used,=20as=20it's=20the=0A+=20*=20only=20= way=20to=20make=20NSS=20use=20an=20already=20set=20up=20POSIX=20file=20= descriptor=20rather=0A+=20*=20than=20opening=20one=20itself.=20To=20= quote=20the=20NSS=20documentation:=0A+=20*=0A+=20*=09=09"In=20theory,=20= code=20that=20uses=20PR_ImportTCPSocket=20may=20break=20when=20NSPR's=0A= +=20*=09=09implementation=20changes.=20In=20practice,=20this=20is=20= unlikely=20to=20happen=20because=0A+=20*=09=09NSPR's=20implementation=20= has=20been=20stable=20for=20years=20and=20because=20of=20NSPR's=0A+=20*=09= =09strong=20commitment=20to=20backward=20compatibility."=0A+=20*=0A+=20*=20= https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/P= R_ImportTCPSocket=0A+=20*=0A+=20*=20The=20function=20is=20declared=20in=20= ,=20but=20as=20it=20is=20a=20header=20marked=0A+=20*=20= private=20we=20declare=20it=20here=20rather=20than=20including=20it.=0A+=20= */=0A+NSPR_API(PRFileDesc=20*)=20PR_ImportTCPSocket(int);=0A+=0A+static=20= SECMODModule=20*=20ca_trust=20=3D=20NULL;=0A+static=20NSSInitContext=20*=20= nss_context=20=3D=20NULL;=0A+=0A+/*=0A+=20*=20This=20logic=20exist=20in=20= NSS=20as=20well,=20but=20it's=20only=20available=20for=20when=20there=20= is=0A+=20*=20a=20database=20to=20open,=20and=20not=20only=20using=20the=20= system=20trust=20store.=20Thus,=20we=0A+=20*=20need=20to=20keep=20our=20= own=20copy.=0A+=20*/=0A+#if=20defined(WIN32)=0A+static=20const=20char=20= *ca_trust_name=20=3D=20"nssckbi.dll";=0A+#elif=20defined(__darwin__)=0A= +static=20const=20char=20*ca_trust_name=20=3D=20"libnssckbi.dylib";=0A= +#else=0A+static=20const=20char=20*ca_trust_name=20=3D=20= "libnssckbi.so";=0A+#endif=0A+=0A+static=20PQsslKeyPassHook_nss_type=20= PQsslKeyPassHook=20=3D=20NULL;=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09=20Procedures=20common=20to=20all=20secure=20sessions=09=09=09*/=0A= +/*=20------------------------------------------------------------=20*/=0A= +=0A+/*=0A+=20*=20pgtls_init_library=0A+=20*=0A+=20*=20There=20is=20no=20= direct=20equivalent=20for=20PQinitOpenSSL=20in=20NSS/NSPR,=20with=20= PR_Init=0A+=20*=20being=20the=20closest=20match=20there=20is.=20PR_Init=20= is=20however=20already=20documented=20to=0A+=20*=20not=20be=20required=20= so=20simply=20making=20this=20a=20noop=20seems=20like=20the=20best=20= option.=0A+=20*/=0A+void=0A+pgtls_init_library(bool=20do_ssl,=20int=20= do_crypto)=0A+{=0A+=09/*=20noop=20*/=0A+}=0A+=0A+int=0A= +pgtls_init(PGconn=20*conn)=0A+{=0A+=09conn->ssl_in_use=20=3D=20false;=0A= +=09conn->has_password=20=3D=20false;=0A+=0A+=09return=200;=0A+}=0A+=0A= +void=0A+pgtls_close(PGconn=20*conn)=0A+{=0A+=09if=20(nss_context)=0A+=09= {=0A+=09=09NSS_ShutdownContext(nss_context);=0A+=09=09nss_context=20=3D=20= NULL;=0A+=09}=0A+}=0A+=0A+PostgresPollingStatusType=0A= +pgtls_open_client(PGconn=20*conn)=0A+{=0A+=09SECStatus=09status;=0A+=09= PRFileDesc=20*pr_fd;=0A+=09PRFileDesc=20*model;=0A+=09NSSInitParameters=20= params;=0A+=09SSLVersionRange=20desired_range;=0A+=0A+=09/*=0A+=09=20*=20= The=20NSPR=20documentation=20states=20that=20runtime=20initialization=20= via=20PR_Init=0A+=09=20*=20is=20no=20longer=20required,=20as=20the=20= first=20caller=20into=20NSPR=20will=20perform=20the=0A+=09=20*=20= initialization=20implicitly.=20See=20be-secure-nss.c=20for=20further=20= discussion=0A+=09=20*=20on=20PR_Init.=0A+=09=20*/=0A+=09= PR_Init(PR_USER_THREAD,=20PR_PRIORITY_NORMAL,=200);=0A+=0A+=09/*=0A+=09=20= *=20NSS=20initialization=20and=20the=20use=20of=20contexts=20is=20= further=20discussed=20in=0A+=09=20*=20be-secure-nss.c=0A+=09=20*/=0A+=09= memset(¶ms,=200,=20sizeof(params));=0A+=09params.length=20=3D=20= sizeof(params);=0A+=0A+=09if=20(conn->cert_database=20&&=20= strlen(conn->cert_database)=20>=200)=0A+=09{=0A+=09=09char=09=20=20=20= *cert_database_path=20=3D=20psprintf("sql:%s",=20conn->cert_database);=0A= +=0A+=09=09nss_context=20=3D=20NSS_InitContext(cert_database_path,=20"",=20= "",=20"",=0A+=09=09=09=09=09=09=09=09=09=20=20¶ms,=0A+=09=09=09=09=09= =09=09=09=09=20=20NSS_INIT_READONLY=20|=20NSS_INIT_PK11RELOAD);=0A+=09=09= pfree(cert_database_path);=0A+=0A+=09=09if=20(!nss_context)=0A+=09=09{=0A= +=09=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09= =20=20libpq_gettext("unable=20to=20open=20certificate=20database=20= \"%s\":=20%s"),=0A+=09=09=09=09=09=09=09=20=20conn->cert_database,=0A+=09= =09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09=09= return=20PGRES_POLLING_FAILED;=0A+=09=09}=0A+=09}=0A+=09else=0A+=09{=0A+=09= =09nss_context=20=3D=20NSS_InitContext("",=20"",=20"",=20"",=20¶ms,=0A= +=09=09=09=09=09=09=09=09=09=20=20NSS_INIT_READONLY=20|=20= NSS_INIT_NOCERTDB=20|=0A+=09=09=09=09=09=09=09=09=09=20=20= NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A+=09=09=09=09=09=09=09=09= =09=20=20NSS_INIT_NOROOTINIT=20|=20NSS_INIT_PK11RELOAD);=0A+=09=09if=20= (!nss_context)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20create=20certificate=20database:=20%s"),=0A= +=09=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09=09= return=20PGRES_POLLING_FAILED;=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20= *=20Configure=20cipher=20policy.=0A+=09=20*/=0A+=09status=20=3D=20= NSS_SetDomesticPolicy();=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09{=0A= +=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20configure=20cipher=20policy:=20%s"),=0A+=09=09= =09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20If=20we=20don't=20= have=20a=20certificate=20database,=20the=20system=20trust=20store=20is=20= the=0A+=09=20*=20fallback=20we=20can=20use.=20If=20we=20fail=20to=20= initialize=20that=20as=20well,=20we=20can=0A+=09=20*=20still=20attempt=20= a=20connection=20as=20long=20as=20the=20sslmode=20isn't=20verify*.=0A+=09= =20*/=0A+=09if=20(!conn->cert_database=20&&=20conn->sslmode[0]=20=3D=3D=20= 'v')=0A+=09{=0A+=09=09status=20=3D=20pg_load_nss_module(&ca_trust,=20= ca_trust_name,=20"\"Root=20Certificates\"");=0A+=09=09if=20(status=20!=3D=20= SECSuccess)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("WARNING:=20unable=20to=20load=20NSS=20trust=20module=20= \"%s\"=20:=20%s"),=0A+=09=09=09=09=09=09=09=20=20ca_trust_name,=0A+=09=09= =09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=0A+=09=09=09= return=20PGRES_POLLING_FAILED;=0A+=09=09}=0A+=09}=0A+=0A+=0A+=09= PK11_SetPasswordFunc(PQssl_passwd_cb);=0A+=0A+=09/*=0A+=09=20*=20Import=20= the=20already=20opened=20socket=20as=20we=20don't=20want=20to=20use=20= NSPR=20functions=0A+=09=20*=20for=20opening=20the=20network=20socket=20= due=20to=20how=20the=20PostgreSQL=20protocol=20works=0A+=09=20*=20with=20= TLS=20connections.=20This=20function=20is=20not=20part=20of=20the=20NSPR=20= public=20API,=0A+=09=20*=20see=20the=20comment=20at=20the=20top=20of=20= the=20file=20for=20the=20rationale=20of=20still=20using=0A+=09=20*=20it.=0A= +=09=20*/=0A+=09pr_fd=20=3D=20PR_ImportTCPSocket(conn->sock);=0A+=09if=20= (!pr_fd)=0A+=09{=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09= =09=09=09=09=20=20libpq_gettext("unable=20to=20attach=20to=20socket:=20= %s"),=0A+=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09= =09return=20PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Most=20= of=20the=20documentation=20available,=20and=20implementations=20of,=20= NSS/NSPR=0A+=09=20*=20use=20the=20PR_NewTCPSocket()=20function=20here,=20= which=20has=20the=20drawback=20that=20it=0A+=09=20*=20can=20only=20= create=20IPv4=20sockets.=20Instead=20use=20PR_OpenTCPSocket()=20which=0A= +=09=20*=20copes=20with=20IPv6=20as=20well.=0A+=09=20*/=0A+=09model=20=3D=20= SSL_ImportFD(NULL,=20PR_OpenTCPSocket(conn->laddr.addr.ss_family));=0A+=09= if=20(!model)=0A+=09{=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A= +=09=09=09=09=09=09=20=20libpq_gettext("unable=20to=20enable=20TLS:=20= %s"),=0A+=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09= =09return=20PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=20Disable=20old=20= protocol=20versions=20(SSLv2=20and=20SSLv3)=20*/=0A+=09= SSL_OptionSet(model,=20SSL_ENABLE_SSL2,=20PR_FALSE);=0A+=09= SSL_OptionSet(model,=20SSL_V2_COMPATIBLE_HELLO,=20PR_FALSE);=0A+=09= SSL_OptionSet(model,=20SSL_ENABLE_SSL3,=20PR_FALSE);=0A+=0A+#ifdef=20= SSL_CBC_RANDOM_IV=0A+=0A+=09/*=0A+=09=20*=20Enable=20protection=20= against=20the=20BEAST=20attack=20in=20case=20the=20NSS=20library=20has=0A= +=09=20*=20support=20for=20that.=20While=20SSLv3=20is=20disabled,=20we=20= may=20still=20allow=20TLSv1=0A+=09=20*=20which=20is=20affected.=20The=20= option=20isn't=20documented=20as=20an=20SSL=20option,=20but=20as=0A+=09=20= *=20an=20NSS=20environment=20variable.=0A+=09=20*/=0A+=09= SSL_OptionSet(model,=20SSL_CBC_RANDOM_IV,=20PR_TRUE);=0A+#endif=0A+=0A+=09= /*=20Set=20us=20up=20as=20a=20TLS=20client=20for=20the=20handshake=20*/=0A= +=09SSL_OptionSet(model,=20SSL_HANDSHAKE_AS_CLIENT,=20PR_TRUE);=0A+=0A+=09= /*=0A+=09=20*=20When=20setting=20the=20available=20protocols,=20we=20= either=20use=20the=20user=20defined=0A+=09=20*=20configuration=20values,=20= and=20if=20missing=20we=20accept=20whatever=20is=20the=20highest=0A+=09=20= *=20version=20supported=20by=20the=20library=20as=20the=20max=20and=20= only=20limit=20the=20range=20in=0A+=09=20*=20the=20other=20end=20at=20= TLSv1.0.=20ssl_variant_stream=20is=20a=20ProtocolVariant=20enum=0A+=09=20= *=20for=20Stream=20protocols,=20rather=20than=20datagram.=0A+=09=20*/=0A= +=09SSL_VersionRangeGetSupported(ssl_variant_stream,=20&desired_range);=0A= +=09desired_range.min=20=3D=20SSL_LIBRARY_VERSION_TLS_1_0;=0A+=0A+=09if=20= (conn->ssl_min_protocol_version=20&&=20= strlen(conn->ssl_min_protocol_version)=20>=200)=0A+=09{=0A+=09=09int=09=09= =09ssl_min_ver=20=3D=20= ssl_protocol_version_to_nss(conn->ssl_min_protocol_version);=0A+=0A+=09=09= if=20(ssl_min_ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("invalid=20value=20\"%s\"=20for=20minimum=20version=20of=20= SSL=20protocol\n"),=0A+=09=09=09=09=09=09=09=20=20= conn->ssl_min_protocol_version);=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=0A= +=09=09desired_range.min=20=3D=20ssl_min_ver;=0A+=09}=0A+=0A+=09if=20= (conn->ssl_max_protocol_version=20&&=20= strlen(conn->ssl_max_protocol_version)=20>=200)=0A+=09{=0A+=09=09int=09=09= =09ssl_max_ver=20=3D=20= ssl_protocol_version_to_nss(conn->ssl_max_protocol_version);=0A+=0A+=09=09= if=20(ssl_max_ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("invalid=20value=20\"%s\"=20for=20maximum=20version=20of=20= SSL=20protocol\n"),=0A+=09=09=09=09=09=09=09=20=20= conn->ssl_max_protocol_version);=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=0A= +=09=09desired_range.max=20=3D=20ssl_max_ver;=0A+=09}=0A+=0A+=09if=20= (SSL_VersionRangeSet(model,=20&desired_range)=20!=3D=20SECSuccess)=0A+=09= {=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20= =20libpq_gettext("unable=20to=20set=20allowed=20SSL=20protocol=20version=20= range:=20%s"),=0A+=09=09=09=09=09=09=20=20= pg_SSLerrmessage(PR_GetError()));=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Set=20up=20= callback=20for=20verifying=20server=20certificates,=20as=20well=20as=20= for=20how=0A+=09=20*=20to=20handle=20failed=20verifications.=0A+=09=20*/=0A= +=09SSL_AuthCertificateHook(model,=20pg_cert_auth_handler,=20(void=20*)=20= conn);=0A+=09SSL_BadCertHook(model,=20pg_bad_cert_handler,=20(void=20*)=20= conn);=0A+=0A+=09/*=0A+=09=20*=20Convert=20the=20NSPR=20socket=20to=20an=20= SSL=20socket.=20Ensuring=20the=20success=20of=20this=0A+=09=20*=20= operation=20is=20critical=20as=20NSS=20SSL_*=20functions=20may=20return=20= SECSuccess=20on=0A+=09=20*=20the=20socket=20even=20though=20SSL=20hasn't=20= been=20enabled,=20which=20introduce=20a=20risk=0A+=09=20*=20of=20silent=20= downgrades.=0A+=09=20*/=0A+=09conn->pr_fd=20=3D=20SSL_ImportFD(model,=20= pr_fd);=0A+=09if=20(!conn->pr_fd)=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20configure=20client=20for=20TLS:=20%s"),=0A+=09= =09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20The=20model=20= can=20now=20we=20closed=20as=20we've=20applied=20the=20settings=20of=20= the=20model=0A+=09=20*=20onto=20the=20real=20socket.=20=46rom=20hereon=20= we=20should=20only=20use=20conn->pr_fd.=0A+=09=20*/=0A+=09= PR_Close(model);=0A+=0A+=09/*=20Set=20the=20private=20data=20to=20be=20= passed=20to=20the=20password=20callback=20*/=0A+=09= SSL_SetPKCS11PinArg(conn->pr_fd,=20(void=20*)=20conn);=0A+=0A+=09/*=0A+=09= =20*=20If=20a=20CRL=20file=20has=20been=20specified,=20verify=20if=20it=20= exists=20in=20the=20database=0A+=09=20*=20but=20don't=20fail=20in=20case=20= it=20doesn't.=0A+=09=20*/=0A+=09if=20(conn->sslcrl=20&&=20= strlen(conn->sslcrl)=20>=200)=0A+=09{=0A+=09=09/*=20XXX:=20Implement=20= me..=20*/=0A+=09}=0A+=0A+=09status=20=3D=20= SSL_ResetHandshake(conn->pr_fd,=20PR_FALSE);=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09= =09=09=09=09=09=20=20libpq_gettext("unable=20to=20initiate=20handshake:=20= %s"),=0A+=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09= =09return=20PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Set=20= callback=20for=20client=20authentication=20when=20requested=20by=20the=20= server.=0A+=09=20*/=0A+=09SSL_GetClientAuthDataHook(conn->pr_fd,=20= pg_client_auth_handler,=20(void=20*)=20conn);=0A+=0A+=09/*=0A+=09=20*=20= Specify=20which=20hostname=20we=20are=20expecting=20to=20talk=20to.=20= This=20is=20required,=0A+=09=20*=20albeit=20mostly=20applies=20to=20when=20= opening=20a=20connection=20to=20a=20traditional=0A+=09=20*=20http=20= server=20it=20seems.=0A+=09=20*/=0A+=09SSL_SetURL(conn->pr_fd,=20= (conn->connhost[conn->whichhost]).host);=0A+=0A+=09do=0A+=09{=0A+=09=09= status=20=3D=20SSL_ForceHandshake(conn->pr_fd);=0A+=09}=0A+=09while=20= (status=20!=3D=20SECSuccess=20&&=20PR_GetError()=20=3D=3D=20= PR_WOULD_BLOCK_ERROR);=0A+=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09= {=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20= =20libpq_gettext("SSL=20error:=20%s"),=0A+=09=09=09=09=09=09=20=20= pg_SSLerrmessage(PR_GetError()));=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09conn->ssl_in_use=20=3D=20true;=0A= +=09return=20PGRES_POLLING_OK;=0A+}=0A+=0A+ssize_t=0A+pgtls_read(PGconn=20= *conn,=20void=20*ptr,=20size_t=20len)=0A+{=0A+=09PRInt32=09=09nread;=0A+=09= PRErrorCode=20status;=0A+=09int=09=09=09read_errno=20=3D=200;=0A+=0A+=09= /*=0A+=09=20*=20PR_Recv=20blocks=20until=20there=20is=20data=20to=20read=20= or=20the=20timeout=20expires.=20We=0A+=09=20*=20don't=20want=20to=20sit=20= blocked=20here,=20so=20the=20timeout=20is=20turned=20off=20by=20using=0A= +=09=20*=20PR_INTERVAL_NO_WAIT=20which=20means=20"return=20immediately",=20= =20Zero=20is=20returned=0A+=09=20*=20for=20closed=20connections,=20while=20= -1=20indicates=20an=20error=20within=20the=20ongoing=0A+=09=20*=20= connection.=0A+=09=20*/=0A+=09nread=20=3D=20PR_Recv(conn->pr_fd,=20ptr,=20= len,=200,=20PR_INTERVAL_NO_WAIT);=0A+=0A+=09if=20(nread=20=3D=3D=200)=0A= +=09{=0A+=09=09read_errno=20=3D=20ECONNRESET;=0A+=09=09nread=20=3D=20-1;=0A= +=09}=0A+=09else=20if=20(nread=20=3D=3D=20-1)=0A+=09{=0A+=09=09status=20= =3D=20PR_GetError();=0A+=0A+=09=09switch=20(status)=0A+=09=09{=0A+=09=09=09= case=20PR_IO_TIMEOUT_ERROR:=0A+=09=09=09=09/*=20No=20data=20available=20= yet.=20*/=0A+=09=09=09=09nread=20=3D=200;=0A+=09=09=09=09break;=0A+=0A+=09= =09=09case=20PR_WOULD_BLOCK_ERROR:=0A+=09=09=09=09read_errno=20=3D=20= EWOULDBLOCK;=0A+=09=09=09=09break;=0A+=0A+=09=09=09=09/*=0A+=09=09=09=09=20= *=20The=20error=20cases=20for=20PR_Recv=20are=20not=20documented,=20but=20= can=20be=0A+=09=09=09=09=20*=20reverse=20engineered=20from=20= _MD_unix_map_default_error()=20in=20the=0A+=09=09=09=09=20*=20NSPR=20= code,=20defined=20in=20pr/src/md/unix/unix_errors.c.=0A+=09=09=09=09=20= */=0A+=09=09=09case=20PR_NETWORK_UNREACHABLE_ERROR:=0A+=09=09=09case=20= PR_CONNECT_RESET_ERROR:=0A+=09=09=09=09read_errno=20=3D=20ECONNRESET;=0A= +=09=09=09=09break;=0A+=0A+=09=09=09default:=0A+=09=09=09=09break;=0A+=09= =09}=0A+=0A+=09=09if=20(nread=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("TLS=20read=20error:=20%s"),=0A+=09=09=09=09=09=09=09=20=20= pg_SSLerrmessage(status));=0A+=09=09}=0A+=09}=0A+=0A+=09= SOCK_ERRNO_SET(read_errno);=0A+=09return=20(ssize_t)=20nread;=0A+}=0A+=0A= +/*=0A+=20*=20pgtls_read_pending=0A+=20*=09=09Check=20for=20the=20= existence=20of=20data=20to=20be=20read.=0A+=20*=0A+=20*=20This=20is=20= part=20of=20the=20PostgreSQL=20TLS=20backend=20API.=0A+=20*/=0A+bool=0A= +pgtls_read_pending(PGconn=20*conn)=0A+{=0A+=09unsigned=20char=20c;=0A+=09= int=09=09=09n;=0A+=0A+=09/*=0A+=09=20*=20PR_Recv=20peeks=20into=20the=20= stream=20with=20the=20timeount=20turned=20off,=20to=20see=20if=0A+=09=20= *=20there=20is=20another=20byte=20to=20read=20off=20the=20wire.=20There=20= is=20an=20NSS=20function=0A+=09=20*=20SSL_DataPending()=20which=20might=20= seem=20like=20a=20better=20fit,=20but=20it=20will=20only=0A+=09=20*=20= check=20already=20encrypted=20data=20in=20the=20SSL=20buffer,=20not=20= still=20unencrypted=0A+=09=20*=20data,=20thus=20it=20doesn't=20guarantee=20= that=20a=20subsequent=20call=20to=0A+=09=20*=20PR_Read/PR_Recv=20won't=20= block.=0A+=09=20*/=0A+=09n=20=3D=20PR_Recv(conn->pr_fd,=20&c,=201,=20= PR_MSG_PEEK,=20PR_INTERVAL_NO_WAIT);=0A+=09return=20(n=20>=200);=0A+}=0A= +=0A+ssize_t=0A+pgtls_write(PGconn=20*conn,=20const=20void=20*ptr,=20= size_t=20len)=0A+{=0A+=09PRInt32=09=09n;=0A+=09PRErrorCode=20status;=0A+=09= int=09=09=09write_errno=20=3D=200;=0A+=0A+=09n=20=3D=20= PR_Write(conn->pr_fd,=20ptr,=20len);=0A+=0A+=09if=20(n=20<=200)=0A+=09{=0A= +=09=09status=20=3D=20PR_GetError();=0A+=0A+=09=09switch=20(status)=0A+=09= =09{=0A+=09=09=09case=20PR_WOULD_BLOCK_ERROR:=0A+#ifdef=20EAGAIN=0A+=09=09= =09=09write_errno=20=3D=20EAGAIN;=0A+#else=0A+=09=09=09=09write_errno=20= =3D=20EINTR;=0A+#endif=0A+=09=09=09=09break;=0A+=0A+=09=09=09default:=0A= +=09=09=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09= =09=09=20=20libpq_gettext("TLS=20write=20error:=20%s"),=0A+=09=09=09=09=09= =09=09=09=20=20pg_SSLerrmessage(status));=0A+=09=09=09=09write_errno=20=3D= =20ECONNRESET;=0A+=09=09=09=09break;=0A+=09=09}=0A+=09}=0A+=0A+=09= SOCK_ERRNO_SET(write_errno);=0A+=09return=20(ssize_t)=20n;=0A+}=0A+=0A= +char=20*=0A+pgtls_get_peer_certificate_hash(PGconn=20*conn,=20size_t=20= *len)=0A+{=0A+=09CERTCertificate=20*server_cert;=0A+=09SECOidTag=09= signature_alg;=0A+=09SECOidTag=09digest_alg;=0A+=09int=09=09=09= digest_len;=0A+=09const=20NSSSignatureAlgorithms=20*candidate;=0A+=09= PLArenaPool=20*arena;=0A+=09SECItem=09=09digest;=0A+=09char=09=20=20=20= *ret;=0A+=09SECStatus=09status;=0A+=0A+=09*len=20=3D=200;=0A+=0A+=09= server_cert=20=3D=20SSL_PeerCertificate(conn->pr_fd);=0A+=09if=20= (!server_cert)=0A+=09=09return=20NULL;=0A+=0A+=09signature_alg=20=3D=20= SECOID_GetAlgorithmTag(&server_cert->signature);=0A+=0A+=09candidate=20=3D= =20NSS_SCRAMDigestAlgorithm;=0A+=09while=20(candidate->signature)=0A+=09= {=0A+=09=09if=20(signature_alg=20=3D=3D=20candidate->signature)=0A+=09=09= {=0A+=09=09=09digest_alg=20=3D=20candidate->hash;=0A+=09=09=09digest_len=20= =3D=20candidate->len;=0A+=09=09=09break;=0A+=09=09}=0A+=0A+=09=09= candidate++;=0A+=09}=0A+=0A+=09if=20(!candidate->signature)=0A+=09{=0A+=09= =09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("could=20not=20find=20digest=20for=20OID=20'%s'\n"),=0A+=09= =09=09=09=09=09=20=20SECOID_FindOIDTagDescription(signature_alg));=0A+=09= =09return=20NULL;=0A+=09}=0A+=0A+=09arena=20=3D=20= PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);=0A+=09digest.data=20=3D=20= PORT_ArenaZAlloc(arena,=20sizeof(unsigned=20char)=20*=20digest_len);=0A+=09= digest.len=20=3D=20digest_len;=0A+=0A+=09status=20=3D=20= PK11_HashBuf(digest_alg,=20digest.data,=20server_cert->derCert.data,=0A+=09= =09=09=09=09=09=20=20server_cert->derCert.len);=0A+=0A+=09if=20(status=20= !=3D=20SECSuccess)=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20generate=20peer=20certificate=20digest:=20= %s"),=0A+=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09= =09PORT_FreeArena(arena,=20PR_TRUE);=0A+=09=09return=20NULL;=0A+=09}=0A+=0A= +=09ret=20=3D=20pg_malloc(digest.len);=0A+=09memcpy(ret,=20digest.data,=20= digest.len);=0A+=09*len=20=3D=20digest_len;=0A+=09PORT_FreeArena(arena,=20= PR_TRUE);=0A+=0A+=09return=20ret;=0A+}=0A+=0A+/*=0A+=20*=09Verify=20that=20= the=20server=20certificate=20matches=20the=20hostname=20we=20connected=20= to.=0A+=20*=0A+=20*=20The=20certificate's=20Common=20Name=20and=20= Subject=20Alternative=20Names=20are=20considered.=0A+=20*/=0A+int=0A= +pgtls_verify_peer_name_matches_certificate_guts(PGconn=20*conn,=0A+=09=09= =09=09=09=09=09=09=09=09=09=09int=20*names_examined,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09char=20**first_name)=0A+{=0A+=09char=09=20=20=20= *server_hostname=20=3D=20NULL;=0A+=09CERTCertificate=20*server_cert=20=3D=20= NULL;=0A+=09SECStatus=09status=20=3D=20SECSuccess;=0A+=09SECItem=09=09= altname_item;=0A+=09PLArenaPool=20*arena=20=3D=20NULL;=0A+=09= CERTGeneralName=20*san_list;=0A+=09CERTGeneralName=20*cn;=0A+=0A+=09= server_hostname=20=3D=20SSL_RevealURL(conn->pr_fd);=0A+=09if=20= (!server_hostname=20||=20server_hostname[0]=20=3D=3D=20'\0')=0A+=09=09= goto=20done;=0A+=0A+=09/*=0A+=09=20*=20CERT_VerifyCertName=20will=20= internally=20perform=20RFC=202818=20SubjectAltName=0A+=09=20*=20= verification.=0A+=09=20*/=0A+=09server_cert=20=3D=20= SSL_PeerCertificate(conn->pr_fd);=0A+=09status=20=3D=20= CERT_VerifyCertName(server_cert,=20server_hostname);=0A+=09if=20(status=20= !=3D=20SECSuccess)=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20verify=20server=20hostname:=20%s"),=0A+=09=09= =09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09goto=20= done;=0A+=09}=0A+=0A+=09status=20=3D=20= CERT_FindCertExtension(server_cert,=20SEC_OID_X509_SUBJECT_ALT_NAME,=0A+=09= =09=09=09=09=09=09=09=09&altname_item);=0A+=09if=20(status=20=3D=3D=20= SECSuccess)=0A+=09{=0A+=09=09arena=20=3D=20= PORT_NewArena(DER_DEFAULT_CHUNKSIZE);=0A+=09=09if=20(!arena)=0A+=09=09{=0A= +=09=09=09status=20=3D=20SECFailure;=0A+=09=09=09goto=20done;=0A+=09=09}=0A= +=09=09san_list=20=3D=20CERT_DecodeAltNameExtension(arena,=20= &altname_item);=0A+=09=09if=20(!san_list)=0A+=09=09{=0A+=09=09=09status=20= =3D=20SECFailure;=0A+=09=09=09goto=20done;=0A+=09=09}=0A+=0A+=09=09for=20= (cn=20=3D=20san_list;=20cn=20!=3D=20san_list;=20cn=20=3D=20= CERT_GetNextGeneralName(cn))=0A+=09=09{=0A+=09=09=09char=09=20=20=20= *alt_name;=0A+=09=09=09int=09=09=09rv;=0A+=09=09=09char=09=09tmp[512];=0A= +=0A+=09=09=09status=20=3D=20CERT_RFC1485_EscapeAndQuote(tmp,=20= sizeof(tmp),=0A+=09=09=09=09=09=09=09=09=09=09=09=09=20(char=20*)=20= cn->name.other.data,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=20= cn->name.other.len);=0A+=0A+=09=09=09if=20(status=20!=3D=20SECSuccess)=0A= +=09=09=09=09goto=20done;=0A+=0A+=09=09=09rv=20=3D=20= pq_verify_peer_name_matches_certificate_name(conn,=20tmp,=0A+=09=09=09=09= =09=09=09=09=09=09=09=09=09=09=09=20=20strlen(tmp),=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=20=20&alt_name);=0A+=09=09=09if=20(alt_name)=0A= +=09=09=09{=0A+=09=09=09=09if=20(!*first_name)=0A+=09=09=09=09=09= *first_name=20=3D=20alt_name;=0A+=09=09=09=09else=0A+=09=09=09=09=09= free(alt_name);=0A+=09=09=09}=0A+=0A+=09=09=09if=20(rv=20=3D=3D=201)=0A+=09= =09=09=09status=20=3D=20SECSuccess;=0A+=09=09=09else=0A+=09=09=09{=0A+=09= =09=09=09status=20=3D=20SECFailure;=0A+=09=09=09=09break;=0A+=09=09=09}=0A= +=09=09}=0A+=09}=0A+=09else=20if=20(PORT_GetError()=20=3D=3D=20= SEC_ERROR_EXTENSION_NOT_FOUND)=0A+=09=09status=20=3D=20SECSuccess;=0A+=09= else=0A+=09=09status=20=3D=20SECSuccess;=0A+=0A+done:=0A+=09/*=20= san_list=20will=20be=20freed=20by=20freeing=20the=20arena=20it=20was=20= allocated=20in=20*/=0A+=09if=20(arena)=0A+=09=09PORT_FreeArena(arena,=20= PR_TRUE);=0A+=09PR_Free(server_hostname);=0A+=0A+=09if=20(status=20=3D=3D=20= SECSuccess)=0A+=09=09return=201;=0A+=0A+=09return=200;=0A+}=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09PostgreSQL=20specific=20TLS=20support=20functions=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +static=20const=20char=20*=0A+pg_SSLerrmessage(PRErrorCode=20errcode)=0A= +{=0A+=09const=20char=20*error;=0A+=0A+=09/*=0A+=09=20*=20Try=20to=20get=20= the=20user=20friendly=20error=20description,=20and=20if=20that=20fails=20= try=0A+=09=20*=20to=20fall=20back=20on=20the=20name=20of=20the=20= PRErrorCode.=0A+=09=20*/=0A+=09error=20=3D=20PR_ErrorToString(errcode,=20= PR_LANGUAGE_I_DEFAULT);=0A+=09if=20(!error)=0A+=09=09error=20=3D=20= PR_ErrorToName(errcode);=0A+=09if=20(error)=0A+=09=09return=20error;=0A+=0A= +=09return=20"unknown=20TLS=20error";=0A+}=0A+=0A+static=20SECStatus=0A= +pg_load_nss_module(SECMODModule=20*=20*module,=20const=20char=20= *library,=20const=20char=20*name)=0A+{=0A+=09SECMODModule=20*mod;=0A+=09= char=09=20=20=20*modulespec;=0A+=0A+=09modulespec=20=3D=20= psprintf("library=3D\"%s\",=20name=3D\"%s\"",=20library,=20name);=0A+=0A= +=09/*=0A+=09=20*=20Attempt=20to=20load=20the=20specified=20module.=20= The=20second=20parameter=20is=20"parent"=0A+=09=20*=20which=20should=20= always=20be=20NULL=20for=20application=20code.=20The=20third=20parameter=0A= +=09=20*=20defines=20if=20loading=20should=20recurse=20which=20is=20only=20= applicable=20when=20loading=0A+=09=20*=20a=20module=20from=20within=20= another=20module.=20This=20hierarchy=20would=20have=20to=20be=0A+=09=20*=20= defined=20in=20the=20modulespec,=20and=20since=20we=20don't=20support=20= anything=20but=0A+=09=20*=20directly=20addressed=20modules=20we=20should=20= pass=20PR_FALSE.=0A+=09=20*/=0A+=09mod=20=3D=20= SECMOD_LoadUserModule(modulespec,=20NULL,=20PR_FALSE);=0A+=09= pfree(modulespec);=0A+=0A+=09if=20(mod=20&&=20mod->loaded)=0A+=09{=0A+=09= =09*module=20=3D=20mod;=0A+=09=09return=20SECSuccess;=0A+=09}=0A+=0A+=09= SECMOD_DestroyModule(mod);=0A+=09return=20SECFailure;=0A+}=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09=09=09=09NSS=20Callbacks=09=09=09=09=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +/*=0A+=20*=20pg_cert_auth_handler=0A+=20*=09=09=09Callback=20for=20= authenticating=20server=20certificate=0A+=20*=0A+=20*=20This=20is=20= pretty=20much=20the=20same=20procedure=20as=20the=20SSL_AuthCertificate=20= function=0A+=20*=20provided=20by=20NSS,=20with=20the=20difference=20= being=20server=20hostname=20validation.=20With=0A+=20*=20= SSL_AuthCertificate=20there=20is=20no=20way=20to=20do=20verify-ca,=20it=20= only=20does=20the=20-full=0A+=20*=20flavor=20of=20our=20sslmodes,=20so=20= we=20need=20our=20own=20implementation.=0A+=20*/=0A+static=20SECStatus=0A= +pg_cert_auth_handler(void=20*arg,=20PRFileDesc=20*fd,=20PRBool=20= checksig,=20PRBool=20isServer)=0A+{=0A+=09SECStatus=09status;=0A+=09= PGconn=09=20=20=20*conn=20=3D=20(PGconn=20*)=20arg;=0A+=09= CERTCertificate=20*server_cert;=0A+=09void=09=20=20=20*pin;=0A+=0A+=09= Assert(!isServer);=0A+=0A+=09pin=20=3D=20SSL_RevealPinArg(conn->pr_fd);=0A= +=09server_cert=20=3D=20SSL_PeerCertificate(conn->pr_fd);=0A+=0A+=09= status=20=3D=20CERT_VerifyCertificateNow((CERTCertDBHandle=20*)=20= CERT_GetDefaultCertDB(),=0A+=09=09=09=09=09=09=09=09=09=20=20=20= server_cert,=0A+=09=09=09=09=09=09=09=09=09=20=20=20checksig,=0A+=09=09=09= =09=09=09=09=09=09=20=20=20certificateUsageSSLServer,=0A+=09=09=09=09=09=09= =09=09=09=20=20=20pin,=0A+=09=09=09=09=09=09=09=09=09=20=20=20NULL);=0A+=0A= +=09/*=0A+=09=20*=20If=20we've=20already=20failed=20validation=20then=20= there=20is=20no=20point=20in=20also=0A+=09=20*=20performing=20the=20= hostname=20check=20for=20verify-full.=0A+=09=20*/=0A+=09if=20(status=20= =3D=3D=20SECSuccess)=0A+=09{=0A+=09=09if=20= (!pq_verify_peer_name_matches_certificate(conn))=0A+=09=09=09status=20=3D=20= SECFailure;=0A+=09}=0A+=09else=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20verify=20certificate:=20%s"),=0A+=09=09=09=09= =09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09}=0A+=0A+=09return=20= status;=0A+}=0A+=0A+/*=0A+=20*=20pg_client_auth_handler=0A+=20*=09=09= Callback=20for=20client=20certificate=20validation=0A+=20*=0A+=20*=20The=20= client=20auth=20callback=20is=20not=20on=20by=20default=20in=20NSS,=20so=20= we=20need=20to=20invoke=0A+=20*=20it=20ourselves=20to=20ensure=20we=20= can=20do=20cert=20authentication.=20A=20TODO=20is=20to=20support=0A+=20*=20= running=20without=20a=20specified=20sslcert=20parameter.=20By=20= retrieving=20all=20the=20certs=0A+=20*=20via=20nickname=20from=20the=20= cert=20database=20and=20see=20if=20we=20find=20one=20which=20apply=20= with=0A+=20*=20NSS_CmpCertChainWCANames()=20and=20= PK11_FindKeyByAnyCert()=20we=20could=20support=0A+=20*=20just=20running=20= with=20a=20ssl=20database=20specified.=0A+=20*=0A+=20*=20For=20now,=20we=20= use=20the=20default=20client=20certificate=20validation=20which=20= requires=20a=0A+=20*=20defined=20nickname=20to=20identify=20the=20cert=20= in=20the=20database.=0A+=20*/=0A+static=20SECStatus=0A= +pg_client_auth_handler(void=20*arg,=20PRFileDesc=20*=20socket,=20= CERTDistNames=20*=20caNames,=0A+=09=09=09=09=09=20=20=20CERTCertificate=20= *=20*pRetCert,=20SECKEYPrivateKey=20*=20*pRetKey)=0A+{=0A+=09PGconn=09=20= =20=20*conn=20=3D=20(PGconn=20*)=20arg;=0A+=0A+=09return=20= NSS_GetClientAuthData(conn->sslcert,=20socket,=20caNames,=20pRetCert,=20= pRetKey);=0A+}=0A+=0A+/*=0A+=20*=20pg_bad_cert_handler=0A+=20*=09=09= Callback=20for=20failed=20certificate=20validation=0A+=20*=0A+=20*=20The=20= TLS=20handshake=20will=20call=20this=20function=20iff=20the=20server=20= certificate=20failed=0A+=20*=20validation.=20Depending=20on=20the=20= sslmode,=20we=20allow=20the=20connection=20anyways.=0A+=20*/=0A+static=20= SECStatus=0A+pg_bad_cert_handler(void=20*arg,=20PRFileDesc=20*=20fd)=0A= +{=0A+=09PGconn=09=20=20=20*conn=20=3D=20(PGconn=20*)=20arg;=0A+=09= PRErrorCode=20err;=0A+=0A+=09/*=0A+=09=20*=20This=20really=20shouldn't=20= happen,=20as=20we've=20set=20the=20PGconn=20object=20as=20our=0A+=09=20*=20= callback=20data,=20and=20at=20the=20callsite=20we=20know=20it=20will=20= be=20populated.=20That=0A+=09=20*=20being=20said,=20the=20NSS=20code=20= itself=20performs=20this=20check=20even=20when=20it=20should=0A+=09=20*=20= not=20be=20required=20so=20let's=20use=20the=20same=20belts=20with=20our=20= suspenders.=0A+=09=20*/=0A+=09if=20(!arg)=0A+=09=09return=20SECFailure;=0A= +=0A+=09/*=0A+=09=20*=20For=20sslmodes=20other=20than=20verify-full=20= and=20verify-ca=20we=20don't=20perform=20peer=0A+=09=20*=20validation,=20= so=20return=20immediately.=20=20sslmode=20require=20with=20a=20database=0A= +=09=20*=20specified=20which=20contains=20a=20CA=20certificate=20will=20= work=20like=20verify-ca=20to=0A+=09=20*=20be=20compatible=20with=20the=20= OpenSSL=20implementation.=0A+=09=20*/=0A+=09if=20(strcmp(conn->sslmode,=20= "require")=20=3D=3D=200)=0A+=09{=0A+=09=09if=20(conn->cert_database=20&&=20= strlen(conn->cert_database)=20>=200=20&&=20cert_database_has_CA(conn))=0A= +=09=09=09return=20SECFailure;=0A+=09}=0A+=09if=20(conn->sslmode[0]=20=3D=3D= =20'v')=0A+=09=09return=20SECFailure;=0A+=0A+=09err=20=3D=20= PORT_GetError();=0A+=0A+=09/*=0A+=09=20*=20TODO:=20these=20are=20= relevant=20error=20codes=20that=20can=20occur=20in=20certificate=0A+=09=20= *=20validation,=20figure=20out=20which=20we=20don't=20want=20for=20= require/prefer=20etc.=0A+=09=20*/=0A+=09switch=20(err)=0A+=09{=0A+=09=09= case=20SEC_ERROR_INVALID_AVA:=0A+=09=09case=20SEC_ERROR_INVALID_TIME:=0A= +=09=09case=20SEC_ERROR_BAD_SIGNATURE:=0A+=09=09case=20= SEC_ERROR_EXPIRED_CERTIFICATE:=0A+=09=09case=20SEC_ERROR_UNKNOWN_ISSUER:=0A= +=09=09case=20SEC_ERROR_UNTRUSTED_ISSUER:=0A+=09=09case=20= SEC_ERROR_UNTRUSTED_CERT:=0A+=09=09case=20SEC_ERROR_CERT_VALID:=0A+=09=09= case=20SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:=0A+=09=09case=20= SEC_ERROR_CRL_EXPIRED:=0A+=09=09case=20SEC_ERROR_CRL_BAD_SIGNATURE:=0A+=09= =09case=20SEC_ERROR_EXTENSION_VALUE_INVALID:=0A+=09=09case=20= SEC_ERROR_CA_CERT_INVALID:=0A+=09=09case=20= SEC_ERROR_CERT_USAGES_INVALID:=0A+=09=09case=20= SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:=0A+=09=09=09return=20SECSuccess;=0A= +=09=09=09break;=0A+=09=09default:=0A+=09=09=09return=20SECFailure;=0A+=09= =09=09break;=0A+=09}=0A+=0A+=09/*=20Unreachable=20*/=0A+=09return=20= SECSuccess;=0A+}=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09=09=09SSL=20information=20functions=09=09=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +/*=0A+=20*=20PQgetssl=0A+=20*=0A+=20*=20Return=20NULL=20as=20this=20is=20= legacy=20and=20defined=20to=20always=20be=20equal=20to=20calling=0A+=20*=20= PQsslStruct(conn,=20"OpenSSL");=20This=20should=20ideally=20trigger=20a=20= logged=20warning=0A+=20*=20somewhere=20as=20it's=20nonsensical=20to=20= run=20in=20a=20non-OpenSSL=20build,=20but=20the=20color=0A+=20*=20of=20= said=20bikeshed=20hasn't=20yet=20been=20determined.=0A+=20*/=0A+void=20*=0A= +PQgetssl(PGconn=20*conn)=0A+{=0A+=09return=20NULL;=0A+}=0A+=0A+void=20*=0A= +PQsslStruct(PGconn=20*conn,=20const=20char=20*struct_name)=0A+{=0A+=09= if=20(!conn)=0A+=09=09return=20NULL;=0A+=0A+=09/*=0A+=09=20*=20Return=20= the=20underlying=20PRFileDesc=20which=20can=20be=20used=20to=20access=0A= +=09=20*=20information=20on=20the=20connection=20details.=20There=20is=20= no=20SSL=20context=20per=20se.=0A+=09=20*/=0A+=09if=20= (strcmp(struct_name,=20"NSS")=20=3D=3D=200)=0A+=09=09return=20= conn->pr_fd;=0A+=09return=20NULL;=0A+}=0A+=0A+const=20char=20*const=20*=0A= +PQsslAttributeNames(PGconn=20*conn)=0A+{=0A+=09static=20const=20char=20= *const=20result[]=20=3D=20{=0A+=09=09"library",=0A+=09=09"cipher",=0A+=09= =09"protocol",=0A+=09=09"key_bits",=0A+=09=09"compression",=0A+=09=09= NULL=0A+=09};=0A+=0A+=09return=20result;=0A+}=0A+=0A+const=20char=20*=0A= +PQsslAttribute(PGconn=20*conn,=20const=20char=20*attribute_name)=0A+{=0A= +=09SECStatus=09status;=0A+=09SSLChannelInfo=20channel;=0A+=09= SSLCipherSuiteInfo=20suite;=0A+=0A+=09if=20(!conn=20||=20!conn->pr_fd)=0A= +=09=09return=20NULL;=0A+=0A+=09if=20(strcmp(attribute_name,=20= "library")=20=3D=3D=200)=0A+=09=09return=20"NSS";=0A+=0A+=09status=20=3D=20= SSL_GetChannelInfo(conn->pr_fd,=20&channel,=20sizeof(channel));=0A+=09if=20= (status=20!=3D=20SECSuccess)=0A+=09=09return=20NULL;=0A+=0A+=09status=20= =3D=20SSL_GetCipherSuiteInfo(channel.cipherSuite,=20&suite,=20= sizeof(suite));=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20= NULL;=0A+=0A+=09if=20(strcmp(attribute_name,=20"cipher")=20=3D=3D=200)=0A= +=09=09return=20suite.cipherSuiteName;=0A+=0A+=09if=20= (strcmp(attribute_name,=20"key_bits")=20=3D=3D=200)=0A+=09{=0A+=09=09= static=20char=20key_bits_str[8];=0A+=0A+=09=09snprintf(key_bits_str,=20= sizeof(key_bits_str),=20"%i",=20suite.effectiveKeyBits);=0A+=09=09return=20= key_bits_str;=0A+=09}=0A+=0A+=09if=20(strcmp(attribute_name,=20= "protocol")=20=3D=3D=200)=0A+=09{=0A+=09=09switch=20= (channel.protocolVersion)=0A+=09=09{=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_3=0A+=09=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_3:=0A+=09=09=09=09return=20"TLSv1.3";=0A= +#endif=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_2=0A+=09=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_2:=0A+=09=09=09=09return=20"TLSv1.2";=0A= +#endif=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_1=0A+=09=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_1:=0A+=09=09=09=09return=20"TLSv1.1";=0A= +#endif=0A+=09=09=09case=20SSL_LIBRARY_VERSION_TLS_1_0:=0A+=09=09=09=09= return=20"TLSv1.0";=0A+=09=09=09default:=0A+=09=09=09=09return=20= "unknown";=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20NSS=20disabled=20= support=20for=20compression=20in=20version=203.33,=20and=20it=20was=20= only=0A+=09=20*=20available=20for=20SSLv3=20at=20that=20point=20anyways,=20= so=20we=20can=20safely=20return=20off=0A+=09=20*=20here=20without=20= checking.=0A+=09=20*/=0A+=09if=20(strcmp(attribute_name,=20= "compression")=20=3D=3D=200)=0A+=09=09return=20"off";=0A+=0A+=09return=20= NULL;=0A+}=0A+=0A+static=20int=0A+ssl_protocol_version_to_nss(const=20= char=20*protocol)=0A+{=0A+=09if=20(pg_strcasecmp("TLSv1",=20protocol)=20= =3D=3D=200)=0A+=09=09return=20SSL_LIBRARY_VERSION_TLS_1_0;=0A+=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_1=0A+=09if=20(pg_strcasecmp("TLSv1.1",=20= protocol)=20=3D=3D=200)=0A+=09=09return=20SSL_LIBRARY_VERSION_TLS_1_1;=0A= +#endif=0A+=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_2=0A+=09if=20= (pg_strcasecmp("TLSv1.2",=20protocol)=20=3D=3D=200)=0A+=09=09return=20= SSL_LIBRARY_VERSION_TLS_1_2;=0A+#endif=0A+=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_3=0A+=09if=20(pg_strcasecmp("TLSv1.3",=20= protocol)=20=3D=3D=200)=0A+=09=09return=20SSL_LIBRARY_VERSION_TLS_1_3;=0A= +#endif=0A+=0A+=09return=20-1;=0A+}=0A+=0A+/*=0A+=20*=20= cert_database_has_CA=0A+=20*=0A+=20*=20Returns=20true=20in=20case=20= there=20is=20a=20CA=20certificate=20in=20the=20database=20connected=0A+=20= *=20to=20in=20the=20conn=20object,=20else=20false.=20This=20function=20= only=20checks=20for=20the=0A+=20*=20presence=20of=20a=20CA=20= certificate,=20not=20it's=20validity=20and/or=20usefulness.=0A+=20*/=0A= +static=20bool=0A+cert_database_has_CA(PGconn=20*conn)=0A+{=0A+=09= CERTCertList=20*certificates;=0A+=09bool=09=09hasCA;=0A+=0A+=09/*=0A+=09=20= *=20If=20the=20certificate=20database=20has=20a=20password=20we=20must=20= provide=20it,=20since=0A+=09=20*=20this=20API=20doesn't=20invoke=20the=20= standard=20password=20callback.=0A+=09=20*/=0A+=09if=20= (conn->has_password)=0A+=09=09certificates=20=3D=20= PK11_ListCerts(PK11CertListCA,=20PQssl_passwd_cb(NULL,=20PR_FALSE,=20= (void=20*)=20conn));=0A+=09else=0A+=09=09certificates=20=3D=20= PK11_ListCerts(PK11CertListCA,=20NULL);=0A+=09hasCA=20=3D=20= !CERT_LIST_EMPTY(certificates);=0A+=09= CERT_DestroyCertList(certificates);=0A+=0A+=09return=20hasCA;=0A+}=0A+=0A= +PQsslKeyPassHook_nss_type=0A+PQgetSSLKeyPassHook_nss(void)=0A+{=0A+=09= return=20PQsslKeyPassHook;=0A+}=0A+=0A+void=0A= +PQsetSSLKeyPassHook_nss(PQsslKeyPassHook_nss_type=20hook)=0A+{=0A+=09= PQsslKeyPassHook=20=3D=20hook;=0A+}=0A+=0A+/*=0A+=20*=20Supply=20a=20= password=20to=20decrypt=20a=20client=20certificate.=0A+=20*=0A+=20*=20= This=20must=20match=20NSS=20type=20PK11PasswordFunc.=0A+=20*/=0A+static=20= char=20*=0A+PQssl_passwd_cb(PK11SlotInfo=20*slot,=20PRBool=20retry,=20= void=20*arg)=0A+{=0A+=09PGconn=09=20=20=20*conn=20=3D=20(PGconn=20*)=20= arg;=0A+=0A+=09conn->has_password=20=3D=20true;=0A+=0A+=09if=20= (PQsslKeyPassHook)=0A+=09=09return=20PQsslKeyPassHook(slot,=20(PRBool)=20= retry,=20arg);=0A+=09else=0A+=09=09return=20= PQdefaultSSLKeyPassHook_nss(slot,=20retry,=20arg);=0A+}=0A+=0A+/*=0A+=20= *=20The=20default=20password=20handler=20callback.=0A+=20*/=0A+char=20*=0A= +PQdefaultSSLKeyPassHook_nss(PK11SlotInfo=20*=20slot,=20PRBool=20retry,=20= void=20*arg)=0A+{=0A+=09PGconn=09=20=20=20*conn=20=3D=20(PGconn=20*)=20= arg;=0A+=0A+=09/*=0A+=09=20*=20If=20the=20password=20didn't=20work=20the=20= first=20time=20there=20is=20no=20point=20in=0A+=09=20*=20retrying=20as=20= it=20hasn't=20changed.=0A+=09=20*/=0A+=09if=20(retry=20!=3D=20PR_TRUE=20= &&=20conn->sslpassword=20&&=20strlen(conn->sslpassword)=20>=200)=0A+=09=09= return=20PORT_Strdup(conn->sslpassword);=0A+=0A+=09return=20NULL;=0A+}=0A= diff=20--git=20a/src/interfaces/libpq/fe-secure.c=20= b/src/interfaces/libpq/fe-secure.c=0Aindex=2000b87bdc96..44385ee391=20= 100644=0A---=20a/src/interfaces/libpq/fe-secure.c=0A+++=20= b/src/interfaces/libpq/fe-secure.c=0A@@=20-421,6=20+421,9=20@@=20= PQsslAttributeNames(PGconn=20*conn)=0A=20=0A=20=09return=20result;=0A=20= }=0A+#endif=09=09=09=09=09=09=09/*=20USE_SSL=20*/=0A+=0A+#ifndef=20= USE_OPENSSL=0A=20=0A=20PQsslKeyPassHook_OpenSSL_type=0A=20= PQgetSSLKeyPassHook_OpenSSL(void)=0A@@=20-439,7=20+442,7=20@@=20= PQdefaultSSLKeyPassHook_OpenSSL(char=20*buf,=20int=20size,=20PGconn=20= *conn)=0A=20{=0A=20=09return=200;=0A=20}=0A-#endif=09=09=09=09=09=09=09= /*=20USE_SSL=20*/=0A+#endif=09=09=09=09=09=09=09/*=20USE_OPENSSL=20*/=0A=20= =0A=20/*=20Dummy=20version=20of=20GSSAPI=20information=20functions,=20= when=20built=20without=20GSS=20support=20*/=0A=20#ifndef=20ENABLE_GSS=0A= diff=20--git=20a/src/interfaces/libpq/libpq-fe.h=20= b/src/interfaces/libpq/libpq-fe.h=0Aindex=20c266ad5b13..aba32e6635=20= 100644=0A---=20a/src/interfaces/libpq/libpq-fe.h=0A+++=20= b/src/interfaces/libpq/libpq-fe.h=0A@@=20-619,12=20+619,23=20@@=20extern=20= int=09pg_valid_server_encoding_id(int=20encoding);=0A=20=0A=20/*=20=3D=3D=3D= =20in=20fe-secure-openssl.c=20=3D=3D=3D=20*/=0A=20=0A-/*=20Support=20for=20= overriding=20sslpassword=20handling=20with=20a=20callback.=20*/=0A+/*=20= Support=20for=20overriding=20sslpassword=20handling=20with=20a=20= callback=20*/=0A=20typedef=20int=20(*PQsslKeyPassHook_OpenSSL_type)=20= (char=20*buf,=20int=20size,=20PGconn=20*conn);=0A=20extern=20= PQsslKeyPassHook_OpenSSL_type=20PQgetSSLKeyPassHook_OpenSSL(void);=0A=20= extern=20void=20= PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type=20hook);=0A=20= extern=20int=09PQdefaultSSLKeyPassHook_OpenSSL(char=20*buf,=20int=20= size,=20PGconn=20*conn);=0A=20=0A+/*=20=3D=3D=20in=20fe-secure-nss.c=20= =3D=3D=3D=20*/=0A+typedef=20struct=20PK11SlotInfoStr=20PK11SlotInfo;=0A= +typedef=20int=20PRIntn;=0A+typedef=20PRIntn=20PRBool;=0A+=0A+/*=20= Support=20for=20overriding=20sslpassword=20handling=20with=20a=20= callback=20*/=0A+typedef=20char=20*(*PQsslKeyPassHook_nss_type)=20= (PK11SlotInfo=20*slot,=20PRBool=20retry,=20void=20*arg);=0A+extern=20= PQsslKeyPassHook_nss_type=20PQgetSSLKeyPassHook_nss(void);=0A+extern=20= void=20PQsetSSLKeyPassHook_nss(PQsslKeyPassHook_nss_type=20hook);=0A= +extern=20char=20*PQdefaultSSLKeyPassHook_nss(PK11SlotInfo=20*slot,=20= PRBool=20retry,=20void=20*arg);=0A+=0A=20#ifdef=20__cplusplus=0A=20}=0A=20= #endif=0Adiff=20--git=20a/src/interfaces/libpq/libpq-int.h=20= b/src/interfaces/libpq/libpq-int.h=0Aindex=204db498369c..a95450fbba=20= 100644=0A---=20a/src/interfaces/libpq/libpq-int.h=0A+++=20= b/src/interfaces/libpq/libpq-int.h=0A@@=20-362,6=20+362,7=20@@=20struct=20= pg_conn=0A=20=09char=09=20=20=20*sslpassword;=09/*=20client=20key=20file=20= password=20*/=0A=20=09char=09=20=20=20*sslrootcert;=09/*=20root=20= certificate=20filename=20*/=0A=20=09char=09=20=20=20*sslcrl;=09=09=09/*=20= certificate=20revocation=20list=20filename=20*/=0A+=09char=09=20=20=20= *cert_database;=09/*=20NSS=20certificate/key=20database=20*/=0A=20=09= char=09=20=20=20*requirepeer;=09/*=20required=20peer=20credentials=20for=20= local=20sockets=20*/=0A=20=09char=09=20=20=20*gssencmode;=09=09/*=20GSS=20= mode=20(require,prefer,disable)=20*/=0A=20=09char=09=20=20=20= *krbsrvname;=09=09/*=20Kerberos=20service=20name=20*/=0A@@=20-485,6=20= +486,23=20@@=20struct=20pg_conn=0A=20=09=09=09=09=09=09=09=09=20*=20= OpenSSL=20version=20changes=20*/=0A=20#endif=0A=20#endif=09=09=09=09=09=09= =09/*=20USE_OPENSSL=20*/=0A+=0A+#ifdef=20USE_NSS=0A+=09void=09=20=20=20= *pr_fd;=09=09=09/*=20NSPR=20file=20descriptor=20for=20the=20connection=20= */=0A+=0A+=09/*=0A+=09=20*=20Track=20whether=20the=20NSS=20database=20= has=20a=20password=20set=20or=20not.=20There=20is=20no=0A+=09=20*=20API=20= function=20for=20retrieving=20password=20status=20of=20a=20database,=20= but=20we=20need=0A+=09=20*=20to=20know=20since=20some=20NSS=20API=20= calls=20require=20the=20password=20passed=20in=20(they=0A+=09=20*=20= don't=20call=20the=20callback=20themselves).=20To=20track,=20we=20simply=20= flip=20this=20to=0A+=09=20*=20true=20in=20case=20NSS=20invoked=20the=20= password=20callback=20-=20as=20that=20will=20only=0A+=09=20*=20happen=20= in=20case=20there=20is=20a=20password.=20The=20reason=20for=20tracking=20= this=20is=0A+=09=20*=20that=20there=20are=20calls=20which=20require=20a=20= password=20parameter,=20but=20doesn't=0A+=09=20*=20use=20the=20callbacks=20= provided,=20so=20we=20must=20call=20the=20callback=20on=20behalf=20of=0A= +=09=20*=20these.=0A+=09=20*/=0A+=09bool=09=09has_password;=0A+#endif=09=09= =09=09=09=09=09/*=20USE_NSS=20*/=0A=20#endif=09=09=09=09=09=09=09/*=20= USE_SSL=20*/=0A=20=0A=20#ifdef=20ENABLE_GSS=0A@@=20-759,7=20+777,7=20@@=20= extern=20ssize_t=20pgtls_write(PGconn=20*conn,=20const=20void=20*ptr,=20= size_t=20len);=0A=20=20*=20This=20is=20not=20supported=20with=20old=20= versions=20of=20OpenSSL=20that=20don't=20have=0A=20=20*=20the=20= X509_get_signature_nid()=20function.=0A=20=20*/=0A-#if=20= defined(USE_OPENSSL)=20&&=20defined(HAVE_X509_GET_SIGNATURE_NID)=0A+#if=20= defined(USE_NSS)=20||=20(defined(USE_OPENSSL)=20&&=20= defined(HAVE_X509_GET_SIGNATURE_NID))=0A=20#define=20= HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH=0A=20extern=20char=20= *pgtls_get_peer_certificate_hash(PGconn=20*conn,=20size_t=20*len);=0A=20= #endif=0Adiff=20--git=20a/src/tools/msvc/Mkvcbuild.pm=20= b/src/tools/msvc/Mkvcbuild.pm=0Aindex=2090328db04e..ff01acf3f6=20100644=0A= ---=20a/src/tools/msvc/Mkvcbuild.pm=0A+++=20= b/src/tools/msvc/Mkvcbuild.pm=0A@@=20-195,12=20+195,19=20@@=20sub=20= mkvcbuild=0A=20=09$postgres->FullExportDLL('postgres.lib');=0A=20=0A=20=09= #=20The=20OBJS=20scraper=20doesn't=20know=20about=20ifdefs,=20so=20= remove=20appropriate=20files=0A-=09#=20if=20building=20without=20= OpenSSL.=0A-=09if=20(!$solution->{options}->{openssl})=0A+=09#=20if=20= building=20without=20various=20options.=0A+=09if=20= (!$solution->{options}->{openssl}=20&&=20!$solution->{options}->{nss})=0A= =20=09{=0A=20=09=09= $postgres->RemoveFile('src/backend/libpq/be-secure-common.c');=0A+=09}=0A= +=09if=20(!$solution->{options}->{openssl})=0A+=09{=0A=20=09=09= $postgres->RemoveFile('src/backend/libpq/be-secure-openssl.c');=0A=20=09= }=0A+=09if=20(!$solution->{options}->{nss})=0A+=09{=0A+=09=09= $postgres->RemoveFile('src/backend/libpq/be-secure-nss.c');=0A+=09}=0A=20= =09if=20(!$solution->{options}->{gss})=0A=20=09{=0A=20=09=09= $postgres->RemoveFile('src/backend/libpq/be-gssapi-common.c');=0A@@=20= -258,12=20+265,19=20@@=20sub=20mkvcbuild=0A=20=09= $libpq->AddReference($libpgcommon,=20$libpgport);=0A=20=0A=20=09#=20The=20= OBJS=20scraper=20doesn't=20know=20about=20ifdefs,=20so=20remove=20= appropriate=20files=0A-=09#=20if=20building=20without=20OpenSSL.=0A-=09= if=20(!$solution->{options}->{openssl})=0A+=09#=20if=20building=20= without=20various=20options=0A+=09if=20(!$solution->{options}->{openssl}=20= &&=20!$solution->{options}->{nss})=0A=20=09{=0A=20=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-secure-common.c');=0A+=09}=0A= +=09if=20(!$solution->{options}->{openssl})=0A+=09{=0A=20=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-secure-openssl.c');=0A=20=09= }=0A+=09if=20(!$solution->{options}->{nss})=0A+=09{=0A+=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-secure-nss.c');=0A+=09}=0A=20= =09if=20(!$solution->{options}->{gss})=0A=20=09{=0A=20=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-gssapi-common.c');=0Adiff=20= --git=20a/src/tools/msvc/Solution.pm=20b/src/tools/msvc/Solution.pm=0A= index=202f28de0355..aece3edfc8=20100644=0A---=20= a/src/tools/msvc/Solution.pm=0A+++=20b/src/tools/msvc/Solution.pm=0A@@=20= -488,6=20+488,7=20@@=20sub=20GenerateFiles=0A=20=09=09USE_LLVM=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=3D>=20undef,=0A=20=09=09= USE_NAMED_POSIX_SEMAPHORES=20=3D>=20undef,=0A=20=09=09USE_OPENSSL=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=3D>=20undef,=0A+=09=09USE_NSS=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=3D>=20undef,=0A=20= =09=09USE_PAM=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =3D>=20undef,=0A=20=09=09USE_SLICING_BY_8_CRC32C=20=20=20=20=3D>=20= undef,=0A=20=09=09USE_SSE42_CRC32C=20=20=20=20=20=20=20=20=20=20=20=3D>=20= undef,=0A@@=20-540,6=20+541,10=20@@=20sub=20GenerateFiles=0A=20=09=09=09= $define{HAVE_OPENSSL_INIT_SSL}=20=20=20=20=20=20=3D=201;=0A=20=09=09}=0A=20= =09}=0A+=09if=20($self->{options}->{nss})=0A+=09{=0A+=09=09= $define{USE_NSS}=20=3D=201;=0A+=09}=0A=20=0A=20=09= $self->GenerateConfigHeader('src/include/pg_config.h',=20=20=20=20=20= \%define,=201);=0A=20=09= $self->GenerateConfigHeader('src/include/pg_config_ext.h',=20\%define,=20= 0);=0A@@=20-1005,6=20+1010,21=20@@=20sub=20AddProject=0A=20=09=09=09}=0A=20= =09=09}=0A=20=09}=0A+=09if=20($self->{options}->{nss})=0A+=09{=0A+=09=09= $proj->AddIncludeDir($self->{options}->{nss}=20.=20'\..\public\nss');=0A= +=09=09$proj->AddIncludeDir($self->{options}->{nss}=20.=20= '\include\nspr');=0A+=09=09foreach=20my=20$lib=20(qw(plds4=20plc4=20= nspr4))=0A+=09=09{=0A+=09=09=09$proj->AddLibrary($self->{options}->{nss}=20= .=0A+=09=09=09=09=09=09=09=20=20'\lib\lib'=20.=20"$lib.lib",=200);=0A+=09= =09}=0A+=09=09foreach=20my=20$lib=20(qw(ssl3=20smime3=20nss3))=0A+=09=09= {=0A+=09=09=09$proj->AddLibrary($self->{options}->{nss}=20.=0A+=09=09=09=09= =09=09=09=20=20'\lib'=20.=20"\\$lib.dll.lib",=200);=0A+=09=09}=0A+=09}=0A= =20=09if=20($self->{options}->{nls})=0A=20=09{=0A=20=09=09= $proj->AddIncludeDir($self->{options}->{nls}=20.=20'\include');=0Adiff=20= --git=20a/src/tools/msvc/config_default.pl=20= b/src/tools/msvc/config_default.pl=0Aindex=202ef2cfc4e9..49dc4d5864=20= 100644=0A---=20a/src/tools/msvc/config_default.pl=0A+++=20= b/src/tools/msvc/config_default.pl=0A@@=20-17,6=20+17,7=20@@=20our=20= $config=20=3D=20{=0A=20=09perl=20=20=20=20=20=20=3D>=20undef,=20=20=20=20= #=20--with-perl=3D=0A=20=09python=20=20=20=20=3D>=20undef,=20=20=20= =20#=20--with-python=3D=0A=20=09openssl=20=20=20=3D>=20undef,=20=20= =20=20#=20--with-openssl=3D=0A+=09nss=20=20=20=20=20=20=20=3D>=20= undef,=20=20=20=20#=20--with-nss=3D=0A=20=09uuid=20=20=20=20=20=20= =3D>=20undef,=20=20=20=20#=20--with-uuid=3D=0A=20=09xml=20=20=20=20= =20=20=20=3D>=20undef,=20=20=20=20#=20--with-libxml=3D=0A=20=09= xslt=20=20=20=20=20=20=3D>=20undef,=20=20=20=20#=20--with-libxslt=3D= =0A--=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2 Content-Disposition: attachment; filename=v23-0001-Introduce-with-ssl.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v23-0001-Introduce-with-ssl.patch" Content-Transfer-Encoding: quoted-printable =46rom=20b319d0be8ddbda4a4e0e3600521da83240bd6e73=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2027=20Jan=202021=2014:41:05=20+0100=0ASubject:=20[PATCH=20= v23=201/8]=20Introduce=20--with-ssl=0A=0A---=0A=20configure=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20|=20110=20+++++++++++-------=0A=20configure.ac=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20|=20=2031=20+++--=0A=20contrib/Makefile=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=202=20+-=0A=20contrib/pgcrypto/Makefile=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20|=20=20=204=20+-=0A=20= src/Makefile.global.in=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20|=20=20=202=20+-=0A=20src/backend/libpq/Makefile=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=202=20+-=0A= =20src/common/Makefile=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20|=20=20=202=20+-=0A=20= src/interfaces/libpq/Makefile=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20|=20=20=208=20+-=0A=20src/test/Makefile=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=202=20= +-=0A=20src/test/modules/Makefile=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20|=20=20=202=20+-=0A=20= .../modules/ssl_passphrase_callback/Makefile=20=20|=20=20=202=20+-=0A=20= .../ssl_passphrase_callback/t/001_testfunc.pl=20|=20=20=204=20+-=0A=20= src/test/ssl/Makefile=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20|=20=20=202=20+-=0A=2013=20files=20changed,=20108=20= insertions(+),=2065=20deletions(-)=0A=0Adiff=20--git=20a/configure=20= b/configure=0Aindex=20e202697bbf..ce9ea36999=20100755=0A---=20= a/configure=0A+++=20b/configure=0A@@=20-653,6=20+653,7=20@@=20LIBOBJS=0A=20= UUID_LIBS=0A=20LDAP_LIBS_BE=0A=20LDAP_LIBS_FE=0A+with_ssl=0A=20= PTHREAD_CFLAGS=0A=20PTHREAD_LIBS=0A=20PTHREAD_CC=0A@@=20-709,7=20+710,6=20= @@=20with_uuid=0A=20with_readline=0A=20with_systemd=0A=20with_selinux=0A= -with_openssl=0A=20with_ldap=0A=20with_krb_srvnam=0A=20krb_srvtab=0A@@=20= -854,7=20+854,6=20@@=20with_pam=0A=20with_bsd_auth=0A=20with_ldap=0A=20= with_bonjour=0A-with_openssl=0A=20with_selinux=0A=20with_systemd=0A=20= with_readline=0A@@=20-866,6=20+865,8=20@@=20with_libxslt=0A=20= with_system_tzdata=0A=20with_zlib=0A=20with_gnu_ld=0A+with_ssl=0A= +with_openssl=0A=20enable_largefile=0A=20'=0A=20=20=20=20=20=20=20= ac_precious_vars=3D'build_alias=0A@@=20-1556,7=20+1557,6=20@@=20Optional=20= Packages:=0A=20=20=20--with-bsd-auth=20=20=20=20=20=20=20=20=20build=20= with=20BSD=20Authentication=20support=0A=20=20=20--with-ldap=20=20=20=20=20= =20=20=20=20=20=20=20=20build=20with=20LDAP=20support=0A=20=20=20= --with-bonjour=20=20=20=20=20=20=20=20=20=20build=20with=20Bonjour=20= support=0A-=20=20--with-openssl=20=20=20=20=20=20=20=20=20=20build=20= with=20OpenSSL=20support=0A=20=20=20--with-selinux=20=20=20=20=20=20=20=20= =20=20build=20with=20SELinux=20support=0A=20=20=20--with-systemd=20=20=20= =20=20=20=20=20=20=20build=20with=20systemd=20support=0A=20=20=20= --without-readline=20=20=20=20=20=20do=20not=20use=20GNU=20Readline=20= nor=20BSD=20Libedit=20for=20editing=0A@@=20-1570,6=20+1570,8=20@@=20= Optional=20Packages:=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20use=20system=20time=20zone=20data=20in=20= DIR=0A=20=20=20--without-zlib=20=20=20=20=20=20=20=20=20=20do=20not=20= use=20Zlib=0A=20=20=20--with-gnu-ld=20=20=20=20=20=20=20=20=20=20=20= assume=20the=20C=20compiler=20uses=20GNU=20ld=20[default=3Dno]=0A+=20=20= --with-ssl=3DLIB=20=20=20=20=20=20=20=20=20=20use=20LIB=20for=20SSL/TLS=20= support=20(openssl)=0A+=20=20--with-openssl=20=20=20=20=20=20=20=20=20=20= obsolete=20spelling=20of=20--with-ssl=3Dopenssl=0A=20=0A=20Some=20= influential=20environment=20variables:=0A=20=20=20CC=20=20=20=20=20=20=20= =20=20=20C=20compiler=20command=0A@@=20-8070,41=20+8072,6=20@@=20fi=0A=20= $as_echo=20"$with_bonjour"=20>&6;=20}=0A=20=0A=20=0A-#=0A-#=20OpenSSL=0A= -#=0A-{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20checking=20whether=20= to=20build=20with=20OpenSSL=20support"=20>&5=0A-$as_echo_n=20"checking=20= whether=20to=20build=20with=20OpenSSL=20support...=20"=20>&6;=20}=0A-=0A= -=0A-=0A-#=20Check=20whether=20--with-openssl=20was=20given.=0A-if=20= test=20"${with_openssl+set}"=20=3D=20set;=20then=20:=0A-=20=20= withval=3D$with_openssl;=0A-=20=20case=20$withval=20in=0A-=20=20=20=20= yes)=0A-=0A-$as_echo=20"#define=20USE_OPENSSL=201"=20>>confdefs.h=0A-=0A= -=20=20=20=20=20=20;;=0A-=20=20=20=20no)=0A-=20=20=20=20=20=20:=0A-=20=20= =20=20=20=20;;=0A-=20=20=20=20*)=0A-=20=20=20=20=20=20as_fn_error=20$?=20= "no=20argument=20expected=20for=20--with-openssl=20option"=20"$LINENO"=20= 5=0A-=20=20=20=20=20=20;;=0A-=20=20esac=0A-=0A-else=0A-=20=20= with_openssl=3Dno=0A-=0A-fi=0A-=0A-=0A-{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20$with_openssl"=20>&5=0A= -$as_echo=20"$with_openssl"=20>&6;=20}=0A-=0A-=0A=20#=0A=20#=20SELinux=0A= =20#=0A@@=20-12174,7=20+12141,64=20@@=20fi=0A=20=20=20fi=0A=20fi=0A=20=0A= +#=0A+#=20SSL=20Library=0A+#=0A+#=20There=20is=20currently=20only=20one=20= supported=20SSL/TLS=20library:=20OpenSSL.=0A+#=0A+=0A+=0A+=0A+#=20Check=20= whether=20--with-ssl=20was=20given.=0A+if=20test=20"${with_ssl+set}"=20=3D= =20set;=20then=20:=0A+=20=20withval=3D$with_ssl;=0A+=20=20case=20= $withval=20in=0A+=20=20=20=20yes)=0A+=20=20=20=20=20=20as_fn_error=20$?=20= "argument=20required=20for=20--with-ssl=20option"=20"$LINENO"=205=0A+=20=20= =20=20=20=20;;=0A+=20=20=20=20no)=0A+=20=20=20=20=20=20as_fn_error=20$?=20= "argument=20required=20for=20--with-ssl=20option"=20"$LINENO"=205=0A+=20=20= =20=20=20=20;;=0A+=20=20=20=20*)=0A+=0A+=20=20=20=20=20=20;;=0A+=20=20= esac=0A+=0A+fi=0A+=0A+=0A+if=20test=20x"$with_ssl"=20=3D=20x""=20;=20= then=0A+=20=20with_ssl=3Dno=0A+fi=0A+=0A+=0A+=0A+#=20Check=20whether=20= --with-openssl=20was=20given.=0A+if=20test=20"${with_openssl+set}"=20=3D=20= set;=20then=20:=0A+=20=20withval=3D$with_openssl;=0A+=20=20case=20= $withval=20in=0A+=20=20=20=20yes)=0A+=20=20=20=20=20=20:=0A+=20=20=20=20=20= =20;;=0A+=20=20=20=20no)=0A+=20=20=20=20=20=20:=0A+=20=20=20=20=20=20;;=0A= +=20=20=20=20*)=0A+=20=20=20=20=20=20as_fn_error=20$?=20"no=20argument=20= expected=20for=20--with-openssl=20option"=20"$LINENO"=205=0A+=20=20=20=20= =20=20;;=0A+=20=20esac=0A+=0A+else=0A+=20=20with_openssl=3Dno=0A+=0A+fi=0A= +=0A+=0A=20if=20test=20"$with_openssl"=20=3D=20yes=20;=20then=0A+=20=20= with_ssl=3Dopenssl=0A+fi=0A+=0A+if=20test=20"$with_ssl"=20=3D=20openssl=20= ;=20then=0A=20=20=20=20=20#=20Minimum=20required=20OpenSSL=20version=20= is=201.0.1=0A=20=0A=20$as_echo=20"#define=20OPENSSL_API_COMPAT=20= 0x10001000L"=20>>confdefs.h=0A@@=20-12435,8=20+12459,14=20@@=20_ACEOF=0A=20= fi=0A=20done=0A=20=0A+=0A+$as_echo=20"#define=20USE_OPENSSL=201"=20= >>confdefs.h=0A+=0A+elif=20test=20"$with_ssl"=20!=3D=20no=20;=20then=0A+=20= =20as_fn_error=20$?=20"--with-ssl=20must=20specify=20openssl"=20= "$LINENO"=205=0A=20fi=0A=20=0A+=0A=20if=20test=20"$with_pam"=20=3D=20yes=20= ;=20then=0A=20=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20= checking=20for=20pam_start=20in=20-lpam"=20>&5=0A=20$as_echo_n=20= "checking=20for=20pam_start=20in=20-lpam...=20"=20>&6;=20}=0A@@=20= -13322,7=20+13352,7=20@@=20done=0A=20=0A=20fi=0A=20=0A-if=20test=20= "$with_openssl"=20=3D=20yes=20;=20then=0A+if=20test=20"$with_ssl"=20=3D=20= openssl=20;=20then=0A=20=20=20ac_fn_c_check_header_mongrel=20"$LINENO"=20= "openssl/ssl.h"=20"ac_cv_header_openssl_ssl_h"=20"$ac_includes_default"=0A= =20if=20test=20"x$ac_cv_header_openssl_ssl_h"=20=3D=20xyes;=20then=20:=0A= =20=0A@@=20-18098,7=20+18128,7=20@@=20fi=0A=20#=20will=20be=20used.=0A=20= {=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20checking=20which=20random=20= number=20source=20to=20use"=20>&5=0A=20$as_echo_n=20"checking=20which=20= random=20number=20source=20to=20use...=20"=20>&6;=20}=0A-if=20test=20= x"$with_openssl"=20=3D=20x"yes"=20;=20then=0A+if=20test=20x"$with_ssl"=20= =3D=20x"openssl"=20;=20then=0A=20=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20OpenSSL"=20>&5=0A=20$as_echo=20= "OpenSSL"=20>&6;=20}=0A=20elif=20test=20x"$PORTNAME"=20=3D=20x"win32"=20= ;=20then=0Adiff=20--git=20a/configure.ac=20b/configure.ac=0Aindex=20= a5ad072ee4..07da84d401=20100644=0A---=20a/configure.ac=0A+++=20= b/configure.ac=0A@@=20-852,15=20+852,6=20@@=20PGAC_ARG_BOOL(with,=20= bonjour,=20no,=0A=20AC_MSG_RESULT([$with_bonjour])=0A=20=0A=20=0A-#=0A-#=20= OpenSSL=0A-#=0A-AC_MSG_CHECKING([whether=20to=20build=20with=20OpenSSL=20= support])=0A-PGAC_ARG_BOOL(with,=20openssl,=20no,=20[build=20with=20= OpenSSL=20support],=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= [AC_DEFINE([USE_OPENSSL],=201,=20[Define=20to=20build=20with=20OpenSSL=20= support.=20(--with-openssl)])])=0A-AC_MSG_RESULT([$with_openssl])=0A= -AC_SUBST(with_openssl)=0A-=0A=20#=0A=20#=20SELinux=0A=20#=0A@@=20= -1205,7=20+1196,21=20@@=20if=20test=20"$with_gssapi"=20=3D=20yes=20;=20= then=0A=20=20=20fi=0A=20fi=0A=20=0A+#=0A+#=20SSL=20Library=0A+#=0A+#=20= There=20is=20currently=20only=20one=20supported=20SSL/TLS=20library:=20= OpenSSL.=0A+#=0A+PGAC_ARG_REQ(with,=20ssl,=20[LIB],=20[use=20LIB=20for=20= SSL/TLS=20support=20(openssl)])=0A+if=20test=20x"$with_ssl"=20=3D=20x""=20= ;=20then=0A+=20=20with_ssl=3Dno=0A+fi=0A+PGAC_ARG_BOOL(with,=20openssl,=20= no,=20[obsolete=20spelling=20of=20--with-ssl=3Dopenssl])=0A=20if=20test=20= "$with_openssl"=20=3D=20yes=20;=20then=0A+=20=20with_ssl=3Dopenssl=0A+fi=0A= +=0A+if=20test=20"$with_ssl"=20=3D=20openssl=20;=20then=0A=20=20=20dnl=20= Order=20matters!=0A=20=20=20#=20Minimum=20required=20OpenSSL=20version=20= is=201.0.1=0A=20=20=20AC_DEFINE(OPENSSL_API_COMPAT,=20[0x10001000L],=0A= @@=20-1229,7=20+1234,11=20@@=20if=20test=20"$with_openssl"=20=3D=20yes=20= ;=20then=0A=20=20=20#=20thread-safety.=20In=201.1.0,=20it's=20no=20= longer=20required,=20and=20CRYPTO_lock()=0A=20=20=20#=20function=20was=20= removed.=0A=20=20=20AC_CHECK_FUNCS([CRYPTO_lock])=0A+=20=20= AC_DEFINE([USE_OPENSSL],=201,=20[Define=20to=201=20if=20you=20have=20= OpenSSL=20support.])=0A+elif=20test=20"$with_ssl"=20!=3D=20no=20;=20then=0A= +=20=20AC_MSG_ERROR([--with-ssl=20must=20specify=20openssl])=0A=20fi=0A= +AC_SUBST(with_ssl)=0A=20=0A=20if=20test=20"$with_pam"=20=3D=20yes=20;=20= then=0A=20=20=20AC_CHECK_LIB(pam,=20=20=20=20pam_start,=20[],=20= [AC_MSG_ERROR([library=20'pam'=20is=20required=20for=20PAM])])=0A@@=20= -1402,7=20+1411,7=20@@=20if=20test=20"$with_gssapi"=20=3D=20yes=20;=20= then=0A=20=09[AC_CHECK_HEADERS(gssapi.h,=20[],=20[AC_MSG_ERROR([gssapi.h=20= header=20file=20is=20required=20for=20GSSAPI])])])=0A=20fi=0A=20=0A-if=20= test=20"$with_openssl"=20=3D=20yes=20;=20then=0A+if=20test=20"$with_ssl"=20= =3D=20openssl=20;=20then=0A=20=20=20AC_CHECK_HEADER(openssl/ssl.h,=20[],=20= [AC_MSG_ERROR([header=20file=20=20is=20required=20for=20= OpenSSL])])=0A=20=20=20AC_CHECK_HEADER(openssl/err.h,=20[],=20= [AC_MSG_ERROR([header=20file=20=20is=20required=20for=20= OpenSSL])])=0A=20fi=0A@@=20-2159,7=20+2168,7=20@@=20fi=0A=20#=20first=20= choice,=20else=20the=20native=20platform=20sources=20(Windows=20API=20or=20= /dev/urandom)=0A=20#=20will=20be=20used.=0A=20AC_MSG_CHECKING([which=20= random=20number=20source=20to=20use])=0A-if=20test=20x"$with_openssl"=20= =3D=20x"yes"=20;=20then=0A+if=20test=20x"$with_ssl"=20=3D=20x"openssl"=20= ;=20then=0A=20=20=20AC_MSG_RESULT([OpenSSL])=0A=20elif=20test=20= x"$PORTNAME"=20=3D=20x"win32"=20;=20then=0A=20=20=20= AC_MSG_RESULT([Windows=20native])=0Adiff=20--git=20a/contrib/Makefile=20= b/contrib/Makefile=0Aindex=20cdc041c7db..ba414fe581=20100644=0A---=20= a/contrib/Makefile=0A+++=20b/contrib/Makefile=0A@@=20-51,7=20+51,7=20@@=20= SUBDIRS=20=3D=20\=0A=20=09=09unaccent=09\=0A=20=09=09vacuumlo=0A=20=0A= -ifeq=20($(with_openssl),yes)=0A+ifneq=20($(with_ssl),no)=0A=20SUBDIRS=20= +=3D=20sslinfo=0A=20else=0A=20ALWAYS_SUBDIRS=20+=3D=20sslinfo=0Adiff=20= --git=20a/contrib/pgcrypto/Makefile=20b/contrib/pgcrypto/Makefile=0A= index=20316a26e58d..3500bd4c72=20100644=0A---=20= a/contrib/pgcrypto/Makefile=0A+++=20b/contrib/pgcrypto/Makefile=0A@@=20= -10,8=20+10,8=20@@=20OSSL_TESTS=20=3D=20sha2=20des=203des=20cast5=0A=20= ZLIB_TST=20=3D=20pgp-compression=0A=20ZLIB_OFF_TST=20=3D=20= pgp-zlib-DISABLED=0A=20=0A-CF_SRCS=20=3D=20$(if=20$(subst=20= no,,$(with_openssl)),=20$(OSSL_SRCS),=20$(INT_SRCS))=0A-CF_TESTS=20=3D=20= $(if=20$(subst=20no,,$(with_openssl)),=20$(OSSL_TESTS),=20$(INT_TESTS))=0A= +CF_SRCS=20=3D=20$(if=20$(subst=20openssl,,$(with_ssl)),=20$(OSSL_SRCS),=20= $(INT_SRCS))=0A+CF_TESTS=20=3D=20$(if=20$(subst=20openssl,,$(with_ssl)),=20= $(OSSL_TESTS),=20$(INT_TESTS))=0A=20CF_PGP_TESTS=20=3D=20$(if=20$(subst=20= no,,$(with_zlib)),=20$(ZLIB_TST),=20$(ZLIB_OFF_TST))=0A=20=0A=20SRCS=20=3D= =20\=0Adiff=20--git=20a/src/Makefile.global.in=20= b/src/Makefile.global.in=0Aindex=209a1688c97c..74b3a6acd2=20100644=0A---=20= a/src/Makefile.global.in=0A+++=20b/src/Makefile.global.in=0A@@=20-183,7=20= +183,7=20@@=20with_icu=09=3D=20@with_icu@=0A=20with_perl=09=3D=20= @with_perl@=0A=20with_python=09=3D=20@with_python@=0A=20with_tcl=09=3D=20= @with_tcl@=0A-with_openssl=09=3D=20@with_openssl@=0A+with_ssl=09=3D=20= @with_ssl@=0A=20with_readline=09=3D=20@with_readline@=0A=20with_selinux=09= =3D=20@with_selinux@=0A=20with_systemd=09=3D=20@with_systemd@=0Adiff=20= --git=20a/src/backend/libpq/Makefile=20b/src/backend/libpq/Makefile=0A= index=20efc5ef760a..8d1d16b0fc=20100644=0A---=20= a/src/backend/libpq/Makefile=0A+++=20b/src/backend/libpq/Makefile=0A@@=20= -28,7=20+28,7=20@@=20OBJS=20=3D=20\=0A=20=09pqmq.o=20\=0A=20=09= pqsignal.o=0A=20=0A-ifeq=20($(with_openssl),yes)=0A+ifeq=20= ($(with_ssl),openssl)=0A=20OBJS=20+=3D=20be-secure-openssl.o=0A=20endif=0A= =20=0Adiff=20--git=20a/src/common/Makefile=20b/src/common/Makefile=0A= index=201a1d0d3406..5422579a6a=20100644=0A---=20a/src/common/Makefile=0A= +++=20b/src/common/Makefile=0A@@=20-80,7=20+80,7=20@@=20OBJS_COMMON=20=3D=20= \=0A=20=09wait_error.o=20\=0A=20=09wchar.o=0A=20=0A-ifeq=20= ($(with_openssl),yes)=0A+ifeq=20($(with_ssl),openssl)=0A=20OBJS_COMMON=20= +=3D=20\=0A=20=09protocol_openssl.o=20\=0A=20=09cryptohash_openssl.o=0A= diff=20--git=20a/src/interfaces/libpq/Makefile=20= b/src/interfaces/libpq/Makefile=0Aindex=20c4fde3f93d..c5ef0bead5=20= 100644=0A---=20a/src/interfaces/libpq/Makefile=0A+++=20= b/src/interfaces/libpq/Makefile=0A@@=20-45,9=20+45,13=20@@=20OBJS=20=3D=20= \=0A=20=09pqexpbuffer.o=20\=0A=20=09fe-auth.o=0A=20=0A-ifeq=20= ($(with_openssl),yes)=0A+ifneq=20($(with_ssl),no)=0A+OBJS=20+=3D=20\=0A+=09= fe-secure-common.o=0A+endif=0A+=0A+ifeq=20($(with_ssl),openssl)=0A=20= OBJS=20+=3D=20\=0A-=09fe-secure-common.o=20\=0A=20=09fe-secure-openssl.o=0A= =20endif=0A=20=0Adiff=20--git=20a/src/test/Makefile=20= b/src/test/Makefile=0Aindex=20ab1ef9a475..414749d627=20100644=0A---=20= a/src/test/Makefile=0A+++=20b/src/test/Makefile=0A@@=20-28,7=20+28,7=20= @@=20ifneq=20(,$(filter=20ldap,$(PG_TEST_EXTRA)))=0A=20SUBDIRS=20+=3D=20= ldap=0A=20endif=0A=20endif=0A-ifeq=20($(with_openssl),yes)=0A+ifneq=20= ($(with_ssl),no)=0A=20ifneq=20(,$(filter=20ssl,$(PG_TEST_EXTRA)))=0A=20= SUBDIRS=20+=3D=20ssl=0A=20endif=0Adiff=20--git=20= a/src/test/modules/Makefile=20b/src/test/modules/Makefile=0Aindex=20= 59921b46cf..5391f461a2=20100644=0A---=20a/src/test/modules/Makefile=0A= +++=20b/src/test/modules/Makefile=0A@@=20-28,7=20+28,7=20@@=20SUBDIRS=20= =3D=20\=0A=20=09=09=20=20unsafe_tests=20\=0A=20=09=09=20=20worker_spi=0A=20= =0A-ifeq=20($(with_openssl),yes)=0A+ifeq=20($(with_ssl),openssl)=0A=20= SUBDIRS=20+=3D=20ssl_passphrase_callback=0A=20else=0A=20ALWAYS_SUBDIRS=20= +=3D=20ssl_passphrase_callback=0Adiff=20--git=20= a/src/test/modules/ssl_passphrase_callback/Makefile=20= b/src/test/modules/ssl_passphrase_callback/Makefile=0Aindex=20= f81265c296..a34d7ea46a=20100644=0A---=20= a/src/test/modules/ssl_passphrase_callback/Makefile=0A+++=20= b/src/test/modules/ssl_passphrase_callback/Makefile=0A@@=20-1,6=20+1,6=20= @@=0A=20#=20ssl_passphrase_callback=20Makefile=0A=20=0A-export=20= with_openssl=0A+export=20with_ssl=0A=20=0A=20MODULE_big=20=3D=20= ssl_passphrase_func=0A=20OBJS=20=3D=20ssl_passphrase_func.o=20= $(WIN32RES)=0Adiff=20--git=20= a/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl=20= b/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl=0Aindex=20= dbc084f870..c7bff75f07=20100644=0A---=20= a/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl=0A+++=20= b/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl=0A@@=20-7,9=20= +7,9=20@@=20use=20TestLib;=0A=20use=20Test::More;=0A=20use=20= PostgresNode;=0A=20=0A-unless=20(($ENV{with_openssl}=20||=20'no')=20eq=20= 'yes')=0A+if=20($ENV{with_ssl}=20eq=20'no')=0A=20{=0A-=09plan=20skip_all=20= =3D>=20'SSL=20not=20supported=20by=20this=20build';=0A+=09plan=20= skip_all=20=3D>=20'OpenSSL=20not=20supported=20by=20this=20build';=0A=20= }=0A=20=0A=20my=20$clearpass=20=3D=20"FooBaR1";=0Adiff=20--git=20= a/src/test/ssl/Makefile=20b/src/test/ssl/Makefile=0Aindex=20= 93335b1ea2..d545382eea=20100644=0A---=20a/src/test/ssl/Makefile=0A+++=20= b/src/test/ssl/Makefile=0A@@=20-13,7=20+13,7=20@@=20subdir=20=3D=20= src/test/ssl=0A=20top_builddir=20=3D=20../../..=0A=20include=20= $(top_builddir)/src/Makefile.global=0A=20=0A-export=20with_openssl=0A= +export=20with_ssl=0A=20=0A=20CERTIFICATES=20:=3D=20server_ca=20= server-cn-and-alt-names=20\=0A=20=09server-cn-only=20= server-single-alt-name=20server-multiple-alt-names=20\=0A--=20=0A2.21.1=20= (Apple=20Git-122.3)=0A=0A= --Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii --Apple-Mail=_2ABE0C36-6AED-4B2A-88BC-1B5C2991D3D2--