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 1mpWXd-0004cn-98 for pgsql-hackers@arkaria.postgresql.org; Tue, 23 Nov 2021 14:13:02 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1mpWXc-0008JU-4f for pgsql-hackers@arkaria.postgresql.org; Tue, 23 Nov 2021 14:13:00 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mpWXa-0008JF-HW for pgsql-hackers@lists.postgresql.org; Tue, 23 Nov 2021 14:12:59 +0000 Received: from smtp.outgoing.loopia.se ([93.188.3.37]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mpWXT-0003tX-KK for pgsql-hackers@lists.postgresql.org; Tue, 23 Nov 2021 14:12:57 +0000 Received: from s807.loopia.se (localhost [127.0.0.1]) by s807.loopia.se (Postfix) with ESMTP id D59FF2F05376 for ; Tue, 23 Nov 2021 15:12:47 +0100 (CET) Received: from s630.loopia.se (unknown [172.22.191.5]) by s807.loopia.se (Postfix) with ESMTP id C0FE72E2D581; Tue, 23 Nov 2021 15:12:47 +0100 (CET) Received: from s473.loopia.se (unknown [172.22.191.6]) by s630.loopia.se (Postfix) with ESMTP id 9E78A13AC077; Tue, 23 Nov 2021 15:12:47 +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 s473.loopia.se (s473.loopia.se [172.22.190.13]) (amavisd-new, port 10024) with LMTP id YLt-b-uWdXhX; Tue, 23 Nov 2021 15:12:46 +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.144] (customer-89-255-232-193.stosn.net [89.255.232.193]) (Authenticated sender: daniel@yesql.se) by s499.loopia.se (Postfix) with ESMTPSA id 0BA611CE0810; Tue, 23 Nov 2021 15:12:46 +0100 (CET) From: Daniel Gustafsson Message-Id: <3EEE302A-62CF-4B74-A120-DE0E9699094D@yesql.se> Content-Type: multipart/mixed; boundary="Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F" Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.120.23.2.7\)) Subject: Re: Support for NSS as a libpq TLS backend Date: Tue, 23 Nov 2021 15:12:45 +0100 In-Reply-To: Cc: Kevin Burke , Jacob Champion , "pgsql-hackers@lists.postgresql.org" , "hlinnaka@iki.fi" , "andrew.dunstan@2ndquadrant.com" , "sfrost@snowman.net" , "rachelmheaton@gmail.com" , "thomas.munro@gmail.com" , "michael@paquier.xyz" , "andres@anarazel.de" To: Joshua Brindle References: <8335133C-920E-438D-9CEB-DEF4C1533F73@yesql.se> <4ec146256e31afa0542f9fa970ec258c5f1a5f98.camel@vmware.com> <70A12E33-90B8-4761-8FA6-8DDB9EEA4D3E@yesql.se> <14b33300304507db6f4e4d8a77da105a8d18ea1a.camel@vmware.com> <02AB4044-0823-4F77-B69B-18DB378C8743@yesql.se> <33A9AFD6-7285-4064-9806-B08D7E61A88C@yesql.se> <93011BD4-4CC5-419B-9D5D-526274824831@yesql.se> <2A20EED9-2D5E-4779-B201-B7458DFC3FE2@yesql.se> <09DB934A-2B4B-4F1E-9DAA-C55D50F254D1@yesql.se> <5c54945a0ac555a49a4951cd87b681a5ed4d21c8.camel@vmware.com> <47f36fb0fad537fdd76d9bc9286d1bde3b614dfc.camel@vmware.com> <690B28CA-D819-4714-B8F6-54DD6F02722C@yesql.se> <7DD7A38D-BB7C-4D07-BF31-CF27802D459C@yesql.se> <09520D9F-9C15-4ECC-A753-C6840AE7DA66@yesql.se> <26D2D9CD-329D-421E-A57E-6996204580DF@yesql.se> X-Mailer: Apple Mail (2.3608.120.23.2.7) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii > On 17 Nov 2021, at 19:42, Joshua Brindle = wrote: > On Tue, Nov 16, 2021 at 1:26 PM Joshua Brindle > wrote: >> I think there it a typo in the docs here that prevents them from >> building (this diff seems to fix it): Ah yes, thanks, I had noticed that one but forgot to send out a new = version to make the CFBot green. > After a bit more testing, the server is up and running with an nss > database but before configuring the client database I tried connecting > and got a segfault: Interesting. I'm unable to reproduce this crash, can you show the = sequence of commands which led to this? > It looks like the ssl connection falls through to attempt a non-ssl > connection but at some point conn->ssl_in_use gets set to true, > despite pr_fd and nss_context being null. pgtls_close missed setting ssl_in_use to false, fixed in the attached. = I've also added some assertions to the connection setup for debugging this. > This patch fixes the segfault but I suspect is not the correct fix, > due to the error when connecting saying "Success": Right, without an SSL enabled FD we should never get here. -- Daniel Gustafsson https://vmware.com/ --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F Content-Disposition: attachment; filename=v49-0001-nss-Support-libnss-as-TLS-library-in-libpq.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v49-0001-nss-Support-libnss-as-TLS-library-in-libpq.patch" Content-Transfer-Encoding: quoted-printable =46rom=207759149588610dfe194098db6159c34296a11b6e=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:22=20+0100=0ASubject:=20[PATCH=20= v49=2001/10]=20nss:=20Support=20libnss=20as=20TLS=20library=20in=20libpq=0A= =0AThis=20commit=20contains=20the=20frontend=20and=20backend=20portion=20= of=20TLS=20support=0Ain=20libpq=20to=20allow=20encrypted=20connections=20= using=20NSS.=20The=20implementation=0Ais=20done=20as=20a=20drop-in=20= replacement=20for=20the=20OpenSSL=20support=20and=20leverages=0Athe=20= same=20internal=20API=20for=20abstracting=20library=20specific=20= details.=0A=0AA=20new=20GUC,=20ssl_database,=20is=20used=20to=20identify=20= the=20NSS=20database=20used=20for=0Athe=20serverside=20certificates=20= and=20keys.=20The=20existing=20certificate=20and=20key=0AGUCs=20are=20= used=20for=20providing=20certificate=20and=20key=20nicknames.=0A=0A= Client=20side=20there=20is=20a=20new=20connection=20parameter,=20= cert_database,=20to=0Aidentify=20the=20client=20cert=20and=20key.=20All=20= existing=20sslmodes=20are=20supported=0Ain=20the=20same=20way=20as=20= with=20OpenSSL.=0A=0AAuthors:=20Daniel=20Gustafsson,=20Andrew=20Dunstan,=20= Jacob=20Champion=0AReviewed-by:=20Michael=20Paquier=0A---=0A=20= .../postgres_fdw/expected/postgres_fdw.out=20=20=20=20|=20=20=20=202=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=206=20+=0A=20= src/backend/libpq/be-secure-nss.c=20=20=20=20=20=20=20=20=20=20=20=20=20= |=201574=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=201=20+=0A=20= src/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=2018=20+-=0A=20src/common/cipher_nss.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=20192=20++=0A=20= src/common/protocol_nss.c=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20|=20=20=2059=20+=0A=20src/include/common/nss.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=2052=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=20src/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=201=20+=0A=20= src/include/pg_config_manual.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20|=20=20=20=202=20+-=0A=20src/interfaces/libpq/fe-connect.c=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20=20=20=204=20+=0A=20= src/interfaces/libpq/fe-secure-nss.c=20=20=20=20=20=20=20=20=20=20|=20= 1229=20+++++++++++++=0A=20src/interfaces/libpq/fe-secure.c=20=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20=20=2021=20+=0A=20= src/interfaces/libpq/libpq-fe.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20|=20=20=2011=20+=0A=20src/interfaces/libpq/libpq-int.h=20=20=20=20=20=20= =20=20=20=20=20=20=20=20|=20=20=2029=20+-=0A=2016=20files=20changed,=20= 3209=20insertions(+),=207=20deletions(-)=0A=20create=20mode=20100644=20= src/backend/libpq/be-secure-nss.c=0A=20create=20mode=20100644=20= src/common/cipher_nss.c=0A=20create=20mode=20100644=20= src/common/protocol_nss.c=0A=20create=20mode=20100644=20= src/include/common/nss.h=0A=20create=20mode=20100644=20= src/interfaces/libpq/fe-secure-nss.c=0A=0Adiff=20--git=20= a/contrib/postgres_fdw/expected/postgres_fdw.out=20= b/contrib/postgres_fdw/expected/postgres_fdw.out=0Aindex=20= 786781db4b..18a7b188f1=20100644=0A---=20= a/contrib/postgres_fdw/expected/postgres_fdw.out=0A+++=20= b/contrib/postgres_fdw/expected/postgres_fdw.out=0A@@=20-9505,7=20= +9505,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= sslcrldir,=20sslsni,=20requirepeer,=20ssl_min_protocol_version,=20= ssl_max_protocol_version,=20gssencmode,=20krbsrvname,=20gsslib,=20= target_session_attrs,=20use_remote_estimate,=20fdw_startup_cost,=20= fdw_tuple_cost,=20extensions,=20updatable,=20truncatable,=20fetch_size,=20= batch_size,=20async_capable,=20keep_connections=0A+HINT:=20=20Valid=20= options=20in=20this=20context=20are:=20service,=20passfile,=20= channel_binding,=20connect_timeout,=20dbname,=20host,=20hostaddr,=20= port,=20options,=20application_name,=20keepalives,=20keepalives_idle,=20= keepalives_interval,=20keepalives_count,=20tcp_user_timeout,=20sslmode,=20= sslcompression,=20sslcert,=20sslkey,=20sslrootcert,=20sslcrl,=20= sslcrldir,=20sslsni,=20requirepeer,=20ssl_min_protocol_version,=20= ssl_max_protocol_version,=20gssencmode,=20krbsrvname,=20gsslib,=20= target_session_attrs,=20ssldatabase,=20use_remote_estimate,=20= fdw_startup_cost,=20fdw_tuple_cost,=20extensions,=20updatable,=20= truncatable,=20fetch_size,=20batch_size,=20async_capable,=20= keep_connections=0A=20CONTEXT:=20=20SQL=20statement=20"ALTER=20SERVER=20= loopback_nopw=20OPTIONS=20(ADD=20password=20'dummypw')"=0A=20PL/pgSQL=20= function=20inline_code_block=20line=203=20at=20EXECUTE=0A=20--=20If=20we=20= add=20a=20password=20for=20our=20user=20mapping=20instead,=20we=20should=20= get=20a=20different=0Adiff=20--git=20a/src/backend/libpq/auth.c=20= b/src/backend/libpq/auth.c=0Aindex=207bcf52523b..9d0e30f248=20100644=0A= ---=20a/src/backend/libpq/auth.c=0A+++=20b/src/backend/libpq/auth.c=0A@@=20= -2752,7=20+2752,13=20@@=20CheckCertAuth(Port=20*port)=0A=20=09int=09=09=09= status_check_usermap=20=3D=20STATUS_ERROR;=0A=20=09char=09=20=20=20= *peer_username=20=3D=20NULL;=0A=20=0A+#if=20defined(USE_OPENSSL)=0A=20=09= Assert(port->ssl);=0A+#elif=20defined(USE_NSS)=0A+=09= Assert(port->pr_fd);=0A+#else=0A+=09Assert(false);=0A+#endif=0A=20=0A=20=09= /*=20select=20the=20correct=20field=20to=20compare=20*/=0A=20=09switch=20= (port->hba->clientcertname)=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..dfa4581caa=0A---=20/dev/null=0A+++=20= b/src/backend/libpq/be-secure-nss.c=0A@@=20-0,0=20+1,1574=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-2021,=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+#include=20"common/nss.h"=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+=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+#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=20can=20be=20= overridden=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*nss_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=20PRStatus=20= pg_ssl_close(PRFileDesc=20*fd);=0A+/*=20Utility=20functions=20*/=0A= +static=20PRFileDesc=20*init_iolayer(Port=20*port);=0A+static=20uint16=20= ssl_protocol_version_to_nss(int=20v);=0A+=0A+static=20char=20= *pg_SSLerrmessage(PRErrorCode=20errcode);=0A+static=20SECStatus=20= pg_cert_auth_handler(void=20*arg,=20PRFileDesc=20*fd,=0A+=09=09=09=09=09=09= =09=09=09=20=20PRBool=20checksig,=20PRBool=20isServer);=0A+static=20= SECStatus=20pg_bad_cert_handler(void=20*arg,=20PRFileDesc=20*fd);=0A= +static=20char=20*dummy_ssl_passphrase_cb(PK11SlotInfo=20*slot,=20PRBool=20= retry,=20void=20*arg);=0A+static=20char=20= *pg_CERT_GetDistinguishedName(CERTCertificate=20*cert);=0A+static=20= const=20char=20*tag_to_name(SECOidTag=20tag);=0A+static=20SECStatus=20= pg_SSLShutdownFunc(void=20*private_data,=20void=20*nss_data);=0A+static=20= void=20pg_SSLAlertSent(const=20PRFileDesc=20*fd,=20void=20*private_data,=20= const=20SSLAlert=20*alert);=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+=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+=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+/*=0A+=20*=20= be_tls_open_server=0A+=20*=0A+=20*=20Since=20NSPR=20initialization=20= must=20happen=20after=20forking,=20most=20of=20the=20actual=0A+=20*=20= setup=20of=20NSPR/NSS=20is=20done=20here=20rather=20than=20in=20= be_tls_init.=20This=20introduce=0A+=20*=20differences=20with=20the=20= OpenSSL=20support=20where=20some=20errors=20are=20only=20reported=0A+=20= *=20at=20runtime=20with=20NSS=20where=20they=20are=20reported=20at=20= startup=20with=20OpenSSL.=0A+=20*/=0A+int=0A+be_tls_open_server(Port=20= *port)=0A+{=0A+=09SECStatus=09status;=0A+=09PRFileDesc=20*model;=0A+=09= PRFileDesc=20*layer;=0A+=09CERTCertificate=20*server_cert;=0A+=09= SECKEYPrivateKey=20*private_key;=0A+=09CERTSignedCrl=20*crl;=0A+=09= SECItem=09=09crlname;=0A+=09char=09=20=20=20*cert_database;=0A+=09= NSSInitParameters=20params;=0A+=0A+=09/*=0A+=09=20*=20The=20NSPR=20= documentation=20states=20that=20runtime=20initialization=20via=20PR_Init=0A= +=09=20*=20is=20no=20longer=20required,=20as=20the=20first=20caller=20= into=20NSPR=20will=20perform=20the=0A+=09=20*=20initialization=20= implicitly.=20The=20documentation=20doesn't=20however=20clarify=0A+=09=20= *=20from=20which=20version=20this=20is=20holds=20true,=20so=20let's=20= perform=20the=20potentially=0A+=09=20*=20superfluous=20initialization=20= anyways=20to=20avoid=20crashing=20on=20older=20versions=0A+=09=20*=20of=20= NSPR,=20as=20there=20is=20no=20difference=20in=20overhead.=20=20The=20= NSS=20documentation=0A+=09=20*=20still=20states=20that=20PR_Init=20must=20= be=20called=20in=20some=20way=20(implicitly=20or=0A+=09=20*=20= explicitly).=0A+=09=20*=0A+=09=20*=20The=20below=20parameters=20are=20= what=20the=20implicit=20initialization=20would've=20done=0A+=09=20*=20= for=20us,=20and=20should=20work=20even=20for=20older=20versions=20where=20= it=20might=20not=20be=0A+=09=20*=20done=20automatically.=20The=20last=20= parameter,=20maxPTDs,=20is=20set=20to=20various=0A+=09=20*=20values=20in=20= other=20codebases,=20but=20has=20been=20unused=20since=20NSPR=202.1=20= which=20was=0A+=09=20*=20released=20sometime=20in=201998.=20In=20current=20= versions=20of=20NSPR=20all=20parameters=0A+=09=20*=20are=20ignored.=0A+=09= =20*/=0A+=09PR_Init(PR_USER_THREAD,=20PR_PRIORITY_NORMAL,=200=20/*=20= maxPTDs=20*/=20);=0A+=0A+=09/*=0A+=09=20*=20The=20certificate=20path=20= (configdir)=20must=20contain=20a=20valid=20NSS=20database.=20If=0A+=09=20= *=20the=20certificate=20path=20isn't=20a=20valid=20directory,=20NSS=20= will=20fall=20back=20on=20the=0A+=09=20*=20system=20certificate=20= database.=20If=20the=20certificate=20path=20is=20a=20directory=20but=0A+=09= =20*=20is=20empty=20then=20the=20initialization=20will=20fail.=20On=20= the=20client=20side=20this=20can=0A+=09=20*=20be=20allowed=20for=20any=20= sslmode=20but=20the=20verify-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+=09port->pr_fd=20=3D=20PR_ImportTCPSocket(port->sock);=0A+=09= if=20(!port->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+=09= =09bool=09=09found=20=3D=20false;=0A+=0A+=09=09/*=0A+=09=09=20*=20If=20= the=20user=20has=20specified=20a=20set=20of=20preferred=20cipher=20= suites=20we=20start=0A+=09=09=20*=20by=20turning=20off=20all=20the=20= existing=20suites=20to=20avoid=20the=20risk=20of=20down-=0A+=09=09=20*=20= grades=20to=20a=20weaker=20cipher=20than=20expected.=0A+=09=09=20*/=0A+=09= =09nss_ciphers=20=3D=20SSL_GetImplementedCiphers();=0A+=09=09for=20(int=20= i=20=3D=200;=20i=20<=20SSL_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=09if=20(pg_find_cipher(c,=20&ciphercode))=0A+=09=09=09{=0A+=09=09= =09=09status=20=3D=20SSL_CipherPrefSet(model,=20ciphercode,=20PR_TRUE);=0A= +=09=09=09=09found=20=3D=20true;=0A+=09=09=09=09if=20(status=20!=3D=20= SECSuccess)=0A+=09=09=09=09{=0A+=09=09=09=09=09ereport(COMMERROR,=0A+=09=09= =09=09=09=09=09(errmsg("invalid=20cipher-suite=20specified:=20%s",=20= c)));=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+=0A+=09=09if=20(!found)=0A+=09=09{=0A= +=09=09=09ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("no=20= cipher-suites=20found")));=0A+=09=09=09return=20-1;=0A+=09=09}=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=20in=20order=20to=20be=20able=20to=20= provide=20custom=20call-=0A+=09=20*=20backs=20for=20IO=20operations=20= which=20override=20the=20built-in=20behavior.=20For=20now=0A+=09=20*=20= we=20need=20this=20in=20order=20to=20support=20debug=20builds=20of=20= NSS/NSPR.=0A+=09=20*/=0A+=09layer=20=3D=20init_iolayer(port);=0A+=09if=20= (!layer)=0A+=09=09return=20-1;=0A+=0A+=09if=20= (PR_PushIOLayer(port->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+=09/*=20Set=20up=20= certificate=20authentication=20callback=20*/=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= /*=0A+=09=20*=20Apply=20the=20configuration=20from=20the=20model=20= template=20onto=20our=20actual=20socket=0A+=09=20*=20to=20set=20it=20up=20= as=20a=20TLS=20server.=0A+=09=20*/=0A+=09port->pr_fd=20=3D=20= SSL_ImportFD(model,=20port->pr_fd);=0A+=09if=20(!port->pr_fd)=0A+=09{=0A= +=09=09ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= configure=20socket=20for=20TLS=20server=20mode:=20%s",=0A+=09=09=09=09=09= =09pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20-1;=0A+=09}=0A+=0A= +=09/*=0A+=09=20*=20The=20intention=20with=20the=20model=20FD=20is=20to=20= keep=20it=20as=20a=20template=20for=20coming=0A+=09=20*=20connections=20= to=20amortize=20the=20cost=20and=20complexity=20across=20all=20client=0A= +=09=20*=20sockets.=20Since=20we=20won't=20get=20another=20socket=20= connected=20in=20this=20backend=0A+=09=20*=20we=20can=20however=20close=20= the=20model=20immediately.=0A+=09=20*/=0A+=09PR_Close(model);=0A+=0A+=09= /*=0A+=09=20*=20Force=20a=20handshake=20on=20the=20next=20I/O=20request,=20= the=20second=20parameter=20means=0A+=09=20*=20that=20we=20are=20a=20= server,=20PR_FALSE=20would=20indicate=20being=20a=20client.=20NSPR=0A+=09= =20*=20requires=20us=20to=20call=20SSL_ResetHandshake=20since=20we=20= imported=20an=20already=0A+=09=20*=20established=20socket.=0A+=09=20*/=0A= +=09status=20=3D=20SSL_ResetHandshake(port->pr_fd,=20PR_TRUE);=0A+=09if=20= (status=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09= =09=09(errmsg("unable=20to=20initiate=20handshake:=20%s",=0A+=09=09=09=09= =09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20-1;=0A+=09}=0A= +=09status=20=3D=20SSL_ForceHandshake(port->pr_fd);=0A+=09if=20(status=20= !=3D=20SECSuccess)=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+=0A+=09/*=20Register=20our=20= shutdown=20callback=20*/=0A+=09NSS_RegisterShutdown(pg_SSLShutdownFunc,=20= port);=0A+=0A+=09/*=20Register=20callback=20for=20TLS=20alerts=20*/=0A+=09= SSL_AlertSentCallback(port->pr_fd,=20pg_SSLAlertSent,=20port);=0A+=0A+=09= return=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,=20= ptr,=20len);=0A+=0A+=09if=20(n_read=20<=200)=0A+=09{=0A+=09=09err=20=3D=20= PR_GetError();=0A+=0A+=09=09if=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=09= errno=20=3D=20EWOULDBLOCK;=0A+=09=09}=0A+=09=09else=0A+=09=09=09errno=20= =3D=20ECONNRESET;=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+/*=0A+=20*=20be_tls_close=0A+=20*=0A+=20*=20= Callback=20for=20closing=20down=20the=20current=20connection,=20if=20= any.=0A+=20*/=0A+void=0A+be_tls_close(Port=20*port)=0A+{=0A+=09if=20= (!port)=0A+=09=09return;=0A+=09/*=0A+=09=20*=20Immediately=20signal=20to=20= the=20rest=20of=20the=20backend=20that=20this=20connnection=20is=0A+=09=20= *=20no=20longer=20to=20be=20considered=20to=20be=20using=20TLS=20= encryption.=0A+=09=20*/=0A+=09port->ssl_in_use=20=3D=20false;=0A+=0A+=09= if=20(port->peer_cn)=0A+=09{=0A+=09=09= SSL_InvalidateSession(port->pr_fd);=0A+=09=09pfree(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+=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+/*=0A+=20*=20be_tls_destroy=0A+=20*=0A+=20*=20Callback=20= for=20destroying=20global=20contexts=20during=20SIGHUP.=0A+=20*/=0A+void=0A= +be_tls_destroy(void)=0A+{=0A+=09/*=0A+=09=20*=20It=20reads=20a=20bit=20= odd=20to=20clear=20a=20session=20cache=20when=20we=20are=20destroying=20= the=0A+=09=20*=20context=20altogether,=20but=20if=20the=20session=20= cache=20isn't=20cleared=20before=0A+=09=20*=20shutting=20down=20the=20= context=20it=20will=20fail=20with=20SEC_ERROR_BUSY.=0A+=09=20*/=0A+=09= SSL_ClearSessionCache();=0A+}=0A+=0A+/*=0A+=20*=20be_tls_get_cipher_bits=0A= +=20*=0A+=20*=20Returns=20the=20number=20of=20bits=20in=20the=20= encryption=20key=20used,=20or=20zero=20in=20case=0A+=20*=20of=20errors.=0A= +=20*/=0A+int=0A+be_tls_get_cipher_bits(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.effectiveKeyBits;=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=200;=0A+}=0A+=0A+/*=0A+=20= *=20be_tls_get_version=0A+=20*=0A+=20*=20Returns=20the=20protocol=20= version=20used=20for=20the=20current=20connection,=20or=20NULL=20in=0A+=20= *=20case=20of=20errors.=0A+=20*/=0A+const=20char=20*=0A= +be_tls_get_version(Port=20*port)=0A+{=0A+=09SECStatus=09status;=0A+=09= SSLChannelInfo=20channel;=0A+=0A+=09status=20=3D=20= SSL_GetChannelInfo(port->pr_fd,=20&channel,=20sizeof(channel));=0A+=09if=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=09return=20= NULL;=0A+=09}=0A+=0A+=09return=20= ssl_protocol_version_to_string(channel.protocolVersion);=0A+}=0A+=0A+/*=0A= +=20*=20be_tls_get_cipher=0A+=20*=0A+=20*=20Returns=20the=20cipher=20= used=20for=20the=20current=20connection,=20or=20NULL=20in=20case=20of=0A= +=20*=20errors.=0A+=20*/=0A+const=20char=20*=0A+be_tls_get_cipher(Port=20= *port)=0A+{=0A+=09SECStatus=09status;=0A+=09SSLChannelInfo=20channel;=0A= +=09SSLCipherSuiteInfo=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+/*=0A= +=20*=20be_tls_get_peer_subject_name=0A+=20*=0A+=20*=20Returns=20the=20= subject=20name=20of=20the=20peer=20certificate.=0A+=20*/=0A+void=0A= +be_tls_get_peer_subject_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->subject),=20len);=0A+=09= else=0A+=09=09ptr[0]=20=3D=20'\0';=0A+}=0A+=0A+/*=0A+=20*=20= be_tls_get_peer_issuer_name=0A+=20*=0A+=20*=20Returns=20the=20issuer=20= name=20of=20the=20peer=20certificate.=0A+=20*/=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+/*=0A+=20*=20= be_tls_get_peer_serial=0A+=20*=0A+=20*=20Returns=20the=20serial=20of=20= the=20peer=20certificate.=0A+=20*/=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+/*=0A+=20*=20= be_tls_get_certificate_hash=0A+=20*=0A+=20*=20Returns=20the=20hash=20= data=20of=20the=20server=20certificate=20for=20SCRAM=20channel=20= binding.=0A+=20*/=0A+char=20*=0A+be_tls_get_certificate_hash(Port=20= *port,=20size_t=20*len)=0A+{=0A+=09CERTCertificate=20*certificate;=0A+=09= SECOidTag=09signature_tag;=0A+=09SECOidTag=09digest_alg;=0A+=09int=09=09=09= digest_len;=0A+=09SECStatus=09status;=0A+=09PLArenaPool=20*arena=20=3D=20= NULL;=0A+=09SECItem=09=09digest;=0A+=09char=09=20=20=20*ret;=0A+=09= PK11Context=20*ctx=20=3D=20NULL;=0A+=09unsigned=20int=20outlen;=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_tag=20=3D=20= SECOID_GetAlgorithmTag(&certificate->signature);=0A+=09if=20= (!pg_find_signature_algorithm(signature_tag,=20&digest_alg,=20= &digest_len))=0A+=09=09elog(ERROR,=20"could=20not=20find=20digest=20for=20= OID=20'%s'",=0A+=09=09=09=20= SECOID_FindOIDTagDescription(signature_tag));=0A+=0A+=09/*=0A+=09=20*=20= The=20TLS=20server's=20certificate=20bytes=20need=20to=20be=20hashed=20= with=20SHA-256=20if=0A+=09=20*=20its=20signature=20algorithm=20is=20MD5=20= or=20SHA-1=20as=20per=20RFC=205929=0A+=09=20*=20= (https://tools.ietf.org/html/rfc5929#section-4.1).=20=20If=20something=20= else=0A+=09=20*=20is=20used,=20the=20same=20hash=20as=20the=20signature=20= algorithm=20is=20used.=0A+=09=20*/=0A+=09if=20(digest_alg=20=3D=3D=20= SEC_OID_SHA1=20||=20digest_alg=20=3D=3D=20SEC_OID_MD5)=0A+=09{=0A+=09=09= digest_alg=20=3D=20SEC_OID_SHA256;=0A+=09=09digest_len=20=3D=20= SHA256_LENGTH;=0A+=09}=0A+=0A+=09ctx=20=3D=20= PK11_CreateDigestContext(digest_alg);=0A+=09if=20(!ctx)=0A+=09=09= elog(ERROR,=20"out=20of=20memory");=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= if=20(!digest.data)=0A+=09=09elog(ERROR,=20"out=20of=20memory");=0A+=09= digest.len=20=3D=20digest_len;=0A+=0A+=09status=20=3D=20SECSuccess;=0A+=09= status=20|=3D=20PK11_DigestBegin(ctx);=0A+=09status=20|=3D=20= PK11_DigestOp(ctx,=20certificate->derCert.data,=20= certificate->derCert.len);=0A+=09status=20|=3D=20PK11_DigestFinal(ctx,=20= digest.data,=20&outlen,=20digest_len);=0A+=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09PORT_FreeArena(arena,=20PR_TRUE);=0A+=09=09= PK11_DestroyContext(ctx,=20PR_TRUE);=0A+=09=09elog(ERROR,=20"could=20not=20= generate=20server=20certificate=20hash");=0A+=09}=0A+=0A+=09ret=20=3D=20= palloc(digest.len);=0A+=09memcpy(ret,=20digest.data,=20digest.len);=0A+=09= *len=20=3D=20digest_len;=0A+=0A+=09PORT_FreeArena(arena,=20PR_TRUE);=0A+=09= PK11_DestroyContext(ctx,=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+/*=0A+=20*=20pg_bad_cert_handler=0A+=20*=0A+=20*=20= Callback=20for=20handling=20certificate=20validation=20failure=20during=20= handshake.=20It's=0A+=20*=20called=20from=20SSL_AuthCertificate=20during=20= failure=20cases.=0A+=20*/=0A+static=20SECStatus=0A= +pg_bad_cert_handler(void=20*arg,=20PRFileDesc=20*fd)=0A+{=0A+=09Port=09=20= =20=20*port=20=3D=20(Port=20*)=20arg;=0A+=0A+=09port->peer_cert_valid=20= =3D=20false;=0A+=09return=20SECFailure;=0A+}=0A+=0A+/*=0A+=20*=20= tag_to_name=0A+=20*=0A+=20*=20Return=20the=20name=20of=20the=20RDN=20= identified=20by=20the=20tag=20passed=20as=20parameter.=20NSS=0A+=20*=20= has=20this=20information=20in=20a=20struct,=20but=20the=20only=20= publicly=20accessible=20API=20for=0A+=20*=20using=20it=20is=20limited=20= to=20retrieving=20the=20maximum=20length=20of=20the=20ava.=0A+=20*/=0A= +static=20const=20char=20*=0A+tag_to_name(SECOidTag=20tag)=0A+{=0A+=09= switch(tag)=0A+=09{=0A+=09=09case=20SEC_OID_AVA_COMMON_NAME:=0A+=09=09=09= return=20"CN";=0A+=09=09case=20SEC_OID_AVA_STATE_OR_PROVINCE:=0A+=09=09=09= return=20"ST";=0A+=09=09case=20SEC_OID_AVA_ORGANIZATION_NAME:=0A+=09=09=09= return=20"O";=0A+=09=09case=20SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:=0A+=09= =09=09return=20"OU";=0A+=09=09case=20SEC_OID_AVA_COUNTRY_NAME:=0A+=09=09=09= return=20"C";=0A+=09=09case=20SEC_OID_AVA_LOCALITY:=0A+=09=09=09return=20= "L";=0A+=09=09case=20SEC_OID_AVA_SURNAME:=0A+=09=09=09return=20"SN";=0A+=09= =09case=20SEC_OID_AVA_DC:=0A+=09=09=09return=20"DC";=0A+=09=09case=20= SEC_OID_RFC1274_MAIL:=0A+=09=09=09return=20"MAIL";=0A+=09=09case=20= SEC_OID_RFC1274_UID:=0A+=09=09=09return=20"UID";=0A+=09=09/*=0A+=09=09=20= *=20TODO:=20what=20would=20be=20the=20most=20appropriate=20thing=20to=20= do=20here?=0A+=09=09=20*/=0A+=09=09default:=0A+=09=09=09return=20"";=0A+=09= }=0A+}=0A+=0A+/*=0A+=20*=20pg_CERT_GetDistinguishedName=0A+=20*=0A+=20*=20= NSS=20doesn't=20provide=20a=20DN=20equivalent=20of=20CERT_GetCommonName,=20= so=20we=20have=20to=0A+=20*=20keep=20our=20own.=0A+=20*/=0A+static=20= char=20*=0A+pg_CERT_GetDistinguishedName(CERTCertificate=20*cert)=0A+{=0A= +=09CERTName=09=09subject=20=3D=20cert->subject;=0A+=09CERTRDN=09=09=20=20= **rdn;=0A+=09StringInfoData=09dnbuf;=0A+=09char=09=09=20=20=20*dn=20=3D=20= NULL;=0A+=0A+=09initStringInfo(&dnbuf);=0A+=0A+=09for=20(rdn=20=3D=20= subject.rdns;=20*rdn;=20rdn++)=0A+=09{=0A+=09=09CERTAVA=20=20=20**ava;=0A= +=09=09bool=09=09first=20=3D=20true;=0A+=0A+=09=09for=20(ava=20=3D=20= (*rdn)->avas;=20*ava;=20ava++)=0A+=09=09{=0A+=09=09=09SECItem=09=20=20=20= *buf;=0A+=09=09=09SECStatus=09status;=0A+=09=09=09char=09=20=20=20= *tmpstr;=0A+=09=09=09char=09=20=20=20*dststr;=0A+=09=09=09int=09=09=09= tmplen;=0A+=0A+=09=09=09/*=20See=20raw_subject_common_name=20comment=20= for=20discussion=20*/=0A+=09=09=09buf=20=3D=20= CERT_DecodeAVAValue(&(*ava)->value);=0A+=09=09=09if=20(!buf)=0A+=09=09=09= =09return=20NULL;=0A+=0A+=09=09=09tmpstr=20=3D=20palloc0(buf->len=20+=20= 1);=0A+=09=09=09tmplen=20=3D=20buf->len;=0A+=09=09=09memcpy(tmpstr,=20= buf->data,=20buf->len);=0A+=09=09=09SECITEM_FreeItem(buf,=20PR_TRUE);=0A= +=09=09=09/*=20Check=20for=20embedded=20null=20*/=0A+=09=09=09if=20= (strlen(tmpstr)=20!=3D=20tmplen)=0A+=09=09=09=09return=20NULL;=0A+=0A+=09= =09=09/*=20Make=20room=20for=20the=20worst=20case=20escaping=20*/=0A+=09=09= =09dststr=20=3D=20palloc0((tmplen=20*=203)=20+=201);=0A+=0A+=09=09=09/*=0A= +=09=09=09=20*=20While=20the=20function=20name=20refers=20to=20RFC=20= 1485,=20the=20underlying=0A+=09=09=09=20*=20quoting=20code=20conforms=20= to=20the=20RFC=202253=20rules.=0A+=09=09=09=20*/=0A+=09=09=09status=20=3D=20= CERT_RFC1485_EscapeAndQuote(dststr,=20tmplen=20*=203,=20tmpstr,=20= tmplen);=0A+=09=09=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09=09{=0A+=09= =09=09=09pfree(dststr);=0A+=09=09=09=09pfree(tmpstr);=0A+=09=09=09=09= return=20NULL;=0A+=09=09=09}=0A+=0A+=09=09=09appendStringInfo(&dnbuf,=20= "%s%s=3D%s",=0A+=09=09=09=09=09=09=09=20(first=20?=20""=20:=20","),=0A+=09= =09=09=09=09=09=09=20tag_to_name(CERT_GetAVATag(*ava)),=20dststr);=0A+=09= =09=09first=20=3D=20false;=0A+=0A+=09=09=09pfree(dststr);=0A+=09=09=09= pfree(tmpstr);=0A+=09=09}=0A+=09}=0A+=0A+=09if=20(dnbuf.len)=0A+=09{=0A+=09= =09dn=20=3D=20MemoryContextAllocZero(TopMemoryContext,=20dnbuf.len=20+=20= 1);=0A+=09=09strlcpy(dn,=20dnbuf.data,=20dnbuf.len=20+=201);=0A+=09}=0A+=0A= +=09return=20dn;=0A+}=0A+=0A+/*=0A+=20*=20raw_subject_common_name=0A+=20= *=0A+=20*=20Returns=20the=20Subject=20Common=20Name=20for=20the=20given=20= certificate=20as=20a=20raw=20char=0A+=20*=20buffer=20(that=20is,=20= without=20any=20form=20of=20escaping=20for=20unprintable=20characters=20= or=0A+=20*=20embedded=20nulls),=20with=20the=20length=20of=20the=20= buffer=20returned=20in=20the=20len=20param.=0A+=20*=20The=20buffer=20is=20= allocated=20in=20the=20TopMemoryContext=20and=20is=20given=20a=20NULL=0A= +=20*=20terminator=20so=20that=20callers=20are=20safe=20to=20call=20= strlen()=20on=20it.=0A+=20*=0A+=20*=20This=20is=20used=20instead=20of=20= CERT_GetCommonName(),=20which=20always=20performs=20quoting=0A+=20*=20= and/or=20escaping.=20NSS=20doesn't=20appear=20to=20give=20us=20a=20way=20= to=20easily=20unescape=20the=0A+=20*=20result,=20and=20we=20need=20to=20= store=20the=20raw=20CN=20into=20port->peer_cn=20for=20compatibility=0A+=20= *=20with=20the=20OpenSSL=20implementation.=0A+=20*/=0A+static=20char=20*=0A= +raw_subject_common_name(CERTCertificate=20*cert,=20unsigned=20int=20= *len)=0A+{=0A+=09CERTName=09subject=20=3D=20cert->subject;=0A+=09CERTRDN=09= =20=20**rdn;=0A+=0A+=09for=20(rdn=20=3D=20subject.rdns;=20*rdn;=20rdn++)=0A= +=09{=0A+=09=09CERTAVA=09=20=20**ava;=0A+=0A+=09=09for=20(ava=20=3D=20= (*rdn)->avas;=20*ava;=20ava++)=0A+=09=09{=0A+=09=09=09SECItem=09=20=20=20= *buf;=0A+=09=09=09char=09=20=20=20*cn;=0A+=0A+=09=09=09if=20= (CERT_GetAVATag(*ava)=20!=3D=20SEC_OID_AVA_COMMON_NAME)=0A+=09=09=09=09= continue;=0A+=0A+=09=09=09/*=20Found=20a=20CN,=20decode=20and=20copy=20= it=20into=20a=20newly=20allocated=20buffer=20*/=0A+=09=09=09buf=20=3D=20= CERT_DecodeAVAValue(&(*ava)->value);=0A+=09=09=09if=20(!buf)=0A+=09=09=09= {=0A+=09=09=09=09/*=0A+=09=09=09=09=20*=20This=20failure=20case=20is=20= difficult=20to=20test.=20(Since=20this=20code=0A+=09=09=09=09=20*=20runs=20= after=20certificate=20authentication=20has=20otherwise=0A+=09=09=09=09=20= *=20succeeded,=20you'd=20need=20to=20convince=20a=20CA=20implementation=20= to=0A+=09=09=09=09=20*=20sign=20a=20corrupted=20certificate=20in=20order=20= to=20get=20here.)=0A+=09=09=09=09=20*=0A+=09=09=09=09=20*=20Follow=20the=20= behavior=20of=20CERT_GetCommonName()=20in=20this=20case=20and=0A+=09=09=09= =09=20*=20simply=20return=20NULL,=20as=20if=20a=20Common=20Name=20had=20= not=20been=20found.=0A+=09=09=09=09=20*/=0A+=09=09=09=09goto=20fail;=0A+=09= =09=09}=0A+=0A+=09=09=09cn=20=3D=20MemoryContextAlloc(TopMemoryContext,=20= buf->len=20+=201);=0A+=09=09=09memcpy(cn,=20buf->data,=20buf->len);=0A+=09= =09=09cn[buf->len]=20=3D=20'\0';=0A+=0A+=09=09=09*len=20=3D=20buf->len;=0A= +=0A+=09=09=09SECITEM_FreeItem(buf,=20PR_TRUE);=0A+=09=09=09return=20cn;=0A= +=09=09}=0A+=09}=0A+=0A+fail:=0A+=09/*=20Not=20found=20=20*/=0A+=09*len=20= =3D=200;=0A+=09return=20NULL;=0A+}=0A+=0A+/*=0A+=20*=20= pg_cert_auth_handler=0A+=20*=0A+=20*=20Callback=20for=20validation=20of=20= incoming=20certificates.=20Returning=20SECFailure=20will=0A+=20*=20cause=20= NSS=20to=20terminate=20the=20connection=20immediately.=0A+=20*/=0A= +static=20SECStatus=0A+pg_cert_auth_handler(void=20*arg,=20PRFileDesc=20= *fd,=20PRBool=20checksig,=20PRBool=20isServer)=0A+{=0A+=09SECStatus=09= status;=0A+=09Port=09=20=20=20*port=20=3D=20(Port=20*)=20arg;=0A+=09= CERTCertificate=20*cert;=0A+=09char=09=20=20=20*peer_cn;=0A+=09unsigned=20= int=20len;=0A+=0A+=09status=20=3D=20= SSL_AuthCertificate(CERT_GetDefaultCertDB(),=20port->pr_fd,=20checksig,=20= PR_TRUE);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20= status;=0A+=0A+=09port->peer_cn=20=3D=20NULL;=0A+=09= port->peer_cert_valid=20=3D=20false;=0A+=0A+=09cert=20=3D=20= SSL_PeerCertificate(port->pr_fd);=0A+=09if=20(!cert)=0A+=09{=0A+=09=09/*=20= Shouldn't=20be=20possible;=20why=20did=20we=20get=20a=20client=20cert=20= callback?=20*/=0A+=09=09Assert(cert=20!=3D=20NULL);=0A+=0A+=09=09= PR_SetError(SEC_ERROR_LIBRARY_FAILURE,=200);=0A+=09=09return=20= SECFailure;=0A+=09}=0A+=0A+=09peer_cn=20=3D=20= raw_subject_common_name(cert,=20&len);=0A+=09if=20(!peer_cn)=0A+=09{=0A+=09= =09/*=20No=20Common=20Name,=20but=20the=20certificate=20otherwise=20= checks=20out.=20*/=0A+=09=09port->peer_cert_valid=20=3D=20true;=0A+=0A+=09= =09status=20=3D=20SECSuccess;=0A+=09=09goto=20cleanup;=0A+=09}=0A+=0A+=09= /*=0A+=09=20*=20Reject=20embedded=20NULLs=20in=20certificate=20common=20= name=20to=20prevent=20attacks=20like=0A+=09=20*=20CVE-2009-4034.=0A+=09=20= */=0A+=09if=20(len=20!=3D=20strlen(peer_cn))=0A+=09{=0A+=09=09= ereport(COMMERROR,=0A+=09=09=09=09(errcode(ERRCODE_PROTOCOL_VIOLATION),=0A= +=09=09=09=09=20errmsg("SSL=20certificate's=20common=20name=20contains=20= embedded=20null")));=0A+=0A+=09=09pfree(peer_cn);=0A+=09=09= PR_SetError(SEC_ERROR_CERT_NOT_VALID,=200);=0A+=0A+=09=09status=20=3D=20= SECFailure;=0A+=09=09goto=20cleanup;=0A+=09}=0A+=0A+=09port->peer_cn=20=3D= =20peer_cn;=0A+=09port->peer_cert_valid=20=3D=20true;=0A+=0A+=09= port->peer_dn=20=3D=20pg_CERT_GetDistinguishedName(cert);=0A+=09if=20=20= (!port->peer_dn)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09= (errcode(ERRCODE_PROTOCOL_VIOLATION),=0A+=09=09=09=09=20errmsg("unable=20= to=20get=20SSL=20certificate's=20distinguished=20name")));=0A+=0A+=09=09= pfree(peer_cn);=0A+=09=09PR_SetError(SEC_ERROR_CERT_NOT_VALID,=200);=0A+=0A= +=09=09status=20=3D=20SECFailure;=0A+=09=09goto=20cleanup;=0A+=09}=0A+=0A= +=09status=20=3D=20SECSuccess;=0A+=0A+cleanup:=0A+=09= CERT_DestroyCertificate(cert);=0A+=09return=20status;=0A+}=0A+=0A+static=20= PRStatus=0A+pg_ssl_close(PRFileDesc=20*fd)=0A+{=0A+=09/*=0A+=09=20*=20= Disconnect=20our=20private=20Port=20from=20the=20fd=20before=20closing=20= out=20the=20stack.=0A+=09=20*=20(Debug=20builds=20of=20NSPR=20will=20= assert=20if=20we=20do=20not.)=0A+=09=20*/=0A+=09fd->secret=20=3D=20NULL;=0A= +=09return=20PR_GetDefaultIOMethods()->close(fd);=0A+}=0A+=0A+static=20= PRFileDesc=20*=0A+init_iolayer(Port=20*port)=0A+{=0A+=09const=09=09= PRIOMethods=20*default_methods;=0A+=09PRFileDesc=20*layer;=0A+=0A+=09/*=0A= +=09=20*=20Start=20by=20initializing=20our=20layer=20with=20all=20the=20= default=20methods=20so=20that=20we=0A+=09=20*=20can=20selectively=20= override=20the=20ones=20we=20want=20while=20still=20ensuring=20that=20we=0A= +=09=20*=20have=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.close=20=3D=20pg_ssl_close;=0A+=0A+=09/*=0A+=09=20*=20Each=20= IO=20layer=20must=20be=20identified=20by=20a=20unique=20name,=20where=20= uniqueness=20is=0A+=09=20*=20per=20connection.=20Each=20connection=20in=20= a=20postgres=20cluster=20can=20generate=20the=0A+=09=20*=20identity=20= from=20the=20same=20string=20as=20they=20will=20create=20their=20IO=20= layers=20on=0A+=09=20*=20different=20sockets.=20Only=20one=20layer=20per=20= socket=20can=20have=20the=20same=20name.=0A+=09=20*/=0A+=09pr_id=20=3D=20= PR_GetUniqueIdentity("PostgreSQL=20Server");=0A+=09if=20(pr_id=20=3D=3D=20= PR_INVALID_IO_LAYER)=0A+=09{=0A+=09=09ereport(ERROR,=0A+=09=09=09=09= (errmsg("out=20of=20memory=20when=20setting=20up=20TLS=20connection")));=0A= +=09=09return=20NULL;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Create=20the=20= actual=20IO=20layer=20as=20a=20stub=20such=20that=20it=20can=20be=20= pushed=20onto=0A+=09=20*=20the=20layer=20stack.=20The=20step=20via=20a=20= stub=20is=20required=20as=20we=20define=20custom=0A+=09=20*=20callbacks.=0A= +=09=20*/=0A+=09layer=20=3D=20PR_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=20NSS=20I/O=20layer")));=0A+=09=09= return=20NULL;=0A+=09}=0A+=0A+=09/*=20Store=20the=20Port=20as=20private=20= data=20available=20in=20callbacks=20*/=0A+=09layer->secret=20=3D=20(void=20= *)=20port;=0A+=0A+=09return=20layer;=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)=0A+{=0A= +=09switch=20(v)=0A+=09{=0A+=09=09=09/*=0A+=09=09=09=20*=20There=20is=20= no=20SSL_LIBRARY_=20macro=20defined=20in=20NSS=20with=20the=20value=0A+=09= =09=09=20*=20zero,=20so=20we=20use=20this=20to=20signal=20the=20caller=20= that=20the=20highest=0A+=09=09=09=20*=20useful=20version=20should=20be=20= set=20on=20the=20connection.=0A+=09=09=09=20*/=0A+=09=09case=20= PG_TLS_ANY:=0A+=09=09=09return=200;=0A+=0A+=09=09=09/*=0A+=09=09=09=20*=20= No=20guard=20is=20required=20here=20as=20there=20are=20no=20versions=20= of=20NSS=0A+=09=09=09=20*=20without=20support=20for=20TLS1.=0A+=09=09=09=20= */=0A+=09=09case=20PG_TLS1_VERSION:=0A+=09=09=09return=20= SSL_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= +=0A+/*=0A+=20*=20pg_SSLAlertSent=0A+=20*=09=09Callback=20for=20TLS=20= alerts=20sent=20from=20NSS=0A+=20*=0A+=20*=20The=20alert=20system=20is=20= intended=20to=20provide=20information=20on=20ongoing=20issues=20to=0A+=20= *=20the=20TLS=20implementation=20such=20that=20they=20can=20be=20logged.=20= It=20is=20not=20replacing=0A+=20*=20error=20handling=20for=20the=20NSS=20= API,=20but=20rather=20adds=20a=20more=20finegrained=20way=20of=0A+=20*=20= extracting=20information=20on=20errors=20during=20connection=20= processing.=20The=20actual=0A+=20*=20error=20names=20are=20however=20= only=20accessible=20in=20a=20private=20NSS=20header=20and=20not=0A+=20*=20= exported.=20Thus,=20we=20only=20use=20it=20for=20close_notify=20which=20= is=20defined=20as=20zero.=0A+=20*=0A+=20*=20See=20= https://bugzilla.mozilla.org/show_bug.cgi?id=3D956866=20for=20further=0A= +=20*=20discussion=20on=20this=20interface.=0A+=20*/=0A+static=20void=0A= +pg_SSLAlertSent(const=20PRFileDesc=20*fd,=20void=20*private_data,=20= const=20SSLAlert=20*alert)=0A+{=0A+=09Port=20*port=20=3D=20(Port=20*)=20= private_data;=0A+=0A+=09/*=0A+=09=20*=20close_notify=20is=20not=20an=20= error,=20but=20an=20indication=20that=20the=20connection=0A+=09=20*=20= was=20orderly=20closed.=20Since=20the=20backend=20is=20only=20closing=20= connections=20where=0A+=09=20*=20TLS=20is=20no=20longer=20in=20use,=20= log=20an=20error=20in=20case=20this=20wasn't=20the=20case.=0A+=09=20*=20= close_notify=20is=20defined=20in=20the=20NSS=20private=20enum=20= SSL3AlertDescription=0A+=09=20*=20as=20zero.=0A+=09=20*/=0A+=09if=20= (alert->description=20=3D=3D=200)=0A+=09{=0A+=09=09if=20= (port->ssl_in_use)=0A+=09=09=09ereport(COMMERROR,=0A+=09=09=09=09=09=20= errmsg("closing=20an=20active=20TLS=20connection"));=0A+=09=09return;=0A= +=09}=0A+=0A+=09/*=0A+=09=20*=20Any=20other=20alert=20received=20= indicates=20an=20error,=20but=20since=20they=20can't=20be=0A+=09=20*=20= made=20heads=20or=20tails=20with=20without=20reading=20the=20NSS=20= source=20code=20let's=0A+=09=20*=20just=20log=20them=20as=20DEBUG=20= information=20as=20they=20are=20of=20limited=20value=20in=0A+=09=20*=20= any=20other=20circumstance.=0A+=09=20*/=0A+=09ereport(DEBUG2,=0A+=09=09=09= (errmsg_internal("TLS=20alert=20received:=20%d",=20= alert->description)));=0A+}=0A+=0A+/*=0A+=20*=20pg_SSLShutdownFunc=0A+=20= *=09=09Callback=20for=20NSS=20shutdown=0A+=20*=0A+=20*=20If=20NSS=20is=20= terminated=20from=20the=20outside=20when=20the=20connection=20is=20still=20= in=20use=0A+=20*=20we=20must=20treat=20this=20as=20potentially=20hostile=20= and=20immediately=20close=20to=20avoid=0A+=20*=20leaking=20the=20= connection=20in=20any=20way.=20Once=20this=20is=20called,=20NSS=20will=20= shutdown=0A+=20*=20regardless=20so=20we=20may=20as=20well=20clean=20up=20= the=20best=20we=20can.=20Returning=20SECFailure=0A+=20*=20will=20cause=20= the=20NSS=20shutdown=20to=20return=20with=20an=20error,=20but=20it=20= will=20shutdown=0A+=20*=20nevertheless.=20nss_data=20is=20reserved=20for=20= future=20use=20and=20is=20always=20NULL.=0A+=20*/=0A+static=20SECStatus=0A= +pg_SSLShutdownFunc(void=20*private_data,=20void=20*nss_data)=0A+{=0A+=09= Port=20*port=20=3D=20(Port=20*)=20private_data;=0A+=0A+=09if=20(!port=20= ||=20!port->ssl_in_use)=0A+=09=09return=20SECSuccess;=0A+=0A+=09/*=0A+=09= =20*=20There=20is=20a=20connection=20still=20open,=20close=20it=20and=20= signal=20to=20whatever=20that=0A+=09=20*=20called=20the=20shutdown=20= that=20it=20was=20erroneous.=0A+=09=20*/=0A+=09be_tls_close(port);=0A+=09= be_tls_destroy();=0A+=0A+=09return=20SECFailure;=0A+}=0Adiff=20--git=20= a/src/backend/libpq/be-secure.c=20b/src/backend/libpq/be-secure.c=0A= index=208ef083200a..cf056f5364=20100644=0A---=20= a/src/backend/libpq/be-secure.c=0A+++=20b/src/backend/libpq/be-secure.c=0A= @@=20-50,6=20+50,7=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+char=09=20=20= =20*ssl_database;=0A=20=0A=20/*=20GUC=20variable=20controlling=20SSL=20= cipher=20list=20*/=0A=20char=09=20=20=20*SSLCipherSuites=20=3D=20NULL;=0A= diff=20--git=20a/src/backend/utils/misc/guc.c=20= b/src/backend/utils/misc/guc.c=0Aindex=20e91d5a3cfd..3c7317eac8=20100644=0A= ---=20a/src/backend/utils/misc/guc.c=0A+++=20= b/src/backend/utils/misc/guc.c=0A@@=20-4435,7=20+4435,11=20@@=20static=20= struct=20config_string=20ConfigureNamesString[]=20=3D=0A=20=09=09},=0A=20= =09=09&ssl_library,=0A=20#ifdef=20USE_SSL=0A+#if=20defined(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-4503,6=20+4507,16=20= @@=20static=20struct=20config_string=20ConfigureNamesString[]=20=3D=0A=20= =09=09check_canonical_path,=20assign_pgstat_temp_directory,=20NULL=0A=20=09= },=0A=20=0A+=09{=0A+=09=09{"ssl_database",=20PGC_SIGHUP,=20= CONN_AUTH_SSL,=0A+=09=09=09gettext_noop("Location=20of=20the=20NSS=20= certificate=20database."),=0A+=09=09=09NULL=0A+=09=09},=0A+=09=09= &ssl_database,=0A+=09=09"",=0A+=09=09NULL,=20NULL,=20NULL=0A+=09},=0A+=0A= =20=09{=0A=20=09=09{"synchronous_standby_names",=20PGC_SIGHUP,=20= REPLICATION_PRIMARY,=0A=20=09=09=09gettext_noop("Number=20of=20= synchronous=20standbys=20and=20list=20of=20names=20of=20potential=20= synchronous=20ones."),=0A@@=20-4531,8=20+4545,10=20@@=20static=20struct=20= config_string=20ConfigureNamesString[]=20=3D=0A=20=09=09=09= GUC_SUPERUSER_ONLY=0A=20=09=09},=0A=20=09=09&SSLCipherSuites,=0A-#ifdef=20= USE_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/cipher_nss.c=20b/src/common/cipher_nss.c=0Anew=20file=20= mode=20100644=0Aindex=200000000000..30b32a7908=0A---=20/dev/null=0A+++=20= b/src/common/cipher_nss.c=0A@@=20-0,0=20+1,192=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20cipher_nss.c=0A+=20*=09=20=20NSS=20functionality=20= shared=20between=20frontend=20and=20backend=20for=20working=0A+=20*=09=20= =20with=20ciphers=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-2021,=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*=20=20=20=20=20=20=20=20src/common/cipher_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+#include=20"common/nss.h"=0A= +=0A+#define=20INVALID_CIPHER=090xFFFF=0A+=0A+typedef=20struct=0A+{=0A+=09= SECOidTag=09signature;=0A+=09SECOidTag=09hash;=0A+=09int=09=09=09len;=0A= +}=09=09=09NSSSignatureAlgorithm;=0A+=0A+static=20const=20= NSSSignatureAlgorithm=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= +typedef=20struct=0A+{=0A+=09const=20char=20*name;=0A+=09PRUint16=09= number;=0A+}=09=09=09NSSCiphers;=0A+=0A+/*=0A+=20*=20This=20list=20is=20= a=20partial=20copy=20of=20the=20ciphers=20in=20NSS=20files=20= lib/ssl/sslproto.h=0A+=20*=20in=20order=20to=20provide=20a=20human=20= readable=20version=20of=20the=20ciphers.=20It=20would=20be=0A+=20*=20= nice=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+bool=0A+pg_find_cipher(char=20*name,=20= PRUint16=20*cipher)=0A+{=0A+=09const=09=09NSSCiphers=20*cipher_list;=0A+=0A= +=09for=20(cipher_list=20=3D=20NSS_CipherList;=20cipher_list->name;=20= cipher_list++)=0A+=09{=0A+=09=09if=20(pg_strcasecmp(cipher_list->name,=20= name)=20=3D=3D=200)=0A+=09=09{=0A+=09=09=09*cipher=20=3D=20= cipher_list->number;=0A+=09=09=09return=20true;=0A+=09=09}=0A+=09}=0A+=0A= +=09return=20false;=0A+}=0A+=0A+bool=0A= +pg_find_signature_algorithm(SECOidTag=20signature,=20SECOidTag=20= *algorithm,=20int=20*len)=0A+{=0A+=09const=20NSSSignatureAlgorithm=20= *candidate;=0A+=0A+=09candidate=20=3D=20NSS_SCRAMDigestAlgorithm;=0A+=0A= +=09for=20(candidate=20=3D=20NSS_SCRAMDigestAlgorithm;=20= candidate->signature;=20candidate++)=0A+=09{=0A+=09=09if=20(signature=20= =3D=3D=20candidate->signature)=0A+=09=09{=0A+=09=09=09*algorithm=20=3D=20= candidate->hash;=0A+=09=09=09*len=20=3D=20candidate->len;=0A+=09=09=09= return=20true;=0A+=09=09}=0A+=09}=0A+=0A+=09return=20false;=0A+}=0Adiff=20= --git=20a/src/common/protocol_nss.c=20b/src/common/protocol_nss.c=0Anew=20= file=20mode=20100644=0Aindex=200000000000..4d12c9f388=0A---=20/dev/null=0A= +++=20b/src/common/protocol_nss.c=0A@@=20-0,0=20+1,59=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20protocol_nss.c=0A+=20*=09=20=20NSS=20functionality=20= shared=20between=20frontend=20and=20backend=20for=20working=0A+=20*=09=20= =20with=20protocols=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-2021,=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/protocol_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+#include=20"common/nss.h"=0A= +=0A+/*=0A+=20*=20ssl_protocol_version_to_string=0A+=20*=09=09=09= Translate=20NSS=20TLS=20version=20to=20string=0A+=20*/=0A+char=20*=0A= +ssl_protocol_version_to_string(int=20v)=0A+{=0A+=09switch=20(v)=0A+=09{=0A= +=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=20"TLSv1.0";=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_1=0A+=09=09case=20SSL_LIBRARY_VERSION_TLS_1_1:=0A= +=09=09=09return=20"TLSv1.1";=0A+#endif=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_2=0A+=09=09case=20SSL_LIBRARY_VERSION_TLS_1_2:=0A= +=09=09=09return=20"TLSv1.2";=0A+#endif=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_3=0A+=09=09case=20SSL_LIBRARY_VERSION_TLS_1_3:=0A= +=09=09=09return=20"TLSv1.3";=0A+#endif=0A+=09}=0A+=0A+=09return=20= "unknown";=0A+}=0A+=0Adiff=20--git=20a/src/include/common/nss.h=20= b/src/include/common/nss.h=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..10455ecbe5=0A---=20/dev/null=0A+++=20= b/src/include/common/nss.h=0A@@=20-0,0=20+1,52=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20nss.h=0A+=20*=09=20=20NSS=20supporting=20= functionality=20shared=20between=20frontend=20and=20backend=0A+=20*=0A+=20= *=20Portions=20Copyright=20(c)=201996-2021,=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/include/common/nss.h=0A+=20*=0A+=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+#ifndef=20COMMON_NSS_H=0A+#define=20COMMON_NSS_H=0A+=0A= +#ifdef=20USE_NSS=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+=20*=20The=20nspr/obsolete/protypes.h=20= NSPR=20header=20typedefs=20uint64=20and=20int64=20with=0A+=20*=20= colliding=20definitions=20from=20ours,=20causing=20a=20much=20expected=20= compiler=20error.=0A+=20*=20Remove=20backwards=20compatibility=20with=20= ancient=20NSPR=20versions=20to=20avoid=20this.=0A+=20*/=0A+#define=20= NO_NSPR_10_SUPPORT=0A+#include=20=0A+#include=20=0A= +#include=20=0A+#include=20=0A+#include=20=0A= +=0A+=0A+#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+=0A+/*=20= src/common/cipher_nss.c=20*/=0A+bool=20pg_find_cipher(char=20*name,=20= PRUint16=20*cipher);=0A+bool=20pg_find_signature_algorithm(SECOidTag=20= signature,=20SECOidTag=20*digest,=20int=20*len);=0A+=0A+/*=20= src/common/protocol_nss.c=20*/=0A+char=20= *ssl_protocol_version_to_string(int=20version);=0A+=0A+#endif=09=09=09=09= =09=09=09/*=20USE_NSS=20*/=0A+=0A+#endif=09=09=09=09=09=09=09/*=20= COMMON_NSS_H=20*/=0Adiff=20--git=20a/src/include/libpq/libpq-be.h=20= b/src/include/libpq/libpq-be.h=0Aindex=2002015efe13..c8388c5450=20100644=0A= ---=20a/src/include/libpq/libpq-be.h=0A+++=20= b/src/include/libpq/libpq-be.h=0A@@=20-212,13=20+212,18=20@@=20typedef=20= struct=20Port=0A=20=09bool=09=09peer_cert_valid;=0A=20=0A=20=09/*=0A-=09=20= *=20OpenSSL=20structures.=20(Keep=20these=20last=20so=20that=20the=20= locations=20of=20other=0A-=09=20*=20fields=20are=20the=20same=20whether=20= or=20not=20you=20build=20with=20SSL=20enabled.)=0A+=09=20*=20TLS=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= -301,7=20+306,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-311,6=20+316,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=206b67a2a318..351520901e=20100644=0A= ---=20a/src/include/libpq/libpq.h=0A+++=20b/src/include/libpq/libpq.h=0A= @@=20-98,6=20+98,7=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+extern=20= char=20*ssl_database;=0A=20=0A=20extern=20int=09secure_initialize(bool=20= isServerStart);=0A=20extern=20bool=20= secure_loaded_verify_locations(void);=0Adiff=20--git=20= a/src/include/pg_config_manual.h=20b/src/include/pg_config_manual.h=0A= index=20225c5b87cc..c431645ba0=20100644=0A---=20= a/src/include/pg_config_manual.h=0A+++=20= b/src/include/pg_config_manual.h=0A@@=20-202,7=20+202,7=20@@=0A=20=20*=20= USE_SSL=20code=20should=20be=20compiled=20only=20when=20compiling=20with=20= an=20SSL=0A=20=20*=20implementation.=0A=20=20*/=0A-#ifdef=20USE_OPENSSL=0A= +#if=20defined(USE_OPENSSL)=20||=20defined(USE_NSS)=0A=20#define=20= USE_SSL=0A=20#endif=0A=20=0Adiff=20--git=20= a/src/interfaces/libpq/fe-connect.c=20= b/src/interfaces/libpq/fe-connect.c=0Aindex=209b6a6939f0..3aa68a336b=20= 100644=0A---=20a/src/interfaces/libpq/fe-connect.c=0A+++=20= b/src/interfaces/libpq/fe-connect.c=0A@@=20-344,6=20+344,10=20@@=20= static=20const=20internalPQconninfoOption=20PQconninfoOptions[]=20=3D=20= {=0A=20=09=09"Target-Session-Attrs",=20"",=2015,=20/*=20= sizeof("prefer-standby")=20=3D=2015=20*/=0A=20=09offsetof(struct=20= pg_conn,=20target_session_attrs)},=0A=20=0A+=09{"ssldatabase",=20NULL,=20= NULL,=20NULL,=0A+=09=09"CertificateDatabase",=20"",=2064,=0A+=09= offsetof(struct=20pg_conn,=20ssldatabase)},=0A+=0A=20=09/*=20Terminating=20= entry=20---=20MUST=20BE=20LAST=20*/=0A=20=09{NULL,=20NULL,=20NULL,=20= NULL,=0A=20=09NULL,=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..cc5bc1d80d=0A---=20/dev/null=0A+++=20= b/src/interfaces/libpq/fe-secure-nss.c=0A@@=20-0,0=20+1,1229=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-2021,=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/cryptohash.h"=0A+#include=20"common/nss.h"=0A+=0A+#ifdef=20= ENABLE_THREAD_SAFETY=0A+#ifdef=20WIN32=0A+#include=20"pthread-win32.h"=0A= +#else=0A+#include=20=0A+#endif=0A+#endif=0A+=0A+/*=0A+=20*=20= The=20nspr/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= +=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= +static=20SECStatus=20pg_load_nss_module(SECMODModule=20**module,=20= const=20char=20*library,=20const=20char=20*name);=0A+static=20SECStatus=20= pg_bad_cert_handler(void=20*arg,=20PRFileDesc=20*fd);=0A+static=20const=20= char=20*pg_SSLerrmessage(PRErrorCode=20errcode);=0A+static=20SECStatus=20= pg_client_auth_handler(void=20*arg,=20PRFileDesc=20*socket,=20= CERTDistNames=20*caNames,=0A+=09=09=09=09=09=09=09=09=09=09= CERTCertificate=20**pRetCert,=20SECKEYPrivateKey=20**pRetKey);=0A+static=20= SECStatus=20pg_cert_auth_handler(void=20*arg,=20PRFileDesc=20*fd,=20= PRBool=20checksig,=20PRBool=20isServer);=0A+static=20int=09= ssl_protocol_param_to_nss(const=20char=20*protocol);=0A+static=20bool=20= certificate_database_has_CA(PGconn=20*conn);=0A+=0A+static=20char=20= *PQssl_passwd_cb(PK11SlotInfo=20*slot,=20PRBool=20retry,=20void=20*arg);=0A= +=0A+/*=0A+=20*=20PR_ImportTCPSocket()=20is=20a=20private=20API,=20but=20= very=20widely=20used,=20as=20it's=20the=0A+=20*=20only=20way=20to=20make=20= NSS=20use=20an=20already=20set=20up=20POSIX=20file=20descriptor=20rather=0A= +=20*=20than=20opening=20one=20itself.=20To=20quote=20the=20NSS=20= documentation:=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+static=20= SECMODModule=20*ca_trust=20=3D=20NULL;=0A+=0A+/*=0A+=20*=20This=20logic=20= exists=20in=20NSS=20as=20well,=20but=20it's=20only=20available=20for=20= when=20there=20is=0A+=20*=20a=20database=20to=20open,=20and=20not=20only=20= using=20the=20system=20trust=20store.=20Thus,=20we=0A+=20*=20need=20to=20= keep=20our=20own=20copy.=0A+=20*/=0A+#if=20defined(WIN32)=0A+static=20= const=20char=20*ca_trust_name=20=3D=20"nssckbi.dll";=0A+#elif=20= defined(__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=20= PQsslKeyPassHook_nss_type=20PQsslKeyPassHook=20=3D=20NULL;=0A+=0A+#ifdef=20= ENABLE_THREAD_SAFETY=0A+#ifndef=20WIN32=0A+static=20pthread_mutex_t=20= ssl_config_mutex=20=3D=20PTHREAD_MUTEX_INITIALIZER;=0A+#else=0A+static=20= pthread_mutex_t=20ssl_config_mutex=20=3D=20NULL;=0A+static=20long=20= win32_ssl_create_mutex=20=3D=200;=0A+#endif=0A+#endif=09=09=09=09=09=09=09= /*=20ENABLE_THREAD_SAFETY=20*/=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,=20bool=20do_ssl,=20bool=20do_crypto)=0A+{=0A= +=09if=20(do_ssl)=0A+=09{=0A+=09=09conn->nss_context=20=3D=20NULL;=0A+=0A= +=09=09conn->ssl_in_use=20=3D=20false;=0A+=09=09conn->has_password=20=3D=20= false;=0A+=09}=0A+=0A+=09return=200;=0A+}=0A+=0A+void=0A= +pgtls_close(PGconn=20*conn)=0A+{=0A+=09conn->ssl_in_use=20=3D=20false;=0A= +=09conn->has_password=20=3D=20false;=0A+=0A+=09/*=0A+=09=20*=20All=20= NSS=20references=20must=20be=20cleaned=20up=20before=20we=20close=20out=20= the=0A+=09=20*=20context.=0A+=09=20*/=0A+=09if=20(conn->pr_fd)=0A+=09{=0A= +=09=09PRStatus=09status;=0A+=0A+=09=09status=20=3D=20= PR_Close(conn->pr_fd);=0A+=09=09if=20(status=20!=3D=20PR_SUCCESS)=0A+=09=09= {=0A+=09=09=09pqInternalNotice(&conn->noticeHooks,=0A+=09=09=09=09=09=09=09= =20"unable=20to=20close=20NSPR=20fd:=20%s",=0A+=09=09=09=09=09=09=09=20= pg_SSLerrmessage(PR_GetError()));=0A+=09=09}=0A+=0A+=09=09conn->pr_fd=20= =3D=20NULL;=0A+=09}=0A+=0A+=09if=20(conn->nss_context)=0A+=09{=0A+=09=09= SECStatus=09status;=0A+=0A+=09=09/*=20The=20session=20cache=20must=20be=20= cleared,=20or=20we'll=20leak=20references=20*/=0A+=09=09= SSL_ClearSessionCache();=0A+=0A+=09=09status=20=3D=20= NSS_ShutdownContext(conn->nss_context);=0A+=0A+=09=09if=20(status=20!=3D=20= SECSuccess)=0A+=09=09{=0A+=09=09=09pqInternalNotice(&conn->noticeHooks,=0A= +=09=09=09=09=09=09=09=20"unable=20to=20shut=20down=20NSS=20context:=20= %s",=0A+=09=09=09=09=09=09=09=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09= }=0A+=0A+=09=09conn->nss_context=20=3D=20NULL;=0A+=09}=0A+}=0A+=0A= +PostgresPollingStatusType=0A+pgtls_open_client(PGconn=20*conn)=0A+{=0A+=09= SECStatus=09status;=0A+=09PRFileDesc=20*model;=0A+=09NSSInitParameters=20= params;=0A+=09SSLVersionRange=20desired_range;=0A+=0A+#ifdef=20= ENABLE_THREAD_SAFETY=0A+#ifdef=20WIN32=0A+=09/*=20This=20locking=20is=20= modelled=20after=20fe-secure-openssl.c=20*/=0A+=09if=20(ssl_config_mutex=20= =3D=3D=20NULL)=0A+=09{=0A+=09=09while=20= (InterlockedExchange(&win32_ssl_create_mutex,=201)=20=3D=3D=201)=0A+=09=09= =09/*=20loop=20while=20another=20thread=20owns=20the=20lock=20*/=20;=0A+=09= =09if=20(ssl_config_mutex=20=3D=3D=20NULL)=0A+=09=09{=0A+=09=09=09if=20= (pthread_mutex_init(&ssl_config_mutex,=20NULL))=0A+=09=09=09{=0A+=09=09=09= =09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20lock=20thread"));=0A+=09=09=09=09return=20= PGRES_POLLING_FAILED;=0A+=09=09=09}=0A+=09=09}=0A+=09=09= InterlockedExchange(&win32_ssl_create_mutex,=200);=0A+=09}=0A+#endif=0A+=09= if=20(pthread_mutex_lock(&ssl_config_mutex))=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20lock=20thread"));=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+#endif=09=09=09=09=09=09=09/*=20= ENABLE_THREAD_SAFETY=20*/=0A+=0A+=09/*=0A+=09=20*=20The=20NSPR=20= documentation=20states=20that=20runtime=20initialization=20via=20PR_Init=0A= +=09=20*=20is=20no=20longer=20required,=20as=20the=20first=20caller=20= into=20NSPR=20will=20perform=20the=0A+=09=20*=20initialization=20= implicitly.=20See=20be-secure-nss.c=20for=20further=20discussion=0A+=09=20= *=20on=20PR_Init.=0A+=09=20*/=0A+=09PR_Init(PR_USER_THREAD,=20= PR_PRIORITY_NORMAL,=200);=0A+=0A+=09/*=0A+=09=20*=20NSS=20initialization=20= and=20the=20use=20of=20contexts=20is=20further=20discussed=20in=0A+=09=20= *=20be-secure-nss.c=0A+=09=20*/=0A+=09memset(¶ms,=200,=20= sizeof(params));=0A+=09params.length=20=3D=20sizeof(params);=0A+=09= params.dbTokenDescription=20=3D=20strdup("postgres");=0A+=0A+=09if=20= (conn->ssldatabase=20&&=20strlen(conn->ssldatabase)=20>=200)=0A+=09{=0A+=09= =09PQExpBufferData=20ssldatabase_path;=0A+=0A+=09=09= initPQExpBuffer(&ssldatabase_path);=0A+=09=09= appendPQExpBuffer(&ssldatabase_path,=20"sql:%s",=20conn->ssldatabase);=0A= +=0A+=09=09if=20(PQExpBufferDataBroken(ssldatabase_path))=0A+=09=09{=0A+=09= =09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("out=20of=20memory\n"));=0A+=09=09=09return=20= PGRES_POLLING_FAILED;=0A+=09=09}=0A+=0A+=09=09conn->nss_context=20=3D=20= NSS_InitContext(ssldatabase_path.data,=20"",=20"",=20"",=0A+=09=09=09=09=09= =09=09=09=09=09=09¶ms,=0A+=09=09=09=09=09=09=09=09=09=09=09= NSS_INIT_READONLY=20|=20NSS_INIT_PK11RELOAD);=0A+=09=09= termPQExpBuffer(&ssldatabase_path);=0A+=0A+=09=09if=20= (!conn->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=20open=20certificate=20database=20\"%s\":=20= %s"),=0A+=09=09=09=09=09=09=09=20=20conn->ssldatabase,=0A+=09=09=09=09=09= =09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09=09return=20= PGRES_POLLING_FAILED;=0A+=09=09}=0A+=09}=0A+=09else=0A+=09{=0A+=09=09= conn->nss_context=20=3D=20NSS_InitContext("",=20"",=20"",=20"",=20= ¶ms,=0A+=09=09=09=09=09=09=09=09=09=09=09NSS_INIT_READONLY=20|=20= NSS_INIT_NOCERTDB=20|=0A+=09=09=09=09=09=09=09=09=09=09=09= NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A+=09=09=09=09=09=09=09=09= =09=09=09NSS_INIT_NOROOTINIT=20|=20NSS_INIT_PK11RELOAD);=0A+=09=09if=20= (!conn->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=20initialize=20NSS:=20%s"),=0A+=09=09=09=09=09= =09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09=09return=20= PGRES_POLLING_FAILED;=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20= Configure=20cipher=20policy=20by=20setting=20the=20domestic=20suite.=0A+=09= =20*=0A+=09=20*=20Historically=20there=20were=20different=20cipher=20= policies=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+=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->ssldatabase=20&&=0A+=09=09= (strcmp(conn->sslmode,=20"verify-ca")=20=3D=3D=200=20||=0A+=09=09=20= strcmp(conn->sslmode,=20"verify-full")=20=3D=3D=200))=0A+=09{=0A+=09=09= status=20=3D=20pg_load_nss_module(&ca_trust,=20ca_trust_name,=20"\"Root=20= Certificates\"");=0A+=09=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09{=0A= +=09=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09= =20=20libpq_gettext("WARNING:=20unable=20to=20load=20system=20NSS=20= trust=20module=20\"%s\",=20create=20a=20local=20NSS=20database=20and=20= retry=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+#ifdef=20= ENABLE_THREAD_SAFETY=0A+=09pthread_mutex_unlock(&ssl_config_mutex);=0A= +#endif=0A+=0A+=09PK11_SetPasswordFunc(PQssl_passwd_cb);=0A+=0A+=09/*=0A= +=09=20*=20Import=20the=20already=20opened=20socket=20as=20we=20don't=20= want=20to=20use=20NSPR=20functions=0A+=09=20*=20for=20opening=20the=20= network=20socket=20due=20to=20how=20the=20PostgreSQL=20protocol=20works=0A= +=09=20*=20with=20TLS=20connections.=20This=20function=20is=20not=20part=20= of=20the=20NSPR=20public=20API,=0A+=09=20*=20see=20the=20comment=20at=20= the=20top=20of=20the=20file=20for=20the=20rationale=20of=20still=20using=0A= +=09=20*=20it.=0A+=09=20*/=0A+=09conn->pr_fd=20=3D=20= PR_ImportTCPSocket(conn->sock);=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=20attach=20to=20socket:=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*=20Most=20of=20the=20= documentation=20available,=20and=20implementations=20of,=20NSS/NSPR=0A+=09= =20*=20use=20the=20PR_NewTCPSocket()=20function=20here,=20which=20has=20= the=20drawback=20that=20it=0A+=09=20*=20can=20only=20create=20IPv4=20= sockets.=20Instead=20use=20PR_OpenTCPSocket()=20which=0A+=09=20*=20copes=20= with=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_param_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_param_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= conn->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=20be=20closed=20as=20we've=20applied=20the=20settings=20of=20= the=20model=0A+=09=20*=20onto=20the=20real=20socket.=20=46rom=20here=20= on=20we=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+=09status=20= =3D=20SSL_ResetHandshake(conn->pr_fd,=20PR_FALSE);=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=20initiate=20handshake:=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/*=20Set=20callback=20for=20= client=20authentication=20when=20requested=20by=20the=20server=20*/=0A+=09= SSL_GetClientAuthDataHook(conn->pr_fd,=20pg_client_auth_handler,=20(void=20= *)=20conn);=0A+=0A+=09/*=0A+=09=20*=20Specify=20which=20hostname=20we=20= are=20expecting=20to=20talk=20to=20for=20the=20ClientHello=0A+=09=20*=20= SNI=20extension,=20unless=20the=20user=20has=20disabled=20it.=20NSS=20= will=20suppress=20IP=0A+=09=20*=20addresses=20in=20SNIs,=20so=20we=20= don't=20need=20to=20filter=20those=20explicitly=20like=20we=20do=0A+=09=20= *=20for=20OpenSSL.=0A+=09=20*/=0A+=09if=20(conn->sslsni=20&&=20= conn->sslsni[0]=20=3D=3D=20'1')=0A+=09{=0A+=09=09const=20char=20*host=20= =3D=20conn->connhost[conn->whichhost].host;=0A+=09=09if=20(host=20&&=20= host[0])=0A+=09=09=09SSL_SetURL(conn->pr_fd,=20host);=0A+=09}=0A+=0A+=09= status=20=3D=20SSL_ForceHandshake(conn->pr_fd);=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("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+=09Assert(conn->nss_context);=0A+=09= Assert(conn->pr_fd);=0A+=0A+=09conn->ssl_in_use=20=3D=20true;=0A+=09= return=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=09appendPQExpBufferStr(&conn->errorMessage,=0A+=09=09=09=09=09= =09=09=20libpq_gettext("TLS=20read=20error:=20EOF=20detected\n"));=0A+=09= =09read_errno=20=3D=20ECONNRESET;=0A+=09=09nread=20=3D=20-1;=0A+=09}=0A+=09= else=20if=20(nread=20=3D=3D=20-1)=0A+=09{=0A+=09=09status=20=3D=20= PR_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*=20SSL_DataPending=20= will=20check=20for=20decrypted=20data=20in=20the=20receiving=20buffer,=20= but=0A+=20*=20does=20not=20reveal=20anything=20about=20still=20encrypted=20= data=20which=20will=20be=20made=0A+=20*=20available.=20Thus,=20if=20= pgtls_read_pending=20returns=20zero=20it=20does=20not=20guarantee=0A+=20= *=20that=20a=20subsequent=20call=20to=20pgtls_read=20would=20block.=20= This=20is=20modelled=0A+=20*=20around=20how=20the=20OpenSSL=20= implementation=20treats=20pending=20data.=20The=20equivalent=0A+=20*=20= to=20the=20OpenSSL=20SSL_has_pending=20function=20would=20be=20to=20call=20= PR_Recv=20with=20no=0A+=20*=20wait=20and=20PR_MSG_PEEK=20like=20so:=0A+=20= *=0A+=20*=20=20=20=20=20PR_Recv(conn->pr_fd,=20&c,=201,=20PR_MSG_PEEK,=20= PR_INTERVAL_NO_WAIT);=0A+=20*/=0A+bool=0A+pgtls_read_pending(PGconn=20= *conn)=0A+{=0A+=09return=20SSL_DataPending(conn->pr_fd)=20>=200;=0A+}=0A= +=0A+/*=0A+=20*=20pgtls_write=0A+=20*=09=09Write=20data=20on=20the=20= secure=20socket=0A+=20*=0A+=20*/=0A+ssize_t=0A+pgtls_write(PGconn=20= *conn,=20const=20void=20*ptr,=20size_t=20len)=0A+{=0A+=09PRInt32=09=09n;=0A= +=09PRErrorCode=20status;=0A+=09int=09=09=09write_errno=20=3D=200;=0A+=0A= +=09n=20=3D=20PR_Write(conn->pr_fd,=20ptr,=20len);=0A+=0A+=09if=20(n=20<=20= 0)=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=20= EAGAIN=0A+=09=09=09=09write_errno=20=3D=20EAGAIN;=0A+#else=0A+=09=09=09=09= write_errno=20=3D=20EINTR;=0A+#endif=0A+=09=09=09=09break;=0A+=0A+=09=09=09= default:=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=09= write_errno=20=3D=20ECONNRESET;=0A+=09=09=09=09break;=0A+=09=09}=0A+=09}=0A= +=0A+=09SOCK_ERRNO_SET(write_errno);=0A+=09return=20(ssize_t)=20n;=0A+}=0A= +=0A+char=20*=0A+pgtls_get_peer_certificate_hash(PGconn=20*conn,=20= size_t=20*len)=0A+{=0A+=09CERTCertificate=20*server_cert;=0A+=09= SECOidTag=09signature_tag;=0A+=09SECOidTag=09digest_alg;=0A+=09int=09=09=09= digest_len;=0A+=09PLArenaPool=20*arena=20=3D=20NULL;=0A+=09SECItem=09=09= digest;=0A+=09char=09=20=20=20*ret=20=3D=20NULL;=0A+=09SECStatus=09= status;=0A+=0A+=09*len=20=3D=200;=0A+=0A+=09server_cert=20=3D=20= SSL_PeerCertificate(conn->pr_fd);=0A+=09if=20(!server_cert)=0A+=09=09= goto=20cleanup;=0A+=0A+=09signature_tag=20=3D=20= SECOID_GetAlgorithmTag(&server_cert->signature);=0A+=09if=20= (!pg_find_signature_algorithm(signature_tag,=20&digest_alg,=20= &digest_len))=0A+=09{=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A= +=09=09=09=09=09=09=20=20libpq_gettext("could=20not=20find=20digest=20= for=20OID=20'%s'\n"),=0A+=09=09=09=09=09=09=20=20= SECOID_FindOIDTagDescription(signature_tag));=0A+=09=09goto=20cleanup;=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= if=20(!digest.data)=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("out=20of=20memory"));=0A+=09=09goto=20cleanup;=0A+=09}=0A= +=09digest.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= =09goto=20cleanup;=0A+=09}=0A+=0A+=09ret=20=3D=20malloc(digest.len);=0A+=09= if=20(ret=20=3D=3D=20NULL)=0A+=09{=0A+=09=09= appendPQExpBufferStr(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20= libpq_gettext("out=20of=20memory\n"));=0A+=09=09goto=20cleanup;=0A+=09}=0A= +=0A+=09memcpy(ret,=20digest.data,=20digest.len);=0A+=09*len=20=3D=20= digest_len;=0A+=0A+cleanup:=0A+=09if=20(arena)=0A+=09=09= PORT_FreeArena(arena,=20PR_TRUE);=0A+=09if=20(server_cert)=0A+=09=09= CERT_DestroyCertificate(server_cert);=0A+=0A+=09return=20ret;=0A+}=0A+=0A= +/*=0A+=20*=09Verify=20that=20the=20server=20certificate=20matches=20the=20= hostname=20we=20connected=20to.=0A+=20*=0A+=20*=20The=20certificate's=20= Common=20Name=20and=20Subject=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=20NULL;=0A+=09SECStatus=09status=20=3D=20SECSuccess;=0A= +=09SECItem=09=09altname_item;=0A+=09PLArenaPool=20*arena=20=3D=20NULL;=0A= +=09CERTGeneralName=20*san_list;=0A+=09CERTGeneralName=20*cn;=0A+=0A+=09= /*=0A+=09=20*=20In=20the=20"standard"=20NSS=20use=20case,=20we'd=20call=20= SSL_RevealURL()=20to=20get=20the=0A+=09=20*=20hostname.=20In=20our=20= case,=20SSL_SetURL()=20won't=20have=20been=20called=20if=20the=20user=0A= +=09=20*=20has=20disabled=20SNI,=20so=20we=20always=20pull=20the=20= hostname=20from=20connhost=20instead.=0A+=09=20*/=0A+=09server_hostname=20= =3D=20conn->connhost[conn->whichhost].host;=0A+=09if=20(!server_hostname=20= ||=20server_hostname[0]=20=3D=3D=20'\0')=0A+=09{=0A+=09=09/*=20= verify-full=20shouldn't=20progress=20this=20far=20without=20a=20= hostname.=20*/=0A+=09=09status=20=3D=20SECFailure;=0A+=09=09goto=20done;=0A= +=09}=0A+=0A+=09/*=0A+=09=20*=20CERT_VerifyCertName=20will=20internally=20= perform=20RFC=202818=20SubjectAltName=0A+=09=20*=20verification.=0A+=09=20= */=0A+=09server_cert=20=3D=20SSL_PeerCertificate(conn->pr_fd);=0A+=09= status=20=3D=20CERT_VerifyCertName(server_cert,=20server_hostname);=0A+=09= if=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+=09if=20(server_cert)=0A+=09=09= CERT_DestroyCertificate(server_cert);=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**module,=20const=20char=20*library,=20= const=20char=20*name)=0A+{=0A+=09SECMODModule=20*mod;=0A+=09= PQExpBufferData=20modulespec;=0A+=0A+=09initPQExpBuffer(&modulespec);=0A= +=09appendPQExpBuffer(&modulespec,=20"library=3D\"%s\",=20name=3D\"%s\"",=20= library,=20name);=0A+=09if=20(PQExpBufferDataBroken(modulespec))=0A+=09{=0A= +=09=09PR_SetError(SEC_ERROR_NO_MEMORY,=200);=0A+=09=09return=20= SECFailure;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Attempt=20to=20load=20the=20= specified=20module.=20The=20second=20parameter=20is=20"parent"=0A+=09=20= *=20which=20should=20always=20be=20NULL=20for=20application=20code.=20= The=20third=20parameter=0A+=09=20*=20defines=20if=20loading=20should=20= recurse=20which=20is=20only=20applicable=20when=20loading=0A+=09=20*=20a=20= module=20from=20within=20another=20module.=20This=20hierarchy=20would=20= have=20to=20be=0A+=09=20*=20defined=20in=20the=20modulespec,=20and=20= since=20we=20don't=20support=20anything=20but=0A+=09=20*=20directly=20= addressed=20modules=20we=20should=20pass=20PR_FALSE.=0A+=09=20*/=0A+=09= mod=20=3D=20SECMOD_LoadUserModule(modulespec.data,=20NULL,=20PR_FALSE);=0A= +=09termPQExpBuffer(&modulespec);=0A+=0A+=09if=20(mod=20&&=20= mod->loaded)=0A+=09{=0A+=09=09*module=20=3D=20mod;=0A+=09=09return=20= SECSuccess;=0A+=09}=0A+=0A+=09SECMOD_DestroyModule(mod);=0A+=09return=20= SECFailure;=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/*=0A= +=09=20*=20VerifyCertificateNow=20verifies=20the=20validity=20using=20= PR_now=20from=20NSPR=20as=20a=0A+=09=20*=20timestamp=20and=20will=20= perform=20CRL=20and=20OSCP=20revocation=20checks.=20conn->sslcrl=0A+=09=20= *=20does=20not=20impact=20NSS=20connections=20as=20any=20CRL=20in=20the=20= NSS=20database=20will=20be=0A+=09=20*=20used=20automatically.=0A+=09=20= */=0A+=09status=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+=0A+=09CERT_DestroyCertificate(server_cert);=0A+=09= return=20status;=0A+}=0A+=0A+/*=0A+=20*=20pg_client_auth_handler=0A+=20*=09= =09Callback=20for=20client=20certificate=20validation=0A+=20*=0A+=20*=20= The=20client=20auth=20callback=20is=20not=20on=20by=20default=20in=20= NSS,=20so=20we=20need=20to=20invoke=0A+=20*=20it=20ourselves=20to=20= ensure=20we=20can=20do=20cert=20authentication.=0A+=20*/=0A+static=20= SECStatus=0A+pg_client_auth_handler(void=20*arg,=20PRFileDesc=20*socket,=20= CERTDistNames=20*caNames,=0A+=09=09=09=09=09=20=20=20CERTCertificate=20= **pRetCert,=20SECKEYPrivateKey=20**pRetKey)=0A+{=0A+=09PGconn=09=20=20=20= *conn=20=3D=20(PGconn=20*)=20arg;=0A+=09char=09=20=20=20*nnptr=20=3D=20= NULL;=0A+=09char=09=09nickname[MAXPGPATH];=0A+=0A+=09/*=0A+=09=20*=20If=20= we=20have=20an=20sslcert=20configured=20we=20use=20that=20combined=20= with=20the=20token-=0A+=09=20*=20name=20as=20the=20nickname.=20When=20no=20= sslcert=20is=20set=20we=20pass=20in=20NULL=20and=20let=0A+=09=20*=20NSS=20= try=20to=20find=20the=20certificate=20among=20the=20ones=20present=20in=20= the=20database.=0A+=09=20*=20Without=20an=20sslcert=20we=20cannot=20set=20= the=20database=20token=20since=20NSS=20parses=0A+=09=20*=20the=20given=20= string=20expecting=20to=20find=20a=20certificate=20nickname=20after=20= the=0A+=09=20*=20colon.=0A+=09=20*/=0A+=09if=20(conn->sslcert)=0A+=09{=0A= +=09=09snprintf(nickname,=20sizeof(nickname),=20"postgres:%s",=20= conn->sslcert);=0A+=09=09nnptr=20=3D=20nickname;=0A+=09}=0A+=0A+=09= return=20NSS_GetClientAuthData(nnptr,=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*fd)=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+=09err=20=3D=20PORT_GetError();=0A+=0A+=09/*=0A+=09=20*=20For=20= sslmodes=20other=20than=20verify-full=20and=20verify-ca=20we=20don't=20= perform=20peer=0A+=09=20*=20validation,=20so=20return=20immediately.=20=20= sslmode=20require=20with=20a=20database=0A+=09=20*=20specified=20which=20= contains=20a=20CA=20certificate=20will=20work=20like=20verify-ca=20to=0A= +=09=20*=20be=20compatible=20with=20the=20OpenSSL=20implementation.=0A+=09= =20*/=0A+=09if=20(strcmp(conn->sslmode,=20"require")=20=3D=3D=200)=0A+=09= {=0A+=09=09if=20(conn->ssldatabase=20&&=0A+=09=09=09= strlen(conn->ssldatabase)=20>=200=20&&=0A+=09=09=09= certificate_database_has_CA(conn))=0A+=09=09=09goto=20failure;=0A+=09}=0A= +=09else=20if=20(strcmp(conn->sslmode,=20"verify-full")=20=3D=3D=200=20= ||=0A+=09=09=09=20strcmp(conn->sslmode,=20"verify-ca")=20=3D=3D=200)=0A+=09= =09goto=20failure;=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=09break;=0A+=09=09= default:=0A+=09=09=09goto=20failure;=0A+=09=09=09break;=0A+=09}=0A+=0A+=09= return=20SECSuccess;=0A+=0A+failure:=0A+=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20verify=20certificate:=20%s"),=0A+=09=09=09=09= =09=20=20pg_SSLerrmessage(err));=0A+=0A+=09return=20SECFailure;=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.=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=09return=20= ssl_protocol_version_to_string(channel.protocolVersion);=0A+=0A+=09/*=0A= +=09=20*=20NSS=20disabled=20support=20for=20compression=20in=20version=20= 3.33,=20and=20it=20was=20only=0A+=09=20*=20available=20for=20SSLv3=20at=20= that=20point=20anyways,=20so=20we=20can=20safely=20return=20off=0A+=09=20= *=20here=20without=20even=20checking.=0A+=09=20*/=0A+=09if=20= (strcmp(attribute_name,=20"compression")=20=3D=3D=200)=0A+=09=09return=20= "off";=0A+=0A+=09return=20NULL;=0A+}=0A+=0A+/*=0A+=20*=20= ssl_protocol_param_to_nss=0A+=20*=0A+=20*=20Return=20the=20NSS=20= internal=20representation=20of=20the=20protocol=20asked=20for=20by=20the=0A= +=20*=20user=20as=20a=20connection=20parameter.=0A+=20*/=0A+static=20int=0A= +ssl_protocol_param_to_nss(const=20char=20*protocol)=0A+{=0A+=09if=20= (pg_strcasecmp("TLSv1",=20protocol)=20=3D=3D=200)=0A+=09=09return=20= SSL_LIBRARY_VERSION_TLS_1_0;=0A+=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_1=0A= +=09if=20(pg_strcasecmp("TLSv1.1",=20protocol)=20=3D=3D=200)=0A+=09=09= return=20SSL_LIBRARY_VERSION_TLS_1_1;=0A+#endif=0A+=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_2=0A+=09if=20(pg_strcasecmp("TLSv1.2",=20= protocol)=20=3D=3D=200)=0A+=09=09return=20SSL_LIBRARY_VERSION_TLS_1_2;=0A= +#endif=0A+=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_3=0A+=09if=20= (pg_strcasecmp("TLSv1.3",=20protocol)=20=3D=3D=200)=0A+=09=09return=20= SSL_LIBRARY_VERSION_TLS_1_3;=0A+#endif=0A+=0A+=09return=20-1;=0A+}=0A+=0A= +/*=0A+=20*=20certificate_database_has_CA=0A+=20*=09=09=20Check=20for=20= the=20presence=20of=20a=20CA=20certificate=0A+=20*=0A+=20*=20Returns=20= true=20in=20case=20there=20is=20a=20CA=20certificate=20in=20the=20= database=20connected=0A+=20*=20to=20in=20the=20conn=20object,=20else=20= false.=20This=20function=20only=20checks=20for=20the=0A+=20*=20presence=20= of=20a=20CA=20certificate,=20not=20its=20validity=20and/or=20usefulness.=0A= +=20*/=0A+static=20bool=0A+certificate_database_has_CA(PGconn=20*conn)=0A= +{=0A+=09CERTCertList=20*certificates;=0A+=09bool=09=09hasCA;=0A+=0A+=09= /*=0A+=09=20*=20If=20the=20certificate=20database=20has=20a=20password=20= we=20must=20provide=20it,=20since=0A+=09=20*=20this=20API=20doesn't=20= invoke=20the=20standard=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*=20PQssl_passwd_cb=0A= +=20*=09=09=20Supply=20a=20password=20to=20decrypt=20an=20object=0A+=20*=0A= +=20*=20If=20an=20object=20in=20the=20NSS=20database=20is=20password=20= protected,=20or=20if=20the=20entire=0A+=20*=20NSS=20database=20is=20= itself=20password=20protected,=20this=20callback=20will=20be=20invoked.=0A= +=20*=0A+=20*=20This=20must=20match=20NSS=20type=20PK11PasswordFunc.=0A+=20= */=0A+static=20char=20*=0A+PQssl_passwd_cb(PK11SlotInfo=20*slot,=20= PRBool=20retry,=20void=20*arg)=0A+{=0A+=09PGconn=09=20=20=20*conn=20=3D=20= (PGconn=20*)=20arg;=0A+=0A+=09conn->has_password=20=3D=20true;=0A+=0A+=09= if=20(PQsslKeyPassHook)=0A+=09=09return=20PQsslKeyPassHook(slot,=20= (PRBool)=20retry,=20arg);=0A+=09else=0A+=09=09return=20= PQdefaultSSLKeyPassHook_nss(slot,=20retry,=20arg);=0A+}=0A+=0A+/*=0A+=20= *=20PQdefaultSSLKeyPassHook_nss=0A+=20*=20=09=09=20Default=20password=20= handler=20callback=0A+=20*=0A+=20*=20If=20no=20user=20defined=20password=20= callback=20has=20been=20set=20up,=20the=20callback=20below=0A+=20*=20= will=20try=20the=20password=20set=20by=20the=20sslpassword=20parameter.=20= Since=20we=20by=20legacy=0A+=20*=20only=20have=20support=20for=20a=20= single=20password,=20there=20is=20little=20reason=20to=20inspect=0A+=20*=20= the=20slot=20for=20the=20object=20in=20question.=20A=20TODO=20is=20to=20= support=20different=0A+=20*=20passwords=20for=20different=20objects,=20= either=20via=20a=20DSL=20in=20sslpassword=20or=20with=20a=0A+=20*=20new=20= key/value=20style=20parameter.=20Users=20can=20supply=20their=20own=20= password=20hook=20to=0A+=20*=20do=20this=20of=20course,=20but=20it=20= would=20be=20nice=20to=20support=20something=20in=20core=20too.=0A+=20*/=0A= +char=20*=0A+PQdefaultSSLKeyPassHook_nss(PK11SlotInfo=20*slot,=20PRBool=20= retry,=20void=20*arg)=0A+{=0A+=09PGconn=09=20=20=20*conn=20=3D=20(PGconn=20= *)=20arg;=0A+=0A+=09/*=0A+=09=20*=20If=20the=20password=20didn't=20work=20= the=20first=20time=20there=20is=20no=20point=20in=0A+=09=20*=20retrying=20= as=20it=20hasn't=20changed.=0A+=09=20*/=0A+=09if=20(retry=20!=3D=20= PR_TRUE=20&&=20conn->sslpassword=20&&=20strlen(conn->sslpassword)=20>=20= 0)=0A+=09=09return=20PORT_Strdup(conn->sslpassword);=0A+=0A+=09return=20= NULL;=0A+}=0Adiff=20--git=20a/src/interfaces/libpq/fe-secure.c=20= b/src/interfaces/libpq/fe-secure.c=0Aindex=20b15d8d137c..d76eb4806f=20= 100644=0A---=20a/src/interfaces/libpq/fe-secure.c=0A+++=20= b/src/interfaces/libpq/fe-secure.c=0A@@=20-447,6=20+447,27=20@@=20= PQdefaultSSLKeyPassHook_OpenSSL(char=20*buf,=20int=20size,=20PGconn=20= *conn)=0A=20}=0A=20#endif=09=09=09=09=09=09=09/*=20USE_OPENSSL=20*/=0A=20= =0A+#ifndef=20USE_NSS=0A+=0A+PQsslKeyPassHook_nss_type=0A= +PQgetSSLKeyPassHook_nss(void)=0A+{=0A+=09return=20NULL;=0A+}=0A+=0A= +void=0A+PQsetSSLKeyPassHook_nss(PQsslKeyPassHook_nss_type=20hook)=0A+{=0A= +=09return;=0A+}=0A+=0A+char=20*=0A= +PQdefaultSSLKeyPassHook_nss(PK11SlotInfo=20*=20slot,=20PRBool=20retry,=20= void=20*arg)=0A+{=0A+=09return=20NULL;=0A+}=0A+#endif=09=09=09=09=09=09=09= /*=20USE_NSS=20*/=0A+=0A=20/*=20Dummy=20version=20of=20GSSAPI=20= information=20functions,=20when=20built=20without=20GSS=20support=20*/=0A= =20#ifndef=20ENABLE_GSS=0A=20=0Adiff=20--git=20= a/src/interfaces/libpq/libpq-fe.h=20b/src/interfaces/libpq/libpq-fe.h=0A= index=20a6fd69aceb..186e0a28f4=20100644=0A---=20= a/src/interfaces/libpq/libpq-fe.h=0A+++=20= b/src/interfaces/libpq/libpq-fe.h=0A@@=20-665,6=20+665,17=20@@=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=20490458adef..ab0da13700=20= 100644=0A---=20a/src/interfaces/libpq/libpq-int.h=0A+++=20= b/src/interfaces/libpq/libpq-int.h=0A@@=20-81,6=20+81,10=20@@=20typedef=20= struct=0A=20#endif=0A=20#endif=09=09=09=09=09=09=09/*=20USE_OPENSSL=20*/=0A= =20=0A+#ifdef=20USE_NSS=0A+#include=20"common/nss.h"=0A+#endif=0A+=0A=20= /*=0A=20=20*=20POSTGRES=20backend=20dependent=20Constants.=0A=20=20*/=0A= @@=20-385,6=20+389,7=20@@=20struct=20pg_conn=0A=20=09char=09=20=20=20= *sslcrl;=09=09=09/*=20certificate=20revocation=20list=20filename=20*/=0A=20= =09char=09=20=20=20*sslcrldir;=09=09/*=20certificate=20revocation=20list=20= directory=20name=20*/=0A=20=09char=09=20=20=20*sslsni;=09=09=09/*=20use=20= SSL=20SNI=20extension=20(0=20or=201)=20*/=0A+=09char=09=20=20=20= *ssldatabase;=09/*=20NSS=20certificate/key=20database=20*/=0A=20=09char=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-526,6=20= +531,28=20@@=20struct=20pg_conn=0A=20=09=09=09=09=09=09=09=09=20*=20= removed=20as=20this=20locking=20is=20handled=0A=20=09=09=09=09=09=09=09=09= =20*=20internally=20in=20OpenSSL=20>=3D=201.1.0.=20*/=0A=20#endif=09=09=09= =09=09=09=09/*=20USE_OPENSSL=20*/=0A+=0A+/*=0A+=20*=20The=20NSS/NSPR=20= specific=20types=20aren't=20used=20to=20avoid=20pulling=20in=20the=20= required=0A+=20*=20headers=20here,=20as=20they=20are=20causing=20= conflicts=20with=20PG=20definitions.=0A+=20*/=0A+#ifdef=20USE_NSS=0A+=09= NSSInitContext=09=20=20=20*nss_context;=09/*=20NSS=20connection=20= specific=20context=20*/=0A+=09PRFileDesc=09=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=20has=20a=20password=20= set=20or=20not.=20There=20is=20no=0A+=09=20*=20API=20function=20for=20= retrieving=20password=20status=20of=20a=20database,=20but=20we=20need=0A= +=09=20*=20to=20know=20since=20some=20NSS=20API=20calls=20require=20the=20= password=20passed=20in=20(they=0A+=09=20*=20don't=20call=20the=20= callback=20themselves).=20To=20track,=20we=20simply=20flip=20this=20to=0A= +=09=20*=20true=20in=20case=20NSS=20invoked=20the=20password=20callback=20= -=20as=20that=20will=20only=0A+=09=20*=20happen=20in=20case=20there=20is=20= a=20password.=20The=20reason=20for=20tracking=20this=20is=0A+=09=20*=20= that=20there=20are=20calls=20which=20require=20a=20password=20parameter,=20= but=20doesn't=0A+=09=20*=20use=20the=20callbacks=20provided,=20so=20we=20= must=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/*=20= USE_NSS=20*/=0A=20#endif=09=09=09=09=09=09=09/*=20USE_SSL=20*/=0A=20=0A=20= #ifdef=20ENABLE_GSS=0A@@=20-780,7=20+807,7=20@@=20extern=20ssize_t=20= pgtls_write(PGconn=20*conn,=20const=20void=20*ptr,=20size_t=20len);=0A=20= =20*=20This=20is=20not=20supported=20with=20old=20versions=20of=20= OpenSSL=20that=20don't=20have=0A=20=20*=20the=20X509_get_signature_nid()=20= function.=0A=20=20*/=0A-#if=20defined(USE_OPENSSL)=20&&=20= defined(HAVE_X509_GET_SIGNATURE_NID)=0A+#if=20defined(USE_NSS)=20||=20= (defined(USE_OPENSSL)=20&&=20defined(HAVE_X509_GET_SIGNATURE_NID))=0A=20= #define=20HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH=0A=20extern=20char=20= *pgtls_get_peer_certificate_hash(PGconn=20*conn,=20size_t=20*len);=0A=20= #endif=0A--=20=0A2.24.3=20(Apple=20Git-128)=0A=0A= --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F Content-Disposition: attachment; filename=v49-0002-Refactor-SSL-testharness-for-multiple-library.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v49-0002-Refactor-SSL-testharness-for-multiple-library.patch" Content-Transfer-Encoding: quoted-printable =46rom=20c2bc097628f204f6ca89b265ac75dcf00cdd4a9a=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:34=20+0100=0ASubject:=20[PATCH=20= v49=2002/10]=20Refactor=20SSL=20testharness=20for=20multiple=20library=0A= =0AThe=20SSL=20testharness=20was=20fully=20tied=20to=20OpenSSL=20in=20= the=20way=20the=20server=20was=0Aset=20up=20and=20reconfigured.=20This=20= refactors=20the=20SSLServer=20module=20into=20a=20SSL=0Alibrary=20= agnostic=20SSL/Server=20module=20which=20in=20turn=20use=20= SSL/Backend/=0Amodules=20for=20the=20implementation=20details.=0A=0A= No=20changes=20are=20done=20to=20the=20actual=20tests,=20this=20only=20= change=20how=20setup=20and=0Ateardown=20is=20performed.=0A---=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|=20=2056=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=20=206=20+-=0A=20= src/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>=20SSL/Server.pm}=20= =20=20=20=20|=20=2083=20+++++++++++---=0A=204=20files=20changed,=20181=20= insertions(+),=2067=20deletions(-)=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/t/001_ssltests.pl=20= b/src/test/ssl/t/001_ssltests.pl=0Aindex=202f30d11763..d965fbb658=20= 100644=0A---=20a/src/test/ssl/t/001_ssltests.pl=0A+++=20= b/src/test/ssl/t/001_ssltests.pl=0A@@=20-8,12=20+8,10=20@@=20use=20= PostgreSQL::Test::Cluster;=0A=20use=20PostgreSQL::Test::Utils;=0A=20use=20= Test::More;=0A=20=0A-use=20File::Copy;=0A-=0A=20use=20FindBin;=0A=20use=20= lib=20$FindBin::RealBin;=0A=20=0A-use=20SSLServer;=0A+use=20SSL::Server;=0A= =20=0A=20if=20($ENV{with_ssl}=20ne=20'openssl')=0A=20{=0A@@=20-36,32=20= +34,6=20@@=20my=20$SERVERHOSTCIDR=20=3D=20'127.0.0.1/32';=0A=20#=20= Allocation=20of=20base=20connection=20string=20shared=20among=20multiple=20= tests.=0A=20my=20$common_connstr;=0A=20=0A-#=20The=20client's=20private=20= key=20must=20not=20be=20world-readable,=20so=20take=20a=20copy=0A-#=20of=20= the=20key=20stored=20in=20the=20code=20tree=20and=20update=20its=20= permissions.=0A-#=0A-#=20This=20changes=20ssl/client.key=20to=20= ssl/client_tmp.key=20etc=20for=20the=20rest=0A-#=20of=20the=20tests.=0A= -my=20@keys=20=3D=20(=0A-=09"client",=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20"client-revoked",=0A-=09"client-der",=20=20=20=20=20=20=20=20=20= =20=20"client-encrypted-pem",=0A-=09"client-encrypted-der",=20= "client-dn");=0A-foreach=20my=20$key=20(@keys)=0A-{=0A-=09= copy("ssl/${key}.key",=20"ssl/${key}_tmp.key")=0A-=09=20=20or=20die=0A-=09= =20=20"couldn't=20copy=20ssl/${key}.key=20to=20ssl/${key}_tmp.key=20for=20= permissions=20change:=20$!";=0A-=09chmod=200600,=20"ssl/${key}_tmp.key"=0A= -=09=20=20or=20die=20"failed=20to=20change=20permissions=20on=20= ssl/${key}_tmp.key:=20$!";=0A-}=0A-=0A-#=20Also=20make=20a=20copy=20of=20= that=20explicitly=20world-readable.=20=20We=20can't=0A-#=20necessarily=20= rely=20on=20the=20file=20in=20the=20source=20tree=20having=20those=0A-#=20= permissions.=20=20Add=20it=20to=20@keys=20to=20include=20it=20in=20the=20= final=20clean=0A-#=20up=20phase.=0A-copy("ssl/client.key",=20= "ssl/client_wrongperms_tmp.key");=0A-chmod=200644,=20= "ssl/client_wrongperms_tmp.key";=0A-push=20@keys,=20'client_wrongperms';=0A= -=0A=20####=20Set=20up=20the=20server.=0A=20=0A=20note=20"setting=20up=20= data=20directory";=0A@@=20-76,32=20+48,22=20@@=20$node->start;=0A=20=0A=20= #=20Run=20this=20before=20we=20lock=20down=20access=20below.=0A=20my=20= $result=20=3D=20$node->safe_psql('postgres',=20"SHOW=20ssl_library");=0A= -is($result,=20'OpenSSL',=20'ssl_library=20parameter');=0A+is($result,=20= SSL::Server::ssl_library(),=20'ssl_library=20parameter');=0A=20=0A=20= configure_test_server_for_ssl($node,=20$SERVERHOSTADDR,=20= $SERVERHOSTCIDR,=0A=20=09'trust');=0A=20=0A=20note=20"testing=20= password-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-=0A+set_server_cert($node,=20'server-cn-only',=20= 'root+client_ca',=0A+=09=09=09=09=20=20=20'server-password',=20'echo=20= wrongpassword');=0A=20command_fails(=0A=20=09[=20'pg_ctl',=20'-D',=20= $node->data_dir,=20'-l',=20$node->logfile,=20'restart'=20],=0A=20=09= 'restart=20fails=20with=20password-protected=20key=20file=20with=20wrong=20= password');=0A=20$node->_update_pid(0);=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-=0A= +set_server_cert($node,=20'server-cn-only',=20'root+client_ca',=0A+=09=09= =09=09'server-password',=20'echo=20secret1');=0A=20command_ok(=0A=20=09[=20= 'pg_ctl',=20'-D',=20$node->data_dir,=20'-l',=20$node->logfile,=20= 'restart'=20],=0A=20=09'restart=20succeeds=20with=20password-protected=20= key=20file');=0A@@=20-613,7=20+575,5=20@@=20$node->connect_fails(=0A=20=09= expected_stderr=20=3D>=20qr/SSL=20error:=20sslv3=20alert=20certificate=20= revoked/);=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=20983554263f..59f520cb5b=20100644=0A= ---=20a/src/test/ssl/t/002_scram.pl=0A+++=20= b/src/test/ssl/t/002_scram.pl=0A@@=20-14,11=20+14,11=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=20if=20= ($ENV{with_ssl}=20ne=20'openssl')=0A=20{=0A-=09plan=20skip_all=20=3D>=20= 'OpenSSL=20not=20supported=20by=20this=20build';=0A+=09plan=20skip_all=20= =3D>=20'SSL=20not=20supported=20by=20this=20build';=0A=20}=0A=20=0A=20#=20= This=20is=20the=20hostname=20used=20to=20connect=20to=20the=20server.=0A= @@=20-115,5=20+115,3=20@@=20$node->connect_ok(=0A=20=0A=20#=20clean=20up=0A= =20unlink($client_tmp_key);=0A-=0A-done_testing($number_of_tests);=0A= diff=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..e77ee25cc7=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=20=20=20=20=20=20=20=20= =20=20"client-revoked",=0A+=09=09"client-der",=20=20=20=20=20=20=20=20=20= =20=20"client-encrypted-pem",=0A+=09=09"client-encrypted-der",=20= "client-dn");=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+=09= bless=20$self,=20$class;=0A+=0A+=09return=20$self;=0A+}=0A+=0A+sub=20= get_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+=09my=20@keys=20=3D=20(=0A+=09=09"client",=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20"client-revoked",=0A+=09=09= "client-der",=20=20=20=20=20=20=20=20=20=20=20"client-encrypted-pem",=0A= +=09=09"client-encrypted-der",=20"client-dn");=0A+=09foreach=20my=20$key=20= (@keys)=0A+=09{=0A+=09=09copy("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=20= to=20ssl/${key}_tmp.key=20for=20permissions=20change:=20$!";=0A+=09=09= chmod=200600,=20"ssl/${key}_tmp.key"=0A+=09=09=20=20or=20die=20"failed=20= to=20change=20permissions=20on=20ssl/${key}_tmp.key:=20$!";=0A+=09}=0A+=0A= +=09#=20Also=20make=20a=20copy=20of=20that=20explicitly=20= world-readable.=20=20We=20can't=0A+=09#=20necessarily=20rely=20on=20the=20= file=20in=20the=20source=20tree=20having=20those=0A+=09#=20permissions.=20= =20Add=20it=20to=20@keys=20to=20include=20it=20in=20the=20final=20clean=0A= +=09#=20up=20phase.=0A+=09copy("ssl/client.key",=20= "ssl/client_wrongperms_tmp.key");=0A+=09chmod=200644,=20= "ssl/client_wrongperms_tmp.key";=0A+=09push=20@keys,=20= 'client_wrongperms';=0A+}=0A+=0A+#=20Change=20the=20configuration=20to=20= use=20given=20server=20cert=20file,=20and=20reload=0A+#=20the=20server=20= so=20that=20the=20configuration=20takes=20effect.=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]=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=20c5999e0b33..83df239e20=20100644=0A= ---=20a/src/test/ssl/t/SSLServer.pm=0A+++=20= b/src/test/ssl/t/SSL/Server.pm=0A@@=20-26,19=20+26,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=20PostgreSQL::Test::Cluster;=0A=20use=20= PostgreSQL::Test::Utils;=0A+use=20PostgreSQL::Test::RecursiveCopy;=0A=20= use=20File::Basename;=0A=20use=20File::Copy;=0A=20use=20Test::More;=0A= +use=20SSL::Backend::OpenSSL=20qw(get_new_openssl_backend);=0A+use=20= SSL::Backend::NSS=20qw(get_new_nss_backend);=0A+=0A+our=20($openssl,=20= $nss,=20$backend);=0A+=0A+#=20The=20TLS=20backend=20which=20the=20server=20= is=20using=20should=20be=20mostly=20transparent=20for=0A+#=20the=20user,=20= apart=20from=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);=0A=20=0A@@=20-112,14=20+132,21=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-=09= mkdir("$pgdata/root+client-crldir");=0A-=09= copy_files("ssl/root+client-crldir/*",=20"$pgdata/root+client-crldir/");=0A= +=09if=20(defined($openssl))=0A+=09{=0A+=09=09= copy_files("ssl/server-*.crt",=20$pgdata);=0A+=09=09= copy_files("ssl/server-*.key",=20$pgdata);=0A+=09=09chmod(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=09= mkdir("$pgdata/root+client-crldir");=0A+=09=09= copy_files("ssl/root+client-crldir/*",=20"$pgdata/root+client-crldir/");=0A= +=09}=0A+=09elsif=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-127,20=20= +154,36=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$crlfile=20=20=3D=20= "root+client.crl";=0A=20=09my=20$crldir;=0A=20=09my=20$pgdata=20=3D=20= $node->data_dir;=0A=20=0A+=09$keyfile=20=3D=20$certfile=20if=20$keyfile=20= eq=20'';=0A+=0A=20=09#=20defaults=20to=20use=20crl=20file=0A=20=09if=20= (defined=20$_[3]=20||=20defined=20$_[4])=0A=20=09{=0A@@=20-150,13=20= +193,23=20@@=20sub=20switch_server_cert=0A=20=0A=20=09open=20my=20= $sslconf,=20'>',=20"$pgdata/sslconfig.conf";=0A=20=09print=20$sslconf=20= "ssl=3Don\n";=0A-=09print=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= $backend->set_server_cert($certfile,=20$cafile,=20$keyfile);=0A=20=09= print=20$sslconf=20"ssl_crl_file=3D'$crlfile'\n"=20if=20defined=20= $crlfile;=0A=20=09print=20$sslconf=20"ssl_crl_dir=3D'$crldir'\n"=20=20=20= if=20defined=20$crldir;=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=20= the=20configuration=20to=20use=20given=20server=20cert=20file,=20and=20= reload=0A+#=20the=20server=20so=20that=20the=20configuration=20takes=20= effect.=0A+#=20Takes=20the=20same=20arguments=20as=20set_server_cert,=20= which=20it=20calls=20to=20do=20that=0A+#=20piece=20of=20the=20work.=0A= +sub=20switch_server_cert=0A+{=0A+=09my=20$node=20=3D=20$_[0];=0A+=09= set_server_cert(@_);=0A=20=09$node->restart;=0A=20=09return;=0A=20}=0A--=20= =0A2.24.3=20(Apple=20Git-128)=0A=0A= --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F Content-Disposition: attachment; filename=v49-0003-nss-Add-NSS-specific-tests.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v49-0003-nss-Add-NSS-specific-tests.patch" Content-Transfer-Encoding: quoted-printable =46rom=205ee978e770ec1154be5a996047004a121aedb948=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:37=20+0100=0ASubject:=20[PATCH=20= v49=2003/10]=20nss:=20Add=20NSS=20specific=20tests=0A=0AThis=20adds=20= the=20SSL/Backend/NSS=20which=20implements=20the=20setup=20and=20= teardown=0Arequired=20as=20well=20as=20adds=20the=20NSS=20configuration=20= to=20the=20existing=20tests.=0A=0AThe=20OpenSSL=20testfiles=20are=20= reused=20by=20repackaging=20them=20into=20NSS=20databases=0Ain=20order=20= for=20the=20tests=20to=20be=20cross-library.=20Additional=20testfiles=20= are=0Agenerated=20by=20using=20only=20the=20NSS=20toolchain=20as=20well=20= as=20rudimentary=20tests=0Ausing=20these.=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=2011=20+-=0A=20src/test/ssl/sslfiles.mk=20=20=20=20=20=20=20=20=20=20= =20=20=20=20|=20=20=204=20+-=0A=20src/test/ssl/sslfiles_nss.mk=20=20=20=20= =20=20=20=20=20=20|=20268=20++++++++++++++++=0A=20= src/test/ssl/t/001_ssltests.pl=20=20=20=20=20=20=20=20|=20432=20= +++++++++++++++++---------=0A=20src/test/ssl/t/002_scram.pl=20=20=20=20=20= =20=20=20=20=20=20|=20=2033=20+-=0A=20src/test/ssl/t/SSL/Backend/NSS.pm=20= =20=20=20=20|=20=2061=20++++=0A=20src/test/ssl/t/SSL/Backend/OpenSSL.pm=20= |=20=2019=20+-=0A=20src/test/ssl/t/SSL/Server.pm=20=20=20=20=20=20=20=20=20= =20|=20=2048=20+--=0A=208=20files=20changed,=20664=20insertions(+),=20= 212=20deletions(-)=0A=20create=20mode=20100644=20= src/test/ssl/sslfiles_nss.mk=0A=20create=20mode=20100644=20= src/test/ssl/t/SSL/Backend/NSS.pm=0A=0Adiff=20--git=20= a/src/test/ssl/Makefile=20b/src/test/ssl/Makefile=0Aindex=20= cb24e31c6e..d3d007d1fb=20100644=0A---=20a/src/test/ssl/Makefile=0A+++=20= b/src/test/ssl/Makefile=0A@@=20-16,14=20+16,21=20@@=20include=20= $(top_builddir)/src/Makefile.global=0A=20export=20with_ssl=0A=20=0A=20#=20= The=20sslfiles=20targets=20are=20separated=20into=20their=20own=20file=20= due=20to=20interactions=0A-#=20with=20settings=20in=20Makefile.global.=0A= +#=20with=20settings=20in=20Makefile.global.=20There=20is=20no=20library=20= guard=20on=20with_ssl=20for=0A+#=20the=20targets,=20as=20nssfiles=20rely=20= on=20the=20openssl=20generated=20files=20and=20also=20the=0A+#=20openssl=20= toolchain=20to=20some=20degree.=0A=20.PHONY:=20sslfiles=20sslfiles-clean=0A= =20sslfiles=20sslfiles-clean:=0A-=09$(MAKE)=20-f=20$(srcdir)/sslfiles.mk=20= $@=0A+=09MKDIR_P=3D"$(MKDIR_P)"=20$(MAKE)=20-f=20$(srcdir)/sslfiles.mk=20= $@=0A+=0A+.PHONY:=20nssfiles=20nssfiles-clean=0A+nssfiles=20= nssfiles-clean:=0A+=09MKDIR_P=3D"$(MKDIR_P)"=20$(MAKE)=20-f=20= $(srcdir)/sslfiles_nss.mk=20$@=0A=20=0A=20clean=20distclean=20= maintainer-clean:=0A=20=09rm=20-rf=20tmp_check=0A=20=09$(MAKE)=20-f=20= $(srcdir)/sslfiles.mk=20$@=0A+=09$(MAKE)=20-f=20= $(srcdir)/sslfiles_nss.mk=20$@=0A=20=0A=20#=20Doesn't=20depend=20on=20= sslfiles=20because=20we=20don't=20rebuild=20them=20by=20default=0A=20= check:=0Adiff=20--git=20a/src/test/ssl/sslfiles.mk=20= b/src/test/ssl/sslfiles.mk=0Aindex=2081c20aac9e..e505f8552d=20100644=0A= ---=20a/src/test/ssl/sslfiles.mk=0A+++=20b/src/test/ssl/sslfiles.mk=0A@@=20= -185,7=20+185,7=20@@=20ssl/%.csr:=20ssl/%.key=20conf/%.config=0A=20#=20= OpenSSL=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-=09mkdir=20$@=0A= +=09$(MKDIR_P)=20$@=0A=20=0A=20ssl/%-certindex:=0A=20=09touch=20$@=0A@@=20= -225,7=20+225,7=20@@=20ssl/client-crldir:=20ssl/client.crl=0A=20= crlhashfile=20=3D=20$(shell=20openssl=20crl=20-hash=20-noout=20-in=20= $(1)).r0=0A=20=0A=20ssl/%-crldir:=0A-=09mkdir=20-p=20$@=0A+=09$(MKDIR_P)=20= $@=0A=20=09rm=20-f=20$@/*.r0=0A=20=09$(foreach=20crl,$^,cp=20$(crl)=20= $@/$(call=20crlhashfile,$(crl))=20&&)=20true=0A=20=09touch=20$@=0Adiff=20= --git=20a/src/test/ssl/sslfiles_nss.mk=20b/src/test/ssl/sslfiles_nss.mk=0A= new=20file=20mode=20100644=0Aindex=200000000000..adb7363d63=0A---=20= /dev/null=0A+++=20b/src/test/ssl/sslfiles_nss.mk=0A@@=20-0,0=20+1,268=20= @@=0A= +#------------------------------------------------------------------------= -=0A+#=0A+#=20Makefile=20for=20sslfiles=20using=20NSS=0A+#=0A+#=20=20=20= The=20SSL=20test=20files=20are=20completely=20disjoint=20from=20the=20= rest=20of=20the=20build;=20they=0A+#=20=20=20don't=20rely=20on=20other=20= targets=20or=20on=20Makefile.global.=20=20The=20targets=20in=20this=0A+#=20= =20=20file=20rely=20on=20the=20certificates=20and=20keys=20generated=20= by=20the=20OpenSSL=20backend=0A+#=20=20=20support.=0A+#=0A+#=20Portions=20= Copyright=20(c)=201996-2021,=20PostgreSQL=20Global=20Development=20Group=0A= +#=20Portions=20Copyright=20(c)=201994,=20Regents=20of=20the=20= University=20of=20California=0A+#=0A+#=20src/test/ssl/sslfiles_nss.mk=0A= +#=0A= +#------------------------------------------------------------------------= -=0A+=0A+#=20Even=20though=20we=20in=20practice=20could=20get=20away=20= with=20far=20fewer=20NSS=20databases,=20they=0A+#=20are=20generated=20to=20= mimic=20the=20setup=20for=20the=20OpenSSL=20tests=20in=20order=20to=20= ensure=0A+#=20we=20isolate=20the=20same=20behavior=20between=20the=20= backends.=20The=20database=20name=20should=0A+#=20contain=20the=20files=20= included=20for=20easier=20test=20suite=20code=20reading.=0A+NSSFILES=20= :=3D=20ssl/nss/client_ca.crt.db=20\=0A+=09ssl/nss/server_ca.crt.db=20\=0A= +=09ssl/nss/root+server_ca.crt.db=20\=0A+=09= ssl/nss/root+client_ca.crt.db=20\=0A+=09= ssl/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/server-cn-only.crt__server-cn-only.key.crldir.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/root+server_ca.crt__root+server.crldir.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+nssfiles:=20$(NSSFILES)=0A+=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= +ssl/nss/root+server_ca.crt__root+server.crldir.db:=20= ssl/root+server_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/root+server_ca.crt=20-i=20ssl/root+server_ca.crt=20-t=20= "CT,C,C"=0A+=09crlutil=20-I=20-i=20ssl/nss/root.crl=20-d=20$@=20-B=0A+=09= for=20c=20in=20$(shell=20ls=20ssl/root+server-crldir)=20;=20do=20\=0A+=09= =09echo=20$${c}=20;=20\=0A+=09=09openssl=20crl=20-in=20= ssl/root+server-crldir/$${c}=20-outform=20der=20-out=20ssl/nss/$${c}=20;=20= \=0A+=09=09crlutil=20-I=20-i=20ssl/nss/$${c}=20-d=20$@=20-B=20;=20\=0A+=09= done=0A+=0A+#=20pk12util=20won't=20preserve=20the=20password=20when=20= importing=20the=20password=20protected=0A+#=20key,=20the=20password=20= must=20be=20set=20on=20the=20database=20*before*=20importing=20it=20as=20= the=0A+#=20password=20in=20the=20pkcs12=20envelope=20will=20be=20= dropped.=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= certutil=20-d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20ssl/root_ca.crt=20= -t=20"CT,C,C"=0A+=09openssl=20pkcs12=20-export=20-out=20= ssl/nss/server-cn-only.pfx=20-inkey=20ssl/server-cn-only.key=20-in=20= ssl/server-cn-only.crt=20-certfile=20ssl/server_ca.crt=20-passout=20= pass:=0A+=09pk12util=20-i=20ssl/nss/server-cn-only.pfx=20-d=20"sql:$@"=20= -W=20''=0A+=0A+ssl/nss/server-cn-only.crt__server-cn-only.key.crldir.db:=20= ssl/nss/server-cn-only.crt__server-cn-only.key.db=0A+=09cp=20-R=20$<=20= $@=0A+=09for=20c=20in=20$(shell=20ls=20ssl/root+client-crldir)=20;=20do=20= \=0A+=09=09echo=20$${c}=20;=20\=0A+=09=09openssl=20crl=20-in=20= ssl/root+client-crldir/$${c}=20-outform=20der=20-out=20ssl/nss/$${c}=20;=20= \=0A+=09=09crlutil=20-I=20-i=20ssl/nss/$${c}=20-d=20$@=20-B=20;=20\=0A+=09= done=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+=0A+#=20Client=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+server_ca.crt=20-i=20ssl/root+server_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= +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+#=20Client=20certificate,=20signed=20by=20client=20CA=0A= +ssl/nss/client+client_ca.crt__client.key.db:=20ssl/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=20= ssl/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=20ssl/root+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.pfx=20-inkey=20ssl/client.key=20-in=20= ssl/client.crt=20-certfile=20ssl/client_ca.crt=20-passout=20pass:=0A+=09= pk12util=20-i=20ssl/nss/client.pfx=20-d=20"sql:$@"=20-W=20''=0A+=0A= +ssl/nss/client.crl:=20ssl/client.crl=0A+=09openssl=20crl=20-in=20$^=20= -outform=20der=20-out=20$@=0A+=0A+ssl/nss/server.crl:=20ssl/server.crl=0A= +=09openssl=20crl=20-in=20$^=20-outform=20der=20-out=20$@=0A+=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+####=20NSS=20specific=20certificates=20and=20keys=0A+=0A= +ssl/nss/native_ca-%.db:=0A+=09$(MKDIR_P)=20ssl/nss/native_ca-$*.db=0A+=09= certutil=20-N=20-d=20"sql:ssl/nss/native_ca-$*.db/"=20--empty-password=0A= +=09echo=20y=20>=20nss_ca_params.txt=0A+=09echo=2010=20>>=20= nss_ca_params.txt=0A+=09echo=20y=20>>=20nss_ca_params.txt=0A+=09cat=20= nss_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=20= CA=20for=20PostgreSQL=20SSL=20regression=20tests,OU=3DPostgreSQL=20test=20= suite"=20\=0A+=09-x=20-k=20rsa=20-g=202048=20-m=205432=20-t=20= CTu,CTu,CTu=20\=0A+=09--keyUsage=20certSigning=20-2=20--nsCertType=20= sslCA,smimeCA,objectSigningCA=20\=0A+=09-z=20Makefile=20-Z=20SHA256=0A+=09= rm=20nss_ca_params.txt=0A+=0A+ssl/nss/native_ca-%.pem:=20= ssl/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+.PHONY:=20= nssfiles-clean=0A+nssfiles-clean:=0A+=09rm=20-rf=20ssl/nss=0A+=0A+#=20= The=20difference=20between=20the=20below=20clean=20targets=20and=20= nssfiles-clean=20is=20that=20the=0A+#=20clean=20targets=20will=20be=20= run=20during=20a=20"standard"=20recursive=20clean=20run=20from=20the=0A= +#=20main=20build=20tree.=20The=20nssfiles-clean=20target=20must=20be=20= run=20explicitly=20from=20this=0A+#=20directory.=0A+.PHONY:=20clean=20= distclean=20maintainer-clean=0A+clean=20distclean=20maintainer-clean:=0A= +=09rm=20-rf=20ssl/nss=0A+=0Adiff=20--git=20= a/src/test/ssl/t/001_ssltests.pl=20b/src/test/ssl/t/001_ssltests.pl=0A= index=20d965fbb658..2fec9143c5=20100644=0A---=20= a/src/test/ssl/t/001_ssltests.pl=0A+++=20= b/src/test/ssl/t/001_ssltests.pl=0A@@=20-13,13=20+13,22=20@@=20use=20lib=20= $FindBin::RealBin;=0A=20=0A=20use=20SSL::Server;=0A=20=0A-if=20= ($ENV{with_ssl}=20ne=20'openssl')=0A+my=20$openssl;=0A+my=20$nss;=0A+=0A= +if=20($ENV{with_ssl}=20eq=20'openssl')=0A+{=0A+=09$openssl=20=3D=201;=0A= +=09plan=20tests=20=3D>=20112;=0A+}=0A+elsif=20($ENV{with_ssl}=20eq=20= 'nss')=0A=20{=0A-=09plan=20skip_all=20=3D>=20'OpenSSL=20not=20supported=20= by=20this=20build';=0A+=09$nss=20=3D=201;=0A+=09plan=20tests=20=3D>=20= 112;=0A=20}=0A=20else=0A=20{=0A-=09plan=20tests=20=3D>=20110;=0A+=09plan=20= skip_all=20=3D>=20'SSL=20not=20supported=20by=20this=20build';=0A=20}=0A=20= =0A=20####=20Some=20configuration=0A@@=20-55,19=20+64,68=20@@=20= configure_test_server_for_ssl($node,=20$SERVERHOSTADDR,=20= $SERVERHOSTCIDR,=0A=20=0A=20note=20"testing=20password-protected=20= keys";=0A=20=0A-set_server_cert($node,=20'server-cn-only',=20= 'root+client_ca',=0A-=09=09=09=09=20=20=20'server-password',=20'echo=20= wrongpassword');=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=20password-protected=20key=20file=20with=20wrong=20= password');=0A-$node->_update_pid(0);=0A+#=20Since=20the=20passphrase=20= callbacks=20operate=20at=20different=20stages=20in=20OpenSSL=20and=0A+#=20= NSS=20we=20have=20two=20separate=20blocks=20for=20them=0A+SKIP:=0A+{=0A+=09= skip=20"Certificate=20passphrases=20aren't=20checked=20on=20server=20= restart=20in=20NSS",=202=0A+=09=20=20if=20($nss);=0A+=0A+=09= switch_server_cert($node,=0A+=09=09certfile=20=3D>=20'server-cn-only',=0A= +=09=09cafile=20=3D>=20'root+client_ca',=0A+=09=09keyfile=20=3D>=20= 'server-password',=0A+=09=09nssdatabase=20=3D>=20= 'server-cn-only.crt__server-password.key.db',=0A+=09=09passphrase_cmd=20= =3D>=20'echo=20wrongpassword',=0A+=09=09restart=20=3D>=20'no'=20);=0A+=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=20= with=20password-protected=20key=20file=20with=20wrong=20password');=0A+=09= $node->_update_pid(0);=0A+=0A+=09switch_server_cert($node,=0A+=09=09= certfile=20=3D>=20'server-cn-only',=0A+=09=09cafile=20=3D>=20= 'root+client_ca',=0A+=09=09keyfile=20=3D>=20'server-password',=0A+=09=09= nssdatabase=20=3D>=20'server-cn-only.crt__server-password.key.db',=0A+=09= =09passphrase_cmd=20=3D>=20'echo=20secret1',=0A+=09=09restart=20=3D>=20= 'no');=0A+=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=20password-protected=20key=20file');=0A+=09= $node->_update_pid(1);=0A+}=0A=20=0A-set_server_cert($node,=20= 'server-cn-only',=20'root+client_ca',=0A-=09=09=09=09'server-password',=20= 'echo=20secret1');=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+SKIP:=0A+{=0A+=09skip=20"Certificate=20= passphrases=20are=20checked=20on=20connection=20in=20NSS",=203=0A+=09=20=20= if=20($openssl);=0A+=0A+=09switch_server_cert($node,=0A+=09=09certfile=20= =3D>=20'server-cn-only',=0A+=09=09cafile=20=3D>=20'root+client_ca',=0A+=09= =09keyfile=20=3D>=20'server-password',=0A+=09=09nssdatabase=20=3D>=20= 'server-cn-only.crt__server-password.key.db',=0A+=09=09passphrase_cmd=20= =3D>=20'echo=20wrongpassword');=0A+=0A+=09$node->connect_fails(=0A+=09=09= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= hostaddr=3D$SERVERHOSTADDR=20host=3Dcommon-name.pg-ssltest.test=20= sslrootcert=3Dinvalid=20sslmode=3Drequire",=0A+=09=09"connect=20to=20= server=20with=20incorrect=20key=20password=20configured",=0A+=09=09= expected_stderr=20=3D>=20qr/\QSSL=20error\E/);=0A+=0A+=09= switch_server_cert($node,=0A+=09=09certfile=20=3D>=20'server-cn-only',=0A= +=09=09cafile=20=3D>=20'root+client_ca',=0A+=09=09keyfile=20=3D>=20= 'server-password',=0A+=09=09nssdatabase=20=3D>=20= 'server-cn-only.crt__server-password.key.db',=0A+=09=09passphrase_cmd=20= =3D>=20'echo=20secret1');=0A+=0A+=09$node->connect_ok(=0A+=09=09= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= hostaddr=3D$SERVERHOSTADDR=20host=3Dcommon-name.pg-ssltest.test=20= sslrootcert=3Dinvalid=20sslmode=3Drequire",=0A+=09=09"connect=20to=20= server=20with=20correct=20key=20password=20configured");=0A+}=0A=20=0A=20= #=20Test=20compatibility=20of=20SSL=20protocols.=0A=20#=20TLSv1.1=20is=20= lower=20than=20TLSv1.2,=20so=20it=20won't=20work.=0A@@=20-95,7=20+153,7=20= @@=20command_ok(=0A=20=0A=20note=20"running=20client=20tests";=0A=20=0A= -switch_server_cert($node,=20'server-cn-only');=0A= +switch_server_cert($node,=20certfile=20=3D>=20'server-cn-only',=20= nssdatabase=20=3D>=20'server-cn-only.crt__server-cn-only.key.db');=0A=20=0A= =20$common_connstr=20=3D=0A=20=20=20"user=3Dssltestuser=20dbname=3Dtrustdb= =20sslcert=3Dinvalid=20hostaddr=3D$SERVERHOSTADDR=20= host=3Dcommon-name.pg-ssltest.test";=0A@@=20-114,87=20+172,104=20@@=20= $node->connect_ok(=0A=20$node->connect_fails(=0A=20=09"$common_connstr=20= sslrootcert=3Dinvalid=20sslmode=3Dverify-ca",=0A=20=09"connect=20without=20= server=20root=20cert=20sslmode=3Dverify-ca",=0A-=09expected_stderr=20=3D>=20= qr/root=20certificate=20file=20"invalid"=20does=20not=20exist/);=0A+=09= expected_stderr=20=3D>=20qr/root=20certificate=20file=20"invalid"=20does=20= not=20exist|Peer's=20certificate=20issuer=20has=20been=20marked=20as=20= not=20trusted=20by=20the=20user/);=0A=20$node->connect_fails(=0A=20=09= "$common_connstr=20sslrootcert=3Dinvalid=20sslmode=3Dverify-full",=0A=20=09= "connect=20without=20server=20root=20cert=20sslmode=3Dverify-full",=0A-=09= expected_stderr=20=3D>=20qr/root=20certificate=20file=20"invalid"=20does=20= not=20exist/);=0A+=09expcted_stderr=20=3D>=20qr/root=20certificate=20= file=20"invalid"=20does=20not=20exist|Peer's=20certificate=20issuer=20= has=20been=20marked=20as=20not=20trusted=20by=20the=20user/);=0A=20=0A=20= #=20Try=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=20$node->connect_fails(=0A-=09= "$common_connstr=20sslrootcert=3Dssl/client_ca.crt=20sslmode=3Drequire",=0A= +=09"$common_connstr=20sslrootcert=3Dssl/client_ca.crt=20sslmode=3Drequire= =20ssldatabase=3Dssl/nss/client_ca.crt.db",=0A=20=09"connect=20with=20= wrong=20server=20root=20cert=20sslmode=3Drequire",=0A-=09expected_stderr=20= =3D>=20qr/SSL=20error:=20certificate=20verify=20failed/);=0A+=09= expected_stderr=20=3D>=20qr/SSL=20error:=20certificate=20verify=20= failed|Peer's=20certificate=20issuer=20has=20been=20marked=20as=20not=20= trusted=20by=20the=20user/);=0A=20$node->connect_fails(=0A-=09= "$common_connstr=20sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-ca",= =0A+=09"$common_connstr=20sslrootcert=3Dssl/client_ca.crt=20= sslmode=3Dverify-ca=20ssldatabase=3Dssl/nss/client_ca.crt.db",=0A=20=09= "connect=20with=20wrong=20server=20root=20cert=20sslmode=3Dverify-ca",=0A= -=09expected_stderr=20=3D>=20qr/SSL=20error:=20certificate=20verify=20= failed/);=0A+=09expected_stderr=20=3D>=20qr/SSL=20error:=20certificate=20= verify=20failed|Peer's=20certificate=20issuer=20has=20been=20marked=20as=20= not=20trusted=20by=20the=20user/);=0A=20$node->connect_fails(=0A-=09= "$common_connstr=20sslrootcert=3Dssl/client_ca.crt=20= sslmode=3Dverify-full",=0A+=09"$common_connstr=20= sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-full=20= ssldatabase=3Dssl/nss/client_ca.crt.db",=0A=20=09"connect=20with=20wrong=20= server=20root=20cert=20sslmode=3Dverify-full",=0A-=09expected_stderr=20= =3D>=20qr/SSL=20error:=20certificate=20verify=20failed/);=0A+=09= expected_stderr=20=3D>=20qr/SSL=20error:=20certificate=20verify=20= failed|Peer's=20certificate=20issuer=20has=20been=20marked=20as=20not=20= trusted=20by=20the=20user/);=0A=20=0A-#=20Try=20with=20just=20the=20= server=20CA's=20cert.=20This=20fails=20because=20the=20root=20file=0A-#=20= must=20contain=20the=20whole=20chain=20up=20to=20the=20root=20CA.=0A= -$node->connect_fails(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/server_ca.crt=20sslmode=3Dverify-ca",=0A-=09"connect=20= with=20server=20CA=20cert,=20without=20root=20CA",=0A-=09expected_stderr=20= =3D>=20qr/SSL=20error:=20certificate=20verify=20failed/);=0A+SKIP:=0A+{=0A= +=09#=20NSS=20supports=20partial=20chain=20validation,=20so=20this=20= test=20doesn't=20work=20there.=0A+=09#=20This=20is=20similar=20to=20the=20= OpenSSL=20option=20X509_V_FLAG_PARTIAL_CHAIN=20which=0A+=09#=20we=20= don'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= +=09$node->connect_fails(=0A+=09=09"$common_connstr=20= sslrootcert=3Dssl/server_ca.crt=20sslmode=3Dverify-ca",=0A+=09=09= "connect=20with=20server=20CA=20cert,=20without=20root=20CA",=0A+=09=09= expected_stderr=20=3D>=20qr/SSL=20error:=20certificate=20verify=20= failed/);=0A+}=0A=20=0A=20#=20And=20finally,=20with=20the=20correct=20= root=20cert.=0A=20$node->connect_ok(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire",=0A+=09= "$common_connstr=20sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Drequire=20ssldatabase=3Dssl/nss/root+server_ca.crt.db",=0A=20=09= "connect=20with=20correct=20server=20CA=20cert=20file=20= sslmode=3Drequire");=0A=20$node->connect_ok(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca",=0A+=09= "$common_connstr=20sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20ssldatabase=3Dssl/nss/root+server_ca.crt.db",=0A=20= =09"connect=20with=20correct=20server=20CA=20cert=20file=20= sslmode=3Dverify-ca");=0A=20$node->connect_ok(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-full",=0A+=09= "$common_connstr=20sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-full=20ssldatabase=3Dssl/nss/root+server_ca.crt.db",=0A=20= =09"connect=20with=20correct=20server=20CA=20cert=20file=20= sslmode=3Dverify-full");=0A=20=0A-#=20Test=20with=20cert=20root=20file=20= that=20contains=20two=20certificates.=20The=20client=20should=0A-#=20be=20= able=20to=20pick=20the=20right=20one,=20regardless=20of=20the=20order=20= in=20the=20file.=0A-$node->connect_ok(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/both-cas-1.crt=20sslmode=3Dverify-ca",=0A-=09"cert=20= root=20file=20that=20contains=20two=20certificates,=20order=201");=0A= -$node->connect_ok(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/both-cas-2.crt=20sslmode=3Dverify-ca",=0A-=09"cert=20= root=20file=20that=20contains=20two=20certificates,=20order=202");=0A-=0A= +SKIP:=0A+{=0A+=09skip=20"CA=20ordering=20is=20irrelevant=20in=20NSS=20= databases",=202=20if=20($nss);=0A+=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+=09$node->connect_ok(=0A+=09=09= "$common_connstr=20sslrootcert=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+=09$node->connect_ok(=0A+=09=09= "$common_connstr=20sslrootcert=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=20$node->connect_ok(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dinvalid",=0A+=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dinvalid=20ssldatabase=3Dssl/nss/root+server_ca.crt.db",=0A=20=09= "sslcrl=20option=20with=20invalid=20file=20name");=0A=20=0A-#=20A=20CRL=20= belonging=20to=20a=20different=20CA=20is=20not=20accepted,=20fails=0A= -$node->connect_fails(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dssl/client.crl",=0A-=09"CRL=20belonging=20to=20a=20different=20= CA",=0A-=09expected_stderr=20=3D>=20qr/SSL=20error:=20certificate=20= verify=20failed/);=0A+SKIP:=0A+{=0A+=09skip=20"CRL's=20are=20verified=20= when=20adding=20to=20NSS=20database",=204=20if=20($nss);=0A+=09#=20A=20= CRL=20belonging=20to=20a=20different=20CA=20is=20not=20accepted,=20fails=0A= +=09$node->connect_fails(=0A+=09=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dssl/client.crl",=0A+=09=09"CRL=20belonging=20to=20a=20different=20= CA",=0A+=09=09expected_stderr=20=3D>=20qr/SSL=20error:=20certificate=20= verify=20failed/);=0A=20=0A-#=20The=20same=20for=20CRL=20directory=0A= -$node->connect_fails(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrldir=3Dssl/client-crldir",=0A-=09"directory=20CRL=20belonging=20to=20= a=20different=20CA",=0A-=09expected_stderr=20=3D>=20qr/SSL=20error:=20= certificate=20verify=20failed/);=0A+=09#=20The=20same=20for=20CRL=20= directory=0A+=09$node->connect_fails(=0A+=09=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrldir=3Dssl/client-crldir",=0A+=09=09"directory=20CRL=20belonging=20= to=20a=20different=20CA",=0A+=09=09expected_stderr=20=3D>=20qr/SSL=20= error:=20certificate=20verify=20failed/);=0A+}=0A=20=0A=20#=20With=20the=20= correct=20CRL,=20succeeds=20(this=20cert=20is=20not=20revoked)=0A=20= $node->connect_ok(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dssl/root+server.crl",=0A+=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dssl/root+server.crl=20= ssldatabase=3Dssl/nss/root+server_ca.crt__root+server.crl.db",=0A=20=09= "CRL=20with=20a=20non-revoked=20cert");=0A=20=0A=20#=20The=20same=20for=20= CRL=20directory=0A=20$node->connect_ok(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrldir=3Dssl/root+server-crldir",=0A+=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrldir=3Dssl/root+server-crldir=20= ssldatabase=3Dssl/nss/root+server_ca.crt__root+server.crldir.db",=0A=20=09= "directory=20CRL=20with=20a=20non-revoked=20cert");=0A=20=0A=20#=20Check=20= that=20connecting=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= ssldatabase=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= $node->connect_ok("$common_connstr=20sslmode=3Drequire=20= host=3Dwronghost.test",=0A=20=09"mismatch=20between=20host=20name=20and=20= server=20certificate=20sslmode=3Drequire");=0A@@=20-205,14=20+280,14=20= @@=20$node->connect_fails(=0A=20=09"$common_connstr=20= sslmode=3Dverify-full=20host=3Dwronghost.test",=0A=20=09"mismatch=20= between=20host=20name=20and=20server=20certificate=20= sslmode=3Dverify-full",=0A=20=09expected_stderr=20=3D>=0A-=09=20=20= qr/\Qserver=20certificate=20for=20"common-name.pg-ssltest.test"=20does=20= not=20match=20host=20name=20"wronghost.test"\E/=0A+=09=20=20qr/\Qserver=20= certificate=20for=20"common-name.pg-ssltest.test"=20does=20not=20match=20= host=20name=20"wronghost.test"\E|requested=20domain=20name=20does=20not=20= match=20the=20server's=20certificate/=0A=20);=0A=20=0A=20#=20Test=20= Subject=20Alternative=20Names.=0A-switch_server_cert($node,=20= 'server-multiple-alt-names');=0A+switch_server_cert($node,=20certfile=20= =3D>=20'server-multiple-alt-names',=20nssdatabase=20=3D>=20= 'server-multiple-alt-names.crt__server-multiple-alt-names.key.db');=0A=20= =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=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= ssldatabase=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= $node->connect_ok(=0A=20=09"$common_connstr=20= host=3Ddns1.alt-name.pg-ssltest.test",=0A@@=20-227,21=20+302,22=20@@=20= $node->connect_fails(=0A=20=09"$common_connstr=20= host=3Dwronghost.alt-name.pg-ssltest.test",=0A=20=09"host=20name=20not=20= matching=20with=20X.509=20Subject=20Alternative=20Names",=0A=20=09= expected_stderr=20=3D>=0A-=09=20=20qr/\Qserver=20certificate=20for=20= "dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20names)=20does=20not=20= match=20host=20name=20"wronghost.alt-name.pg-ssltest.test"\E/=0A+=09=20=20= qr/\Qserver=20certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=20= 2=20other=20names)=20does=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);=0A+=0A=20= $node->connect_fails(=0A=20=09"$common_connstr=20= host=3Ddeep.subdomain.wildcard.pg-ssltest.test",=0A=20=09"host=20name=20= not=20matching=20with=20X.509=20Subject=20Alternative=20Names=20= wildcard",=0A=20=09expected_stderr=20=3D>=0A-=09=20=20qr/\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+=09=20=20qr/\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);=0A=20=0A=20#=20= Test=20certificate=20with=20a=20single=20Subject=20Alternative=20Name.=20= (this=20gives=20a=0A=20#=20slightly=20different=20error=20message,=20= that's=20all)=0A-switch_server_cert($node,=20'server-single-alt-name');=0A= +switch_server_cert($node,=20certfile=20=3D>=20'server-single-alt-name',=20= nssdatabase=20=3D>=20= 'server-single-alt-name.crt__server-single-alt-name.key.db');=0A=20=0A=20= $common_connstr=20=3D=0A-=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR=20sslmode=3Dverify-full";=0A+=20=20= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= sslmode=3Dverify-full=20ssldatabase=3Dssl/nss/root+server_ca.crt.db";=0A=20= =0A=20$node->connect_ok(=0A=20=09"$common_connstr=20= host=3Dsingle.alt-name.pg-ssltest.test",=0A@@=20-251,21=20+327,21=20@@=20= $node->connect_fails(=0A=20=09"$common_connstr=20= host=3Dwronghost.alt-name.pg-ssltest.test",=0A=20=09"host=20name=20not=20= matching=20with=20a=20single=20X.509=20Subject=20Alternative=20Name",=0A=20= =09expected_stderr=20=3D>=0A-=09=20=20qr/\Qserver=20certificate=20for=20= "single.alt-name.pg-ssltest.test"=20does=20not=20match=20host=20name=20= "wronghost.alt-name.pg-ssltest.test"\E/=0A+=09=20=20qr/\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|requested=20= domain=20name=20does=20not=20match=20the=20server's=20certificate/=0A=20= );=0A=20$node->connect_fails(=0A=20=09"$common_connstr=20= host=3Ddeep.subdomain.wildcard.pg-ssltest.test",=0A=20=09"host=20name=20= not=20matching=20with=20a=20single=20X.509=20Subject=20Alternative=20= Name=20wildcard",=0A=20=09expected_stderr=20=3D>=0A-=09=20=20qr/\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= =20=20qr/\Qserver=20certificate=20for=20= "single.alt-name.pg-ssltest.test"=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);=0A=20=0A=20#=20= Test=20server=20certificate=20with=20a=20CN=20and=20SANs.=20Per=20RFCs=20= 2818=20and=206125,=20the=20CN=0A=20#=20should=20be=20ignored=20when=20= the=20certificate=20has=20both.=0A-switch_server_cert($node,=20= 'server-cn-and-alt-names');=0A+switch_server_cert($node,=20certfile=20=3D>= =20'server-cn-and-alt-names',=20nssdatabase=20=3D>=20= 'server-cn-and-alt-names.crt__server-cn-and-alt-names.key.db');=0A=20=0A=20= $common_connstr=20=3D=0A-=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR=20sslmode=3Dverify-full";=0A+=20=20= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= sslmode=3Dverify-full=20ssldatabase=3Dssl/nss/root+server_ca.crt.db";=0A=20= =0A=20$node->connect_ok("$common_connstr=20= host=3Ddns1.alt-name.pg-ssltest.test",=0A=20=09"certificate=20with=20= both=20a=20CN=20and=20SANs=201");=0A@@=20-275,43=20+351,43=20@@=20= $node->connect_fails(=0A=20=09"$common_connstr=20= host=3Dcommon-name.pg-ssltest.test",=0A=20=09"certificate=20with=20both=20= a=20CN=20and=20SANs=20ignores=20CN",=0A=20=09expected_stderr=20=3D>=0A-=09= =20=20qr/\Qserver=20certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20= (and=201=20other=20name)=20does=20not=20match=20host=20name=20= "common-name.pg-ssltest.test"\E/=0A+=09=20=20qr/\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|requested=20= domain=20name=20does=20not=20match=20the=20server's=20certificate/=0A=20= );=0A=20=0A=20#=20Finally,=20test=20a=20server=20certificate=20that=20= has=20no=20CN=20or=20SANs.=20Of=20course,=20that's=0A=20#=20not=20a=20= very=20sensible=20certificate,=20but=20libpq=20should=20handle=20it=20= gracefully.=0A-switch_server_cert($node,=20'server-no-names');=0A= +switch_server_cert($node,=20certfile=20=3D>=20'server-no-names',=20= nssdatabase=20=3D>=20'server-no-names.crt__server-no-names.key.db');=0A=20= $common_connstr=20=3D=0A-=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR";=0A+=20=20"user=3Dssltestuser=20= dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= ssldatabase=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= $node->connect_ok(=0A=20=09"$common_connstr=20sslmode=3Dverify-ca=20= host=3Dcommon-name.pg-ssltest.test",=0A=20=09"server=20certificate=20= without=20CN=20or=20SANs=20sslmode=3Dverify-ca");=0A=20= $node->connect_fails(=0A=20=09$common_connstr=20.=20"=20"=0A-=09=20=20.=20= "sslmode=3Dverify-full=20host=3Dcommon-name.pg-ssltest.test",=0A+=09.=20= "sslmode=3Dverify-full=20host=3Dcommon-name.pg-ssltest.test",=0A=20=09= "server=20certificate=20without=20CN=20or=20SANs=20sslmode=3Dverify-full",= =0A=20=09expected_stderr=20=3D>=0A-=09=20=20qr/could=20not=20get=20= server's=20host=20name=20from=20server=20certificate/);=0A+=09=20=20= qr/could=20not=20get=20server's=20host=20name=20from=20server=20= certificate|requested=20domain=20name=20does=20not=20match=20the=20= server's=20certificate./);=0A=20=0A=20#=20Test=20that=20the=20CRL=20= works=0A-switch_server_cert($node,=20'server-revoked');=0A= +switch_server_cert($node,=20certfile=20=3D>=20'server-revoked',=20= nssdatabase=20=3D>=20'server-revoked.crt__server-revoked.key.db');=0A=20=0A= =20$common_connstr=20=3D=0A=20=20=20"user=3Dssltestuser=20dbname=3Dtrustdb= =20sslcert=3Dinvalid=20hostaddr=3D$SERVERHOSTADDR=20= host=3Dcommon-name.pg-ssltest.test";=0A=20=0A=20#=20Without=20the=20CRL,=20= succeeds.=20With=20it,=20fails.=0A=20$node->connect_ok(=0A-=09= "$common_connstr=20sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca",=0A+=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= ssldatabase=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connects=20= without=20client-side=20CRL");=0A=20$node->connect_fails(=0A-=09= "$common_connstr=20sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dssl/root+server.crl",=0A+=09= "$common_connstr=20sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dssl/root+server.crl=20= ssldatabase=3Dssl/nss/root+server_ca.crt__root+server.crl.db",=0A=20=09= "does=20not=20connect=20with=20client-side=20CRL=20file",=0A-=09= expected_stderr=20=3D>=20qr/SSL=20error:=20certificate=20verify=20= failed/);=0A+=09expected_stderr=20=3D>=20qr/SSL=20error:=20certificate=20= verify=20failed|SSL=20error:=20Peer's=20Certificate=20has=20been=20= revoked/);=0A=20$node->connect_fails(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrldir=3Dssl/root+server-crldir",=0A+=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrldir=3Dssl/root+server-crldir=20= ssldatabase=3Dssl/nss/root+server_ca.crt__root+server.crldir.db",=0A=20=09= "does=20not=20connect=20with=20client-side=20CRL=20directory",=0A-=09= expected_stderr=20=3D>=20qr/SSL=20error:=20certificate=20verify=20= failed/);=0A+=09expected_stderr=20=3D>=20qr/SSL=20error:=20certificate=20= verify=20failed|SSL=20error:=20Peer's=20Certificate=20has=20been=20= revoked/);=0A=20=0A=20#=20pg_stat_ssl=0A=20command_like(=0A@@=20-329,29=20= +405,46=20@@=20command_like(=0A=20=0A=20#=20Test=20min/max=20SSL=20= protocol=20versions.=0A=20$node->connect_ok(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3DTLSv1.2=20ssl_max_protocol_version=3DTLSv1.2",=0A= +=09"$common_connstr=20sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Drequire=20ssl_min_protocol_version=3DTLSv1.2=20= ssl_max_protocol_version=3DTLSv1.2=20= ssldatabase=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connection=20= success=20with=20correct=20range=20of=20TLS=20protocol=20versions");=0A=20= $node->connect_fails(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3DTLSv1.2=20ssl_max_protocol_version=3DTLSv1.1",=0A= +=09"$common_connstr=20sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Drequire=20ssl_min_protocol_version=3DTLSv1.2=20= ssl_max_protocol_version=3DTLSv1.1=20= ssldatabase=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connection=20= failure=20with=20incorrect=20range=20of=20TLS=20protocol=20versions",=0A=20= =09expected_stderr=20=3D>=20qr/invalid=20SSL=20protocol=20version=20= range/);=0A=20$node->connect_fails(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3Dincorrect_tls",=0A+=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3Dincorrect_tls=20= ssldatabase=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connection=20= failure=20with=20an=20incorrect=20SSL=20protocol=20minimum=20bound",=0A=20= =09expected_stderr=20=3D>=20qr/invalid=20ssl_min_protocol_version=20= value/);=0A=20$node->connect_fails(=0A-=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_max_protocol_version=3Dincorrect_tls",=0A+=09"$common_connstr=20= sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_max_protocol_version=3Dincorrect_tls=20= ssldatabase=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connection=20= failure=20with=20an=20incorrect=20SSL=20protocol=20maximum=20bound",=0A=20= =09expected_stderr=20=3D>=20qr/invalid=20ssl_max_protocol_version=20= value/);=0A=20=0A+#=20tests=20of=20NSS=20generated=20certificates/keys=0A= +SKIP:=0A+{=0A+=09skip=20"NSS=20specific=20tests",=20=20=20=20=20=20=20=20= =20=20=20=201=20if=20($openssl);=0A+=0A+=09switch_server_cert($node,=20= certfile=20=3D>=20'native_server-root',=20cafile=20=3D>=20= 'native_ca-root',=20nssdatabase=20=3D>=20'native_server-root.db');=0A+=09= $common_connstr=20=3D=0A+=09=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= hostaddr=3D$SERVERHOSTADDR=20host=3Dcommon-name.pg-ssltest.test";=0A+=0A= +=09$node->connect_ok(=0A+=09=09"$common_connstr=20sslmode=3Drequire=20= user=3Dssltestuser",=0A+=09=09"NSS=20generated=20certificates"=0A+=09);=0A= +}=0A+=0A=20###=20Server-side=20tests.=0A=20###=0A=20###=20Test=20= certificate=20authorization.=0A=20=0A+switch_server_cert($node,=20= certfile=20=3D>=20'server-revoked',=20nssdatabase=20=3D>=20= 'server-revoked.crt__server-revoked.key.db');=0A+=0A=20note=20"running=20= server=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= ssldatabase=3Dssl/nss/client.crt__client.key.db";=0A=20=0A=20#=20no=20= client=20cert=0A=20$node->connect_fails(=0A@@=20-365,62=20+458,82=20@@=20= $node->connect_ok(=0A=20=09"certificate=20authorization=20succeeds=20= with=20correct=20client=20cert=20in=20PEM=20format"=0A=20);=0A=20=0A-#=20= correct=20client=20cert=20in=20unencrypted=20DER=0A-$node->connect_ok(=0A= -=09"$common_connstr=20user=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= +SKIP:=0A+{=0A+=09skip=20"Automatic=20certificate=20resolution=20is=20= NSS=20specific",=201=20if=20($openssl);=0A+=09#=20correct=20client=20= cert=20in=20unencrypted=20PEM=20without=20a=20nickname=20(sslcert)=0A+=09= $node->connect_ok(=0A+=09=09"$common_connstr=20user=3Dssltestuser",=0A+=09= =09"certificate=20authorization=20succeeds=20without=20correct=20client=20= cert=20in=20connstring"=0A+=09);=0A+}=0A+=0A+SKIP:=0A+{=0A+=09skip=20= "NSS=20database=20not=20implemented=20in=20the=20Makefile",=201=20if=20= ($nss);=0A+=09#=20correct=20client=20cert=20in=20unencrypted=20DER=0A+=09= $node->connect_ok(=0A+=09=09"$common_connstr=20user=3Dssltestuser=20= sslcert=3Dssl/client.crt=20sslkey=3Dssl/client-der_tmp.key",=0A+=09=09= "certificate=20authorization=20succeeds=20with=20correct=20client=20cert=20= in=20DER=20format"=0A+=09);=0A+}=0A=20=0A=20#=20correct=20client=20cert=20= in=20encrypted=20PEM=0A=20$node->connect_ok(=0A-=09"$common_connstr=20= user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-encrypted-pem_tmp.key=20sslpassword=3D'dUmmyP^#+'",=0A= +=09"$common_connstr=20user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-encrypted-pem_tmp.key=20sslpassword=3D'dUmmyP^#+'=20= ssldatabase=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-$node->connect_ok(=0A-=09"$common_connstr=20= 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= $node->connect_ok(=0A+=09=09"$common_connstr=20user=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=20$node->connect_fails(=0A-=09= "$common_connstr=20user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-encrypted-pem_tmp.key=20sslpassword=3D'wrong'",=0A+=09= "$common_connstr=20user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-encrypted-pem_tmp.key=20sslpassword=3D'wrong'=20= ssldatabase=3Dssl/nss/client.crt__client-encrypted-pem.key.db",=0A=20=09= "certificate=20authorization=20fails=20with=20correct=20client=20cert=20= and=20wrong=20password=20in=20encrypted=20PEM=20format",=0A=20=09= expected_stderr=20=3D>=0A-=09=20=20qr!\Qprivate=20key=20file=20= "ssl/client-encrypted-pem_tmp.key":=20bad=20decrypt\E!=0A+=09=20=20= qr!connection=20requires=20a=20valid=20client=20certificate|\Qprivate=20= key=20file=20"ssl/client-encrypted-pem_tmp.key":=20bad=20decrypt\E!,=0A=20= );=0A=20=0A-=0A-#=20correct=20client=20cert=20using=20whole=20DN=0A-my=20= $dn_connstr=20=3D=20"$common_connstr=20dbname=3Dcertdb_dn";=0A-=0A= -$node->connect_ok(=0A-=09"$dn_connstr=20user=3Dssltestuser=20= sslcert=3Dssl/client-dn.crt=20sslkey=3Dssl/client-dn_tmp.key",=0A-=09= "certificate=20authorization=20succeeds=20with=20DN=20mapping",=0A-=09= log_like=20=3D>=20[=0A-=09=09qr/connection=20authenticated:=20= identity=3D"CN=3Dssltestuser-dn,OU=3DTesting,OU=3DEngineering,O=3DPGDG"=20= method=3Dcert/=0A-=09],);=0A-=0A-#=20same=20thing=20but=20with=20a=20= regex=0A-$dn_connstr=20=3D=20"$common_connstr=20dbname=3Dcertdb_dn_re";=0A= -=0A-$node->connect_ok(=0A-=09"$dn_connstr=20user=3Dssltestuser=20= sslcert=3Dssl/client-dn.crt=20sslkey=3Dssl/client-dn_tmp.key",=0A-=09= "certificate=20authorization=20succeeds=20with=20DN=20regex=20mapping");=0A= -=0A-#=20same=20thing=20but=20using=20explicit=20CN=0A-$dn_connstr=20=3D=20= "$common_connstr=20dbname=3Dcertdb_cn";=0A-=0A-$node->connect_ok(=0A-=09= "$dn_connstr=20user=3Dssltestuser=20sslcert=3Dssl/client-dn.crt=20= sslkey=3Dssl/client-dn_tmp.key",=0A-=09"certificate=20authorization=20= succeeds=20with=20CN=20mapping",=0A-=09#=20the=20full=20DN=20should=20= still=20be=20used=20as=20the=20authenticated=20identity=0A-=09log_like=20= =3D>=20[=0A-=09=09qr/connection=20authenticated:=20= identity=3D"CN=3Dssltestuser-dn,OU=3DTesting,OU=3DEngineering,O=3DPGDG"=20= method=3Dcert/=0A-=09],);=0A-=0A-=0A+SKIP:=0A+{=0A+=09skip=20"DN=20= mapping=20not=20implemented=20in=20NSS",=20=20=20=20=20=20=20=20=20=20=20= =203=20if=20($nss);=0A+=0A+=09#=20correct=20client=20cert=20using=20= whole=20DN=0A+=09my=20$dn_connstr=20=3D=20"$common_connstr=20= dbname=3Dcertdb_dn";=0A+=0A+=09$node->connect_ok(=0A+=09=09"$dn_connstr=20= user=3Dssltestuser=20sslcert=3Dssl/client-dn.crt=20= sslkey=3Dssl/client-dn_tmp.key",=0A+=09=09"certificate=20authorization=20= succeeds=20with=20DN=20mapping",=0A+=09=09log_like=20=3D>=20[=0A+=09=09=09= qr/connection=20authenticated:=20= identity=3D"CN=3Dssltestuser-dn,OU=3DTesting,OU=3DEngineering,O=3DPGDG"=20= method=3Dcert/=0A+=09=09],);=0A+=0A+=09#=20same=20thing=20but=20with=20a=20= regex=0A+=09$dn_connstr=20=3D=20"$common_connstr=20dbname=3Dcertdb_dn_re";= =0A+=0A+=09$node->connect_ok(=0A+=09=09"$dn_connstr=20user=3Dssltestuser=20= sslcert=3Dssl/client-dn.crt=20sslkey=3Dssl/client-dn_tmp.key",=0A+=09=09= "certificate=20authorization=20succeeds=20with=20CN=20mapping",=0A+=09=09= #=20the=20full=20DN=20should=20still=20be=20used=20as=20the=20= authenticated=20identity=0A+=09=09log_like=20=3D>=20[=0A+=09=09=09= qr/connection=20authenticated:=20= identity=3D"CN=3Dssltestuser-dn,OU=3DTesting,OU=3DEngineering,O=3DPGDG"=20= method=3Dcert/=0A+=09=09],);=0A+=0A+=09#=20same=20thing=20but=20using=20= explicit=20CN=0A+=09$dn_connstr=20=3D=20"$common_connstr=20= dbname=3Dcertdb_cn";=0A+=0A+=09$node->connect_ok(=0A+=09=09"$dn_connstr=20= user=3Dssltestuser=20sslcert=3Dssl/client-dn.crt=20= sslkey=3Dssl/client-dn_tmp.key",=0A+=09=09"certificate=20authorization=20= succeeds=20with=20CN=20mapping");=0A+}=0A=20=0A=20TODO:=0A=20{=0A@@=20= -449,30=20+562,33=20@@=20TODO:=0A=20=0A=20#=20pg_stat_ssl=0A=20=0A-my=20= $serialno=20=3D=20`openssl=20x509=20-serial=20-noout=20-in=20= ssl/client.crt`;=0A-if=20($?=20=3D=3D=200)=0A+#=20If=20the=20serial=20= number=20can't=20be=20extracted=20to=20match=20against,=20fall=20back=20= to=20just=0A+#=20checking=20for=20it=20being=20integer.=0A+#=20TODO:=20= figure=20put=20a=20corresponding=20command=20for=20NSS=20to=20extract=20= the=20serial=20from=0A+#=20the=20cert.=0A+my=20$serialno=20=3D=20'\d+';=0A= +if=20($openssl)=0A=20{=0A-=09#=20OpenSSL=20prints=20serial=20numbers=20= in=20hexadecimal=20and=20converting=20the=20serial=0A-=09#=20from=20hex=20= requires=20a=2064-bit=20capable=20Perl=20as=20the=20serialnumber=20is=20= based=20on=0A-=09#=20the=20current=20timestamp.=20On=2032-bit=20fall=20= back=20to=20checking=20for=20it=20being=20an=0A-=09#=20integer=20like=20= how=20we=20do=20when=20grabbing=20the=20serial=20fails.=0A-=09if=20= ($Config{ivsize}=20=3D=3D=208)=0A+=09my=20$serialno=20=3D=20`openssl=20= x509=20-serial=20-noout=20-in=20ssl/client.crt`;=0A+=09if=20($?=20=3D=3D=20= 0)=0A=20=09{=0A-=09=09$serialno=20=3D~=20s/^serial=3D//;=0A-=09=09= $serialno=20=3D=20hex($serialno);=0A+=09=09#=20OpenSSL=20prints=20serial=20= numbers=20in=20hexadecimal=20and=20converting=20the=20serial=0A+=09=09#=20= from=20hex=20requires=20a=2064-bit=20capable=20Perl=20as=20the=20= serialnumber=20is=20based=20on=0A+=09=09#=20the=20current=20timestamp.=20= On=2032-bit=20fall=20back=20to=20checking=20for=20it=20being=20an=0A+=09=09= #=20integer=20like=20how=20we=20do=20when=20grabbing=20the=20serial=20= fails.=0A+=09=09if=20($Config{ivsize}=20=3D=3D=208)=0A+=09=09{=0A+=09=09=09= $serialno=20=3D~=20s/^serial=3D//;=0A+=09=09=09$serialno=20=3D=20= hex($serialno);=0A+=09=09}=0A=20=09}=0A=20=09else=0A=20=09{=0A-=09=09= $serialno=20=3D=20'\d+';=0A+=09=09#=20OpenSSL=20isn't=20functioning=20on=20= the=20user's=20PATH.=20This=20probably=20isn't=20worth=0A+=09=09#=20= skipping=20the=20test=20over,=20so=20just=20fall=20back=20to=20a=20= generic=20integer=20match.=0A+=09=09warn=20'couldn\'t=20run=20`openssl=20= x509`=20to=20get=20client=20cert=20serialno';=0A=20=09}=0A=20}=0A-else=0A= -{=0A-=09#=20OpenSSL=20isn't=20functioning=20on=20the=20user's=20PATH.=20= This=20probably=20isn't=20worth=0A-=09#=20skipping=20the=20test=20over,=20= so=20just=20fall=20back=20to=20a=20generic=20integer=20match.=0A-=09warn=20= 'couldn\'t=20run=20`openssl=20x509`=20to=20get=20client=20cert=20= serialno';=0A-=09$serialno=20=3D=20'\d+';=0A-}=0A=20=0A=20command_like(=0A= =20=09[=0A@@=20-484,18=20+600,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= ssldatabase=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,client_dn,client_serial,issuer_dn\r?\n=0A= -=09=09=09=09= ^\d+,t,TLSv[\d.]+,[\w-]+,\d+,/CN=3Dssltestuser,$serialno,\Q/CN=3DTest=20= CA=20for=20PostgreSQL=20SSL=20regression=20test=20client=20= certs\E\r?$}mx,=0A+=09=09=09=09= ^\d+,t,TLSv[\d.]+,[\w-]+,\d+,/?CN=3Dssltestuser,$serialno,/?\QCN=3DTest=20= CA=20for=20PostgreSQL=20SSL=20regression=20test=20client=20= certs\E\r?$}mx,=0A=20=09'pg_stat_ssl=20with=20client=20certificate');=0A=20= =0A=20#=20client=20key=20with=20wrong=20permissions=0A=20SKIP:=0A=20{=0A=20= =09skip=20"Permissions=20check=20not=20enforced=20on=20Windows",=202=20= if=20($windows_os);=0A+=09skip=20"Key=20not=20on=20filesystem=20with=20= NSS",=20=20=20=20=20=20=20=20=20=20=20=202=20if=20($nss);=0A=20=0A=20=09= $node->connect_fails(=0A=20=09=09"$common_connstr=20user=3Dssltestuser=20= sslcert=3Dssl/client.crt=20sslkey=3Dssl/client_wrongperms_tmp.key",=0A@@=20= -510,16=20+627,20=20@@=20$node->connect_fails(=0A=20=09"$common_connstr=20= user=3Danotheruser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client_tmp.key",=0A=20=09"certificate=20authorization=20= fails=20with=20client=20cert=20belonging=20to=20another=20user",=0A=20=09= expected_stderr=20=3D>=0A-=09=20=20qr/certificate=20authentication=20= failed=20for=20user=20"anotheruser"/,=0A+=09=20=20qr/unable=20to=20= verify=20certificate|certificate=20authentication=20failed=20for=20user=20= "anotheruser"/,=0A=20=09#=20certificate=20authentication=20should=20be=20= logged=20even=20on=20failure=0A=20=09log_like=20=3D>=0A=20=09=20=20= [qr/connection=20authenticated:=20identity=3D"CN=3Dssltestuser"=20= method=3Dcert/],);=0A=20=0A+$common_connstr=20=3D=0A+=20=20= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= dbname=3Dcertdb=20hostaddr=3D$SERVERHOSTADDR=20= ssldatabase=3Dssl/nss/client-revoked.crt__client-revoked.key.db";=0A+=0A=20= #=20revoked=20client=20cert=0A=20$node->connect_fails(=0A=20=09= "$common_connstr=20user=3Dssltestuser=20sslcert=3Dssl/client-revoked.crt=20= sslkey=3Dssl/client-revoked_tmp.key",=0A=20=09"certificate=20= authorization=20fails=20with=20revoked=20client=20cert",=0A-=09= expected_stderr=20=3D>=20qr/SSL=20error:=20sslv3=20alert=20certificate=20= revoked/,=0A+=09expected_stderr=20=3D>=0A+=09=20=20qr/SSL=20error:=20= sslv3=20alert=20certificate=20revoked|SSL=20error:=20Peer's=20= certificate=20issuer=20has=20been=20marked=20as=20not=20trusted=20by=20= the=20user/,=0A=20=09#=20revoked=20certificates=20should=20not=20= authenticate=20the=20user=0A=20=09log_unlike=20=3D>=20[qr/connection=20= authenticated:/],);=0A=20=0A@@=20-527,7=20+648,7=20@@=20= $node->connect_fails(=0A=20#=20works,=20iff=20username=20matches=20= Common=20Name=0A=20#=20fails,=20iff=20username=20doesn't=20match=20= Common=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= ssldatabase=3Dssl/nss/client.crt__client.key.db";=0A=20=0A=20= $node->connect_ok(=0A=20=09"$common_connstr=20user=3Dssltestuser=20= sslcert=3Dssl/client.crt=20sslkey=3Dssl/client_tmp.key",=0A@@=20-552,9=20= +673,9=20@@=20$node->connect_ok(=0A=20=09log_unlike=20=3D>=20= [qr/connection=20authenticated:/],);=0A=20=0A=20#=20intermediate=20= client_ca.crt=20is=20provided=20by=20client,=20and=20isn't=20in=20= server's=20ssl_ca_file=0A-switch_server_cert($node,=20'server-cn-only',=20= 'root_ca');=0A+switch_server_cert($node,=20certfile=20=3D>=20= 'server-cn-only',=20cafile=20=3D>=20'root_ca',=20nssdatabase=20=3D>=20= 'server-cn-only.crt__server-cn-only.key.db');=0A=20$common_connstr=20=3D=0A= -=20=20"user=3Dssltestuser=20dbname=3Dcertdb=20sslkey=3Dssl/client_tmp.key= =20sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR";=0A= +=20=20"user=3Dssltestuser=20dbname=3Dcertdb=20sslkey=3Dssl/client_tmp.key= =20sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= ssldatabase=3Dssl/nss/client+client_ca.crt__client.key.db";=0A=20=0A=20= $node->connect_ok(=0A=20=09"$common_connstr=20sslmode=3Drequire=20= sslcert=3Dssl/client+client_ca.crt",=0A@@=20-562,17=20+683,18=20@@=20= $node->connect_ok(=0A=20$node->connect_fails(=0A=20=09$common_connstr=20= .=20"=20"=20.=20"sslmode=3Drequire=20sslcert=3Dssl/client.crt",=0A=20=09= "intermediate=20client=20certificate=20is=20missing",=0A-=09= expected_stderr=20=3D>=20qr/SSL=20error:=20tlsv1=20alert=20unknown=20= ca/);=0A+=09expected_stderr=20=3D>=0A+=09=20=20qr/SSL=20error:=20tlsv1=20= alert=20unknown=20ca|connection=20requires=20a=20valid=20client=20= certificate/);=0A=20=0A=20#=20test=20server-side=20CRL=20directory=0A= -switch_server_cert($node,=20'server-cn-only',=20undef,=20undef,=0A-=09= 'root+client-crldir');=0A+switch_server_cert($node,=20certfile=20=3D>=20= 'server-cn-only',=20crldir=20=3D>=20'root+client-crldir',=20nssdatabase=20= =3D>=20'server-cn-only.crt__server-cn-only.key.crldir.db');=0A=20=0A=20#=20= revoked=20client=20cert=0A=20$node->connect_fails(=0A-=09= "$common_connstr=20user=3Dssltestuser=20sslcert=3Dssl/client-revoked.crt=20= sslkey=3Dssl/client-revoked_tmp.key",=0A+=09"$common_connstr=20= user=3Dssltestuser=20sslcert=3Dssl/client-revoked.crt=20= sslkey=3Dssl/client-revoked_tmp.key=20= ssldatabase=3Dssl/nss/client-revoked.crt__client-revoked.key.db",=0A=20=09= "certificate=20authorization=20fails=20with=20revoked=20client=20cert=20= with=20server-side=20CRL=20directory",=0A-=09expected_stderr=20=3D>=20= qr/SSL=20error:=20sslv3=20alert=20certificate=20revoked/);=0A+=09= expected_stderr=20=3D>=0A+=09=20=20qr/SSL=20error:=20sslv3=20alert=20= certificate=20revoked|SSL=20peer=20rejected=20your=20certificate=20as=20= revoked/);=0A=20=0A=20#=20clean=20up=0A=20=0Adiff=20--git=20= a/src/test/ssl/t/002_scram.pl=20b/src/test/ssl/t/002_scram.pl=0Aindex=20= 59f520cb5b..f6a0a23390=20100644=0A---=20a/src/test/ssl/t/002_scram.pl=0A= +++=20b/src/test/ssl/t/002_scram.pl=0A@@=20-16,7=20+16,26=20@@=20use=20= lib=20$FindBin::RealBin;=0A=20=0A=20use=20SSL::Server;=0A=20=0A-if=20= ($ENV{with_ssl}=20ne=20'openssl')=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= 'openssl')=0A+{=0A+=09$openssl=20=3D=201;=0A+=09#=20Determine=20whether=20= build=20supports=20tls-server-end-point.=0A+=09= $supports_tls_server_end_point=20=3D=0A+=09=09check_pg_config("#define=20= HAVE_X509_GET_SIGNATURE_NID=201");=0A+=09plan=20tests=20=3D>=20= $supports_tls_server_end_point=20?=2011=20:=2012;=0A+}=0A+elsif=20= ($ENV{with_ssl}=20eq=20'nss')=0A+{=0A+=09$nss=20=3D=201;=0A+=09= $supports_tls_server_end_point=20=3D=201;=0A+=09plan=20tests=20=3D>=20= 11;=0A+}=0A+else=0A=20{=0A=20=09plan=20skip_all=20=3D>=20'SSL=20not=20= supported=20by=20this=20build';=0A=20}=0A@@=20-26,12=20+45,6=20@@=20my=20= $SERVERHOSTADDR=20=3D=20'127.0.0.1';=0A=20#=20This=20is=20the=20pattern=20= to=20use=20in=20pg_hba.conf=20to=20match=20incoming=20connections.=0A=20= my=20$SERVERHOSTCIDR=20=3D=20'127.0.0.1/32';=0A=20=0A-#=20Determine=20= whether=20build=20supports=20tls-server-end-point.=0A-my=20= $supports_tls_server_end_point=20=3D=0A-=20=20check_pg_config("#define=20= HAVE_X509_GET_SIGNATURE_NID=201");=0A-=0A-my=20$number_of_tests=20=3D=20= $supports_tls_server_end_point=20?=2011=20:=2012;=0A-=0A=20#=20= Allocation=20of=20base=20connection=20string=20shared=20among=20multiple=20= tests.=0A=20my=20$common_connstr;=0A=20=0A@@=20-50,7=20+63,7=20@@=20= $node->start;=0A=20#=20Configure=20server=20for=20SSL=20connections,=20= with=20password=20handling.=0A=20configure_test_server_for_ssl($node,=20= $SERVERHOSTADDR,=20$SERVERHOSTCIDR,=0A=20=09"scram-sha-256",=20"pass",=20= "scram-sha-256");=0A-switch_server_cert($node,=20'server-cn-only');=0A= +switch_server_cert($node,=20certfile=20=3D>=20'server-cn-only',=20= nssdatabase=20=3D>=20'server-cn-only.crt__server-cn-only.key.db');=0A=20= $ENV{PGPASSWORD}=20=3D=20"pass";=0A=20$common_connstr=20=3D=0A=20=20=20= "dbname=3Dtrustdb=20sslmode=3Drequire=20sslcert=3Dinvalid=20= sslrootcert=3Dinvalid=20hostaddr=3D$SERVERHOSTADDR";=0A@@=20-99,7=20= +112,7=20@@=20my=20$client_tmp_key=20=3D=20"ssl/client_scram_tmp.key";=0A= =20copy("ssl/client.key",=20$client_tmp_key);=0A=20chmod=200600,=20= $client_tmp_key;=0A=20$node->connect_fails(=0A-=09= "sslcert=3Dssl/client.crt=20sslkey=3D$client_tmp_key=20= sslrootcert=3Dinvalid=20hostaddr=3D$SERVERHOSTADDR=20dbname=3Dcertdb=20= user=3Dssltestuser=20channel_binding=3Drequire",=0A+=09= "sslcert=3Dssl/client.crt=20sslkey=3D$client_tmp_key=20= sslrootcert=3Dinvalid=20hostaddr=3D$SERVERHOSTADDR=20= ssldatabase=3Dssl/nss/client.crt__client.key.db=20dbname=3Dcertdb=20= user=3Dssltestuser=20channel_binding=3Drequire",=0A=20=09"Cert=20= authentication=20and=20channel_binding=3Drequire",=0A=20=09= expected_stderr=20=3D>=0A=20=09=20=20qr/channel=20binding=20required,=20= but=20server=20authenticated=20client=20without=20channel=20binding/=0A= @@=20-107,7=20+120,7=20@@=20$node->connect_fails(=0A=20=0A=20#=20= Certificate=20verification=20at=20the=20connection=20level=20should=20= still=20work=20fine.=0A=20$node->connect_ok(=0A-=09= "sslcert=3Dssl/client.crt=20sslkey=3D$client_tmp_key=20= sslrootcert=3Dinvalid=20hostaddr=3D$SERVERHOSTADDR=20dbname=3Dverifydb=20= user=3Dssltestuser",=0A+=09"sslcert=3Dssl/client.crt=20= sslkey=3D$client_tmp_key=20sslrootcert=3Dinvalid=20= hostaddr=3D$SERVERHOSTADDR=20= ssldatabase=3Dssl/nss/client.crt__client.key.db=20dbname=3Dverifydb=20= user=3Dssltestuser",=0A=20=09"SCRAM=20with=20clientcert=3Dverify-full",=0A= =20=09log_like=20=3D>=20[=0A=20=09=09qr/connection=20authenticated:=20= identity=3D"ssltestuser"=20method=3Dscram-sha-256/=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..20633fe41b=0A---=20/dev/null=0A+++=20= b/src/test/ssl/t/SSL/Backend/NSS.pm=0A@@=20-0,0=20+1,61=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=3D=20$_[0];=0A+=09my=20= $params=20=3D=20$_[1];=0A+=0A+=09$params->{cafile}=20=3D=20= 'root+client_ca'=20unless=20defined=20$params->{cafile};=0A+=0A+=09my=20= $sslconf=20=3D=0A+=09=20=20=20=20"ssl_ca_file=3D'$params->{cafile}.crt'\n"= =0A+=09=20=20.=20"ssl_cert_file=3D'ssl/$params->{certfile}.crt'\n"=0A+=09= =20=20.=20"ssl_crl_file=3D''\n"=0A+=09=20=20.=20= "ssl_database=3D'nss/$params->{nssdatabase}'\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=0Aindex=20e77ee25cc7..9e419b0e0f=20= 100644=0A---=20a/src/test/ssl/t/SSL/Backend/OpenSSL.pm=0A+++=20= b/src/test/ssl/t/SSL/Backend/OpenSSL.pm=0A@@=20-71,16=20+71,19=20@@=20= sub=20init=0A=20#=20the=20server=20so=20that=20the=20configuration=20= takes=20effect.=0A=20sub=20set_server_cert=0A=20{=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+=09my=20$self=20=20=20=3D=20$_[0];=0A= +=09my=20$params=20=3D=20$_[1];=0A+=0A+=09$params->{cafile}=20=3D=20= 'root+client_ca'=20unless=20defined=20$params->{cafile};=0A+=09= $params->{crlfile}=20=3D=20'root+client.crl'=20unless=20defined=20= $params->{crlfile};=0A+=09$params->{keyfile}=20=3D=20$params->{certfile}=20= unless=20defined=20$params->{keyfile};=0A=20=0A=20=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+=09=20=20=20=20= "ssl_ca_file=3D'$params->{cafile}.crt'\n"=0A+=09=20=20.=20= "ssl_cert_file=3D'$params->{certfile}.crt'\n"=0A+=09=20=20.=20= "ssl_key_file=3D'$params->{keyfile}.key'\n"=0A+=09=20=20.=20= "ssl_crl_file=3D'$params->{crlfile}'\n";=0A+=09$sslconf=20.=3D=20= "ssl_crl_dir=3D'$params->{crldir}'\n"=20if=20defined=20= $params->{crldir};=0A=20=0A=20=09return=20$sslconf;=0A=20}=0Adiff=20= --git=20a/src/test/ssl/t/SSL/Server.pm=20b/src/test/ssl/t/SSL/Server.pm=0A= index=2083df239e20..68cfd53dc3=20100644=0A---=20= a/src/test/ssl/t/SSL/Server.pm=0A+++=20b/src/test/ssl/t/SSL/Server.pm=0A= @@=20-58,7=20+58,6=20@@=20elsif=20($ENV{with_ssl}=20eq=20'nss')=0A=20use=20= Exporter=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);=0A=20=0A@@=20-145,7=20+144,7=20@@=20sub=20= configure_test_server_for_ssl=0A=20=09}=0A=20=09elsif=20(defined($nss))=0A= =20=09{=0A-=09=09RecursiveCopy::copypath("ssl/nss",=20$pgdata=20.=20= "/nss")=20if=20-e=20"ssl/nss";=0A+=09=09= PostgreSQL::Test::RecursiveCopy::copypath("ssl/nss",=20$pgdata=20.=20= "/nss")=20if=20-e=20"ssl/nss";=0A=20=09}=0A=20=0A=20=09#=20Stop=20and=20= restart=20server=20to=20load=20new=20listen_addresses.=0A@@=20-170,46=20= +169,25=20@@=20sub=20cleanup=0A=20=09$backend->cleanup();=0A=20}=0A=20=0A= -#=20Change=20the=20configuration=20to=20use=20given=20server=20cert=20= file,=0A-sub=20set_server_cert=0A+#=20Change=20the=20configuration=20to=20= use=20the=20given=20set=20of=20certificate,=20key,=20ca=20and=0A+#=20= CRL,=20and=20potentially=20reload=20the=20configuration=20by=20= restarting=20the=20server=20so=0A+#=20that=20the=20configuration=20takes=20= effect.=20=20Restarting=20is=20the=20default,=20passing=0A+#=20restart=20= =3D>=20'no'=20opts=20out=20of=20it=20leaving=20the=20server=20running.=0A= +sub=20switch_server_cert=0A=20{=0A-=09my=20$node=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= '';=0A-=09my=20$pwcmd=20=20=20=20=3D=20$_[4]=20||=20'';=0A-=09my=20= $crlfile=20=20=3D=20"root+client.crl";=0A-=09my=20$crldir;=0A+=09my=20= $node=20=20=20=3D=20shift;=0A+=09my=20%params=20=3D=20@_;=0A=20=09my=20= $pgdata=20=3D=20$node->data_dir;=0A=20=0A-=09$keyfile=20=3D=20$certfile=20= if=20$keyfile=20eq=20'';=0A-=0A-=09#=20defaults=20to=20use=20crl=20file=0A= -=09if=20(defined=20$_[3]=20||=20defined=20$_[4])=0A-=09{=0A-=09=09= $crlfile=20=3D=20$_[3];=0A-=09=09$crldir=20=20=3D=20$_[4];=0A-=09}=0A-=0A= =20=09open=20my=20$sslconf,=20'>',=20"$pgdata/sslconfig.conf";=0A=20=09= print=20$sslconf=20"ssl=3Don\n";=0A-=09print=20$sslconf=20= $backend->set_server_cert($certfile,=20$cafile,=20$keyfile);=0A-=09print=20= $sslconf=20"ssl_crl_file=3D'$crlfile'\n"=20if=20defined=20$crlfile;=0A-=09= print=20$sslconf=20"ssl_crl_dir=3D'$crldir'\n"=20=20=20if=20defined=20= $crldir;=0A-=09print=20$sslconf=20"ssl_passphrase_command=3D'$pwcmd'\n"=0A= -=09=20=20unless=20$pwcmd=20eq=20'';=0A+=09print=20$sslconf=20= $backend->set_server_cert(\%params);=0A+=09print=20$sslconf=20= "ssl_passphrase_command=3D'"=20.=20$params{passphrase_cmd}=20.=20"'\n"=0A= +=09=20=20if=20defined=20$params{passphrase_cmd};=0A=20=09close=20= $sslconf;=0A-=09return;=0A-}=0A=20=0A-#=20Change=20the=20configuration=20= to=20use=20given=20server=20cert=20file,=20and=20reload=0A-#=20the=20= server=20so=20that=20the=20configuration=20takes=20effect.=0A-#=20Takes=20= the=20same=20arguments=20as=20set_server_cert,=20which=20it=20calls=20to=20= do=20that=0A-#=20piece=20of=20the=20work.=0A-sub=20switch_server_cert=0A= -{=0A-=09my=20$node=20=3D=20$_[0];=0A-=09set_server_cert(@_);=0A+=09= return=20if=20(defined($params{restart})=20&&=20$params{restart}=20eq=20= 'no');=0A+=0A=20=09$node->restart;=0A=20=09return;=0A=20}=0A--=20=0A= 2.24.3=20(Apple=20Git-128)=0A=0A= --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F Content-Disposition: attachment; filename=v49-0004-test-check-for-empty-stderr-during-connect_ok.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v49-0004-test-check-for-empty-stderr-during-connect_ok.patch" Content-Transfer-Encoding: quoted-printable =46rom=2004291d97919c4bbaea93fbd062817f3d540750ac=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Jacob=20Champion=20=0A= Date:=20Sat,=2019=20Jun=202021=2001:37:30=20+0200=0ASubject:=20[PATCH=20= v49=2004/10]=20test:=20check=20for=20empty=20stderr=20during=20= connect_ok()=0A=0A...in=20a=20similar=20manner=20to=20command_like(),=20= to=20catch=20notices-as-errors=0Acoming=20from=20NSS.=0A---=0A=20= src/test/authentication/t/001_password.pl=20|=202=20+-=0A=20= src/test/authentication/t/002_saslprep.pl=20|=202=20+-=0A=20= src/test/kerberos/t/001_auth.pl=20=20=20=20=20=20=20=20=20=20=20|=202=20= +-=0A=20src/test/ldap/t/001_auth.pl=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20|=202=20+-=0A=20src/test/perl/PostgreSQL/Test/Cluster.pm=20=20|=20= 5=20++++-=0A=20src/test/ssl/t/001_ssltests.pl=20=20=20=20=20=20=20=20=20=20= =20=20|=204=20++--=0A=20src/test/ssl/t/002_scram.pl=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20|=204=20++--=0A=207=20files=20changed,=2012=20= insertions(+),=209=20deletions(-)=0A=0Adiff=20--git=20= a/src/test/authentication/t/001_password.pl=20= b/src/test/authentication/t/001_password.pl=0Aindex=20= 11ca525c6c..f749633ca8=20100644=0A---=20= a/src/test/authentication/t/001_password.pl=0A+++=20= b/src/test/authentication/t/001_password.pl=0A@@=20-20,7=20+20,7=20@@=20= if=20(!$use_unix_sockets)=0A=20}=0A=20else=0A=20{=0A-=09plan=20tests=20= =3D>=2023;=0A+=09plan=20tests=20=3D>=2032;=0A=20}=0A=20=0A=20=0Adiff=20= --git=20a/src/test/authentication/t/002_saslprep.pl=20= b/src/test/authentication/t/002_saslprep.pl=0Aindex=20= 766fed67cc..8b8fad7c86=20100644=0A---=20= a/src/test/authentication/t/002_saslprep.pl=0A+++=20= b/src/test/authentication/t/002_saslprep.pl=0A@@=20-17,7=20+17,7=20@@=20= if=20(!$use_unix_sockets)=0A=20}=0A=20else=0A=20{=0A-=09plan=20tests=20= =3D>=2012;=0A+=09plan=20tests=20=3D>=2020;=0A=20}=0A=20=0A=20#=20Delete=20= pg_hba.conf=20from=20the=20given=20node,=20add=20a=20new=20entry=20to=20= it=0Adiff=20--git=20a/src/test/kerberos/t/001_auth.pl=20= b/src/test/kerberos/t/001_auth.pl=0Aindex=2013d664dda0..28a6f44250=20= 100644=0A---=20a/src/test/kerberos/t/001_auth.pl=0A+++=20= b/src/test/kerberos/t/001_auth.pl=0A@@=20-23,7=20+23,7=20@@=20use=20= Time::HiRes=20qw(usleep);=0A=20=0A=20if=20($ENV{with_gssapi}=20eq=20= 'yes')=0A=20{=0A-=09plan=20tests=20=3D>=2044;=0A+=09plan=20tests=20=3D>=20= 54;=0A=20}=0A=20else=0A=20{=0Adiff=20--git=20= a/src/test/ldap/t/001_auth.pl=20b/src/test/ldap/t/001_auth.pl=0Aindex=20= 5a9a009832..523a77b2c5=20100644=0A---=20a/src/test/ldap/t/001_auth.pl=0A= +++=20b/src/test/ldap/t/001_auth.pl=0A@@=20-9,7=20+9,7=20@@=20use=20= Test::More;=0A=20=0A=20if=20($ENV{with_ldap}=20eq=20'yes')=0A=20{=0A-=09= plan=20tests=20=3D>=2028;=0A+=09plan=20tests=20=3D>=2040;=0A=20}=0A=20= else=0A=20{=0Adiff=20--git=20a/src/test/perl/PostgreSQL/Test/Cluster.pm=20= b/src/test/perl/PostgreSQL/Test/Cluster.pm=0Aindex=20= 9467a199c8..2798ca8dd6=20100644=0A---=20= a/src/test/perl/PostgreSQL/Test/Cluster.pm=0A+++=20= b/src/test/perl/PostgreSQL/Test/Cluster.pm=0A@@=20-2142,8=20+2142,11=20= @@=20sub=20connect_ok=0A=20=0A=20=09if=20= (defined($params{expected_stdout}))=0A=20=09{=0A-=09=09like($stdout,=20= $params{expected_stdout},=20"$test_name:=20matches");=0A+=09=09= like($stdout,=20$params{expected_stdout},=20"$test_name:=20stdout=20= matches");=0A=20=09}=0A+=0A+=09is($stderr,=20"",=20"$test_name:=20no=20= stderr");=0A+=0A=20=09if=20(@log_like=20or=20@log_unlike)=0A=20=09{=0A=20= =09=09my=20$log_contents=20=3D=20= PostgreSQL::Test::Utils::slurp_file($self->logfile,=20$log_location);=0A= diff=20--git=20a/src/test/ssl/t/001_ssltests.pl=20= b/src/test/ssl/t/001_ssltests.pl=0Aindex=202fec9143c5..8daf499a35=20= 100644=0A---=20a/src/test/ssl/t/001_ssltests.pl=0A+++=20= b/src/test/ssl/t/001_ssltests.pl=0A@@=20-19,12=20+19,12=20@@=20my=20= $nss;=0A=20if=20($ENV{with_ssl}=20eq=20'openssl')=0A=20{=0A=20=09= $openssl=20=3D=201;=0A-=09plan=20tests=20=3D>=20112;=0A+=09plan=20tests=20= =3D>=20144;=0A=20}=0A=20elsif=20($ENV{with_ssl}=20eq=20'nss')=0A=20{=0A=20= =09$nss=20=3D=201;=0A-=09plan=20tests=20=3D>=20112;=0A+=09plan=20tests=20= =3D>=20138;=0A=20}=0A=20else=0A=20{=0Adiff=20--git=20= a/src/test/ssl/t/002_scram.pl=20b/src/test/ssl/t/002_scram.pl=0Aindex=20= f6a0a23390..9fdc7989ab=20100644=0A---=20a/src/test/ssl/t/002_scram.pl=0A= +++=20b/src/test/ssl/t/002_scram.pl=0A@@=20-27,13=20+27,13=20@@=20if=20= ($ENV{with_ssl}=20eq=20'openssl')=0A=20=09#=20Determine=20whether=20= build=20supports=20tls-server-end-point.=0A=20=09= $supports_tls_server_end_point=20=3D=0A=20=09=09check_pg_config("#define=20= HAVE_X509_GET_SIGNATURE_NID=201");=0A-=09plan=20tests=20=3D>=20= $supports_tls_server_end_point=20?=2011=20:=2012;=0A+=09plan=20tests=20= =3D>=2015;=0A=20}=0A=20elsif=20($ENV{with_ssl}=20eq=20'nss')=0A=20{=0A=20= =09$nss=20=3D=201;=0A=20=09$supports_tls_server_end_point=20=3D=201;=0A-=09= plan=20tests=20=3D>=2011;=0A+=09plan=20tests=20=3D>=2015;=0A=20}=0A=20= else=0A=20{=0A--=20=0A2.24.3=20(Apple=20Git-128)=0A=0A= --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F Content-Disposition: attachment; filename=v49-0005-nss-pg_strong_random-support.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v49-0005-nss-pg_strong_random-support.patch" Content-Transfer-Encoding: quoted-printable =46rom=201f099e22e60251a6357bda011609f5bf24863723=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:39=20+0100=0ASubject:=20[PATCH=20= v49=2005/10]=20nss:=20pg_strong_random=20support=0A=0AThis=20adds=20= support=20for=20using=20the=20RNG=20in=20libnss=20as=20a=20backend=20for=0A= pg_strong_random.=0A---=0A=20src/port/pg_strong_random.c=20|=2052=20= +++++++++++++++++++++++++++++++++++--=0A=201=20file=20changed,=2050=20= insertions(+),=202=20deletions(-)=0A=0Adiff=20--git=20= a/src/port/pg_strong_random.c=20b/src/port/pg_strong_random.c=0Aindex=20= 07f24c0089..29bcb796c8=20100644=0A---=20a/src/port/pg_strong_random.c=0A= +++=20b/src/port/pg_strong_random.c=0A@@=20-137,10=20+137,58=20@@=20= pg_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=20USE_OPENSSL=20or=20WIN32=20= */=0A+#elif=20defined(USE_NSS)=0A+=0A+#define=20pg_BITS_PER_BYTE=20= BITS_PER_BYTE=0A+#undef=20BITS_PER_BYTE=0A+#define=20NO_NSPR_10_SUPPORT=0A= +#include=20=0A+#include=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+void=0A= +pg_strong_random_init(void)=0A+{=0A+=09/*=20No=20initialization=20= needed=20on=20NSS=20*/=0A+}=0A+=0A+bool=0A+pg_strong_random(void=20*buf,=20= size_t=20len)=0A+{=0A+=09NSSInitParameters=20params;=0A+=09= NSSInitContext=20*nss_context;=0A+=09SECStatus=09status;=0A+=0A+=09= memset(¶ms,=200,=20sizeof(params));=0A+=09params.length=20=3D=20= sizeof(params);=0A+=09nss_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=20= NSS_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*=20Without=20= OpenSSL=20or=20Win32=20support,=20just=20read=20/dev/urandom=20= ourselves.=0A+=20*=20Without=20OpenSSL,=20NSS=20or=20Win32=20support,=20= just=20read=20/dev/urandom=20ourselves.=0A=20=20*/=0A=20=0A=20void=0A--=20= =0A2.24.3=20(Apple=20Git-128)=0A=0A= --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F Content-Disposition: attachment; filename=v49-0006-nss-Documentation.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v49-0006-nss-Documentation.patch" Content-Transfer-Encoding: quoted-printable =46rom=20faa35b6ff302febbabf01ad8b10196cd26a0b961=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:42=20+0100=0ASubject:=20[PATCH=20= v49=2006/10]=20nss:=20Documentation=0A=0ABasic=20documentation=20of=20= the=20new=20API=20(keypass=20hooks)=20as=20well=20as=20config=0A= parameters=20and=20installation.=20Additionally=20there=20is=20a=20= section=20on=20how=0Ato=20create=20certificate=20and=20keys=20using=20= the=20NSS=20toolchain.=0A---=0A=20doc/src/sgml/acronyms.sgml=20=20=20=20=20= |=20=2033=20++++=0A=20doc/src/sgml/config.sgml=20=20=20=20=20=20=20|=20=20= 30=20++-=0A=20doc/src/sgml/installation.sgml=20|=20=2034=20+++-=0A=20= doc/src/sgml/libpq.sgml=20=20=20=20=20=20=20=20|=20341=20= +++++++++++++++++++++++++--------=0A=20doc/src/sgml/runtime.sgml=20=20=20= =20=20=20|=20124=20+++++++++++-=0A=20src/backend/libpq/README.SSL=20=20=20= |=20=2028=20+++=0A=206=20files=20changed,=20497=20insertions(+),=2093=20= deletions(-)=0A=0Adiff=20--git=20a/doc/src/sgml/acronyms.sgml=20= b/doc/src/sgml/acronyms.sgml=0Aindex=209ed148ab84..4da20cb4d3=20100644=0A= ---=20a/doc/src/sgml/acronyms.sgml=0A+++=20b/doc/src/sgml/acronyms.sgml=0A= @@=20-452,6=20+452,28=20@@=0A=20=20=20=20=20=0A=20=20=20=20= =0A=20=0A+=20=20=20=0A+=20=20=20=20= NSPR=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= -550,6=20+572,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=0Adiff=20--git=20a/doc/src/sgml/config.sgml=20= b/doc/src/sgml/config.sgml=0Aindex=203f806740d5..ea964c67cc=20100644=0A= ---=20a/doc/src/sgml/config.sgml=0A+++=20b/doc/src/sgml/config.sgml=0A@@=20= -1310,6=20+1310,24=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=20ssl_database=20= (string)=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20ssl_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=0A+=20=20=20=20= =20=20=20=20SSL/TLS=0A+=20=20=20=20= =20=20=20=20connections.=20This=20parameter=20can=20only=20be=20set=20in=20= the=0A+=20=20=20=20=20=20=20=20postgresql.conf=20= file=20or=20on=20the=20server=20command=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-1326,7=20+1344,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-1538,8=20+1558,12=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.=20= This=20requires=20that=20the=20certificate=20database=20hasn't=0A+=20=20=20= =20=20=20=20=20been=20created=20with=20a=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=20the=20standard=20= output=20and=20exit=0Adiff=20--git=20a/doc/src/sgml/installation.sgml=20= b/doc/src/sgml/installation.sgml=0Aindex=20d38f9bc916..db44c415d0=20= 100644=0A---=20a/doc/src/sgml/installation.sgml=0A+++=20= b/doc/src/sgml/installation.sgml=0A@@=20-999,14=20+999,34=20@@=20= build-postgresql:=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=20Build=20with=20support=20= for=20SSL=20(encrypted)=0A-=20=20=20=20=20=20=20=20=20= connections.=20The=20only=20LIBRARY=0A-=20=20=20= =20=20=20=20=20=20supported=20is=20.=20This=20= requires=20the=0A-=20=20=20=20=20=20=20=20=20= OpenSSL=20package=20to=20be=20installed.=0A-=20= =20=20=20=20=20=20=20=20configure=20will=20check=20= for=20the=20required=0A-=20=20=20=20=20=20=20=20=20header=20files=20and=20= libraries=20to=20make=20sure=20that=20your=0A-=20=20=20=20=20=20=20=20=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= connections.=20LIBRARY=20must=20be=20one=20= of:=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=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=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.=0A+=20=20=20=20=20=20=20=20=20=20=20=20= Additionally,=20NSS=20requires=0A+=20=20=20=20= =20=20=20=20=20=20=20=20NSPR=20to=20be=20= installed.=20configure=0A+=20=20=20=20=20=20=20=20=20= =20=20=20will=20check=20for=20the=20required=20header=20files=20and=20= libraries=20to=20make=20sure=20that=20your=0A+=20=20=20=20=20=20=20=20=20= =20=20=20NSS=20installation=20is=20sufficient=20= before=0A+=20=20=20=20=20=20=20=20=20=20=20=20proceeding.=20On=20systems=20= where=20nss-config=0A+=20=20=20=20=20=20=20=20= =20=20=20=20is=20not=20installed=20in=20a=20location=20that=20is=20= searched=20by=20default,=20you=0A+=20=20=20=20=20=20=20=20=20=20=20=20= must=20use=20the=20option=20=20in=20= addition=0A+=20=20=20=20=20=20=20=20=20=20=20=20to=20this=20option=20to=20= indicate=20where=20the=20header=20files=20are=20located.=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=0A=20=20=20=20=20=20=20=20=0A= =20=20=20=20=20=20=20=0A=20=0Adiff=20--git=20= a/doc/src/sgml/libpq.sgml=20b/doc/src/sgml/libpq.sgml=0Aindex=20= c17d33a54f..29431ac076=20100644=0A---=20a/doc/src/sgml/libpq.sgml=0A+++=20= b/doc/src/sgml/libpq.sgml=0A@@=20-835,6=20+835,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=20has=20no=20effect=20= unless=0A+=20=20=20=20=20=20=20=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-851,6=20+857,70=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=20has=20no=20effect=20= unless=0A+=20=20=20=20=20=20=20=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=20has=20no=20effect=20= unless=0A+=20=20=20=20=20=20=20=20the=20server=20was=20compiled=20with=20= NSS=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=20has=20no=20effect=20= unless=20the=0A+=20=20=20=20=20=20=20=20server=20was=20compiled=20with=20= NSS=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-1643,23=20+1713,25=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20=20=20= If=20set=20to=201,=20data=20sent=20over=20SSL=20connections=20will=20be=20= compressed.=20=20If=0A=20=20=20=20=20=20=20=20=20set=20to=200,=20= compression=20will=20be=20disabled.=20=20The=20default=20is=200.=20=20= This=0A=20=20=20=20=20=20=20=20=20parameter=20is=20ignored=20if=20a=20= connection=20without=20SSL=20is=20made.=0A-=20=20=20=20=20=20=20=0A= -=0A-=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20=20SSL=20= compression=20is=20nowadays=20considered=20insecure=20and=20its=20use=20= is=20no=0A-=20=20=20=20=20=20=20=20longer=20recommended.=20=20= OpenSSL=201.1.0=20disables=0A-=20=20=20=20=20=20= =20=20compression=20by=20default,=20and=20many=20operating=20system=20= distributions=0A-=20=20=20=20=20=20=20=20disable=20it=20in=20prior=20= versions=20as=20well,=20so=20setting=20this=20parameter=20to=20on=0A-=20=20= =20=20=20=20=20=20will=20not=20have=20any=20effect=20if=20the=20server=20= does=20not=20accept=20compression.=0A-=20=20=20=20=20=20=20=20= PostgreSQL=2014=20disables=20compression=0A-=20= =20=20=20=20=20=20=20completely=20in=20the=20backend.=0A-=20=20=20=20=20=20= =20=0A+=20=20=20=20=20=20=20=20longer=20recommended.=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= OpenSSL:=201.1.0=20disables=20compression=20= by=0A+=20=20=20=20=20=20=20=20=20=20=20default,=20and=20many=20operating=20= system=20distributions=20disable=20it=20in=20prior=0A+=20=20=20=20=20=20=20= =20=20=20=20versions=20as=20well,=20so=20setting=20this=20parameter=20to=20= on=20will=20not=20have=20any=0A+=20=20=20=20=20=20=20=20=20=20=20effect=20= if=20the=20server=20does=20not=20accept=20compression.=0A+=20=20=20=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=0A=20=0A= -=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20=20=20If=20security=20= is=20not=20a=20primary=20concern,=20compression=20can=20improve=0A-=20=20= =20=20=20=20=20=20throughput=20if=20the=20network=20is=20the=20= bottleneck.=20=20Disabling=20compression=0A-=20=20=20=20=20=20=20=20can=20= improve=20response=20time=20and=20throughput=20if=20CPU=20performance=20= is=20the=0A-=20=20=20=20=20=20=20=20limiting=20factor.=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=20NSS:=20SSL=20= compression=20is=20not=20supported=20in=0A+=20=20=20=20=20=20=20=20=20=20= =20NSS,=20this=20parameter=20has=20no=20= effect.=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=0A=20=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A@@=20-1668,10=20+1740,24=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20= sslcert=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= This=20parameter=20specifies=20the=20file=20name=20of=20the=20client=20= SSL=0A-=20=20=20=20=20=20=20=20certificate,=20replacing=20the=20default=0A= -=20=20=20=20=20=20=20=20= ~/.postgresql/postgresql.crt.=0A-=20=20=20=20=20=20=20= =20This=20parameter=20is=20ignored=20if=20an=20SSL=20connection=20is=20= not=20made.=0A+=20=20=20=20=20=20=20=20This=20parameter=20specifies=20= the=20name=20or=20location=20of=20the=20client=20SSL=0A+=20=20=20=20=20=20= =20=20certificate.=20=20This=20parameter=20is=20ignored=20if=20an=20SSL=20= connection=20is=20not=0A+=20=20=20=20=20=20=20=20made.=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= OpenSSL:=20can=20replace=20the=20default=0A+=20= =20=20=20=20=20=20=20=20=20=20= ~/.postgresql/postgresql.crt.=0A+=20=20=20=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=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=20NSS:=20the=20= nickname=20of=20the=20client=20SSL=0A+=20=20=20=20=20=20=20=20=20=20=20= certificate.=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=0A=20=20=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20= =20=0A@@=20-1680,15=20+1766,30=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20= sslkey=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=20This=20= parameter=20specifies=20the=20location=20for=20the=20secret=20key=20used=20= for=0A-=20=20=20=20=20=20=20=20the=20client=20certificate.=20It=20can=20= either=20specify=20a=20file=20name=20that=20will=0A-=20=20=20=20=20=20=20= =20be=20used=20instead=20of=20the=20default=0A-=20=20=20=20=20=20=20=20= ~/.postgresql/postgresql.key,=20or=20it=20can=20= specify=20a=20key=0A-=20=20=20=20=20=20=20=20obtained=20from=20an=20= external=20engine=20(engines=20are=0A-=20=20=20=20=20=20=20= =20OpenSSL=20loadable=20modules).=20=20An=20= external=20engine=0A-=20=20=20=20=20=20=20=20specification=20should=20= consist=20of=20a=20colon-separated=20engine=20name=20and=0A-=20=20=20=20=20= =20=20=20an=20engine-specific=20key=20identifier.=20=20This=20parameter=20= is=20ignored=20if=20an=0A-=20=20=20=20=20=20=20=20SSL=20connection=20is=20= not=20made.=0A+=20=20=20=20=20=20=20=20This=20parameter=20specifies=20= the=20name=20or=20location=20for=20the=20secret=20key=20used=0A+=20=20=20= =20=20=20=20=20for=20the=20client=20certificate.=20This=20parameter=20is=20= ignored=20if=20an=20SSL=0A+=20=20=20=20=20=20=20=20connection=20is=20not=20= made.=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=20OpenSSL:=20can=20either=20= specify=20a=20file=20name=0A+=20=20=20=20=20=20=20=20=20=20=20that=20= will=20be=20used=20instead=20of=20the=20default=0A+=20=20=20=20=20=20=20=20= =20=20=20~/.postgresql/postgresql.key,=20or=20it=20= can=20specify=0A+=20=20=20=20=20=20=20=20=20=20=20a=20key=20obtained=20= from=20an=20external=20engine=20(engines=20are=0A+=20=20=20= =20=20=20=20=20=20=20=20OpenSSL=20loadable=20= modules).=20=20An=20external=0A+=20=20=20=20=20=20=20=20=20=20=20engine=20= specification=20should=20consist=20of=20a=20colon-separated=20engine=20= name=0A+=20=20=20=20=20=20=20=20=20=20=20and=20an=20engine-specific=20= key=20identifier.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=20=20=0A+=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= NSS:=20this=20parameter=20has=20no=20effect.=20= =20Keys=0A+=20=20=20=20=20=20=20=20=20=20=20should=20be=20loaded=20into=20= the=20NSS=0A+=20=20=20=20=20=20=20=20=20=20=20= database.=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=0A=20=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A@@=20-1699,28=20+1800,44=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20=20This=20parameter=20specifies=20the=20= password=20for=20the=20secret=20key=20specified=20in=0A=20=20=20=20=20=20= =20=20=20sslkey,=20allowing=20client=20certificate=20= private=20keys=0A-=20=20=20=20=20=20=20=20to=20be=20stored=20in=20= encrypted=20form=20on=20disk=20even=20when=20interactive=20passphrase=0A= +=20=20=20=20=20=20=20=20to=20be=20stored=20in=20encrypted=20form=20even=20= when=20interactive=20passphrase=0A=20=20=20=20=20=20=20=20=20input=20is=20= not=20practical.=0A-=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20=20= =0A-=20=20=20=20=20=20=20=20Specifying=20this=20parameter=20with=20= any=20non-empty=20value=20suppresses=20the=0A-=20=20=20=20=20=20=20=20= Enter=20PEM=20pass=20phrase:=0A-=20=20=20=20=20=20=20=20= prompt=20that=20OpenSSL=20will=20emit=20by=20= default=0A-=20=20=20=20=20=20=20=20when=20an=20encrypted=20client=20= certificate=20key=20is=20provided=20to=0A-=20=20=20=20=20=20=20=20= libpq.=0A-=20=20=20=20=20=20=20=0A-=20=20=20=20= =20=20=20=0A-=20=20=20=20=20=20=20=20If=20the=20key=20is=20not=20= encrypted=20this=20parameter=20is=20ignored.=20The=20parameter=0A-=20=20=20= =20=20=20=20=20has=20no=20effect=20on=20keys=20specified=20by=20= OpenSSL=0A-=20=20=20=20=20=20=20=20engines=20= unless=20the=20engine=20uses=20the=20OpenSSL=0A= -=20=20=20=20=20=20=20=20password=20callback=20mechanism=20for=20= prompts.=0A-=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20=20=0A= -=20=20=20=20=20=20=20=20There=20is=20no=20environment=20variable=20= equivalent=20to=20this=20option,=20and=20no=0A-=20=20=20=20=20=20=20=20= facility=20for=20looking=20it=20up=20in=20.pgpass.=20= It=20can=20be=0A-=20=20=20=20=20=20=20=20used=20in=20a=20service=20file=20= connection=20definition.=20Users=20with=0A-=20=20=20=20=20=20=20=20more=20= sophisticated=20uses=20should=20consider=20using=20= OpenSSL=20engines=20and=0A-=20=20=20=20=20=20=20= =20tools=20like=20PKCS#11=20or=20USB=20crypto=20offload=20devices.=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=20OpenSSL:=20specifying=20this=20= parameter=20with=0A+=20=20=20=20=20=20=20=20=20=20=20any=20non-empty=20= value=20suppresses=20the=0A+=20=20=20=20=20=20=20=20=20=20=20= Enter=20PEM=20pass=20phrase:=20prompt=20that=0A+=20=20= =20=20=20=20=20=20=20=20=20OpenSSL=20will=20= emit=20by=20default=20when=20an=0A+=20=20=20=20=20=20=20=20=20=20=20= encrypted=20client=20certificate=20key=20is=20provided=20to=0A+=20=20=20=20= =20=20=20=20=20=20=20libpq.=0A+=20=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=20If=20the=20key=20is=20not=20encrypted=20this=20parameter=20= is=20ignored.=20The=20parameter=0A+=20=20=20=20=20=20=20=20=20=20=20has=20= no=20effect=20on=20keys=20specified=20by=20= OpenSSL=0A+=20=20=20=20=20=20=20=20=20=20=20= engines=20unless=20the=20engine=20uses=20the=20= OpenSSL=0A+=20=20=20=20=20=20=20=20=20=20=20= password=20callback=20mechanism=20for=20prompts.=0A+=20=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=20There=20is=20no=20environment=20variable=20equivalent=20= to=20this=20option,=20and=20no=0A+=20=20=20=20=20=20=20=20=20=20=20= facility=20for=20looking=20it=20up=20in=20.pgpass.=20= It=20can=20be=0A+=20=20=20=20=20=20=20=20=20=20=20used=20in=20a=20= service=20file=20connection=20definition.=20Users=20with=0A+=20=20=20=20=20= =20=20=20=20=20=20more=20sophisticated=20uses=20should=20consider=20= using=0A+=20=20=20=20=20=20=20=20=20=20=20= OpenSSL=20engines=20and=20tools=20like=20= PKCS#11=20or=0A+=20=20=20=20=20=20=20=20=20=20=20USB=20crypto=20offload=20= devices.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20=20=0A+=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= NSS:=20specifying=20the=20parameter=20is=20= required=0A+=20=20=20=20=20=20=20=20=20=20=20in=20case=20any=20password=20= protected=20items=20are=20referenced=20in=20the=0A+=20=20=20=20=20=20=20=20= =20=20=20NSS=20database,=20or=20if=20the=20= database=20itself=0A+=20=20=20=20=20=20=20=20=20=20=20is=20password=20= protected.=20All=20attempts=20to=20decrypt=20objects=20which=20are=0A+=20= =20=20=20=20=20=20=20=20=20=20password=20protected=20in=20the=20database=20= will=20use=20this=20password.=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= =0A=20=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=0A@@=20-1729,11=20= +1846,27=20@@=20postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20= =20=20=20=20sslrootcert=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= =20This=20parameter=20specifies=20the=20name=20of=20a=20file=20= containing=20SSL=0A-=20=20=20=20=20=20=20=20certificate=20authority=20= (CA)=20certificate(s).=0A-=20=20=20=20=20=20=20=20If=20= the=20file=20exists,=20the=20server's=20certificate=20will=20be=20= verified=0A-=20=20=20=20=20=20=20=20to=20be=20signed=20by=20one=20of=20= these=20authorities.=20=20The=20default=20is=0A-=20=20=20=20=20=20=20=20= ~/.postgresql/root.crt.=0A+=20=20=20=20=20=20=20=20= This=20parameter=20specifies=20the=20name=20of=20SSL=20certificate=20= authority=0A+=20=20=20=20=20=20=20=20(CA)=20= certificate(s).=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=20OpenSSL:=20= specifies=20the=20name=20of=20a=20file=0A+=20=20=20=20=20=20=20=20=20=20=20= containing=20SSL=20certificate=20authority=20(CA)=0A+=20= =20=20=20=20=20=20=20=20=20=20certificate(s).=20=20If=20the=20file=20= exists,=20the=20server's=20certificate=20will=0A+=20=20=20=20=20=20=20=20= =20=20=20be=20verified=20to=20be=20signed=20by=20one=20of=20these=20= authorities.=20=20The=20default=20is=0A+=20=20=20=20=20=20=20=20=20=20=20= ~/.postgresql/root.crt.=0A+=20=20=20=20=20=20=20=20=20= =20=0A+=20=20=20=20=20=20=20=20=20=0A+=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=20NSS:=20this=20= parameter=20has=20no=20effect.=20=20CA=0A+=20=20=20=20=20=20=20=20=20=20=20= certificates=20should=20be=20loaded=20into=20the=20= NSS=0A+=20=20=20=20=20=20=20=20=20=20=20= database=20using=20the=20certutil=20tool.=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=0A=20=20=20=20=20=20= =20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A@@=20-1743,13=20+1876,29=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=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=20= This=20parameter=20specifies=20the=20file=20name=20of=20the=20SSL=20= certificate=0A-=20=20=20=20=20=20=20=20revocation=20list=20(CRL).=20=20= Certificates=20listed=20in=20this=20file,=20if=20it=0A-=20=20=20=20=20=20= =20=20exists,=20will=20be=20rejected=20while=20attempting=20to=20= authenticate=20the=0A-=20=20=20=20=20=20=20=20server's=20certificate.=20=20= If=20neither=0A-=20=20=20=20=20=20=20=20=20nor=0A-=20=20=20=20=20=20=20=20= =20is=20set,=20this=20= setting=20is=0A-=20=20=20=20=20=20=20=20taken=20as=0A-=20=20=20=20=20=20=20= =20~/.postgresql/root.crl.=0A+=20=20=20=20=20=20=20=20= revocation=20list=20(CRL).=20=20=0A+=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= OpenSSL:=20Certificates=20listed=20in=20this=20= file,=0A+=20=20=20=20=20=20=20=20=20=20=20if=20it=20exists,=20will=20be=20= rejected=20while=20attempting=20to=20authenticate=20the=0A+=20=20=20=20=20= =20=20=20=20=20=20server's=20certificate.=20=20If=20neither=0A+=20=20=20=20= =20=20=20=20=20=20=20=20nor=0A= +=20=20=20=20=20=20=20=20=20=20=20=20is=20set,=20this=20setting=20is=0A= +=20=20=20=20=20=20=20=20=20=20=20taken=20as=20= ~/.postgresql/root.crl.=20=0A+=20=20=20=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=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=20NSS:=20This=20= parameter=20has=20no=20effect.=20=20CRL=0A+=20=20=20=20=20=20=20=20=20=20= =20files=20should=20be=20loaded=20into=20the=20= NSS=0A+=20=20=20=20=20=20=20=20=20=20=20= database=20using=20the=20crlutil=20tool.=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=0A+=0A=20=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A@@=20-1762,19=20+1911,31=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20=20=20= revocation=20list=20(CRL).=20=20Certificates=20listed=20in=20the=20files=20= in=20this=0A=20=20=20=20=20=20=20=20=20directory,=20if=20it=20exists,=20= will=20be=20rejected=20while=20attempting=20to=0A=20=20=20=20=20=20=20=20= =20authenticate=20the=20server's=20certificate.=0A-=20=20=20=20=20=20=20= =0A=20=0A-=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20=20=20= The=20directory=20needs=20to=20be=20prepared=20with=20the=0A-=20=20=20=20= =20=20=20=20OpenSSL=20command=0A-=20=20=20=20=20= =20=20=20openssl=20rehash=20or=20= c_rehash.=20=20See=0A-=20=20=20=20=20=20=20=20its=20= documentation=20for=20details.=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=20=0A= +=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= OpenSSL:=20the=20directory=20needs=20to=20be=0A= +=20=20=20=20=20=20=20=20=20=20=20prepared=20with=20the=20= OpenSSL=20command=0A+=20=20=20=20=20=20=20=20=20= =20=20openssl=20rehash=20or=20= c_rehash.=0A+=20=20=20=20=20=20=20=20=20=20=20See=20= its=20documentation=20for=20details.=0A+=20=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=20Both=20sslcrl=20and=20= sslcrldir=20can=0A+=20=20=20=20=20=20=20=20=20=20=20= be=20specified=20together.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=20=20=0A=20=0A-=20=20=20=20=20=20=20=0A= -=20=20=20=20=20=20=20=20Both=20sslcrl=20and=20= sslcrldir=20can=20be=0A-=20=20=20=20=20=20=20=20= specified=20together.=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= NSS:=20This=20parameter=20has=20no=20effect.=20= =20CRL=0A+=20=20=20=20=20=20=20=20=20=20=20files=20should=20be=20loaded=20= into=20the=20NSS=0A+=20=20=20=20=20=20=20=20=20= =20=20database=20using=20the=20crlutil=20= tool.=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=0A=20=20=20=20=20= =20=20=20=0A+=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20= =20=0A=20=0A@@=20-1829,8=20+1990,8=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20=20=20= for=20the=20connection.=20Valid=20values=20are=20= TLSv1,=0A=20=20=20=20=20=20=20=20=20= TLSv1.1,=20TLSv1.2=20and=0A=20=20=20= =20=20=20=20=20=20TLSv1.3.=20The=20supported=20= protocols=20depend=20on=20the=0A-=20=20=20=20=20=20=20=20version=20of=20= OpenSSL=20used,=20older=20versions=0A-=20=20=20= =20=20=20=20=20not=20supporting=20the=20most=20modern=20protocol=20= versions.=20If=20not=20specified,=0A+=20=20=20=20=20=20=20=20version=20= of=20the=20SSL=20library=20used,=20older=20versions=20may=20=0A+=20=20=20= =20=20=20=20=20not=20support=20the=20most=20modern=20protocol=20= versions.=20If=20not=20specified,=0A=20=20=20=20=20=20=20=20=20the=20= default=20is=20TLSv1.2,=20which=20satisfies=20= industry=0A=20=20=20=20=20=20=20=20=20best=20practices=20as=20of=20this=20= writing.=0A=20=20=20=20=20=20=20=20=0A@@=20-1845,8=20+2006,8=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20=20=20= for=20the=20connection.=20Valid=20values=20are=20= TLSv1,=0A=20=20=20=20=20=20=20=20=20= TLSv1.1,=20TLSv1.2=20and=0A=20=20=20= =20=20=20=20=20=20TLSv1.3.=20The=20supported=20= protocols=20depend=20on=20the=0A-=20=20=20=20=20=20=20=20version=20of=20= OpenSSL=20used,=20older=20versions=0A-=20=20=20= =20=20=20=20=20not=20supporting=20the=20most=20modern=20protocol=20= versions.=20If=20not=20set,=20this=0A+=20=20=20=20=20=20=20=20version=20= of=20the=20SSL=20library=20used,=20older=20versions=0A+=20=20=20=20=20=20= =20=20may=20not=20support=20the=20most=20modern=20protocol=20versions.=20= If=20not=20set,=20this=0A=20=20=20=20=20=20=20=20=20parameter=20is=20= ignored=20and=20the=20connection=20will=20use=20the=20maximum=20bound=0A=20= =20=20=20=20=20=20=20=20defined=20by=20the=20backend,=20if=20set.=20= Setting=20the=20maximum=20protocol=20version=0A=20=20=20=20=20=20=20=20=20= is=20mainly=20useful=20for=20testing=20or=20if=20some=20component=20has=20= issues=20working=0A@@=20-2608,6=20+2769,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-2631,9=20+2794,15=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=20SSL=0A= +=20=20=20=20=20=20=20PRFileDesc=20associated=20with=20= the=20connection.=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=20used=20to=20= verify=20encryption=20levels,=20check=20server=0A+=20=20=20=20=20=20=20= certificates,=20and=20more.=20Refer=20to=20the=20SSL=20= library=0A+=20=20=20=20=20=20=20documentation=20for=20information=20= about=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-2660,6=20= +2829,10=20@@=20void=20*PQgetssl(const=20PGconn=20*conn);=0A=20=20=20=20=20= =20=20=20=20instead,=20and=20for=20= more=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=20This=20= function=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-8714,6=20+8887,12=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,=20no=20special=20initialization=20= is=0A+=20=20=20=20=20=20=20required=20for=20= NSS.=0A+=20=20=20=20=20=20=0A=20=20=20=20= =20=20=0A=20=20=20=20=20=0A=20=0A@@=20-8740,6=20= +8919,12=20@@=20void=20PQinitSSL(int=20do_ssl);=0A=20=20=20=20=20=20=20=20= might=20be=20preferable=20for=20applications=20that=20need=20to=20work=20= with=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,=20no=20special=20= initialization=20is=0A+=20=20=20=20=20=20=20required=20for=20= NSS.=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=2058150996b8..c61b4abb45=20100644=0A= ---=20a/doc/src/sgml/runtime.sgml=0A+++=20b/doc/src/sgml/runtime.sgml=0A= @@=20-2182,15=20+2182,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-2210,8=20+2216,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-2301,6=20+2312,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-2375,7=20= +2398,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-2422,6=20+2445,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-2445,7=20+2476,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-2549,6=20+2580,89=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=20requires=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=20= certutil=20with=20the=20-f=20= parameter.=0A+=20=20=20=20First=20create=20a=20self-signed=20CA.=20To=20= use=20a=20different=20certificate=20validity=0A+=20=20=20=20time=20than=20= the=20default,=20use=20-v=20to=20specify=20= the=0A+=20=20=20=20number=20of=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=20=0A+=20=20=0A+=0A=20=20=0A= =20=0A=20=20=0Adiff=20--git=20= a/src/backend/libpq/README.SSL=20b/src/backend/libpq/README.SSL=0Aindex=20= d84a434a6e..c0722b558d=20100644=0A---=20a/src/backend/libpq/README.SSL=0A= +++=20b/src/backend/libpq/README.SSL=0A@@=20-80,3=20+80,31=20@@=20are=20= unacceptable.=0A=20The=20downside=20to=20EDH=20is=20that=20it=20makes=20= it=20impossible=20to=20use=20ssldump(1)=0A=20if=20there's=20a=20problem=20= establishing=20an=20SSL=20session.=20=20In=20this=20case=20you'll=0A=20= need=20to=20temporarily=20disable=20EDH=20(see=20initialize_dh()).=0A+=0A= +=0A+Supporting=20a=20new=20TLS=20backend=0A= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=0A+=0A+TLS=20support=20in=20PostgreSQL=20is=20implemented=20= with=20an=20API=20which=20abstracts=20any=0A+knowledge=20about=20the=20= library=20used=20from=20core=20server=20backend=20and=20frontend=20code.=0A= +Adding=20support=20for=20a=20new=20TLS=20library=20can=20be=20done=20= almost=20without=20changing=20any=0A+core=20PostgreSQL=20code.=20The=20= modules=20which=20needs=20to=20be=20implemented=20are=20briefly=0A= +described=20below.=0A+=0A+Each=20supported=20TLS=20library=20is=20= implemented=20in=20its=20own=20file=20for=20the=20libpq=0A+frontend=20= and=20backend.=20The=20API=20is=20defined=20in=20be-secure.c=20and=20= fe-secure.c=0A+respectively.=20Each=20library=20can=20add=20relevant=20= connection=20structures=20to=20the=0A+Port=20and=20PGConn=20objects.=0A+=0A= +pg_cryptohash=20is=20an=20internal=20API=20for=20invoking=20= cryptographic=20hash=20algorithms=0A+on=20data.=20Each=20supported=20TLS=20= library=20implements=20the=20API=20defined=20in=20the=20header=0A= +common/cryptohash.h,=20with=20the=20implementation=20used=20decided=20= at=20build-time.=0A+=0A+pg_strong_random=20provide=20the=20backend=20= with=20a=20source=20of=20cryptographically=20secure=0A+random=20numbers.=0A= +=0A+contrib/sslinfo=20provide=20similar=20information=20to=20= pg_stat_ssl,=20with=20a=20few=20library=0A+specific=20extensions.=0A+=0A= +contrib/pgcrypto=20provide=20a=20larger=20selection=20of=20digest=20and=20= hash=20algorithms=0A+when=20compiled=20against=20a=20TLS=20library.=0A--=20= =0A2.24.3=20(Apple=20Git-128)=0A=0A= --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F Content-Disposition: attachment; filename=v49-0007-nss-Support-NSS-in-pgcrypto.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v49-0007-nss-Support-NSS-in-pgcrypto.patch" Content-Transfer-Encoding: quoted-printable =46rom=2088baafadb8af8950ff2364fd4a520c8a658f6d8d=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:45=20+0100=0ASubject:=20[PATCH=20= v49=2007/10]=20nss:=20Support=20NSS=20in=20pgcrypto=0A=0AThis=20extends=20= pgcrypto=20to=20be=20able=20to=20use=20libnss=20as=20a=20cryptographic=0A= backend=20for=20pgcrypto=20much=20like=20how=20OpenSSL=20is=20a=20= supported=20backend.=0ABlowfish=20is=20not=20a=20supported=20cipher=20in=20= NSS,=20so=20the=20implementation=0Afalls=20back=20on=20the=20built-in=20= BF=20code=20to=20be=20compatible=20in=20terms=20of=0Acipher=20support.=0A= ---=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=202=20+=0A=20= contrib/pgcrypto/expected/blowfish_2.out=20=20=20=20=20=20|=20=2095=20= +++=0A=20contrib/pgcrypto/expected/cast5_2.out=20=20=20=20=20=20=20=20=20= |=20=2048=20++=0A=20contrib/pgcrypto/expected/pgp-decrypt_2.out=20=20=20= |=20421=20++++++++++++=0A=20contrib/pgcrypto/expected/pgp-encrypt_1.out=20= =20=20|=20202=20++++++=0A=20.../expected/pgp-pubkey-decrypt_2.out=20=20=20= =20=20=20=20=20=20|=20632=20++++++++++++++++++=0A=20= .../expected/pgp-pubkey-encrypt_1.out=20=20=20=20=20=20=20=20=20|=20=20= 50=20++=0A=20contrib/pgcrypto/nss.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|=20601=20+++++++++++++++++=0A=20= contrib/pgcrypto/openssl.c=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=20contrib/pgcrypto/pgp-mpi-nss.c=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20|=20=2053=20++=0A=20= contrib/pgcrypto/pgp-mpi-openssl.c=20=20=20=20=20=20=20=20=20=20=20=20|=20= =20=203=20+=0A=20doc/src/sgml/pgcrypto.sgml=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20|=20=20=209=20+-=0A=2012=20files=20= changed,=202117=20insertions(+),=203=20deletions(-)=0A=20create=20mode=20= 100644=20contrib/pgcrypto/expected/blowfish_2.out=0A=20create=20mode=20= 100644=20contrib/pgcrypto/expected/cast5_2.out=0A=20create=20mode=20= 100644=20contrib/pgcrypto/expected/pgp-decrypt_2.out=0A=20create=20mode=20= 100644=20contrib/pgcrypto/expected/pgp-encrypt_1.out=0A=20create=20mode=20= 100644=20contrib/pgcrypto/expected/pgp-pubkey-decrypt_2.out=0A=20create=20= mode=20100644=20contrib/pgcrypto/expected/pgp-pubkey-encrypt_1.out=0A=20= create=20mode=20100644=20contrib/pgcrypto/nss.c=0A=20create=20mode=20= 100644=20contrib/pgcrypto/pgp-mpi-nss.c=0A=0Adiff=20--git=20= a/contrib/pgcrypto/Makefile=20b/contrib/pgcrypto/Makefile=0Aindex=20= 7fb59f51b7..645ba634a1=20100644=0A---=20a/contrib/pgcrypto/Makefile=0A= +++=20b/contrib/pgcrypto/Makefile=0A@@=20-12,6=20+12,7=20@@=20OBJS=20=3D=20= \=0A=20=09crypt-gensalt.o=20\=0A=20=09crypt-md5.o=20\=0A=20=09mbuf.o=20\=0A= +=09nss.o=20\=0A=20=09openssl.o=20\=0A=20=09pgcrypto.o=20\=0A=20=09= pgp-armor.o=20\=0A@@=20-21,6=20+22,7=20@@=20OBJS=20=3D=20\=0A=20=09= pgp-encrypt.o=20\=0A=20=09pgp-info.o=20\=0A=20=09pgp-mpi.o=20\=0A+=09= pgp-mpi-nss.o=20\=0A=20=09pgp-mpi-openssl.o=20\=0A=20=09pgp-pgsql.o=20\=0A= =20=09pgp-pubdec.o=20\=0Adiff=20--git=20= a/contrib/pgcrypto/expected/blowfish_2.out=20= b/contrib/pgcrypto/expected/blowfish_2.out=0Anew=20file=20mode=20100644=0A= index=200000000000..26f4485d04=0A---=20/dev/null=0A+++=20= b/contrib/pgcrypto/expected/blowfish_2.out=0A@@=20-0,0=20+1,95=20@@=0A= +--=0A+--=20Blowfish=20cipher=0A+--=0A+--=20ensure=20consistent=20test=20= output=20regardless=20of=20the=20default=20bytea=20format=0A+SET=20= bytea_output=20TO=20escape;=0A+--=20some=20standard=20Blowfish=20= testvalues=0A+SELECT=20encode(encrypt(=0A+decode('0000000000000000',=20= 'hex'),=0A+decode('0000000000000000',=20'hex'),=0A+'bf-ecb/pad:none'),=20= 'hex');=0A+ERROR:=20=20Cannot=20use=20"bf-ecb/pad:none":=20No=20such=20= cipher=20algorithm=0A+SELECT=20encode(encrypt(=0A= +decode('ffffffffffffffff',=20'hex'),=0A+decode('ffffffffffffffff',=20= 'hex'),=0A+'bf-ecb/pad:none'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20= "bf-ecb/pad:none":=20No=20such=20cipher=20algorithm=0A+SELECT=20= encode(encrypt(=0A+decode('1000000000000001',=20'hex'),=0A= +decode('3000000000000000',=20'hex'),=0A+'bf-ecb/pad:none'),=20'hex');=0A= +ERROR:=20=20Cannot=20use=20"bf-ecb/pad:none":=20No=20such=20cipher=20= algorithm=0A+SELECT=20encode(encrypt(=0A+decode('1111111111111111',=20= 'hex'),=0A+decode('1111111111111111',=20'hex'),=0A+'bf-ecb/pad:none'),=20= 'hex');=0A+ERROR:=20=20Cannot=20use=20"bf-ecb/pad:none":=20No=20such=20= cipher=20algorithm=0A+SELECT=20encode(encrypt(=0A= +decode('0123456789abcdef',=20'hex'),=0A+decode('fedcba9876543210',=20= 'hex'),=0A+'bf-ecb/pad:none'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20= "bf-ecb/pad:none":=20No=20such=20cipher=20algorithm=0A+SELECT=20= encode(encrypt(=0A+decode('01a1d6d039776742',=20'hex'),=0A= +decode('fedcba9876543210',=20'hex'),=0A+'bf-ecb/pad:none'),=20'hex');=0A= +ERROR:=20=20Cannot=20use=20"bf-ecb/pad:none":=20No=20such=20cipher=20= algorithm=0A+SELECT=20encode(encrypt(=0A+decode('ffffffffffffffff',=20= 'hex'),=0A+decode('0000000000000000',=20'hex'),=0A+'bf-ecb/pad:none'),=20= 'hex');=0A+ERROR:=20=20Cannot=20use=20"bf-ecb/pad:none":=20No=20such=20= cipher=20algorithm=0A+--=20setkey=0A+SELECT=20encode(encrypt(=0A= +decode('fedcba9876543210',=20'hex'),=0A= +decode('f0e1d2c3b4a5968778695a4b3c2d1e0f',=20'hex'),=0A= +'bf-ecb/pad:none'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20= "bf-ecb/pad:none":=20No=20such=20cipher=20algorithm=0A+--=20with=20= padding=0A+SELECT=20encode(encrypt(=0A+decode('01234567890123456789',=20= 'hex'),=0A+decode('33443344334433443344334433443344',=20'hex'),=0A= +'bf-ecb'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20"bf-ecb":=20No=20= such=20cipher=20algorithm=0A+--=20cbc=0A+--=2028=20bytes=20key=0A+SELECT=20= encode(encrypt(=0A= +decode('6b77b4d63006dee605b156e27403979358deb9e7154616d959f1652bd5',=20= 'hex'),=0A= +decode('37363534333231204e6f77206973207468652074696d6520666f7220',=20= 'hex'),=0A+'bf-cbc'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20"bf-cbc":=20= No=20such=20cipher=20algorithm=0A+--=2029=20bytes=20key=0A+SELECT=20= encode(encrypt(=0A= +decode('6b77b4d63006dee605b156e27403979358deb9e7154616d959f1652bd5ff92cc'= ,=20'hex'),=0A= +decode('37363534333231204e6f77206973207468652074696d6520666f722000',=20= 'hex'),=0A+'bf-cbc'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20"bf-cbc":=20= No=20such=20cipher=20algorithm=0A+--=20blowfish-448=0A+SELECT=20= encode(encrypt(=0A+decode('fedcba9876543210',=20'hex'),=0A= +decode('f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455667704689104c2fd3b2f5= 84023641aba61761f1f1f1f0e0e0e0effffffffffffffff',=20'hex'),=0A= +'bf-ecb/pad:none'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20= "bf-ecb/pad:none":=20No=20such=20cipher=20algorithm=0A+--=20result:=20= c04504012e4e1f53=0A+--=20empty=20data=0A+select=20encode(encrypt('',=20= 'foo',=20'bf'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20"bf":=20No=20= such=20cipher=20algorithm=0A+--=2010=20bytes=20key=0A+select=20= encode(encrypt('foo',=20'0123456789',=20'bf'),=20'hex');=0A+ERROR:=20=20= Cannot=20use=20"bf":=20No=20such=20cipher=20algorithm=0A+--=2022=20bytes=20= key=0A+select=20encode(encrypt('foo',=20'0123456789012345678901',=20= 'bf'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20"bf":=20No=20such=20= cipher=20algorithm=0A+--=20decrypt=0A+select=20decrypt(encrypt('foo',=20= '0123456',=20'bf'),=20'0123456',=20'bf');=0A+ERROR:=20=20Cannot=20use=20= "bf":=20No=20such=20cipher=20algorithm=0A+--=20iv=0A+select=20= encode(encrypt_iv('foo',=20'0123456',=20'abcd',=20'bf'),=20'hex');=0A= +ERROR:=20=20Cannot=20use=20"bf":=20No=20such=20cipher=20algorithm=0A= +select=20decrypt_iv(decode('95c7e89322525d59',=20'hex'),=20'0123456',=20= 'abcd',=20'bf');=0A+ERROR:=20=20Cannot=20use=20"bf":=20No=20such=20= cipher=20algorithm=0A+--=20long=20message=0A+select=20= encode(encrypt('Lets=20try=20a=20longer=20message.',=20'0123456789',=20= 'bf'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20"bf":=20No=20such=20= cipher=20algorithm=0A+select=20decrypt(encrypt('Lets=20try=20a=20longer=20= message.',=20'0123456789',=20'bf'),=20'0123456789',=20'bf');=0A+ERROR:=20= =20Cannot=20use=20"bf":=20No=20such=20cipher=20algorithm=0Adiff=20--git=20= a/contrib/pgcrypto/expected/cast5_2.out=20= b/contrib/pgcrypto/expected/cast5_2.out=0Anew=20file=20mode=20100644=0A= index=200000000000..dd5e92b869=0A---=20/dev/null=0A+++=20= b/contrib/pgcrypto/expected/cast5_2.out=0A@@=20-0,0=20+1,48=20@@=0A+--=0A= +--=20Cast5=20cipher=0A+--=0A+--=20ensure=20consistent=20test=20output=20= regardless=20of=20the=20default=20bytea=20format=0A+SET=20bytea_output=20= TO=20escape;=0A+--=20test=20vectors=20from=20RFC2144=0A+--=20128=20bit=20= key=0A+SELECT=20encode(encrypt(=0A+decode('01=2023=2045=2067=2089=20AB=20= CD=20EF',=20'hex'),=0A+decode('01=2023=2045=2067=2012=2034=2056=2078=20= 23=2045=2067=2089=2034=2056=2078=209A',=20'hex'),=0A= +'cast5-ecb/pad:none'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20= "cast5-ecb/pad:none":=20No=20such=20cipher=20algorithm=0A+--=20result:=20= 23=208B=204F=20E5=2084=207E=2044=20B2=0A+--=2080=20bit=20key=0A+SELECT=20= encode(encrypt(=0A+decode('01=2023=2045=2067=2089=20AB=20CD=20EF',=20= 'hex'),=0A+decode('01=2023=2045=2067=2012=2034=2056=2078=2023=2045',=20= 'hex'),=0A+'cast5-ecb/pad:none'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20= "cast5-ecb/pad:none":=20No=20such=20cipher=20algorithm=0A+--=20result:=20= EB=206A=2071=201A=202C=2002=2027=201B=0A+--=2040=20bit=20key=0A+SELECT=20= encode(encrypt(=0A+decode('01=2023=2045=2067=2089=20AB=20CD=20EF',=20= 'hex'),=0A+decode('01=2023=2045=2067=2012',=20'hex'),=0A= +'cast5-ecb/pad:none'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20= "cast5-ecb/pad:none":=20No=20such=20cipher=20algorithm=0A+--=20result:=20= 7A=20C8=2016=20D1=206E=209B=2030=202E=0A+--=20cbc=0A+--=20empty=20data=0A= +select=20encode(=09encrypt('',=20'foo',=20'cast5'),=20'hex');=0A+ERROR:=20= =20Cannot=20use=20"cast5":=20No=20such=20cipher=20algorithm=0A+--=2010=20= bytes=20key=0A+select=20encode(=09encrypt('foo',=20'0123456789',=20= 'cast5'),=20'hex');=0A+ERROR:=20=20Cannot=20use=20"cast5":=20No=20such=20= cipher=20algorithm=0A+--=20decrypt=0A+select=20decrypt(encrypt('foo',=20= '0123456',=20'cast5'),=20'0123456',=20'cast5');=0A+ERROR:=20=20Cannot=20= use=20"cast5":=20No=20such=20cipher=20algorithm=0A+--=20iv=0A+select=20= encode(encrypt_iv('foo',=20'0123456',=20'abcd',=20'cast5'),=20'hex');=0A= +ERROR:=20=20Cannot=20use=20"cast5":=20No=20such=20cipher=20algorithm=0A= +select=20decrypt_iv(decode('384a970695ce016a',=20'hex'),=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20'0123456',=20'abcd',=20'cast5');=0A= +ERROR:=20=20Cannot=20use=20"cast5":=20No=20such=20cipher=20algorithm=0A= +--=20long=20message=0A+select=20encode(encrypt('Lets=20try=20a=20longer=20= message.',=20'0123456789',=20'cast5'),=20'hex');=0A+ERROR:=20=20Cannot=20= use=20"cast5":=20No=20such=20cipher=20algorithm=0A+select=20= decrypt(encrypt('Lets=20try=20a=20longer=20message.',=20'0123456789',=20= 'cast5'),=20'0123456789',=20'cast5');=0A+ERROR:=20=20Cannot=20use=20= "cast5":=20No=20such=20cipher=20algorithm=0Adiff=20--git=20= a/contrib/pgcrypto/expected/pgp-decrypt_2.out=20= b/contrib/pgcrypto/expected/pgp-decrypt_2.out=0Anew=20file=20mode=20= 100644=0Aindex=200000000000..0b5414020c=0A---=20/dev/null=0A+++=20= b/contrib/pgcrypto/expected/pgp-decrypt_2.out=0A@@=20-0,0=20+1,421=20@@=0A= +--=0A+--=20pgp=20decrypt=20tests=0A+--=0A+--=20=20Checking=20ciphers=0A= +select=20pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A= +Comment:=20dat1.blowfish.sha1.mdc.s2k3.z0=0A+=0A= +jA0EBAMCfFNwxnvodX9g0jwB4n4s26/g5VmKzVab1bX1SmwY7gvgvlWdF3jKisvS=0A= +yA6Ce1QTMK3KdL2MPfamsTUSAML8huCJMwYQFfE=3D=0A+=3DJcP+=0A+-----END=20PGP=20= MESSAGE-----=0A+'),=20'foobar');=0A+ERROR:=20=20Unsupported=20cipher=20= algorithm=0A+select=20pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20= MESSAGE-----=0A+Comment:=20dat1.aes.sha1.mdc.s2k3.z0=0A+=0A= +jA0EBwMCci97v0Q6Z0Zg0kQBsVf5Oe3iC+FBzUmuMV9KxmAyOMyjCc/5i8f1Eest=0A= +UTAsG35A1vYs02VARKzGz6xI2UHwFUirP+brPBg3Ee7muOx8pA=3D=3D=0A+=3DXtrP=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20= =0A+-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes192.sha1.mdc.s2k3.z0=0A+=0A= +jA0ECAMCI7YQpWqp3D1g0kQBCjB7GlX7+SQeXNleXeXQ78ZAPNliquGDq9u378zI=0A= +5FPTqAhIB2/2fjY8QEIs1ai00qphjX2NitxV/3Wn+6dufB4Q4g=3D=3D=0A+=3DrCZt=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20= =0A+-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes256.sha1.mdc.s2k3.z0=0A+=0A= +jA0ECQMC4f/5djqCC1Rg0kQBTHEPsD+Sw7biBsM2er3vKyGPAQkuTBGKC5ie7hT/=0A= +lceMfQdbAg6oTFyJpk/wH18GzRDphCofg0X8uLgkAKMrpcmgog=3D=3D=0A+=3DfB6S=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20= =0A+-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+--=20= Checking=20MDC=20modes=0A+select=20pgp_sym_decrypt(dearmor('=0A= +-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes.sha1.nomdc.s2k3.z0=0A+=0A= +jA0EBwMCnv07rlXqWctgyS2Dm2JfOKCRL4sLSLJUC8RS2cH7cIhKSuLitOtyquB+=0A= +u9YkgfJfsuRJmgQ9tmo=3D=0A+=3D60ui=0A+-----END=20PGP=20MESSAGE-----=0A= +'),=20'foobar');=0A+=20pgp_sym_decrypt=20=0A+-----------------=0A+=20= Secret=20message.=0A+(1=20row)=0A+=0A+select=20pgp_sym_decrypt(dearmor('=0A= +-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20dat1.aes.sha1.mdc.s2k3.z0=0A= +=0A+jA0EBwMCEeP3idNjQ1Bg0kQBf4G0wX+2QNzLh2YNwYkQgQkfYhn/hLXjV4nK9nsE=0A= +8Ex1Dsdt5UPvOz8W8VKQRS6loOfOe+yyXil8W3IYFwUpdDUi+Q=3D=3D=0A+=3DmoGf=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20= =0A+-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+--=20= Checking=20hashes=0A+select=20pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20= PGP=20MESSAGE-----=0A+Comment:=20dat1.aes.md5.mdc.s2k3.z0=0A+=0A= +jA0EBwMClrXXtOXetohg0kQBn0Kl1ymevQZRHkdoYRHgzCwSQEiss7zYff2UNzgO=0A= +KyRrHf7zEBuZiZ2AG34jNVMOLToj1jJUg5zTSdecUzQVCykWTA=3D=3D=0A+=3DNyLk=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20= =0A+-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes.sha1.mdc.s2k3.z0=0A+=0A= +jA0EBwMCApbdlrURoWJg0kQBzHM/E0o7djY82bNuspjxjAcPFrrtp0uvDdMQ4z2m=0A= +/PM8jhgI5vxFYfNQjLl8y3fHYIomk9YflN9K/Q13iq8A8sjeTw=3D=3D=0A+=3DFxbQ=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20= =0A+-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+--=20= Checking=20S2K=20modes=0A+select=20pgp_sym_decrypt(dearmor('=0A= +-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20dat1.aes.sha1.mdc.s2k0.z0=0A= +=0A+jAQEBwAC0kQBKTaLAKE3xzps+QIZowqRNb2eAdzBw2LxEW2YD5PgNlbhJdGg+dvw=0A= +Ah9GXjGS1TVALzTImJbz1uHUZRfhJlFbc5yGQw=3D=3D=0A+=3DYvkV=0A+-----END=20= PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20=0A= +-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes.sha1.mdc.s2k1.z0=0A+=0A= +jAwEBwEC/QTByBLI3b/SRAHPxKzI6SZBo5lAEOD+EsvKQWO4adL9tDY+++Iqy1xK=0A= +4IaWXVKEj9R2Lr2xntWWMGZtcKtjD2lFFRXXd9dZp1ZThNDz=0A+=3DdbXm=0A+-----END=20= PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20=0A= +-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes.sha1.mdc.s2k3.z0=0A+=0A= +jA0EBwMCEq4Su3ZqNEJg0kQB4QG5jBTKF0i04xtH+avzmLhstBNRxvV3nsmB3cwl=0A= +z+9ZaA/XdSx5ZiFnMym8P6r8uY9rLjjNptvvRHlxIReF+p9MNg=3D=3D=0A+=3DVJKg=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20= =0A+-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes192.sha1.mdc.s2k0.z0=0A+=0A= +jAQECAAC0kQBBDnQWkgsx9YFaqDfWmpsiyAJ6y2xG/sBvap1dySYEMuZ+wJTXQ9E=0A= +Cr3i2M7TgVZ0M4jp4QL0adG1lpN5iK7aQeOwMw=3D=3D=0A+=3Dcg+i=0A+-----END=20= PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20=0A= +-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes192.sha1.mdc.s2k1.z0=0A+=0A= +jAwECAECruOfyNDFiTnSRAEVoGXm4A9UZKkWljdzjEO/iaE7mIraltIpQMkiqCh9=0A= +7h8uZ2u9uRBOv222fZodGvc6bvq/4R4hAa/6qSHtm8mdmvGt=0A+=3DaHmC=0A+-----END=20= PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20=0A= +-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes192.sha1.mdc.s2k3.z0=0A+=0A= +jA0ECAMCjFn6SRi3SONg0kQBqtSHPaD0m7rXfDAhCWU/ypAsI93GuHGRyM99cvMv=0A= +q6eF6859ZVnli3BFSDSk3a4e/pXhglxmDYCfjAXkozKNYLo6yw=3D=3D=0A+=3DK0LS=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20= =0A+-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes256.sha1.mdc.s2k0.z0=0A+=0A= +jAQECQAC0kQB4L1eMbani07XF2ZYiXNK9LW3v8w41oUPl7dStmrJPQFwsdxmrDHu=0A= +rQr3WbdKdY9ufjOE5+mXI+EFkSPrF9rL9NCq6w=3D=3D=0A+=3DRGts=0A+-----END=20= PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20=0A= +-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes256.sha1.mdc.s2k1.z0=0A+=0A= +jAwECQECKHhrou7ZOIXSRAHWIVP+xjVQcjAVBTt+qh9SNzYe248xFTwozkwev3mO=0A= ++KVJW0qhk0An+Y2KF99/bYFl9cL5D3Tl43fC8fXGl3x3m7pR=0A+=3DSUrU=0A+-----END=20= PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20=0A= +-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20= dat1.aes256.sha1.mdc.s2k3.z0=0A+=0A= +jA0ECQMCjc8lwZu8Fz1g0kQBkEzjImi21liep5jj+3dAJ2aZFfUkohi8b3n9z+7+=0A= +4+NRzL7cMW2RLAFnJbiqXDlRHMwleeuLN1up2WIxsxtYYuaBjA=3D=3D=0A+=3DXZrG=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'foobar');=0A+=20pgp_sym_decrypt=20= =0A+-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+--=20= Checking=20longer=20passwords=0A+select=20pgp_sym_decrypt(dearmor('=0A= +-----BEGIN=20PGP=20MESSAGE-----=0A+Comment:=20dat1.aes.sha1.mdc.s2k3.z0=0A= +=0A+jA0EBwMCx6dBiuqrYNRg0kQBEo63AvA1SCslxP7ayanLf1H0/hlk2nONVhTwVEWi=0A= +tTGup1mMz6Cfh1uDRErUuXpx9A0gdMu7zX0o5XjrL7WGDAZdSw=3D=3D=0A+=3DXKKG=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'0123456789abcdefghij');=0A+=20= pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret=20message.=0A+(1=20= row)=0A+=0A+select=20pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20= MESSAGE-----=0A+Comment:=20dat1.aes.sha1.mdc.s2k3.z0=0A+=0A= +jA0EBwMCBDvYuS990iFg0kQBW31UK5OiCjWf5x6KJ8qNNT2HZWQCjCBZMU0XsOC6=0A= +CMxFKadf144H/vpoV9GA0f22keQgCl0EsTE4V4lweVOPTKCMJg=3D=3D=0A+=3DgWDh=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20= '0123456789abcdefghij2jk4h5g2j54khg23h54g2kh54g2khj54g23hj54');=0A+=20= pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret=20message.=0A+(1=20= row)=0A+=0A+select=20pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20= MESSAGE-----=0A+Comment:=20dat1.aes.sha1.mdc.s2k3.z0=0A+=0A= +jA0EBwMCqXbFafC+ofVg0kQBejyiPqH0QMERVGfmPOjtAxvyG5KDIJPYojTgVSDt=0A= +FwsDabdQUz5O7bgNSnxfmyw1OifGF+W2bIn/8W+0rDf8u3+O+Q=3D=3D=0A+=3DOxOF=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'x');=0A+=20pgp_sym_decrypt=20=0A= +-----------------=0A+=20Secret=20message.=0A+(1=20row)=0A+=0A+--=20= Checking=20various=20data=0A+select=20= encode(digest(pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20= MESSAGE-----=0A+Comment:=20dat1.aes.sha1.mdc.s2k3.z0=0A+=0A= +jA0EBwMCGJ+SpuOysINg0kQBJfSjzsW0x4OVcAyr17O7FBvMTwIGeGcJd99oTQU8=0A= +Xtx3kDqnhUq9Z1fS3qPbi5iNP2A9NxOBxPWz2JzxhydANlgbxg=3D=3D=0A+=3DW/ik=0A= +-----END=20PGP=20MESSAGE-----=0A+'),=20'0123456789abcdefghij'),=20= 'sha1'),=20'hex');=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20encode=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=0A= +------------------------------------------=0A+=20= 0225e3ede6f2587b076d021a189ff60aad67e066=0A+(1=20row)=0A+=0A+--=20= expected:=200225e3ede6f2587b076d021a189ff60aad67e066=0A+select=20= encode(digest(pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20= MESSAGE-----=0A+Comment:=20dat2.aes.sha1.mdc.s2k3.z0=0A+=0A= +jA0EBwMCvdpDvidNzMxg0jUBvj8eS2+1t/9/zgemxvhtc0fvdKGGbjH7dleaTJRB=0A= +SaV9L04ky1qECNDx3XjnoKLC+H7IOQ=3D=3D=0A+=3DFxen=0A+-----END=20PGP=20= MESSAGE-----=0A+'),=20'0123456789abcdefghij'),=20'sha1'),=20'hex');=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20encode=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=0A= +------------------------------------------=0A+=20= da39a3ee5e6b4b0d3255bfef95601890afd80709=0A+(1=20row)=0A+=0A+--=20= expected:=20da39a3ee5e6b4b0d3255bfef95601890afd80709=0A+select=20= encode(digest(pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20= MESSAGE-----=0A+Comment:=20dat3.aes.sha1.mdc.s2k3.z0=0A+=0A= +jA0EBwMCxQvxJZ3G/HRg0lgBeYmTa7/uDAjPyFwSX4CYBgpZWVn/JS8JzILrcWF8=0A= +gFnkUKIE0PSaYFp+Yi1VlRfUtRQ/X/LYNGa7tWZS+4VQajz2Xtz4vUeAEiYFYPXk=0A= +73Hb8m1yRhQK=0A+=3DivrD=0A+-----END=20PGP=20MESSAGE-----=0A+'),=20= '0123456789abcdefghij'),=20'sha1'),=20'hex');=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20encode=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=0A+------------------------------------------=0A+=20= 5e5c135efc0dd00633efc6dfd6e731ea408a5b4c=0A+(1=20row)=0A+=0A+--=20= expected:=205e5c135efc0dd00633efc6dfd6e731ea408a5b4c=0A+--=20Checking=20= CRLF=0A+select=20encode(digest(pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20= PGP=20MESSAGE-----=0A+Comment:=20crlf=20mess=0A+=0A= +ww0ECQMCt7VAtby6l4Bi0lgB5KMIZiiF/b3CfMfUyY0eDncsGXtkbu1X+l9brjpMP8eJnY79A= mms=0A+a3nsOzKTXUfS9VyaXo8IrncM6n7fdaXpwba/3tNsAhJG4lDv1k4g9v8Ix2dfv6Rs=0A= +=3DmBP9=0A+-----END=20PGP=20MESSAGE-----=0A+'),=20'key',=20= 'convert-crlf=3D0'),=20'sha1'),=20'hex');=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20encode=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=0A+------------------------------------------=0A+=20= 9353062be7720f1446d30b9e75573a4833886784=0A+(1=20row)=0A+=0A+--=20= expected:=209353062be7720f1446d30b9e75573a4833886784=0A+select=20= encode(digest(pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20= MESSAGE-----=0A+Comment:=20crlf=20mess=0A+=0A= +ww0ECQMCt7VAtby6l4Bi0lgB5KMIZiiF/b3CfMfUyY0eDncsGXtkbu1X+l9brjpMP8eJnY79A= mms=0A+a3nsOzKTXUfS9VyaXo8IrncM6n7fdaXpwba/3tNsAhJG4lDv1k4g9v8Ix2dfv6Rs=0A= +=3DmBP9=0A+-----END=20PGP=20MESSAGE-----=0A+'),=20'key',=20= 'convert-crlf=3D1'),=20'sha1'),=20'hex');=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20encode=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=0A+------------------------------------------=0A+=20= 7efefcab38467f7484d6fa43dc86cf5281bd78e2=0A+(1=20row)=0A+=0A+--=20= expected:=207efefcab38467f7484d6fa43dc86cf5281bd78e2=0A+--=20check=20BUG=20= #11905,=20problem=20with=20messages=206=20less=20than=20a=20power=20of=20= 2.=0A+select=20= pgp_sym_decrypt(pgp_sym_encrypt(repeat('x',65530),'1'),'1')=20=3D=20= repeat('x',65530);=0A+=20?column?=20=0A+----------=0A+=20t=0A+(1=20row)=0A= +=0A+--=20expected:=20true=0A+--=20Negative=20tests=0A+--=20Decryption=20= with=20a=20certain=20incorrect=20key=20yields=20an=20apparent=20Literal=20= Data=0A+--=20packet=20reporting=20its=20content=20to=20be=20binary=20= data.=20=20Ciphertext=20source:=0A+--=20iterative=20= pgp_sym_encrypt('secret',=20'key')=20until=20the=20random=20prefix=20= gave=0A+--=20rise=20to=20that=20property.=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+=0A= +ww0EBwMCxf8PTrQBmJdl0jcB6y2joE7GSLKRv7trbNsF5Z8ou5NISLUg31llVH/S0B2wl4bvz= ZjV=0A+VsxxqLSPzNLAeIspJk5G=0A+=3DmSd/=0A+-----END=20PGP=20MESSAGE-----=0A= +'),=20'wrong-key',=20'debug=3D1');=0A+NOTICE:=20=20dbg:=20prefix_init:=20= corrupt=20prefix=0A+NOTICE:=20=20dbg:=20parse_literal_data:=20data=20= type=3Db=0A+NOTICE:=20=20dbg:=20mdcbuf_finish:=20bad=20MDC=20pkt=20hdr=0A= +ERROR:=20=20Wrong=20key=20or=20corrupt=20data=0A+--=20Routine=20= text/binary=20mismatch.=0A+select=20= pgp_sym_decrypt(pgp_sym_encrypt_bytea('P',=20'key'),=20'key',=20= 'debug=3D1');=0A+NOTICE:=20=20dbg:=20parse_literal_data:=20data=20type=3Db= =0A+ERROR:=20=20Not=20text=20data=0A+--=20Decryption=20with=20a=20= certain=20incorrect=20key=20yields=20an=20apparent=20BZip2-compressed=0A= +--=20plaintext.=20=20Ciphertext=20source:=20iterative=20= pgp_sym_encrypt('secret',=20'key')=0A+--=20until=20the=20random=20prefix=20= gave=20rise=20to=20that=20property.=0A+select=20= pgp_sym_decrypt(dearmor('=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+=0A= +ww0EBwMC9rK/dMkF5Zlt0jcBlzAQ1mQY2qYbKYbw8h3EZ5Jk0K2IiY92R82TRhWzBIF/8cmXD= PtP=0A+GXsd65oYJZp3Khz0qfyn=0A+=3DNmpq=0A+-----END=20PGP=20MESSAGE-----=0A= +'),=20'wrong-key',=20'debug=3D1');=0A+NOTICE:=20=20dbg:=20prefix_init:=20= corrupt=20prefix=0A+NOTICE:=20=20dbg:=20parse_compressed_data:=20bzip2=20= unsupported=0A+NOTICE:=20=20dbg:=20mdcbuf_finish:=20bad=20MDC=20pkt=20= hdr=0A+ERROR:=20=20Wrong=20key=20or=20corrupt=20data=0A+--=20Routine=20= use=20of=20BZip2=20compression.=20=20Ciphertext=20source:=0A+--=20echo=20= x=20|=20gpg=20--homedir=20/nonexistent=20--personal-compress-preferences=20= bzip2=20\=0A+--=20=20=20=20=20=20--personal-cipher-preferences=20aes=20= --no-emit-version=20--batch=20\=0A+--=20=20=20=20=20=20--symmetric=20= --passphrase=20key=20--armor=0A+select=20pgp_sym_decrypt(dearmor('=0A= +-----BEGIN=20PGP=20MESSAGE-----=0A+=0A= +jA0EBwMCRhFrAKNcLVJg0mMBLJG1cCASNk/x/3dt1zJ+2eo7jHfjgg3N6wpB3XIe=0A= +QCwkWJwlBG5pzbO5gu7xuPQN+TbPJ7aQ2sLx3bAHhtYb0i3vV9RO10Gw++yUyd4R=0A= +UCAAw2JRIISttRHMfDpDuZJpvYo=3D=0A+=3DAZ9M=0A+-----END=20PGP=20= MESSAGE-----=0A+'),=20'key',=20'debug=3D1');=0A+NOTICE:=20=20dbg:=20= parse_compressed_data:=20bzip2=20unsupported=0A+ERROR:=20=20Unsupported=20= compression=20algorithm=0Adiff=20--git=20= a/contrib/pgcrypto/expected/pgp-encrypt_1.out=20= b/contrib/pgcrypto/expected/pgp-encrypt_1.out=0Anew=20file=20mode=20= 100644=0Aindex=200000000000..68709bd15f=0A---=20/dev/null=0A+++=20= b/contrib/pgcrypto/expected/pgp-encrypt_1.out=0A@@=20-0,0=20+1,202=20@@=0A= +--=0A+--=20PGP=20encrypt=0A+--=0A+--=20ensure=20consistent=20test=20= output=20regardless=20of=20the=20default=20bytea=20format=0A+SET=20= bytea_output=20TO=20escape;=0A+select=20= pgp_sym_decrypt(pgp_sym_encrypt('Secret.',=20'key'),=20'key');=0A+=20= pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret.=0A+(1=20row)=0A+=0A= +--=20check=20whether=20the=20defaults=20are=20ok=0A+select=20= pgp_sym_decrypt(pgp_sym_encrypt('Secret.',=20'key'),=0A+=09'key',=20= 'expect-cipher-algo=3Daes128,=0A+=09=09expect-disable-mdc=3D0,=0A+=09=09= expect-sess-key=3D0,=0A+=09=09expect-s2k-mode=3D3,=0A+=09=09= expect-s2k-digest-algo=3Dsha1,=0A+=09=09expect-compress-algo=3D0=0A+=09=09= ');=0A+=20pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret.=0A+(1=20= row)=0A+=0A+--=20maybe=20the=20expect-=20stuff=20simply=20does=20not=20= work=0A+select=20pgp_sym_decrypt(pgp_sym_encrypt('Secret.',=20'key'),=0A= +=09'key',=20'expect-cipher-algo=3Dbf,=0A+=09=09expect-disable-mdc=3D1,=0A= +=09=09expect-sess-key=3D1,=0A+=09=09expect-s2k-mode=3D0,=0A+=09=09= expect-s2k-digest-algo=3Dmd5,=0A+=09=09expect-compress-algo=3D1=0A+=09=09= ');=0A+NOTICE:=20=20pgp_decrypt:=20unexpected=20cipher_algo:=20expected=20= 4=20got=207=0A+NOTICE:=20=20pgp_decrypt:=20unexpected=20s2k_mode:=20= expected=200=20got=203=0A+NOTICE:=20=20pgp_decrypt:=20unexpected=20= s2k_digest_algo:=20expected=201=20got=202=0A+NOTICE:=20=20pgp_decrypt:=20= unexpected=20use_sess_key:=20expected=201=20got=200=0A+NOTICE:=20=20= pgp_decrypt:=20unexpected=20disable_mdc:=20expected=201=20got=200=0A= +NOTICE:=20=20pgp_decrypt:=20unexpected=20compress_algo:=20expected=201=20= got=200=0A+=20pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret.=0A= +(1=20row)=0A+=0A+--=20bytea=20as=20text=0A+select=20= pgp_sym_decrypt(pgp_sym_encrypt_bytea('Binary',=20'baz'),=20'baz');=0A= +ERROR:=20=20Not=20text=20data=0A+--=20text=20as=20bytea=0A+select=20= pgp_sym_decrypt_bytea(pgp_sym_encrypt('Text',=20'baz'),=20'baz');=0A+=20= pgp_sym_decrypt_bytea=20=0A+-----------------------=0A+=20Text=0A+(1=20= row)=0A+=0A+--=20algorithm=20change=0A+select=20pgp_sym_decrypt(=0A+=09= pgp_sym_encrypt('Secret.',=20'key',=20'cipher-algo=3Dbf'),=0A+=09'key',=20= 'expect-cipher-algo=3Dbf');=0A+ERROR:=20=20Unsupported=20cipher=20= algorithm=0A+select=20pgp_sym_decrypt(=0A+=09pgp_sym_encrypt('Secret.',=20= 'key',=20'cipher-algo=3Daes'),=0A+=09'key',=20= 'expect-cipher-algo=3Daes128');=0A+=20pgp_sym_decrypt=20=0A= +-----------------=0A+=20Secret.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(=0A+=09pgp_sym_encrypt('Secret.',=20'key',=20= 'cipher-algo=3Daes192'),=0A+=09'key',=20'expect-cipher-algo=3Daes192');=0A= +=20pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret.=0A+(1=20row)=0A= +=0A+--=20s2k=20change=0A+select=20pgp_sym_decrypt(=0A+=09= pgp_sym_encrypt('Secret.',=20'key',=20's2k-mode=3D0'),=0A+=09'key',=20= 'expect-s2k-mode=3D0');=0A+=20pgp_sym_decrypt=20=0A+-----------------=0A= +=20Secret.=0A+(1=20row)=0A+=0A+select=20pgp_sym_decrypt(=0A+=09= pgp_sym_encrypt('Secret.',=20'key',=20's2k-mode=3D1'),=0A+=09'key',=20= 'expect-s2k-mode=3D1');=0A+=20pgp_sym_decrypt=20=0A+-----------------=0A= +=20Secret.=0A+(1=20row)=0A+=0A+select=20pgp_sym_decrypt(=0A+=09= pgp_sym_encrypt('Secret.',=20'key',=20's2k-mode=3D3'),=0A+=09'key',=20= 'expect-s2k-mode=3D3');=0A+=20pgp_sym_decrypt=20=0A+-----------------=0A= +=20Secret.=0A+(1=20row)=0A+=0A+--=20s2k=20count=20change=0A+select=20= pgp_sym_decrypt(=0A+=09pgp_sym_encrypt('Secret.',=20'key',=20= 's2k-count=3D1024'),=0A+=09'key',=20'expect-s2k-count=3D1024');=0A+=20= pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret.=0A+(1=20row)=0A+=0A= +--=20s2k_count=20rounds=20up=0A+select=20pgp_sym_decrypt(=0A+=09= pgp_sym_encrypt('Secret.',=20'key',=20's2k-count=3D65000000'),=0A+=09= 'key',=20'expect-s2k-count=3D65000000');=0A+NOTICE:=20=20pgp_decrypt:=20= unexpected=20s2k_count:=20expected=2065000000=20got=2065011712=0A+=20= pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret.=0A+(1=20row)=0A+=0A= +--=20s2k=20digest=20change=0A+select=20pgp_sym_decrypt(=0A+=09= pgp_sym_encrypt('Secret.',=20'key',=20's2k-digest-algo=3Dmd5'),=0A+=09= 'key',=20'expect-s2k-digest-algo=3Dmd5');=0A+=20pgp_sym_decrypt=20=0A= +-----------------=0A+=20Secret.=0A+(1=20row)=0A+=0A+select=20= pgp_sym_decrypt(=0A+=09=09pgp_sym_encrypt('Secret.',=20'key',=20= 's2k-digest-algo=3Dsha1'),=0A+=09'key',=20= 'expect-s2k-digest-algo=3Dsha1');=0A+=20pgp_sym_decrypt=20=0A= +-----------------=0A+=20Secret.=0A+(1=20row)=0A+=0A+--=20sess=20key=0A= +select=20pgp_sym_decrypt(=0A+=09pgp_sym_encrypt('Secret.',=20'key',=20= 'sess-key=3D0'),=0A+=09'key',=20'expect-sess-key=3D0');=0A+=20= pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret.=0A+(1=20row)=0A+=0A= +select=20pgp_sym_decrypt(=0A+=09pgp_sym_encrypt('Secret.',=20'key',=20= 'sess-key=3D1'),=0A+=09'key',=20'expect-sess-key=3D1');=0A+=20= pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret.=0A+(1=20row)=0A+=0A= +select=20pgp_sym_decrypt(=0A+=09pgp_sym_encrypt('Secret.',=20'key',=20= 'sess-key=3D1,=20cipher-algo=3Dbf'),=0A+=09'key',=20'expect-sess-key=3D1,=20= expect-cipher-algo=3Dbf');=0A+ERROR:=20=20Unsupported=20cipher=20= algorithm=0A+select=20pgp_sym_decrypt(=0A+=09pgp_sym_encrypt('Secret.',=20= 'key',=20'sess-key=3D1,=20cipher-algo=3Daes192'),=0A+=09'key',=20= 'expect-sess-key=3D1,=20expect-cipher-algo=3Daes192');=0A+=20= pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret.=0A+(1=20row)=0A+=0A= +select=20pgp_sym_decrypt(=0A+=09pgp_sym_encrypt('Secret.',=20'key',=20= 'sess-key=3D1,=20cipher-algo=3Daes256'),=0A+=09'key',=20= 'expect-sess-key=3D1,=20expect-cipher-algo=3Daes256');=0A+=20= pgp_sym_decrypt=20=0A+-----------------=0A+=20Secret.=0A+(1=20row)=0A+=0A= +--=20no=20mdc=0A+select=20pgp_sym_decrypt(=0A+=09=09= pgp_sym_encrypt('Secret.',=20'key',=20'disable-mdc=3D1'),=0A+=09'key',=20= 'expect-disable-mdc=3D1');=0A+=20pgp_sym_decrypt=20=0A+-----------------=0A= +=20Secret.=0A+(1=20row)=0A+=0A+--=20crlf=0A+select=20= encode(pgp_sym_decrypt_bytea(=0A+=09pgp_sym_encrypt(E'1\n2\n3\r\n',=20= 'key',=20'convert-crlf=3D1'),=0A+=09'key'),=20'hex');=0A+=20=20=20=20=20=20= =20=20encode=20=20=20=20=20=20=20=20=0A+----------------------=0A+=20= 310d0a320d0a330d0d0a=0A+(1=20row)=0A+=0A+--=20conversion=20should=20be=20= lossless=0A+select=20encode(digest(pgp_sym_decrypt(=0A+=20=20= pgp_sym_encrypt(E'\r\n0\n1\r\r\n\n2\r',=20'key',=20'convert-crlf=3D1'),=0A= +=09'key',=20'convert-crlf=3D1'),=20'sha1'),=20'hex')=20as=20result,=0A+=20= =20encode(digest(E'\r\n0\n1\r\r\n\n2\r',=20'sha1'),=20'hex')=20as=20= expect;=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20result=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=20expect=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=0A= +------------------------------------------+------------------------------= ------------=0A+=2047bde5d88d6ef8770572b9cbb4278b402aa69966=20|=20= 47bde5d88d6ef8770572b9cbb4278b402aa69966=0A+(1=20row)=0A+=0Adiff=20--git=20= a/contrib/pgcrypto/expected/pgp-pubkey-decrypt_2.out=20= b/contrib/pgcrypto/expected/pgp-pubkey-decrypt_2.out=0Anew=20file=20mode=20= 100644=0Aindex=200000000000..6eb8ad8525=0A---=20/dev/null=0A+++=20= b/contrib/pgcrypto/expected/pgp-pubkey-decrypt_2.out=0A@@=20-0,0=20= +1,632=20@@=0A+--=0A+--=20PGP=20Public=20Key=20Encryption=0A+--=0A+--=20= As=20most=20of=20the=20low-level=20stuff=20is=20tested=20in=20symmetric=20= key=0A+--=20tests,=20here's=20only=20public-key=20specific=20tests=0A= +create=20table=20keytbl=20(=0A+=09id=20int4,=0A+=09name=20text,=0A+=09= pubkey=20text,=0A+=09seckey=20text=0A+);=0A+create=20table=20encdata=20(=0A= +=09id=20int4,=0A+=09data=20text=0A+);=0A+insert=20into=20keytbl=20(id,=20= name,=20pubkey,=20seckey)=0A+values=20(1,=20'elg1024',=20'=0A+-----BEGIN=20= PGP=20PUBLIC=20KEY=20BLOCK-----=0A+Version:=20GnuPG=20v1.4.1=20= (GNU/Linux)=0A+=0A= +mQGiBELIIUgRBACp401L6jXrLB28c3YA4sM3OJKnxM1GT9YTkWyE3Vyte65H8WU9=0A= +tGPBX7OMuaX5eGZ84LFUGvaP0k7anfmXcDkCO3P9GgL+ro/dS2Ps/vChQPZqHaxE=0A= +xpKDUt47B7DGdRJrC8DRnIR4wbSyQA6ma3S1yFqC5pJhSs+mqf9eExOjiwCgntth=0A= +klRxIYw352ZX9Ov9oht/p/ED/1Xi4PS+tkXVvyIw5aZfa61bT6XvDkoPI0Aj3GE5=0A= +YmCHJlKA/IhEr8QJOLV++5VEv4l6KQ1/DFoJzoNdr1AGJukgTc6X/WcQRzfQtUic=0A= +PHQme5oAWoHa6bVQZOwvbJh3mOXDq/Tk/KF22go8maM44vMn4bvv+SBbslviYLiL=0A= +jZJ1A/9JXF1esNq+X9HehJyqHHU7LEEf/ck6zC7o2erM3/LZlZuLNPD2cv3oL3Nv=0A= +saEgcTSZl+8XmO8pLmzjKIb+hi70qVx3t2IhMqbb4B/dMY1Ck62gPBKa81/Wwi7v=0A= +IsEBQLEtyBmGmI64YpzoRNFeaaF9JY+sAKqROqe6dLjJ7vebQLQfRWxnYW1hbCAx=0A= +MDI0IDx0ZXN0QGV4YW1wbGUub3JnPoheBBMRAgAeBQJCyCFIAhsDBgsJCAcDAgMV=0A= +AgMDFgIBAh4BAheAAAoJEBwpvA0YF3NkOtsAniI9W2bC3CxARTpYrev7ihreDzFc=0A= +AJ9WYLQxDQAi5Ec9AQoodPkIagzZ4LkBDQRCyCFKEAQAh5SNbbJMAsJ+sQbcWEzd=0A= +ku8AdYB5zY7Qyf9EOvn0g39bzANhxmmb6gbRlQN0ioymlDwraTKUAfuCZgNcg/0P=0A= +sxFGb9nDcvjIV8qdVpnq1PuzMFuBbmGI6weg7Pj01dlPiO0wt1lLX+SubktqbYxI=0A= ++h31c3RDZqxj+KAgxR8YNGMAAwYD+wQs2He1Z5+p4OSgMERiNzF0acZUYmc0e+/9=0A= +6gfL0ft3IP+SSFo6hEBrkKVhZKoPSSRr5KpNaEobhdxsnKjUaw/qyoaFcNMzb4sF=0A= +k8wq5UlCkR+h72u6hv8FuleCV8SJUT1U2JjtlXJR2Pey9ifh8rZfu57UbdwdHa0v=0A= +iWc4DilhiEkEGBECAAkFAkLIIUoCGwwACgkQHCm8DRgXc2TtrwCfdPom+HlNVE9F=0A= +ig3hGY1Rb4NEk1gAn1u9IuQB+BgDP40YHHz6bKWS/x80=0A+=3DRWci=0A+-----END=20= PGP=20PUBLIC=20KEY=20BLOCK-----=0A+',=20'=0A+-----BEGIN=20PGP=20PRIVATE=20= KEY=20BLOCK-----=0A+Version:=20GnuPG=20v1.4.1=20(GNU/Linux)=0A+=0A= +lQG7BELIIUgRBACp401L6jXrLB28c3YA4sM3OJKnxM1GT9YTkWyE3Vyte65H8WU9=0A= +tGPBX7OMuaX5eGZ84LFUGvaP0k7anfmXcDkCO3P9GgL+ro/dS2Ps/vChQPZqHaxE=0A= +xpKDUt47B7DGdRJrC8DRnIR4wbSyQA6ma3S1yFqC5pJhSs+mqf9eExOjiwCgntth=0A= +klRxIYw352ZX9Ov9oht/p/ED/1Xi4PS+tkXVvyIw5aZfa61bT6XvDkoPI0Aj3GE5=0A= +YmCHJlKA/IhEr8QJOLV++5VEv4l6KQ1/DFoJzoNdr1AGJukgTc6X/WcQRzfQtUic=0A= +PHQme5oAWoHa6bVQZOwvbJh3mOXDq/Tk/KF22go8maM44vMn4bvv+SBbslviYLiL=0A= +jZJ1A/9JXF1esNq+X9HehJyqHHU7LEEf/ck6zC7o2erM3/LZlZuLNPD2cv3oL3Nv=0A= +saEgcTSZl+8XmO8pLmzjKIb+hi70qVx3t2IhMqbb4B/dMY1Ck62gPBKa81/Wwi7v=0A= +IsEBQLEtyBmGmI64YpzoRNFeaaF9JY+sAKqROqe6dLjJ7vebQAAAnj4i4st+s+C6=0A= +WKTIDcL1Iy0Saq8lCp60H0VsZ2FtYWwgMTAyNCA8dGVzdEBleGFtcGxlLm9yZz6I=0A= +XgQTEQIAHgUCQsghSAIbAwYLCQgHAwIDFQIDAxYCAQIeAQIXgAAKCRAcKbwNGBdz=0A= +ZDrbAJ9cp6AsjOhiLxwznsMJheGf4xkH8wCfUPjMCLm4tAEnyYn2hDNt7CB8B6Kd=0A= +ATEEQsghShAEAIeUjW2yTALCfrEG3FhM3ZLvAHWAec2O0Mn/RDr59IN/W8wDYcZp=0A= +m+oG0ZUDdIqMppQ8K2kylAH7gmYDXIP9D7MRRm/Zw3L4yFfKnVaZ6tT7szBbgW5h=0A= +iOsHoOz49NXZT4jtMLdZS1/krm5Lam2MSPod9XN0Q2asY/igIMUfGDRjAAMGA/sE=0A= +LNh3tWefqeDkoDBEYjcxdGnGVGJnNHvv/eoHy9H7dyD/kkhaOoRAa5ClYWSqD0kk=0A= +a+SqTWhKG4XcbJyo1GsP6sqGhXDTM2+LBZPMKuVJQpEfoe9ruob/BbpXglfEiVE9=0A= +VNiY7ZVyUdj3svYn4fK2X7ue1G3cHR2tL4lnOA4pYQAA9030E4u2ZKOfJBpUM+EM=0A= +m9VmsGjaQZV4teB0R/q3W8sRIYhJBBgRAgAJBQJCyCFKAhsMAAoJEBwpvA0YF3Nk=0A= +7a8AniFFotw1x2X+oryu3Q3nNtmxoKHpAJ9HU7jw7ydg33dI9J8gVkrmsSZ2/w=3D=3D=0A= +=3Dnvqq=0A+-----END=20PGP=20PRIVATE=20KEY=20BLOCK-----=0A+');=0A+insert=20= into=20keytbl=20(id,=20name,=20pubkey,=20seckey)=0A+values=20(2,=20= 'elg2048',=20'=0A+-----BEGIN=20PGP=20PUBLIC=20KEY=20BLOCK-----=0A= +Version:=20GnuPG=20v1.4.1=20(GNU/Linux)=0A+=0A= +mQGiBELIIgoRBAC1onBpxKYgDvrgCaUWPY34947X3ogxGOfCN0p6Eqrx+2PUhm4n=0A= +vFvmczpMT4iDc0mUO+iwnwsEkXQI1eC99g8c0jnZAvzJZ5miAHL8hukMAMfDkYke=0A= +5aVvcPPc8uPDlItpszGmH0rM0V9TIt/i9QEXetpyNWhk4jj5qnohYhLeZwCgkOdO=0A= +RFAdNi4vfFPivvtAp2ffjU8D/R3x/UJCvkzi7i9rQHGo313xxmQu5BuqIjANBUij=0A= +8IE7LRPI/Qhg2hYy3sTJwImDi7VkS+fuvNVk0d6MTWplAXYU96bn12JaD21R9sKl=0A= +Fzcc+0iZI1wYA1PczisUkoTISE+dQFUsoGHfpDLhoBuesXQrhBavI8t8VPd+nkdt=0A= +J+oKA/9iRQ87FzxdYTkh2drrv69FZHc3Frsjw9nPcBq/voAvXH0MRilqyCg7HpW/=0A= +T9naeOERksa+Rj4R57IF1l4e5oiiGJo9QmaKZcsCsXrREJCycrlEtMqXfSPy+bi5=0A= +0yDZE/Qm1dwu13+OXOsRvkoNYjO8Mzo9K8wU12hMqN0a2bu6a7QjRWxnYW1hbCAy=0A= +MDQ4IDx0ZXN0MjA0OEBleGFtcGxlLm9yZz6IXgQTEQIAHgUCQsgiCgIbAwYLCQgH=0A= +AwIDFQIDAxYCAQIeAQIXgAAKCRBI6c1W/qZo29PDAKCG724enIxRog1j+aeCp/uq=0A= +or6mbwCePuKy2/1kD1FvnhkZ/R5fpm+pdm25Ag0EQsgiIhAIAJI3Gb2Ehtz1taQ9=0A= +AhPY4Avad2BsqD3S5X/R11Cm0KBE/04D29dxn3f8QfxDsexYvNIZjoJPBqqZ7iMX=0A= +MhoWyw8ZF5Zs1mLIjFGVorePrm94N3MNPWM7x9M36bHUjx0vCZKFIhcGY1g+htE/=0A= +QweaJzNVeA5z4qZmik41FbQyQSyHa3bOkTZu++/U6ghP+iDp5UDBjMTkVyqITUVN=0A= +gC+MR+da/I60irBVhue7younh4ovF+CrVDQJC06HZl6CAJJyA81SmRfi+dmKbbjZ=0A= +LF6rhz0norPjISJvkIqvdtM4VPBKI5wpgwCzpEqjuiKrAVujRT68zvBvJ4aVqb11=0A= +k5QdJscAAwUH/jVJh0HbWAoiFTe+NvohfrA8vPcD0rtU3Y+siiqrabotnxJd2NuC=0A= +bxghJYGfNtnx0KDjFbCRKJVeTFok4UnuVYhXdH/c6i0/rCTNdeW2D6pmR4GfBozR=0A= +Pw/ARf+jONawGLyUj7uq13iquwMSE7VyNuF3ycL2OxXjgOWMjkH8c+zfHHpjaZ0R=0A= +QsetMq/iNBWraayKZnWUd+eQqNzE+NUo7w1jAu7oDpy+8a1eipxzK+O0HfU5LTiF=0A= +Z1Oe4Um0P2l3Xtx8nEgj4vSeoEkl2qunfGW00ZMMTCWabg0ZgxPzMfMeIcm6525A=0A= +Yn2qL+X/qBJTInAl7/hgPz2D1Yd7d5/RdWaISQQYEQIACQUCQsgiIgIbDAAKCRBI=0A= +6c1W/qZo25ZSAJ98WTrtl2HiX8ZqZq95v1+9cHtZPQCfZDoWQPybkNescLmXC7q5=0A= +1kNTmEU=3D=0A+=3D8QM5=0A+-----END=20PGP=20PUBLIC=20KEY=20BLOCK-----=0A= +',=20'=0A+-----BEGIN=20PGP=20PRIVATE=20KEY=20BLOCK-----=0A+Version:=20= GnuPG=20v1.4.1=20(GNU/Linux)=0A+=0A= +lQG7BELIIgoRBAC1onBpxKYgDvrgCaUWPY34947X3ogxGOfCN0p6Eqrx+2PUhm4n=0A= +vFvmczpMT4iDc0mUO+iwnwsEkXQI1eC99g8c0jnZAvzJZ5miAHL8hukMAMfDkYke=0A= +5aVvcPPc8uPDlItpszGmH0rM0V9TIt/i9QEXetpyNWhk4jj5qnohYhLeZwCgkOdO=0A= +RFAdNi4vfFPivvtAp2ffjU8D/R3x/UJCvkzi7i9rQHGo313xxmQu5BuqIjANBUij=0A= +8IE7LRPI/Qhg2hYy3sTJwImDi7VkS+fuvNVk0d6MTWplAXYU96bn12JaD21R9sKl=0A= +Fzcc+0iZI1wYA1PczisUkoTISE+dQFUsoGHfpDLhoBuesXQrhBavI8t8VPd+nkdt=0A= +J+oKA/9iRQ87FzxdYTkh2drrv69FZHc3Frsjw9nPcBq/voAvXH0MRilqyCg7HpW/=0A= +T9naeOERksa+Rj4R57IF1l4e5oiiGJo9QmaKZcsCsXrREJCycrlEtMqXfSPy+bi5=0A= +0yDZE/Qm1dwu13+OXOsRvkoNYjO8Mzo9K8wU12hMqN0a2bu6awAAn2F+iNBElfJS=0A= +8azqO/kEiIfpqu6/DQG0I0VsZ2FtYWwgMjA0OCA8dGVzdDIwNDhAZXhhbXBsZS5v=0A= +cmc+iF0EExECAB4FAkLIIgoCGwMGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQSOnN=0A= +Vv6maNvTwwCYkpcJmpl3aHCQdGomz7dFohDgjgCgiThZt2xTEi6GhBB1vuhk+f55=0A= +n3+dAj0EQsgiIhAIAJI3Gb2Ehtz1taQ9AhPY4Avad2BsqD3S5X/R11Cm0KBE/04D=0A= +29dxn3f8QfxDsexYvNIZjoJPBqqZ7iMXMhoWyw8ZF5Zs1mLIjFGVorePrm94N3MN=0A= +PWM7x9M36bHUjx0vCZKFIhcGY1g+htE/QweaJzNVeA5z4qZmik41FbQyQSyHa3bO=0A= +kTZu++/U6ghP+iDp5UDBjMTkVyqITUVNgC+MR+da/I60irBVhue7younh4ovF+Cr=0A= +VDQJC06HZl6CAJJyA81SmRfi+dmKbbjZLF6rhz0norPjISJvkIqvdtM4VPBKI5wp=0A= +gwCzpEqjuiKrAVujRT68zvBvJ4aVqb11k5QdJscAAwUH/jVJh0HbWAoiFTe+Nvoh=0A= +frA8vPcD0rtU3Y+siiqrabotnxJd2NuCbxghJYGfNtnx0KDjFbCRKJVeTFok4Unu=0A= +VYhXdH/c6i0/rCTNdeW2D6pmR4GfBozRPw/ARf+jONawGLyUj7uq13iquwMSE7Vy=0A= +NuF3ycL2OxXjgOWMjkH8c+zfHHpjaZ0RQsetMq/iNBWraayKZnWUd+eQqNzE+NUo=0A= +7w1jAu7oDpy+8a1eipxzK+O0HfU5LTiFZ1Oe4Um0P2l3Xtx8nEgj4vSeoEkl2qun=0A= +fGW00ZMMTCWabg0ZgxPzMfMeIcm6525AYn2qL+X/qBJTInAl7/hgPz2D1Yd7d5/R=0A= +dWYAAVQKFPXbRaxbdArwRVXMzSD3qj/+VwwhwEDt8zmBGnlBfwVdkjQQrDUMmV1S=0A= +EwyISQQYEQIACQUCQsgiIgIbDAAKCRBI6c1W/qZo25ZSAJ4sgUfHTVsG/x3p3fcM=0A= +3b5R86qKEACggYKSwPWCs0YVRHOWqZY0pnHtLH8=3D=0A+=3D3Dgk=0A+-----END=20PGP=20= PRIVATE=20KEY=20BLOCK-----=0A+');=0A+insert=20into=20keytbl=20(id,=20= name,=20pubkey,=20seckey)=0A+values=20(3,=20'elg4096',=20'=0A+-----BEGIN=20= PGP=20PUBLIC=20KEY=20BLOCK-----=0A+Version:=20GnuPG=20v1.4.1=20= (GNU/Linux)=0A+=0A= +mQGiBELII7wRBACFuaAvb11cIvjJK9LkZr4cYuYhLWh3DJdojNNnLNiym5OEksvY=0A= +05cw8OgqKtPzICU7o/mHXTWhzJYUt3i50/AeYygI8Q0uATS6RnDAKNlES1EMoHKz=0A= +2a5iFbYs4bm4IwlkvYd8uWjcu+U0YLbxir39u+anIc6eT+q3WiH/q3zDRwCgkT98=0A= +cnIG8iO8PdwDSP8G4Lt6TYED/R45GvCzJ4onQALLE92KkLUz8aFWSl05r84kczEN=0A= +SxiP9Ss6m465RmwWHfwYAu4b+c4GeNyU8fIU2EM8cezchC+edEi3xu1s+pCV0Dk4=0A= +18DGC8WKCICO30vBynuNmYg7W/7Zd4wtjss454fMW7+idVDNM701mmXBtI1nsBtG=0A= +7Z4tA/9FxjFbJK9jh24RewfjHpLYqcfCo2SsUjOwsnMZ5yg2yv9KyVVQhRqwmrqt=0A= +q8MRyjGmfoD9PPdCgvqgzy0hHvAHUtTm2zUczGTG+0g4hNIklxC/Mv6J4KE+NWTh=0A= +uB4acqofHyaw2WnKOuRUsoDi6rG5AyjNMyAK/vVcEGj7J1tk27QjRWxnYW1hbCA0=0A= +MDk2IDx0ZXN0NDA5NkBleGFtcGxlLm9yZz6IXgQTEQIAHgUCQsgjvAIbAwYLCQgH=0A= +AwIDFQIDAxYCAQIeAQIXgAAKCRBj+HX2P2d0oAEDAJ9lI+CNmb42z3+a6TnVusM6=0A= +FI7oLwCfUwA1zEcRdsT3nIkoYh0iKxFSDFW5BA0EQsgkdhAQAJQbLXlgcJ/jq+Xh=0A= +Eujb77/eeftFJObNIRYD9fmJ7HFIXbUcknEpbs+cRH/nrj5dGSY3OT3jCXOUtvec=0A= +sCoX/CpZWL0oqDjAiZtNSFiulw5Gav4gHYkWKgKdSo+2rkavEPqKIVHvMeXaJtGT=0A= +d7v/AmL/P8T7gls93o5WFBOLtPbDvWqaKRy2U5TAhl1laiM0vGALRVjvSCgnGw9g=0A= +FpSnXbO3AfenUSjDzZujfGLHtU44ixHSS/D4DepiF3YaYLsN4CBqZRv6FbMZD5W3=0A= +DnJY4kS1kH0MzdcF19TlcZ3itTCcGIt1tMKf84mccPoqdMzH7vumBGTeFEly5Afp=0A= +9berJcirqh2fzlunN0GS02z6SGWnjTbDlkNDxuxPSBbpcpNyD3jpYAUqSwRsZ/+5=0A= +zkzcbGtDmvy9sJ5lAXkxGoIoQ1tEVX/LOHnh2NQHK8ourVOnr7MS0nozssITZJ5E=0A= +XqtHiREjiYEuPyZiVZKJHLWuYYaF+n40znnz3sJuXFRreHhHbbvRdlYUU5mJV+XZ=0A= +BLgKuS33NdpGeMIngnCc/9IQ6OZb6ixc94kbkd3w2PVr8CbKlu/IHTjWOO2mAo+D=0A= ++OydlYl23FiM3KOyMP1HcEOJMB/nwkMtrvd+522Lu9n77ktKfot9IPrQDIQTyXjR=0A= +3pCOFtCOBnk2tJHMPoG9jn9ah/LHAAMHEACDZ5I/MHGfmiKg2hrmqBu2J2j/deC8=0A= +CpwcyDH1ovQ0gHvb9ESa+CVRU2Wdy2CD7Q9SmtMverB5eneL418iPVRcQdwRmQ2y=0A= +IH4udlBa6ce9HTUCaecAZ4/tYBnaC0Av/9l9tz14eYcwRMDpB+bnkhgF+PZ1KAfD=0A= +9wcY2aHbtsf3lZBc5h4owPJkxpe/BNzuJxW3q4VpSbLsZhwnCZ2wg7DRwP44wFIk=0A= +00ptmoBY59gsU6I40XtzrF8JDr0cA57xND5RY21Z8lnnYRE1Tc8h5REps9ZIxW3/=0A= +yl91404bPLqxczpUHQAMSTAmBaStPYX1nS51uofOhLs5SKPCUmxfGKIOhsD0oLUn=0A= +78DnkONVGeXzBibSwwtbgfMzee4G8wSUfJ7w8WXz1TyanaGLnJ+DuKASSOrFoBCD=0A= +HEDuWZWgSL74NOQupFRk0gxOPmqU94Y8HziQWma/cETbmD83q8rxN+GM2oBxQkQG=0A= +xcbqMTHE7aVhV3tymbSWVaYhww3oIwsZS9oUIi1DnPEowS6CpVRrwdvLjLJnJzzV=0A= +O3AFPn9eZ1Q7R1tNx+zZ4OOfhvI/OlRJ3HBx2L53embkbdY9gFYCCdTjPyjKoDIx=0A= +kALgCajjCYMNUsAKNSd6mMCQ8TtvukSzkZS1RGKP27ohsdnzIVsiEAbxDMMcI4k1=0A= +ul0LExUTCXSjeIhJBBgRAgAJBQJCyCR2AhsMAAoJEGP4dfY/Z3Sg19sAn0NDS8pb=0A= +qrMpQAxSb7zRTmcXEFd9AJ435H0ttP/NhLHXC9ezgbCMmpXMOQ=3D=3D=0A+=3DkRxT=0A= +-----END=20PGP=20PUBLIC=20KEY=20BLOCK-----=0A+',=20'=0A+-----BEGIN=20= PGP=20PRIVATE=20KEY=20BLOCK-----=0A+Version:=20GnuPG=20v1.4.1=20= (GNU/Linux)=0A+=0A= +lQG7BELII7wRBACFuaAvb11cIvjJK9LkZr4cYuYhLWh3DJdojNNnLNiym5OEksvY=0A= +05cw8OgqKtPzICU7o/mHXTWhzJYUt3i50/AeYygI8Q0uATS6RnDAKNlES1EMoHKz=0A= +2a5iFbYs4bm4IwlkvYd8uWjcu+U0YLbxir39u+anIc6eT+q3WiH/q3zDRwCgkT98=0A= +cnIG8iO8PdwDSP8G4Lt6TYED/R45GvCzJ4onQALLE92KkLUz8aFWSl05r84kczEN=0A= +SxiP9Ss6m465RmwWHfwYAu4b+c4GeNyU8fIU2EM8cezchC+edEi3xu1s+pCV0Dk4=0A= +18DGC8WKCICO30vBynuNmYg7W/7Zd4wtjss454fMW7+idVDNM701mmXBtI1nsBtG=0A= +7Z4tA/9FxjFbJK9jh24RewfjHpLYqcfCo2SsUjOwsnMZ5yg2yv9KyVVQhRqwmrqt=0A= +q8MRyjGmfoD9PPdCgvqgzy0hHvAHUtTm2zUczGTG+0g4hNIklxC/Mv6J4KE+NWTh=0A= +uB4acqofHyaw2WnKOuRUsoDi6rG5AyjNMyAK/vVcEGj7J1tk2wAAoJCUNy6awTkw=0A= +XfbLbpqh0fvDst7jDLa0I0VsZ2FtYWwgNDA5NiA8dGVzdDQwOTZAZXhhbXBsZS5v=0A= +cmc+iF4EExECAB4FAkLII7wCGwMGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQY/h1=0A= +9j9ndKABAwCeNEOVK87EzXYbtxYBsnjrUI948NIAn2+f3BXiBFDV5NvqPwIZ0m77=0A= +Fwy4nQRMBELIJHYQEACUGy15YHCf46vl4RLo2++/3nn7RSTmzSEWA/X5iexxSF21=0A= +HJJxKW7PnER/564+XRkmNzk94wlzlLb3nLAqF/wqWVi9KKg4wImbTUhYrpcORmr+=0A= +IB2JFioCnUqPtq5GrxD6iiFR7zHl2ibRk3e7/wJi/z/E+4JbPd6OVhQTi7T2w71q=0A= +mikctlOUwIZdZWojNLxgC0VY70goJxsPYBaUp12ztwH3p1Eow82bo3xix7VOOIsR=0A= +0kvw+A3qYhd2GmC7DeAgamUb+hWzGQ+Vtw5yWOJEtZB9DM3XBdfU5XGd4rUwnBiL=0A= +dbTCn/OJnHD6KnTMx+77pgRk3hRJcuQH6fW3qyXIq6odn85bpzdBktNs+khlp402=0A= +w5ZDQ8bsT0gW6XKTcg946WAFKksEbGf/uc5M3GxrQ5r8vbCeZQF5MRqCKENbRFV/=0A= +yzh54djUByvKLq1Tp6+zEtJ6M7LCE2SeRF6rR4kRI4mBLj8mYlWSiRy1rmGGhfp+=0A= +NM55897CblxUa3h4R2270XZWFFOZiVfl2QS4Crkt9zXaRnjCJ4JwnP/SEOjmW+os=0A= +XPeJG5Hd8Nj1a/AmypbvyB041jjtpgKPg/jsnZWJdtxYjNyjsjD9R3BDiTAf58JD=0A= +La73fudti7vZ++5LSn6LfSD60AyEE8l40d6QjhbQjgZ5NrSRzD6BvY5/WofyxwAD=0A= +BxAAg2eSPzBxn5oioNoa5qgbtido/3XgvAqcHMgx9aL0NIB72/REmvglUVNlnctg=0A= +g+0PUprTL3qweXp3i+NfIj1UXEHcEZkNsiB+LnZQWunHvR01AmnnAGeP7WAZ2gtA=0A= +L//Zfbc9eHmHMETA6Qfm55IYBfj2dSgHw/cHGNmh27bH95WQXOYeKMDyZMaXvwTc=0A= +7icVt6uFaUmy7GYcJwmdsIOw0cD+OMBSJNNKbZqAWOfYLFOiONF7c6xfCQ69HAOe=0A= +8TQ+UWNtWfJZ52ERNU3PIeURKbPWSMVt/8pfdeNOGzy6sXM6VB0ADEkwJgWkrT2F=0A= +9Z0udbqHzoS7OUijwlJsXxiiDobA9KC1J+/A55DjVRnl8wYm0sMLW4HzM3nuBvME=0A= +lHye8PFl89U8mp2hi5yfg7igEkjqxaAQgxxA7lmVoEi++DTkLqRUZNIMTj5qlPeG=0A= +PB84kFpmv3BE25g/N6vK8TfhjNqAcUJEBsXG6jExxO2lYVd7cpm0llWmIcMN6CML=0A= +GUvaFCItQ5zxKMEugqVUa8Hby4yyZyc81TtwBT5/XmdUO0dbTcfs2eDjn4byPzpU=0A= +Sdxwcdi+d3pm5G3WPYBWAgnU4z8oyqAyMZAC4Amo4wmDDVLACjUnepjAkPE7b7pE=0A= +s5GUtURij9u6IbHZ8yFbIhAG8QzDHCOJNbpdCxMVEwl0o3gAAckBdfKuasiNUn5G=0A= +L5XRnSvaOFzftr8zteOlZChCSNvzH5k+i1j7RJbWq06OeKRywPzjfjgM2MvRzI43=0A= +ICeISQQYEQIACQUCQsgkdgIbDAAKCRBj+HX2P2d0oNfbAJ9+G3SeXrk+dWwo9EGi=0A= +hqMi2GVTsgCfeoQJPsc8FLYUgfymc/3xqAVLUtg=3D=0A+=3DGjq6=0A+-----END=20PGP=20= PRIVATE=20KEY=20BLOCK-----=0A+');=0A+insert=20into=20keytbl=20(id,=20= name,=20pubkey,=20seckey)=0A+values=20(4,=20'rsa2048',=20'=0A+-----BEGIN=20= PGP=20PUBLIC=20KEY=20BLOCK-----=0A+Version:=20GnuPG=20v1.4.1=20= (GNU/Linux)=0A+=0A= +mQELBELIJbEBCADAIdtcoLAmQfl8pb73pPRuEYx8qW9klLfCGG5A4OUOi00JHNwP=0A= +ZaABe1PGzjoeXrgM1MTQZhoZu1Vdg+KDI6XAtiy9P6bLg7ntsXksD4wBoIKtQKc2=0A= +55pdukxTiu+xeJJG2q8ZZPOp97CV9fbQ9vPCwgnuSsDCoQlibZikDVPAyVTvp7Jx=0A= +5rz8yXsl4sxvaeMZPqqFPtA/ENeQ3cpsyR1BQXSvoZpH1Fq0b8GcZTEdWWD/w6/K=0A= +MCRC8TmgEd+z3e8kIsCwFQ+TSHbCcxRWdgZE7gE31sJHHVkrZlXtLU8MPXWqslVz=0A= +R0cX+yC8j6bXI6/BqZ2SvRndJwuunRAr4um7AAYptB5SU0EgMjA0OCA8cnNhMjA0=0A= +OEBleGFtcGxlLm9yZz6JATQEEwECAB4FAkLIJbECGwMGCwkIBwMCAxUCAwMWAgEC=0A= +HgECF4AACgkQnc+OnJvTHyQqHwf8DtzuAGmObfe3ggtn14x2wnU1Nigebe1K5liR=0A= +nrLuVlLBpdO6CWmMUzfKRvyZlx54GlA9uUQSjW+RlgejdOTQqesDrcTEukYd4yzw=0A= +bLZyM5Gb3lsE/FEmE7Dxw/0Utf59uACqzG8LACQn9J6sEgZWKxAupuYTHXd12lDP=0A= +D3dnU4uzKPhMcjnSN00pzjusP7C9NZd3OLkAx2vw/dmb4Q+/QxeZhVYYsAUuR2hv=0A= +9bgGWopumlOkt8Zu5YG6+CtTbJXprPI7pJ1jHbeE+q/29hWJQtS8Abx82AcOkzhv=0A= +S3NZKoJ/1DrGgoDAu1mGkM4KvLAxfDs/qQ9dZhtEmDbKPLTVEA=3D=3D=0A+=3DlR4n=0A= +-----END=20PGP=20PUBLIC=20KEY=20BLOCK-----=0A+',=20'=0A+-----BEGIN=20= PGP=20PRIVATE=20KEY=20BLOCK-----=0A+Version:=20GnuPG=20v1.4.1=20= (GNU/Linux)=0A+=0A= +lQOWBELIJbEBCADAIdtcoLAmQfl8pb73pPRuEYx8qW9klLfCGG5A4OUOi00JHNwP=0A= +ZaABe1PGzjoeXrgM1MTQZhoZu1Vdg+KDI6XAtiy9P6bLg7ntsXksD4wBoIKtQKc2=0A= +55pdukxTiu+xeJJG2q8ZZPOp97CV9fbQ9vPCwgnuSsDCoQlibZikDVPAyVTvp7Jx=0A= +5rz8yXsl4sxvaeMZPqqFPtA/ENeQ3cpsyR1BQXSvoZpH1Fq0b8GcZTEdWWD/w6/K=0A= +MCRC8TmgEd+z3e8kIsCwFQ+TSHbCcxRWdgZE7gE31sJHHVkrZlXtLU8MPXWqslVz=0A= +R0cX+yC8j6bXI6/BqZ2SvRndJwuunRAr4um7AAYpAAf/QZsrrz0c7dgWwGqMIpw6=0A= +fP+/lLa74+fa2CFRWtYowEiKsfDg/wN7Ua07036dNhPa8aZPsU6SRzm5PybKOURe=0A= +D9pNt0FxJkX0j5pCWfjSJgTbc1rCdqZ/oyBk/U6pQtf//zfw3PbDl7I8TC6GOt2w=0A= +5NgcXdsWHP7LAmPctOVUyzFsenevR0MFTHkMbmKI1HpFm8XN/e1Fl+qIAD+OagTF=0A= +5B32VvpoJtkh5nxnIuToNJsa9Iy7F9MM2CeFOyTMihMcjXKBBUaAYoF115irBvqu=0A= +7N/qWmzqLg8yxBZ56mh6meCF3+67VA2y7fL8rhw2QuqgLg1JFlKAVL+9crCSrn//=0A= +GQQA1kT7FytW6BNOffblFYZkrJer3icoRDqa/ljgH/yVaWoVT1igy0E9XzYO7MwP=0A= +2usj/resLy0NC1qCthk51cZ/wthooMl88e5Wb4l5FYwBEac7muSBTo4W8cAH1hFj=0A= +TWL6XAGvEzGX3Mt9pn8uYGlQLZAhJoNCAU2EOCbN1PchDvsEAOWNKYesuUVk8+sQ=0A= +St0NDNhd9BWtTWTHkCZb1dKC3JTfr9PqkTBLrWFbYjkOtvdPAW7FDaXXXZfdH1jH=0A= +WfwP3Q+I6sqgSaWpCS4dBAns3/RVtO7czVgyIwma04iIvJqderYrfvkUq95KfwP2=0A= +V8wXkhrPPPxyrg5y3wQlpY2jb5RBBAC17SK1ms+DBtck4vpdjp3SJ32SbyC/DU30=0A= +89Q12j74S7Zdu1qZlKnvy3kWPYX/hMuSzGZ+mLVJNFEqH2X01aFzppYz0hdI9PGB=0A= +9tTFEqZWQL9ZkXfjc79Cgnt12pNukRbtw0N/kyutOdIFHVT79wVAd+powqziXJsC=0A= +Kc+4xjwSCkZitB5SU0EgMjA0OCA8cnNhMjA0OEBleGFtcGxlLm9yZz6JATQEEwEC=0A= +AB4FAkLIJbECGwMGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQnc+OnJvTHyQqHwf8=0A= +DtzuAGmObfe3ggtn14x2wnU1Nigebe1K5liRnrLuVlLBpdO6CWmMUzfKRvyZlx54=0A= +GlA9uUQSjW+RlgejdOTQqesDrcTEukYd4yzwbLZyM5Gb3lsE/FEmE7Dxw/0Utf59=0A= +uACqzG8LACQn9J6sEgZWKxAupuYTHXd12lDPD3dnU4uzKPhMcjnSN00pzjusP7C9=0A= +NZd3OLkAx2vw/dmb4Q+/QxeZhVYYsAUuR2hv9bgGWopumlOkt8Zu5YG6+CtTbJXp=0A= +rPI7pJ1jHbeE+q/29hWJQtS8Abx82AcOkzhvS3NZKoJ/1DrGgoDAu1mGkM4KvLAx=0A= +fDs/qQ9dZhtEmDbKPLTVEA=3D=3D=0A+=3DWKAv=0A+-----END=20PGP=20PRIVATE=20= KEY=20BLOCK-----=0A+');=0A+insert=20into=20keytbl=20(id,=20name,=20= pubkey,=20seckey)=0A+values=20(5,=20'psw-elg1024',=20'=0A+-----BEGIN=20= PGP=20PUBLIC=20KEY=20BLOCK-----=0A+Version:=20GnuPG=20v1.4.1=20= (GNU/Linux)=0A+=0A= +mQGiBELIIUgRBACp401L6jXrLB28c3YA4sM3OJKnxM1GT9YTkWyE3Vyte65H8WU9=0A= +tGPBX7OMuaX5eGZ84LFUGvaP0k7anfmXcDkCO3P9GgL+ro/dS2Ps/vChQPZqHaxE=0A= +xpKDUt47B7DGdRJrC8DRnIR4wbSyQA6ma3S1yFqC5pJhSs+mqf9eExOjiwCgntth=0A= +klRxIYw352ZX9Ov9oht/p/ED/1Xi4PS+tkXVvyIw5aZfa61bT6XvDkoPI0Aj3GE5=0A= +YmCHJlKA/IhEr8QJOLV++5VEv4l6KQ1/DFoJzoNdr1AGJukgTc6X/WcQRzfQtUic=0A= +PHQme5oAWoHa6bVQZOwvbJh3mOXDq/Tk/KF22go8maM44vMn4bvv+SBbslviYLiL=0A= +jZJ1A/9JXF1esNq+X9HehJyqHHU7LEEf/ck6zC7o2erM3/LZlZuLNPD2cv3oL3Nv=0A= +saEgcTSZl+8XmO8pLmzjKIb+hi70qVx3t2IhMqbb4B/dMY1Ck62gPBKa81/Wwi7v=0A= +IsEBQLEtyBmGmI64YpzoRNFeaaF9JY+sAKqROqe6dLjJ7vebQLQfRWxnYW1hbCAx=0A= +MDI0IDx0ZXN0QGV4YW1wbGUub3JnPoheBBMRAgAeBQJCyCFIAhsDBgsJCAcDAgMV=0A= +AgMDFgIBAh4BAheAAAoJEBwpvA0YF3NkOtsAniI9W2bC3CxARTpYrev7ihreDzFc=0A= +AJ9WYLQxDQAi5Ec9AQoodPkIagzZ4LkBDQRCyCFKEAQAh5SNbbJMAsJ+sQbcWEzd=0A= +ku8AdYB5zY7Qyf9EOvn0g39bzANhxmmb6gbRlQN0ioymlDwraTKUAfuCZgNcg/0P=0A= +sxFGb9nDcvjIV8qdVpnq1PuzMFuBbmGI6weg7Pj01dlPiO0wt1lLX+SubktqbYxI=0A= ++h31c3RDZqxj+KAgxR8YNGMAAwYD+wQs2He1Z5+p4OSgMERiNzF0acZUYmc0e+/9=0A= +6gfL0ft3IP+SSFo6hEBrkKVhZKoPSSRr5KpNaEobhdxsnKjUaw/qyoaFcNMzb4sF=0A= +k8wq5UlCkR+h72u6hv8FuleCV8SJUT1U2JjtlXJR2Pey9ifh8rZfu57UbdwdHa0v=0A= +iWc4DilhiEkEGBECAAkFAkLIIUoCGwwACgkQHCm8DRgXc2TtrwCfdPom+HlNVE9F=0A= +ig3hGY1Rb4NEk1gAn1u9IuQB+BgDP40YHHz6bKWS/x80=0A+=3DRWci=0A+-----END=20= PGP=20PUBLIC=20KEY=20BLOCK-----=0A+',=20'=0A+-----BEGIN=20PGP=20PRIVATE=20= KEY=20BLOCK-----=0A+Version:=20GnuPG=20v1.4.1=20(GNU/Linux)=0A+=0A= +lQHpBELIIUgRBACp401L6jXrLB28c3YA4sM3OJKnxM1GT9YTkWyE3Vyte65H8WU9=0A= +tGPBX7OMuaX5eGZ84LFUGvaP0k7anfmXcDkCO3P9GgL+ro/dS2Ps/vChQPZqHaxE=0A= +xpKDUt47B7DGdRJrC8DRnIR4wbSyQA6ma3S1yFqC5pJhSs+mqf9eExOjiwCgntth=0A= +klRxIYw352ZX9Ov9oht/p/ED/1Xi4PS+tkXVvyIw5aZfa61bT6XvDkoPI0Aj3GE5=0A= +YmCHJlKA/IhEr8QJOLV++5VEv4l6KQ1/DFoJzoNdr1AGJukgTc6X/WcQRzfQtUic=0A= +PHQme5oAWoHa6bVQZOwvbJh3mOXDq/Tk/KF22go8maM44vMn4bvv+SBbslviYLiL=0A= +jZJ1A/9JXF1esNq+X9HehJyqHHU7LEEf/ck6zC7o2erM3/LZlZuLNPD2cv3oL3Nv=0A= +saEgcTSZl+8XmO8pLmzjKIb+hi70qVx3t2IhMqbb4B/dMY1Ck62gPBKa81/Wwi7v=0A= +IsEBQLEtyBmGmI64YpzoRNFeaaF9JY+sAKqROqe6dLjJ7vebQP4HAwImKZ5q2QwT=0A= +D2DDAY/IQBjes7WgqZeacfLPDoB8ecD/KLoSCH6Z3etvbPHSOKiazxoJ962Ix74H=0A= +ZAE6ZbMTtl5dZW1ptB9FbGdhbWFsIDEwMjQgPHRlc3RAZXhhbXBsZS5vcmc+iF4E=0A= +ExECAB4FAkLIIUgCGwMGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQHCm8DRgXc2Q6=0A= +2wCfXKegLIzoYi8cM57DCYXhn+MZB/MAn1D4zAi5uLQBJ8mJ9oQzbewgfAeinQFf=0A= +BELIIUoQBACHlI1tskwCwn6xBtxYTN2S7wB1gHnNjtDJ/0Q6+fSDf1vMA2HGaZvq=0A= +BtGVA3SKjKaUPCtpMpQB+4JmA1yD/Q+zEUZv2cNy+MhXyp1WmerU+7MwW4FuYYjr=0A= +B6Ds+PTV2U+I7TC3WUtf5K5uS2ptjEj6HfVzdENmrGP4oCDFHxg0YwADBgP7BCzY=0A= +d7Vnn6ng5KAwRGI3MXRpxlRiZzR77/3qB8vR+3cg/5JIWjqEQGuQpWFkqg9JJGvk=0A= +qk1oShuF3GycqNRrD+rKhoVw0zNviwWTzCrlSUKRH6Hva7qG/wW6V4JXxIlRPVTY=0A= +mO2VclHY97L2J+Hytl+7ntRt3B0drS+JZzgOKWH+BwMCJimeatkMEw9gRkFjt4Xa=0A= +9rX8awMBE5+vVcGKv/DNiCvJnlYvSdCj8VfuHsYFliiJo6u17NJon+K43e3yvDNk=0A= +f631VOVanGEz7TyqOkWQiEkEGBECAAkFAkLIIUoCGwwACgkQHCm8DRgXc2TtrwCe=0A= +IUWi3DXHZf6ivK7dDec22bGgoekAn0dTuPDvJ2Dfd0j0nyBWSuaxJnb/=0A+=3DSNvr=0A= +-----END=20PGP=20PRIVATE=20KEY=20BLOCK-----=0A+');=0A+insert=20into=20= keytbl=20(id,=20name,=20pubkey,=20seckey)=0A+values=20(6,=20= 'rsaenc2048',=20'=0A+-----BEGIN=20PGP=20PUBLIC=20KEY=20BLOCK-----=0A= +Version:=20GnuPG=20v1.4.1=20(GNU/Linux)=0A+=0A= +mQELBELr2m0BCADOrnknlnXI0EzRExf/TgoHvK7Xx/E0keWqV3KrOyC3/tY2KOrj=0A= +UVxaAX5pkFX9wdQObGPIJm06u6D16CH6CildX/vxG7YgvvKzK8JGAbwrXAfk7OIW=0A= +czO2zRaZGDynoK3mAxHRBReyTKtNv8rDQhuZs6AOozJNARdbyUO/yqUnqNNygWuT=0A= +4htFDEuLPIJwAbMSD0BvFW6YQaPdxzaAZm3EWVNbwDzjgbBUdBiUUwRdZIFUhsjJ=0A= +dirFdy5+uuZru6y6CNC1OERkJ7P8EyoFiZckAIE5gshVZzNuyLOZjc5DhWBvLbX4=0A= +NZElAnfiv+4nA6y8wQLSIbmHA3nqJaBklj85AAYptCVSU0EgMjA0OCBFbmMgPHJz=0A= +YTIwNDhlbmNAZXhhbXBsZS5vcmc+iQE0BBMBAgAeBQJC69ptAhsDBgsJCAcDAgMV=0A= +AgMDFgIBAh4BAheAAAoJEMiZ6pNEGVVZHMkIAJtGHHZ9iM8Yq1rr0zl1L6SvlQP8=0A= +JCaxHa31wH3PKqGtq2M+cpb2rXf7gAY/doHJPXggfVzkyFrysmQ1gPbDGYLyOutw=0A= ++IkhihEb5bWxQBNj+3zAFs1YX6v2HXWbSUSmyY1V9/+NTtKk03olDc/swd3lXzku=0A= +UOhcgfpBgIt3Q+MpT6M2+OIF7lVfSb1rWdpwTfGhZzW9szQOeoS4gPvxCCRyuabQ=0A= +RJ6DWH61F8fFIDJg1z+A/Obx4fqX6GOA69RzgZ3oukFBIXxNwV9PZNnAmHtZVYO8=0A= +0g/oVYBbuvOYedffDBeQarhERZ5W2TnIE+nqY61YOLBqosliygdZTXULzNi5AQsE=0A= +QuvaugEIAOuCJZdkzORA6e1lr81Lnr4JzMsVBFA+X/yIkBbV6qX/A4nVSLAZKNPX=0A= +z1YIrMTu+1rMIiy10IWbA6zgMTpzPhJRfgePONgdnCYyK5Ksh5/C5ntzKwwGwxfK=0A= +lAXIxJurCHXTbEa+YvPdn76vJ3HsXOXVEL+fLb4U3l3Ng87YM202Lh1Ha2MeS2zE=0A= +FZcAoKbFqAAjDLEai64SoOFh0W3CsD1DL4zmfp+YZrUPHTtZadsi53i4KKW/ws9U=0A= +rHlolqYNhYze/uRLyfnUx9PN4r/GhEzauyDMV0smo91uB3aewPft+eCpmeWnu0PF=0A= +JVK4xyRmhIq2rVCw16a1pBJirvGM+y0ABimJAR8EGAECAAkFAkLr2roCGwwACgkQ=0A= +yJnqk0QZVVku1wgAg1bLSjPkhw+ldG5HzumpqR84+JKyozdJaJzefu2+1iqYE0B0=0A= +WLz2PJVIiK41xiEkKhBvTOQYuXmtWqAWXptD91P5SoXoNJWLQO3TNwarANhHxkWg=0A= +w/TOUxQqoctlRUej5NDD+4eW5G9lcS1FEGuKDWtX096u80vO+TbyJjvx2eVM1k+X=0A= +dmeYsGOiNgDimCreJGYc14G7eY9jt24gw10n1sMAKI1qm6lcoHqZ9OOyla+wJdro=0A= +PYZGO7R8+1O9R22WrK6BYDT5j/1JwMZqbOESjNvDEVT0yOHClCHRN4CChbt6LhKh=0A= +CLUNdz/udIt0JAC6c/HdPLSW3HnmM3+iNj+Kug=3D=3D=0A+=3DpwU2=0A+-----END=20= PGP=20PUBLIC=20KEY=20BLOCK-----=0A+',=20'=0A+-----BEGIN=20PGP=20PRIVATE=20= KEY=20BLOCK-----=0A+Version:=20GnuPG=20v1.4.1=20(GNU/Linux)=0A+=0A= +lQOWBELr2m0BCADOrnknlnXI0EzRExf/TgoHvK7Xx/E0keWqV3KrOyC3/tY2KOrj=0A= +UVxaAX5pkFX9wdQObGPIJm06u6D16CH6CildX/vxG7YgvvKzK8JGAbwrXAfk7OIW=0A= +czO2zRaZGDynoK3mAxHRBReyTKtNv8rDQhuZs6AOozJNARdbyUO/yqUnqNNygWuT=0A= +4htFDEuLPIJwAbMSD0BvFW6YQaPdxzaAZm3EWVNbwDzjgbBUdBiUUwRdZIFUhsjJ=0A= +dirFdy5+uuZru6y6CNC1OERkJ7P8EyoFiZckAIE5gshVZzNuyLOZjc5DhWBvLbX4=0A= +NZElAnfiv+4nA6y8wQLSIbmHA3nqJaBklj85AAYpAAf9GuKpxrXp267eSPw9ZeSw=0A= +Ik6ob1I0MHbhhHeaXQnF0SuOViJ1+Bs74hUB3/F5fqrnjVLIS/ysYzegYpbpXOIa=0A= +MZwYcp2e+dpmVb7tkGQgzXH0igGtBQBqoSUVq9mG2XKPVh2JmiYgOH6GrHSGmnCq=0A= +GCgEK4ezSomB/3OtPFSjAxOlSw6dXSkapSxW3pEGvCdaWd9p8yl4rSpGsZEErPPL=0A= +uSbZZrHtWfgq5UXdPeE1UnMlBcvSruvpN4qgWMgSMs4d2lXvzXJLcht/nryP+atT=0A= +H1gwnRmlDCVv5BeJepKo3ORJDvcPlXkJPhqS9If3BhTqt6QgQEFI4aIYYZOZpZoi=0A= +2QQA2Zckzktmsc1MS04zS9gm1CbxM9d2KK8EOlh7fycRQhYYqqavhTBH2MgEp+Dd=0A= +ZtuEN5saNDe9x/fwi2ok1Bq6luGMWPZU/nZe7fxadzwfliy/qPzStWFW3vY9mMLu=0A= +6uEqgjin/lf4YrAswXDZaEc5e4GuNgGfwr27hpjxE1jg3PsEAPMqXEOMT2yh+yRu=0A= +DlLRbFhYOI4aUHY2CGoQQONnwv2O5gFvmOcPlg3J5lvnwlOYCx0c3bDxAtHyjPJq=0A= +FAZqcJBaB9RDhKHwlWDrbx/6FPH2SuKE+u4msIhPFin4V3FAP+yTem/TKrdnaWy6=0A= +EUrhCWTXVRTijBaCudfjFd/ipHZbA/0dv7UAcoWK6kiVLzyE+jOvtN+ZxTzxq7CW=0A= +mlFPgAC966hgJmz9IXqadtMgPAoL3PK9q1DbPM3JhsQcJrNzTJqZrdN1/kPU0HHa=0A= ++aof1BVy3wSvp2mXgaRUULStyhUIyBRM6hAYp3/MoWEYn/bwr+zQkIU8Zsk6OsZ6=0A= +q1xE3cowrUWFtCVSU0EgMjA0OCBFbmMgPHJzYTIwNDhlbmNAZXhhbXBsZS5vcmc+=0A= +iQE0BBMBAgAeBQJC69ptAhsDBgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEMiZ6pNE=0A= +GVVZHMkIAJtGHHZ9iM8Yq1rr0zl1L6SvlQP8JCaxHa31wH3PKqGtq2M+cpb2rXf7=0A= +gAY/doHJPXggfVzkyFrysmQ1gPbDGYLyOutw+IkhihEb5bWxQBNj+3zAFs1YX6v2=0A= +HXWbSUSmyY1V9/+NTtKk03olDc/swd3lXzkuUOhcgfpBgIt3Q+MpT6M2+OIF7lVf=0A= +Sb1rWdpwTfGhZzW9szQOeoS4gPvxCCRyuabQRJ6DWH61F8fFIDJg1z+A/Obx4fqX=0A= +6GOA69RzgZ3oukFBIXxNwV9PZNnAmHtZVYO80g/oVYBbuvOYedffDBeQarhERZ5W=0A= +2TnIE+nqY61YOLBqosliygdZTXULzNidA5YEQuvaugEIAOuCJZdkzORA6e1lr81L=0A= +nr4JzMsVBFA+X/yIkBbV6qX/A4nVSLAZKNPXz1YIrMTu+1rMIiy10IWbA6zgMTpz=0A= +PhJRfgePONgdnCYyK5Ksh5/C5ntzKwwGwxfKlAXIxJurCHXTbEa+YvPdn76vJ3Hs=0A= +XOXVEL+fLb4U3l3Ng87YM202Lh1Ha2MeS2zEFZcAoKbFqAAjDLEai64SoOFh0W3C=0A= +sD1DL4zmfp+YZrUPHTtZadsi53i4KKW/ws9UrHlolqYNhYze/uRLyfnUx9PN4r/G=0A= +hEzauyDMV0smo91uB3aewPft+eCpmeWnu0PFJVK4xyRmhIq2rVCw16a1pBJirvGM=0A= ++y0ABikAB/oC3z7lv6sVg+ngjbpWy9lZu2/ECZ9FqViVz7bUkjfvSuowgpncryLW=0A= +4EpVV4U6mMSgU6kAi5VGT/BvYGSAtnqDWGiPs7Kk+h4Adz74bEAXzU280pNBtSfX=0A= +tGvzlS4a376KzYFSCJDRBdMebEhJMbY0wQmR8lTZu5JSUI4YYEuN0c7ckdsw8w42=0A= +QWTLonG8HC6h8UPKS0EAcaCo7tFubMIesU6cWuTYucsHE+wjbADjuSNX968qczNe=0A= +NoL2BUznXOQoPu6HQO4/8cr7ib+VQkB2bHQcMoZazPUStIID1e4CL4XcxfuAmT8o=0A= +3XDvMLgVqNp5W2f8Mzmk3/DbtsLXLOv5BADsCzQpseC8ikSYJC72hcon1wlUmGeH=0A= +3qgGiiHhYXFa18xgI5juoO8DaWno0rPPlgr36Y8mSB5qjYHMXwjKnKyUmt11H+hU=0A= ++6uk4hq3Rjd8l+vfuOSr1xoTrtBUg9Rwfw6JVo0DC+8CWg4oBWsLXVM6KQXPFdJs=0A= +8kyFQplR/iP1XQQA/2tbDANjAYGNNDjJO9/0kEnSAUyYMasFJDrA2q17J5CroVQw=0A= +QpMmWwdDkRANUVPKnWHS5sS65BRc7UytKe2f3A3ZInGXJIK2Hl+TzapWYcYxql+4=0A= +ol5mEDDMDbhEE8Wmj9KyB6iifdLI0K+yxNb9T4Jpj3J18+St+G8+9AcFcBEEAM1b=0A= +M9C+/05cnV8gjcByqH9M9ypo8fzPvMKVXWwCLQXpaL50QIkzLURkiMoEWrCdELaA=0A= +sVPotRzePTIQ1ooLeDxd1gRnDqjZiIR0kwmv6vq8tfzY96O2ZbGWFI5eth89aWEJ=0A= +WB8AR3zYcXpwJLwPuhXW2/NlZF0bclJ3jNzAfTIeQmeJAR8EGAECAAkFAkLr2roC=0A= +GwwACgkQyJnqk0QZVVku1wgAg1bLSjPkhw+ldG5HzumpqR84+JKyozdJaJzefu2+=0A= +1iqYE0B0WLz2PJVIiK41xiEkKhBvTOQYuXmtWqAWXptD91P5SoXoNJWLQO3TNwar=0A= +ANhHxkWgw/TOUxQqoctlRUej5NDD+4eW5G9lcS1FEGuKDWtX096u80vO+TbyJjvx=0A= +2eVM1k+XdmeYsGOiNgDimCreJGYc14G7eY9jt24gw10n1sMAKI1qm6lcoHqZ9OOy=0A= +la+wJdroPYZGO7R8+1O9R22WrK6BYDT5j/1JwMZqbOESjNvDEVT0yOHClCHRN4CC=0A= +hbt6LhKhCLUNdz/udIt0JAC6c/HdPLSW3HnmM3+iNj+Kug=3D=3D=0A+=3DUKh3=0A= +-----END=20PGP=20PRIVATE=20KEY=20BLOCK-----=0A+');=0A+insert=20into=20= keytbl=20(id,=20name,=20pubkey,=20seckey)=0A+values=20(7,=20= 'rsaenc2048-psw',=20'=0A+same=20key=20with=20password=0A+',=20'=0A= +-----BEGIN=20PGP=20PRIVATE=20KEY=20BLOCK-----=0A+Version:=20GnuPG=20= v1.4.11=20(GNU/Linux)=0A+=0A= +lQPEBELr2m0BCADOrnknlnXI0EzRExf/TgoHvK7Xx/E0keWqV3KrOyC3/tY2KOrj=0A= +UVxaAX5pkFX9wdQObGPIJm06u6D16CH6CildX/vxG7YgvvKzK8JGAbwrXAfk7OIW=0A= +czO2zRaZGDynoK3mAxHRBReyTKtNv8rDQhuZs6AOozJNARdbyUO/yqUnqNNygWuT=0A= +4htFDEuLPIJwAbMSD0BvFW6YQaPdxzaAZm3EWVNbwDzjgbBUdBiUUwRdZIFUhsjJ=0A= +dirFdy5+uuZru6y6CNC1OERkJ7P8EyoFiZckAIE5gshVZzNuyLOZjc5DhWBvLbX4=0A= +NZElAnfiv+4nA6y8wQLSIbmHA3nqJaBklj85AAYp/gcDCNnoEKwFo86JYCE1J92R=0A= +HRQ7DoyAZpW1O0dTXL8Epk0sKsKDrCJOrIkDymsjfyBexADIeqOkioy/50wD2Mku=0A= +CVHKWO2duAiJN5t/FoRgpR1/Q11K6QdfqOG0HxwfIXLcPv7eSIso8kWorj+I01BP=0A= +Fn/atGEbIjdWaz/q2XHbu0Q3x6Et2gIsbLRVMhiYz1UG9uzGJ0TYCdBa2SFhs184=0A= +52akMpD+XVdM0Sq9/Cx40Seo8hzERB96+GXnQ48q2OhlvcEXiFyD6M6wYCWbEV+6=0A= +XQVMymbl22FPP/bD9ReQX2kjrkQlFAtmhr+0y8reMCbcxwLuQfA3173lSPo7jrbH=0A= +oLrGhkRpqd2bYCelqdy/XMmRFso0+7uytHfTFrUNfDWfmHVrygoVrNnarCbxMMI0=0A= +I8Q+tKHMThWgf0rIOSh0+w38kOXFCEqEWF8YkAqCrMZIlJIed78rOCFgG4aHajZR=0A= +D8rpXdUOIr/WeUddK25Tu8IuNJb0kFf12IMgNh0nS+mzlqWiofS5kA0TeB8wBV6t=0A= +RotaeyDNSsMoowfN8cf1yHMTxli+K1Tasg003WVUoWgUc+EsJ5+KTNwaX5uGv0Cs=0A= +j6dg6/FVeVRL9UsyF+2kt7euX3mABuUtcVGx/ZKTq/MNGEh6/r3B5U37qt+FDRbw=0A= +ppKPc2AP+yBUWsQskyrxFgv4eSpcLEg+lgdz/zLyG4qW4lrFUoO790Cm/J6C7/WQ=0A= +Z+E8kcS8aINJkg1skahH31d59ZkbW9PVeJMFGzNb0Z2LowngNP/BMrJ0LT2CQyLs=0A= +UxbT16S/gwAyUpJnbhWYr3nDdlwtC0rVopVTPD7khPRppcsq1f8D70rdIxI4Ouuw=0A= +vbjNZ1EWRJ9f2Ywb++k/xgSXwJkGodUlrUr+3i8cv8mPx+fWvif9q7Y5Ex1wCRa8=0A= +8FAj/o+hEbQlUlNBIDIwNDggRW5jIDxyc2EyMDQ4ZW5jQGV4YW1wbGUub3JnPokB=0A= +NAQTAQIAHgUCQuvabQIbAwYLCQgHAwIDFQIDAxYCAQIeAQIXgAAKCRDImeqTRBlV=0A= +WRzJCACbRhx2fYjPGKta69M5dS+kr5UD/CQmsR2t9cB9zyqhratjPnKW9q13+4AG=0A= +P3aByT14IH1c5Mha8rJkNYD2wxmC8jrrcPiJIYoRG+W1sUATY/t8wBbNWF+r9h11=0A= +m0lEpsmNVff/jU7SpNN6JQ3P7MHd5V85LlDoXIH6QYCLd0PjKU+jNvjiBe5VX0m9=0A= +a1nacE3xoWc1vbM0DnqEuID78Qgkcrmm0ESeg1h+tRfHxSAyYNc/gPzm8eH6l+hj=0A= +gOvUc4Gd6LpBQSF8TcFfT2TZwJh7WVWDvNIP6FWAW7rzmHnX3wwXkGq4REWeVtk5=0A= +yBPp6mOtWDiwaqLJYsoHWU11C8zYnQPEBELr2roBCADrgiWXZMzkQOntZa/NS56+=0A= +CczLFQRQPl/8iJAW1eql/wOJ1UiwGSjT189WCKzE7vtazCIstdCFmwOs4DE6cz4S=0A= +UX4HjzjYHZwmMiuSrIefwuZ7cysMBsMXypQFyMSbqwh102xGvmLz3Z++rydx7Fzl=0A= +1RC/ny2+FN5dzYPO2DNtNi4dR2tjHktsxBWXAKCmxagAIwyxGouuEqDhYdFtwrA9=0A= +Qy+M5n6fmGa1Dx07WWnbIud4uCilv8LPVKx5aJamDYWM3v7kS8n51MfTzeK/xoRM=0A= +2rsgzFdLJqPdbgd2nsD37fngqZnlp7tDxSVSuMckZoSKtq1QsNemtaQSYq7xjPst=0A= +AAYp/gcDCNnoEKwFo86JYAsxoD+wQ0zBi5RBM5EphXTpM1qKxmigsKOvBSaMmr0y=0A= +VjHtGY3poyV3t6VboOGCsFcaKm0tIdDL7vrxxwyYESETpF29b7QrYcoaLKMG7fsy=0A= +t9SUI3UV2H9uUquHgqHtsqz0jYOgm9tYnpesgQ/kOAWI/tej1ZJXUIWEmZMH/W6d=0A= +ATNvZ3ivwApfC0qF5G3oPgBSoIuQ/8I+pN/kmuyNAnJWNgagFhA/2VFBvh5XgztV=0A= +NW7G//KpR1scsn140SO/wpGBM3Kr4m8ztl9w9U6a7NlQZ2ub3/pIUTpSzyLBxJZ/=0A= +RfuZI7ROdgDMKmEgCYrN2kfp0LIxnYL6ZJu3FDcS4V098lyf5rHvB3PAEdL6Zyhd=0A= +qYp3Sx68r0F4vzk5iAIWf6pG2YdfoP2Z48Pmq9xW8qD9iwFcoz9oAzDEMENn6dfq=0A= +6MzfoaXEoYp8cR/o+aeEaGUtYBHiaxQcJYx35B9IhsXXA49yRORK8qdwhSHxB3NQ=0A= +H3pUWkfw368f/A207hQVs9yYXlEvMZikxl58gldCd3BAPqHm/XzgknRRNQZBPPKJ=0A= +BMZebZ22Dm0qDuIqW4GXLB4sLf0+UXydVINIUOlzg+S4jrwx7eZqb6UkRXTIWVo5=0A= +psTsD14wzWBRdUQHZOZD33+M8ugmewvLY/0Uix+2RorkmB7/jqoZvx/MehDwmCZd=0A= +VH8sb2wpZ55sj7gCXxvrfieQD/VeH54OwjjbtK56iYq56RVD0h1az8xDY2GZXeT7=0A= +J0c3BGpuoca5xOFWr1SylAr/miEPxOBfnfk8oZQJvZrjSBGjsTbALep2vDJk8ROD=0A= +sdQCJuU1RHDrwKHlbUL0NbGRO2juJGsatdWnuVKsFbaFW2pHHkezKuwOcaAJv7Xt=0A= +8LRF17czAJ1uaLKwV8Paqx6UIv+089GbWZi7HIkBHwQYAQIACQUCQuvaugIbDAAK=0A= +CRDImeqTRBlVWS7XCACDVstKM+SHD6V0bkfO6ampHzj4krKjN0lonN5+7b7WKpgT=0A= +QHRYvPY8lUiIrjXGISQqEG9M5Bi5ea1aoBZem0P3U/lKheg0lYtA7dM3BqsA2EfG=0A= +RaDD9M5TFCqhy2VFR6Pk0MP7h5bkb2VxLUUQa4oNa1fT3q7zS875NvImO/HZ5UzW=0A= +T5d2Z5iwY6I2AOKYKt4kZhzXgbt5j2O3biDDXSfWwwAojWqbqVygepn047KVr7Al=0A= +2ug9hkY7tHz7U71HbZasroFgNPmP/UnAxmps4RKM28MRVPTI4cKUIdE3gIKFu3ou=0A= +EqEItQ13P+50i3QkALpz8d08tJbceeYzf6I2P4q6=0A+=3DQFm5=0A+-----END=20PGP=20= PRIVATE=20KEY=20BLOCK-----=0A+');=0A+--=20elg1024=20/=20aes128=0A+insert=20= into=20encdata=20(id,=20data)=20values=20(1,=20'=0A+-----BEGIN=20PGP=20= MESSAGE-----=0A+Version:=20GnuPG=20v1.4.1=20(GNU/Linux)=0A+=0A= +hQEOA9k2z2S7c/RmEAQAgVWW0DeLrZ+1thWJGBPp2WRFL9HeNqqWHbKJCXJbz1Uy=0A= +faUY7yxVvG5Eutmo+JMiY3mg23/DgVVXHQZsTWpGvGM6djgUNGKUjZDbW6Nog7Mr=0A= +e78IywattCOmgUP9vIwwg3OVjuDCN/nVirGQFnXpJBc8DzWqDMWRWDy1M0ZsK7AD=0A= +/2JTosSFxUdpON0DKtIY3GLzmh6Nk3iV0g8VgJKUBT1rhCXuMDj3snm//EMm7hTY=0A= +PlnObq4mIhgz8NqprmhooxnU0Kapofb3P3wCHPpU14zxhXY8iKO/3JhBq2uFcx4X=0A= +uBMwkW4AdNxY/mzJZELteTL8Tr0s7PISk+owb4URpG3n0jsBc0CVULxrjh5Ejkdw=0A= +wCM195J6+KbQxOOFQ0b3uOVvv4dEgd/hRERCOq5EPaFhlHegyYJ7YO842vnSDA=3D=3D=0A= +=3DPABx=0A+-----END=20PGP=20MESSAGE-----=0A+');=0A+--=20elg2048=20/=20= blowfish=0A+insert=20into=20encdata=20(id,=20data)=20values=20(2,=20'=0A= +-----BEGIN=20PGP=20MESSAGE-----=0A+Version:=20GnuPG=20v1.4.1=20= (GNU/Linux)=0A+=0A= +hQIOAywibh/+XMfUEAf+OINhBngEsw4a/IJIeJvUgv1gTQzBwOdQEuc/runr4Oa8=0A= +Skw/Bj0X/zgABVZLem1a35NHaNwaQaCFwMQ41YyWCu+jTdsiyX/Nw0w8LKKz0rNC=0A= +vVpG6YuV7Turtsf8a5lXy1K0SHkLlgxQ6c76GS4gtSl5+bsL2+5R1gSRJ9NXqCQP=0A= +OHRipEiYwBPqr5R21ZG0FXXNKGOGkj6jt/M/wh3WVtAhYuBI+HPKRfAEjd/Pu/eD=0A= +e1zYtkH1dKKFmp44+nF0tTI274xpuso7ShfKYrOK3saFWrl0DWiWteUinjSA1YBY=0A= +m7dG7NZ8PW+g1SZWhEoPjEEEHz3kWMvlKheMRDudnQf/dDyX6kZVIAQF/5B012hq=0A= +QyVewgTGysowFIDn01uIewoEA9cASw699jw9IoJp+k5WZXnU+INllBLzQxniQCSu=0A= +iEcr0x3fYqNtj9QBfbIqyRcY6HTWcmzyOUeGaSyX76j+tRAvtVtXpraFFFnaHB70=0A= +YpXTjLkp8EBafzMghFaKDeXlr2TG/T7rbwcwWrFIwPqEAUKWN5m97Q3eyo8/ioMd=0A= +YoFD64J9ovSsgbuU5IpIGAsjxK+NKzg/2STH7zZFEVCtgcIXsTHTZfiwS98/+1H9=0A= +p1DIDaXIcUFV2ztmcKxh9gt2sXRz1W+x6D8O0k3nanU5yGG4miLKaq18fbcA0BD1=0A= ++NIzAfelq6nvvxYKcGcamBMgLo5JkZOBHvyr6RsAKIT5QYc0QTjysTk9l0Am3gYc=0A= +G2pAE+3k=0A+=3DTBHV=0A+-----END=20PGP=20MESSAGE-----=0A+');=0A+--=20= elg4096=20/=20aes256=0A+insert=20into=20encdata=20(id,=20data)=20values=20= (3,=20'=0A+-----BEGIN=20PGP=20MESSAGE-----=0A+Version:=20GnuPG=20v1.4.1=20= (GNU/Linux)=0A+=0A= +hQQOA7aFBP0Sjh/5EA/+JCgncc8IZmmRjPStWnGf9tVJhgHTn+smIclibGzs0deS=0A= +SPSCitzpblwbUDvu964+/5e5Q1l7rRuNN+AgETlEd4eppv7Swn2ChdgOXxRwukcT=0A= +Nh3G+PTFvD4ayi7w1db3qvXIt0MwN4Alt436wJmK1oz2Ka9IcyO+wHWrDy1nSGSx=0A= +z5x7YEj+EZPgWc/YAvudqE8Jpzd/OT5zSHN09UFkIAk6NxisKaIstbEGFgpqtoDZ=0A= +1SJM84XAdL2IcaJ3YY7k/yzwlawhsakKd4GSd5vWmAwvyzzbSiBMfKsDE16ePLNU=0A= +ZBF7CzmlCBPZ7YrFAHLpXBXXkCQvzD2BEYOjse50ZEfJ036T7950Ozcdy1EQbGon=0A= +nyQ4Gh0PBpnMcBuiXOceWuYzhlzFOzDtlVKdNTxFRDcbEyW2jo9xQYvCCLnYy8EH=0A= +2M7S8jCtVYJBbn63a82ELv+3+kWYcsvBJv2ZVBh4ncrBu9o0P+OYS7ApoOU+j6p2=0A= ++t0RXHksqXS1YiUwYF5KSw09EbYMgNZ9G04Px/PxLU6fSC9iDrGX7Xt3kOUP0mku=0A= +C518fPckT0zzRXqfFruJNRzDytW50KxkOQZzU1/Az1YlYN9QzWeU4EtLPb2fftZo=0A= +D0qH/ln+f9Op5t6sD2fcxZVECU1b/bFtZsxvwH406YL+UQ7hU/XnZrzVVzODal8P=0A= +/j1hg7v7BdJqu1DTp9nFWUuwMFcYAczuXn29IG183NZ7Ts4whDeYEhS8eNoLPX4j=0A= +txY12ILD/w/3Q4LoW/hPa6OdfEzsn0U5GLf1WiGmJE1H6ft2U/xUnerc/u0kt+FU=0A= +WAisArd4MuKtf7B5Vu/VF3kUdrR0hTniUKUivmC4o1jSId31Dufxj4aadVyldXAr=0A= +6TNBcdyragZjxEZ6hsBCYzA0Rd1a8atd6OaQoIEEfAzCu5Ks29pydHErStYGjWJ1=0A= +KA5KPLVvjbHpDmRhlCcm8vgpYQsBYEB5gE9fx5yCTlsVhCB6y23h7hfdMqerDqkO=0A= +ZOPsO5h+tiHCdIrQ36sMjuINy1/K2rYcXd+Crh2iHcfidpU9fvDz2ihTRNQlhjuT=0A= +0cQZM5JhctEx4VXF4LDctRhit7Hn0iqsk604woQfJVvP8O673xSXT/kBY0A/v9C0=0A= +3C4YoFNeSaKwbfZQ/4u1ZFPJxK2IIJa8UGpyAUewLMlzGVVagljybv/f4Z9ERAhy=0A= +huq5sMmw8UPsrJF2TUGHz5WSIwoh0J/qovoQI09I9sdEnFczDvRavMO2Mldy3E5i=0A= +exz9oewtel6GOmsZQSYWT/vJzbYMmvHNmNpVwwoKrLV6oI3kyQ80GHBwI1WlwHoK=0A= +2iRB0w8q4VVvJeYAz8ZIp380cqC3pfO0uZsrOx4g3k4X0jsB5y7rF5xXcZfnVbvG=0A= +DYKcOy60/OHMWVvpw6trAoA+iP+cVWPtrbRvLglTVTfYmi1ToZDDipkALBhndQ=3D=3D=0A= +=3DL/M/=0A+-----END=20PGP=20MESSAGE-----=0A+');=0A+--=20rsaenc2048=20/=20= aes128=0A+insert=20into=20encdata=20(id,=20data)=20values=20(4,=20'=0A= +-----BEGIN=20PGP=20MESSAGE-----=0A+Version:=20GnuPG=20v1.4.1=20= (GNU/Linux)=0A+=0A= +hQEMA/0CBsQJt0h1AQf+JyYnCiortj26P11zk28MKOGfWpWyAhuIgwbJXsdQ+e6r=0A= +pEyyqs9GC6gI7SNF6+J8B/gsMwvkAL4FHAQCvA4ZZ6eeXR1Of4YG22JQGmpWVWZg=0A= +DTyfhA2vkczuqfAD2tgUpMT6sdyGkQ/fnQ0lknlfHgC5GRx7aavOoAKtMqiZW5PR=0A= +yae/qR48mjX7Mb+mLvbagv9mHEgQSmHwFpaq2k456BbcZ23bvCmBnCvqV/90Ggfb=0A= +VP6gkSoFVsJ19RHsOhW1dk9ehbl51WB3zUOO5FZWwUTY9DJvKblRK/frF0+CXjE4=0A= +HfcZXHSpSjx4haGGTsMvEJ85qFjZpr0eTGOdY5cFhNJAAVP8MZfji7OhPRAoOOIK=0A= +eRGOCkao12pvPyFTFnPd5vqmyBbdNpK4Q0hS82ljugMJvM0p3vJZVzW402Kz6iBL=0A= +GQ=3D=3D=0A+=3DXHkF=0A+-----END=20PGP=20MESSAGE-----=0A+');=0A+--=20= rsaenc2048=20/=20aes128=20(not=20from=20gnupg)=0A+insert=20into=20= encdata=20(id,=20data)=20values=20(5,=20'=0A+-----BEGIN=20PGP=20= MESSAGE-----=0A+=0A= +wcBMA/0CBsQJt0h1AQgAzxZ8j+OTeZ8IlLxfZ/mVd28/gUsCY+xigWBk/anZlK3T=0A= +p2tNU2idHzKdAttH2Hu/PWbZp4kwjl9spezYxMqCeBZqtfGED88Y+rqK0n/ul30A=0A= +7jjFHaw0XUOqFNlST1v6H2i7UXndnp+kcLfHPhnO5BIYWxB2CYBehItqtrn75eqr=0A= +C7trGzU/cr74efcWagbCDSNjiAV7GlEptlzmgVMmNikyI6w0ojEUx8lCLc/OsFz9=0A= +pJUAX8xuwjxDVv+W7xk6c96grQiQlm+FLDYGiGNXoAzx3Wi/howu3uV40dXfY+jx=0A= +3WBrhEew5Pkpt1SsWoFnJWOfJ8GLd0ec8vfRCqAIVdLgAeS7NyawQYtd6wuVrEAj=0A= +5SMg4Thb4d+g45RksuGLHUUr4qO9tiXglODa4InhmJfgNuLk+RGz4LXjq8wepEmW=0A= +vRbgFOG54+Cf4C/gC+HkreDm5JKSKjvvw4B/jC6CDxq+JoziEe2Z1uEjCuEcr+Es=0A= +/eGzeOi36BejXPMHeKxXejj5qBBHKV0pHVhZSgffR0TtlXdB967Yl/5agV0R89hI=0A= +7Gw52emfnH4Z0Y4V0au2H0k1dR/2IxXdJEWSTG7Be1JHT59p9ei2gSEOrdBMIOjP=0A= +tbYYUlmmbvD49bHfThkDiC+oc9947LgQsk3kOOLbNHcjkbrjH8R5kjII4m/SEZA1=0A= +g09T+338SzevBcVXh/cFrQ6/Et+lyyO2LJRUMs69g/HyzJOVWT2Iu8E0eS9MWevY=0A= +Qtrkrhrpkl3Y02qEp/j6M03Yu2t6ZF7dp51aJ5VhO2mmmtHaTnCyCc8Fcf72LmD8=0A= +blH2nKZC9d6fi4YzSYMepZpMOFR65M80MCMiDUGnZBB8sEADu2/iVtqDUeG8mAA=3D=0A= +=3DPHJ1=0A+-----END=20PGP=20MESSAGE-----=0A+');=0A+--=20successful=20= decrypt=0A+select=20pgp_pub_decrypt(dearmor(data),=20dearmor(seckey))=0A= +from=20keytbl,=20encdata=20where=20keytbl.id=3D1=20and=20encdata.id=3D1;=0A= +ERROR:=20=20Unsupported=20public=20key=20algorithm=0A+select=20= pgp_pub_decrypt(dearmor(data),=20dearmor(seckey))=0A+from=20keytbl,=20= encdata=20where=20keytbl.id=3D2=20and=20encdata.id=3D2;=0A+ERROR:=20=20= Unsupported=20public=20key=20algorithm=0A+select=20= pgp_pub_decrypt(dearmor(data),=20dearmor(seckey))=0A+from=20keytbl,=20= encdata=20where=20keytbl.id=3D3=20and=20encdata.id=3D3;=0A+ERROR:=20=20= Unsupported=20public=20key=20algorithm=0A+select=20= pgp_pub_decrypt(dearmor(data),=20dearmor(seckey))=0A+from=20keytbl,=20= encdata=20where=20keytbl.id=3D6=20and=20encdata.id=3D4;=0A+ERROR:=20=20= Unsupported=20public=20key=20algorithm=0A+--=20wrong=20key=0A+select=20= pgp_pub_decrypt(dearmor(data),=20dearmor(seckey))=0A+from=20keytbl,=20= encdata=20where=20keytbl.id=3D2=20and=20encdata.id=3D1;=0A+ERROR:=20=20= Wrong=20key=0A+--=20sign-only=20key=0A+select=20= pgp_pub_decrypt(dearmor(data),=20dearmor(seckey))=0A+from=20keytbl,=20= encdata=20where=20keytbl.id=3D4=20and=20encdata.id=3D1;=0A+ERROR:=20=20= No=20encryption=20key=20found=0A+--=20rsa:=20password-protected=20secret=20= key,=20wrong=20password=0A+select=20pgp_pub_decrypt(dearmor(data),=20= dearmor(seckey),=20'123')=0A+from=20keytbl,=20encdata=20where=20= keytbl.id=3D7=20and=20encdata.id=3D4;=0A+ERROR:=20=20Wrong=20key=20or=20= corrupt=20data=0A+--=20rsa:=20password-protected=20secret=20key,=20right=20= password=0A+select=20pgp_pub_decrypt(dearmor(data),=20dearmor(seckey),=20= 'parool')=0A+from=20keytbl,=20encdata=20where=20keytbl.id=3D7=20and=20= encdata.id=3D4;=0A+ERROR:=20=20Unsupported=20public=20key=20algorithm=0A= +--=20password-protected=20secret=20key,=20no=20password=0A+select=20= pgp_pub_decrypt(dearmor(data),=20dearmor(seckey))=0A+from=20keytbl,=20= encdata=20where=20keytbl.id=3D5=20and=20encdata.id=3D1;=0A+ERROR:=20=20= Need=20password=20for=20secret=20key=0A+--=20password-protected=20secret=20= key,=20wrong=20password=0A+select=20pgp_pub_decrypt(dearmor(data),=20= dearmor(seckey),=20'foo')=0A+from=20keytbl,=20encdata=20where=20= keytbl.id=3D5=20and=20encdata.id=3D1;=0A+ERROR:=20=20Wrong=20key=20or=20= corrupt=20data=0A+--=20password-protected=20secret=20key,=20right=20= password=0A+select=20pgp_pub_decrypt(dearmor(data),=20dearmor(seckey),=20= 'parool')=0A+from=20keytbl,=20encdata=20where=20keytbl.id=3D5=20and=20= encdata.id=3D1;=0A+ERROR:=20=20Unsupported=20public=20key=20algorithm=0A= +--=20test=20for=20a=20short=20read=20from=20prefix_init=0A+select=20= pgp_pub_decrypt(dearmor(data),=20dearmor(seckey))=0A+from=20keytbl,=20= encdata=20where=20keytbl.id=3D6=20and=20encdata.id=3D5;=0A+ERROR:=20=20= Unsupported=20public=20key=20algorithm=0Adiff=20--git=20= a/contrib/pgcrypto/expected/pgp-pubkey-encrypt_1.out=20= b/contrib/pgcrypto/expected/pgp-pubkey-encrypt_1.out=0Anew=20file=20mode=20= 100644=0Aindex=200000000000..2247c6527c=0A---=20/dev/null=0A+++=20= b/contrib/pgcrypto/expected/pgp-pubkey-encrypt_1.out=0A@@=20-0,0=20+1,50=20= @@=0A+--=0A+--=20PGP=20Public=20Key=20Encryption=0A+--=0A+--=20ensure=20= consistent=20test=20output=20regardless=20of=20the=20default=20bytea=20= format=0A+SET=20bytea_output=20TO=20escape;=0A+--=20successful=20= encrypt/decrypt=0A+select=20pgp_pub_decrypt(=0A+=09= pgp_pub_encrypt('Secret=20msg',=20dearmor(pubkey)),=0A+=09= dearmor(seckey))=0A+from=20keytbl=20where=20keytbl.id=3D1;=0A+ERROR:=20=20= Unsupported=20public=20key=20algorithm=0A+select=20pgp_pub_decrypt(=0A+=09= =09pgp_pub_encrypt('Secret=20msg',=20dearmor(pubkey)),=0A+=09=09= dearmor(seckey))=0A+from=20keytbl=20where=20keytbl.id=3D2;=0A+ERROR:=20=20= Unsupported=20public=20key=20algorithm=0A+select=20pgp_pub_decrypt(=0A+=09= =09pgp_pub_encrypt('Secret=20msg',=20dearmor(pubkey)),=0A+=09=09= dearmor(seckey))=0A+from=20keytbl=20where=20keytbl.id=3D3;=0A+ERROR:=20=20= Unsupported=20public=20key=20algorithm=0A+select=20pgp_pub_decrypt(=0A+=09= =09pgp_pub_encrypt('Secret=20msg',=20dearmor(pubkey)),=0A+=09=09= dearmor(seckey))=0A+from=20keytbl=20where=20keytbl.id=3D6;=0A+ERROR:=20=20= Unsupported=20public=20key=20algorithm=0A+--=20try=20with=20rsa-sign=20= only=0A+select=20pgp_pub_decrypt(=0A+=09=09pgp_pub_encrypt('Secret=20= msg',=20dearmor(pubkey)),=0A+=09=09dearmor(seckey))=0A+from=20keytbl=20= where=20keytbl.id=3D4;=0A+ERROR:=20=20No=20encryption=20key=20found=0A= +--=20try=20with=20secret=20key=0A+select=20pgp_pub_decrypt(=0A+=09=09= pgp_pub_encrypt('Secret=20msg',=20dearmor(seckey)),=0A+=09=09= dearmor(seckey))=0A+from=20keytbl=20where=20keytbl.id=3D1;=0A+ERROR:=20=20= Refusing=20to=20encrypt=20with=20secret=20key=0A+--=20does=20= text-to-bytea=20works=0A+select=20pgp_pub_decrypt_bytea(=0A+=09=09= pgp_pub_encrypt('Secret=20msg',=20dearmor(pubkey)),=0A+=09=09= dearmor(seckey))=0A+from=20keytbl=20where=20keytbl.id=3D1;=0A+ERROR:=20=20= Unsupported=20public=20key=20algorithm=0A+--=20and=20bytea-to-text?=0A= +select=20pgp_pub_decrypt(=0A+=09=09pgp_pub_encrypt_bytea('Secret=20= msg',=20dearmor(pubkey)),=0A+=09=09dearmor(seckey))=0A+from=20keytbl=20= where=20keytbl.id=3D1;=0A+ERROR:=20=20Unsupported=20public=20key=20= algorithm=0Adiff=20--git=20a/contrib/pgcrypto/nss.c=20= b/contrib/pgcrypto/nss.c=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..590d0a8559=0A---=20/dev/null=0A+++=20= b/contrib/pgcrypto/nss.c=0A@@=20-0,0=20+1,601=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-2021,=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+#ifdef=20USE_NSS=0A+=0A= +#include=20"px.h"=0A+#include=20"common/nss.h"=0A+#include=20= "utils/memutils.h"=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*=20Data=20structures=20for=20= recording=20cipher=20implementations=20as=20well=20as=20ongoing=0A+=20*=20= cipher=20operations.=0A+=20*/=0A+typedef=20struct=20nss_digest=0A+{=0A+=09= NSSInitContext=20*context;=0A+=09PK11Context=20*hash_context;=0A+=09= HASH_HashType=20hash_type;=0A+}=09=09=09nss_digest;=0A+=0A+typedef=20= struct=20cipher_implementation=0A+{=0A+=09/*=20Function=20pointers=20to=20= cipher=20operations=20*/=0A+=09int=09=09=09(*init)=20(PX_Cipher=20*pxc,=20= const=20uint8=20*key,=20unsigned=20klen,=20const=20uint8=20*iv);=0A+=09= unsigned=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,=20= const=20uint8=20*data,=20unsigned=20dlen,=20uint8=20*res);=0A+=09int=09=09= =09(*decrypt)=20(PX_Cipher=20*pxc,=20const=20uint8=20*data,=20unsigned=20= dlen,=20uint8=20*res);=0A+=09void=09=09(*free)=20(PX_Cipher=20*pxc);=0A+=0A= +=09/*=20The=20mechanism=20describing=20the=20cipher=20used=20*/=0A+=09= CK_MECHANISM_TYPE=20mechanism;=0A+=09int=09=09=09keylen;=0A+}=09=09=09= cipher_implementation;=0A+=0A+typedef=20struct=20nss_cipher=0A+{=0A+=09= const=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=20nss_cipher_ref=0A+{=0A+=09const=20= char=20*name;=0A+=09const=20cipher_implementation=20*impl;=0A+}=09=09=09= nss_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= +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=20=3D=3D=20CKM_AES_CBC=20||=0A+=09=09= cipher->impl->mechanism=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,=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,=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=20PK11_ParamFromIV(cipher->impl->mechanism,=20= &iv_item);=0A+=0A+=09/*=20If=20we=20had=20to=20make=20a=20mock=20IV,=20= free=20it=20once=20made=20into=20a=20param=20*/=0A+=09if=20(!iv)=0A+=09=09= pfree(iv_item_data);=0A+=0A+=09if=20(cipher->params=20=3D=3D=20NULL)=0A+=09= =09return=20PXE_CIPHER_INIT;=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20= int=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,=20CKA_DECRYPT,=0A+=09= =09=09=09=09=09=09=09=09=20=20=20cipher->decrypt_key,=20cipher->params);=0A= +=09}=0A+=0A+=09status=20=3D=20PK11_CipherOp(cipher->crypt_context,=20= res,=20&outlen,=20dlen,=20data,=20dlen);=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09=09return=20PXE_DECRYPT_FAILED;=0A+=0A+=09return=200;=0A= +}=0A+=0A+static=20int=0A+nss_encrypt(PX_Cipher=20*pxc,=20const=20uint8=20= *data,=20unsigned=20dlen,=20uint8=20*res)=0A+{=0A+=09nss_cipher=20= *cipher=20=3D=20(nss_cipher=20*)=20pxc->ptr;=0A+=09SECStatus=09status;=0A= +=09int=09=09=09outlen;=0A+=0A+=09if=20(!cipher->crypt_context)=0A+=09{=0A= +=09=09cipher->crypt_context=20=3D=0A+=09=09=09= PK11_CreateContextBySymKey(cipher->impl->mechanism,=20CKA_ENCRYPT,=0A+=09= =09=09=09=09=09=09=09=09=20=20=20cipher->decrypt_key,=20cipher->params);=0A= +=09}=0A+=0A+=09status=20=3D=20PK11_CipherOp(cipher->crypt_context,=20= res,=20&outlen,=20dlen,=20data,=20dlen);=0A+=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09=09return=20PXE_DECRYPT_FAILED;=0A+=0A+=09return=200;=0A= +}=0A+=0A+static=20void=0A+nss_free(PX_Cipher=20*pxc)=0A+{=0A+=09= nss_cipher=20*cipher=20=3D=20pxc->ptr;=0A+=09PRBool=09=09free_ctx=20=3D=20= PR_TRUE;=0A+=0A+=09PK11_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,=20NULL);=0A+}=0A+=0A+static=20= unsigned=0A+nss_get_key_size(PX_Cipher=20*pxc)=0A+{=0A+=09nss_cipher=20= *cipher=20=3D=20pxc->ptr;=0A+=0A+=09return=20cipher->impl->keylen;=0A+}=0A= +=0A+static=20unsigned=0A+nss_get_iv_size(PX_Cipher=20*pxc)=0A+{=0A+=09= nss_cipher=20*cipher=20=3D=20pxc->ptr;=0A+=0A+=09return=20= PK11_GetIVLength(cipher->impl->mechanism);=0A+}=0A+=0A+/*=0A+=20*=20= Cipher=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=20=3D=20CKM_DES_CBC,=0A+=09.keylen=20=3D=208,=0A= +};=0A+=0A+static=20const=20cipher_implementation=20nss_des_ecb=20=3D=20= {=0A+=09.init=20=3D=20nss_symkey_blockcipher_init,=0A+=09.get_block_size=20= =3D=20nss_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=20=3D=20CKM_DES_ECB,=0A+=09.keylen=20=3D=208,=0A= +};=0A+=0A+static=20const=20cipher_implementation=20nss_des3_cbc=20=3D=20= {=0A+=09.init=20=3D=20nss_symkey_blockcipher_init,=0A+=09.get_block_size=20= =3D=20nss_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=20=3D=20CKM_DES3_CBC,=0A+=09.keylen=20=3D=20= 24,=0A+};=0A+=0A+static=20const=20cipher_implementation=20nss_des3_ecb=20= =3D=20{=0A+=09.init=20=3D=20nss_symkey_blockcipher_init,=0A+=09= .get_block_size=20=3D=20nss_get_block_size,=0A+=09.get_key_size=20=3D=20= nss_get_key_size,=0A+=09.get_iv_size=20=3D=20nss_get_iv_size,=0A+=09= .encrypt=20=3D=20nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09= .free=20=3D=20nss_free,=0A+=09.mechanism=20=3D=20CKM_DES3_ECB,=0A+=09= .keylen=20=3D=2024,=0A+};=0A+=0A+static=20const=20cipher_implementation=20= nss_aes_cbc=20=3D=20{=0A+=09.init=20=3D=20nss_symkey_blockcipher_init,=0A= +=09.get_block_size=20=3D=20nss_get_block_size,=0A+=09.get_key_size=20=3D=20= nss_get_key_size,=0A+=09.get_iv_size=20=3D=20nss_get_iv_size,=0A+=09= .encrypt=20=3D=20nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09= .free=20=3D=20nss_free,=0A+=09.mechanism=20=3D=20CKM_AES_CBC,=0A+=09= .keylen=20=3D=2032,=0A+};=0A+=0A+static=20const=20cipher_implementation=20= nss_aes_ecb=20=3D=20{=0A+=09.init=20=3D=20nss_symkey_blockcipher_init,=0A= +=09.get_block_size=20=3D=20nss_get_block_size,=0A+=09.get_key_size=20=3D=20= nss_get_key_size,=0A+=09.get_iv_size=20=3D=20nss_get_iv_size,=0A+=09= .encrypt=20=3D=20nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09= .free=20=3D=20nss_free,=0A+=09.mechanism=20=3D=20CKM_AES_ECB,=0A+=09= .keylen=20=3D=2032,=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.=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{NULL}=0A+};=0A+=0A+/*=0A+=20= *=20px_find_cipher=0A+=20*=0A+=20*=20Search=20for=20the=20requested=20= cipher=20and=20see=20if=20there=20is=20support=20for=20it,=20and=20if=0A= +=20*=20so=20return=20an=20allocated=20object=20containing=20the=20= playbook=20for=20how=20to=20encrypt=0A+=20*=20and=20decrypt=20using=20= the=20cipher.=0A+=20*/=0A+int=0A+px_find_cipher(const=20char=20*alias,=20= PX_Cipher=20**res)=0A+{=0A+=09const=20nss_cipher_ref=20*cipher_ref;=0A+=09= PX_Cipher=20=20*px_cipher;=0A+=09NSSInitParameters=20params;=0A+=09= NSSInitContext=20*nss_context;=0A+=09nss_cipher=20*cipher;=0A+=0A+=09for=20= (cipher_ref=20=3D=20nss_cipher_lookup;=20cipher_ref->name;=20= cipher_ref++)=0A+=09{=0A+=09=09if=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=20PXE_NO_CIPHER;=0A+=0A+=09/*=0A+=09=20= *=20Fill=20in=20the=20PX_Cipher=20to=20pass=20back=20to=20PX=20= describing=20the=20operations=20to=0A+=09=20*=20perform=20in=20order=20= to=20use=20the=20cipher.=0A+=09=20*/=0A+=09px_cipher=20=3D=20= palloc(sizeof(*px_cipher));=0A+=09px_cipher->block_size=20=3D=20= cipher_ref->impl->get_block_size;=0A+=09px_cipher->key_size=20=3D=20= cipher_ref->impl->get_key_size;=0A+=09px_cipher->iv_size=20=3D=20= cipher_ref->impl->get_iv_size;=0A+=09px_cipher->free=20=3D=20= cipher_ref->impl->free;=0A+=09px_cipher->init=20=3D=20= cipher_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*=20Initialize=20our=20= own=20NSS=20context=20without=20a=20database=20backing=20it.=20At=0A+=09=20= *=20some=20point=20we=20might=20want=20to=20allow=20users=20to=20use=20= stored=20keys=20in=20the=0A+=09=20*=20database=20rather=20than=20passing=20= them=20via=20SELECT=20encrypt(),=20and=20then=0A+=09=20*=20this=20need=20= to=20be=20changed=20to=20open=20a=20user=20specified=20database.=0A+=09=20= */=0A+=09memset(¶ms,=200,=20sizeof(params));=0A+=09params.length=20=3D= =20sizeof(params);=0A+=09nss_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=20= NSS_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+=09/*=20= nss_cipher=20is=20the=20private=20state=20struct=20for=20the=20operation=20= */=0A+=09cipher=20=3D=20palloc(sizeof(*cipher));=0A+=09cipher->context=20= =3D=20nss_context;=0A+=09cipher->impl=20=3D=20cipher_ref->impl;=0A+=09= cipher->crypt_context=20=3D=20NULL;=0A+=0A+=09px_cipher->ptr=20=3D=20= cipher;=0A+=0A+=09*res=20=3D=20px_cipher;=0A+=09return=200;=0A+}=0A+=0A= +#endif=09=09/*=20USE_NSS=20*/=0Adiff=20--git=20= a/contrib/pgcrypto/openssl.c=20b/contrib/pgcrypto/openssl.c=0Aindex=20= e236b0d79c..7f6b15551b=20100644=0A---=20a/contrib/pgcrypto/openssl.c=0A= +++=20b/contrib/pgcrypto/openssl.c=0A@@=20-31,6=20+31,8=20@@=0A=20=0A=20= #include=20"postgres.h"=0A=20=0A+#ifdef=20USE_OPENSSL=0A+=0A=20#include=20= =0A=20#include=20=0A=20#include=20= =0A@@=20-819,3=20+821,5=20@@=20px_find_cipher(const=20= char=20*name,=20PX_Cipher=20**res)=0A=20=09*res=20=3D=20c;=0A=20=09= return=200;=0A=20}=0A+=0A+#endif=09=09/*=20USE_OPENSSL=20*/=0Adiff=20= --git=20a/contrib/pgcrypto/pgp-mpi-nss.c=20= b/contrib/pgcrypto/pgp-mpi-nss.c=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..5f8192d695=0A---=20/dev/null=0A+++=20= b/contrib/pgcrypto/pgp-mpi-nss.c=0A@@=20-0,0=20+1,53=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20pgp-mpi-nss.c=0A+=20*=09=20=20Wrapper=20for=20using=20= NSS=20as=20a=20backend=20for=20pgcrypto=20PGP=0A+=20*=0A+=20*=0A+=20*=20= Portions=20Copyright=20(c)=201996-2021,=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/pgp-mpi-nss.c=0A+=20*=0A= +=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#include=20"postgres.h"=0A+=0A+#ifdef=20USE_NSS=0A+=0A= +#include=20"pgp.h"=0A+#include=20"px.h"=0A+=0A+/*=0A+=20*=20TODO:=20= There=20is=20no=20exported=20BIGNUM=20library=20in=20NSS=20mapping=20to=20= the=20OpenSSL=0A+=20*=20counterpart=20so=20for=20now=20this=20isn't=20= supported=20when=20using=20NSS=20as=20a=20backend.=0A+=20*/=0A+int=0A= +pgp_elgamal_encrypt(PGP_PubKey=20*pk,=20PGP_MPI=20*_m,=0A+=09=09=09=09=09= PGP_MPI=20**c1_p,=20PGP_MPI=20**c2_p)=0A+{=0A+=09return=20= PXE_PGP_UNSUPPORTED_PUBALGO;=0A+}=0A+=0A+int=0A= +pgp_elgamal_decrypt(PGP_PubKey=20*pk,=20PGP_MPI=20*_c1,=20PGP_MPI=20= *_c2,=0A+=09=09=09=09=09PGP_MPI=20**msg_p)=0A+{=0A+=09return=20= PXE_PGP_UNSUPPORTED_PUBALGO;=0A+}=0A+=0A+int=0A= +pgp_rsa_encrypt(PGP_PubKey=20*pk,=20PGP_MPI=20*_m,=20PGP_MPI=20**c_p)=0A= +{=0A+=09return=20PXE_PGP_UNSUPPORTED_PUBALGO;=0A+}=0A+=0A+int=0A= +pgp_rsa_decrypt(PGP_PubKey=20*pk,=20PGP_MPI=20*_c,=20PGP_MPI=20**m_p)=0A= +{=0A+=09return=20PXE_PGP_UNSUPPORTED_PUBALGO;=0A+}=0A+=0A+#endif=09=09=09= =09=09=09=09/*=20USE_NSS=20*/=0Adiff=20--git=20= a/contrib/pgcrypto/pgp-mpi-openssl.c=20= b/contrib/pgcrypto/pgp-mpi-openssl.c=0Aindex=2075e4c8b300..898f8a493e=20= 100644=0A---=20a/contrib/pgcrypto/pgp-mpi-openssl.c=0A+++=20= b/contrib/pgcrypto/pgp-mpi-openssl.c=0A@@=20-30,6=20+30,8=20@@=0A=20=20= */=0A=20#include=20"postgres.h"=0A=20=0A+#ifdef=20USE_OPENSSL=0A+=0A=20= #include=20=0A=20=0A=20#include=20"pgp.h"=0A@@=20-282,3=20= +284,4=20@@=20err:=0A=20=09=09BN_clear_free(c);=0A=20=09return=20res;=0A=20= }=0A+#endif=09=09=09=09=09=09=09/*=20USE_OPENSSL=20*/=0Adiff=20--git=20= a/doc/src/sgml/pgcrypto.sgml=20b/doc/src/sgml/pgcrypto.sgml=0Aindex=20= 79759654a7..844aa31e86=20100644=0A---=20a/doc/src/sgml/pgcrypto.sgml=0A= +++=20b/doc/src/sgml/pgcrypto.sgml=0A@@=20-765,7=20+765,9=20@@=20= pgp_sym_encrypt(data,=20psw,=20'compress-algo=3D1,=20= cipher-algo=3Daes256')=0A=20=20=20=20cipher-algo=0A=20=0A=20= =20=20=20=0A-=20=20=20=20Which=20cipher=20algorithm=20to=20use.=0A= +=20=20=20=20Which=20cipher=20algorithm=20to=20use.=20=20= cast5=20is=20only=20available=0A+=20=20=20=20if=20= PostgreSQL=20was=20built=20with=0A+=20=20=20=20= OpenSSL.=0A=20=20=20=20=0A=20= =0A=20Values:=20bf,=20aes128,=20aes192,=20aes256,=203des,=20= cast5=0A@@=20-1157,8=20+1159,8=20@@=20gen_random_uuid()=20returns=20uuid=0A= =20=20=20=20=0A=20=20=20=20=20pgcrypto=20= configures=20itself=20according=20to=20the=20findings=20of=20the=0A=20=20= =20=20=20main=20PostgreSQL=20configure=20script.=20=20= The=20options=20that=0A-=20=20=20=20affect=20it=20are=20= --with-zlib=20and=0A-=20=20=20=20= --with-ssl=3Dopenssl.=0A+=20=20=20=20affect=20it=20= are=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-1177,6=20+1179,7=20@@=20gen_random_uuid()=20returns=20= uuid=0A=20=20=20=20=20openssl.cnf=20configuration=20= file=20in=20order=20to=20use=20older=0A=20=20=20=20=20ciphers=20like=20= DES=20or=20Blowfish.=0A=20=20=20=20=0A+=0A=20=20=20=0A=20=0A= =20=20=20=0A--=20=0A2.24.3=20(Apple=20Git-128)=0A=0A= --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F Content-Disposition: attachment; filename=v49-0008-nss-Support-NSS-in-sslinfo.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v49-0008-nss-Support-NSS-in-sslinfo.patch" Content-Transfer-Encoding: quoted-printable =46rom=205c03623985cc4fc2b866e27d25cf0b26381121aa=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:48=20+0100=0ASubject:=20[PATCH=20= v49=2008/10]=20nss:=20Support=20NSS=20in=20sslinfo=0A=0ASince=20sslinfo=20= to=20a=20large=20extent=20uses=20the=20be_tls_*=20API=20this=20mostly=0A= disables=20functionality=20which=20currently=20is=20OpenSSL=20specific.=0A= ---=0A=20contrib/sslinfo/sslinfo.c=20|=2032=20= ++++++++++++++++++++++++++++++++=0A=20doc/src/sgml/sslinfo.sgml=20|=2012=20= +++++++++++-=0A=202=20files=20changed,=2043=20insertions(+),=201=20= deletion(-)=0A=0Adiff=20--git=20a/contrib/sslinfo/sslinfo.c=20= b/contrib/sslinfo/sslinfo.c=0Aindex=205fd46b9874..25a068fa60=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= -32,6=20+34,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-42,6=20+45,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-142,6=20+146,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-293,7=20+298,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-349,6=20+370,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-482,3=20+504,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/sslinfo.sgml=20b/doc/src/sgml/sslinfo.sgml=0Aindex=20= 2a9c45a111..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=20won't=20build=20at=20all=20unless=20= the=20installation=20was=0A-=20=20configured=20with=20= --with-ssl=3Dopenssl.=0A+=20=20configured=20with=20= SSL=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= --=20=0A2.24.3=20(Apple=20Git-128)=0A=0A= --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F Content-Disposition: attachment; filename=v49-0009-nss-Support-NSS-in-cryptohash.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v49-0009-nss-Support-NSS-in-cryptohash.patch" Content-Transfer-Encoding: quoted-printable =46rom=2080de919fd7ef484d5e7cdfaa0c638c29ba000dbf=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:51=20+0100=0ASubject:=20[PATCH=20= v49=2009/10]=20nss:=20Support=20NSS=20in=20cryptohash=0A=0AThis=20adds=20= support=20for=20using=20libnss=20as=20a=20crypto=20backend=20for=20the=20= built-=0Ain=20cryptohash=20support.=20Much=20of=20this=20code=20is=20= similar=20to=20the=20pgcrypto=0Asupport.=0A---=0A=20= src/common/cryptohash_nss.c=20|=20264=20= ++++++++++++++++++++++++++++++++++++=0A=201=20file=20changed,=20264=20= insertions(+)=0A=20create=20mode=20100644=20src/common/cryptohash_nss.c=0A= =0Adiff=20--git=20a/src/common/cryptohash_nss.c=20= b/src/common/cryptohash_nss.c=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..85cf138ae5=0A---=20/dev/null=0A+++=20= b/src/common/cryptohash_nss.c=0A@@=20-0,0=20+1,264=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-2021,=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+#include=20"common/nss.h"=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+#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=20= the=20backend,=20use=20an=20allocation=20in=20TopMemoryContext=20to=20= count=20for=0A+=20*=20resowner=20cleanup=20handling.=20=20In=20the=20= frontend,=20use=20malloc=20to=20be=20able=0A+=20*=20to=20return=20a=20= failure=20status=20back=20to=20the=20caller.=0A+=20*/=0A+#ifndef=20= FRONTEND=0A+#define=20ALLOC(size)=20MemoryContextAlloc(TopMemoryContext,=20= size)=0A+#define=20FREE(ptr)=20pfree(ptr)=0A+#else=0A+#define=20= ALLOC(size)=20malloc(size)=0A+#define=20FREE(ptr)=20free(ptr)=0A+#endif=0A= +=0A+/*=0A+=20*=20Internal=20pg_cryptohash_ctx=20structure.=0A+=20*/=0A= +struct=20pg_cryptohash_ctx=0A+{=0A+=09pg_cryptohash_type=20type;=0A+=0A= +=09PK11Context=20*pk11_context;=0A+=09SECOidTag=09hash_type;=0A+=0A= +#ifndef=20FRONTEND=0A+=09ResourceOwner=20resowner;=0A+#endif=0A+};=0A+=0A= +/*=0A+=20*=20pg_cryptohash_create=0A+=20*=0A+=20*=20Create=20and=20= allocate=20a=20new=20hash=20context.=20Returns=20NULL=20on=20failure=20= in=20the=0A+=20*=20frontend,=20and=20raise=20error=20without=20returning=20= in=20the=20backend.=0A+=20*/=0A+pg_cryptohash_ctx=20*=0A= +pg_cryptohash_create(pg_cryptohash_type=20type)=0A+{=0A+=09= NSSInitParameters=20params;=0A+=09pg_cryptohash_ctx=20*ctx;=0A+=09= SECOidData=20*hash;=0A+=09SECStatus=20status;=0A+=0A+#ifndef=20FRONTEND=0A= +=09/*=0A+=09=20*=20Make=20sure=20that=20the=20resource=20owner=20has=20= space=20to=20remember=20this=20reference.=0A+=09=20*=20This=20can=20= error=20out=20with=20"out=20of=20memory",=20so=20do=20this=20before=20= any=20other=0A+=09=20*=20allocation=20to=20avoid=20leaking.=0A+=09=20*/=0A= +=09ResourceOwnerEnlargeCryptoHash(CurrentResourceOwner);=0A+#endif=0A+=0A= +=09ctx=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=20= PG_SHA1:=0A+=09=09=09ctx->hash_type=20=3D=20SEC_OID_SHA1;=0A+=09=09=09= break;=0A+=09=09case=20PG_MD5:=0A+=09=09=09ctx->hash_type=20=3D=20= SEC_OID_MD5;=0A+=09=09=09break;=0A+=09=09case=20PG_SHA224:=0A+=09=09=09= ctx->hash_type=20=3D=20SEC_OID_SHA224;=0A+=09=09=09break;=0A+=09=09case=20= PG_SHA256:=0A+=09=09=09ctx->hash_type=20=3D=20SEC_OID_SHA256;=0A+=09=09=09= break;=0A+=09=09case=20PG_SHA384:=0A+=09=09=09ctx->hash_type=20=3D=20= SEC_OID_SHA384;=0A+=09=09=09break;=0A+=09=09case=20PG_SHA512:=0A+=09=09=09= ctx->hash_type=20=3D=20SEC_OID_SHA512;=0A+=09=09=09break;=0A+=09}=0A+=0A= +=09/*=0A+=09=20*=20Initialize=20our=20own=20NSS=20context=20without=20a=20= database=20backing=20it.=0A+=09=20*/=0A+=09memset(¶ms,=200,=20= sizeof(params));=0A+=09params.length=20=3D=20sizeof(params);=0A+=09= status=20=3D=20NSS_NoDB_Init(".");=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09explicit_bzero(ctx,=20= sizeof(pg_cryptohash_ctx));=0A+=09=09FREE(ctx);=0A+=09=09goto=20error;=0A= +=09}=0A+=0A+=09ctx->type=20=3D=20type;=0A+=09hash=20=3D=20= SECOID_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,=20= size_t=20len)=0A+{=0A+=09SECStatus=09status;=0A+=09unsigned=20int=20= outlen;=0A+=0A+=09switch=20(ctx->type)=0A+=09{=0A+=09=09case=20PG_MD5:=0A= +=09=09=09if=20(len=20<=20MD5_LENGTH)=0A+=09=09=09=09return=20-1;=0A+=09=09= =09break;=0A+=09=09case=20PG_SHA1:=0A+=09=09=09if=20(len=20<=20= SHA1_LENGTH)=0A+=09=09=09=09return=20-1;=0A+=09=09=09break;=0A+=09=09= case=20PG_SHA224:=0A+=09=09=09if=20(len=20<=20SHA224_LENGTH)=0A+=09=09=09= =09return=20-1;=0A+=09=09=09break;=0A+=09=09case=20PG_SHA256:=0A+=09=09=09= if=20(len=20<=20SHA256_LENGTH)=0A+=09=09=09=09return=20-1;=0A+=09=09=09= break;=0A+=09=09case=20PG_SHA384:=0A+=09=09=09if=20(len=20<=20= SHA384_LENGTH)=0A+=09=09=09=09return=20-1;=0A+=09=09=09break;=0A+=09=09= case=20PG_SHA512:=0A+=09=09=09if=20(len=20<=20SHA512_LENGTH)=0A+=09=09=09= =09return=20-1;=0A+=09=09=09break;=0A+=09}=0A+=0A+=09status=20=3D=20= PK11_DigestFinal(ctx->pk11_context,=20dest,=20&outlen,=20len);=0A+=0A+=09= if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20-1;=0A+=0A+=09return=20= 0;=0A+}=0A+=0A+/*=0A+=20*=20pg_cryptohash_free=0A+=20*=0A+=20*=20Free=20= a=20hash=20context=20and=20the=20associated=20NSS=20context.=0A+=20*/=0A= +void=0A+pg_cryptohash_free(pg_cryptohash_ctx=20*ctx)=0A+{=0A+=09PRBool=09= =09free_context=20=3D=20PR_TRUE;=0A+=0A+=09if=20(!ctx)=0A+=09=09return;=0A= +=0A+=09PK11_DestroyContext(ctx->pk11_context,=20free_context);=0A= +#ifndef=20FRONTEND=0A+=09ResourceOwnerForgetCryptoHash(ctx->resowner,=20= PointerGetDatum(ctx));=0A+#endif=0A+=09explicit_bzero(ctx,=20= sizeof(pg_cryptohash_ctx));=0A+=09FREE(ctx);=0A+}=0A--=20=0A2.24.3=20= (Apple=20Git-128)=0A=0A= --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F Content-Disposition: attachment; filename=v49-0010-nss-Build-infrastructure.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v49-0010-nss-Build-infrastructure.patch" Content-Transfer-Encoding: quoted-printable =46rom=2026e1da8f9b26dd544d9709c8dc24a0df1604f06e=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:55=20+0100=0ASubject:=20[PATCH=20= v49=2010/10]=20nss:=20Build=20infrastructure=0A=0AFinally=20this=20adds=20= the=20infrastructure=20to=20build=20a=20postgres=20installation=0Awith=20= libnss=20support.=0A---=0A=20configure=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20375=20+++++++++++++++++++++++++++++++++-=0A= =20configure.ac=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20= =2081=20+++++++-=0A=20src/backend/libpq/Makefile=20=20=20=20|=20=20=204=20= +=0A=20src/common/Makefile=20=20=20=20=20=20=20=20=20=20=20|=20=20=208=20= +=0A=20src/include/pg_config.h.in=20=20=20=20|=20=2012=20++=0A=20= src/interfaces/libpq/Makefile=20|=20=20=205=20+=0A=20= src/tools/msvc/Install.pm=20=20=20=20=20|=20=20=203=20+-=0A=20= src/tools/msvc/Mkvcbuild.pm=20=20=20|=20=2030=20++-=0A=20= src/tools/msvc/Solution.pm=20=20=20=20|=20=2026=20+++=0A=209=20files=20= changed,=20532=20insertions(+),=2012=20deletions(-)=0A=0Adiff=20--git=20= a/configure=20b/configure=0Aindex=20896b781473..80592cca46=20100755=0A= ---=20a/configure=0A+++=20b/configure=0A@@=20-654,6=20+654,8=20@@=20= UUID_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=20= PTHREAD_CC=0A@@=20-1577,7=20+1579,7=20@@=20Optional=20Packages:=0A=20=20=20= --without-zlib=20=20=20=20=20=20=20=20=20=20do=20not=20use=20Zlib=0A=20=20= =20--with-lz4=20=20=20=20=20=20=20=20=20=20=20=20=20=20build=20with=20= LZ4=20support=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-ssl=3DLIB=20=20=20=20=20=20=20=20=20=20= use=20LIB=20for=20SSL/TLS=20support=20(openssl,=20nss)=0A=20=20=20= --with-openssl=20=20=20=20=20=20=20=20=20=20obsolete=20spelling=20of=20= --with-ssl=3Dopenssl=0A=20=0A=20Some=20influential=20environment=20= variables:=0A@@=20-12931,8=20+12933,355=20@@=20done=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=20if=20test=20-z=20= "$NSS_CONFIG";=20then=0A+=20=20for=20ac_prog=20in=20nss-config=0A+do=0A+=20= =20#=20Extract=20the=20first=20word=20of=20"$ac_prog",=20so=20it=20can=20= be=20a=20program=20name=20with=20args.=0A+set=20dummy=20$ac_prog;=20= ac_word=3D$2=0A+{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20checking=20= for=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=20= in=0A+=20=20[\\/]*=20|=20?:[\\/]*)=0A+=20=20= ac_cv_path_NSS_CONFIG=3D"$NSS_CONFIG"=20#=20Let=20the=20user=20override=20= the=20test=20with=20a=20path.=0A+=20=20;;=0A+=20=20*)=0A+=20=20= as_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=20test=20-z=20"$as_dir"=20&&=20= as_dir=3D.=0A+=20=20=20=20for=20ac_exec_ext=20in=20''=20= $ac_executable_extensions;=20do=0A+=20=20if=20as_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+=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+=09= NSS_VERSION=3D`$NSS_CONFIG=20--version`=0A+=20=20=20=20if=20echo=20= "$NSS_VERSION"=20|=20sed=20's/[.]/=20/g'=20|=20\=0A+=20=20=20=20=20=20= $AWK=20'{if=20($1=20=3D=3D=203=20&&=20($2=20>=3D=2042))=20exit=201;=20= else=20exit=200;=20}'=0A+=20=20=20=20then=0A+=20=20=20=20=20=20= as_fn_error=20$?=20"=0A+***=20The=20installed=20version=20of=20NSS=20is=20= too=20old=20to=20use=20with=20PostgreSQL.=0A+***=20NSS=20version=203.42=20= or=20later=20is=20required,=20this=20is=20$NSS_VERSION."=20"$LINENO"=205=0A= +=20=20=20=20fi=0A+=20=20=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20using=20NSS=20version=20$NSS_VERSION"=20= >&5=0A+$as_echo=20"$as_me:=20using=20NSS=20version=20$NSS_VERSION"=20= >&6;}=0A+=20=20else=0A+=09#=20No=20nss-config=20was=20found,=20manually=20= try=20to=20get=20the=20version=20and=20check=20for=0A+=09#=20library=20= capabilities=0A+=20=20=20=20cat=20confdefs.h=20-=20<<_ACEOF=20= >conftest.$ac_ext=0A+/*=20end=20confdefs.h.=20=20*/=0A+=0A+#define=20= RC_INVOKED=0A+#include=20=0A+=0A+int=0A+main=20()=0A+{=0A+=0A= +#if=20NSS_VMAJOR=20<=203=20||=20(NSS_VMAJOR=20=3D=3D=203=20&&=20= NSS_VMINOR=20<=2042)=0A+choke=20me=0A+#endif=0A+=0A+=20=20;=0A+=20=20= return=200;=0A+}=0A+_ACEOF=0A+if=20ac_fn_c_try_compile=20"$LINENO";=20= then=20:=0A+=0A+else=0A+=20=20as_fn_error=20$?=20"=0A+***=20The=20= installed=20version=20of=20NSS=20is=20too=20old=20to=20use=20with=20= PostgreSQL.=0A+***=20NSS=20version=203.42=20or=20later=20is=20required."=20= "$LINENO"=205=0A+fi=0A+rm=20-f=20core=20conftest.err=20= conftest.$ac_objext=20conftest.$ac_ext=0A+=0A+=20=20=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=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20checking=20= for=20SSL_GetImplementedCiphers=20in=20-lssl3"=20>&5=0A+$as_echo_n=20= "checking=20for=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+=20=20fi=0A+=0A+=20=20if=20test=20-n=20= "$NSPR_CONFIG";=20then=0A+=09NSPR_LIBS=3D`$NSPR_CONFIG=20--libs`=0A+=09= NSPR_CFLAGS=3D`$NSPR_CONFIG=20--cflags`=0A+=09NSPR_VERSION=3D`$NSPR_CONFIG= =20--version`=0A+=0A+=20=20=20=20if=20echo=20"$NSPR_VERSION"=20|=20sed=20= 's/[.]/=20/g'=20|=20\=0A+=20=20=20=20=20=20$AWK=20'{if=20($1=20=3D=3D=20= 4=20&&=20($2=20>=3D=2020))=20exit=201;=20else=20exit=200;=20}'=0A+=20=20=20= =20then=0A+=20=20=20=20=20=20as_fn_error=20$?=20"=0A+***=20The=20= installed=20version=20of=20NSPR=20is=20too=20old=20to=20use=20with=20= PostgreSQL.=0A+***=20NSPR=20version=204.20=20or=20later=20is=20required,=20= this=20is=20$NSPR_VERSION."=20"$LINENO"=205=0A+=20=20=20=20fi=0A+=20=20=20= =20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20using=20NSPR=20version=20= $NSPR_VERSION"=20>&5=0A+$as_echo=20"$as_me:=20using=20NSPR=20version=20= $NSPR_VERSION"=20>&6;}=0A+=20=20else=0A+=0A+=09cat=20confdefs.h=20-=20= <<_ACEOF=20>conftest.$ac_ext=0A+/*=20end=20confdefs.h.=20=20*/=0A+=0A= +#define=20NO_NSPR_10_SUPPORT=0A+#include=20=0A+=0A+int=0A= +main=20()=0A+{=0A+=0A+#if=20PR_VMAJOR=20<=204=20||=20(PR_VMAJOR=20=3D=3D=20= 4=20&&=20PR_VMINOR=20<=2020)=0A+choke=20me=0A+#endif=0A+=0A+=20=20;=0A+=20= =20return=200;=0A+}=0A+_ACEOF=0A+if=20ac_fn_c_try_compile=20"$LINENO";=20= then=20:=0A+=0A+else=0A+=20=20as_fn_error=20$?=20"=0A+***=20The=20= installed=20version=20of=20NSPR=20is=20too=20old=20to=20use=20with=20= PostgreSQL.=0A+***=20NSPR=20version=204.20=20or=20later=20is=20= required."=20"$LINENO"=205=0A+fi=0A+rm=20-f=20core=20conftest.err=20= conftest.$ac_objext=20conftest.$ac_ext=0A+=0A+=20=20=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20PR_GetDefaultIOMethods=20= in=20-lnspr4"=20>&5=0A+$as_echo_n=20"checking=20for=20= PR_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=20fi=0A+=0A+=20=20LDFLAGS=3D"$LDFLAGS=20= $NSS_LIBS=20$NSPR_LIBS"=0A+=20=20CFLAGS=3D"$CFLAGS=20$NSS_CFLAGS=20= $NSPR_CFLAGS"=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= -13903,6=20+14252,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"ssl.h"=20"ac_cv_header_ssl_h"=20"$ac_includes_default"=0A= +if=20test=20"x$ac_cv_header_ssl_h"=20=3D=20xyes;=20then=20:=0A+=0A+else=0A= +=20=20as_fn_error=20$?=20"header=20file=20=20is=20required=20= for=20NSS"=20"$LINENO"=205=0A+fi=0A+=0A+=0A+=20=20= ac_fn_c_check_header_mongrel=20"$LINENO"=20"nss.h"=20= "ac_cv_header_nss_h"=20"$ac_includes_default"=0A+if=20test=20= "x$ac_cv_header_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-18702,6=20+19068,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= -18731,7=20+19100,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=20b50130b323..d95bc29bed=20= 100644=0A---=20a/configure.ac=0A+++=20b/configure.ac=0A@@=20-1270,7=20= +1270,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-1304,8=20+1304,78=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=20to=20build=20with=20= OpenSSL=20support.=20(--with-ssl=3Dopenssl)])=0A+elif=20test=20= "$with_ssl"=20=3D=20nss=20;=20then=0A+=20=20PGAC_PATH_PROGS(NSS_CONFIG,=20= nss-config)=0A+=20=20PGAC_PATH_PROGS(NSPR_CONFIG,=20nspr-config)=0A+=0A+=20= =20if=20test=20-n=20"$NSS_CONFIG";=20then=0A+=20=20=20=20= NSS_LIBS=3D`$NSS_CONFIG=20--libs`=0A+=09NSS_CFLAGS=3D`$NSS_CONFIG=20= --cflags`=0A+=09NSS_VERSION=3D`$NSS_CONFIG=20--version`=0A+=20=20=20=20= if=20echo=20"$NSS_VERSION"=20|=20sed=20['s/[.]/=20/g']=20|=20\=0A+=20=20=20= =20=20=20$AWK=20'{if=20([$]1=20=3D=3D=203=20&&=20([$]2=20>=3D=2042))=20= exit=201;=20else=20exit=200;=20}'=0A+=20=20=20=20then=0A+=20=20=20=20=20=20= AC_MSG_ERROR([=0A+***=20The=20installed=20version=20of=20NSS=20is=20too=20= old=20to=20use=20with=20PostgreSQL.=0A+***=20NSS=20version=203.42=20or=20= later=20is=20required,=20this=20is=20$NSS_VERSION.])=0A+=20=20=20=20fi=0A= +=20=20=20=20AC_MSG_NOTICE([using=20NSS=20version=20$NSS_VERSION])=0A+=20= =20else=0A+=09#=20No=20nss-config=20was=20found,=20manually=20try=20to=20= get=20the=20version=20and=20check=20for=0A+=09#=20library=20capabilities=0A= +=20=20=20=20AC_COMPILE_IFELSE([AC_LANG_PROGRAM([=0A+#define=20= RC_INVOKED=0A+#include=20=0A+],=20[=0A+#if=20NSS_VMAJOR=20<=20= 3=20||=20(NSS_VMAJOR=20=3D=3D=203=20&&=20NSS_VMINOR=20<=2042)=0A+choke=20= me=0A+#endif=0A+])],=20[],=0A+[AC_MSG_ERROR([=0A+***=20The=20installed=20= version=20of=20NSS=20is=20too=20old=20to=20use=20with=20PostgreSQL.=0A= +***=20NSS=20version=203.42=20or=20later=20is=20required.])])=0A+=0A+=20=20= =20=20AC_CHECK_LIB(nss3,=20NSS_InitContext,=20[],=20= [AC_MSG_ERROR([library=20'nss3'=20is=20required=20for=20NSS])])=0A+=20=20= =20=20AC_CHECK_LIB(ssl3,=20SSL_GetImplementedCiphers,=20[],=20= [AC_MSG_ERROR([library=20'ssl3'=20is=20required=20for=20NSS])])=0A+=20=20= fi=0A+=0A+=20=20if=20test=20-n=20"$NSPR_CONFIG";=20then=0A+=09= NSPR_LIBS=3D`$NSPR_CONFIG=20--libs`=0A+=09NSPR_CFLAGS=3D`$NSPR_CONFIG=20= --cflags`=0A+=09NSPR_VERSION=3D`$NSPR_CONFIG=20--version`=0A+=0A+=20=20=20= =20if=20echo=20"$NSPR_VERSION"=20|=20sed=20['s/[.]/=20/g']=20|=20\=0A+=20= =20=20=20=20=20$AWK=20'{if=20([$1]=20=3D=3D=204=20&&=20([$]2=20>=3D=20= 20))=20exit=201;=20else=20exit=200;=20}'=0A+=20=20=20=20then=0A+=20=20=20= =20=20=20AC_MSG_ERROR([=0A+***=20The=20installed=20version=20of=20NSPR=20= is=20too=20old=20to=20use=20with=20PostgreSQL.=0A+***=20NSPR=20version=20= 4.20=20or=20later=20is=20required,=20this=20is=20$NSPR_VERSION.])=0A+=20=20= =20=20fi=0A+=20=20=20=20AC_MSG_NOTICE([using=20NSPR=20version=20= $NSPR_VERSION])=0A+=20=20else=0A+=0A+=09= AC_COMPILE_IFELSE([AC_LANG_PROGRAM([=0A+#define=20NO_NSPR_10_SUPPORT=0A= +#include=20=0A+],=20[=0A+#if=20PR_VMAJOR=20<=204=20||=20= (PR_VMAJOR=20=3D=3D=204=20&&=20PR_VMINOR=20<=2020)=0A+choke=20me=0A= +#endif=0A+])],=20[],=0A+[AC_MSG_ERROR([=0A+***=20The=20installed=20= version=20of=20NSPR=20is=20too=20old=20to=20use=20with=20PostgreSQL.=0A= +***=20NSPR=20version=204.20=20or=20later=20is=20required.])])=0A+=0A+=20= =20=20=20AC_CHECK_LIB(nspr4,=20PR_GetDefaultIOMethods,=20[],=20= [AC_MSG_ERROR([library=20'nspr4'=20is=20required=20for=20NSS])])=0A+=20=20= fi=0A+=0A+=20=20LDFLAGS=3D"$LDFLAGS=20$NSS_LIBS=20$NSPR_LIBS"=0A+=20=20= CFLAGS=3D"$CFLAGS=20$NSS_CFLAGS=20$NSPR_CFLAGS"=0A+=20=20= CPPFLAGS=3D"$CPPFLAGS=20$NSS_CFLAGS=20$NSPR_CFLAGS"=0A+=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-1495,6=20+1565,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(ssl.h,=20[],=20= [AC_MSG_ERROR([header=20file=20=20is=20required=20for=20= NSS])])=0A+=20=20AC_CHECK_HEADER(nss.h,=20[],=20[AC_MSG_ERROR([header=20= file=20=20is=20required=20for=20NSS])])=0A=20fi=0A=20=0A=20if=20= test=20"$with_pam"=20=3D=20yes=20;=20then=0A@@=20-2287,6=20+2360,8=20@@=20= fi=0A=20AC_MSG_CHECKING([which=20random=20number=20source=20to=20use])=0A= =20if=20test=20x"$with_ssl"=20=3D=20x"openssl"=20;=20then=0A=20=20=20= AC_MSG_RESULT([OpenSSL])=0A+elif=20test=20x"$with_ssl"=20=3D=20x"nss"=20= ;=20then=0A+=20=20AC_MSG_RESULT([NSS])=0A=20elif=20test=20x"$PORTNAME"=20= =3D=20x"win32"=20;=20then=0A=20=20=20AC_MSG_RESULT([Windows=20native])=0A= =20else=0A@@=20-2296,7=20+2371,7=20@@=20else=0A=20=20=20if=20test=20= x"$ac_cv_file__dev_urandom"=20=3D=20x"no"=20;=20then=0A=20=20=20=20=20= AC_MSG_ERROR([=0A=20no=20source=20of=20strong=20random=20numbers=20was=20= found=0A-PostgreSQL=20can=20use=20OpenSSL,=20native=20Windows=20API=20or=20= /dev/urandom=20as=20a=20source=20of=20random=20numbers.])=0A+PostgreSQL=20= can=20use=20OpenSSL,=20NSS,=20native=20Windows=20API=20or=20/dev/urandom=20= as=20a=20source=20of=20random=20numbers.])=0A=20=20=20fi=0A=20fi=0A=20=0A= diff=20--git=20a/src/backend/libpq/Makefile=20= b/src/backend/libpq/Makefile=0Aindex=206d385fd6a4..344fdf2e58=20100644=0A= ---=20a/src/backend/libpq/Makefile=0A+++=20b/src/backend/libpq/Makefile=0A= @@=20-31,6=20+31,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/common/Makefile=20b/src/common/Makefile=0Aindex=20= 880722fcf5..8a75ca0df3=20100644=0A---=20a/src/common/Makefile=0A+++=20= b/src/common/Makefile=0A@@=20-85,6=20+85,13=20@@=20OBJS_COMMON=20+=3D=20= \=0A=20=09cryptohash_openssl.o=20\=0A=20=09hmac_openssl.o=0A=20else=0A= +ifeq=20($(with_ssl),nss)=0A+OBJS_COMMON=20+=3D=20\=0A+=09hmac.o=20\=0A+=09= cipher_nss.o=20\=0A+=09protocol_nss.o=20\=0A+=09cryptohash_nss.o=0A+else=0A= =20OBJS_COMMON=20+=3D=20\=0A=20=09cryptohash.o=20\=0A=20=09hmac.o=20\=0A= @@=20-92,6=20+99,7=20@@=20OBJS_COMMON=20+=3D=20\=0A=20=09sha1.o=20\=0A=20= =09sha2.o=0A=20endif=0A+endif=0A=20=0A=20#=20A=20few=20files=20are=20= currently=20only=20built=20for=20frontend,=20not=20server=0A=20#=20= (Mkvcbuild.pm=20has=20a=20copy=20of=20this=20list,=20too).=20=20= logging.c=20is=20excluded=0Adiff=20--git=20a/src/include/pg_config.h.in=20= b/src/include/pg_config.h.in=0Aindex=20ca3592465e..9444ba57ea=20100644=0A= ---=20a/src/include/pg_config.h.in=0A+++=20b/src/include/pg_config.h.in=0A= @@=20-328,6=20+328,12=20@@=0A=20/*=20Define=20to=201=20if=20you=20have=20= the=20`m'=20library=20(-lm).=20*/=0A=20#undef=20HAVE_LIBM=0A=20=0A+/*=20= Define=20to=201=20if=20you=20have=20the=20`nspr4'=20library=20(-lnspr4).=20= */=0A+#undef=20HAVE_LIBNSPR4=0A+=0A+/*=20Define=20to=201=20if=20you=20= have=20the=20`nss3'=20library=20(-lnss3).=20*/=0A+#undef=20HAVE_LIBNSS3=0A= +=0A=20/*=20Define=20to=201=20if=20you=20have=20the=20`pam'=20library=20= (-lpam).=20*/=0A=20#undef=20HAVE_LIBPAM=0A=20=0A@@=20-340,6=20+346,9=20= @@=0A=20/*=20Define=20to=201=20if=20you=20have=20the=20`ssl'=20library=20= (-lssl).=20*/=0A=20#undef=20HAVE_LIBSSL=0A=20=0A+/*=20Define=20to=201=20= if=20you=20have=20the=20`ssl3'=20library=20(-lssl3).=20*/=0A+#undef=20= HAVE_LIBSSL3=0A+=0A=20/*=20Define=20to=201=20if=20you=20have=20the=20= `wldap32'=20library=20(-lwldap32).=20*/=0A=20#undef=20HAVE_LIBWLDAP32=0A=20= =0A@@=20-917,6=20+926,9=20@@=0A=20/*=20Define=20to=20select=20named=20= POSIX=20semaphores.=20*/=0A=20#undef=20USE_NAMED_POSIX_SEMAPHORES=0A=20=0A= +/*=20Define=20to=201=20if=20you=20have=20NSS=20support,=20*/=0A+#undef=20= USE_NSS=0A+=0A=20/*=20Define=20to=201=20to=20build=20with=20OpenSSL=20= support.=20(--with-ssl=3Dopenssl)=20*/=0A=20#undef=20USE_OPENSSL=0A=20=0A= diff=20--git=20a/src/interfaces/libpq/Makefile=20= b/src/interfaces/libpq/Makefile=0Aindex=2040a96c881d..dc56228ec8=20= 100644=0A---=20a/src/interfaces/libpq/Makefile=0A+++=20= b/src/interfaces/libpq/Makefile=0A@@=20-56,6=20+56,11=20@@=20OBJS=20+=3D=20= \=0A=20=09fe-secure-openssl.o=0A=20endif=0A=20=0A+ifeq=20($(with_ssl),=20= nss)=0A+OBJS=20+=3D=20\=0A+=09fe-secure-nss.o=0A+endif=0A+=0A=20ifeq=20= ($(with_gssapi),yes)=0A=20OBJS=20+=3D=20\=0A=20=09fe-gssapi-common.o=20\=0A= diff=20--git=20a/src/tools/msvc/Install.pm=20b/src/tools/msvc/Install.pm=0A= index=20c932322e35..d55611b024=20100644=0A---=20= a/src/tools/msvc/Install.pm=0A+++=20b/src/tools/msvc/Install.pm=0A@@=20= -440,7=20+440,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= 41172eab36..890ef29418=20100644=0A---=20a/src/tools/msvc/Mkvcbuild.pm=0A= +++=20b/src/tools/msvc/Mkvcbuild.pm=0A@@=20-137,6=20+137,12=20@@=20sub=20= mkvcbuild=0A=20=09=09push(@pgcommonallfiles,=20'hmac_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=09= push(@pgcommonallfiles,=20'cipher_nss.c');=0A+=09=09= push(@pgcommonallfiles,=20'protocol_nss.c');=0A+=09}=0A=20=09else=0A=20=09= {=0A=20=09=09push(@pgcommonallfiles,=20'cryptohash.c');=0A@@=20-202,12=20= +208,19=20@@=20sub=20mkvcbuild=0A=20=09= $postgres->FullExportDLL('postgres.lib');=0A=20=0A=20=09#=20The=20OBJS=20= scraper=20doesn't=20know=20about=20ifdefs,=20so=20remove=20appropriate=20= files=0A-=09#=20if=20building=20without=20OpenSSL.=0A-=09if=20= (!$solution->{options}->{openssl})=0A+=09#=20if=20building=20without=20= various=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= -265,12=20+278,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');=0A@@=20= -442,7=20+462,7=20@@=20sub=20mkvcbuild=0A=20=09=09push=20= @contrib_excludes,=20'xml2';=0A=20=09}=0A=20=0A-=09if=20= (!$solution->{options}->{openssl})=0A+=09if=20= (!$solution->{options}->{openssl}=20&&=20!$solution->{options}->{nss})=0A= =20=09{=0A=20=09=09push=20@contrib_excludes,=20'sslinfo',=20= 'ssl_passphrase_callback',=20'pgcrypto';=0A=20=09}=0Adiff=20--git=20= a/src/tools/msvc/Solution.pm=20b/src/tools/msvc/Solution.pm=0Aindex=20= a013951e0d..560a65ea1a=20100644=0A---=20a/src/tools/msvc/Solution.pm=0A= +++=20b/src/tools/msvc/Solution.pm=0A@@=20-303,10=20+303,13=20@@=20sub=20= GenerateFiles=0A=20=09=09HAVE_LIBLDAP=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=3D>=20= undef,=0A=20=09=09HAVE_LIBLZ4=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=3D>=20undef,=0A=20= =09=09HAVE_LIBM=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=3D>=20undef,=0A+=09=09= HAVE_LIBNSPR4=09=09=09=09=09=09=09=09=3D>=20undef,=0A+=09=09HAVE_LIBNSS3=09= =09=09=09=09=09=09=09=3D>=20undef,=0A=20=09=09HAVE_LIBPAM=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=3D>=20undef,=0A=20=09=09HAVE_LIBREADLINE=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=3D>=20undef,=0A= =20=09=09HAVE_LIBSELINUX=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=3D>=20undef,=0A=20=09=09HAVE_LIBSSL=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=3D>=20undef,=0A+=09=09HAVE_LIBSSL3=09=09=09=09=09=09= =09=09=3D>=20undef,=0A=20=09=09HAVE_LIBWLDAP32=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=3D>=20= undef,=0A=20=09=09HAVE_LIBXML2=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=3D>=20undef,=0A=20=09= =09HAVE_LIBXSLT=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=3D>=20undef,=0A@@=20-496,6=20+499,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-557,6=20+561,13=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=09$define{HAVE_LIBNSPR4}=20=3D=201;=0A= +=09=09$define{HAVE_LIBNSS3}=20=3D=201;=0A+=09=09$define{HAVE_LIBSSL3}=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-1016,6=20+1027,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');=0A--=20=0A= 2.24.3=20(Apple=20Git-128)=0A=0A= --Apple-Mail=_DAF9D1F5-CBEC-4305-A06C-305B103D571F--