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 1kY9j8-0000n5-DY for pgsql-hackers@arkaria.postgresql.org; Thu, 29 Oct 2020 15:20:35 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kY9j7-0000ez-A9 for pgsql-hackers@arkaria.postgresql.org; Thu, 29 Oct 2020 15:20:33 +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 1kY9j6-0000ep-D7 for pgsql-hackers@lists.postgresql.org; Thu, 29 Oct 2020 15:20:33 +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 1kY9j0-00089g-Sj for pgsql-hackers@lists.postgresql.org; Thu, 29 Oct 2020 15:20:31 +0000 Received: from s807.loopia.se (localhost [127.0.0.1]) by s807.loopia.se (Postfix) with ESMTP id D239C10CF201 for ; Thu, 29 Oct 2020 16:20:21 +0100 (CET) Received: from s500.loopia.se (unknown [172.22.191.5]) by s807.loopia.se (Postfix) with ESMTP id B1F3F2EB140A; Thu, 29 Oct 2020 16:20:21 +0100 (CET) Received: from s473.loopia.se (unknown [172.22.191.6]) by s500.loopia.se (Postfix) with ESMTP id A913A1E32CE0; Thu, 29 Oct 2020 16:20:21 +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 s498.loopia.se ([172.22.191.6]) by s473.loopia.se (s473.loopia.se [172.22.190.13]) (amavisd-new, port 10024) with LMTP id WLlGxHRdWADv; Thu, 29 Oct 2020 16:20:20 +0100 (CET) X-Loopia-Auth: user X-Loopia-User: daniel@yesql.se X-Loopia-Originating-IP: 89.255.232.193 Received: from [192.168.72.43] (customer-89-255-232-193.stosn.net [89.255.232.193]) (Authenticated sender: daniel@yesql.se) by s498.loopia.se (Postfix) with ESMTPSA id 9F4C448935A; Thu, 29 Oct 2020 16:20:19 +0100 (CET) From: Daniel Gustafsson Message-Id: Content-Type: multipart/mixed; boundary="Apple-Mail=_C39967DC-7CE2-4297-8DC3-75F0E858FBDB" Mime-Version: 1.0 (Mac OS X Mail 12.4 \(3445.104.15\)) Subject: Re: Support for NSS as a libpq TLS backend Date: Thu, 29 Oct 2020 16:20:19 +0100 In-Reply-To: <20201028063957.cvln377jgao33ssu@alap3.anarazel.de> Cc: Postgres hackers , Michael Paquier , Andrew Dunstan , Stephen Frost , Thomas Munro To: Andres Freund References: <20200904012334.GF19499@paquier.xyz> <20200917074134.GX2873@paquier.xyz> <20200929055939.GF7117@paquier.xyz> <411593A7-E037-474D-BFD7-D3D6683C1D46@yesql.se> <20201020191529.5yverw3ybaube3pg@alap3.anarazel.de> <907FA7D1-9BD9-464B-A6EC-DEEB53438D36@yesql.se> <20201028063957.cvln377jgao33ssu@alap3.anarazel.de> X-Mailer: Apple Mail (2.3445.104.15) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --Apple-Mail=_C39967DC-7CE2-4297-8DC3-75F0E858FBDB Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii > On 28 Oct 2020, at 07:39, Andres Freund wrote: > Have you done testing to ensure that NSS PG cooperates correctly with > openssl PG? Is there a way we can make that easier to do? E.g. = allowing > to build frontend with NSS and backend with openssl and vice versa? When I wrote the Secure Transport patch I had a patch against = PostgresNode which allowed for overriding the server binaries like so: SSLTEST_SERVER_BIN=3D/path/bin/ make -C src/test/ssl/ check I've used that coupled with manual testing so far to make sure that an = openssl client can talk to an NSS backend and so on. Before any other backend = is added we clearly need *a* way of doing this, one which no doubt will need to = be improved upon to suit more workflows. This is sort of the same situation as pg_upgrade, where two trees is = needed to really test it. I can clean that patch up and post as a starting point for discussions. >>>> if test "$with_openssl" =3D yes ; then >>>> + if test x"$with_nss" =3D x"yes" ; then >>>> + AC_MSG_ERROR([multiple SSL backends cannot be enabled = simultaneously"]) >>>> + fi >>>=20 >>> Based on a quick look there's no similar error check for the msvc >>> build. Should there be? >>=20 >> Thats a good question. When embarking on this is seemed quite = natural to me >> that it should be, but now I'm not so sure. Maybe there should be a >> --with-openssl-preferred like how we handle readline/libedit or just = allow >> multiple and let the last one win? Do you have any input on what = would make >> sense? >>=20 >> The only thing I think makes no sense is to allow multiple ones at = the same >> time given the current autoconf switches, even if it would just be to = pick say >> pg_strong_random from one and libpq TLS from another. >=20 > Maybe we should just have --with-ssl=3D{openssl,nss}? That'd avoid = needing > to check for errors. Thats another option, with --with-openssl being an alias for = --with-ssl=3Dopenssl. After another round of thinking I like this even better as it makes the = build infra cleaner, so the attached patch has this implemented. > Even better, of course, would be to allow switching of the SSL backend > based on config options (PGC_POSTMASTER GUC for backend, connection > string for frontend). Mainly because that would make testing of > interoperability so much easier. Obviously still a few places like > pgcrypto, randomness, etc, where only a compile time decision seems to > make sense. It would make testing easier, but the expense seems potentially rather = high. How would a GUC switch be allowed to operate, would we have mixed = backends or would be require all openssl connectins to be dropped before serving nss = ones? >>>> + CLEANLDFLAGS=3D"$LDFLAGS" >>>> + # TODO: document this set of LDFLAGS >>>> + LDFLAGS=3D"-lssl3 -lsmime3 -lnss3 -lplds4 -lplc4 -lnspr4 = $LDFLAGS" >>>=20 >>> Shouldn't this use nss-config or such? >>=20 >> Indeed it should, where available. I've added rudimentary support = for that >> without a fallback as of now. >=20 > When would we need a fallback? One one of my boxes I have NSS/NSPR installed via homebrew and they = don't ship an nss-config AFAICT. I wouldn't be surprised if there are other cases. >>> I think it'd also be better if we could include these files as = nss/ssl.h >>> etc - ssl.h is a name way too likely to conflict imo. >>=20 >> I've changed this to be nss/ssl.h and nspr/nspr.h etc, but the = include path >> will still need the direct path to the headers (from autoconf) since = nss.h >> includes NSPR headers as #include and so on. >=20 > Hm. Then it's probably not worth going there... It does however make visual parsing of the source files easer since it's = clear which ssl.h is being referred to. I'm in favor of keeping it. >>>> +static SECStatus >>>> +pg_cert_auth_handler(void *arg, PRFileDesc * fd, PRBool checksig, = PRBool isServer) >>>> +{ >>>> + SECStatus status; >>>> + Port *port =3D (Port *) arg; >>>> + CERTCertificate *cert; >>>> + char *peer_cn; >>>> + int len; >>>> + >>>> + status =3D SSL_AuthCertificate(CERT_GetDefaultCertDB(), = port->pr_fd, checksig, PR_TRUE); >>>> + if (status =3D=3D SECSuccess) >>>> + { >>>> + cert =3D SSL_PeerCertificate(port->pr_fd); >>>> + len =3D strlen(cert->subjectName); >>>> + peer_cn =3D MemoryContextAllocZero(TopMemoryContext, len = + 1); >>>> + if (strncmp(cert->subjectName, "CN=3D", 3) =3D=3D 0) >>>> + strlcpy(peer_cn, cert->subjectName + = strlen("CN=3D"), len + 1); >>>> + else >>>> + strlcpy(peer_cn, cert->subjectName, len + 1); >>>> + CERT_DestroyCertificate(cert); >>>> + >>>> + port->peer_cn =3D peer_cn; >>>> + port->peer_cert_valid =3D true; >>>=20 >>> Hm. We either should have something similar to >>>=20 >>> /* >>> * Reject embedded NULLs in certificate common = name to prevent >>> * attacks like CVE-2009-4034. >>> */ >>> if (len !=3D strlen(peer_cn)) >>> { >>> ereport(COMMERROR, >>> = (errcode(ERRCODE_PROTOCOL_VIOLATION), >>> errmsg("SSL = certificate's common name contains embedded null"))); >>> pfree(peer_cn); >>> return -1; >>> } >>> here, or a comment explaining why not. >>=20 >> We should, but it's proving rather difficult as there is no = equivalent API call >> to get the string as well as the expected length of it. >=20 > Hm. Should at least have a test to ensure that's not a problem then. I > hope/assume NSS rejects this somewhere internally... Agreed, I'll try to hack up a testcase. >>> Also, what's up with the CN=3D bit? Why is that needed here, but not = for >>> openssl? >>=20 >> OpenSSL returns only the value portion, whereas NSS returns key=3Dvalue= so we >> need to skip over the key=3D part. >=20 > Why is it a conditional path though? It was mostly just a belts-and-suspenders thing, I don't have any hard = evidence that it's been a thing in any modern NSS version so it can be removed. >>>> +/* >>>> + * PR_ImportTCPSocket() is a private API, but very widely used, as = it's the >>>> + * only way to make NSS use an already set up POSIX file = descriptor rather >>>> + * than opening one itself. To quote the NSS documentation: >>>> + * >>>> + * "In theory, code that uses PR_ImportTCPSocket = may break when NSPR's >>>> + * implementation changes. In practice, this is = unlikely to happen because >>>> + * NSPR's implementation has been stable for years = and because of NSPR's >>>> + * strong commitment to backward compatibility." >>>> + * >>>> + * = https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/P= R_ImportTCPSocket >>>> + * >>>> + * The function is declared in , but as it is a = header marked >>>> + * private we declare it here rather than including it. >>>> + */ >>>> +NSPR_API(PRFileDesc *) PR_ImportTCPSocket(int); >>>=20 >>> Ugh. This is really the way to do this? How do other applications = deal >>> with this problem? >>=20 >> They either #include or they do it like this (or = vendor NSPR >> which makes calling private APIs less problematic). It sure is ugly, = but there >> is no alternative to using this function. >=20 > Hm - in debian unstable's NSS this function appears to be in = nss/ssl.h, > not pprio.h: >=20 > /* > ** Imports fd into SSL, returning a new socket. Copies SSL = configuration > ** from model. > */ > SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc = *fd); >=20 > and ssl.h starts with: > /* > * This file contains prototypes for the public SSL functions. Right, but that's Import*FD*, not Import*TCPSocket*. We use ImportFD as = well since it's the API for importing an NSPR socket into NSS and enabling = SSL/TLS on it. Thats been a public API for a long time. ImportTCPSocket is = used to import an already opened socket into NSPR, else NSPR must open the = socket itself. That part has been kept private for reasons unknown, as it's incredibly useful. >>>> + PK11_SetPasswordFunc(PQssl_passwd_cb); >>>=20 >>> Is it actually OK to do stuff like this when other users of NSS = might be >>> present? That's obviously more likely in the libpq case, compared to = the >>> backend case (where it's also possible, of course). What prevents us >>> from overriding another user's callback? >>=20 >> The password callback pointer is stored in a static variable in NSS = (in the >> file lib/pk11wrap/pk11auth.c). >=20 > But, uh, how is that not a problem? What happens if a backend imports > libpq? What if plpython imports curl which then also uses nss? Sorry, that sentence wasn't really finished. What I meant to write was = that I don't really have good answers here. The available implementation is = via the static var, and there are no alternative APIs. I've tried googling for insights but haven't come across any. The only datapoint I have is that I can't recall there ever being a = complaint against libcurl doing this exact thing. That of course doesn't mean it = cannot happen or cause problems. >> + /* >> + * Finally we must configure the socket for being a server by = setting the >> + * certificate and key. >> + */ >> + status =3D SSL_ConfigSecureServer(model, server_cert, = private_key, kt_rsa); >> + if (status !=3D SECSuccess) >> + ereport(ERROR, >> + (errmsg("unable to configure secure = server: %s", >> + = pg_SSLerrmessage(PR_GetError())))); >> + status =3D SSL_ConfigServerCert(model, server_cert, private_key, = NULL, 0); >> + if (status !=3D SECSuccess) >> + ereport(ERROR, >> + (errmsg("unable to configure server for = TLS server connections: %s", >> + = pg_SSLerrmessage(PR_GetError())))); >=20 > Why do both of these need to get called? The NSS docs say: >=20 > /* > ** Deprecated variant of SSL_ConfigServerCert. > ** > ... > SSL_IMPORT SECStatus SSL_ConfigSecureServer( > PRFileDesc *fd, CERTCertificate *ce rt, > SECKEYPrivateKey *key, SSLKEAType kea); They don't, I had missed the deprecation warning as it's not mentioned = at all in the online documentation: = https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/SSL_function= s/sslfnc.html (SSL_ConfigServerCert isn't at all mentioned there which dates it to = before this went it obsoleting SSL_ConfigSecureServer.) Fixed by removing the superfluous call. Thanks again for reviewing! cheers ./daniel --Apple-Mail=_C39967DC-7CE2-4297-8DC3-75F0E858FBDB Content-Disposition: attachment; filename=v15-0001-NSS-Frontend-Backend-and-build-infra.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v15-0001-NSS-Frontend-Backend-and-build-infra.patch" Content-Transfer-Encoding: quoted-printable =46rom=2067efed92f5b60196066b79cae1fdb775f0edd785=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2028=20Oct=202020=2011:18:42=20+0100=0ASubject:=20[PATCH=20= v15=201/6]=20NSS=20Frontend,=20Backend=20and=20build=20infra=0A=0A---=0A=20= configure=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20401=20+++++-=0A=20= configure.ac=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=2060=20+-=0A=20= .../postgres_fdw/expected/postgres_fdw.out=20=20=20=20|=20=20=20=202=20= +-=0A=20src/Makefile.global.in=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20=20=20=202=20+-=0A=20= src/backend/libpq/Makefile=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20|=20=20=20=206=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=207=20+=0A= =20src/backend/libpq/be-secure-nss.c=20=20=20=20=20=20=20=20=20=20=20=20=20= |=201173=20+++++++++++++++++=0A=20src/backend/libpq/be-secure.c=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=20=203=20+=0A=20= src/backend/libpq/hba.c=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20|=20=20=20=202=20+-=0A=20src/backend/utils/misc/guc.c=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=2020=20+-=0A=20= src/common/Makefile=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20=20=20=202=20+-=0A=20= src/include/common/pg_nss.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20|=20=20141=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=2013=20+-=0A=20= src/include/libpq/libpq.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20|=20=20=20=203=20+=0A=20src/include/pg_config.h.in=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=20=203=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=205=20+-=0A=20src/interfaces/libpq/Makefile=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20|=20=20=2013=20+-=0A=20= src/interfaces/libpq/fe-connect.c=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=20=204=20+=0A=20src/interfaces/libpq/fe-secure-nss.c=20=20=20=20=20= =20=20=20=20=20|=201018=20++++++++++++++=0A=20= src/interfaces/libpq/fe-secure.c=20=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=20=205=20+-=0A=20src/interfaces/libpq/libpq-fe.h=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20=20=2011=20+=0A=20= src/interfaces/libpq/libpq-int.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=20=205=20+=0A=20src/tools/msvc/Mkvcbuild.pm=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20|=20=20=2022=20+-=0A=20= src/tools/msvc/Solution.pm=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20|=20=20=2020=20+=0A=20src/tools/msvc/config_default.pl=20=20=20= =20=20=20=20=20=20=20=20=20=20=20|=20=20=20=201=20+=0A=2025=20files=20= changed,=202871=20insertions(+),=2071=20deletions(-)=0A=20create=20mode=20= 100644=20src/backend/libpq/be-secure-nss.c=0A=20create=20mode=20100644=20= src/include/common/pg_nss.h=0A=20create=20mode=20100644=20= src/interfaces/libpq/fe-secure-nss.c=0A=0Adiff=20--git=20a/configure=20= b/configure=0Aindex=20ace4ed5dec..6287a0e2fe=20100755=0A---=20= a/configure=0A+++=20b/configure=0A@@=20-654,6=20+654,9=20@@=20LIBOBJS=0A=20= UUID_LIBS=0A=20LDAP_LIBS_BE=0A=20LDAP_LIBS_FE=0A+with_ssl=0A+NSPR_CONFIG=0A= +NSS_CONFIG=0A=20PTHREAD_CFLAGS=0A=20PTHREAD_LIBS=0A=20PTHREAD_CC=0A@@=20= -711,7=20+714,6=20@@=20with_uuid=0A=20with_readline=0A=20with_systemd=0A=20= with_selinux=0A-with_openssl=0A=20with_ldap=0A=20with_krb_srvnam=0A=20= krb_srvtab=0A@@=20-856,7=20+858,6=20@@=20with_pam=0A=20with_bsd_auth=0A=20= with_ldap=0A=20with_bonjour=0A-with_openssl=0A=20with_selinux=0A=20= with_systemd=0A=20with_readline=0A@@=20-868,6=20+869,8=20@@=20= with_libxslt=0A=20with_system_tzdata=0A=20with_zlib=0A=20with_gnu_ld=0A= +with_ssl=0A+with_openssl=0A=20enable_largefile=0A=20'=0A=20=20=20=20=20=20= =20ac_precious_vars=3D'build_alias=0A@@=20-1558,7=20+1561,6=20@@=20= Optional=20Packages:=0A=20=20=20--with-bsd-auth=20=20=20=20=20=20=20=20=20= build=20with=20BSD=20Authentication=20support=0A=20=20=20--with-ldap=20=20= =20=20=20=20=20=20=20=20=20=20=20build=20with=20LDAP=20support=0A=20=20=20= --with-bonjour=20=20=20=20=20=20=20=20=20=20build=20with=20Bonjour=20= support=0A-=20=20--with-openssl=20=20=20=20=20=20=20=20=20=20build=20= with=20OpenSSL=20support=0A=20=20=20--with-selinux=20=20=20=20=20=20=20=20= =20=20build=20with=20SELinux=20support=0A=20=20=20--with-systemd=20=20=20= =20=20=20=20=20=20=20build=20with=20systemd=20support=0A=20=20=20= --without-readline=20=20=20=20=20=20do=20not=20use=20GNU=20Readline=20= nor=20BSD=20Libedit=20for=20editing=0A@@=20-1572,6=20+1574,8=20@@=20= Optional=20Packages:=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20use=20system=20time=20zone=20data=20in=20= DIR=0A=20=20=20--without-zlib=20=20=20=20=20=20=20=20=20=20do=20not=20= use=20Zlib=0A=20=20=20--with-gnu-ld=20=20=20=20=20=20=20=20=20=20=20= assume=20the=20C=20compiler=20uses=20GNU=20ld=20[default=3Dno]=0A+=20=20= --with-ssl=3DLIB=20=20=20=20=20=20=20=20=20=20use=20LIB=20for=20SSL/TLS=20= support=20(openssl,=20nss)=0A+=20=20--with-openssl=20=20=20=20=20=20=20=20= =20=20obsolete=20spelling=20of=20--with-ssl=3Dopenssl=0A=20=0A=20Some=20= influential=20environment=20variables:=0A=20=20=20CC=20=20=20=20=20=20=20= =20=20=20C=20compiler=20command=0A@@=20-8071,41=20+8075,6=20@@=20fi=0A=20= $as_echo=20"$with_bonjour"=20>&6;=20}=0A=20=0A=20=0A-#=0A-#=20OpenSSL=0A= -#=0A-{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20checking=20whether=20= to=20build=20with=20OpenSSL=20support"=20>&5=0A-$as_echo_n=20"checking=20= whether=20to=20build=20with=20OpenSSL=20support...=20"=20>&6;=20}=0A-=0A= -=0A-=0A-#=20Check=20whether=20--with-openssl=20was=20given.=0A-if=20= test=20"${with_openssl+set}"=20=3D=20set;=20then=20:=0A-=20=20= withval=3D$with_openssl;=0A-=20=20case=20$withval=20in=0A-=20=20=20=20= yes)=0A-=0A-$as_echo=20"#define=20USE_OPENSSL=201"=20>>confdefs.h=0A-=0A= -=20=20=20=20=20=20;;=0A-=20=20=20=20no)=0A-=20=20=20=20=20=20:=0A-=20=20= =20=20=20=20;;=0A-=20=20=20=20*)=0A-=20=20=20=20=20=20as_fn_error=20$?=20= "no=20argument=20expected=20for=20--with-openssl=20option"=20"$LINENO"=20= 5=0A-=20=20=20=20=20=20;;=0A-=20=20esac=0A-=0A-else=0A-=20=20= with_openssl=3Dno=0A-=0A-fi=0A-=0A-=0A-{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20$with_openssl"=20>&5=0A= -$as_echo=20"$with_openssl"=20>&6;=20}=0A-=0A-=0A=20#=0A=20#=20SELinux=0A= =20#=0A@@=20-12179,7=20+12148,64=20@@=20fi=0A=20=20=20fi=0A=20fi=0A=20=0A= +#=0A+#=20SSL=20Library=0A+#=0A+#=20There=20are=20currently=20two=20= supported=20SSL/TLS=20libraries,=20OpenSSL=20and=20NSS.=0A+#=0A+=0A+=0A+=0A= +#=20Check=20whether=20--with-ssl=20was=20given.=0A+if=20test=20= "${with_ssl+set}"=20=3D=20set;=20then=20:=0A+=20=20withval=3D$with_ssl;=0A= +=20=20case=20$withval=20in=0A+=20=20=20=20yes)=0A+=20=20=20=20=20=20= as_fn_error=20$?=20"argument=20required=20for=20--with-ssl=20option"=20= "$LINENO"=205=0A+=20=20=20=20=20=20;;=0A+=20=20=20=20no)=0A+=20=20=20=20=20= =20as_fn_error=20$?=20"argument=20required=20for=20--with-ssl=20option"=20= "$LINENO"=205=0A+=20=20=20=20=20=20;;=0A+=20=20=20=20*)=0A+=0A+=20=20=20=20= =20=20;;=0A+=20=20esac=0A+=0A+fi=0A+=0A+=0A+if=20test=20x"$with_ssl"=20=3D= =20x""=20;=20then=0A+=20=20with_ssl=3Dno=0A+fi=0A+=0A+=0A+=0A+#=20Check=20= whether=20--with-openssl=20was=20given.=0A+if=20test=20= "${with_openssl+set}"=20=3D=20set;=20then=20:=0A+=20=20= withval=3D$with_openssl;=0A+=20=20case=20$withval=20in=0A+=20=20=20=20= yes)=0A+=20=20=20=20=20=20:=0A+=20=20=20=20=20=20;;=0A+=20=20=20=20no)=0A= +=20=20=20=20=20=20:=0A+=20=20=20=20=20=20;;=0A+=20=20=20=20*)=0A+=20=20=20= =20=20=20as_fn_error=20$?=20"no=20argument=20expected=20for=20= --with-openssl=20option"=20"$LINENO"=205=0A+=20=20=20=20=20=20;;=0A+=20=20= esac=0A+=0A+else=0A+=20=20with_openssl=3Dno=0A+=0A+fi=0A+=0A+=0A=20if=20= test=20"$with_openssl"=20=3D=20yes=20;=20then=0A+=20=20with_ssl=3Dopenssl=0A= +fi=0A+=0A+if=20test=20"$with_ssl"=20=3D=20openssl=20;=20then=0A=20=20=20= =20=20#=20Minimum=20required=20OpenSSL=20version=20is=201.0.1=0A=20=0A=20= $as_echo=20"#define=20OPENSSL_API_COMPAT=200x10001000L"=20>>confdefs.h=0A= @@=20-12440,8=20+12466,280=20@@=20_ACEOF=0A=20fi=0A=20done=0A=20=0A+=0A= +$as_echo=20"#define=20USE_OPENSSL=201"=20>>confdefs.h=0A+=0A+elif=20= test=20"$with_ssl"=20=3D=20nss=20;=20then=0A+=20=20#=20TODO:=20fallback=20= in=20case=20nss-config/nspr-config=20aren't=20found.=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=20= it=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}:=20= checking=20for=20$ac_word"=20>&5=0A+$as_echo_n=20"checking=20for=20= $ac_word...=20"=20>&6;=20}=0A+if=20${ac_cv_path_NSS_CONFIG+:}=20false;=20= then=20:=0A+=20=20$as_echo_n=20"(cached)=20"=20>&6=0A+else=0A+=20=20case=20= $NSS_CONFIG=20in=0A+=20=20[\\/]*=20|=20?:[\\/]*)=0A+=20=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=20fi=0A=20=0A+=0A+=20=20test=20-n=20= "$NSS_CONFIG"=20&&=20break=0A+done=0A+=0A+else=0A+=20=20#=20Report=20the=20= value=20of=20NSS_CONFIG=20in=20configure's=20output=20in=20all=20cases.=0A= +=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20checking=20for=20= NSS_CONFIG"=20>&5=0A+$as_echo_n=20"checking=20for=20NSS_CONFIG...=20"=20= >&6;=20}=0A+=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20= $NSS_CONFIG"=20>&5=0A+$as_echo=20"$NSS_CONFIG"=20>&6;=20}=0A+fi=0A+=0A+=20= =20if=20test=20-z=20"$NSPR_CONFIG";=20then=0A+=20=20for=20ac_prog=20in=20= nspr-config=0A+do=0A+=20=20#=20Extract=20the=20first=20word=20of=20= "$ac_prog",=20so=20it=20can=20be=20a=20program=20name=20with=20args.=0A= +set=20dummy=20$ac_prog;=20ac_word=3D$2=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20$ac_word"=20>&5=0A= +$as_echo_n=20"checking=20for=20$ac_word...=20"=20>&6;=20}=0A+if=20= ${ac_cv_path_NSPR_CONFIG+:}=20false;=20then=20:=0A+=20=20$as_echo_n=20= "(cached)=20"=20>&6=0A+else=0A+=20=20case=20$NSPR_CONFIG=20in=0A+=20=20= [\\/]*=20|=20?:[\\/]*)=0A+=20=20ac_cv_path_NSPR_CONFIG=3D"$NSPR_CONFIG"=20= #=20Let=20the=20user=20override=20the=20test=20with=20a=20path.=0A+=20=20= ;;=0A+=20=20*)=0A+=20=20as_save_IFS=3D$IFS;=20IFS=3D$PATH_SEPARATOR=0A= +for=20as_dir=20in=20$PATH=0A+do=0A+=20=20IFS=3D$as_save_IFS=0A+=20=20= test=20-z=20"$as_dir"=20&&=20as_dir=3D.=0A+=20=20=20=20for=20ac_exec_ext=20= in=20''=20$ac_executable_extensions;=20do=0A+=20=20if=20= as_fn_executable_p=20"$as_dir/$ac_word$ac_exec_ext";=20then=0A+=20=20=20=20= ac_cv_path_NSPR_CONFIG=3D"$as_dir/$ac_word$ac_exec_ext"=0A+=20=20=20=20= $as_echo=20"$as_me:${as_lineno-$LINENO}:=20found=20= $as_dir/$ac_word$ac_exec_ext"=20>&5=0A+=20=20=20=20break=202=0A+=20=20fi=0A= +done=0A+=20=20done=0A+IFS=3D$as_save_IFS=0A+=0A+=20=20;;=0A+esac=0A+fi=0A= +NSPR_CONFIG=3D$ac_cv_path_NSPR_CONFIG=0A+if=20test=20-n=20= "$NSPR_CONFIG";=20then=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20$NSPR_CONFIG"=20>&5=0A= +$as_echo=20"$NSPR_CONFIG"=20>&6;=20}=0A+else=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20no"=20>&5=0A+$as_echo=20"no"=20= >&6;=20}=0A+fi=0A+=0A+=0A+=20=20test=20-n=20"$NSPR_CONFIG"=20&&=20break=0A= +done=0A+=0A+else=0A+=20=20#=20Report=20the=20value=20of=20NSPR_CONFIG=20= in=20configure's=20output=20in=20all=20cases.=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20NSPR_CONFIG"=20>&5=0A= +$as_echo_n=20"checking=20for=20NSPR_CONFIG...=20"=20>&6;=20}=0A+=20=20{=20= $as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20$NSPR_CONFIG"=20>&5=0A= +$as_echo=20"$NSPR_CONFIG"=20>&6;=20}=0A+fi=0A+=0A+=20=20if=20test=20-n=20= "$NSS_CONFIG";=20then=0A+=20=20=20=20NSS_LIBS=3D`$NSS_CONFIG=20--libs`=0A= +=09NSS_CFLAGS=3D`$NSS_CONFIG=20--cflags`=0A+=20=20fi=0A+=20=20if=20test=20= -n=20"$NSPR_CONFIG";=20then=0A+=09NSPR_LIBS=3D`$NSPR_CONFIG=20--libs`=0A= +=09NSPR_CFLAGS=3D`$NSPR_CONFIG=20--cflags`=0A+=20=20fi=0A+=0A+=20=20= LDFLAGS=3D"$LDFLAGS=20$NSS_LIBS=20$NSPR_LIBS"=0A+=20=20CFLAGS=3D"$CFLAGS=20= $NSS_CFLAGS=20$NSPR_CFLAGS"=0A+=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20SSL_VersionRangeSet=20= in=20-lnss3"=20>&5=0A+$as_echo_n=20"checking=20for=20SSL_VersionRangeSet=20= in=20-lnss3...=20"=20>&6;=20}=0A+if=20= ${ac_cv_lib_nss3_SSL_VersionRangeSet+:}=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"-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= SSL_VersionRangeSet=20();=0A+int=0A+main=20()=0A+{=0A+return=20= SSL_VersionRangeSet=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_SSL_VersionRangeSet=3Dyes=0A+else=0A+=20=20= ac_cv_lib_nss3_SSL_VersionRangeSet=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_SSL_VersionRangeSet"=20>&5=0A+$as_echo=20= "$ac_cv_lib_nss3_SSL_VersionRangeSet"=20>&6;=20}=0A+if=20test=20= "x$ac_cv_lib_nss3_SSL_VersionRangeSet"=20=3D=20xyes;=20then=20:=0A+=20=20= cat=20>>confdefs.h=20<<_ACEOF=0A+#define=20HAVE_LIBNSS3=201=0A+_ACEOF=0A= +=0A+=20=20LIBS=3D"-lnss3=20$LIBS"=0A+=0A+else=0A+=20=20as_fn_error=20$?=20= "library=20'nss3'=20is=20required=20for=20NSS"=20"$LINENO"=205=0A+fi=0A+=0A= +=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20checking=20for=20= PR_GetDefaultIOMethods=20in=20-lnspr4"=20>&5=0A+$as_echo_n=20"checking=20= for=20PR_GetDefaultIOMethods=20in=20-lnspr4...=20"=20>&6;=20}=0A+if=20= ${ac_cv_lib_nspr4_PR_GetDefaultIOMethods+:}=20false;=20then=20:=0A+=20=20= $as_echo_n=20"(cached)=20"=20>&6=0A+else=0A+=20=20= ac_check_lib_save_LIBS=3D$LIBS=0A+LIBS=3D"-lnspr4=20=20$LIBS"=0A+cat=20= confdefs.h=20-=20<<_ACEOF=20>conftest.$ac_ext=0A+/*=20end=20confdefs.h.=20= =20*/=0A+=0A+/*=20Override=20any=20GCC=20internal=20prototype=20to=20= avoid=20an=20error.=0A+=20=20=20Use=20char=20because=20int=20might=20= match=20the=20return=20type=20of=20a=20GCC=0A+=20=20=20builtin=20and=20= then=20its=20argument=20prototype=20would=20still=20apply.=20=20*/=0A= +#ifdef=20__cplusplus=0A+extern=20"C"=0A+#endif=0A+char=20= PR_GetDefaultIOMethods=20();=0A+int=0A+main=20()=0A+{=0A+return=20= PR_GetDefaultIOMethods=20();=0A+=20=20;=0A+=20=20return=200;=0A+}=0A= +_ACEOF=0A+if=20ac_fn_c_try_link=20"$LINENO";=20then=20:=0A+=20=20= ac_cv_lib_nspr4_PR_GetDefaultIOMethods=3Dyes=0A+else=0A+=20=20= ac_cv_lib_nspr4_PR_GetDefaultIOMethods=3Dno=0A+fi=0A+rm=20-f=20core=20= conftest.err=20conftest.$ac_objext=20\=0A+=20=20=20=20conftest$ac_exeext=20= conftest.$ac_ext=0A+LIBS=3D$ac_check_lib_save_LIBS=0A+fi=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20= $ac_cv_lib_nspr4_PR_GetDefaultIOMethods"=20>&5=0A+$as_echo=20= "$ac_cv_lib_nspr4_PR_GetDefaultIOMethods"=20>&6;=20}=0A+if=20test=20= "x$ac_cv_lib_nspr4_PR_GetDefaultIOMethods"=20=3D=20xyes;=20then=20:=0A+=20= =20cat=20>>confdefs.h=20<<_ACEOF=0A+#define=20HAVE_LIBNSPR4=201=0A= +_ACEOF=0A+=0A+=20=20LIBS=3D"-lnspr4=20$LIBS"=0A+=0A+else=0A+=20=20= as_fn_error=20$?=20"library=20'nspr4'=20is=20required=20for=20NSS"=20= "$LINENO"=205=0A+fi=0A+=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20= SSL_GetImplementedCiphers=20in=20-lssl3"=20>&5=0A+$as_echo_n=20"checking=20= for=20SSL_GetImplementedCiphers=20in=20-lssl3...=20"=20>&6;=20}=0A+if=20= ${ac_cv_lib_ssl3_SSL_GetImplementedCiphers+:}=20false;=20then=20:=0A+=20=20= $as_echo_n=20"(cached)=20"=20>&6=0A+else=0A+=20=20= ac_check_lib_save_LIBS=3D$LIBS=0A+LIBS=3D"-lssl3=20=20$LIBS"=0A+cat=20= confdefs.h=20-=20<<_ACEOF=20>conftest.$ac_ext=0A+/*=20end=20confdefs.h.=20= =20*/=0A+=0A+/*=20Override=20any=20GCC=20internal=20prototype=20to=20= avoid=20an=20error.=0A+=20=20=20Use=20char=20because=20int=20might=20= match=20the=20return=20type=20of=20a=20GCC=0A+=20=20=20builtin=20and=20= then=20its=20argument=20prototype=20would=20still=20apply.=20=20*/=0A= +#ifdef=20__cplusplus=0A+extern=20"C"=0A+#endif=0A+char=20= SSL_GetImplementedCiphers=20();=0A+int=0A+main=20()=0A+{=0A+return=20= SSL_GetImplementedCiphers=20();=0A+=20=20;=0A+=20=20return=200;=0A+}=0A= +_ACEOF=0A+if=20ac_fn_c_try_link=20"$LINENO";=20then=20:=0A+=20=20= ac_cv_lib_ssl3_SSL_GetImplementedCiphers=3Dyes=0A+else=0A+=20=20= ac_cv_lib_ssl3_SSL_GetImplementedCiphers=3Dno=0A+fi=0A+rm=20-f=20core=20= conftest.err=20conftest.$ac_objext=20\=0A+=20=20=20=20conftest$ac_exeext=20= conftest.$ac_ext=0A+LIBS=3D$ac_check_lib_save_LIBS=0A+fi=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20= $ac_cv_lib_ssl3_SSL_GetImplementedCiphers"=20>&5=0A+$as_echo=20= "$ac_cv_lib_ssl3_SSL_GetImplementedCiphers"=20>&6;=20}=0A+if=20test=20= "x$ac_cv_lib_ssl3_SSL_GetImplementedCiphers"=20=3D=20xyes;=20then=20:=0A= +=20=20cat=20>>confdefs.h=20<<_ACEOF=0A+#define=20HAVE_LIBSSL3=201=0A= +_ACEOF=0A+=0A+=20=20LIBS=3D"-lssl3=20$LIBS"=0A+=0A+else=0A+=20=20= as_fn_error=20$?=20"library=20'ssl3'=20is=20required=20for=20NSS"=20= "$LINENO"=205=0A+fi=0A+=0A+=0A+$as_echo=20"#define=20USE_NSS=201"=20= >>confdefs.h=0A+=0A+elif=20test=20"$with_ssl"=20!=3D=20no=20;=20then=0A+=20= =20as_fn_error=20$?=20"--with-ssl=20must=20specify=20one=20of=20openssl=20= or=20nss"=20"$LINENO"=205=0A+fi=0A+=0A+=0A=20if=20test=20"$with_pam"=20=3D= =20yes=20;=20then=0A=20=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20pam_start=20in=20-lpam"=20= >&5=0A=20$as_echo_n=20"checking=20for=20pam_start=20in=20-lpam...=20"=20= >&6;=20}=0A@@=20-13327,7=20+13625,7=20@@=20done=0A=20=0A=20fi=0A=20=0A= -if=20test=20"$with_openssl"=20=3D=20yes=20;=20then=0A+if=20test=20= "$with_ssl"=20=3D=20openssl=20;=20then=0A=20=20=20= ac_fn_c_check_header_mongrel=20"$LINENO"=20"openssl/ssl.h"=20= "ac_cv_header_openssl_ssl_h"=20"$ac_includes_default"=0A=20if=20test=20= "x$ac_cv_header_openssl_ssl_h"=20=3D=20xyes;=20then=20:=0A=20=0A@@=20= -13344,6=20+13642,25=20@@=20else=0A=20fi=0A=20=0A=20=0A+fi=0A+=0A+if=20= test=20"$with_ssl"=20=3D=20nss=20;=20then=0A+=20=20= ac_fn_c_check_header_mongrel=20"$LINENO"=20"nss/ssl.h"=20= "ac_cv_header_nss_ssl_h"=20"$ac_includes_default"=0A+if=20test=20= "x$ac_cv_header_nss_ssl_h"=20=3D=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+=20=20ac_fn_c_check_header_mongrel=20= "$LINENO"=20"nss/nss.h"=20"ac_cv_header_nss_nss_h"=20= "$ac_includes_default"=0A+if=20test=20"x$ac_cv_header_nss_nss_h"=20=3D=20= xyes;=20then=20:=0A+=0A+else=0A+=20=20as_fn_error=20$?=20"header=20file=20= =20is=20required=20for=20NSS"=20"$LINENO"=205=0A+fi=0A+=0A+=0A= =20fi=0A=20=0A=20if=20test=20"$with_pam"=20=3D=20yes=20;=20then=0A@@=20= -18061,11=20+18378,13=20@@=20fi=0A=20#=20in=20the=20template=20or=20= configure=20command=20line.=0A=20=0A=20#=20If=20not=20selected=20= manually,=20try=20to=20select=20a=20source=20automatically.=0A-if=20test=20= x"$USE_OPENSSL_RANDOM"=20=3D=20x""=20&&=20test=20x"$USE_WIN32_RANDOM"=20= =3D=20x""=20&&=20test=20x"$USE_DEV_URANDOM"=20=3D=20x""=20;=20then=0A-=20= =20if=20test=20x"$with_openssl"=20=3D=20x"yes"=20;=20then=0A+if=20test=20= x"$USE_OPENSSL_RANDOM"=20=3D=20x""=20&&=20test=20x"$USE_WIN32_RANDOM"=20= =3D=20x""=20&&=20test=20x"$USE_DEV_URANDOM"=20=3D=20x""=20&&=20test=20= x"$USE_NSS_RANDOM"=20=3D=20x""=20;=20then=0A+=20=20if=20test=20= x"$with_ssl"=20=3D=20x"openssl"=20;=20then=0A=20=20=20=20=20= USE_OPENSSL_RANDOM=3D1=0A=20=20=20elif=20test=20"$PORTNAME"=20=3D=20= "win32"=20;=20then=0A=20=20=20=20=20USE_WIN32_RANDOM=3D1=0A+=20=20elif=20= test=20x"$with_ssl"=20=3D=20x"nss"=20;=20then=0A+=20=20=20=20= USE_NSS_RANDOM=3D1=0A=20=20=20else=0A=20=20=20=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20/dev/urandom"=20>&5=0A=20= $as_echo_n=20"checking=20for=20/dev/urandom...=20"=20>&6;=20}=0Adiff=20= --git=20a/configure.ac=20b/configure.ac=0Aindex=205b91c83fd0..706c9862e7=20= 100644=0A---=20a/configure.ac=0A+++=20b/configure.ac=0A@@=20-852,15=20= +852,6=20@@=20PGAC_ARG_BOOL(with,=20bonjour,=20no,=0A=20= AC_MSG_RESULT([$with_bonjour])=0A=20=0A=20=0A-#=0A-#=20OpenSSL=0A-#=0A= -AC_MSG_CHECKING([whether=20to=20build=20with=20OpenSSL=20support])=0A= -PGAC_ARG_BOOL(with,=20openssl,=20no,=20[build=20with=20OpenSSL=20= support],=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= [AC_DEFINE([USE_OPENSSL],=201,=20[Define=20to=20build=20with=20OpenSSL=20= support.=20(--with-openssl)])])=0A-AC_MSG_RESULT([$with_openssl])=0A= -AC_SUBST(with_openssl)=0A-=0A=20#=0A=20#=20SELinux=0A=20#=0A@@=20= -1209,7=20+1200,21=20@@=20if=20test=20"$with_gssapi"=20=3D=20yes=20;=20= then=0A=20=20=20fi=0A=20fi=0A=20=0A+#=0A+#=20SSL=20Library=0A+#=0A+#=20= There=20are=20currently=20two=20supported=20SSL/TLS=20libraries,=20= OpenSSL=20and=20NSS.=0A+#=0A+PGAC_ARG_REQ(with,=20ssl,=20[LIB],=20[use=20= LIB=20for=20SSL/TLS=20support=20(openssl,=20nss)])=0A+if=20test=20= x"$with_ssl"=20=3D=20x""=20;=20then=0A+=20=20with_ssl=3Dno=0A+fi=0A= +PGAC_ARG_BOOL(with,=20openssl,=20no,=20[obsolete=20spelling=20of=20= --with-ssl=3Dopenssl])=0A=20if=20test=20"$with_openssl"=20=3D=20yes=20;=20= then=0A+=20=20with_ssl=3Dopenssl=0A+fi=0A+=0A+if=20test=20"$with_ssl"=20= =3D=20openssl=20;=20then=0A=20=20=20dnl=20Order=20matters!=0A=20=20=20#=20= Minimum=20required=20OpenSSL=20version=20is=201.0.1=0A=20=20=20= AC_DEFINE(OPENSSL_API_COMPAT,=20[0x10001000L],=0A@@=20-1233,7=20+1238,31=20= @@=20if=20test=20"$with_openssl"=20=3D=20yes=20;=20then=0A=20=20=20#=20= thread-safety.=20In=201.1.0,=20it's=20no=20longer=20required,=20and=20= CRYPTO_lock()=0A=20=20=20#=20function=20was=20removed.=0A=20=20=20= AC_CHECK_FUNCS([CRYPTO_lock])=0A+=20=20AC_DEFINE([USE_OPENSSL],=201,=20= [Define=20to=201=20if=20you=20have=20OpenSSL=20support.])=0A+elif=20test=20= "$with_ssl"=20=3D=20nss=20;=20then=0A+=20=20#=20TODO:=20fallback=20in=20= case=20nss-config/nspr-config=20aren't=20found.=0A+=20=20= PGAC_PATH_PROGS(NSS_CONFIG,=20nss-config)=0A+=20=20= PGAC_PATH_PROGS(NSPR_CONFIG,=20nspr-config)=0A+=20=20if=20test=20-n=20= "$NSS_CONFIG";=20then=0A+=20=20=20=20NSS_LIBS=3D`$NSS_CONFIG=20--libs`=0A= +=09NSS_CFLAGS=3D`$NSS_CONFIG=20--cflags`=0A+=20=20fi=0A+=20=20if=20test=20= -n=20"$NSPR_CONFIG";=20then=0A+=09NSPR_LIBS=3D`$NSPR_CONFIG=20--libs`=0A= +=09NSPR_CFLAGS=3D`$NSPR_CONFIG=20--cflags`=0A+=20=20fi=0A+=0A+=20=20= LDFLAGS=3D"$LDFLAGS=20$NSS_LIBS=20$NSPR_LIBS"=0A+=20=20CFLAGS=3D"$CFLAGS=20= $NSS_CFLAGS=20$NSPR_CFLAGS"=0A+=0A+=20=20AC_CHECK_LIB(nss3,=20= SSL_VersionRangeSet,=20[],=20[AC_MSG_ERROR([library=20'nss3'=20is=20= required=20for=20NSS])])=0A+=20=20AC_CHECK_LIB(nspr4,=20= PR_GetDefaultIOMethods,=20[],=20[AC_MSG_ERROR([library=20'nspr4'=20is=20= required=20for=20NSS])])=0A+=20=20AC_CHECK_LIB(ssl3,=20= SSL_GetImplementedCiphers,=20[],=20[AC_MSG_ERROR([library=20'ssl3'=20is=20= required=20for=20NSS])])=0A+=20=20AC_DEFINE([USE_NSS],=201,=20[Define=20= to=201=20if=20you=20have=20NSS=20support,])=0A+elif=20test=20"$with_ssl"=20= !=3D=20no=20;=20then=0A+=20=20AC_MSG_ERROR([--with-ssl=20must=20specify=20= one=20of=20openssl=20or=20nss])=0A=20fi=0A+AC_SUBST(with_ssl)=0A=20=0A=20= if=20test=20"$with_pam"=20=3D=20yes=20;=20then=0A=20=20=20= AC_CHECK_LIB(pam,=20=20=20=20pam_start,=20[],=20[AC_MSG_ERROR([library=20= 'pam'=20is=20required=20for=20PAM])])=0A@@=20-1405,11=20+1434,16=20@@=20= if=20test=20"$with_gssapi"=20=3D=20yes=20;=20then=0A=20=09= [AC_CHECK_HEADERS(gssapi.h,=20[],=20[AC_MSG_ERROR([gssapi.h=20header=20= file=20is=20required=20for=20GSSAPI])])])=0A=20fi=0A=20=0A-if=20test=20= "$with_openssl"=20=3D=20yes=20;=20then=0A+if=20test=20"$with_ssl"=20=3D=20= openssl=20;=20then=0A=20=20=20AC_CHECK_HEADER(openssl/ssl.h,=20[],=20= [AC_MSG_ERROR([header=20file=20=20is=20required=20for=20= OpenSSL])])=0A=20=20=20AC_CHECK_HEADER(openssl/err.h,=20[],=20= [AC_MSG_ERROR([header=20file=20=20is=20required=20for=20= OpenSSL])])=0A=20fi=0A=20=0A+if=20test=20"$with_ssl"=20=3D=20nss=20;=20= then=0A+=20=20AC_CHECK_HEADER(nss/ssl.h,=20[],=20[AC_MSG_ERROR([header=20= file=20=20is=20required=20for=20NSS])])=0A+=20=20= AC_CHECK_HEADER(nss/nss.h,=20[],=20[AC_MSG_ERROR([header=20file=20= =20is=20required=20for=20NSS])])=0A+fi=0A+=0A=20if=20test=20= "$with_pam"=20=3D=20yes=20;=20then=0A=20=20=20= AC_CHECK_HEADERS(security/pam_appl.h,=20[],=0A=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20[AC_CHECK_HEADERS(pam/pam_appl.h,=20[],=0A= @@=20-2158,11=20+2192,13=20@@=20fi=0A=20#=20in=20the=20template=20or=20= configure=20command=20line.=0A=20=0A=20#=20If=20not=20selected=20= manually,=20try=20to=20select=20a=20source=20automatically.=0A-if=20test=20= x"$USE_OPENSSL_RANDOM"=20=3D=20x""=20&&=20test=20x"$USE_WIN32_RANDOM"=20= =3D=20x""=20&&=20test=20x"$USE_DEV_URANDOM"=20=3D=20x""=20;=20then=0A-=20= =20if=20test=20x"$with_openssl"=20=3D=20x"yes"=20;=20then=0A+if=20test=20= x"$USE_OPENSSL_RANDOM"=20=3D=20x""=20&&=20test=20x"$USE_WIN32_RANDOM"=20= =3D=20x""=20&&=20test=20x"$USE_DEV_URANDOM"=20=3D=20x""=20&&=20test=20= x"$USE_NSS_RANDOM"=20=3D=20x""=20;=20then=0A+=20=20if=20test=20= x"$with_ssl"=20=3D=20x"openssl"=20;=20then=0A=20=20=20=20=20= USE_OPENSSL_RANDOM=3D1=0A=20=20=20elif=20test=20"$PORTNAME"=20=3D=20= "win32"=20;=20then=0A=20=20=20=20=20USE_WIN32_RANDOM=3D1=0A+=20=20elif=20= test=20x"$with_ssl"=20=3D=20x"nss"=20;=20then=0A+=20=20=20=20= USE_NSS_RANDOM=3D1=0A=20=20=20else=0A=20=20=20=20=20= AC_CHECK_FILE([/dev/urandom],=20[],=20[])=0A=20=0Adiff=20--git=20= a/contrib/postgres_fdw/expected/postgres_fdw.out=20= b/contrib/postgres_fdw/expected/postgres_fdw.out=0Aindex=20= 2d88d06358..984efc0d7e=20100644=0A---=20= a/contrib/postgres_fdw/expected/postgres_fdw.out=0A+++=20= b/contrib/postgres_fdw/expected/postgres_fdw.out=0A@@=20-8911,7=20= +8911,7=20@@=20DO=20$d$=0A=20=20=20=20=20END;=0A=20$d$;=0A=20ERROR:=20=20= invalid=20option=20"password"=0A-HINT:=20=20Valid=20options=20in=20this=20= context=20are:=20service,=20passfile,=20channel_binding,=20= connect_timeout,=20dbname,=20host,=20hostaddr,=20port,=20options,=20= application_name,=20keepalives,=20keepalives_idle,=20= keepalives_interval,=20keepalives_count,=20tcp_user_timeout,=20sslmode,=20= sslcompression,=20sslcert,=20sslkey,=20sslrootcert,=20sslcrl,=20= requirepeer,=20ssl_min_protocol_version,=20ssl_max_protocol_version,=20= gssencmode,=20krbsrvname,=20gsslib,=20target_session_attrs,=20= use_remote_estimate,=20fdw_startup_cost,=20fdw_tuple_cost,=20extensions,=20= updatable,=20fetch_size=0A+HINT:=20=20Valid=20options=20in=20this=20= context=20are:=20service,=20passfile,=20channel_binding,=20= connect_timeout,=20dbname,=20host,=20hostaddr,=20port,=20options,=20= application_name,=20keepalives,=20keepalives_idle,=20= keepalives_interval,=20keepalives_count,=20tcp_user_timeout,=20sslmode,=20= sslcompression,=20sslcert,=20sslkey,=20sslrootcert,=20sslcrl,=20= requirepeer,=20ssl_min_protocol_version,=20ssl_max_protocol_version,=20= gssencmode,=20krbsrvname,=20gsslib,=20target_session_attrs,=20= cert_database,=20use_remote_estimate,=20fdw_startup_cost,=20= fdw_tuple_cost,=20extensions,=20updatable,=20fetch_size=0A=20CONTEXT:=20=20= SQL=20statement=20"ALTER=20SERVER=20loopback_nopw=20OPTIONS=20(ADD=20= password=20'dummypw')"=0A=20PL/pgSQL=20function=20inline_code_block=20= line=203=20at=20EXECUTE=0A=20--=20If=20we=20add=20a=20password=20for=20= our=20user=20mapping=20instead,=20we=20should=20get=20a=20different=0A= diff=20--git=20a/src/Makefile.global.in=20b/src/Makefile.global.in=0A= index=207ca1e9aac5..bdab2a6825=20100644=0A---=20a/src/Makefile.global.in=0A= +++=20b/src/Makefile.global.in=0A@@=20-183,7=20+183,7=20@@=20with_icu=09= =3D=20@with_icu@=0A=20with_perl=09=3D=20@with_perl@=0A=20with_python=09=3D= =20@with_python@=0A=20with_tcl=09=3D=20@with_tcl@=0A-with_openssl=09=3D=20= @with_openssl@=0A+with_ssl=09=3D=20@with_ssl@=0A=20with_readline=09=3D=20= @with_readline@=0A=20with_selinux=09=3D=20@with_selinux@=0A=20= with_systemd=09=3D=20@with_systemd@=0Adiff=20--git=20= a/src/backend/libpq/Makefile=20b/src/backend/libpq/Makefile=0Aindex=20= efc5ef760a..045d2c2f6b=20100644=0A---=20a/src/backend/libpq/Makefile=0A= +++=20b/src/backend/libpq/Makefile=0A@@=20-28,8=20+28,12=20@@=20OBJS=20=3D= =20\=0A=20=09pqmq.o=20\=0A=20=09pqsignal.o=0A=20=0A-ifeq=20= ($(with_openssl),yes)=0A+ifeq=20($(with_ssl),openssl)=0A=20OBJS=20+=3D=20= be-secure-openssl.o=0A+else=0A+ifeq=20($(with_ssl),nss)=0A+OBJS=20+=3D=20= be-secure-nss.o=0A+endif=0A=20endif=0A=20=0A=20ifeq=20= ($(with_gssapi),yes)=0Adiff=20--git=20a/src/backend/libpq/auth.c=20= b/src/backend/libpq/auth.c=0Aindex=20d132c5cb48..d476101583=20100644=0A= ---=20a/src/backend/libpq/auth.c=0A+++=20b/src/backend/libpq/auth.c=0A@@=20= -2870,7=20+2870,14=20@@=20CheckCertAuth(Port=20*port)=0A=20{=0A=20=09int=09= =09=09status_check_usermap=20=3D=20STATUS_ERROR;=0A=20=0A+#if=20= defined(USE_OPENSSL)=0A=20=09Assert(port->ssl);=0A+#elif=20= defined(USE_NSS)=0A+=09/*=20TODO:=20should=20we=20rename=20pr_fd=20to=20= ssl,=20to=20keep=20consistency?=20*/=0A+=09Assert(port->pr_fd);=0A+#else=0A= +=09Assert(false);=0A+#endif=0A=20=0A=20=09/*=20Make=20sure=20we=20have=20= received=20a=20username=20in=20the=20certificate=20*/=0A=20=09if=20= (port->peer_cn=20=3D=3D=20NULL=20||=0Adiff=20--git=20= a/src/backend/libpq/be-secure-nss.c=20= b/src/backend/libpq/be-secure-nss.c=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..b26a4bd620=0A---=20/dev/null=0A+++=20= b/src/backend/libpq/be-secure-nss.c=0A@@=20-0,0=20+1,1173=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20be-secure-nss.c=0A+=20*=09=20=20functions=20for=20= supporting=20NSS=20as=20a=20TLS=20backend=0A+=20*=0A+=20*=0A+=20*=20= Portions=20Copyright=20(c)=201996-2020,=20PostgreSQL=20Global=20= Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=201994,=20= Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=09=20=20src/backend/libpq/be-secure-nss.c=0A+=20*=0A= +=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#include=20"postgres.h"=0A+=0A+#include=20=0A= +=0A+/*=0A+=20*=20BITS_PER_BYTE=20is=20also=20defined=20in=20the=20NSPR=20= header=20files,=20so=20we=20need=20to=20undef=0A+=20*=20our=20version=20= to=20avoid=20compiler=20warnings=20on=20redefinition.=0A+=20*/=0A= +#define=20pg_BITS_PER_BYTE=20BITS_PER_BYTE=0A+#undef=20BITS_PER_BYTE=0A= +=0A+/*=0A+=20*=20The=20nspr/obsolete/protypes.h=20NSPR=20header=20= typedefs=20uint64=20and=20int64=20with=0A+=20*=20colliding=20definitions=20= from=20ours,=20causing=20a=20much=20expected=20compiler=20error.=0A+=20*=20= Remove=20backwards=20compatibility=20with=20ancient=20NSPR=20versions=20= to=20avoid=20this.=0A+=20*/=0A+#define=20NO_NSPR_10_SUPPORT=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+#include=20=0A+=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+=0A+/*=0A+=20*=20Ensure=20that=20the=20= colliding=20definitions=20match,=20else=20throw=20an=20error.=20In=20= case=0A+=20*=20NSPR=20has=20removed=20the=20definition=20for=20some=20= reason,=20make=20sure=20to=20put=20ours=0A+=20*=20back=20again.=0A+=20*/=0A= +#if=20defined(BITS_PER_BYTE)=0A+#if=20BITS_PER_BYTE=20!=3D=20= pg_BITS_PER_BYTE=0A+#error=20"incompatible=20byte=20widths=20between=20= NSPR=20and=20postgres"=0A+#endif=0A+#else=0A+#define=20BITS_PER_BYTE=20= pg_BITS_PER_BYTE=0A+#endif=0A+#undef=20pg_BITS_PER_BYTE=0A+=0A+#include=20= "common/pg_nss.h"=0A+#include=20"lib/stringinfo.h"=0A+#include=20= "libpq/libpq.h"=0A+#include=20"nodes/pg_list.h"=0A+#include=20= "miscadmin.h"=0A+#include=20"storage/fd.h"=0A+#include=20"utils/guc.h"=0A= +#include=20"utils/memutils.h"=0A+=0A+=0A+/*=20default=20init=20hook=20= can=20be=20overridden=20by=20a=20shared=20library=20*/=0A+static=20void=20= default_nss_tls_init(bool=20isServerStart);=0A+nss_tls_init_hook_type=20= nss_tls_init_hook=20=3D=20default_nss_tls_init;=0A+=0A+static=20= PRDescIdentity=20pr_id;=0A+=0A+static=20PRIOMethods=20pr_iomethods;=0A= +static=20NSSInitContext=20*=20nss_context=20=3D=20NULL;=0A+static=20= SSLVersionRange=20desired_sslver;=0A+=0A+static=20char=20= *external_ssl_passphrase_cb(PK11SlotInfo=20*slot,=20PRBool=20retry,=20= void=20*arg);=0A+static=20bool=20dummy_ssl_passwd_cb_called=20=3D=20= false;=0A+static=20bool=20ssl_is_server_start;=0A+=0A+/*=0A+=20*=20= PR_ImportTCPSocket()=20is=20a=20private=20API,=20but=20very=20widely=20= used,=20as=20it's=20the=0A+=20*=20only=20way=20to=20make=20NSS=20use=20= an=20already=20set=20up=20POSIX=20file=20descriptor=20rather=0A+=20*=20= than=20opening=20one=20itself.=20To=20quote=20the=20NSS=20documentation:=0A= +=20*=0A+=20*=09=09"In=20theory,=20code=20that=20uses=20= PR_ImportTCPSocket=20may=20break=20when=20NSPR's=0A+=20*=09=09= implementation=20changes.=20In=20practice,=20this=20is=20unlikely=20to=20= happen=20because=0A+=20*=09=09NSPR's=20implementation=20has=20been=20= stable=20for=20years=20and=20because=20of=20NSPR's=0A+=20*=09=09strong=20= commitment=20to=20backward=20compatibility."=0A+=20*=0A+=20*=20= https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/P= R_ImportTCPSocket=0A+=20*=0A+=20*=20The=20function=20is=20declared=20in=20= ,=20but=20as=20it=20is=20a=20header=20marked=0A+=20*=20= private=20we=20declare=20it=20here=20rather=20than=20including=20it.=0A+=20= */=0A+NSPR_API(PRFileDesc=20*)=20PR_ImportTCPSocket(int);=0A+=0A+/*=20= NSS=20IO=20layer=20callback=20overrides=20*/=0A+static=20PRInt32=20= pg_ssl_read(PRFileDesc=20*=20fd,=20void=20*buf,=20PRInt32=20amount,=0A+=09= =09=09=09=09=09=20=20=20PRIntn=20flags,=20PRIntervalTime=20timeout);=0A= +static=20PRInt32=20pg_ssl_write(PRFileDesc=20*=20fd,=20const=20void=20= *buf,=20PRInt32=20amount,=0A+=09=09=09=09=09=09=09PRIntn=20flags,=20= PRIntervalTime=20timeout);=0A+/*=20Utility=20functions=20*/=0A+static=20= PRFileDesc=20*=20init_iolayer(Port=20*port);=0A+static=20uint16=20= ssl_protocol_version_to_nss(int=20v,=20const=20char=20*guc_name);=0A+=0A= +static=20char=20*pg_SSLerrmessage(PRErrorCode=20errcode);=0A+static=20= char=20*ssl_protocol_version_to_string(int=20v);=0A+static=20SECStatus=20= pg_cert_auth_handler(void=20*arg,=20PRFileDesc=20*=20fd,=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*=20fd);=0A= +static=20char=20*dummy_ssl_passphrase_cb(PK11SlotInfo=20*=20slot,=20= PRBool=20retry,=20void=20*arg);=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09=09=09=09=20Public=20interface=09=09=09=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +/*=0A+=20*=20be_tls_init=0A+=20*=09=09=09Initialize=20the=20nss=20TLS=20= library=20in=20the=20postmaster=0A+=20*=0A+=20*=20The=20majority=20of=20= the=20setup=20needs=20to=20happen=20in=20be_tls_open_server=20since=20= the=0A+=20*=20NSPR=20initialization=20must=20happen=20after=20the=20= forking=20of=20the=20backend.=20We=20could=0A+=20*=20potentially=20move=20= some=20parts=20in=20under=20!isServerStart,=20but=20so=20far=20this=20is=20= the=0A+=20*=20separation=20chosen.=0A+=20*/=0A+int=0A+be_tls_init(bool=20= isServerStart)=0A+{=0A+=09SECStatus=09status;=0A+=09SSLVersionRange=20= supported_sslver;=0A+=0A+=09/*=0A+=09=20*=20Set=20up=20the=20connection=20= cache=20for=20multi-processing=20application=20behavior.=0A+=09=20*=20If=20= we=20are=20in=20ServerStart=20then=20we=20initialize=20the=20cache.=20If=20= the=20server=20is=0A+=09=20*=20already=20started,=20we=20inherit=20the=20= cache=20such=20that=20it=20can=20be=20used=20for=0A+=09=20*=20= connections.=20Calling=20SSL_ConfigMPServerSIDCache=20sets=20an=20= environment=0A+=09=20*=20variable=20which=20contains=20enough=20= information=20for=20the=20forked=20child=20to=20know=0A+=09=20*=20how=20= to=20access=20it.=20=20Passing=20NULL=20to=20SSL_InheritMPServerSIDCache=20= will=0A+=09=20*=20make=20the=20forked=20child=20look=20it=20up=20by=20= the=20default=20name=20SSL_INHERITANCE,=0A+=09=20*=20if=20env=20vars=20= aren't=20inherited=20then=20the=20contents=20of=20the=20variable=20can=20= be=0A+=09=20*=20passed=20instead.=0A+=09=20*/=0A+=09if=20(isServerStart)=0A= +=09{=0A+=09=09/*=0A+=09=09=20*=20SSLv2=20and=20SSLv3=20are=20disabled=20= in=20this=20TLS=20backend,=20but=20when=20setting=0A+=09=09=20*=20up=20= the=20required=20session=20cache=20for=20NSS=20we=20still=20must=20= supply=20timeout=0A+=09=09=20*=20values=20for=20v2=20and=20The=20minimum=20= allowed=20value=20for=20both=20is=205=20seconds,=0A+=09=09=20*=20so=20= opt=20for=20that=20in=20both=20cases=20(the=20defaults=20being=20100=20= seconds=20and=0A+=09=09=20*=2024=20hours).=0A+=09=09=20*=0A+=09=09=20*=20= Passing=20NULL=20as=20the=20directory=20for=20the=20session=20cache=20= will=20default=20to=0A+=09=09=20*=20using=20/tmp=20on=20UNIX=20and=20= \\temp=20on=20Windows.=20=20Deciding=20if=20we=20want=20to=0A+=09=09=20*=20= keep=20closer=20control=20on=20this=20directory=20is=20left=20as=20a=20= TODO.=0A+=09=09=20*/=0A+=09=09status=20=3D=20= SSL_ConfigMPServerSIDCache(MaxConnections,=205,=205,=20NULL);=0A+=09=09= if=20(status=20!=3D=20SECSuccess)=0A+=09=09=09ereport(FATAL,=0A+=09=09=09= =09=09(errmsg("unable=20to=20set=20up=20TLS=20connection=20cache:=20%s",=0A= +=09=09=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=0A+=09}=0A= +=09else=0A+=09{=0A+=09=09status=20=3D=20= SSL_InheritMPServerSIDCache(NULL);=0A+=09=09if=20(status=20!=3D=20= SECSuccess)=0A+=09=09{=0A+=09=09=09ereport(LOG,=0A+=09=09=09=09=09= (errmsg("unable=20to=20connect=20to=20TLS=20connection=20cache:=20%s",=0A= +=09=09=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09=09=09= return=20-1;=0A+=09=09}=0A+=09}=0A+=0A+=09if=20(!ssl_database=20||=20= strlen(ssl_database)=20=3D=3D=200)=0A+=09{=0A+=09=09= ereport(isServerStart=20?=20FATAL=20:=20LOG,=0A+=09=09=09=09(errmsg("no=20= certificate=20database=20specified")));=0A+=09=09goto=20error;=0A+=09}=0A= +=0A+=09/*=0A+=09=20*=20We=20check=20for=20the=20desired=20TLS=20version=20= range=20here,=20even=20though=20we=20cannot=0A+=09=20*=20set=20it=20= until=20be_open_server=20such=20that=20we=20can=20be=20compatible=20with=20= how=20the=0A+=09=20*=20OpenSSL=20backend=20reports=20errors=20for=20= incompatible=20range=20configurations.=0A+=09=20*=20Set=20either=20the=20= default=20supported=20TLS=20version=20range,=20or=20the=20configured=0A+=09= =20*=20range=20from=20ssl_min_protocol_version=20and=20ssl_max_protocol=20= version.=20In=0A+=09=20*=20case=20the=20user=20hasn't=20defined=20the=20= maximum=20allowed=20version=20we=20fall=20back=0A+=09=20*=20to=20the=20= highest=20version=20TLS=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=09= ereport(isServerStart=20?=20FATAL=20:=20LOG,=0A+=09=09=09=09= (errmsg("unable=20to=20get=20default=20protocol=20support=20from=20= NSS")));=0A+=09=09goto=20error;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Set=20= the=20fallback=20versions=20for=20the=20TLS=20protocol=20version=20range=20= to=20a=0A+=09=20*=20combination=20of=20our=20minimal=20requirement=20and=20= the=20library=20maximum.=0A+=09=20*/=0A+=09desired_sslver.min=20=3D=20= SSL_LIBRARY_VERSION_TLS_1_0;=0A+=09desired_sslver.max=20=3D=20= supported_sslver.max;=0A+=0A+=09if=20(ssl_min_protocol_version)=0A+=09{=0A= +=09=09int=09=09=09ver=20=3D=20= ssl_protocol_version_to_nss(ssl_min_protocol_version,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=20=20"ssl_min_protocol_version");=0A+=0A+=09=09if=20= (ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09ereport(isServerStart=20?=20= FATAL=20:=20LOG,=0A+=09=09=09=09=09(errmsg("\"%s\"=20setting=20\"%s\"=20= not=20supported=20by=20this=20build",=0A+=09=09=09=09=09=09=09= "ssl_min_protocol_version",=0A+=09=09=09=09=09=09=09= GetConfigOption("ssl_min_protocol_version",=0A+=09=09=09=09=09=09=09=09=09= =09=09false,=20false))));=0A+=09=09=09goto=20error;=0A+=09=09}=0A+=0A+=09= =09if=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=09= ver=20=3D=20ssl_protocol_version_to_nss(ssl_max_protocol_version,=0A+=09=09= =09=09=09=09=09=09=09=09=09=09=09=20=20"ssl_max_protocol_version");=0A+=0A= +=09=09if=20(ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09= ereport(isServerStart=20?=20FATAL=20:=20LOG,=0A+=09=09=09=09=09= (errmsg("\"%s\"=20setting=20\"%s\"=20not=20supported=20by=20this=20= build",=0A+=09=09=09=09=09=09=09"ssl_max_protocol_version",=0A+=09=09=09=09= =09=09=09GetConfigOption("ssl_max_protocol_version",=0A+=09=09=09=09=09=09= =09=09=09=09=09false,=20false))));=0A+=09=09=09goto=20error;=0A+=09=09}=0A= +=09=09if=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=09goto=20= error;=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Set=20the=20= passphrase=20callback=20which=20will=20be=20used=20both=20to=20obtain=20= the=0A+=09=20*=20passphrase=20from=20the=20user,=20as=20well=20as=20by=20= NSS=20to=20obtain=20the=20phrase=0A+=09=20*=20repeatedly.=0A+=09=20*/=0A= +=09ssl_is_server_start=20=3D=20isServerStart;=0A+=09= (*nss_tls_init_hook)=20(isServerStart);=0A+=0A+=09return=200;=0A+error:=0A= +=09return=20-1;=0A+}=0A+=0A+int=0A+be_tls_open_server(Port=20*port)=0A= +{=0A+=09SECStatus=09status;=0A+=09PRFileDesc=20*model;=0A+=09PRFileDesc=20= *pr_fd;=0A+=09PRFileDesc=20*layer;=0A+=09CERTCertificate=20*server_cert;=0A= +=09SECKEYPrivateKey=20*private_key;=0A+=09CERTSignedCrl=20*crl;=0A+=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=20wont=20allow=20this=20to=20fail=20= however,=20as=20we=20require=20the=20certificate=20and=0A+=09=20*=20key=20= to=20exist.=0A+=09=20*=0A+=09=20*=20The=20original=20design=20of=20NSS=20= was=20for=20a=20single=20application=20to=20use=20a=20single=0A+=09=20*=20= copy=20of=20it,=20initialized=20with=20NSS_Initialize()=20which=20isn't=20= returning=20any=0A+=09=20*=20handle=20with=20which=20to=20refer=20to=20= NSS.=20NSS=20initialization=20and=20shutdown=20are=0A+=09=20*=20global=20= for=20the=20application,=20so=20a=20shutdown=20in=20another=20NSS=20= enabled=0A+=09=20*=20library=20would=20cause=20NSS=20to=20be=20stopped=20= for=20libpq=20as=20well.=20=20The=20fix=20has=0A+=09=20*=20been=20to=20= introduce=20NSS_InitContext=20which=20returns=20a=20context=20handle=20= to=0A+=09=20*=20pass=20to=20NSS_ShutdownContext.=20=20NSS_InitContext=20= was=20introduced=20in=20NSS=0A+=09=20*=203.12,=20but=20the=20use=20of=20= it=20is=20not=20very=20well=20documented.=0A+=09=20*=20= https://bugzilla.redhat.com/show_bug.cgi?id=3D738456=0A+=09=20*=0A+=09=20= *=20The=20InitParameters=20struct=20passed=20can=20be=20used=20to=20= override=20internal=0A+=09=20*=20values=20in=20NSS,=20but=20the=20usage=20= is=20not=20documented=20at=20all.=20When=20using=0A+=09=20*=20NSS_Init=20= initializations,=20the=20values=20are=20instead=20set=20via=20= PK11_Configure=0A+=09=20*=20calls=20so=20the=20PK11_Configure=20= documentation=20can=20be=20used=20to=20glean=20some=0A+=09=20*=20details=20= on=20these.=0A+=09=20*=0A+=09=20*=20= https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/PKCS11/Modul= e_Specs=0A+=09=20*/=0A+=09memset(¶ms,=20'\0',=20sizeof(params));=0A+=09= params.length=20=3D=20sizeof(params);=0A+=0A+=09if=20(!ssl_database=20||=20= strlen(ssl_database)=20=3D=3D=200)=0A+=09=09ereport(FATAL,=0A+=09=09=09=09= (errmsg("no=20certificate=20database=20specified")));=0A+=0A+=09= cert_database=20=3D=20psprintf("sql:%s",=20ssl_database);=0A+=09= nss_context=20=3D=20NSS_InitContext(cert_database,=20"",=20"",=20"",=0A+=09= =09=09=09=09=09=09=09=20=20¶ms,=0A+=09=09=09=09=09=09=09=09=20=20= NSS_INIT_READONLY=20|=20NSS_INIT_PK11RELOAD);=0A+=09= pfree(cert_database);=0A+=0A+=09if=20(!nss_context)=0A+=09=09= ereport(FATAL,=0A+=09=09=09=09(errmsg("unable=20to=20read=20certificate=20= database=20\"%s\":=20%s",=0A+=09=09=09=09=09=09ssl_database,=20= pg_SSLerrmessage(PR_GetError()))));=0A+=0A+=09/*=0A+=09=20*=20Import=20= the=20already=20opened=20socket=20as=20we=20don't=20want=20to=20use=20= NSPR=20functions=0A+=09=20*=20for=20opening=20the=20network=20socket=20= due=20to=20how=20the=20PostgreSQL=20protocol=20works=0A+=09=20*=20with=20= TLS=20connections.=20This=20function=20is=20not=20part=20of=20the=20NSPR=20= public=20API,=0A+=09=20*=20see=20the=20comment=20at=20the=20top=20of=20= the=20file=20for=20the=20rationale=20of=20still=20using=0A+=09=20*=20it.=0A= +=09=20*/=0A+=09pr_fd=20=3D=20PR_ImportTCPSocket(port->sock);=0A+=09if=20= (!pr_fd)=0A+=09=09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= connect=20to=20socket")));=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+=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=20aswell=20in=20that=20we=20can=0A= +=09=20*=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=09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20to=20open=20= socket")));=0A+=0A+=09/*=0A+=09=20*=20Convert=20the=20NSPR=20socket=20to=20= an=20SSL=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+=09model=20=3D=20SSL_ImportFD(NULL,=20model);=0A= +=09if=20(!model)=0A+=09=09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20= to=20enable=20TLS=20on=20socket")));=0A+=0A+=09/*=0A+=09=20*=20Configure=20= basic=20settings=20for=20the=20connection=20over=20the=20SSL=20socket=20= in=0A+=09=20*=20order=20to=20set=20it=20up=20as=20a=20server.=0A+=09=20= */=0A+=09if=20(SSL_OptionSet(model,=20SSL_SECURITY,=20PR_TRUE)=20!=3D=20= SECSuccess)=0A+=09=09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= configure=20TLS=20connection")));=0A+=0A+=09if=20(SSL_OptionSet(model,=20= SSL_HANDSHAKE_AS_SERVER,=20PR_TRUE)=20!=3D=20SECSuccess=20||=0A+=09=09= SSL_OptionSet(model,=20SSL_HANDSHAKE_AS_CLIENT,=20PR_FALSE)=20!=3D=20= SECSuccess)=0A+=09=09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= configure=20TLS=20connection=20as=20server")));=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=20this=0A+=09=20*=20is=20helpful=20or=20not.=20Using=20= the=20policies=20works,=20but=20may=20be=20too=20coarsely=0A+=09=20*=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=09ereport(ERROR,=0A+=09=09=09= =09=09(errmsg("unable=20to=20set=20cipher=20policy:=20%s",=0A+=09=09=09=09= =09=09=09pg_SSLerrmessage(PR_GetError()))));=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=09= char=09=20=20=20*sep=20=3D=20":;,=20";=0A+=09=09PRUint16=09ciphercode;=0A= +=09=09const=09=09PRUint16=20*nss_ciphers;=0A+=0A+=09=09/*=0A+=09=09=20*=20= If=20the=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=09ciphercode=20=3D=20pg_find_cipher(c);=0A+=09=09=09if=20= (ciphercode=20!=3D=20INVALID_CIPHER)=0A+=09=09=09{=0A+=09=09=09=09status=20= =3D=20SSL_CipherPrefSet(model,=20ciphercode,=20PR_TRUE);=0A+=09=09=09=09= if=20(status=20!=3D=20SECSuccess)=0A+=09=09=09=09=09ereport(ERROR,=0A+=09= =09=09=09=09=09=09(errmsg("invalid=20cipher-suite=20specified:=20%s",=20= c)));=0A+=09=09=09}=0A+=09=09}=0A+=0A+=09=09pfree(ciphers);=0A+=09}=0A+=0A= +=09if=20(SSL_VersionRangeSet(model,=20&desired_sslver)=20!=3D=20= SECSuccess)=0A+=09=09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= set=20requested=20SSL=20protocol=20version=20range")));=0A+=0A+=09/*=0A+=09= =20*=20Set=20up=20the=20custom=20IO=20layer.=0A+=09=20*/=0A+=09layer=20=3D= =20init_iolayer(port);=0A+=09if=20(!layer)=0A+=09=09goto=20error;=0A+=0A= +=09/*=20Store=20the=20Port=20as=20private=20data=20available=20in=20= callbacks=20*/=0A+=09layer->secret=20=3D=20(void=20*)=20port;=0A+=0A+=09= if=20(PR_PushIOLayer(pr_fd,=20PR_TOP_IO_LAYER,=20layer)=20!=3D=20= PR_SUCCESS)=0A+=09{=0A+=09=09PR_Close(layer);=0A+=09=09ereport(ERROR,=0A= +=09=09=09=09(errmsg("unable=20to=20push=20IO=20layer")));=0A+=09}=0A+=0A= +=09server_cert=20=3D=20PK11_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=09ereport(ERROR,=0A+=09=09=09=09=09= (errmsg("unable=20to=20load=20certificate=20for=20\"%s\":=20%s",=0A+=09=09= =09=09=09=09=09ssl_cert_file,=20pg_SSLerrmessage(PR_GetError())),=0A+=09=09= =09=09=09=20errhint("The=20certificate=20requires=20a=20password.")));=0A= +=09=09else=0A+=09=09=09ereport(ERROR,=0A+=09=09=09=09=09(errmsg("unable=20= to=20find=20certificate=20for=20\"%s\":=20%s",=0A+=09=09=09=09=09=09=09= ssl_cert_file,=20pg_SSLerrmessage(PR_GetError()))));=0A+=09}=0A+=0A+=09= private_key=20=3D=20PK11_FindKeyByAnyCert(server_cert,=20(void=20*)=20= port);=0A+=09if=20(!private_key)=0A+=09{=0A+=09=09if=20= (dummy_ssl_passwd_cb_called)=0A+=09=09=09ereport(ERROR,=0A+=09=09=09=09=09= (errmsg("unable=20to=20load=20private=20key=20for=20\"%s\":=20%s",=0A+=09= =09=09=09=09=09=09ssl_cert_file,=20pg_SSLerrmessage(PR_GetError())),=0A+=09= =09=09=09=09=20errhint("The=20private=20key=20requires=20a=20= password.")));=0A+=09=09else=0A+=09=09=09ereport(ERROR,=0A+=09=09=09=09=09= (errmsg("unable=20to=20find=20private=20key=20for=20\"%s\":=20%s",=0A+=09= =09=09=09=09=09=09ssl_cert_file,=20pg_SSLerrmessage(PR_GetError()))));=0A= +=09}=0A+=0A+=09/*=0A+=09=20*=20NSS=20doesn't=20use=20CRL=20files=20on=20= disk,=20so=20we=20use=20the=20ssl_crl_file=20guc=20to=0A+=09=20*=20= contain=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=09ereport(ERROR,=0A+=09=09=09= =09=09(errmsg("specified=20CRL=20not=20found=20in=20database")));=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= =09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20to=20configure=20= server=20for=20TLS=20server=20connections:=20%s",=0A+=09=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=0A+=09= ssl_loaded_verify_locations=20=3D=20true;=0A+=0A+=09/*=0A+=09=20*=20At=20= this=20point,=20we=20no=20longer=20have=20use=20for=20the=20certificate=20= and=20private=0A+=09=20*=20key=20as=20they=20have=20been=20copied=20into=20= the=20context=20by=20NSS.=20Destroy=20our=0A+=09=20*=20copies=20= explicitly=20to=20clean=20out=20the=20memory=20as=20best=20we=20can.=0A+=09= =20*/=0A+=09CERT_DestroyCertificate(server_cert);=0A+=09= SECKEY_DestroyPrivateKey(private_key);=0A+=0A+=09status=20=3D=20= SSL_AuthCertificateHook(model,=20pg_cert_auth_handler,=20(void=20*)=20= port);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09ereport(ERROR,=0A= +=09=09=09=09(errmsg("unable=20to=20install=20authcert=20hook:=20%s",=0A= +=09=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09= SSL_BadCertHook(model,=20pg_bad_cert_handler,=20(void=20*)=20port);=0A+=09= SSL_OptionSet(model,=20SSL_REQUEST_CERTIFICATE,=20PR_TRUE);=0A+=09= SSL_OptionSet(model,=20SSL_REQUIRE_CERTIFICATE,=20PR_FALSE);=0A+=0A+=09= port->pr_fd=20=3D=20SSL_ImportFD(model,=20pr_fd);=0A+=09if=20= (!port->pr_fd)=0A+=09=09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20= to=20initialize")));=0A+=0A+=09PR_Close(model);=0A+=0A+=09/*=0A+=09=20*=20= Force=20a=20handshake=20on=20the=20next=20I/O=20request,=20the=20second=20= parameter=20means=0A+=09=20*=20that=20we=20are=20a=20server,=20PR_FALSE=20= would=20indicate=20being=20a=20client.=20NSPR=0A+=09=20*=20requires=20us=20= to=20call=20SSL_ResetHandshake=20since=20we=20imported=20an=20already=0A= +=09=20*=20established=20socket.=0A+=09=20*/=0A+=09status=20=3D=20= SSL_ResetHandshake(port->pr_fd,=20PR_TRUE);=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09=09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= initiate=20handshake:=20%s",=0A+=09=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09status=20=3D=20= SSL_ForceHandshake(port->pr_fd);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A= +=09=09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20to=20handshake:=20= %s",=0A+=09=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=0A+=09= port->ssl_in_use=20=3D=20true;=0A+=09return=200;=0A+=0A+error:=0A+=09= return=201;=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+void=0A+be_tls_close(Port=20*port)=0A+{=0A= +=09if=20(!port)=0A+=09=09return;=0A+=0A+=09if=20(port->peer_cn)=0A+=09{=0A= +=09=09SSL_InvalidateSession(port->pr_fd);=0A+=09=09= pfree(port->peer_cn);=0A+=09=09port->peer_cn=20=3D=20NULL;=0A+=09}=0A+=0A= +=09PR_Close(port->pr_fd);=0A+=09port->pr_fd=20=3D=20NULL;=0A+=09= port->ssl_in_use=20=3D=20false;=0A+=0A+=09if=20(nss_context)=0A+=09{=0A+=09= =09NSS_ShutdownContext(nss_context);=0A+=09=09nss_context=20=3D=20NULL;=0A= +=09}=0A+}=0A+=0A+void=0A+be_tls_destroy(void)=0A+{=0A+=09/*=0A+=09=20*=20= It=20reads=20a=20bit=20odd=20to=20clear=20a=20session=20cache=20when=20= we=20are=20destroying=20the=0A+=09=20*=20context=20altogether,=20but=20= if=20the=20session=20cache=20isn't=20cleared=20before=0A+=09=20*=20= shutting=20down=20the=20context=20it=20will=20fail=20with=20= SEC_ERROR_BUSY.=0A+=09=20*/=0A+=09SSL_ClearSessionCache();=0A+}=0A+=0A= +int=0A+be_tls_get_cipher_bits(Port=20*port)=0A+{=0A+=09SECStatus=09= status;=0A+=09SSLChannelInfo=20channel;=0A+=09SSLCipherSuiteInfo=20= suite;=0A+=0A+=09status=20=3D=20SSL_GetChannelInfo(port->pr_fd,=20= &channel,=20sizeof(channel));=0A+=09if=20(status=20!=3D=20SECSuccess)=0A= +=09=09goto=20error;=0A+=0A+=09status=20=3D=20= SSL_GetCipherSuiteInfo(channel.cipherSuite,=20&suite,=20sizeof(suite));=0A= +=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09goto=20error;=0A+=0A+=09= return=20suite.effectiveKeyBits;=0A+=0A+error:=0A+=09ereport(WARNING,=0A= +=09=09=09(errmsg("unable=20to=20extract=20TLS=20session=20information:=20= %s",=0A+=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09return=20= 0;=0A+}=0A+=0A+/*=0A+=20*=20be_tls_get_compression=0A+=20*=0A+=20*=20NSS=20= disabled=20support=20for=20TLS=20compression=20in=20version=203.33=20and=20= removed=20the=0A+=20*=20code=20in=20a=20subsequent=20release.=20The=20= API=20for=20retrieving=20information=20about=0A+=20*=20compression=20as=20= well=20as=20enabling=20it=20is=20kept=20for=20backwards=20compatibility,=20= but=0A+=20*=20we=20don't=20need=20to=20consult=20it=20since=20it=20was=20= only=20available=20for=20SSLv3=20which=20we=0A+=20*=20don't=20support.=0A= +=20*=0A+=20*=20https://bugzilla.mozilla.org/show_bug.cgi?id=3D1409587=0A= +=20*/=0A+bool=0A+be_tls_get_compression(Port=20*port)=0A+{=0A+=09return=20= false;=0A+}=0A+=0A+/*=0A+=20*=20be_tls_get_version=0A+=20*=0A+=20*=20= Returns=20the=20protocol=20version=20used=20for=20the=20current=20= connection,=20or=20NULL=20in=0A+=20*=20case=20of=20errors.=0A+=20*/=0A= +const=20char=20*=0A+be_tls_get_version(Port=20*port)=0A+{=0A+=09= SECStatus=09status;=0A+=09SSLChannelInfo=20channel;=0A+=0A+=09status=20=3D= =20SSL_GetChannelInfo(port->pr_fd,=20&channel,=20sizeof(channel));=0A+=09= if=20(status=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09ereport(WARNING,=0A+=09= =09=09=09(errmsg("unable=20to=20extract=20TLS=20session=20information:=20= %s",=0A+=09=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09=09= return=20NULL;=0A+=09}=0A+=0A+=09return=20= ssl_protocol_version_to_string(channel.protocolVersion);=0A+}=0A+=0A= +const=20char=20*=0A+be_tls_get_cipher(Port=20*port)=0A+{=0A+=09= SECStatus=09status;=0A+=09SSLChannelInfo=20channel;=0A+=09= SSLCipherSuiteInfo=20suite;=0A+=0A+=09status=20=3D=20= SSL_GetChannelInfo(port->pr_fd,=20&channel,=20sizeof(channel));=0A+=09if=20= (status=20!=3D=20SECSuccess)=0A+=09=09goto=20error;=0A+=0A+=09status=20=3D= =20SSL_GetCipherSuiteInfo(channel.cipherSuite,=20&suite,=20= sizeof(suite));=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09goto=20= error;=0A+=0A+=09return=20suite.cipherSuiteName;=0A+=0A+error:=0A+=09= ereport(WARNING,=0A+=09=09=09(errmsg("unable=20to=20extract=20TLS=20= session=20information:=20%s",=0A+=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09return=20NULL;=0A+}=0A+=0A= +void=0A+be_tls_get_peer_subject_name(Port=20*port,=20char=20*ptr,=20= size_t=20len)=0A+{=0A+=09CERTCertificate=20*certificate;=0A+=0A+=09= certificate=20=3D=20SSL_PeerCertificate(port->pr_fd);=0A+=09if=20= (certificate)=0A+=09=09strlcpy(ptr,=20= CERT_NameToAscii(&certificate->subject),=20len);=0A+=09else=0A+=09=09= ptr[0]=20=3D=20'\0';=0A+}=0A+=0A+void=0A= +be_tls_get_peer_issuer_name(Port=20*port,=20char=20*ptr,=20size_t=20= len)=0A+{=0A+=09CERTCertificate=20*certificate;=0A+=0A+=09certificate=20= =3D=20SSL_PeerCertificate(port->pr_fd);=0A+=09if=20(certificate)=0A+=09=09= strlcpy(ptr,=20CERT_NameToAscii(&certificate->issuer),=20len);=0A+=09= else=0A+=09=09ptr[0]=20=3D=20'\0';=0A+}=0A+=0A+void=0A= +be_tls_get_peer_serial(Port=20*port,=20char=20*ptr,=20size_t=20len)=0A= +{=0A+=09CERTCertificate=20*certificate;=0A+=0A+=09certificate=20=3D=20= SSL_PeerCertificate(port->pr_fd);=0A+=09if=20(certificate)=0A+=09=09= snprintf(ptr,=20len,=20"%li",=20= DER_GetInteger(&(certificate->serialNumber)));=0A+=09else=0A+=09=09= ptr[0]=20=3D=20'\0';=0A+}=0A+=0A+/*=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=0A+=09=20= *=20as=20well=20do=20it=20right.=0A+=09=20*/=0A+=09prompt=20=3D=20= psprintf("Enter=20Password=20or=20Pin=20for=20\"%s\":",=0A+=09=09=09=09=09= =20=20PK11_GetTokenName(slot));=0A+=0A+=09len=20=3D=20= run_ssl_passphrase_command(prompt,=20ssl_is_server_start,=20buf,=20= sizeof(buf));=0A+=09pfree(prompt);=0A+=0A+=09if=20(!len)=0A+=09=09return=20= NULL;=0A+=0A+=09/*=0A+=09=20*=20At=20least=20one=20byte=20with=20= password=20content=20was=20returned,=20and=20NSS=20requires=0A+=09=20*=20= that=20we=20return=20it=20allocated=20in=20NSS=20controlled=20memory.=20= If=20we=20fail=20to=0A+=09=20*=20allocate=20then=20abort=20without=20= passing=20back=20NULL=20and=20bubble=20up=20the=20error=0A+=09=20*=20on=20= the=20PG=20side.=0A+=09=20*/=0A+=09password=20=3D=20(char=20*)=20= PR_Malloc(len=20+=201);=0A+=09if=20(!password)=0A+=09{=0A+=09=09= explicit_bzero(buf,=20sizeof(buf));=0A+=09=09ereport(ERROR,=0A+=09=09=09=09= (errcode(ERRCODE_OUT_OF_MEMORY),=0A+=09=09=09=09=20errmsg("out=20of=20= memory")));=0A+=09}=0A+=09strlcpy(password,=20buf,=20sizeof(password));=0A= +=09explicit_bzero(buf,=20sizeof(buf));=0A+=0A+=09return=20password;=0A= +}=0A+=0A+/*=0A+=20*=20dummy_ssl_passphrase_cb=0A+=20*=0A+=20*=20Return=20= unsuccessful=20if=20we=20are=20asked=20to=20provide=20the=20passphrase=20= for=20a=20cert=20or=0A+=20*=20key,=20without=20having=20a=20passphrase=20= callback=20installed.=0A+=20*/=0A+static=20char=20*=0A= +dummy_ssl_passphrase_cb(PK11SlotInfo=20*slot,=20PRBool=20retry,=20void=20= *arg)=0A+{=0A+=09dummy_ssl_passwd_cb_called=20=3D=20true;=0A+=09return=20= NULL;=0A+}=0A+=0A+static=20SECStatus=0A+pg_bad_cert_handler(void=20*arg,=20= PRFileDesc=20*=20fd)=0A+{=0A+=09Port=09=20=20=20*port=20=3D=20(Port=20*)=20= arg;=0A+=0A+=09port->peer_cert_valid=20=3D=20false;=0A+=09return=20= SECFailure;=0A+}=0A+=0A+static=20SECStatus=0A+pg_cert_auth_handler(void=20= *arg,=20PRFileDesc=20*=20fd,=20PRBool=20checksig,=20PRBool=20isServer)=0A= +{=0A+=09SECStatus=09status;=0A+=09Port=09=20=20=20*port=20=3D=20(Port=20= *)=20arg;=0A+=09CERTCertificate=20*cert;=0A+=09char=09=20=20=20*peer_cn;=0A= +=09int=09=09=09len;=0A+=0A+=09status=20=3D=20= SSL_AuthCertificate(CERT_GetDefaultCertDB(),=20port->pr_fd,=20checksig,=20= PR_TRUE);=0A+=09if=20(status=20=3D=3D=20SECSuccess)=0A+=09{=0A+=09=09= cert=20=3D=20SSL_PeerCertificate(port->pr_fd);=0A+=09=09len=20=3D=20= strlen(cert->subjectName);=0A+=09=09peer_cn=20=3D=20= MemoryContextAllocZero(TopMemoryContext,=20len=20+=201);=0A+=09=09/*=0A+=09= =09=20*=20Skip=20over=20the=20key=3D=20portion=20of=20the=20key=3Dvalue=20= containing=20the=20the=0A+=09=09=20*=20peer=20CN.=0A+=09=09=20*/=0A+=09=09= if=20(strncmp(cert->subjectName,=20"CN=3D",=203)=20=3D=3D=200)=0A+=09=09=09= strlcpy(peer_cn,=20cert->subjectName=20+=20strlen("CN=3D"),=20len=20+=20= 1);=0A+=09=09else=0A+=09=09=09strlcpy(peer_cn,=20cert->subjectName,=20= len=20+=201);=0A+=09=09CERT_DestroyCertificate(cert);=0A+=0A+=09=09= port->peer_cn=20=3D=20peer_cn;=0A+=09=09port->peer_cert_valid=20=3D=20= true;=0A+=09}=0A+=0A+=09return=20status;=0A+}=0A+=0A+static=20PRInt32=0A= +pg_ssl_read(PRFileDesc=20*fd,=20void=20*buf,=20PRInt32=20amount,=20= PRIntn=20flags,=0A+=09=09=09PRIntervalTime=20timeout)=0A+{=0A+=09= PRRecvFN=09read_fn;=0A+=09PRInt32=09=09n_read;=0A+=0A+=09read_fn=20=3D=20= fd->lower->methods->recv;=0A+=09n_read=20=3D=20read_fn(fd->lower,=20buf,=20= amount,=20flags,=20timeout);=0A+=0A+=09return=20n_read;=0A+}=0A+=0A= +static=20PRInt32=0A+pg_ssl_write(PRFileDesc=20*fd,=20const=20void=20= *buf,=20PRInt32=20amount,=20PRIntn=20flags,=0A+=09=09=09=20= PRIntervalTime=20timeout)=0A+{=0A+=09PRSendFN=09send_fn;=0A+=09PRInt32=09= =09n_write;=0A+=0A+=09send_fn=20=3D=20fd->lower->methods->send;=0A+=09= n_write=20=3D=20send_fn(fd->lower,=20buf,=20amount,=20flags,=20timeout);=0A= +=0A+=09return=20n_write;=0A+}=0A+=0A+static=20PRFileDesc=20*=0A= +init_iolayer(Port=20*port)=0A+{=0A+=09const=09=09PRIOMethods=20= *default_methods;=0A+=09PRFileDesc=20*layer;=0A+=0A+=09/*=0A+=09=20*=20= Start=20by=20initializing=20our=20layer=20with=20all=20the=20default=20= methods=20so=20that=20we=0A+=09=20*=20can=20selectively=20override=20the=20= ones=20we=20want=20while=20still=20ensuring=20that=20we=0A+=09=20*=20= have=20a=20complete=20layer=20specification.=0A+=09=20*/=0A+=09= default_methods=20=3D=20PR_GetDefaultIOMethods();=0A+=09= memcpy(&pr_iomethods,=20default_methods,=20sizeof(PRIOMethods));=0A+=0A+=09= pr_iomethods.recv=20=3D=20pg_ssl_read;=0A+=09pr_iomethods.send=20=3D=20= pg_ssl_write;=0A+=0A+=09/*=0A+=09=20*=20Each=20IO=20layer=20must=20be=20= identified=20by=20a=20unique=20name,=20where=20uniqueness=20is=0A+=09=20= *=20per=20connection.=20Each=20connection=20in=20a=20postgres=20cluster=20= can=20generate=20the=0A+=09=20*=20identity=20from=20the=20same=20string=20= as=20they=20will=20create=20their=20IO=20layers=20on=0A+=09=20*=20= different=20sockets.=20Only=20one=20layer=20per=20socket=20can=20have=20= the=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+=09return=20layer;=0A+}=0A+=0A+static=20= char=20*=0A+ssl_protocol_version_to_string(int=20v)=0A+{=0A+=09switch=20= (v)=0A+=09{=0A+=09=09=09/*=20SSL=20v2=20and=20v3=20are=20not=20supported=20= */=0A+=09=09case=20SSL_LIBRARY_VERSION_2:=0A+=09=09case=20= SSL_LIBRARY_VERSION_3_0:=0A+=09=09=09Assert(false);=0A+=09=09=09break;=0A= +=0A+=09=09case=20SSL_LIBRARY_VERSION_TLS_1_0:=0A+=09=09=09return=20= pstrdup("TLSv1.0");=0A+=09=09case=20SSL_LIBRARY_VERSION_TLS_1_1:=0A+=09=09= =09return=20pstrdup("TLSv1.1");=0A+=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_2:=0A+=09=09=09return=20pstrdup("TLSv1.2");=0A= +=09=09case=20SSL_LIBRARY_VERSION_TLS_1_3:=0A+=09=09=09return=20= pstrdup("TLSv1.3");=0A+=09}=0A+=0A+=09return=20pstrdup("unknown");=0A+}=0A= +=0A+=0A+/*=0A+=20*=20ssl_protocol_version_to_nss=0A+=20*=09=09=09= Translate=20PostgreSQL=20TLS=20version=20to=20NSS=20version=0A+=20*=0A+=20= *=20Returns=20zero=20in=20case=20the=20requested=20TLS=20version=20is=20= undefined=20(PG_ANY)=20and=0A+=20*=20should=20be=20set=20by=20the=20= caller,=20or=20-1=20on=20failure.=0A+=20*/=0A+static=20uint16=0A= +ssl_protocol_version_to_nss(int=20v,=20const=20char=20*guc_name)=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= diff=20--git=20a/src/backend/libpq/be-secure.c=20= b/src/backend/libpq/be-secure.c=0Aindex=202ae507a902..f39977b80c=20= 100644=0A---=20a/src/backend/libpq/be-secure.c=0A+++=20= b/src/backend/libpq/be-secure.c=0A@@=20-49,6=20+49,9=20@@=20bool=09=09= ssl_passphrase_command_supports_reload;=0A=20#ifdef=20USE_SSL=0A=20bool=09= =09ssl_loaded_verify_locations=20=3D=20false;=0A=20#endif=0A+#ifdef=20= USE_NSS=0A+char=09=20=20=20*ssl_database;=0A+#endif=0A=20=0A=20/*=20GUC=20= variable=20controlling=20SSL=20cipher=20list=20*/=0A=20char=09=20=20=20= *SSLCipherSuites=20=3D=20NULL;=0Adiff=20--git=20= a/src/backend/libpq/hba.c=20b/src/backend/libpq/hba.c=0Aindex=20= 4c86fb6087..8821c60a34=20100644=0A---=20a/src/backend/libpq/hba.c=0A+++=20= b/src/backend/libpq/hba.c=0A@@=20-1040,7=20+1040,7=20@@=20= parse_hba_line(TokenizedLine=20*tok_line,=20int=20elevel)=0A=20=09=09=09= ereport(elevel,=0A=20=09=09=09=09=09(errcode(ERRCODE_CONFIG_FILE_ERROR),=0A= =20=09=09=09=09=09=20errmsg("hostssl=20record=20cannot=20match=20because=20= SSL=20is=20not=20supported=20by=20this=20build"),=0A-=09=09=09=09=09=20= errhint("Compile=20with=20--with-openssl=20to=20use=20SSL=20= connections."),=0A+=09=09=09=09=09=20errhint("Compile=20with=20= --with-openssl=20or=20--with-nss=20to=20use=20SSL=20connections."),=0A=20= =09=09=09=09=09=20errcontext("line=20%d=20of=20configuration=20file=20= \"%s\"",=0A=20=09=09=09=09=09=09=09=09line_num,=20HbaFileName)));=0A=20=09= =09=09*err_msg=20=3D=20"hostssl=20record=20cannot=20match=20because=20= SSL=20is=20not=20supported=20by=20this=20build";=0Adiff=20--git=20= a/src/backend/utils/misc/guc.c=20b/src/backend/utils/misc/guc.c=0Aindex=20= a62d64eaa4..050f673c68=20100644=0A---=20a/src/backend/utils/misc/guc.c=0A= +++=20b/src/backend/utils/misc/guc.c=0A@@=20-4262,7=20+4262,11=20@@=20= static=20struct=20config_string=20ConfigureNamesString[]=20=3D=0A=20=09=09= },=0A=20=09=09&ssl_library,=0A=20#ifdef=20USE_SSL=0A+#if=20= defined(USE_OPENSSL)=0A=20=09=09"OpenSSL",=0A+#elif=20defined(USE_NSS)=0A= +=09=09"NSS",=0A+#endif=0A=20#else=0A=20=09=09"",=0A=20#endif=0A@@=20= -4320,6=20+4324,18=20@@=20static=20struct=20config_string=20= ConfigureNamesString[]=20=3D=0A=20=09=09check_canonical_path,=20= assign_pgstat_temp_directory,=20NULL=0A=20=09},=0A=20=0A+#ifdef=20= USE_NSS=0A+=09{=0A+=09=09{"ssl_database",=20PGC_SIGHUP,=20CONN_AUTH_SSL,=0A= +=09=09=09gettext_noop("Location=20of=20the=20NSS=20certificate=20= database."),=0A+=09=09=09NULL=0A+=09=09},=0A+=09=09&ssl_database,=0A+=09=09= "",=0A+=09=09NULL,=20NULL,=20NULL=0A+=09},=0A+#endif=0A+=0A=20=09{=0A=20=09= =09{"synchronous_standby_names",=20PGC_SIGHUP,=20REPLICATION_PRIMARY,=0A=20= =09=09=09gettext_noop("Number=20of=20synchronous=20standbys=20and=20list=20= of=20names=20of=20potential=20synchronous=20ones."),=0A@@=20-4348,8=20= +4364,10=20@@=20static=20struct=20config_string=20ConfigureNamesString[]=20= =3D=0A=20=09=09=09GUC_SUPERUSER_ONLY=0A=20=09=09},=0A=20=09=09= &SSLCipherSuites,=0A-#ifdef=20USE_OPENSSL=0A+#if=20defined(USE_OPENSSL)=0A= =20=09=09"HIGH:MEDIUM:+3DES:!aNULL",=0A+#elif=20defined=20(USE_NSS)=0A+=09= =09"",=0A=20#else=0A=20=09=09"none",=0A=20#endif=0Adiff=20--git=20= a/src/common/Makefile=20b/src/common/Makefile=0Aindex=20= 25c55bd642..614f93af09=20100644=0A---=20a/src/common/Makefile=0A+++=20= b/src/common/Makefile=0A@@=20-79,7=20+79,7=20@@=20OBJS_COMMON=20=3D=20\=0A= =20=09wait_error.o=20\=0A=20=09wchar.o=0A=20=0A-ifeq=20= ($(with_openssl),yes)=0A+ifeq=20($(with_ssl),openssl)=0A=20OBJS_COMMON=20= +=3D=20\=0A=20=09protocol_openssl.o=20\=0A=20=09sha2_openssl.o=0Adiff=20= --git=20a/src/include/common/pg_nss.h=20b/src/include/common/pg_nss.h=0A= new=20file=20mode=20100644=0Aindex=200000000000..9205f0fc3b=0A---=20= /dev/null=0A+++=20b/src/include/common/pg_nss.h=0A@@=20-0,0=20+1,141=20= @@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20pg_nss.h=0A+=20*=09=20=20Support=20for=20NSS=20as=20= a=20TLS=20backend=0A+=20*=0A+=20*=20These=20definitions=20are=20used=20= by=20both=20frontend=20and=20backend=20code.=0A+=20*=0A+=20*=20Copyright=20= (c)=202020,=20PostgreSQL=20Global=20Development=20Group=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=20=20=20=20=20=20=20=20= src/include/common/pg_nss.h=0A+=20*=0A+=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+#ifndef=20PG_NSS_H=0A+#define=20PG_NSS_H=0A+=0A+#ifdef=20= USE_NSS=0A+=0A+#include=20=0A+=0A+PRUint16=09= pg_find_cipher(char=20*name);=0A+=0A+typedef=20struct=0A+{=0A+=09const=20= char=20*name;=0A+=09PRUint16=09number;=0A+}=09=09=09NSSCiphers;=0A+=0A= +#define=20INVALID_CIPHER=090xFFFF=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+PRUint16=0A+pg_find_cipher(char=20*name)=0A= +{=0A+=09const=09=09NSSCiphers=20*cipher_list=20=3D=20NSS_CipherList;=0A= +=0A+=09while=20(cipher_list->name)=0A+=09{=0A+=09=09if=20= (pg_strcasecmp(cipher_list->name,=20name)=20=3D=3D=200)=0A+=09=09=09= return=20cipher_list->number;=0A+=0A+=09=09cipher_list++;=0A+=09}=0A+=0A= +=09return=200xFFFF;=0A+}=0A+=0A+#endif=09=09=09=09=09=09=09/*=20USE_NSS=20= */=0A+=0A+#endif=09=09=09=09=09=09=09/*=20PG_NSS_H=20*/=0Adiff=20--git=20= a/src/include/libpq/libpq-be.h=20b/src/include/libpq/libpq-be.h=0Aindex=20= 0a23281ad5..b68ef64ec9=20100644=0A---=20a/src/include/libpq/libpq-be.h=0A= +++=20b/src/include/libpq/libpq-be.h=0A@@=20-192,13=20+192,18=20@@=20= typedef=20struct=20Port=0A=20=09bool=09=09peer_cert_valid;=0A=20=0A=20=09= /*=0A-=09=20*=20OpenSSL=20structures.=20(Keep=20these=20last=20so=20that=20= the=20locations=20of=20other=0A-=09=20*=20fields=20are=20the=20same=20= whether=20or=20not=20you=20build=20with=20OpenSSL.)=0A+=09=20*=20SSL=20= backend=20specific=20structures.=20(Keep=20these=20last=20so=20that=20= the=20locations=0A+=09=20*=20of=20other=20fields=20are=20the=20same=20= whether=20or=20not=20you=20build=20with=20SSL=0A+=09=20*=20enabled.)=0A=20= =09=20*/=0A=20#ifdef=20USE_OPENSSL=0A=20=09SSL=09=09=20=20=20*ssl;=0A=20=09= X509=09=20=20=20*peer;=0A=20#endif=0A+=0A+#ifdef=20USE_NSS=0A+=09void=09=20= =20=20*pr_fd;=0A+#endif=0A=20}=20Port;=0A=20=0A=20#ifdef=20USE_SSL=0A@@=20= -292,6=20+297,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=20b1152475ac..298d87ecae=20100644=0A= ---=20a/src/include/libpq/libpq.h=0A+++=20b/src/include/libpq/libpq.h=0A= @@=20-88,6=20+88,9=20@@=20extern=20PGDLLIMPORT=20bool=20= ssl_passphrase_command_supports_reload;=0A=20#ifdef=20USE_SSL=0A=20= extern=20bool=20ssl_loaded_verify_locations;=0A=20#endif=0A+#ifdef=20= USE_NSS=0A+extern=20char=20*ssl_database;=0A+#endif=0A=20=0A=20extern=20= int=09secure_initialize(bool=20isServerStart);=0A=20extern=20bool=20= secure_loaded_verify_locations(void);=0Adiff=20--git=20= a/src/include/pg_config.h.in=20b/src/include/pg_config.h.in=0Aindex=20= fb270df678..31f808398c=20100644=0A---=20a/src/include/pg_config.h.in=0A= +++=20b/src/include/pg_config.h.in=0A@@=20-893,6=20+893,9=20@@=0A=20/*=20= Define=20to=201=20to=20build=20with=20PAM=20support.=20(--with-pam)=20*/=0A= =20#undef=20USE_PAM=0A=20=0A+/*=20Define=20to=20build=20with=20NSS=20= support=20(--with-nss)=20*/=0A+#undef=20USE_NSS=0A+=0A=20/*=20Define=20= to=201=20to=20use=20software=20CRC-32C=20implementation=20= (slicing-by-8).=20*/=0A=20#undef=20USE_SLICING_BY_8_CRC32C=0A=20=0Adiff=20= --git=20a/src/include/pg_config_manual.h=20= b/src/include/pg_config_manual.h=0Aindex=20705dc69c06..c28b84126d=20= 100644=0A---=20a/src/include/pg_config_manual.h=0A+++=20= b/src/include/pg_config_manual.h=0A@@=20-176,10=20+176,9=20@@=0A=20=0A=20= /*=0A=20=20*=20USE_SSL=20code=20should=20be=20compiled=20only=20when=20= compiling=20with=20an=20SSL=0A-=20*=20implementation.=20=20(Currently,=20= only=20OpenSSL=20is=20supported,=20but=20we=20might=20add=0A-=20*=20more=20= implementations=20in=20the=20future.)=0A+=20*=20implementation.=0A=20=20= */=0A-#ifdef=20USE_OPENSSL=0A+#if=20defined(USE_OPENSSL)=20||=20= defined(USE_NSS)=0A=20#define=20USE_SSL=0A=20#endif=0A=20=0Adiff=20--git=20= a/src/interfaces/libpq/Makefile=20b/src/interfaces/libpq/Makefile=0A= index=204ac5f4b340..e902f38c8e=20100644=0A---=20= a/src/interfaces/libpq/Makefile=0A+++=20b/src/interfaces/libpq/Makefile=0A= @@=20-45,12=20+45,21=20@@=20OBJS=20=3D=20\=0A=20=09pqexpbuffer.o=20\=0A=20= =09fe-auth.o=0A=20=0A-ifeq=20($(with_openssl),yes)=0A+ifneq=20= ($(with_ssl),no)=0A+OBJS=20+=3D=20\=0A+=09fe-secure-common.o=0A+endif=0A= +=0A+ifeq=20($(with_ssl),openssl)=0A=20OBJS=20+=3D=20\=0A-=09= fe-secure-common.o=20\=0A=20=09fe-secure-openssl.o=0A=20endif=0A=20=0A= +ifeq=20($(with_ssl),=20nss)=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=09= fe-gssapi-common.o=20\=0Adiff=20--git=20= a/src/interfaces/libpq/fe-connect.c=20= b/src/interfaces/libpq/fe-connect.c=0Aindex=20b0ca37c2ed..a15a89c50c=20= 100644=0A---=20a/src/interfaces/libpq/fe-connect.c=0A+++=20= b/src/interfaces/libpq/fe-connect.c=0A@@=20-355,6=20+355,10=20@@=20= static=20const=20internalPQconninfoOption=20PQconninfoOptions[]=20=3D=20= {=0A=20=09=09"Target-Session-Attrs",=20"",=2011,=20/*=20= sizeof("read-write")=20=3D=2011=20*/=0A=20=09offsetof(struct=20pg_conn,=20= target_session_attrs)},=0A=20=0A+=09{"cert_database",=20NULL,=20NULL,=20= NULL,=0A+=09=09"CertificateDatabase",=20"",=2064,=0A+=09offsetof(struct=20= pg_conn,=20cert_database)},=0A+=0A=20=09/*=20Terminating=20entry=20---=20= MUST=20BE=20LAST=20*/=0A=20=09{NULL,=20NULL,=20NULL,=20NULL,=0A=20=09= NULL,=20NULL,=200}=0Adiff=20--git=20= a/src/interfaces/libpq/fe-secure-nss.c=20= b/src/interfaces/libpq/fe-secure-nss.c=0Anew=20file=20mode=20100644=0A= index=200000000000..395147f551=0A---=20/dev/null=0A+++=20= b/src/interfaces/libpq/fe-secure-nss.c=0A@@=20-0,0=20+1,1018=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20fe-secure-nss.c=0A+=20*=09=20=20functions=20for=20= supporting=20NSS=20as=20a=20TLS=20backend=20for=20frontend=20libpq=0A+=20= *=0A+=20*=20Portions=20Copyright=20(c)=201996-2020,=20PostgreSQL=20= Global=20Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=20= 1994,=20Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20= *=20IDENTIFICATION=0A+=20*=09=20=20src/interfaces/libpq/fe-secure-nss.c=0A= +=20*=0A+=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#include=20"postgres_fe.h"=0A+=0A+#include=20= "libpq-fe.h"=0A+#include=20"fe-auth.h"=0A+#include=20= "fe-secure-common.h"=0A+#include=20"libpq-int.h"=0A+=0A+/*=0A+=20*=20= BITS_PER_BYTE=20is=20also=20defined=20in=20the=20NSPR=20header=20files,=20= so=20we=20need=20to=20undef=0A+=20*=20our=20version=20to=20avoid=20= compiler=20warnings=20on=20redefinition.=0A+=20*/=0A+#define=20= pg_BITS_PER_BYTE=20BITS_PER_BYTE=0A+#undef=20BITS_PER_BYTE=0A+=0A+/*=0A+=20= *=20The=20nspr/obsolete/protypes.h=20NSPR=20header=20typedefs=20uint64=20= and=20int64=20with=0A+=20*=20colliding=20definitions=20from=20ours,=20= causing=20a=20much=20expected=20compiler=20error.=0A+=20*=20Remove=20= backwards=20compatibility=20with=20ancient=20NSPR=20versions=20to=20= avoid=20this.=0A+=20*/=0A+#define=20NO_NSPR_10_SUPPORT=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+=0A+/*=0A+=20*=20Ensure=20that=20the=20colliding=20= definitions=20match,=20else=20throw=20an=20error.=20In=20case=0A+=20*=20= NSPR=20remove=20the=20definition=20in=20a=20future=20version=20(however=20= unlikely=20that=20may=0A+=20*=20be,=20make=20sure=20to=20put=20ours=20= back=20again.=0A+=20*/=0A+#if=20defined(BITS_PER_BYTE)=0A+#if=20= BITS_PER_BYTE=20!=3D=20pg_BITS_PER_BYTE=0A+#error=20"incompatible=20byte=20= widths=20between=20NSPR=20and=20PostgreSQL"=0A+#endif=0A+#else=0A= +#define=20BITS_PER_BYTE=20pg_BITS_PER_BYTE=0A+#endif=0A+#undef=20= pg_BITS_PER_BYTE=0A+=0A+static=20SECStatus=20= pg_load_nss_module(SECMODModule=20*=20*module,=20const=20char=20= *library,=20const=20char=20*name);=0A+static=20SECStatus=20= pg_bad_cert_handler(void=20*arg,=20PRFileDesc=20*=20fd);=0A+static=20= const=20char=20*pg_SSLerrmessage(PRErrorCode=20errcode);=0A+static=20= SECStatus=20pg_client_auth_handler(void=20*arg,=20PRFileDesc=20*=20= socket,=20CERTDistNames=20*=20caNames,=0A+=09=09=09=09=09=09=09=09=09=09= CERTCertificate=20*=20*pRetCert,=20SECKEYPrivateKey=20*=20*pRetKey);=0A= +static=20SECStatus=20pg_cert_auth_handler(void=20*arg,=20PRFileDesc=20*=20= fd,=20PRBool=20checksig,=20PRBool=20isServer);=0A+static=20int=09= ssl_protocol_version_to_nss(const=20char=20*protocol);=0A+static=20bool=20= cert_database_has_CA(PGconn=20*conn);=0A+=0A+static=20char=20= *PQssl_passwd_cb(PK11SlotInfo=20*=20slot,=20PRBool=20retry,=20void=20= *arg);=0A+=0A+/*=0A+=20*=20PR_ImportTCPSocket()=20is=20a=20private=20= API,=20but=20very=20widely=20used,=20as=20it's=20the=0A+=20*=20only=20= way=20to=20make=20NSS=20use=20an=20already=20set=20up=20POSIX=20file=20= descriptor=20rather=0A+=20*=20than=20opening=20one=20itself.=20To=20= quote=20the=20NSS=20documentation:=0A+=20*=0A+=20*=09=09"In=20theory,=20= code=20that=20uses=20PR_ImportTCPSocket=20may=20break=20when=20NSPR's=0A= +=20*=09=09implementation=20changes.=20In=20practice,=20this=20is=20= unlikely=20to=20happen=20because=0A+=20*=09=09NSPR's=20implementation=20= has=20been=20stable=20for=20years=20and=20because=20of=20NSPR's=0A+=20*=09= =09strong=20commitment=20to=20backward=20compatibility."=0A+=20*=0A+=20*=20= https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/P= R_ImportTCPSocket=0A+=20*=0A+=20*=20The=20function=20is=20declared=20in=20= ,=20but=20as=20it=20is=20a=20header=20marked=0A+=20*=20= private=20we=20declare=20it=20here=20rather=20than=20including=20it.=0A+=20= */=0A+NSPR_API(PRFileDesc=20*)=20PR_ImportTCPSocket(int);=0A+=0A+static=20= SECMODModule=20*=20ca_trust=20=3D=20NULL;=0A+static=20NSSInitContext=20*=20= nss_context=20=3D=20NULL;=0A+=0A+/*=0A+=20*=20Track=20whether=20the=20= NSS=20database=20has=20a=20password=20set=20or=20not.=20There=20is=20no=20= API=0A+=20*=20function=20for=20retrieving=20password=20status,=20so=20we=20= simply=20flip=20this=20to=20true=20in=0A+=20*=20case=20NSS=20invoked=20= the=20password=20callback=20-=20as=20that=20will=20only=20happen=20in=20= case=0A+=20*=20there=20is=20a=20password.=20The=20reason=20for=20= tracking=20this=20is=20that=20there=20are=20calls=0A+=20*=20which=20= require=20a=20password=20parameter,=20but=20doesn't=20use=20the=20= callbacks=20provided,=0A+=20*=20so=20we=20must=20call=20the=20callback=20= on=20behalf=20of=20these.=0A+=20*/=0A+static=20bool=20has_password=20=3D=20= false;=0A+=0A+/*=0A+=20*=20This=20logic=20exist=20in=20NSS=20as=20well,=20= but=20it's=20only=20available=20for=20when=20there=20is=0A+=20*=20a=20= database=20to=20open,=20and=20not=20only=20using=20the=20system=20trust=20= store.=20Thus,=20we=0A+=20*=20need=20to=20keep=20our=20own=20copy.=0A+=20= */=0A+#if=20defined(WIN32)=0A+static=20const=20char=20*ca_trust_name=20=3D= =20"nssckbi.dll";=0A+#elif=20defined(__darwin__)=0A+static=20const=20= char=20*ca_trust_name=20=3D=20"libnssckbi.dylib";=0A+#else=0A+static=20= const=20char=20*ca_trust_name=20=3D=20"libnssckbi.so";=0A+#endif=0A+=0A= +static=20PQsslKeyPassHook_nss_type=20PQsslKeyPassHook=20=3D=20NULL;=0A+=0A= +/*=20------------------------------------------------------------=20*/=0A= +/*=09=09=09=20Procedures=20common=20to=20all=20secure=20sessions=09=09=09= */=0A+/*=20------------------------------------------------------------=20= */=0A+=0A+/*=0A+=20*=20pgtls_init_library=0A+=20*=0A+=20*=20There=20is=20= no=20direct=20equivalent=20for=20PQinitOpenSSL=20in=20NSS/NSPR,=20with=20= PR_Init=0A+=20*=20being=20the=20closest=20match=20there=20is.=20PR_Init=20= is=20however=20already=20documented=20to=0A+=20*=20not=20be=20required=20= so=20simply=20making=20this=20a=20noop=20seems=20like=20the=20best=20= option.=0A+=20*/=0A+void=0A+pgtls_init_library(bool=20do_ssl,=20int=20= do_crypto)=0A+{=0A+=09/*=20noop=20*/=0A+}=0A+=0A+int=0A= +pgtls_init(PGconn=20*conn)=0A+{=0A+=09conn->ssl_in_use=20=3D=20false;=0A= +=0A+=09return=200;=0A+}=0A+=0A+void=0A+pgtls_close(PGconn=20*conn)=0A+{=0A= +=09if=20(nss_context)=0A+=09{=0A+=09=09= NSS_ShutdownContext(nss_context);=0A+=09=09nss_context=20=3D=20NULL;=0A+=09= }=0A+}=0A+=0A+PostgresPollingStatusType=0A+pgtls_open_client(PGconn=20= *conn)=0A+{=0A+=09SECStatus=09status;=0A+=09PRFileDesc=20*pr_fd;=0A+=09= PRFileDesc=20*model;=0A+=09NSSInitParameters=20params;=0A+=09= SSLVersionRange=20desired_range;=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+=0A+=09= if=20(conn->cert_database=20&&=20strlen(conn->cert_database)=20>=200)=0A= +=09{=0A+=09=09char=09=20=20=20*cert_database_path=20=3D=20= psprintf("sql:%s",=20conn->cert_database);=0A+=0A+=09=09nss_context=20=3D=20= NSS_InitContext(cert_database_path,=20"",=20"",=20"",=0A+=09=09=09=09=09=09= =09=09=09=20=20¶ms,=0A+=09=09=09=09=09=09=09=09=09=20=20= NSS_INIT_READONLY=20|=20NSS_INIT_PK11RELOAD);=0A+=09=09= pfree(cert_database_path);=0A+=09}=0A+=09else=0A+=09=09nss_context=20=3D=20= NSS_InitContext("",=20"",=20"",=20"",=20¶ms,=0A+=09=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=09=20=20NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A+=09= =09=09=09=09=09=09=09=09=20=20NSS_INIT_NOROOTINIT=20|=20= NSS_INIT_PK11RELOAD);=0A+=0A+=09if=20(!nss_context)=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20%s=20certificate=20database:=20%s"),=0A+=09=09= =09=09=09=09=20=20conn->cert_database=20?=20"open"=20:=20"create",=0A+=09= =09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=0A+=09=09= return=20PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20= Configure=20cipher=20policy.=0A+=09=20*/=0A+=09status=20=3D=20= NSS_SetDomesticPolicy();=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09{=0A= +=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20configure=20cipher=20policy:=20%s"),=0A+=09=09= =09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20If=20we=20don't=20= have=20a=20certificate=20database,=20the=20system=20trust=20store=20is=20= the=0A+=09=20*=20fallback=20we=20can=20use.=20If=20we=20fail=20to=20= initialize=20that=20as=20well,=20we=20can=0A+=09=20*=20still=20attempt=20= a=20connection=20as=20long=20as=20the=20sslmode=20isn't=20verify*.=0A+=09= =20*/=0A+=09if=20(!conn->cert_database=20&&=20conn->sslmode[0]=20=3D=3D=20= 'v')=0A+=09{=0A+=09=09status=20=3D=20pg_load_nss_module(&ca_trust,=20= ca_trust_name,=20"\"Root=20Certificates\"");=0A+=09=09if=20(status=20!=3D=20= SECSuccess)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("WARNING:=20unable=20to=20load=20NSS=20trust=20module=20= \"%s\"=20:=20%s"),=0A+=09=09=09=09=09=09=09=20=20ca_trust_name,=0A+=09=09= =09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=0A+=09=09=09= return=20PGRES_POLLING_FAILED;=0A+=09=09}=0A+=09}=0A+=0A+=0A+=09= PK11_SetPasswordFunc(PQssl_passwd_cb);=0A+=0A+=09/*=0A+=09=20*=20Import=20= the=20already=20opened=20socket=20as=20we=20don't=20want=20to=20use=20= NSPR=20functions=0A+=09=20*=20for=20opening=20the=20network=20socket=20= due=20to=20how=20the=20PostgreSQL=20protocol=20works=0A+=09=20*=20with=20= TLS=20connections.=20This=20function=20is=20not=20part=20of=20the=20NSPR=20= public=20API,=0A+=09=20*=20see=20the=20comment=20at=20the=20top=20of=20= the=20file=20for=20the=20rationale=20of=20still=20using=0A+=09=20*=20it.=0A= +=09=20*/=0A+=09pr_fd=20=3D=20PR_ImportTCPSocket(conn->sock);=0A+=09if=20= (!pr_fd)=0A+=09{=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09= =09=09=09=09=20=20libpq_gettext("unable=20to=20attach=20to=20socket:=20= %s"),=0A+=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09= =09return=20PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Most=20= of=20the=20documentation=20available,=20and=20implementations=20of,=20= NSS/NSPR=0A+=09=20*=20use=20the=20PR_NewTCPSocket()=20function=20here,=20= which=20has=20the=20drawback=20that=20it=0A+=09=20*=20can=20only=20= create=20IPv4=20sockets.=20Instead=20use=20PR_OpenTCPSocket()=20which=0A= +=09=20*=20copes=20with=20IPv6=20as=20well.=0A+=09=20*/=0A+=09model=20=3D=20= SSL_ImportFD(NULL,=20PR_OpenTCPSocket(conn->laddr.addr.ss_family));=0A+=09= if=20(!model)=0A+=09{=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A= +=09=09=09=09=09=09=20=20libpq_gettext("unable=20to=20enable=20TLS:=20= %s"),=0A+=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09= =09return=20PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=20Disable=20old=20= protocol=20versions=20(SSLv2=20and=20SSLv3)=20*/=0A+=09= SSL_OptionSet(model,=20SSL_ENABLE_SSL2,=20PR_FALSE);=0A+=09= SSL_OptionSet(model,=20SSL_V2_COMPATIBLE_HELLO,=20PR_FALSE);=0A+=09= SSL_OptionSet(model,=20SSL_ENABLE_SSL3,=20PR_FALSE);=0A+=0A+#ifdef=20= SSL_CBC_RANDOM_IV=0A+=0A+=09/*=0A+=09=20*=20Enable=20protection=20= against=20the=20BEAST=20attack=20in=20case=20the=20NSS=20library=20has=0A= +=09=20*=20support=20for=20that.=20While=20SSLv3=20is=20disabled,=20we=20= may=20still=20allow=20TLSv1=0A+=09=20*=20which=20is=20affected.=20The=20= option=20isn't=20documented=20as=20an=20SSL=20option,=20but=20as=0A+=09=20= *=20an=20NSS=20environment=20variable.=0A+=09=20*/=0A+=09= SSL_OptionSet(model,=20SSL_CBC_RANDOM_IV,=20PR_TRUE);=0A+#endif=0A+=0A+=09= /*=20Set=20us=20up=20as=20a=20TLS=20client=20for=20the=20handshake=20*/=0A= +=09SSL_OptionSet(model,=20SSL_HANDSHAKE_AS_CLIENT,=20PR_TRUE);=0A+=0A+=09= /*=0A+=09=20*=20When=20setting=20the=20available=20protocols,=20we=20= either=20use=20the=20user=20defined=0A+=09=20*=20configuration=20values,=20= and=20if=20missing=20we=20accept=20whatever=20is=20the=20highest=0A+=09=20= *=20version=20supported=20by=20the=20library=20as=20the=20max=20and=20= only=20limit=20the=20range=20in=0A+=09=20*=20the=20other=20end=20at=20= TLSv1.0.=20ssl_variant_stream=20is=20a=20ProtocolVariant=20enum=0A+=09=20= *=20for=20Stream=20protocols,=20rather=20than=20datagram.=0A+=09=20*/=0A= +=09SSL_VersionRangeGetSupported(ssl_variant_stream,=20&desired_range);=0A= +=09desired_range.min=20=3D=20SSL_LIBRARY_VERSION_TLS_1_0;=0A+=0A+=09if=20= (conn->ssl_min_protocol_version=20&&=20= strlen(conn->ssl_min_protocol_version)=20>=200)=0A+=09{=0A+=09=09int=09=09= =09ssl_min_ver=20=3D=20= ssl_protocol_version_to_nss(conn->ssl_min_protocol_version);=0A+=0A+=09=09= if=20(ssl_min_ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("invalid=20value=20\"%s\"=20for=20minimum=20version=20of=20= SSL=20protocol\n"),=0A+=09=09=09=09=09=09=09=20=20= conn->ssl_min_protocol_version);=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=0A= +=09=09desired_range.min=20=3D=20ssl_min_ver;=0A+=09}=0A+=0A+=09if=20= (conn->ssl_max_protocol_version=20&&=20= strlen(conn->ssl_max_protocol_version)=20>=200)=0A+=09{=0A+=09=09int=09=09= =09ssl_max_ver=20=3D=20= ssl_protocol_version_to_nss(conn->ssl_max_protocol_version);=0A+=0A+=09=09= if=20(ssl_max_ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("invalid=20value=20\"%s\"=20for=20maximum=20version=20of=20= SSL=20protocol\n"),=0A+=09=09=09=09=09=09=09=20=20= conn->ssl_max_protocol_version);=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=0A= +=09=09desired_range.max=20=3D=20ssl_max_ver;=0A+=09}=0A+=0A+=09if=20= (SSL_VersionRangeSet(model,=20&desired_range)=20!=3D=20SECSuccess)=0A+=09= {=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20= =20libpq_gettext("unable=20to=20set=20allowed=20SSL=20protocol=20version=20= range:=20%s"),=0A+=09=09=09=09=09=09=20=20= pg_SSLerrmessage(PR_GetError()));=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Set=20up=20= callback=20for=20verifying=20server=20certificates,=20as=20well=20as=20= for=20how=0A+=09=20*=20to=20handle=20failed=20verifications.=0A+=09=20*/=0A= +=09SSL_AuthCertificateHook(model,=20pg_cert_auth_handler,=20(void=20*)=20= conn);=0A+=09SSL_BadCertHook(model,=20pg_bad_cert_handler,=20(void=20*)=20= conn);=0A+=0A+=09/*=0A+=09=20*=20Convert=20the=20NSPR=20socket=20to=20an=20= SSL=20socket.=20Ensuring=20the=20success=20of=20this=0A+=09=20*=20= operation=20is=20critical=20as=20NSS=20SSL_*=20functions=20may=20return=20= SECSuccess=20on=0A+=09=20*=20the=20socket=20even=20though=20SSL=20hasn't=20= been=20enabled,=20which=20introduce=20a=20risk=0A+=09=20*=20of=20silent=20= downgrades.=0A+=09=20*/=0A+=09conn->pr_fd=20=3D=20SSL_ImportFD(model,=20= pr_fd);=0A+=09if=20(!conn->pr_fd)=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20configure=20client=20for=20TLS:=20%s"),=0A+=09= =09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20The=20model=20= can=20now=20we=20closed=20as=20we've=20applied=20the=20settings=20of=20= the=20model=0A+=09=20*=20onto=20the=20real=20socket.=20=46rom=20hereon=20= we=20should=20only=20use=20conn->pr_fd.=0A+=09=20*/=0A+=09= PR_Close(model);=0A+=0A+=09/*=20Set=20the=20private=20data=20to=20be=20= passed=20to=20the=20password=20callback=20*/=0A+=09= SSL_SetPKCS11PinArg(conn->pr_fd,=20(void=20*)=20conn);=0A+=0A+=09/*=0A+=09= =20*=20If=20a=20CRL=20file=20has=20been=20specified,=20verify=20if=20it=20= exists=20in=20the=20database=0A+=09=20*=20but=20don't=20fail=20in=20case=20= it=20doesn't.=0A+=09=20*/=0A+=09if=20(conn->sslcrl=20&&=20= strlen(conn->sslcrl)=20>=200)=0A+=09{=0A+=09=09/*=20XXX:=20Implement=20= me..=20*/=0A+=09}=0A+=0A+=09status=20=3D=20= SSL_ResetHandshake(conn->pr_fd,=20PR_FALSE);=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09= =09=09=09=09=09=20=20libpq_gettext("unable=20to=20initiate=20handshake:=20= %s"),=0A+=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09= =09return=20PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Set=20= callback=20for=20client=20authentication=20when=20requested=20by=20the=20= server.=0A+=09=20*/=0A+=09SSL_GetClientAuthDataHook(conn->pr_fd,=20= pg_client_auth_handler,=20(void=20*)=20conn);=0A+=0A+=09/*=0A+=09=20*=20= Specify=20which=20hostname=20we=20are=20expecting=20to=20talk=20to.=20= This=20is=20required,=0A+=09=20*=20albeit=20mostly=20applies=20to=20when=20= opening=20a=20connection=20to=20a=20traditional=0A+=09=20*=20http=20= server=20it=20seems.=0A+=09=20*/=0A+=09SSL_SetURL(conn->pr_fd,=20= (conn->connhost[conn->whichhost]).host);=0A+=0A+=09do=0A+=09{=0A+=09=09= status=20=3D=20SSL_ForceHandshake(conn->pr_fd);=0A+=09}=0A+=09while=20= (status=20!=3D=20SECSuccess=20&&=20PR_GetError()=20=3D=3D=20= PR_WOULD_BLOCK_ERROR);=0A+=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09= {=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20= =20libpq_gettext("SSL=20error:=20%s"),=0A+=09=09=09=09=09=09=20=20= pg_SSLerrmessage(PR_GetError()));=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09conn->ssl_in_use=20=3D=20true;=0A= +=09return=20PGRES_POLLING_OK;=0A+}=0A+=0A+ssize_t=0A+pgtls_read(PGconn=20= *conn,=20void=20*ptr,=20size_t=20len)=0A+{=0A+=09PRInt32=09=09nread;=0A+=09= PRErrorCode=20status;=0A+=09int=09=09=09read_errno=20=3D=200;=0A+=0A+=09= /*=0A+=09=20*=20PR_Recv=20blocks=20until=20there=20is=20data=20to=20read=20= or=20the=20timeout=20expires.=20We=0A+=09=20*=20don't=20want=20to=20sit=20= blocked=20here,=20so=20the=20timeout=20is=20turned=20off=20by=20using=0A= +=09=20*=20PR_INTERVAL_NO_WAIT=20which=20means=20"return=20immediately",=20= =20Zero=20is=20returned=0A+=09=20*=20for=20closed=20connections,=20while=20= -1=20indicates=20an=20error=20within=20the=20ongoing=0A+=09=20*=20= connection.=0A+=09=20*/=0A+=09nread=20=3D=20PR_Recv(conn->pr_fd,=20ptr,=20= len,=200,=20PR_INTERVAL_NO_WAIT);=0A+=0A+=09if=20(nread=20=3D=3D=200)=0A= +=09{=0A+=09=09read_errno=20=3D=20ECONNRESET;=0A+=09=09return=20-1;=0A+=09= }=0A+=0A+=09if=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_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=09default:=0A+=09=09=09=09read_errno=20=3D=20ECONNRESET;=0A= +=09=09=09=09break;=0A+=09=09}=0A+=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("TLS=20read=20error:=20%s"),=0A+=09=09=09=09=09=09=20=20= pg_SSLerrmessage(status));=0A+=09}=0A+=0A+=09SOCK_ERRNO_SET(read_errno);=0A= +=09return=20(ssize_t)=20nread;=0A+}=0A+=0A+/*=0A+=20*=20= pgtls_read_pending=0A+=20*=09=09Check=20for=20the=20existence=20of=20= data=20to=20be=20read.=0A+=20*=0A+=20*=20This=20is=20part=20of=20the=20= PostgreSQL=20TLS=20backend=20API.=0A+=20*/=0A+bool=0A= +pgtls_read_pending(PGconn=20*conn)=0A+{=0A+=09unsigned=20char=20c;=0A+=09= int=09=09=09n;=0A+=0A+=09/*=0A+=09=20*=20PR_Recv=20peeks=20into=20the=20= stream=20with=20the=20timeount=20turned=20off,=20to=20see=20if=0A+=09=20= *=20there=20is=20another=20byte=20to=20read=20off=20the=20wire.=20There=20= is=20an=20NSS=20function=0A+=09=20*=20SSL_DataPending()=20which=20might=20= seem=20like=20a=20better=20fit,=20but=20it=20will=20only=0A+=09=20*=20= check=20already=20encrypted=20data=20in=20the=20SSL=20buffer,=20not=20= still=20unencrypted=0A+=09=20*=20data,=20thus=20it=20doesn't=20guarantee=20= that=20a=20subsequent=20call=20to=0A+=09=20*=20PR_Read/PR_Recv=20wont=20= block.=0A+=09=20*/=0A+=09n=20=3D=20PR_Recv(conn->pr_fd,=20&c,=201,=20= PR_MSG_PEEK,=20PR_INTERVAL_NO_WAIT);=0A+=09return=20(n=20>=200);=0A+}=0A= +=0A+ssize_t=0A+pgtls_write(PGconn=20*conn,=20const=20void=20*ptr,=20= size_t=20len)=0A+{=0A+=09PRInt32=09=09n;=0A+=09PRErrorCode=20status;=0A+=09= int=09=09=09write_errno=20=3D=200;=0A+=0A+=09n=20=3D=20= PR_Write(conn->pr_fd,=20ptr,=20len);=0A+=0A+=09if=20(n=20<=200)=0A+=09{=0A= +=09=09status=20=3D=20PR_GetError();=0A+=0A+=09=09switch=20(status)=0A+=09= =09{=0A+=09=09=09case=20PR_WOULD_BLOCK_ERROR:=0A+#ifdef=20EAGAIN=0A+=09=09= =09=09write_errno=20=3D=20EAGAIN;=0A+#else=0A+=09=09=09=09write_errno=20= =3D=20EINTR;=0A+#endif=0A+=09=09=09=09break;=0A+=0A+=09=09=09default:=0A= +=09=09=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09= =09=09=20=20libpq_gettext("TLS=20write=20error:=20%s"),=0A+=09=09=09=09=09= =09=09=09=20=20pg_SSLerrmessage(status));=0A+=09=09=09=09write_errno=20=3D= =20ECONNRESET;=0A+=09=09=09=09break;=0A+=09=09}=0A+=09}=0A+=0A+=09= SOCK_ERRNO_SET(write_errno);=0A+=09return=20(ssize_t)=20n;=0A+}=0A+=0A= +/*=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=09= =20=20=20*server_hostname=20=3D=20NULL;=0A+=09CERTCertificate=20= *server_cert=20=3D=20NULL;=0A+=09SECStatus=20status=20=3D=20SECSuccess;=0A= +=09SECItem=09=09=09altname_item;=0A+=09PLArenaPool=09=20=20=20*arena=20= =3D=20NULL;=0A+=09CERTGeneralName=20*san_list;=0A+=09CERTGeneralName=20= *cn;=0A+=0A+=09server_hostname=20=3D=20SSL_RevealURL(conn->pr_fd);=0A+=09= if=20(!server_hostname=20||=20server_hostname[0]=20=3D=3D=20'\0')=0A+=09=09= goto=20done;=0A+=0A+=09/*=0A+=09=20*=20CERT_VerifyCertName=20will=20= internally=20perform=20RFC=202818=20SubjectAltName=0A+=09=20*=20= verification.=0A+=09=20*/=0A+=09server_cert=20=3D=20= SSL_PeerCertificate(conn->pr_fd);=0A+=09status=20=3D=20= CERT_VerifyCertName(server_cert,=20server_hostname);=0A+=09if=20(status=20= !=3D=20SECSuccess)=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20verify=20server=20hostname:=20%s"),=0A+=09=09= =09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09goto=20= done;=0A+=09}=0A+=0A+=09status=20=3D=20= CERT_FindCertExtension(server_cert,=20SEC_OID_X509_SUBJECT_ALT_NAME,=0A+=09= =09=09=09=09=09=09=09=09&altname_item);=0A+=09if=20(status=20=3D=3D=20= SECSuccess)=0A+=09{=0A+=09=09arena=20=3D=20= PORT_NewArena(DER_DEFAULT_CHUNKSIZE);=0A+=09=09if=20(!arena)=0A+=09=09{=0A= +=09=09=09status=20=3D=20SECFailure;=0A+=09=09=09goto=20done;=0A+=09=09}=0A= +=09=09san_list=20=3D=20CERT_DecodeAltNameExtension(arena,=20= &altname_item);=0A+=09=09if=20(!san_list)=0A+=09=09{=0A+=09=09=09status=20= =3D=20SECFailure;=0A+=09=09=09goto=20done;=0A+=09=09}=0A+=0A+=09=09for=20= (cn=20=3D=20san_list;=20cn=20!=3D=20san_list;=20cn=20=3D=20= CERT_GetNextGeneralName(cn))=0A+=09=09{=0A+=09=09=09char=09=20=20=20= *alt_name;=0A+=09=09=09int=09=09=09rv;=0A+=09=09=09char=09=09tmp[512];=0A= +=0A+=09=09=09status=20=3D=20CERT_RFC1485_EscapeAndQuote(tmp,=20= sizeof(tmp),=0A+=09=09=09=09=09=09=09=09=09=09=09=09=20(char=20*)=20= cn->name.other.data,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=20= cn->name.other.len);=0A+=0A+=09=09=09if=20(status=20!=3D=20SECSuccess)=0A= +=09=09=09=09goto=20done;=0A+=0A+=09=09=09rv=20=3D=20= pq_verify_peer_name_matches_certificate_name(conn,=20tmp,=0A+=09=09=09=09= =09=09=09=09=09=09=09=09=09=09=09=20=20strlen(tmp),=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=20=20&alt_name);=0A+=09=09=09if=20(alt_name)=0A= +=09=09=09{=0A+=09=09=09=09if=20(!*first_name)=0A+=09=09=09=09=09= *first_name=20=3D=20alt_name;=0A+=09=09=09=09else=0A+=09=09=09=09=09= free(alt_name);=0A+=09=09=09}=0A+=0A+=09=09=09if=20(rv=20=3D=3D=201)=0A+=09= =09=09=09status=20=3D=20SECSuccess;=0A+=09=09=09else=0A+=09=09=09{=0A+=09= =09=09=09status=20=3D=20SECFailure;=0A+=09=09=09=09break;=0A+=09=09=09}=0A= +=09=09}=0A+=09}=0A+=09else=20if=20(PORT_GetError()=20=3D=3D=20= SEC_ERROR_EXTENSION_NOT_FOUND)=0A+=09=09status=20=3D=20SECSuccess;=0A+=09= else=0A+=09=09status=20=3D=20SECSuccess;=0A+=0A+done:=0A+=09/*=20= san_list=20will=20be=20freed=20by=20freeing=20the=20arena=20it=20was=20= allocated=20in=20*/=0A+=09if=20(arena)=0A+=09=09PORT_FreeArena(arena,=20= PR_TRUE);=0A+=09PR_Free(server_hostname);=0A+=0A+=09if=20(status=20=3D=3D=20= SECSuccess)=0A+=09=09return=201;=0A+=0A+=09return=200;=0A+}=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09PostgreSQL=20specific=20TLS=20support=20functions=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +static=20const=20char=20*=0A+pg_SSLerrmessage(PRErrorCode=20errcode)=0A= +{=0A+=09const=20char=20*error;=0A+=0A+=09error=20=3D=20= PR_ErrorToName(errcode);=0A+=09if=20(error)=0A+=09=09return=20error;=0A+=0A= +=09return=20"unknown=20TLS=20error";=0A+}=0A+=0A+static=20SECStatus=0A= +pg_load_nss_module(SECMODModule=20*=20*module,=20const=20char=20= *library,=20const=20char=20*name)=0A+{=0A+=09SECMODModule=20*mod;=0A+=09= char=09=20=20=20*modulespec;=0A+=0A+=09modulespec=20=3D=20= psprintf("library=3D\"%s\",=20name=3D\"%s\"",=20library,=20name);=0A+=0A= +=09/*=0A+=09=20*=20Attempt=20to=20load=20the=20specified=20module.=20= The=20second=20parameter=20is=20"parent"=0A+=09=20*=20which=20should=20= always=20be=20NULL=20for=20application=20code.=20The=20third=20parameter=0A= +=09=20*=20defines=20if=20loading=20should=20recurse=20which=20is=20only=20= applicable=20when=20loading=0A+=09=20*=20a=20module=20from=20within=20= another=20module.=20This=20hierarchy=20would=20have=20to=20be=0A+=09=20*=20= defined=20in=20the=20modulespec,=20and=20since=20we=20don't=20support=20= anything=20but=0A+=09=20*=20directly=20addressed=20modules=20we=20should=20= pass=20PR_FALSE.=0A+=09=20*/=0A+=09mod=20=3D=20= SECMOD_LoadUserModule(modulespec,=20NULL,=20PR_FALSE);=0A+=09= pfree(modulespec);=0A+=0A+=09if=20(mod=20&&=20mod->loaded)=0A+=09{=0A+=09= =09*module=20=3D=20mod;=0A+=09=09return=20SECSuccess;=0A+=09}=0A+=0A+=09= SECMOD_DestroyModule(mod);=0A+=09return=20SECFailure;=0A+}=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09=09=09=09NSS=20Callbacks=09=09=09=09=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +/*=0A+=20*=20pg_cert_auth_handler=0A+=20*=09=09=09Callback=20for=20= authenticating=20server=20certificate=0A+=20*=0A+=20*=20This=20is=20= pretty=20much=20the=20same=20procedure=20as=20the=20SSL_AuthCertificate=20= function=0A+=20*=20provided=20by=20NSS,=20with=20the=20difference=20= being=20server=20hostname=20validation.=20With=0A+=20*=20= SSL_AuthCertificate=20there=20is=20no=20way=20to=20do=20verify-ca,=20it=20= only=20does=20the=20-full=0A+=20*=20flavor=20of=20our=20sslmodes,=20so=20= we=20need=20our=20own=20implementation.=0A+=20*/=0A+static=20SECStatus=0A= +pg_cert_auth_handler(void=20*arg,=20PRFileDesc=20*fd,=20PRBool=20= checksig,=20PRBool=20isServer)=0A+{=0A+=09SECStatus=09status;=0A+=09= PGconn=09=20=20=20*conn=20=3D=20(PGconn=20*)=20arg;=0A+=09= CERTCertificate=20*server_cert;=0A+=09void=09=20=20=20*pin;=0A+=0A+=09= Assert(!isServer);=0A+=0A+=09pin=20=3D=20SSL_RevealPinArg(conn->pr_fd);=0A= +=09server_cert=20=3D=20SSL_PeerCertificate(conn->pr_fd);=0A+=0A+=09= status=20=3D=20CERT_VerifyCertificateNow((CERTCertDBHandle=20*)=20= CERT_GetDefaultCertDB(),=0A+=09=09=09=09=09=09=09=09=09=20=20=20= server_cert,=0A+=09=09=09=09=09=09=09=09=09=20=20=20checksig,=0A+=09=09=09= =09=09=09=09=09=09=20=20=20certificateUsageSSLServer,=0A+=09=09=09=09=09=09= =09=09=09=20=20=20pin,=0A+=09=09=09=09=09=09=09=09=09=20=20=20NULL);=0A+=0A= +=09/*=0A+=09=20*=20If=20we've=20already=20failed=20validation=20then=20= there=20is=20no=20point=20in=20also=0A+=09=20*=20performing=20the=20= hostname=20check=20for=20verify-full.=0A+=09=20*/=0A+=09if=20(status=20= =3D=3D=20SECSuccess)=0A+=09{=0A+=09=09if=20= (!pq_verify_peer_name_matches_certificate(conn))=0A+=09=09=09status=20=3D=20= SECFailure;=0A+=09}=0A+=09else=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20verify=20certificate:=20%s"),=0A+=09=09=09=09= =09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09}=0A+=0A+=09return=20= status;=0A+}=0A+=0A+/*=0A+=20*=20pg_client_auth_handler=0A+=20*=09=09= Callback=20for=20client=20certificate=20validation=0A+=20*=0A+=20*=20The=20= client=20auth=20callback=20is=20not=20on=20by=20default=20in=20NSS,=20so=20= we=20need=20to=20invoke=0A+=20*=20it=20ourselves=20to=20ensure=20we=20= can=20do=20cert=20authentication.=20A=20TODO=20is=20to=20support=0A+=20*=20= running=20without=20a=20specified=20sslcert=20parameter.=20By=20= retrieving=20all=20the=20certs=0A+=20*=20via=20nickname=20from=20the=20= cert=20database=20and=20see=20if=20we=20find=20one=20which=20apply=20= with=0A+=20*=20NSS_CmpCertChainWCANames()=20and=20= PK11_FindKeyByAnyCert()=20we=20could=20support=0A+=20*=20just=20running=20= with=20a=20ssl=20database=20specified.=0A+=20*=0A+=20*=20For=20now,=20we=20= use=20the=20default=20client=20certificate=20validation=20which=20= requires=20a=0A+=20*=20defined=20nickname=20to=20identify=20the=20cert=20= in=20the=20database.=0A+=20*/=0A+static=20SECStatus=0A= +pg_client_auth_handler(void=20*arg,=20PRFileDesc=20*=20socket,=20= CERTDistNames=20*=20caNames,=0A+=09=09=09=09=09=20=20=20CERTCertificate=20= *=20*pRetCert,=20SECKEYPrivateKey=20*=20*pRetKey)=0A+{=0A+=09PGconn=09=20= =20=20*conn=20=3D=20(PGconn=20*)=20arg;=0A+=0A+=09return=20= NSS_GetClientAuthData(conn->sslcert,=20socket,=20caNames,=20pRetCert,=20= pRetKey);=0A+}=0A+=0A+/*=0A+=20*=20pg_bad_cert_handler=0A+=20*=09=09= Callback=20for=20failed=20certificate=20validation=0A+=20*=0A+=20*=20The=20= TLS=20handshake=20will=20call=20this=20function=20iff=20the=20server=20= certificate=20failed=0A+=20*=20validation.=20Depending=20on=20the=20= sslmode,=20we=20allow=20the=20connection=20anyways.=0A+=20*/=0A+static=20= SECStatus=0A+pg_bad_cert_handler(void=20*arg,=20PRFileDesc=20*=20fd)=0A= +{=0A+=09PGconn=09=20=20=20*conn=20=3D=20(PGconn=20*)=20arg;=0A+=09= PRErrorCode=20err;=0A+=0A+=09/*=0A+=09=20*=20This=20really=20shouldn't=20= happen,=20as=20we've=20the=20the=20PGconn=20object=20as=20our=0A+=09=20*=20= callback=20data,=20and=20at=20the=20callsite=20we=20know=20it=20will=20= be=20populated.=20That=0A+=09=20*=20being=20said,=20the=20NSS=20code=20= itself=20performs=20this=20check=20even=20when=20it=20should=0A+=09=20*=20= not=20be=20required=20so=20let's=20use=20the=20same=20belts=20with=20our=20= suspenders.=0A+=09=20*/=0A+=09if=20(!arg)=0A+=09=09return=20SECFailure;=0A= +=0A+=09/*=0A+=09=20*=20For=20sslmodes=20other=20than=20verify-full=20= and=20verify-ca=20we=20don't=20perform=20peer=0A+=09=20*=20validation,=20= so=20return=20immediately.=20=20sslmode=20require=20with=20a=20database=0A= +=09=20*=20specified=20which=20contains=20a=20CA=20certificate=20will=20= work=20like=20verify-ca=20to=0A+=09=20*=20be=20compatible=20with=20the=20= OpenSSL=20implementation.=0A+=09=20*/=0A+=09if=20(strcmp(conn->sslmode,=20= "require")=20=3D=3D=200)=0A+=09{=0A+=09=09if=20(conn->cert_database=20&&=20= strlen(conn->cert_database)=20>=200=20&&=20cert_database_has_CA(conn))=0A= +=09=09=09return=20SECFailure;=0A+=09}=0A+=09if=20(conn->sslmode[0]=20=3D=3D= =20'v')=0A+=09=09return=20SECFailure;=0A+=0A+=09err=20=3D=20= PORT_GetError();=0A+=0A+=09/*=0A+=09=20*=20TODO:=20these=20are=20= relevant=20error=20codes=20that=20can=20occur=20in=20certificate=0A+=09=20= *=20validation,=20figure=20out=20which=20we=20dont=20want=20for=20= require/prefer=20etc.=0A+=09=20*/=0A+=09switch=20(err)=0A+=09{=0A+=09=09= case=20SEC_ERROR_INVALID_AVA:=0A+=09=09case=20SEC_ERROR_INVALID_TIME:=0A= +=09=09case=20SEC_ERROR_BAD_SIGNATURE:=0A+=09=09case=20= SEC_ERROR_EXPIRED_CERTIFICATE:=0A+=09=09case=20SEC_ERROR_UNKNOWN_ISSUER:=0A= +=09=09case=20SEC_ERROR_UNTRUSTED_ISSUER:=0A+=09=09case=20= SEC_ERROR_UNTRUSTED_CERT:=0A+=09=09case=20SEC_ERROR_CERT_VALID:=0A+=09=09= case=20SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:=0A+=09=09case=20= SEC_ERROR_CRL_EXPIRED:=0A+=09=09case=20SEC_ERROR_CRL_BAD_SIGNATURE:=0A+=09= =09case=20SEC_ERROR_EXTENSION_VALUE_INVALID:=0A+=09=09case=20= SEC_ERROR_CA_CERT_INVALID:=0A+=09=09case=20= SEC_ERROR_CERT_USAGES_INVALID:=0A+=09=09case=20= SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:=0A+=09=09=09return=20SECSuccess;=0A= +=09=09=09break;=0A+=09=09default:=0A+=09=09=09return=20SECFailure;=0A+=09= =09=09break;=0A+=09}=0A+=0A+=09/*=20Unreachable=20*/=0A+=09return=20= SECSuccess;=0A+}=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09=09=09SSL=20information=20functions=09=09=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +/*=0A+=20*=20PQgetssl=0A+=20*=0A+=20*=20Return=20NULL=20as=20this=20is=20= legacy=20and=20defined=20to=20always=20be=20equal=20to=20calling=0A+=20*=20= PQsslStruct(conn,=20"OpenSSL");=20This=20should=20ideally=20trigger=20a=20= logged=20warning=0A+=20*=20somewhere=20as=20it's=20nonsensical=20to=20= run=20in=20a=20non-OpenSSL=20build,=20but=20the=20color=0A+=20*=20of=20= said=20bikeshed=20hasn't=20yet=20been=20determined.=0A+=20*/=0A+void=20*=0A= +PQgetssl(PGconn=20*conn)=0A+{=0A+=09return=20NULL;=0A+}=0A+=0A+void=20*=0A= +PQsslStruct(PGconn=20*conn,=20const=20char=20*struct_name)=0A+{=0A+=09= if=20(!conn)=0A+=09=09return=20NULL;=0A+=0A+=09/*=0A+=09=20*=20Return=20= the=20underlying=20PRFileDesc=20which=20can=20be=20used=20to=20access=0A= +=09=20*=20information=20on=20the=20connection=20details.=20There=20is=20= no=20SSL=20context=20per=20se.=0A+=09=20*/=0A+=09if=20= (strcmp(struct_name,=20"NSS")=20=3D=3D=200)=0A+=09=09return=20= conn->pr_fd;=0A+=09return=20NULL;=0A+}=0A+=0A+const=20char=20*const=20*=0A= +PQsslAttributeNames(PGconn=20*conn)=0A+{=0A+=09static=20const=20char=20= *const=20result[]=20=3D=20{=0A+=09=09"library",=0A+=09=09"cipher",=0A+=09= =09"protocol",=0A+=09=09"key_bits",=0A+=09=09"compression",=0A+=09=09= NULL=0A+=09};=0A+=0A+=09return=20result;=0A+}=0A+=0A+const=20char=20*=0A= +PQsslAttribute(PGconn=20*conn,=20const=20char=20*attribute_name)=0A+{=0A= +=09SECStatus=09status;=0A+=09SSLChannelInfo=20channel;=0A+=09= SSLCipherSuiteInfo=20suite;=0A+=0A+=09if=20(!conn=20||=20!conn->pr_fd)=0A= +=09=09return=20NULL;=0A+=0A+=09if=20(strcmp(attribute_name,=20= "library")=20=3D=3D=200)=0A+=09=09return=20"NSS";=0A+=0A+=09status=20=3D=20= SSL_GetChannelInfo(conn->pr_fd,=20&channel,=20sizeof(channel));=0A+=09if=20= (status=20!=3D=20SECSuccess)=0A+=09=09return=20NULL;=0A+=0A+=09status=20= =3D=20SSL_GetCipherSuiteInfo(channel.cipherSuite,=20&suite,=20= sizeof(suite));=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20= NULL;=0A+=0A+=09if=20(strcmp(attribute_name,=20"cipher")=20=3D=3D=200)=0A= +=09=09return=20suite.cipherSuiteName;=0A+=0A+=09if=20= (strcmp(attribute_name,=20"key_bits")=20=3D=3D=200)=0A+=09{=0A+=09=09= static=20char=20key_bits_str[8];=0A+=0A+=09=09snprintf(key_bits_str,=20= sizeof(key_bits_str),=20"%i",=20suite.effectiveKeyBits);=0A+=09=09return=20= key_bits_str;=0A+=09}=0A+=0A+=09if=20(strcmp(attribute_name,=20= "protocol")=20=3D=3D=200)=0A+=09{=0A+=09=09switch=20= (channel.protocolVersion)=0A+=09=09{=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_3=0A+=09=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_3:=0A+=09=09=09=09return=20"TLSv1.3";=0A= +#endif=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_2=0A+=09=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_2:=0A+=09=09=09=09return=20"TLSv1.2";=0A= +#endif=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_1=0A+=09=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_1:=0A+=09=09=09=09return=20"TLSv1.1";=0A= +#endif=0A+=09=09=09case=20SSL_LIBRARY_VERSION_TLS_1_0:=0A+=09=09=09=09= return=20"TLSv1.0";=0A+=09=09=09default:=0A+=09=09=09=09return=20= "unknown";=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20NSS=20disabled=20= support=20for=20compression=20in=20version=203.33,=20and=20it=20was=20= only=0A+=09=20*=20available=20for=20SSLv3=20at=20that=20point=20anyways,=20= so=20we=20can=20safely=20return=20off=0A+=09=20*=20here=20without=20= checking.=0A+=09=20*/=0A+=09if=20(strcmp(attribute_name,=20= "compression")=20=3D=3D=200)=0A+=09=09return=20"off";=0A+=0A+=09return=20= NULL;=0A+}=0A+=0A+static=20int=0A+ssl_protocol_version_to_nss(const=20= char=20*protocol)=0A+{=0A+=09if=20(pg_strcasecmp("TLSv1",=20protocol)=20= =3D=3D=200)=0A+=09=09return=20SSL_LIBRARY_VERSION_TLS_1_0;=0A+=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_1=0A+=09if=20(pg_strcasecmp("TLSv1.1",=20= protocol)=20=3D=3D=200)=0A+=09=09return=20SSL_LIBRARY_VERSION_TLS_1_1;=0A= +#endif=0A+=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_2=0A+=09if=20= (pg_strcasecmp("TLSv1.2",=20protocol)=20=3D=3D=200)=0A+=09=09return=20= SSL_LIBRARY_VERSION_TLS_1_2;=0A+#endif=0A+=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_3=0A+=09if=20(pg_strcasecmp("TLSv1.3",=20= protocol)=20=3D=3D=200)=0A+=09=09return=20SSL_LIBRARY_VERSION_TLS_1_3;=0A= +#endif=0A+=0A+=09return=20-1;=0A+}=0A+=0A+static=20bool=0A= +cert_database_has_CA(PGconn=20*conn)=0A+{=0A+=09CERTCertList=20= *certificates;=0A+=09bool=09=09hasCA;=0A+=0A+=09/*=0A+=09=20*=20If=20the=20= certificate=20database=20has=20a=20password=20we=20must=20provide=20it,=20= since=0A+=09=20*=20this=20API=20doesn't=20invoke=20the=20standard=20= password=20callback.=0A+=09=20*/=0A+=09if=20(has_password)=0A+=09=09= certificates=20=3D=20PK11_ListCerts(PK11CertListCA,=20= PQssl_passwd_cb(NULL,=20PR_FALSE,=20(void=20*)=20conn));=0A+=09else=0A+=09= =09certificates=20=3D=20PK11_ListCerts(PK11CertListCA,=20NULL);=0A+=09= hasCA=20=3D=20!CERT_LIST_EMPTY(certificates);=0A+=09= CERT_DestroyCertList(certificates);=0A+=0A+=09return=20hasCA;=0A+}=0A+=0A= +PQsslKeyPassHook_nss_type=0A+PQgetSSLKeyPassHook_nss(void)=0A+{=0A+=09= return=20PQsslKeyPassHook;=0A+}=0A+=0A+void=0A= +PQsetSSLKeyPassHook_nss(PQsslKeyPassHook_nss_type=20hook)=0A+{=0A+=09= PQsslKeyPassHook=20=3D=20hook;=0A+}=0A+=0A+/*=0A+=20*=20Supply=20a=20= password=20to=20decrypt=20a=20client=20certificate.=0A+=20*=0A+=20*=20= This=20must=20match=20NSS=20type=20PK11PasswordFunc.=0A+=20*/=0A+static=20= char=20*=0A+PQssl_passwd_cb(PK11SlotInfo=20*=20slot,=20PRBool=20retry,=20= void=20*arg)=0A+{=0A+=09has_password=20=3D=20true;=0A+=0A+=09if=20= (PQsslKeyPassHook)=0A+=09=09return=20PQsslKeyPassHook(slot,=20(PRBool)=20= retry,=20arg);=0A+=09else=0A+=09=09return=20= PQdefaultSSLKeyPassHook_nss(slot,=20retry,=20arg);=0A+}=0A+=0A+/*=0A+=20= *=20The=20default=20password=20handler=20callback.=0A+=20*/=0A+char=20*=0A= +PQdefaultSSLKeyPassHook_nss(PK11SlotInfo=20*=20slot,=20PRBool=20retry,=20= void=20*arg)=0A+{=0A+=09PGconn=09=20=20=20*conn=20=3D=20(PGconn=20*)=20= arg;=0A+=0A+=09/*=0A+=09=20*=20If=20the=20password=20didn't=20work=20the=20= first=20time=20there=20is=20no=20point=20in=0A+=09=20*=20retrying=20as=20= it=20hasn't=20changed.=0A+=09=20*/=0A+=09if=20(retry=20!=3D=20PR_TRUE=20= &&=20conn->sslpassword=20&&=20strlen(conn->sslpassword)=20>=200)=0A+=09=09= return=20PORT_Strdup(conn->sslpassword);=0A+=0A+=09return=20NULL;=0A+}=0A= diff=20--git=20a/src/interfaces/libpq/fe-secure.c=20= b/src/interfaces/libpq/fe-secure.c=0Aindex=2097c3805303..dd6ee15c5a=20= 100644=0A---=20a/src/interfaces/libpq/fe-secure.c=0A+++=20= b/src/interfaces/libpq/fe-secure.c=0A@@=20-427,6=20+427,9=20@@=20= PQsslAttributeNames(PGconn=20*conn)=0A=20=0A=20=09return=20result;=0A=20= }=0A+#endif=20/*=20USE_SSL=20*/=0A+=0A+#ifndef=20USE_OPENSSL=0A=20=0A=20= PQsslKeyPassHook_OpenSSL_type=0A=20PQgetSSLKeyPassHook_OpenSSL(void)=0A= @@=20-445,7=20+448,7=20@@=20PQdefaultSSLKeyPassHook_OpenSSL(char=20*buf,=20= int=20size,=20PGconn=20*conn)=0A=20{=0A=20=09return=200;=0A=20}=0A= -#endif=09=09=09=09=09=09=09/*=20USE_SSL=20*/=0A+#endif=09=09=09=09=09=09= =09/*=20USE_OPENSSL=20*/=0A=20=0A=20/*=20Dummy=20version=20of=20GSSAPI=20= information=20functions,=20when=20built=20without=20GSS=20support=20*/=0A= =20#ifndef=20ENABLE_GSS=0Adiff=20--git=20= a/src/interfaces/libpq/libpq-fe.h=20b/src/interfaces/libpq/libpq-fe.h=0A= index=203b6a9fbce3..27c16e187f=20100644=0A---=20= a/src/interfaces/libpq/libpq-fe.h=0A+++=20= b/src/interfaces/libpq/libpq-fe.h=0A@@=20-625,6=20+625,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*=20slot,=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*=20slot,=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=201de91ae295..49a22f6c7d=20= 100644=0A---=20a/src/interfaces/libpq/libpq-int.h=0A+++=20= b/src/interfaces/libpq/libpq-int.h=0A@@=20-362,6=20+362,7=20@@=20struct=20= pg_conn=0A=20=09char=09=20=20=20*sslpassword;=09/*=20client=20key=20file=20= password=20*/=0A=20=09char=09=20=20=20*sslrootcert;=09/*=20root=20= certificate=20filename=20*/=0A=20=09char=09=20=20=20*sslcrl;=09=09=09/*=20= certificate=20revocation=20list=20filename=20*/=0A+=09char=09=20=20=20= *cert_database;=09/*=20NSS=20certificate/key=20database=20*/=0A=20=09= char=09=20=20=20*requirepeer;=09/*=20required=20peer=20credentials=20for=20= local=20sockets=20*/=0A=20=09char=09=20=20=20*gssencmode;=09=09/*=20GSS=20= mode=20(require,prefer,disable)=20*/=0A=20=09char=09=20=20=20= *krbsrvname;=09=09/*=20Kerberos=20service=20name=20*/=0A@@=20-485,6=20= +486,10=20@@=20struct=20pg_conn=0A=20=09=09=09=09=09=09=09=09=20*=20= OpenSSL=20version=20changes=20*/=0A=20#endif=0A=20#endif=09=09=09=09=09=09= =09/*=20USE_OPENSSL=20*/=0A+=0A+#ifdef=20USE_NSS=0A+=09void=09=20=20=20= *pr_fd;=0A+#endif=09=09=09=09=09=09=09/*=20USE_NSS=20*/=0A=20#endif=09=09= =09=09=09=09=09/*=20USE_SSL=20*/=0A=20=0A=20#ifdef=20ENABLE_GSS=0Adiff=20= --git=20a/src/tools/msvc/Mkvcbuild.pm=20b/src/tools/msvc/Mkvcbuild.pm=0A= index=2090594bd41b..29879b51af=20100644=0A---=20= a/src/tools/msvc/Mkvcbuild.pm=0A+++=20b/src/tools/msvc/Mkvcbuild.pm=0A@@=20= -192,12=20+192,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= -255,12=20+262,19=20@@=20sub=20mkvcbuild=0A=20=09= $libpq->AddReference($libpgcommon,=20$libpgport);=0A=20=0A=20=09#=20The=20= OBJS=20scraper=20doesn't=20know=20about=20ifdefs,=20so=20remove=20= appropriate=20files=0A-=09#=20if=20building=20without=20OpenSSL.=0A-=09= if=20(!$solution->{options}->{openssl})=0A+=09#=20if=20building=20= without=20various=20options=0A+=09if=20(!$solution->{options}->{openssl}=20= &&=20!$solution->{options}->{nss})=0A=20=09{=0A=20=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-secure-common.c');=0A+=09}=0A= +=09if=20(!$solution->{options}->{openssl})=0A+=09{=0A=20=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-secure-openssl.c');=0A=20=09= }=0A+=09if=20(!$solution->{options}->{nss})=0A+=09{=0A+=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-secure-nss.c');=0A+=09}=0A=20= =09if=20(!$solution->{options}->{gss})=0A=20=09{=0A=20=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-gssapi-common.c');=0Adiff=20= --git=20a/src/tools/msvc/Solution.pm=20b/src/tools/msvc/Solution.pm=0A= index=20bc8904732f..ac11d9ab26=20100644=0A---=20= a/src/tools/msvc/Solution.pm=0A+++=20b/src/tools/msvc/Solution.pm=0A@@=20= -484,6=20+484,7=20@@=20sub=20GenerateFiles=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=20=09=09= USE_OPENSSL_RANDOM=20=20=20=20=20=20=20=20=20=3D>=20undef,=0A+=09=09= USE_NSS=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=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>=20undef,=0A=20=09=09USE_SSE42_CRC32C=20=20=20=20=20=20=20=20=20=20=20= =3D>=20undef,=0A@@=20-537,6=20+538,10=20@@=20sub=20GenerateFiles=0A=20=09= =09=09$define{HAVE_OPENSSL_INIT_SSL}=20=20=20=20=20=20=3D=201;=0A=20=09=09= }=0A=20=09}=0A+=09if=20($self->{options}->{nss})=0A+=09{=0A+=09=09= $define{USE_NSS}=20=3D=201;=0A+=09}=0A=20=0A=20=09= $self->GenerateConfigHeader('src/include/pg_config.h',=20=20=20=20=20= \%define,=201);=0A=20=09= $self->GenerateConfigHeader('src/include/pg_config_ext.h',=20\%define,=20= 0);=0A@@=20-1004,6=20+1009,21=20@@=20sub=20AddProject=0A=20=09=09=09}=0A=20= =09=09}=0A=20=09}=0A+=09if=20($self->{options}->{nss})=0A+=09{=0A+=09=09= $proj->AddIncludeDir($self->{options}->{nss}=20.=20'\..\public\nss');=0A= +=09=09$proj->AddIncludeDir($self->{options}->{nss}=20.=20= '\include\nspr');=0A+=09=09foreach=20my=20$lib=20(qw(plds4=20plc4=20= nspr4))=0A+=09=09{=0A+=09=09=09$proj->AddLibrary($self->{options}->{nss}=20= .=0A+=09=09=09=09=09=09=09=20=20'\lib\lib'=20.=20"$lib.lib",=200);=0A+=09= =09}=0A+=09=09foreach=20my=20$lib=20(qw(ssl3=20smime3=20nss3))=0A+=09=09= {=0A+=09=09=09$proj->AddLibrary($self->{options}->{nss}=20.=0A+=09=09=09=09= =09=09=09=20=20'\lib'=20.=20"\\$lib.dll.lib",=200);=0A+=09=09}=0A+=09}=0A= =20=09if=20($self->{options}->{nls})=0A=20=09{=0A=20=09=09= $proj->AddIncludeDir($self->{options}->{nls}=20.=20'\include');=0Adiff=20= --git=20a/src/tools/msvc/config_default.pl=20= b/src/tools/msvc/config_default.pl=0Aindex=202ef2cfc4e9..49dc4d5864=20= 100644=0A---=20a/src/tools/msvc/config_default.pl=0A+++=20= b/src/tools/msvc/config_default.pl=0A@@=20-17,6=20+17,7=20@@=20our=20= $config=20=3D=20{=0A=20=09perl=20=20=20=20=20=20=3D>=20undef,=20=20=20=20= #=20--with-perl=3D=0A=20=09python=20=20=20=20=3D>=20undef,=20=20=20= =20#=20--with-python=3D=0A=20=09openssl=20=20=20=3D>=20undef,=20=20= =20=20#=20--with-openssl=3D=0A+=09nss=20=20=20=20=20=20=20=3D>=20= undef,=20=20=20=20#=20--with-nss=3D=0A=20=09uuid=20=20=20=20=20=20= =3D>=20undef,=20=20=20=20#=20--with-uuid=3D=0A=20=09xml=20=20=20=20= =20=20=20=3D>=20undef,=20=20=20=20#=20--with-libxml=3D=0A=20=09= xslt=20=20=20=20=20=20=3D>=20undef,=20=20=20=20#=20--with-libxslt=3D= =0A--=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_C39967DC-7CE2-4297-8DC3-75F0E858FBDB Content-Disposition: attachment; filename=v15-0002-NSS-Testharness-updates.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v15-0002-NSS-Testharness-updates.patch" Content-Transfer-Encoding: quoted-printable =46rom=20312e98aa96ba91a5c0d07481972c34754d0d44f4=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2028=20Oct=202020=2011:22:26=20+0100=0ASubject:=20[PATCH=20= v15=202/6]=20NSS=20Testharness=20updates=0A=0A---=0A=20src/test/Makefile=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20|=20=20=202=20+-=0A=20src/test/modules/Makefile=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=202=20+-=0A=20= .../modules/ssl_passphrase_callback/Makefile=20=20|=20=20=202=20+-=0A=20= .../ssl_passphrase_callback/t/001_testfunc.pl=20|=20=20=204=20+-=0A=20= src/test/ssl/Makefile=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20|=20177=20+++++++++-=0A=20= src/test/ssl/t/001_ssltests.pl=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20|=20328=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/NSS.pm=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=2064=20++++=0A=20src/test/ssl/t/SSL/Backend/OpenSSL.pm=20=20=20=20=20= =20=20=20=20|=20103=20++++++=0A=20.../ssl/t/{SSLServer.pm=20=3D>=20= SSL/Server.pm}=20=20=20=20=20|=20=2080=20++++-=0A=2010=20files=20= changed,=20608=20insertions(+),=20160=20deletions(-)=0A=20create=20mode=20= 100644=20src/test/ssl/t/SSL/Backend/NSS.pm=0A=20create=20mode=20100644=20= src/test/ssl/t/SSL/Backend/OpenSSL.pm=0A=20rename=20= src/test/ssl/t/{SSLServer.pm=20=3D>=20SSL/Server.pm}=20(78%)=0A=0Adiff=20= --git=20a/src/test/Makefile=20b/src/test/Makefile=0Aindex=20= 9774f534d9..a09c350939=20100644=0A---=20a/src/test/Makefile=0A+++=20= b/src/test/Makefile=0A@@=20-27,7=20+27,7=20@@=20ifneq=20(,$(filter=20= ldap,$(PG_TEST_EXTRA)))=0A=20SUBDIRS=20+=3D=20ldap=0A=20endif=0A=20endif=0A= -ifeq=20($(with_openssl),yes)=0A+ifeq=20($(with_ssl),yes)=0A=20ifneq=20= (,$(filter=20ssl,$(PG_TEST_EXTRA)))=0A=20SUBDIRS=20+=3D=20ssl=0A=20endif=0A= diff=20--git=20a/src/test/modules/Makefile=20b/src/test/modules/Makefile=0A= index=20a6d2ffbf9e..6e6ca97d95=20100644=0A---=20= a/src/test/modules/Makefile=0A+++=20b/src/test/modules/Makefile=0A@@=20= -27,7=20+27,7=20@@=20SUBDIRS=20=3D=20\=0A=20=09=09=20=20unsafe_tests=20\=0A= =20=09=09=20=20worker_spi=0A=20=0A-ifeq=20($(with_openssl),yes)=0A+ifeq=20= ($(with_ssl),openssl)=0A=20SUBDIRS=20+=3D=20ssl_passphrase_callback=0A=20= else=0A=20ALWAYS_SUBDIRS=20+=3D=20ssl_passphrase_callback=0Adiff=20--git=20= a/src/test/modules/ssl_passphrase_callback/Makefile=20= b/src/test/modules/ssl_passphrase_callback/Makefile=0Aindex=20= f81265c296..a34d7ea46a=20100644=0A---=20= a/src/test/modules/ssl_passphrase_callback/Makefile=0A+++=20= b/src/test/modules/ssl_passphrase_callback/Makefile=0A@@=20-1,6=20+1,6=20= @@=0A=20#=20ssl_passphrase_callback=20Makefile=0A=20=0A-export=20= with_openssl=0A+export=20with_ssl=0A=20=0A=20MODULE_big=20=3D=20= ssl_passphrase_func=0A=20OBJS=20=3D=20ssl_passphrase_func.o=20= $(WIN32RES)=0Adiff=20--git=20= a/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl=20= b/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl=0Aindex=20= dbc084f870..a2bed5336c=20100644=0A---=20= a/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl=0A+++=20= b/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl=0A@@=20-7,9=20= +7,9=20@@=20use=20TestLib;=0A=20use=20Test::More;=0A=20use=20= PostgresNode;=0A=20=0A-unless=20(($ENV{with_openssl}=20||=20'no')=20eq=20= 'yes')=0A+unless=20($ENV{with_ssl}=20eq=20'openssl')=0A=20{=0A-=09plan=20= skip_all=20=3D>=20'SSL=20not=20supported=20by=20this=20build';=0A+=09= plan=20skip_all=20=3D>=20'OpenSSL=20not=20supported=20by=20this=20= build';=0A=20}=0A=20=0A=20my=20$clearpass=20=3D=20"FooBaR1";=0Adiff=20= --git=20a/src/test/ssl/Makefile=20b/src/test/ssl/Makefile=0Aindex=20= 777ee39413..e8c0db9a95=20100644=0A---=20a/src/test/ssl/Makefile=0A+++=20= b/src/test/ssl/Makefile=0A@@=20-13,7=20+13,7=20@@=20subdir=20=3D=20= src/test/ssl=0A=20top_builddir=20=3D=20../../..=0A=20include=20= $(top_builddir)/src/Makefile.global=0A=20=0A-export=20with_openssl=0A= +export=20with_ssl=0A=20=0A=20CERTIFICATES=20:=3D=20server_ca=20= server-cn-and-alt-names=20\=0A=20=09server-cn-only=20= server-single-alt-name=20server-multiple-alt-names=20\=0A@@=20-30,6=20= +30,32=20@@=20SSLFILES=20:=3D=20$(CERTIFICATES:%=3Dssl/%.key)=20= $(CERTIFICATES:%=3Dssl/%.crt)=20\=0A=20=09ssl/client+client_ca.crt=20= ssl/client-der.key=20\=0A=20=09ssl/client-encrypted-pem.key=20= ssl/client-encrypted-der.key=0A=20=0A+#=20Even=20though=20we=20in=20= practice=20could=20get=20away=20with=20far=20fewer=20NSS=20databases,=20= they=0A+#=20are=20generated=20to=20mimick=20the=20setup=20for=20the=20= OpenSSL=20tests=20in=20order=20to=20ensure=0A+#=20we=20isolate=20the=20= same=20behavior=20between=20the=20backends.=20The=20database=20name=20= should=0A+#=20contain=20the=20files=20included=20for=20easier=20test=20= suite=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+=09ssl/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/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=0A+=0A=20#=20This=20= target=20re-generates=20all=20the=20key=20and=20certificate=20files.=20= Usually=20we=20just=0A=20#=20use=20the=20ones=20that=20are=20committed=20= to=20the=20tree=20without=20rebuilding=20them.=0A=20#=0A@@=20-37,6=20= +63,10=20@@=20SSLFILES=20:=3D=20$(CERTIFICATES:%=3Dssl/%.key)=20= $(CERTIFICATES:%=3Dssl/%.crt)=20\=0A=20#=0A=20sslfiles:=20$(SSLFILES)=0A=20= =0A+#=20Generate=20NSS=20certificate=20databases=20corresponding=20to=20= the=20OpenSSL=20certificates.=0A+#=20This=20target=20will=20fail=20= unless=20preceded=20by=20nssfiles-clean.=0A+nssfiles:=20$(NSSFILES)=0A+=0A= =20#=20OpenSSL=20requires=20a=20directory=20to=20put=20all=20generated=20= certificates=20in.=20We=20don't=0A=20#=20use=20this=20for=20anything,=20= but=20we=20need=20a=20location.=0A=20ssl/new_certs_dir:=0A@@=20-64,6=20= +94,24=20@@=20ssl/%_ca.crt:=20ssl/%_ca.key=20%_ca.config=20= ssl/root_ca.crt=20ssl/new_certs_dir=0A=20=09rm=20ssl/temp_ca.crt=20= ssl/temp_ca_signed.crt=0A=20=09echo=20"01"=20>=20ssl/$*_ca.srl=0A=20=0A= +ssl/nss/%_ca.crt.db:=20ssl/%_ca.crt=0A+=09$(MKDIR_P)=20$@=0A+=09= certutil=20-d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20$*_ca.crt=20-i=20ssl/$*_ca.crt=20-t=20"CT,C,C"=0A+=0A= +ssl/nss/root+server_ca.crt__server.crl.db:=20ssl/root+server_ca.crt=20= ssl/nss/server.crl=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20"sql:$@"=20= -N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= ssl/root+server_ca.crt=20-i=20ssl/root+server_ca.crt=20-t=20"CT,C,C"=0A+=09= crlutil=20-I=20-i=20ssl/nss/server.crl=20-d=20$@=20-B=0A+=0A= +ssl/nss/root+server_ca.crt__root+server.crl.db:=20= ssl/root+server_ca.crt=20ssl/nss/root.crl=20ssl/nss/server.crl=0A+=09= $(MKDIR_P)=20$@=0A+=09certutil=20-d=20"sql:$@"=20-N=20--empty-password=0A= +=09certutil=20-d=20"sql:$@"=20-A=20-n=20ssl/root+server_ca.crt=20-i=20= ssl/root+server_ca.crt=20-t=20"CT,C,C"=0A+=09crlutil=20-I=20-i=20= ssl/nss/root.crl=20-d=20$@=20-B=0A+=09crlutil=20-I=20-i=20= ssl/nss/server.crl=20-d=20$@=20-B=0A+=0A=20#=20Server=20certificates,=20= signed=20by=20server=20CA:=0A=20ssl/server-%.crt:=20ssl/server-%.key=20= ssl/server_ca.crt=20server-%.config=0A=20=09openssl=20req=20-new=20-key=20= ssl/server-$*.key=20-out=20ssl/server-$*.csr=20-config=20= server-$*.config=0A@@=20-77,6=20+125,78=20@@=20ssl/server-ss.crt:=20= ssl/server-cn-only.key=20ssl/server-cn-only.crt=20server-cn-only.=0A=20=09= openssl=20x509=20-req=20-days=2010000=20-in=20ssl/server-ss.csr=20= -signkey=20ssl/server-cn-only.key=20-out=20ssl/server-ss.crt=20=20= -extensions=20v3_req=20-extfile=20server-cn-only.config=0A=20=09rm=20= ssl/server-ss.csr=0A=20=0A+#=20pk12util=20won't=20preserve=20the=20= password=20when=20importing=20the=20password=20protected=0A+#=20key,=20= the=20password=20must=20be=20set=20on=20the=20database=20*before*=20= importing=20it=20as=20the=0A+#=20password=20in=20the=20pkcs12=20envelope=20= will=20be=20dropped.=0A= +ssl/nss/server-cn-only.crt__server-password.key.db:=20= ssl/server-cn-only.crt=0A+=09$(MKDIR_P)=20$@=0A+=09echo=20"secret1"=20>=20= password.txt=0A+=09certutil=20-d=20"sql:$@"=20-N=20-f=20password.txt=0A+=09= certutil=20-d=20"sql:$@"=20-A=20-n=20ssl/server-cn-only.crt=20-i=20= ssl/server-cn-only.crt=20-t=20"CT,C,C"=20-f=20password.txt=0A+=09= certutil=20-d=20"sql:$@"=20-A=20-n=20server_ca.crt=20-i=20= ssl/server_ca.crt=20-t=20"CT,C,C"=20-f=20password.txt=0A+=09certutil=20= -d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20ssl/root_ca.crt=20-t=20= "CT,C,C"=20-f=20password.txt=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20"CT,C,C"=20-f=20= password.txt=0A+=09openssl=20pkcs12=20-export=20-out=20= ssl/nss/server-password.pfx=20-inkey=20ssl/server-password.key=20-in=20= ssl/server-cn-only.crt=20-certfile=20ssl/server_ca.crt=20-passin=20= 'pass:secret1'=20-passout=20'pass:secret1'=0A+=09pk12util=20-i=20= ssl/nss/server-password.pfx=20-d=20$@=20-W=20'secret1'=20-K=20'secret1'=0A= +=0A+ssl/nss/server-cn-only.crt__server-cn-only.key.db:=20= ssl/server-cn-only.crt=20ssl/server-cn-only.key=0A+=09$(MKDIR_P)=20$@=0A= +=09certutil=20-d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20ssl/server-cn-only.crt=20-i=20= ssl/server-cn-only.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20= -A=20-n=20server_ca.crt=20-i=20ssl/server_ca.crt=20-t=20"CT,C,C"=0A+=09= openssl=20pkcs12=20-export=20-out=20ssl/nss/server-cn-only.pfx=20-inkey=20= ssl/server-cn-only.key=20-in=20ssl/server-cn-only.crt=20-certfile=20= ssl/server_ca.crt=20-passout=20pass:=0A+=09pk12util=20-i=20= ssl/nss/server-cn-only.pfx=20-d=20$@=20-W=20''=0A+=0A= +ssl/nss/server-multiple-alt-names.crt__server-multiple-alt-names.key.db:=20= ssl/server-multiple-alt-names.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20= -d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20= -A=20-n=20ssl/server-multiple-alt-names.crt=20-i=20= ssl/server-multiple-alt-names.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20server_ca.crt=20-i=20ssl/server_ca.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20= ssl/root_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20= pkcs12=20-export=20-out=20ssl/nss/server-multiple-alt-names.pfx=20-inkey=20= ssl/server-multiple-alt-names.key=20-in=20= ssl/server-multiple-alt-names.crt=20-certfile=20= ssl/server-multiple-alt-names.crt=20-passout=20pass:=0A+=09pk12util=20-i=20= ssl/nss/server-multiple-alt-names.pfx=20-d=20$@=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$@=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$@=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$@=20-W=20= ''=0A+=0A=20#=20Password-protected=20version=20of=20server-cn-only.key=0A= =20ssl/server-password.key:=20ssl/server-cn-only.key=0A=20=09openssl=20= rsa=20-aes256=20-in=20$<=20-out=20$@=20-passout=20'pass:secret1'=0A@@=20= -88,6=20+208,27=20@@=20ssl/client.crt:=20ssl/client.key=20= ssl/client_ca.crt=0A=20=09openssl=20x509=20-in=20ssl/temp.crt=20-out=20= ssl/client.crt=20#=20to=20keep=20just=20the=20PEM=20cert=0A=20=09rm=20= ssl/client.csr=20ssl/temp.crt=0A=20=0A+#=20Client=20certificate,=20= signed=20by=20client=20CA=0A+ssl/nss/client.crt__client.key.db:=20= ssl/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=20= ssl/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=20ssl/client_ca.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20root+client_ca.crt=20= -i=20ssl/root+client_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20pkcs12=20= -export=20-out=20ssl/nss/client.pfx=20-inkey=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$@=20-W=20''=0A+=0A+#=20Client=20= certificate=20with=20encrypted=20key,=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$@=20-W=20'dUmmyP^#+'=20-k=20$@.pass=0A+=0A=20#=20Another=20client=20= certificate,=20signed=20by=20the=20client=20CA.=20This=20one=20is=20= revoked.=0A=20ssl/client-revoked.crt:=20ssl/client-revoked.key=20= ssl/client_ca.crt=20client.config=0A=20=09openssl=20req=20-new=20-key=20= ssl/client-revoked.key=20-out=20ssl/client-revoked.csr=20-config=20= client.config=0A@@=20-95,6=20+236,14=20@@=20ssl/client-revoked.crt:=20= ssl/client-revoked.key=20ssl/client_ca.crt=20client.config=0A=20=09= openssl=20x509=20-in=20ssl/temp.crt=20-out=20ssl/client-revoked.crt=20#=20= to=20keep=20just=20the=20PEM=20cert=0A=20=09rm=20ssl/client-revoked.csr=20= ssl/temp.crt=0A=20=0A+ssl/nss/client-revoked.crt__client-revoked.key.db:=20= ssl/client-revoked.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/client-revoked.crt=20-i=20ssl/client-revoked.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20client_ca.crt=20-i=20= ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20pkcs12=20-export=20= -out=20ssl/nss/client-revoked.pfx=20-inkey=20ssl/client-revoked.key=20= -in=20ssl/client-revoked.crt=20-certfile=20ssl/client_ca.crt=20-passout=20= pass:=0A+=09pk12util=20-i=20ssl/nss/client-revoked.pfx=20-d=20$@=20-W=20= ''=0A+=0A=20#=20Convert=20the=20key=20to=20DER,=20to=20test=20our=20= behaviour=20there=20too=0A=20ssl/client-der.key:=20ssl/client.key=0A=20=09= openssl=20rsa=20-in=20ssl/client.key=20-outform=20DER=20-out=20= ssl/client-der.key=0A@@=20-127,19=20+276,40=20@@=20= ssl/root+client_ca.crt:=20ssl/root_ca.crt=20ssl/client_ca.crt=0A=20= ssl/client+client_ca.crt:=20ssl/client.crt=20ssl/client_ca.crt=0A=20=09= cat=20$^=20>=20$@=0A=20=0A+#=20Client=20certificate,=20signed=20by=20= client=20CA=0A+ssl/nss/client+client_ca.crt__client.key.db:=20= ssl/client+client_ca.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/client+client_ca.crt=20-i=20ssl/client+client_ca.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= ssl/root+server_ca.crt=20-i=20ssl/root+server_ca.crt=20-t=20"CT,C,C"=0A+=09= openssl=20pkcs12=20-export=20-out=20ssl/nss/client.pfx=20-inkey=20= ssl/client.key=20-in=20ssl/client.crt=20-certfile=20ssl/client_ca.crt=20= -passout=20pass:=0A+=09pk12util=20-i=20ssl/nss/client.pfx=20-d=20$@=20-W=20= ''=0A+=0A=20####=20CRLs=0A=20=0A=20ssl/client.crl:=20= ssl/client-revoked.crt=0A=20=09openssl=20ca=20-config=20cas.config=20= -name=20client_ca=20-revoke=20ssl/client-revoked.crt=0A=20=09openssl=20= ca=20-config=20cas.config=20-name=20client_ca=20-gencrl=20-out=20= ssl/client.crl=0A=20=0A+ssl/nss/client.crl:=20ssl/client.crl=0A+=09= openssl=20crl=20-in=20$^=20-outform=20der=20-out=20$@=0A+=0A=20= ssl/server.crl:=20ssl/server-revoked.crt=0A=20=09openssl=20ca=20-config=20= cas.config=20-name=20server_ca=20-revoke=20ssl/server-revoked.crt=0A=20=09= openssl=20ca=20-config=20cas.config=20-name=20server_ca=20-gencrl=20-out=20= ssl/server.crl=0A=20=0A+ssl/nss/server.crl:=20ssl/server.crl=0A+=09= openssl=20crl=20-in=20$^=20-outform=20der=20-out=20$@=0A+=0A=20= ssl/root.crl:=20ssl/root_ca.crt=0A=20=09openssl=20ca=20-config=20= cas.config=20-name=20root_ca=20-gencrl=20-out=20ssl/root.crl=0A=20=0A= +ssl/nss/root.crl:=20ssl/root.crl=0A+=09openssl=20crl=20-in=20$^=20= -outform=20der=20-out=20$@=0A+=0A+ssl/nss/root+client.crl:=20= ssl/root+client.crl=0A+=09openssl=20crl=20-in=20$^=20-outform=20der=20= -out=20$@=0A+=0A=20#=20If=20a=20CRL=20is=20used,=20OpenSSL=20requires=20= a=20CRL=20file=20for=20*all*=20the=20CAs=20in=20the=0A=20#=20chain,=20= even=20if=20some=20of=20them=20are=20empty.=0A=20ssl/root+server.crl:=20= ssl/root.crl=20ssl/server.crl=0A@@=20-151,9=20+321,14=20@@=20= ssl/root+client.crl:=20ssl/root.crl=20ssl/client.crl=0A=20= sslfiles-clean:=0A=20=09rm=20-f=20$(SSLFILES)=20ssl/client_ca.srl=20= ssl/server_ca.srl=20ssl/client_ca-certindex*=20ssl/server_ca-certindex*=20= ssl/root_ca-certindex*=20ssl/root_ca.srl=20ssl/temp_ca.crt=20= ssl/temp_ca_signed.crt=0A=20=0A+.PHONY:=20nssfiles-clean=0A= +nssfiles-clean:=0A+=09rm=20-rf=20ssl/nss=0A+=0A=20clean=20distclean=20= maintainer-clean:=0A=20=09rm=20-rf=20tmp_check=0A=20=09rm=20-rf=20= ssl/*.old=20ssl/new_certs_dir=20ssl/client*_tmp.key=0A+=09rm=20-rf=20= ssl/nss=0A=20=0A=20#=20Doesn't=20depend=20on=20$(SSLFILES)=20because=20= we=20don't=20rebuild=20them=20by=20default=0A=20check:=0Adiff=20--git=20= a/src/test/ssl/t/001_ssltests.pl=20b/src/test/ssl/t/001_ssltests.pl=0A= index=20fd2727b568..b4d4483fb0=20100644=0A---=20= a/src/test/ssl/t/001_ssltests.pl=0A+++=20= b/src/test/ssl/t/001_ssltests.pl=0A@@=20-4,17=20+4,24=20@@=20use=20= PostgresNode;=0A=20use=20TestLib;=0A=20use=20Test::More;=0A=20=0A-use=20= File::Copy;=0A-=0A=20use=20FindBin;=0A=20use=20lib=20$FindBin::RealBin;=0A= =20=0A-use=20SSLServer;=0A+use=20SSL::Server;=0A+=0A+my=20$openssl;=0A= +my=20$nss;=0A=20=0A-if=20($ENV{with_openssl}=20eq=20'yes')=0A+if=20= ($ENV{with_ssl}=20eq=20'openssl')=0A=20{=0A+=09$openssl=20=3D=201;=0A=20=09= plan=20tests=20=3D>=2093;=0A=20}=0A+elsif=20($ENV{with_ssl}=20eq=20= 'nss')=0A+{=0A+=09$nss=20=3D=201;=0A+=09plan=20tests=20=3D>=2098;=0A+}=0A= =20else=0A=20{=0A=20=09plan=20skip_all=20=3D>=20'SSL=20not=20supported=20= by=20this=20build';=0A@@=20-32,32=20+39,6=20@@=20my=20$SERVERHOSTCIDR=20= =3D=20'127.0.0.1/32';=0A=20#=20Allocation=20of=20base=20connection=20= string=20shared=20among=20multiple=20tests.=0A=20my=20$common_connstr;=0A= =20=0A-#=20The=20client's=20private=20key=20must=20not=20be=20= world-readable,=20so=20take=20a=20copy=0A-#=20of=20the=20key=20stored=20= in=20the=20code=20tree=20and=20update=20its=20permissions.=0A-#=0A-#=20= This=20changes=20ssl/client.key=20to=20ssl/client_tmp.key=20etc=20for=20= the=20rest=0A-#=20of=20the=20tests.=0A-my=20@keys=20=3D=20(=0A-=09= "client",=20=20=20=20=20"client-revoked",=0A-=09"client-der",=20= "client-encrypted-pem",=0A-=09"client-encrypted-der");=0A-foreach=20my=20= $key=20(@keys)=0A-{=0A-=09copy("ssl/${key}.key",=20"ssl/${key}_tmp.key")=0A= -=09=20=20or=20die=0A-=09=20=20"couldn't=20copy=20ssl/${key}.key=20to=20= ssl/${key}_tmp.key=20for=20permissions=20change:=20$!";=0A-=09chmod=20= 0600,=20"ssl/${key}_tmp.key"=0A-=09=20=20or=20die=20"failed=20to=20= change=20permissions=20on=20ssl/${key}_tmp.key:=20$!";=0A-}=0A-=0A-#=20= Also=20make=20a=20copy=20of=20that=20explicitly=20world-readable.=20=20= We=20can't=0A-#=20necessarily=20rely=20on=20the=20file=20in=20the=20= source=20tree=20having=20those=0A-#=20permissions.=20=20Add=20it=20to=20= @keys=20to=20include=20it=20in=20the=20final=20clean=0A-#=20up=20phase.=0A= -copy("ssl/client.key",=20"ssl/client_wrongperms_tmp.key");=0A-chmod=20= 0644,=20"ssl/client_wrongperms_tmp.key";=0A-push=20@keys,=20= 'client_wrongperms';=0A-=0A=20####=20Set=20up=20the=20server.=0A=20=0A=20= note=20"setting=20up=20data=20directory";=0A@@=20-72,36=20+53,65=20@@=20= $node->start;=0A=20=0A=20#=20Run=20this=20before=20we=20lock=20down=20= access=20below.=0A=20my=20$result=20=3D=20$node->safe_psql('postgres',=20= "SHOW=20ssl_library");=0A-is($result,=20'OpenSSL',=20'ssl_library=20= parameter');=0A+is($result,=20SSL::Server::ssl_library(),=20'ssl_library=20= parameter');=0A=20=0A=20configure_test_server_for_ssl($node,=20= $SERVERHOSTADDR,=20$SERVERHOSTCIDR,=0A=20=09'trust');=0A=20=0A=20note=20= "testing=20password-protected=20keys";=0A=20=0A-open=20my=20$sslconf,=20= '>',=20$node->data_dir=20.=20"/sslconfig.conf";=0A-print=20$sslconf=20= "ssl=3Don\n";=0A-print=20$sslconf=20= "ssl_cert_file=3D'server-cn-only.crt'\n";=0A-print=20$sslconf=20= "ssl_key_file=3D'server-password.key'\n";=0A-print=20$sslconf=20= "ssl_passphrase_command=3D'echo=20wrongpassword'\n";=0A-close=20= $sslconf;=0A+#=20Since=20the=20passphrase=20callbacks=20operate=20at=20= different=20stages=20in=20OpenSSL=20and=0A+#=20NSS=20we=20have=20two=20= separate=20blocks=20for=20them.=0A+SKIP:=0A+{=0A+=09skip=20"Certificate=20= passphrases=20aren't=20checked=20on=20server=20restart=20in=20NSS",=202=0A= +=09=20=20if=20($nss);=0A+=0A+=09set_server_cert($node,=20= 'server-cn-only',=20'root+client_ca',=0A+=09=09=09=09=09=20=20=20= 'server-password',=20'echo=20wrongpassword');=0A+=09command_fails(=0A+=09= =09[=20'pg_ctl',=20'-D',=20$node->data_dir,=20'-l',=20$node->logfile,=20= 'restart'=20],=0A+=09=09'restart=20fails=20with=20password-protected=20= key=20file=20with=20wrong=20password');=0A+=09$node->_update_pid(0);=0A+=0A= +=09set_server_cert($node,=20'server-cn-only',=20'root+client_ca',=0A+=09= =09=09=09=09'server-password',=20'echo=20secret1');=0A+=09command_ok(=0A= +=09=09[=20'pg_ctl',=20'-D',=20$node->data_dir,=20'-l',=20= $node->logfile,=20'restart'=20],=0A+=09=09'restart=20succeeds=20with=20= password-protected=20key=20file');=0A+=09$node->_update_pid(1);=0A+}=0A=20= =0A-command_fails(=0A-=09[=20'pg_ctl',=20'-D',=20$node->data_dir,=20= '-l',=20$node->logfile,=20'restart'=20],=0A-=09'restart=20fails=20with=20= password-protected=20key=20file=20with=20wrong=20password');=0A= -$node->_update_pid(0);=0A+SKIP:=0A+{=0A+=09skip=20"Certificate=20= passphrases=20are=20checked=20on=20connection=20in=20NSS",=205=0A+=09=20=20= if=20($openssl);=0A=20=0A-open=20$sslconf,=20'>',=20$node->data_dir=20.=20= "/sslconfig.conf";=0A-print=20$sslconf=20"ssl=3Don\n";=0A-print=20= $sslconf=20"ssl_cert_file=3D'server-cn-only.crt'\n";=0A-print=20$sslconf=20= "ssl_key_file=3D'server-password.key'\n";=0A-print=20$sslconf=20= "ssl_passphrase_command=3D'echo=20secret1'\n";=0A-close=20$sslconf;=0A+=09= set_server_cert($node,=20'server-cn-only',=20'root+client_ca',=0A+=09=09=09= =09=09=20=20=20'server-password',=20'echo=20wrongpassword');=0A+=09= command_ok(=0A+=09=09[=20'pg_ctl',=20'-D',=20$node->data_dir,=20'-l',=20= $node->logfile,=20'restart'=20],=0A+=09=09'restart=20fails=20with=20= password-protected=20key=20file=20with=20wrong=20password');=0A+=09= $node->_update_pid(1);=0A=20=0A-command_ok(=0A-=09[=20'pg_ctl',=20'-D',=20= $node->data_dir,=20'-l',=20$node->logfile,=20'restart'=20],=0A-=09= 'restart=20succeeds=20with=20password-protected=20key=20file');=0A= -$node->_update_pid(1);=0A+=09test_connect_fails(=0A+=09=09= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= hostaddr=3D$SERVERHOSTADDR=20host=3Dcommon-name.pg-ssltest.test",=0A+=09=09= "sslrootcert=3Dinvalid=20sslmode=3Drequire",=0A+=09=09qr/\QSSL=20= error\E/,=0A+=09=09"connect=20to=20server=20with=20incorrect=20key=20= password=20configured");=0A+=0A+=09set_server_cert($node,=20= 'server-cn-only',=20'root+client_ca',=0A+=09=09=09=09=09=20=20=20= 'server-password',=20'echo=20secret1');=0A+=09command_ok(=0A+=09=09[=20= 'pg_ctl',=20'-D',=20$node->data_dir,=20'-l',=20$node->logfile,=20= 'restart'=20],=0A+=09=09'restart=20fails=20with=20password-protected=20= key=20file=20with=20wrong=20password');=0A+=09$node->_update_pid(1);=0A+=0A= +=09test_connect_ok(=0A+=09=09"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20hostaddr=3D$SERVERHOSTADDR=20= host=3Dcommon-name.pg-ssltest.test",=0A+=09=09"sslrootcert=3Dinvalid=20= sslmode=3Drequire",=0A+=09=09"connect=20to=20server=20with=20correct=20= key=20password=20configured");=0A+}=0A=20=0A=20#=20Test=20compatibility=20= of=20SSL=20protocols.=0A=20#=20TLSv1.1=20is=20lower=20than=20TLSv1.2,=20= so=20it=20won't=20work.=0A@@=20-149,82=20+159,105=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "sslrootcert=3Dinvalid=20sslmode=3Dverify-ca",=0A-=09qr/root=20= certificate=20file=20"invalid"=20does=20not=20exist/,=0A+=09qr/root=20= certificate=20file=20"invalid"=20does=20not=20exist|could=20not=20= connect=20to=20server/,=0A=20=09"connect=20without=20server=20root=20= cert=20sslmode=3Dverify-ca");=0A=20test_connect_fails(=0A=20=09= $common_connstr,=0A=20=09"sslrootcert=3Dinvalid=20sslmode=3Dverify-full",=0A= -=09qr/root=20certificate=20file=20"invalid"=20does=20not=20exist/,=0A+=09= qr/root=20certificate=20file=20"invalid"=20does=20not=20exist|could=20= not=20connect=20to=20server/,=0A=20=09"connect=20without=20server=20root=20= cert=20sslmode=3Dverify-full");=0A=20=0A=20#=20Try=20with=20wrong=20root=20= cert,=20should=20fail.=20(We're=20using=20the=20client=20CA=20as=20the=0A= =20#=20root,=20but=20the=20server's=20key=20is=20signed=20by=20the=20= server=20CA.)=0A-test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Drequire",=0A-=09qr/SSL=20= error/,=20"connect=20with=20wrong=20server=20root=20cert=20= sslmode=3Drequire");=0A-test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-ca",=0A-=09qr/SSL=20= error/,=20"connect=20with=20wrong=20server=20root=20cert=20= sslmode=3Dverify-ca");=0A-test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-full",=0A-=09qr/SSL=20= error/,=20"connect=20with=20wrong=20server=20root=20cert=20= sslmode=3Dverify-full");=0A-=0A-#=20Try=20with=20just=20the=20server=20= CA's=20cert.=20This=20fails=20because=20the=20root=20file=0A-#=20must=20= contain=20the=20whole=20chain=20up=20to=20the=20root=20CA.=0A= -test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/server_ca.crt=20sslmode=3Dverify-ca",=0A-=09qr/SSL=20= error/,=20"connect=20with=20server=20CA=20cert,=20without=20root=20CA");=0A= +test_connect_fails(=0A+=09$common_connstr,=0A+=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Drequire=20= cert_database=3Dssl/nss/client_ca.crt.db",=0A+=09qr/SSL=20error/,=0A+=09= "connect=20with=20wrong=20server=20root=20cert=20sslmode=3Drequire");=0A= +test_connect_fails(=0A+=09$common_connstr,=0A+=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-ca=20= cert_database=3Dssl/nss/client_ca.crt.db",=0A+=09qr/SSL=20error/,=0A+=09= "connect=20with=20wrong=20server=20root=20cert=20sslmode=3Dverify-ca");=0A= +test_connect_fails(=0A+=09$common_connstr,=0A+=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-full=20= cert_database=3Dssl/nss/client_ca.crt.db",=0A+=09qr/SSL=20error/,=0A+=09= "connect=20with=20wrong=20server=20root=20cert=20sslmode=3Dverify-full");=0A= +=0A+SKIP:=0A+{=0A+=09#=20NSS=20supports=20partial=20chain=20validation,=20= so=20this=20test=20doesnt=20work=20there.=0A+=09#=20This=20is=20similar=20= to=20the=20OpenSSL=20option=20X509_V_FLAG_PARTIAL_CHAIN=20which=0A+=09#=20= we=20don't=20allow.=0A+=09skip=20"NSS=20support=20partial=20chain=20= validation",=202=20if=20($nss);=0A+=09#=20Try=20with=20just=20the=20= server=20CA's=20cert.=20This=20fails=20because=20the=20root=20file=0A+=09= #=20must=20contain=20the=20whole=20chain=20up=20to=20the=20root=20CA.=0A= +=09test_connect_fails($common_connstr,=0A+=09=09= "sslrootcert=3Dssl/server_ca.crt=20sslmode=3Dverify-ca",=0A+=09=09qr/SSL=20= error/,=20"connect=20with=20server=20CA=20cert,=20without=20root=20CA");=0A= +}=0A=20=0A=20#=20And=20finally,=20with=20the=20correct=20root=20cert.=0A= =20test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connect=20with=20= correct=20server=20CA=20cert=20file=20sslmode=3Drequire");=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connect=20with=20= correct=20server=20CA=20cert=20file=20sslmode=3Dverify-ca");=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-full",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-full=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connect=20with=20= correct=20server=20CA=20cert=20file=20sslmode=3Dverify-full");=0A=20=0A= -#=20Test=20with=20cert=20root=20file=20that=20contains=20two=20= certificates.=20The=20client=20should=0A-#=20be=20able=20to=20pick=20the=20= right=20one,=20regardless=20of=20the=20order=20in=20the=20file.=0A= -test_connect_ok(=0A-=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/both-cas-1.crt=20sslmode=3Dverify-ca",=0A-=09"cert=20= root=20file=20that=20contains=20two=20certificates,=20order=201");=0A= -test_connect_ok(=0A-=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/both-cas-2.crt=20sslmode=3Dverify-ca",=0A-=09"cert=20= root=20file=20that=20contains=20two=20certificates,=20order=202");=0A= +SKIP:=0A+{=0A+=09skip=20"CA=20ordering=20is=20irrelevant=20in=20NSS=20= databases",=202=20if=20($nss);=0A=20=0A+=09#=20Test=20with=20cert=20root=20= file=20that=20contains=20two=20certificates.=20The=20client=20should=0A+=09= #=20be=20able=20to=20pick=20the=20right=20one,=20regardless=20of=20the=20= order=20in=20the=20file.=0A+=09test_connect_ok(=0A+=09=09= $common_connstr,=0A+=09=09"sslrootcert=3Dssl/both-cas-1.crt=20= sslmode=3Dverify-ca",=0A+=09=09"cert=20root=20file=20that=20contains=20= two=20certificates,=20order=201");=0A+=0A+=09#=20How=20about=20import=20= the=20both-file=20into=20a=20database?=0A+=09test_connect_ok(=0A+=09=09= $common_connstr,=0A+=09=09"sslrootcert=3Dssl/both-cas-2.crt=20= sslmode=3Dverify-ca",=0A+=09=09"cert=20root=20file=20that=20contains=20= two=20certificates,=20order=202");=0A+}=0A=20#=20CRL=20tests=0A=20=0A=20= #=20Invalid=20CRL=20filename=20is=20the=20same=20as=20no=20CRL,=20= succeeds=0A=20test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dinvalid",=0A+=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dinvalid=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"sslcrl=20option=20= with=20invalid=20file=20name");=0A=20=0A-#=20A=20CRL=20belonging=20to=20= a=20different=20CA=20is=20not=20accepted,=20fails=0A-test_connect_fails(=0A= -=09$common_connstr,=0A-=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dssl/client.crl",=0A-=09qr/SSL=20error/,=0A= -=09"CRL=20belonging=20to=20a=20different=20CA");=0A+SKIP:=0A+{=0A+=09= skip=20"CRL's=20are=20verified=20when=20adding=20to=20NSS=20database",=20= 2=20if=20($nss);=0A+=09#=20A=20CRL=20belonging=20to=20a=20different=20CA=20= is=20not=20accepted,=20fails=0A+=09test_connect_fails(=0A+=09=09= $common_connstr,=0A+=09=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dssl/client.crl",=0A+=09=09qr/SSL=20= error/,=0A+=09=09"CRL=20belonging=20to=20a=20different=20CA");=0A+}=0A=20= =0A=20#=20With=20the=20correct=20CRL,=20succeeds=20(this=20cert=20is=20= not=20revoked)=0A=20test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dssl/root+server.crl",=0A+=09"sslrootcert=3Dssl/root+server_ca.crt= =20sslmode=3Dverify-ca=20sslcrl=3Dssl/root+server.crl=20= cert_database=3Dssl/nss/root+server_ca.crt__root+server.crl.db",=0A=20=09= "CRL=20with=20a=20non-revoked=20cert");=0A=20=0A=20#=20Check=20that=20= connecting=20with=20verify-full=20fails,=20when=20the=20hostname=20= doesn't=0A=20#=20match=20the=20hostname=20in=20the=20server's=20= certificate.=0A=20$common_connstr=20=3D=0A-=20=20"user=3Dssltestuser=20= dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR";=0A+=20= =20"user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-237,14=20+270,14=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "sslmode=3Dverify-full=20host=3Dwronghost.test",=0A-=09qr/\Qserver=20= certificate=20for=20"common-name.pg-ssltest.test"=20does=20not=20match=20= host=20name=20"wronghost.test"\E/,=0A+=09qr/\Qserver=20certificate=20for=20= "common-name.pg-ssltest.test"=20does=20not=20match=20host=20name=20= "wronghost.test"\E|SSL_ERROR_BAD_CERT_DOMAIN/,=0A=20=09"mismatch=20= between=20host=20name=20and=20server=20certificate=20= sslmode=3Dverify-full");=0A=20=0A=20#=20Test=20Subject=20Alternative=20= Names.=0A=20switch_server_cert($node,=20'server-multiple-alt-names');=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= cert_database=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-262,12=20+295,12=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "host=3Dwronghost.alt-name.pg-ssltest.test",=0A-=09qr/\Qserver=20= certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20= names)=20does=20not=20match=20host=20name=20= "wronghost.alt-name.pg-ssltest.test"\E/,=0A+=09qr/\Qserver=20certificate=20= for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20names)=20does=20= not=20match=20host=20name=20= "wronghost.alt-name.pg-ssltest.test"\E|SSL_ERROR_BAD_CERT_DOMAIN/,=0A=20=09= "host=20name=20not=20matching=20with=20X.509=20Subject=20Alternative=20= Names");=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "host=3Ddeep.subdomain.wildcard.pg-ssltest.test",=0A-=09qr/\Qserver=20= certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20= names)=20does=20not=20match=20host=20name=20= "deep.subdomain.wildcard.pg-ssltest.test"\E/,=0A+=09qr/\Qserver=20= certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20= names)=20does=20not=20match=20host=20name=20= "deep.subdomain.wildcard.pg-ssltest.test"\E|SSL_ERROR_BAD_CERT_DOMAIN/,=0A= =20=09"host=20name=20not=20matching=20with=20X.509=20Subject=20= Alternative=20Names=20wildcard");=0A=20=0A=20#=20Test=20certificate=20= with=20a=20single=20Subject=20Alternative=20Name.=20(this=20gives=20a=0A= @@=20-275,7=20+308,7=20@@=20test_connect_fails(=0A=20= switch_server_cert($node,=20'server-single-alt-name');=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=20cert_database=3Dssl/nss/root+server_ca.crt.db";=0A= =20=0A=20test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-285,12=20= +318,12=20@@=20test_connect_ok(=0A=20test_connect_fails(=0A=20=09= $common_connstr,=0A=20=09"host=3Dwronghost.alt-name.pg-ssltest.test",=0A= -=09qr/\Qserver=20certificate=20for=20"single.alt-name.pg-ssltest.test"=20= does=20not=20match=20host=20name=20= "wronghost.alt-name.pg-ssltest.test"\E/,=0A+=09qr/\Qserver=20certificate=20= for=20"single.alt-name.pg-ssltest.test"=20does=20not=20match=20host=20= name=20= "wronghost.alt-name.pg-ssltest.test"\E|SSL_ERROR_BAD_CERT_DOMAIN/,=0A=20=09= "host=20name=20not=20matching=20with=20a=20single=20X.509=20Subject=20= Alternative=20Name");=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A= =20=09"host=3Ddeep.subdomain.wildcard.pg-ssltest.test",=0A-=09= qr/\Qserver=20certificate=20for=20"single.alt-name.pg-ssltest.test"=20= does=20not=20match=20host=20name=20= "deep.subdomain.wildcard.pg-ssltest.test"\E/,=0A+=09qr/\Qserver=20= certificate=20for=20"single.alt-name.pg-ssltest.test"=20does=20not=20= match=20host=20name=20= "deep.subdomain.wildcard.pg-ssltest.test"\E|SSL_ERROR_BAD_CERT_DOMAIN/,=0A= =20=09"host=20name=20not=20matching=20with=20a=20single=20X.509=20= Subject=20Alternative=20Name=20wildcard"=0A=20);=0A=20=0A@@=20-299,7=20= +332,7=20@@=20test_connect_fails(=0A=20switch_server_cert($node,=20= 'server-cn-and-alt-names');=0A=20=0A=20$common_connstr=20=3D=0A-=20=20= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= sslmode=3Dverify-full";=0A+=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR=20sslmode=3Dverify-full=20= cert_database=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-312,14=20+345,14=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "host=3Dcommon-name.pg-ssltest.test",=0A-=09qr/\Qserver=20certificate=20= for=20"dns1.alt-name.pg-ssltest.test"=20(and=201=20other=20name)=20does=20= not=20match=20host=20name=20"common-name.pg-ssltest.test"\E/,=0A+=09= qr/\Qserver=20certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=20= 1=20other=20name)=20does=20not=20match=20host=20name=20= "common-name.pg-ssltest.test"\E|SSL_ERROR_BAD_CERT_DOMAIN/,=0A=20=09= "certificate=20with=20both=20a=20CN=20and=20SANs=20ignores=20CN");=0A=20=0A= =20#=20Finally,=20test=20a=20server=20certificate=20that=20has=20no=20CN=20= or=20SANs.=20Of=20course,=20that's=0A=20#=20not=20a=20very=20sensible=20= certificate,=20but=20libpq=20should=20handle=20it=20gracefully.=0A=20= switch_server_cert($node,=20'server-no-names');=0A=20$common_connstr=20=3D= =0A-=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR";=0A+=20= =20"user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-328,7=20+361,7=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "sslmode=3Dverify-full=20host=3Dcommon-name.pg-ssltest.test",=0A-=09= qr/could=20not=20get=20server's=20host=20name=20from=20server=20= certificate/,=0A+=09qr/could=20not=20get=20server's=20host=20name=20from=20= server=20certificate|SSL_ERROR_BAD_CERT_DOMAIN/,=0A=20=09"server=20= certificate=20without=20CN=20or=20SANs=20sslmode=3Dverify-full");=0A=20=0A= =20#=20Test=20that=20the=20CRL=20works=0A@@=20-340,11=20+373,11=20@@=20= $common_connstr=20=3D=0A=20#=20Without=20the=20CRL,=20succeeds.=20With=20= it,=20fails.=0A=20test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connects=20= without=20client-side=20CRL");=0A=20test_connect_fails(=0A=20=09= $common_connstr,=0A-=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dssl/root+server.crl",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dssl/server.crl=20= cert_database=3Dssl/nss/root+server_ca.crt__server.crl.db",=0A=20=09= qr/SSL=20error/,=0A=20=09"does=20not=20connect=20with=20client-side=20= CRL");=0A=20=0A@@=20-365,21=20+398,21=20@@=20command_like(=0A=20#=20Test=20= min/max=20SSL=20protocol=20versions.=0A=20test_connect_ok(=0A=20=09= $common_connstr,=0A-=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Drequire=20ssl_min_protocol_version=3DTLSv1.2=20= ssl_max_protocol_version=3DTLSv1.2",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3DTLSv1.2=20ssl_max_protocol_version=3DTLSv1.2=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connection=20= success=20with=20correct=20range=20of=20TLS=20protocol=20versions");=0A=20= test_connect_fails(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3DTLSv1.2=20ssl_max_protocol_version=3DTLSv1.1",=0A= +=09"sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3DTLSv1.2=20ssl_max_protocol_version=3DTLSv1.1=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09qr/invalid=20SSL=20= protocol=20version=20range/,=0A=20=09"connection=20failure=20with=20= incorrect=20range=20of=20TLS=20protocol=20versions");=0A=20= test_connect_fails(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3Dincorrect_tls",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3Dincorrect_tls=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09qr/invalid=20= ssl_min_protocol_version=20value/,=0A=20=09"connection=20failure=20with=20= an=20incorrect=20SSL=20protocol=20minimum=20bound");=0A=20= test_connect_fails(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_max_protocol_version=3Dincorrect_tls",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_max_protocol_version=3Dincorrect_tls=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09qr/invalid=20= ssl_max_protocol_version=20value/,=0A=20=09"connection=20failure=20with=20= an=20incorrect=20SSL=20protocol=20maximum=20bound");=0A=20=0A@@=20-390,7=20= +423,7=20@@=20test_connect_fails(=0A=20note=20"running=20server=20= tests";=0A=20=0A=20$common_connstr=20=3D=0A-=20=20= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= dbname=3Dcertdb=20hostaddr=3D$SERVERHOSTADDR";=0A+=20=20= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= dbname=3Dcertdb=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/client.crt__client.key.db";=0A=20=0A=20#=20no=20= client=20cert=0A=20test_connect_fails(=0A@@=20-406,32=20+439,43=20@@=20= test_connect_ok(=0A=20=09"certificate=20authorization=20succeeds=20with=20= correct=20client=20cert=20in=20PEM=20format"=0A=20);=0A=20=0A-#=20= correct=20client=20cert=20in=20unencrypted=20DER=0A-test_connect_ok(=0A-=09= $common_connstr,=0A-=09"user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-der_tmp.key",=0A-=09"certificate=20authorization=20= succeeds=20with=20correct=20client=20cert=20in=20DER=20format"=0A-);=0A= +$common_connstr=20=3D=0A+=20=20"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Drequire=20dbname=3Dcertdb=20hostaddr=3D$SERVERHOSTADDR";=0A+=0A= +SKIP:=0A+{=0A+=09skip=20"NSS=20database=20not=20implemented=20in=20the=20= Makefile",=201=20if=20($nss);=0A+=09#=20correct=20client=20cert=20in=20= unencrypted=20DER=0A+=09test_connect_ok(=0A+=09=09$common_connstr,=0A+=09= =09"user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-der_tmp.key",=0A+=09=09"certificate=20authorization=20= succeeds=20with=20correct=20client=20cert=20in=20DER=20format"=0A+=09);=0A= +}=0A=20=0A=20#=20correct=20client=20cert=20in=20encrypted=20PEM=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A-=09"user=3Dssltestuser=20= sslcert=3Dssl/client.crt=20sslkey=3Dssl/client-encrypted-pem_tmp.key=20= sslpassword=3D'dUmmyP^#+'",=0A+=09"user=3Dssltestuser=20= sslcert=3Dssl/client.crt=20sslkey=3Dssl/client-encrypted-pem_tmp.key=20= sslpassword=3D'dUmmyP^#+'=20= cert_database=3Dssl/nss/client.crt__client-encrypted-pem.key.db",=0A=20=09= "certificate=20authorization=20succeeds=20with=20correct=20client=20cert=20= in=20encrypted=20PEM=20format"=0A=20);=0A=20=0A-#=20correct=20client=20= cert=20in=20encrypted=20DER=0A-test_connect_ok(=0A-=09$common_connstr,=0A= -=09"user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-encrypted-der_tmp.key=20sslpassword=3D'dUmmyP^#+'",=0A= -=09"certificate=20authorization=20succeeds=20with=20correct=20client=20= cert=20in=20encrypted=20DER=20format"=0A-);=0A+SKIP:=0A+{=0A+=09skip=20= "NSS=20database=20not=20implemented=20in=20the=20Makefile",=201=20if=20= ($nss);=0A+=09#=20correct=20client=20cert=20in=20encrypted=20DER=0A+=09= test_connect_ok(=0A+=09=09$common_connstr,=0A+=09=09"user=3Dssltestuser=20= sslcert=3Dssl/client.crt=20sslkey=3Dssl/client-encrypted-der_tmp.key=20= sslpassword=3D'dUmmyP^#+'",=0A+=09=09"certificate=20authorization=20= succeeds=20with=20correct=20client=20cert=20in=20encrypted=20DER=20= format"=0A+=09);=0A+}=0A=20=0A=20#=20correct=20client=20cert=20in=20= encrypted=20PEM=20with=20wrong=20password=0A=20test_connect_fails(=0A=20=09= $common_connstr,=0A-=09"user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-encrypted-pem_tmp.key=20sslpassword=3D'wrong'",=0A-=09= qr!\Qprivate=20key=20file=20"ssl/client-encrypted-pem_tmp.key":=20bad=20= decrypt\E!,=0A+=09"user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client-encrypted-pem_tmp.key=20sslpassword=3D'wrong'=20= cert_database=3Dssl/nss/client.crt__client-encrypted-pem.key.db",=0A+=09= qr!connection=20requires=20a=20valid=20client=20certificate|\Qprivate=20= key=20file=20"ssl/client-encrypted-pem_tmp.key":=20bad=20decrypt\E!,=0A=20= =09"certificate=20authorization=20fails=20with=20correct=20client=20cert=20= and=20wrong=20password=20in=20encrypted=20PEM=20format"=0A=20);=0A=20=0A= @@=20-471,18=20+515,19=20@@=20command_like(=0A=20=09=09'-P',=0A=20=09=09= 'null=3D_null_',=0A=20=09=09'-d',=0A-=09=09"$common_connstr=20= user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client_tmp.key",=0A+=09=09"$common_connstr=20= user=3Dssltestuser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client_tmp.key=20= cert_database=3Dssl/nss/client.crt__client.key.db",=0A=20=09=09'-c',=0A=20= =09=09"SELECT=20*=20FROM=20pg_stat_ssl=20WHERE=20pid=20=3D=20= pg_backend_pid()"=0A=20=09],=0A=20=09= qr{^pid,ssl,version,cipher,bits,compression,client_dn,client_serial,issuer= _dn\r?\n=0A-=09=09=09=09= ^\d+,t,TLSv[\d.]+,[\w-]+,\d+,f,/CN=3Dssltestuser,1,\Q/CN=3DTest=20CA=20= for=20PostgreSQL=20SSL=20regression=20test=20client=20certs\E\r?$}mx,=0A= +=09=09=09=09= ^\d+,t,TLSv[\d.]+,[\w-]+,\d+,f,/?CN=3Dssltestuser,1,/?\QCN=3DTest=20CA=20= for=20PostgreSQL=20SSL=20regression=20test=20client=20certs\E\r?$}mx,=0A=20= =09'pg_stat_ssl=20with=20client=20certificate');=0A=20=0A=20#=20client=20= key=20with=20wrong=20permissions=0A=20SKIP:=0A=20{=0A=20=09skip=20= "Permissions=20check=20not=20enforced=20on=20Windows",=202=20if=20= ($windows_os);=0A+=09skip=20"Key=20not=20on=20filesystem=20with=20NSS",=20= =20=20=20=20=20=20=20=20=20=20=202=20if=20($nss);=0A=20=0A=20=09= test_connect_fails(=0A=20=09=09$common_connstr,=0A@@=20-495,10=20+540,13=20= @@=20SKIP:=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "user=3Danotheruser=20sslcert=3Dssl/client.crt=20= sslkey=3Dssl/client_tmp.key",=0A-=09qr/certificate=20authentication=20= failed=20for=20user=20"anotheruser"/,=0A+=09qr/unable=20to=20verify=20= certificate|certificate=20authentication=20failed=20for=20user=20= "anotheruser"/,=0A=20=09"certificate=20authorization=20fails=20with=20= client=20cert=20belonging=20to=20another=20user"=0A=20);=0A=20=0A= +$common_connstr=20=3D=0A+=20=20"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Drequire=20dbname=3Dcertdb=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/client-revoked.crt__client-revoked.key.db";=0A+=0A= =20#=20revoked=20client=20cert=0A=20test_connect_fails(=0A=20=09= $common_connstr,=0A@@=20-510,7=20+558,7=20@@=20test_connect_fails(=0A=20= #=20works,=20iff=20username=20matches=20Common=20Name=0A=20#=20fails,=20= iff=20username=20doesn't=20match=20Common=20Name.=0A=20$common_connstr=20= =3D=0A-=20=20"sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= dbname=3Dverifydb=20hostaddr=3D$SERVERHOSTADDR";=0A+=20=20= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= dbname=3Dverifydb=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/client.crt__client.key.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-536,17=20+584,23=20@@=20= test_connect_ok(=0A=20#=20intermediate=20client_ca.crt=20is=20provided=20= by=20client,=20and=20isn't=20in=20server's=20ssl_ca_file=0A=20= switch_server_cert($node,=20'server-cn-only',=20'root_ca');=0A=20= $common_connstr=20=3D=0A-=20=20"user=3Dssltestuser=20dbname=3Dcertdb=20= sslkey=3Dssl/client_tmp.key=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR";=0A+=20=20"user=3Dssltestuser=20= dbname=3Dcertdb=20sslkey=3Dssl/client_tmp.key=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/client+client_ca.crt__client.key.db";=0A=20=0A= -test_connect_ok(=0A+TODO:=0A+{=0A+=09local=20$TODO=20=3D=20"WIP=20= failure=20cause=20currently=20unknown";=0A+=09test_connect_ok(=0A+=09=09= $common_connstr,=0A+=09=09"sslmode=3Drequire=20= sslcert=3Dssl/client+client_ca.crt",=0A+=09=09"intermediate=20client=20= certificate=20is=20provided=20by=20client");=0A+}=0A+=0A= +test_connect_fails(=0A=20=09$common_connstr,=0A-=09"sslmode=3Drequire=20= sslcert=3Dssl/client+client_ca.crt",=0A-=09"intermediate=20client=20= certificate=20is=20provided=20by=20client");=0A= -test_connect_fails($common_connstr,=20"sslmode=3Drequire=20= sslcert=3Dssl/client.crt",=0A-=09qr/SSL=20error/,=20"intermediate=20= client=20certificate=20is=20missing");=0A+=09"sslmode=3Drequire=20= sslcert=3Dssl/client.crt",=0A+=09qr/connection=20requires=20a=20valid=20= client=20certificate|SSL=20error/,=0A+=09"intermediate=20client=20= certificate=20is=20missing");=0A=20=0A=20#=20clean=20up=0A-foreach=20my=20= $key=20(@keys)=0A-{=0A-=09unlink("ssl/${key}_tmp.key");=0A-}=0A+=0A= +SSL::Server::cleanup();=0Adiff=20--git=20a/src/test/ssl/t/002_scram.pl=20= b/src/test/ssl/t/002_scram.pl=0Aindex=2020ab0d5b0b..9c7e1ac977=20100644=0A= ---=20a/src/test/ssl/t/002_scram.pl=0A+++=20= b/src/test/ssl/t/002_scram.pl=0A@@=20-11,11=20+11,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-if=20= ($ENV{with_openssl}=20ne=20'yes')=0A+if=20($ENV{with_ssl}=20ne=20= 'openssl')=0A=20{=0A-=09plan=20skip_all=20=3D>=20'SSL=20not=20supported=20= by=20this=20build';=0A+=09plan=20skip_all=20=3D>=20'OpenSSL=20not=20= supported=20by=20this=20build';=0A=20}=0A=20=0A=20#=20This=20is=20the=20= hostname=20used=20to=20connect=20to=20the=20server.=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..837f0d9891=0A---=20/dev/null=0A+++=20= b/src/test/ssl/t/SSL/Backend/NSS.pm=0A@@=20-0,0=20+1,64=20@@=0A+package=20= SSL::Backend::NSS;=0A+=0A+use=20strict;=0A+use=20warnings;=0A+use=20= Exporter;=0A+=0A+our=20@ISA=20=20=20=20=20=20=20=3D=20qw(Exporter);=0A= +our=20@EXPORT_OK=20=3D=20qw(get_new_nss_backend);=0A+=0A+sub=20new=0A+{=0A= +=09my=20($class)=20=3D=20@_;=0A+=0A+=09my=20$self=20=3D=20{=20_library=20= =3D>=20'NSS'=20};=0A+=0A+=09bless=20$self,=20$class;=0A+=0A+=09return=20= $self;=0A+}=0A+=0A+sub=20get_new_nss_backend=0A+{=0A+=09my=20$class=20=3D=20= 'SSL::Backend::NSS';=0A+=0A+=09return=20$class->new();=0A+}=0A+=0A+sub=20= init=0A+{=0A+=09#=20Make=20sure=20the=20certificate=20databases=20are=20= in=20place?=0A+}=0A+=0A+sub=20get_library=0A+{=0A+=09my=20($self)=20=3D=20= @_;=0A+=0A+=09return=20$self->{_library};=0A+}=0A+=0A+sub=20= set_server_cert=0A+{=0A+=09my=20$self=20=20=20=20=20=3D=20$_[0];=0A+=09= my=20$certfile=20=3D=20$_[1];=0A+=09my=20$cafile=20=20=20=3D=20$_[2];=0A= +=09my=20$keyfile=20=20=3D=20$_[3];=0A+=0A+=09my=20$cert_nickname=20=3D=20= $certfile=20.=20'.crt__'=20.=20$keyfile=20.=20'.key';=0A+=09my=20= $cert_database=20=3D=20$cert_nickname=20.=20'.db';=0A+=0A+=09my=20= $sslconf=20=3D=0A+=09=20=20=20=20"ssl_ca_file=3D'$cafile.crt'\n"=0A+=09=20= =20.=20"ssl_cert_file=3D'ssl/$certfile.crt'\n"=0A+=09=20=20.=20= "ssl_crl_file=3D''\n"=0A+=09=20=20.=20= "ssl_database=3D'nss/$cert_database'\n";=0A+=0A+=09return=20$sslconf;=0A= +}=0A+=0A+sub=20cleanup=0A+{=0A+=09#=20Something?=0A+}=0A+=0A+1;=0Adiff=20= --git=20a/src/test/ssl/t/SSL/Backend/OpenSSL.pm=20= b/src/test/ssl/t/SSL/Backend/OpenSSL.pm=0Anew=20file=20mode=20100644=0A= index=200000000000..62b11b7632=0A---=20/dev/null=0A+++=20= b/src/test/ssl/t/SSL/Backend/OpenSSL.pm=0A@@=20-0,0=20+1,103=20@@=0A= +package=20SSL::Backend::OpenSSL;=0A+=0A+use=20strict;=0A+use=20= warnings;=0A+use=20Exporter;=0A+use=20File::Copy;=0A+=0A+our=20@ISA=20=20= =20=20=20=20=20=3D=20qw(Exporter);=0A+our=20@EXPORT_OK=20=3D=20= qw(get_new_openssl_backend);=0A+=0A+our=20(@keys);=0A+=0A+INIT=0A+{=0A+=09= @keys=20=3D=20(=0A+=09=09"client",=20=20=20=20=20"client-revoked",=0A+=09= =09"client-der",=20"client-encrypted-pem",=0A+=09=09= "client-encrypted-der");=0A+}=0A+=0A+sub=20new=0A+{=0A+=09my=20($class)=20= =3D=20@_;=0A+=0A+=09my=20$self=20=3D=20{=20_library=20=3D>=20'OpenSSL'=20= };=0A+=0A+=09bless=20$self,=20$class;=0A+=0A+=09return=20$self;=0A+}=0A+=0A= +sub=20get_new_openssl_backend=0A+{=0A+=09my=20$class=20=3D=20= 'SSL::Backend::OpenSSL';=0A+=0A+=09my=20$backend=20=3D=20$class->new();=0A= +=0A+=09return=20$backend;=0A+}=0A+=0A+sub=20init=0A+{=0A+=09#=20The=20= client's=20private=20key=20must=20not=20be=20world-readable,=20so=20take=20= a=20copy=0A+=09#=20of=20the=20key=20stored=20in=20the=20code=20tree=20= and=20update=20its=20permissions.=0A+=09#=0A+=09#=20This=20changes=20= ssl/client.key=20to=20ssl/client_tmp.key=20etc=20for=20the=20rest=0A+=09= #=20of=20the=20tests.=0A+=09foreach=20my=20$key=20(@keys)=0A+=09{=0A+=09=09= copy("ssl/${key}.key",=20"ssl/${key}_tmp.key")=0A+=09=09=20=20or=20die=0A= +=09=09=20=20"couldn't=20copy=20ssl/${key}.key=20to=20ssl/${key}_tmp.key=20= for=20permissions=20change:=20$!";=0A+=09=09chmod=200600,=20= "ssl/${key}_tmp.key"=0A+=09=09=20=20or=20die=20"failed=20to=20change=20= permissions=20on=20ssl/${key}_tmp.key:=20$!";=0A+=09}=0A+=0A+=09#=20Also=20= make=20a=20copy=20of=20that=20explicitly=20world-readable.=20=20We=20= can't=0A+=09#=20necessarily=20rely=20on=20the=20file=20in=20the=20source=20= tree=20having=20those=0A+=09#=20permissions.=20Add=20it=20to=20@keys=20= to=20include=20it=20in=20the=20final=20clean=0A+=09#=20up=20phase.=0A+=09= copy("ssl/client.key",=20"ssl/client_wrongperms_tmp.key")=0A+=09=20=20or=20= die=0A+=09=20=20"couldn't=20copy=20ssl/client.key=20to=20= ssl/client_wrongperms_tmp.key:=20$!";=0A+=09chmod=200644,=20= "ssl/client_wrongperms_tmp.key"=0A+=09=20=20or=20die=0A+=09=20=20"failed=20= to=20change=20permissions=20on=20ssl/client_wrongperms_tmp.key:=20$!";=0A= +=09push=20@keys,=20'client_wrongperms';=0A+}=0A+=0A+#=20Change=20the=20= configuration=20to=20use=20given=20server=20cert=20file,=20and=20reload=0A= +#=20the=20server=20so=20that=20the=20configuration=20takes=20effect.=0A= +sub=20set_server_cert=0A+{=0A+=09my=20$self=20=20=20=20=20=3D=20$_[0];=0A= +=09my=20$certfile=20=3D=20$_[1];=0A+=09my=20$cafile=20=20=20=3D=20$_[2]=20= ||=20"root+client_ca";=0A+=09my=20$keyfile=20=20=3D=20$_[3]=20||=20= $certfile;=0A+=0A+=09my=20$sslconf=20=3D=0A+=09=20=20=20=20= "ssl_ca_file=3D'$cafile.crt'\n"=0A+=09=20=20.=20= "ssl_cert_file=3D'$certfile.crt'\n"=0A+=09=20=20.=20= "ssl_key_file=3D'$keyfile.key'\n"=0A+=09=20=20.=20= "ssl_crl_file=3D'root+client.crl'\n";=0A+=0A+=09return=20$sslconf;=0A+}=0A= +=0A+sub=20get_library=0A+{=0A+=09my=20($self)=20=3D=20@_;=0A+=0A+=09= return=20$self->{_library};=0A+}=0A+=0A+sub=20cleanup=0A+{=0A+=09foreach=20= my=20$key=20(@keys)=0A+=09{=0A+=09=09unlink("ssl/${key}_tmp.key");=0A+=09= }=0A+}=0A+=0A+1;=0Adiff=20--git=20a/src/test/ssl/t/SSLServer.pm=20= b/src/test/ssl/t/SSL/Server.pm=0Asimilarity=20index=2078%=0Arename=20= from=20src/test/ssl/t/SSLServer.pm=0Arename=20to=20= src/test/ssl/t/SSL/Server.pm=0Aindex=20f5987a003e..ee901855b5=20100644=0A= ---=20a/src/test/ssl/t/SSLServer.pm=0A+++=20= b/src/test/ssl/t/SSL/Server.pm=0A@@=20-23,19=20+23,39=20@@=0A=20#=20= explicitly=20because=20an=20invalid=20sslcert=20or=20sslrootcert,=20= respectively,=0A=20#=20causes=20those=20to=20be=20ignored.)=0A=20=0A= -package=20SSLServer;=0A+package=20SSL::Server;=0A=20=0A=20use=20strict;=0A= =20use=20warnings;=0A=20use=20PostgresNode;=0A+use=20RecursiveCopy;=0A=20= use=20TestLib;=0A=20use=20File::Basename;=0A=20use=20File::Copy;=0A=20= use=20Test::More;=0A+use=20SSL::Backend::OpenSSL=20= qw(get_new_openssl_backend);=0A+use=20SSL::Backend::NSS=20= qw(get_new_nss_backend);=0A+=0A+our=20($openssl,=20$nss,=20$backend);=0A= +=0A+#=20The=20TLS=20backend=20which=20the=20server=20is=20using=20= should=20be=20mostly=20transparent=20for=0A+#=20the=20user,=20apart=20= from=20individual=20configuration=20settings,=20so=20keep=20the=20= backend=0A+#=20specific=20things=20abstracted=20behind=20SSL::Server.=0A= +if=20($ENV{with_ssl}=20eq=20'openssl')=0A+{=0A+=09$backend=20=3D=20= get_new_openssl_backend();=0A+=09$openssl=20=3D=201;=0A+}=0A+elsif=20= ($ENV{with_ssl}=20eq=20'nss')=0A+{=0A+=09$backend=20=3D=20= get_new_nss_backend();=0A+=09$nss=20=20=20=20=20=3D=201;=0A+}=0A=20=0A=20= use=20Exporter=20'import';=0A=20our=20@EXPORT=20=3D=20qw(=0A=20=20=20= configure_test_server_for_ssl=0A+=20=20set_server_cert=0A=20=20=20= switch_server_cert=0A=20=20=20test_connect_fails=0A=20=20=20= test_connect_ok=0A@@=20-144,12=20+164,19=20@@=20sub=20= configure_test_server_for_ssl=0A=20=09close=20$sslconf;=0A=20=0A=20=09#=20= Copy=20all=20server=20certificates=20and=20keys,=20and=20client=20root=20= cert,=20to=20the=20data=20dir=0A-=09copy_files("ssl/server-*.crt",=20= $pgdata);=0A-=09copy_files("ssl/server-*.key",=20$pgdata);=0A-=09= chmod(0600,=20glob=20"$pgdata/server-*.key")=20or=20die=20$!;=0A-=09= copy_files("ssl/root+client_ca.crt",=20$pgdata);=0A-=09= copy_files("ssl/root_ca.crt",=20=20=20=20=20=20=20=20$pgdata);=0A-=09= copy_files("ssl/root+client.crl",=20=20=20=20$pgdata);=0A+=09if=20= (defined($openssl))=0A+=09{=0A+=09=09copy_files("ssl/server-*.crt",=20= $pgdata);=0A+=09=09copy_files("ssl/server-*.key",=20$pgdata);=0A+=09=09= chmod(0600,=20glob=20"$pgdata/server-*.key")=20or=20die=20$!;=0A+=09=09= copy_files("ssl/root+client_ca.crt",=20$pgdata);=0A+=09=09= copy_files("ssl/root_ca.crt",=20=20=20=20=20=20=20=20$pgdata);=0A+=09=09= copy_files("ssl/root+client.crl",=20=20=20=20$pgdata);=0A+=09}=0A+=09= elsif=20(defined($nss))=0A+=09{=0A+=09=09= RecursiveCopy::copypath("ssl/nss",=20$pgdata=20.=20"/nss")=20if=20-e=20= "ssl/nss";=0A+=09}=0A=20=0A=20=09#=20Stop=20and=20restart=20server=20to=20= load=20new=20listen_addresses.=0A=20=09$node->restart;=0A@@=20-157,26=20= +184,51=20@@=20sub=20configure_test_server_for_ssl=0A=20=09#=20Change=20= pg_hba=20after=20restart=20because=20hostssl=20requires=20ssl=3Don=0A=20=09= configure_hba_for_ssl($node,=20$servercidr,=20$authmethod);=0A=20=0A+=09= #=20Finally,=20perform=20backend=20specific=20configuration=0A+=09= $backend->init();=0A+=0A=20=09return;=0A=20}=0A=20=0A-#=20Change=20the=20= configuration=20to=20use=20given=20server=20cert=20file,=20and=20reload=0A= -#=20the=20server=20so=20that=20the=20configuration=20takes=20effect.=0A= -sub=20switch_server_cert=0A+sub=20ssl_library=0A+{=0A+=09return=20= $backend->get_library();=0A+}=0A+=0A+sub=20cleanup=0A+{=0A+=09= $backend->cleanup();=0A+}=0A+=0A+#=20Change=20the=20configuration=20to=20= use=20given=20server=20cert=20file,=0A+sub=20set_server_cert=0A=20{=0A=20= =09my=20$node=20=20=20=20=20=3D=20$_[0];=0A=20=09my=20$certfile=20=3D=20= $_[1];=0A=20=09my=20$cafile=20=20=20=3D=20$_[2]=20||=20"root+client_ca";=0A= +=09my=20$keyfile=20=20=3D=20$_[3]=20||=20'';=0A+=09my=20$pwcmd=20=20=20=20= =3D=20$_[4]=20||=20'';=0A=20=09my=20$pgdata=20=20=20=3D=20= $node->data_dir;=0A=20=0A+=09$keyfile=20=3D=20$certfile=20if=20$keyfile=20= eq=20'';=0A+=0A=20=09open=20my=20$sslconf,=20'>',=20= "$pgdata/sslconfig.conf";=0A=20=09print=20$sslconf=20"ssl=3Don\n";=0A-=09= print=20$sslconf=20"ssl_ca_file=3D'$cafile.crt'\n";=0A-=09print=20= $sslconf=20"ssl_cert_file=3D'$certfile.crt'\n";=0A-=09print=20$sslconf=20= "ssl_key_file=3D'$certfile.key'\n";=0A-=09print=20$sslconf=20= "ssl_crl_file=3D'root+client.crl'\n";=0A+=09print=20$sslconf=20= $backend->set_server_cert($certfile,=20$cafile,=20$keyfile);=0A+=09print=20= $sslconf=20"ssl_passphrase_command=3D'$pwcmd'\n"=0A+=09=20=20unless=20= $pwcmd=20eq=20'';=0A=20=09close=20$sslconf;=0A+=09return;=0A+}=0A=20=0A= +#=20Change=20the=20configuration=20to=20use=20given=20server=20cert=20= file,=20and=20reload=0A+#=20the=20server=20so=20that=20the=20= configuration=20takes=20effect.=0A+#=20Takes=20the=20same=20arguments=20= as=20set_server_cert,=20which=20it=20calls=20to=20do=20that=0A+#=20piece=20= of=20the=20work.=0A+sub=20switch_server_cert=0A+{=0A+=09my=20$node=20=3D=20= $_[0];=0A+=09set_server_cert(@_);=0A=20=09$node->restart;=0A=20=09= return;=0A=20}=0A--=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_C39967DC-7CE2-4297-8DC3-75F0E858FBDB Content-Disposition: attachment; filename=v15-0003-NSS-pg_strong_random-support.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v15-0003-NSS-pg_strong_random-support.patch" Content-Transfer-Encoding: quoted-printable =46rom=20d9a150702d9441e043ede97445713efc5401257f=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2028=20Oct=202020=2011:24:02=20+0100=0ASubject:=20[PATCH=20= v15=203/6]=20NSS=20pg_strong_random=20support=0A=0A---=0A=20configure=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=208=20+++++++-=0A= =20configure.ac=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=205=20= ++++-=0A=20src/include/pg_config.h.in=20=20|=20=203=20+++=0A=20= src/port/pg_strong_random.c=20|=2037=20= +++++++++++++++++++++++++++++++++++++=0A=204=20files=20changed,=2051=20= insertions(+),=202=20deletions(-)=0A=0Adiff=20--git=20a/configure=20= b/configure=0Aindex=206287a0e2fe..f78772bd42=20100755=0A---=20= a/configure=0A+++=20b/configure=0A@@=20-18426,6=20+18426,12=20@@=20= $as_echo=20"#define=20USE_WIN32_RANDOM=201"=20>>confdefs.h=0A=20=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+elif=20= test=20x"$USE_NSS_RANDOM"=20=3D=20x"1"=20;=20then=0A+=0A+$as_echo=20= "#define=20USE_NSS_RANDOM=201"=20>>confdefs.h=0A+=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"$USE_DEV_URANDOM"=20=3D=20x"1"=20;=20then=0A= =20=0A=20$as_echo=20"#define=20USE_DEV_URANDOM=201"=20>>confdefs.h=0A@@=20= -18435,7=20+18441,7=20@@=20$as_echo=20"/dev/urandom"=20>&6;=20}=0A=20= else=0A=20=20=20as_fn_error=20$?=20"=0A=20no=20source=20of=20strong=20= random=20numbers=20was=20found=0A-PostgreSQL=20can=20use=20OpenSSL=20or=20= /dev/urandom=20as=20a=20source=20of=20random=20numbers."=20"$LINENO"=205=0A= +PostgreSQL=20can=20use=20OpenSSL,=20NSS,=20Windows=20native=20RNG=20or=20= /dev/urandom=20as=20a=20source=20of=20random=20numbers."=20"$LINENO"=205=0A= =20fi=0A=20=0A=20#=20If=20not=20set=20in=20template=20file,=20set=20= bytes=20to=20use=20libc=20memset()=0Adiff=20--git=20a/configure.ac=20= b/configure.ac=0Aindex=20706c9862e7..01c23356ab=20100644=0A---=20= a/configure.ac=0A+++=20b/configure.ac=0A@@=20-2215,13=20+2215,16=20@@=20= if=20test=20x"$USE_OPENSSL_RANDOM"=20=3D=20x"1"=20;=20then=0A=20elif=20= test=20x"$USE_WIN32_RANDOM"=20=3D=20x"1"=20;=20then=0A=20=20=20= AC_DEFINE(USE_WIN32_RANDOM,=201,=20[Define=20to=20use=20native=20Windows=20= API=20for=20random=20number=20generation])=0A=20=20=20= AC_MSG_RESULT([Windows=20native])=0A+elif=20test=20x"$USE_NSS_RANDOM"=20= =3D=20x"1"=20;=20then=0A+=20=20AC_DEFINE(USE_NSS_RANDOM,=201,=20[Define=20= to=20use=20NSS=20for=20random=20number=20generation])=0A+=20=20= AC_MSG_RESULT([NSS])=0A=20elif=20test=20x"$USE_DEV_URANDOM"=20=3D=20x"1"=20= ;=20then=0A=20=20=20AC_DEFINE(USE_DEV_URANDOM,=201,=20[Define=20to=20use=20= /dev/urandom=20for=20random=20number=20generation])=0A=20=20=20= AC_MSG_RESULT([/dev/urandom])=0A=20else=0A=20=20=20AC_MSG_ERROR([=0A=20= no=20source=20of=20strong=20random=20numbers=20was=20found=0A-PostgreSQL=20= can=20use=20OpenSSL=20or=20/dev/urandom=20as=20a=20source=20of=20random=20= numbers.])=0A+PostgreSQL=20can=20use=20OpenSSL,=20NSS,=20Windows=20= native=20RNG=20or=20/dev/urandom=20as=20a=20source=20of=20random=20= numbers.])=0A=20fi=0A=20=0A=20#=20If=20not=20set=20in=20template=20file,=20= set=20bytes=20to=20use=20libc=20memset()=0Adiff=20--git=20= a/src/include/pg_config.h.in=20b/src/include/pg_config.h.in=0Aindex=20= 31f808398c..73c39b449c=20100644=0A---=20a/src/include/pg_config.h.in=0A= +++=20b/src/include/pg_config.h.in=0A@@=20-896,6=20+896,9=20@@=0A=20/*=20= Define=20to=20build=20with=20NSS=20support=20(--with-nss)=20*/=0A=20= #undef=20USE_NSS=0A=20=0A+/*=20Define=20to=20use=20NSS=20for=20random=20= number=20generation=20*/=0A+#undef=20USE_NSS_RANDOM=0A+=0A=20/*=20Define=20= to=201=20to=20use=20software=20CRC-32C=20implementation=20= (slicing-by-8).=20*/=0A=20#undef=20USE_SLICING_BY_8_CRC32C=0A=20=0Adiff=20= --git=20a/src/port/pg_strong_random.c=20b/src/port/pg_strong_random.c=0A= index=2014e8382cd8..33af92a60b=20100644=0A---=20= a/src/port/pg_strong_random.c=0A+++=20b/src/port/pg_strong_random.c=0A@@=20= -30,6=20+30,20=20@@=0A=20#ifdef=20USE_WIN32_RANDOM=0A=20#include=20= =0A=20#endif=0A+#ifdef=20USE_NSS_RANDOM=0A+#define=20= pg_BITS_PER_BYTE=20BITS_PER_BYTE=0A+#undef=20BITS_PER_BYTE=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+#endif=0A=20=0A= =20#ifdef=20USE_WIN32_RANDOM=0A=20/*=0A@@=20-158,6=20+172,29=20@@=20= pg_strong_random(void=20*buf,=20size_t=20len)=0A=20=09}=0A=20=09return=20= false;=0A=20=0A+#elif=20defined(USE_NSS_RANDOM)=0A+=09NSSInitParameters=20= params;=0A+=09NSSInitContext=20*nss_context;=0A+=09SECStatus=20status;=0A= +=0A+=09memset(¶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=20=20NSS_INIT_READONLY=20|=20= NSS_INIT_NOCERTDB=20|=0A+=09=09=09=09=09=09=09=20=20NSS_INIT_NOMODDB=20|=20= NSS_INIT_FORCEOPEN=20|=0A+=09=09=09=09=09=09=09=20=20NSS_INIT_NOROOTINIT=20= |=20NSS_INIT_PK11RELOAD);=0A+=0A+=09if=20(!nss_context)=0A+=09=09return=20= false;=0A+=0A+=09status=20=3D=20PK11_GenerateRandom(buf,=20len);=0A+=09= NSS_ShutdownContext(nss_context);=0A+=0A+=09if=20(status=20=3D=3D=20= SECSuccess)=0A+=09=09return=20true;=0A+=0A+=09return=20false;=0A+=0A=20=09= /*=0A=20=09=20*=20Read=20/dev/urandom=20ourselves.=0A=20=09=20*/=0A--=20=0A= 2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_C39967DC-7CE2-4297-8DC3-75F0E858FBDB Content-Disposition: attachment; filename=v15-0004-NSS-Documentation.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v15-0004-NSS-Documentation.patch" Content-Transfer-Encoding: quoted-printable =46rom=208f5cf6930875caa48f70c3982b9d176beb2f6e86=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2028=20Oct=202020=2011:26:31=20+0100=0ASubject:=20[PATCH=20= v15=204/6]=20NSS=20Documentation=0A=0A---=0A=20= doc/src/sgml/acronyms.sgml=20=20=20=20=20|=2043=20+++++++++++++++++++=0A=20= doc/src/sgml/config.sgml=20=20=20=20=20=20=20|=2028=20++++++++++--=0A=20= doc/src/sgml/installation.sgml=20|=2030=20++++++++++++-=0A=20= doc/src/sgml/libpq.sgml=20=20=20=20=20=20=20=20|=2027=20++++++++++--=0A=20= doc/src/sgml/runtime.sgml=20=20=20=20=20=20|=2078=20= ++++++++++++++++++++++++++++++++--=0A=205=20files=20changed,=20195=20= insertions(+),=2011=20deletions(-)=0A=0Adiff=20--git=20= a/doc/src/sgml/acronyms.sgml=20b/doc/src/sgml/acronyms.sgml=0Aindex=20= 4e5ec983c0..4f6f0cf353=20100644=0A---=20a/doc/src/sgml/acronyms.sgml=0A= +++=20b/doc/src/sgml/acronyms.sgml=0A@@=20-441,6=20+441,28=20@@=0A=20=20=20= =20=20=0A=20=20=20=20=0A=20=0A+=20=20=20= =0A+=20=20=20=20NSPR=0A+=20= =20=20=20=0A+=20=20=20=20=20=0A+=20=20=20=20=20=20=0A= +=20=20=20=20=20=20Netscape=20Portable=20Runtime=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A+=20= =20=20=0A+=20=20=20=20NSS=0A= +=20=20=20=20=0A+=20=20=20=20=20=0A+=20=20=20=20=20=20= =0A= +=20=20=20=20=20=20Network=20Security=20Services=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A=20=20= =20=20=0A=20=20=20=20=20= ODBC=0A=20=20=20=20=20=0A@@=20= -539,6=20+561,17=20@@=0A=20=20=20=20=20=0A=20=20=20=20= =0A=20=0A+=20=20=20=0A+=20=20=20=20= PKCS#12=0A+=20=20=20=20=0A+=20=20= =20=20=20=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20= Public-Key=20Cryptography=20Standards=20#12=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A=20=20= =20=20=0A=20=20=20=20=20PL=0A= =20=20=20=20=20=0A@@=20-684,6=20+717,16=20@@=0A=20=20=20=20=20= =0A=20=20=20=20=0A=20=0A+=20=20=20= =0A+=20=20=20=20TLS=0A+=20=20= =20=20=0A+=20=20=20=20=20=0A+=20=20=20=20=20=20=0A+=20=20= =20=20=20=20Transport=20Layer=20Security=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A=20=20= =20=20=0A=20=20=20=20=20= TOAST=0A=20=20=20=20=20=0Adiff=20= --git=20a/doc/src/sgml/config.sgml=20b/doc/src/sgml/config.sgml=0Aindex=20= f043433e31..f7ae3b1be1=20100644=0A---=20a/doc/src/sgml/config.sgml=0A+++=20= b/doc/src/sgml/config.sgml=0A@@=20-1208,6=20+1208,23=20@@=20include_dir=20= 'conf.d'=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A=20=0A+=20=20=20=20=20=0A+=20=20=20=20=20=20= ssl_database=20(string)=0A+=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20= ssl_database=20configuration=20= parameter=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=0A= +=20=20=20=20=20=20=20=20Specifies=20the=20name=20of=20the=20file=20= containing=20the=20server=20certificates=20and=0A+=20=20=20=20=20=20=20=20= keys=20when=20using=20NSS=20for=20= SSL=0A+=20=20=20=20=20=20=20=20connections.=20This=20= parameter=20can=20only=20be=20set=20in=20the=0A+=20=20=20=20=20=20=20=20= postgresql.conf=20file=20or=20on=20the=20server=20= command=0A+=20=20=20=20=20=20=20=20line.=0A+=20=20=20=20=20=20=20=0A= +=20=20=20=20=20=20=0A+=20=20=20=20=20=0A+=0A=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20= ssl_ciphers=20(string)=0A=20=20=20=20= =20=20=20=0A@@=20-1224,7=20+1241,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-1426,8=20+1445,11=20@@=20include_dir=20'conf.d'=0A=20=20=20=20=20= =20=20=20=0A=20=20=20=20=20=20=20=20=20Sets=20an=20external=20= command=20to=20be=20invoked=20when=20a=20passphrase=20for=0A=20=20=20=20=20= =20=20=20=20decrypting=20an=20SSL=20file=20such=20as=20a=20private=20key=20= needs=20to=20be=20obtained.=20=20By=0A-=20=20=20=20=20=20=20=20default,=20= this=20parameter=20is=20empty,=20which=20means=20the=20built-in=20= prompting=0A-=20=20=20=20=20=20=20=20mechanism=20is=20used.=0A+=20=20=20=20= =20=20=20=20default,=20this=20parameter=20is=20empty.=20When=20the=20= server=20is=20using=0A+=20=20=20=20=20=20=20=20= OpenSSL,=20this=20means=20the=20built-in=20= prompting=0A+=20=20=20=20=20=20=20=20mechanism=20is=20used.=20When=20= using=20NSS,=20there=20is=0A+=20=20=20=20=20=20= =20=20no=20default=20prompting=20so=20a=20blank=20callback=20will=20be=20= used=20returning=20an=0A+=20=20=20=20=20=20=20=20empty=20password.=0A=20=20= =20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20=0A=20=20=20=20= =20=20=20=20=20The=20command=20must=20print=20the=20passphrase=20to=20= the=20standard=20output=20and=20exit=0Adiff=20--git=20= a/doc/src/sgml/installation.sgml=20b/doc/src/sgml/installation.sgml=0A= index=200ac1cb9999..bd09124fb0=20100644=0A---=20= a/doc/src/sgml/installation.sgml=0A+++=20= b/doc/src/sgml/installation.sgml=0A@@=20-250,7=20+250,7=20@@=20su=20-=20= postgres=0A=20=0A=20=20=20=20=20=0A=20=20=20=20=20=20=0A= -=20=20=20=20=20=20You=20need=20OpenSSL,=20if=20= you=20want=20to=20support=0A+=20=20=20=20=20=20You=20need=20a=20= supported=20SSL=20library,=20if=20you=20want=20to=20= support=0A=20=20=20=20=20=20=20encrypted=20client=20connections.=20=20= OpenSSL=20is=0A=20=20=20=20=20=20=20also=20= required=20for=20random=20number=20generation=20on=20platforms=20that=20= do=20not=0A=20=20=20=20=20=20=20have=20/dev/urandom=20= (except=20Windows).=20=20The=20minimum=0A@@=20-966,6=20+966,31=20@@=20= build-postgresql:=0A=20=20=20=20=20=20=20=20=0A=20=20=20=20=20= =20=20=0A=20=0A+=20=20=20=20=20=20=0A+=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20NSS=0A+=20=20=20= =20=20=20=20=20NSPR=0A+=20=20=20=20=20=20=20=20= SSL=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=20=20Build=20with=20support=20for=20= SSL=20(encrypted)=0A+=20=20=20=20=20=20=20=20=20= connections=20using=20NSS.=20This=20requires=20= the=0A+=20=20=20=20=20=20=20=20=20NSS=20= package=20to=20be=20installed.=20Additionally,=0A+=20=20=20=20=20=20=20=20= =20NSS=20requires=20= NSPR=0A+=20=20=20=20=20=20=20=20=20to=20be=20= installed.=20configure=20will=20check=20for=20the=0A= +=20=20=20=20=20=20=20=20=20required=20header=20files=20and=20libraries=20= to=20make=20sure=20that=20your=0A+=20=20=20=20=20=20=20=20=20= NSS=20installation=20is=20sufficient=20before=0A= +=20=20=20=20=20=20=20=20=20proceeding.=0A+=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= This=20option=20is=20incompatible=20with=20= --with-openssl.=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= +=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20= =0A@@=20-982,6=20+1007,9=20@@=20build-postgresql:=0A=20=20=20=20= =20=20=20=20=20=20your=20OpenSSL=20= installation=20is=20sufficient=0A=20=20=20=20=20=20=20=20=20=20before=20= proceeding.=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=20This=20option=20is=20= incompatible=20with=20--with-nss.=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=20a/doc/src/sgml/libpq.sgml=20= b/doc/src/sgml/libpq.sgml=0Aindex=209ce32fb39b..61d9082052=20100644=0A= ---=20a/doc/src/sgml/libpq.sgml=0A+++=20b/doc/src/sgml/libpq.sgml=0A@@=20= -2459,6=20+2459,8=20@@=20void=20*PQsslStruct(const=20PGconn=20*conn,=20= const=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=20= depend=20on=20the=20SSL=20implementation=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-2482,9=20+2484,14=20@@=20void=20*PQsslStruct(const=20PGconn=20= *conn,=20const=20char=20*struct_name);=0A=20]]>=0A=20=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20= =20This=20structure=20can=20be=20used=20to=20verify=20encryption=20= levels,=20check=20server=0A-=20=20=20=20=20=20=20certificates,=20and=20= more.=20Refer=20to=20the=20OpenSSL=0A-=20=20=20= =20=20=20=20documentation=20for=20information=20about=20this=20= structure.=0A+=20=20=20=20=20=20=20For=20NSS,=20= there=20is=20one=20struct=20available=20under=0A+=20=20=20=20=20=20=20= the=20name=20"NSS",=20and=20it=20returns=20a=20pointer=20to=20the=0A+=20=20= =20=20=20=20=20NSS=20= PRFileDesc.=0A+=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20These=20structures=20can=20be=20= used=20to=20verify=20encryption=20levels,=20check=20server=0A+=20=20=20=20= =20=20=20certificates,=20and=20more.=20Refer=20to=20the=20= SSL=20library=0A+=20=20=20=20=20=20=20documentation=20= for=20information=20about=20these=20structures.=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=0A=20=20=20=20=20=0A= @@=20-2511,6=20+2518,10=20@@=20void=20*PQgetssl(const=20PGconn=20*conn);=0A= =20=20=20=20=20=20=20=20=20= instead,=20and=20for=20more=20details=20about=20the=0A=20=20=20=20=20=20=20= =20connection,=20use=20.=0A=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= This=20function=20returns=20NULL=20when=20= SSL=0A+=20=20=20=20=20=20=20librariaes=20other=20than=20= OpenSSL=20are=20used.=0A+=20=20=20=20=20=20= =0A=20=20=20=20=20=20=0A=20=20=20=20=20=0A= =20=0A@@=20-7943,6=20+7954,11=20@@=20void=20PQinitOpenSSL(int=20do_ssl,=20= int=20do_crypto);=0A=20=20=20=20=20=20=20=20before=20first=20opening=20a=20= database=20connection.=20=20Also=20be=20sure=20that=20you=0A=20=20=20=20=20= =20=20=20have=20done=20that=20initialization=20before=20opening=20a=20= database=20connection.=0A=20=20=20=20=20=20=20=0A+=0A+=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20This=20function=20does=20nothing=20= when=20using=20NSS=20as=0A+=20=20=20=20=20=20=20= the=20SSL=20library.=0A+=20=20=20=20=20=20=0A=20= =20=20=20=20=20=0A=20=20=20=20=20=0A=20=0A@@=20= -7969,6=20+7985,11=20@@=20void=20PQinitSSL(int=20do_ssl);=0A=20=20=20=20=20= =20=20=20might=20be=20preferable=20for=20applications=20that=20need=20to=20= work=20with=20older=0A=20=20=20=20=20=20=20=20versions=20of=20= libpq.=0A=20=20=20=20=20=20=20=0A+=0A+=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20This=20function=20does=20= nothing=20when=20using=20NSS=20as=0A+=20=20=20= =20=20=20=20the=20SSL=20library.=0A+=20=20=20=20=20=20= =0A=20=20=20=20=20=20=0A=20=20=20=20=20=0A= =20=20=20=20=0Adiff=20--git=20a/doc/src/sgml/runtime.sgml=20= b/doc/src/sgml/runtime.sgml=0Aindex=2017e938148c..fe7e305b75=20100644=0A= ---=20a/doc/src/sgml/runtime.sgml=0A+++=20b/doc/src/sgml/runtime.sgml=0A= @@=20-2183,15=20+2183,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-2211,8=20+2217,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-2302,6=20+2313,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=20paramaters=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-2376,7=20= +2399,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-2423,6=20+2446,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-2550,6=20+2581,45=20@@=20openssl=20x509=20-req=20-in=20= server.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,=20all=20= certificates=20and=20keys=20must=0A+=20=20=20=20be=20loaded=20into=20an=20= NSS=20certificate=20database.=0A+=20=20=20= =0A+=0A+=20=20=20=0A+=20=20=20=20To=20create=20a=20new=20= NSS=20certificate=20database=20and=0A+=20=20=20= =20load=20the=20certificates=20created=20in=20,=0A+=20=20=20=20use=20the=20= following=20NSS=20commands:=0A= +=0A+certutil=20-d=20"sql:server.db"=20-N=20= --empty-password=0A+certutil=20-d=20"sql:server.db"=20-A=20-n=20= server.crt=20-i=20server.crt=20-t=20"CT,C,C"=0A+certutil=20-d=20= "sql:server.db"=20-A=20-n=20root.crt=20-i=20root.crt=20-t=20"CT,C,C"=0A= +=0A+=20=20=20=20This=20will=20give=20the=20certificate=20= the=20filename=20as=20the=20nickname=20identifier=20in=0A+=20=20=20=20= the=20database=20which=20is=20created=20as=20= server.db.=0A+=20=20=20=0A+=20=20=20=0A= +=20=20=20=20Then=20load=20the=20server=20key,=20which=20require=20= converting=20it=20to=0A+=20=20=20=20PKCS#12=20format=20= using=20the=0A+=20=20=20=20OpenSSL=20tools:=0A= +=0A+openssl=20pkcs12=20-export=20-out=20server.pfx=20= -inkey=20server.key=20-in=20server.crt=20\=0A+=20=20-certfile=20root.crt=20= -passout=20pass:=0A+pk12util=20-i=20server.pfx=20-d=20server.db=20-W=20= ''=0A+=0A+=20=20=20=0A+=20=20=20=0A+=20=20=20= =20Finally=20a=20certificate=20revocation=20list=20can=20be=20loaded=20= with=20the=20following=0A+=20=20=20=20commands:=0A+=0A= +crlutil=20-I=20-i=20server.crl=20-d=20server.db=20-B=0A= +=0A+=20=20=20=0A+=20=20=0A+=0A=20=20= =0A=20=0A=20=20=0A--=20=0A2.21.1=20= (Apple=20Git-122.3)=0A=0A= --Apple-Mail=_C39967DC-7CE2-4297-8DC3-75F0E858FBDB Content-Disposition: attachment; filename=v15-0005-NSS-contrib-modules.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v15-0005-NSS-contrib-modules.patch" Content-Transfer-Encoding: quoted-printable =46rom=20752805f50dd7c63b8784cd15336ad3056d98adf9=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2028=20Oct=202020=2011:34:37=20+0100=0ASubject:=20[PATCH=20= v15=205/6]=20NSS=20contrib=20modules=0A=0A---=0A=20contrib/Makefile=20=20= =20=20=20=20=20=20=20=20=20=20|=20=20=202=20+-=0A=20= contrib/pgcrypto/Makefile=20=20=20|=20=20=207=20+-=0A=20= contrib/pgcrypto/nss.c=20=20=20=20=20=20|=20773=20= ++++++++++++++++++++++++++++++++++++=0A=20contrib/pgcrypto/px.c=20=20=20=20= =20=20=20|=20=20=201=20+=0A=20contrib/pgcrypto/px.h=20=20=20=20=20=20=20= |=20=20=201=20+=0A=20contrib/sslinfo/sslinfo.c=20=20=20|=20164=20= ++++----=0A=20doc/src/sgml/pgcrypto.sgml=20=20|=20=2038=20+-=0A=20= doc/src/sgml/sslinfo.sgml=20=20=20|=20=2012=20+-=0A=20= src/tools/msvc/Install.pm=20=20=20|=20=20=203=20+-=0A=20= src/tools/msvc/Mkvcbuild.pm=20|=20=2012=20+-=0A=2010=20files=20changed,=20= 910=20insertions(+),=20103=20deletions(-)=0A=20create=20mode=20100644=20= contrib/pgcrypto/nss.c=0A=0Adiff=20--git=20a/contrib/Makefile=20= b/contrib/Makefile=0Aindex=207a4866e338..c2232e5a4d=20100644=0A---=20= a/contrib/Makefile=0A+++=20b/contrib/Makefile=0A@@=20-52,7=20+52,7=20@@=20= SUBDIRS=20=3D=20\=0A=20=09=09unaccent=09\=0A=20=09=09vacuumlo=0A=20=0A= -ifeq=20($(with_openssl),yes)=0A+ifneq=20($(with_ssl),no)=0A=20SUBDIRS=20= +=3D=20sslinfo=0A=20else=0A=20ALWAYS_SUBDIRS=20+=3D=20sslinfo=0Adiff=20= --git=20a/contrib/pgcrypto/Makefile=20b/contrib/pgcrypto/Makefile=0A= index=2061eabd2fc0..28b54d321b=20100644=0A---=20= a/contrib/pgcrypto/Makefile=0A+++=20b/contrib/pgcrypto/Makefile=0A@@=20= -7,11=20+7,14=20@@=20INT_TESTS=20=3D=20sha2=0A=20OSSL_SRCS=20=3D=20= openssl.c=20pgp-mpi-openssl.c=0A=20OSSL_TESTS=20=3D=20sha2=20des=203des=20= cast5=0A=20=0A+NSS_SRCS=20=3D=20nss.c=20pgp-mpi-internal.c=20imath.c=20= blf.c=0A+NSS_TESTS=20=3D=20sha2=20des=203des=0A+=0A=20ZLIB_TST=20=3D=20= pgp-compression=0A=20ZLIB_OFF_TST=20=3D=20pgp-zlib-DISABLED=0A=20=0A= -CF_SRCS=20=3D=20$(if=20$(subst=20no,,$(with_openssl)),=20$(OSSL_SRCS),=20= $(INT_SRCS))=0A-CF_TESTS=20=3D=20$(if=20$(subst=20no,,$(with_openssl)),=20= $(OSSL_TESTS),=20$(INT_TESTS))=0A+CF_SRCS=20=3D=20$(if=20$(findstring=20= openssl,=20$(with_ssl)),=20$(OSSL_SRCS),=20$(if=20$(findstring=20nss,=20= $(with_ssl)),=20$(NSS_SRCS),=20$(INT_SRCS)))=0A+CF_TESTS=20=3D=20$(if=20= $(findstring=20openssl,=20$(with_ssl)),=20$(OSSL_TESTS),=20$(if=20= $(findstring=20nss,=20$(with_ssl)),=20$(NSS_TESTS),=20$(INT_TESTS)))=0A=20= CF_PGP_TESTS=20=3D=20$(if=20$(subst=20no,,$(with_zlib)),=20$(ZLIB_TST),=20= $(ZLIB_OFF_TST))=0A=20=0A=20SRCS=20=3D=20\=0Adiff=20--git=20= a/contrib/pgcrypto/nss.c=20b/contrib/pgcrypto/nss.c=0Anew=20file=20mode=20= 100644=0Aindex=200000000000..e1291ed403=0A---=20/dev/null=0A+++=20= b/contrib/pgcrypto/nss.c=0A@@=20-0,0=20+1,773=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20nss.c=0A+=20*=09=20=20Wrapper=20for=20using=20NSS=20= as=20a=20backend=20for=20pgcrypto=20PX=0A+=20*=0A+=20*=0A+=20*=20= Portions=20Copyright=20(c)=201996-2020,=20PostgreSQL=20Global=20= Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=201994,=20= Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=09=20=20contrib/pgcrypto/nss.c=0A+=20*=0A+=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#include=20"postgres.h"=0A+=0A+#include=20"px.h"=0A= +#include=20"blf.h"=0A+#include=20"utils/memutils.h"=0A+=0A+/*=0A+=20*=20= BITS_PER_BYTE=20is=20also=20defined=20in=20the=20NSPR=20header=20files,=20= so=20we=20need=20to=20undef=0A+=20*=20our=20version=20to=20avoid=20= compiler=20warnings=20on=20redefinition.=0A+=20*/=0A+#define=20= pg_BITS_PER_BYTE=20BITS_PER_BYTE=0A+#undef=20BITS_PER_BYTE=0A+=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+=0A+/*=0A+=20*=20Ensure=20= that=20the=20colliding=20definitions=20match,=20else=20throw=20an=20= error.=20In=20case=0A+=20*=20NSPR=20has=20removed=20the=20definition=20= for=20some=20reason,=20make=20sure=20to=20put=20ours=0A+=20*=20back=20= again.=0A+=20*/=0A+#if=20defined(BITS_PER_BYTE)=0A+#if=20BITS_PER_BYTE=20= !=3D=20pg_BITS_PER_BYTE=0A+#error=20"incompatible=20byte=20widths=20= between=20NSPR=20and=20postgres"=0A+#endif=0A+#else=0A+#define=20= BITS_PER_BYTE=20pg_BITS_PER_BYTE=0A+#endif=0A+#undef=20pg_BITS_PER_BYTE=0A= +=0A+/*=0A+=20*=20Define=20our=20own=20mechanisms=20for=20Blowfish=20as=20= it's=20not=20implemented=20by=20NSS.=0A+=20*/=0A+#define=20BLOWFISH_CBC=09= (1)=0A+#define=20BLOWFISH_ECB=09(2)=0A+=0A+/*=0A+=20*=20Data=20= structures=20for=20recording=20cipher=20implementations=20as=20well=20as=20= ongoing=0A+=20*=20cipher=20operations.=0A+=20*/=0A+typedef=20struct=20= nss_digest=0A+{=0A+=09NSSInitContext=20*context;=0A+=09PK11Context=20= *hash_context;=0A+=09HASH_HashType=20hash_type;=0A+}=09=09=09nss_digest;=0A= +=0A+typedef=20struct=20cipher_implementation=0A+{=0A+=09/*=20Function=20= pointers=20to=20cipher=20operations=20*/=0A+=09int=09=09=09(*init)=20= (PX_Cipher=20*pxc,=20const=20uint8=20*key,=20unsigned=20klen,=20const=20= uint8=20*iv);=0A+=09unsigned=09(*get_block_size)=20(PX_Cipher=20*pxc);=0A= +=09unsigned=20=09(*get_key_size)=20(PX_Cipher=20*pxc);=0A+=09unsigned=20= =09(*get_iv_size)=20(PX_Cipher=20*pxc);=0A+=09int=09=09=09(*encrypt)=20= (PX_Cipher=20*pxc,=20const=20uint8=20*data,=20unsigned=20dlen,=20uint8=20= *res);=0A+=09int=09=09=09(*decrypt)=20(PX_Cipher=20*pxc,=20const=20uint8=20= *data,=20unsigned=20dlen,=20uint8=20*res);=0A+=09void=09=09(*free)=20= (PX_Cipher=20*pxc);=0A+=0A+=09/*=20The=20mechanism=20describing=20the=20= cipher=20used=20*/=0A+=09union=0A+=09{=0A+=09=09CK_MECHANISM_TYPE=20nss;=0A= +=09=09CK_ULONG=20internal;=0A+=09}=09=09=09mechanism;=0A+=09int=09=09=09= keylen;=0A+=09bool=09=09is_nss;=0A+}=09=09=09cipher_implementation;=0A+=0A= +typedef=20struct=20nss_cipher=0A+{=0A+=09const=20cipher_implementation=20= *impl;=0A+=09NSSInitContext=20*context;=0A+=09PK11Context=20= *crypt_context;=0A+=09SECItem=20*params;=0A+=0A+=09PK11SymKey=20= *encrypt_key;=0A+=09PK11SymKey=20*decrypt_key;=0A+}=09=09=09nss_cipher;=0A= +=0A+typedef=20struct=20internal_cipher=0A+{=0A+=09const=20= cipher_implementation=20*impl;=0A+=09BlowfishContext=09context;=0A+}=09=09= =09internal_cipher;=0A+=0A+typedef=20struct=20nss_cipher_ref=0A+{=0A+=09= const=20char=20*name;=0A+=09const=20cipher_implementation=20*impl;=0A+}=20= 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=09free_ctx=20=3D=20PR_TRUE;=0A= +=0A+=09PK11_DestroyContext(digest->hash_context,=20free_ctx);=0A+=09= NSS_ShutdownContext(digest->context);=0A+}=0A+=0A+static=20void=0A= +nss_digest_update(PX_MD=20*pxmd,=20const=20uint8=20*data,=20unsigned=20= dlen)=0A+{=0A+=09nss_digest=20*digest=20=3D=20(nss_digest=20*)=20= pxmd->p.ptr;=0A+=0A+=09PK11_DigestOp(digest->hash_context,=20data,=20= dlen);=0A+}=0A+=0A+static=20void=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*pxmd;=0A+=09NSSInitParameters=20= params;=0A+=09NSSInitContext=20*nss_context;=0A+=09bool=20found=20=3D=20= false;=0A+=09nss_digest=20*digest;=0A+=09SECStatus=20status;=0A+=09= SECOidData=20*hash;=0A+=09HASH_HashType=20t;=0A+=0A+=09/*=0A+=09=20*=20= Initialize=20our=20own=20NSS=20context=20without=20a=20database=20= backing=20it.=0A+=09=20*/=0A+=09memset(¶ms,=200,=20sizeof(params));=0A= +=09params.length=20=3D=20sizeof(params);=0A+=09nss_context=20=3D=20= NSS_InitContext("",=20"",=20"",=20"",=20¶ms,=0A+=09=09=09=09=09=09=09= =09=20=20NSS_INIT_READONLY=20|=20NSS_INIT_NOCERTDB=20|=0A+=09=09=09=09=09= =09=09=09=20=20NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A+=09=09=09= =09=09=09=09=09=20=20NSS_INIT_NOROOTINIT=20|=20NSS_INIT_PK11RELOAD);=0A+=0A= +=09/*=0A+=09=20*=20There=20is=20no=20API=20function=20for=20looking=20= up=20a=20digest=20algorithm=20from=20a=20name=0A+=09=20*=20string,=20but=20= there=20is=20a=20publically=20accessible=20array=20which=20can=20be=20= scanned=0A+=09=20*=20for=20the=20name.=0A+=09=20*/=0A+=09for=20(t=20=3D=20= HASH_AlgNULL=20+=201;=20t=20<=20HASH_AlgTOTAL;=20t++)=0A+=09{=0A+=09=09= SECOidTag=20=09hash_oid;=0A+=09=09char=20*p;=0A+=0A+=09=09hash_oid=20=3D=20= nss_GetHashOidTagByHashType(t);=0A+=0A+=09=09if=20(hash_oid=20=3D=3D=20= SEC_OID_UNKNOWN)=0A+=09=09=09return=20PXE_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=09= found=20=3D=20true;=0A+=09=09=09break;=0A+=09=09}=0A+=0A+=09=09/*=0A+=09=09= =20*=20NSS=20saves=20the=20algorithm=20names=20using=20SHA-xxx=20= notation=20whereas=0A+=09=09=20*=20OpenSSL=20use=20SHAxxx.=20To=20make=20= sure=20the=20user=20finds=20the=20requested=0A+=09=09=20*=20algorithm=20= let's=20remove=20the=20dash=20and=20compare=20that=20spelling=20as=20= well.=0A+=09=09=20*/=0A+=09=09if=20((p=20=3D=20strchr(hash->desc,=20= '-'))=20!=3D=20NULL)=0A+=09=09{=0A+=09=09=09char=20tmp[12];=0A+=0A+=09=09= =09memcpy(tmp,=20hash->desc,=20p=20-=20hash->desc);=0A+=09=09=09= memcpy(tmp=20+=20(p=20-=20hash->desc),=20p=20+=201,=20strlen(hash->desc)=20= -=20(p=20-=20hash->desc)=20+=201);=0A+=09=09=09if=20(pg_strcasecmp(tmp,=20= name)=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+=09digest=20=3D=20= palloc(sizeof(*digest));=0A+=0A+=09digest->context=20=3D=20nss_context;=0A= +=09digest->hash_context=20=3D=20PK11_CreateDigestContext(hash->offset);=0A= +=09digest->hash_type=20=3D=20t;=0A+=09if=20(digest->hash_context=20=3D=3D= =20NULL)=0A+=09{=0A+=09=09pfree(digest);=0A+=09=09return=20-1;=0A+=09}=0A= +=0A+=09status=20=3D=20PK11_DigestBegin(digest->hash_context);=0A+=09if=20= (status=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09= PK11_DestroyContext(digest->hash_context,=20PR_TRUE);=0A+=09=09= pfree(digest);=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09pxmd=20=3D=20= palloc(sizeof(*pxmd));=0A+=09pxmd->result_size=20=3D=20= nss_digest_result_size;=0A+=09pxmd->block_size=20=3D=20= nss_digest_block_size;=0A+=09pxmd->reset=20=3D=20nss_digest_reset;=0A+=09= pxmd->update=20=3D=20nss_digest_update;=0A+=09pxmd->finish=20=3D=20= nss_digest_finish;=0A+=09pxmd->free=20=3D=20nss_digest_free;=0A+=09= pxmd->p.ptr=20=3D=20(void=20*)=20digest;=0A+=0A+=09*res=20=3D=20pxmd;=0A= +=0A+=09return=200;=0A+}=0A+=0A+static=20int=0A+bf_init(PX_Cipher=20= *pxc,=20const=20uint8=20*key,=20unsigned=20klen,=20const=20uint8=20*iv)=0A= +{=0A+=09internal_cipher=20*cipher=20=3D=20(internal_cipher=20*)=20= pxc->ptr;=0A+=0A+=09blowfish_setkey(&cipher->context,=20key,=20klen);=0A= +=09if=20(iv)=0A+=09=09blowfish_setiv(&cipher->context,=20iv);=0A+=0A+=09= return=200;=0A+}=0A+=0A+static=20int=0A+bf_encrypt(PX_Cipher=20*pxc,=20= const=20uint8=20*data,=20unsigned=20dlen,=20uint8=20*res)=0A+{=0A+=09= internal_cipher=20*cipher=20=3D=20(internal_cipher=20*)=20pxc->ptr;=0A+=09= uint8=20*buf;=0A+=0A+=09if=20(dlen=20=3D=3D=200)=0A+=09=09return=200;=0A= +=0A+=09if=20(dlen=20&=207)=0A+=09=09return=20PXE_NOTBLOCKSIZE;=0A+=0A+=09= buf=20=3D=20palloc(dlen);=0A+=09memcpy(buf,=20data,=20dlen);=0A+=0A+=09= if=20(cipher->impl->mechanism.internal=20=3D=3D=20BLOWFISH_ECB)=0A+=09=09= blowfish_encrypt_ecb(buf,=20dlen,=20&cipher->context);=0A+=09else=0A+=09=09= blowfish_encrypt_cbc(buf,=20dlen,=20&cipher->context);=0A+=0A+=09= memcpy(res,=20buf,=20dlen);=0A+=09pfree(buf);=0A+=0A+=09return=200;=0A+}=0A= +=0A+static=20int=0A+bf_decrypt(PX_Cipher=20*pxc,=20const=20uint8=20= *data,=20unsigned=20dlen,=20uint8=20*res)=0A+{=0A+=09internal_cipher=20= *cipher=20=3D=20(internal_cipher=20*)=20pxc->ptr;=0A+=0A+=09if=20(dlen=20= =3D=3D=200)=0A+=09=09return=200;=0A+=0A+=09if=20(dlen=20&=207)=0A+=09=09= return=20PXE_NOTBLOCKSIZE;=0A+=0A+=09memcpy(res,=20data,=20dlen);=0A+=09= if=20(cipher->impl->mechanism.internal=20=3D=3D=20BLOWFISH_ECB)=0A+=09=09= blowfish_decrypt_ecb(res,=20dlen,=20&cipher->context);=0A+=09else=0A+=09=09= blowfish_decrypt_cbc(res,=20dlen,=20&cipher->context);=0A+=0A+=09return=20= 0;=0A+}=0A+=0A+static=20void=0A+bf_free(PX_Cipher=20*pxc)=0A+{=0A+=09= internal_cipher=20*cipher=20=3D=20(internal_cipher=20*)=20pxc->ptr;=0A+=0A= +=09pfree(cipher);=0A+=09pfree(pxc);=0A+}=0A+=0A+static=20int=0A= +nss_symkey_blockcipher_init(PX_Cipher=20*pxc,=20const=20uint8=20*key,=20= unsigned=20klen,=0A+=09=09=09=09=09=09=09const=20uint8=20*iv)=0A+{=0A+=09= nss_cipher=09=20=20=20*cipher=20=3D=20(nss_cipher=20*)=20pxc->ptr;=0A+=09= SECItem=09=09=09iv_item;=0A+=09unsigned=20char=20=20*iv_item_data;=0A+=09= SECItem=09=09=09key_item;=0A+=09int=09=09=09=09keylen;=0A+=09= PK11SlotInfo=20=20=20*slot;=0A+=0A+=09if=20(cipher->impl->mechanism.nss=20= =3D=3D=20CKM_AES_CBC=20||=0A+=09=09cipher->impl->mechanism.nss=20=3D=3D=20= CKM_AES_ECB)=0A+=09{=0A+=09=09if=20(klen=20<=3D=20128=20/=208)=0A+=09=09=09= keylen=20=3D=20128=20/=208;=0A+=09=09else=20if=20(klen=20<=3D=20192=20/=20= 8)=0A+=09=09=09keylen=20=3D=20192=20/=208;=0A+=09=09else=20if=20(klen=20= <=3D=20256=20/=208)=0A+=09=09=09keylen=20=3D=20256=20/=208;=0A+=09=09= else=0A+=09=09=09return=20PXE_CIPHER_INIT;=0A+=09}=0A+=09else=0A+=09=09= keylen=20=3D=20cipher->impl->keylen;=0A+=0A+=09key_item.type=20=3D=20= siBuffer;=0A+=09key_item.data=20=3D=20(unsigned=20char=20*)=20key;=0A+=09= key_item.len=20=3D=20keylen;=0A+=0A+=09/*=0A+=09=20*=20If=20hardware=20= acceleration=20is=20configured=20in=20NSS=20one=20can=20theoretically=20= get=0A+=09=20*=20a=20better=20slot=20by=20calling=20PK11_GetBestSlot()=20= with=20the=20mechanism=20passed=0A+=09=20*=20to=20it.=20Unless=20there=20= are=20complaints,=20using=20the=20simpler=20API=20will=20make=0A+=09=20*=20= error=20handling=20easier=20though.=0A+=09=20*/=0A+=09slot=20=3D=20= PK11_GetInternalSlot();=0A+=09if=20(!slot)=0A+=09=09return=20= PXE_CIPHER_INIT;=0A+=0A+=09/*=0A+=09=20*=20The=20key=20must=20be=20set=20= up=20for=20the=20operation,=20and=20since=20we=20don't=20know=20at=0A+=09= =20*=20this=20point=20whether=20we=20are=20asked=20to=20encrypt=20or=20= decrypt=20we=20need=20to=20store=0A+=09=20*=20both=20versions.=0A+=09=20= */=0A+=09cipher->decrypt_key=20=3D=20PK11_ImportSymKey(slot,=20= cipher->impl->mechanism.nss,=0A+=09=09=09=09=09=09=09=09=09=09=09= PK11_OriginUnwrap,=0A+=09=09=09=09=09=09=09=09=09=09=09CKA_DECRYPT,=20= &key_item,=0A+=09=09=09=09=09=09=09=09=09=09=09NULL);=0A+=09= cipher->encrypt_key=20=3D=20PK11_ImportSymKey(slot,=20= cipher->impl->mechanism.nss,=0A+=09=09=09=09=09=09=09=09=09=09=09= PK11_OriginUnwrap,=0A+=09=09=09=09=09=09=09=09=09=09=09CKA_ENCRYPT,=20= &key_item,=0A+=09=09=09=09=09=09=09=09=09=09=09NULL);=0A+=09= PK11_FreeSlot(slot);=0A+=0A+=09if=20(!cipher->decrypt_key=20||=20= !cipher->encrypt_key)=0A+=09=09return=20PXE_CIPHER_INIT;=0A+=0A+=09if=20= (iv)=0A+=09{=0A+=09=09iv_item.type=20=3D=20siBuffer;=0A+=09=09= iv_item.data=20=3D=20(unsigned=20char=20*)=20iv;=0A+=09=09iv_item.len=20= =3D=20nss_get_iv_size(pxc);=0A+=09}=0A+=09else=0A+=09{=0A+=09=09/*=0A+=09= =09=20*=20The=20documentation=20states=20that=20either=20passing=20.data=20= =3D=200;=20.len=20=3D=200;=0A+=09=09=20*=20in=20the=20iv_item,=20or=20= NULL=20as=20iv_item,=20to=20PK11_ParamFromIV=20should=20be=0A+=09=09=20*=20= done=20when=20IV=20is=20missing.=20That=20however=20leads=20to=20= segfaults=20in=20the=0A+=09=09=20*=20library,=20the=20workaround=20that=20= works=20in=20modern=20=20library=20versions=20is=0A+=09=09=20*=20to=20= pass=20in=20a=20keysized=20zeroed=20out=20IV.=0A+=09=09=20*/=0A+=09=09= iv_item_data=20=3D=20palloc0(nss_get_iv_size(pxc));=0A+=09=09= iv_item.type=20=3D=20siBuffer;=0A+=09=09iv_item.data=20=3D=20= iv_item_data;=0A+=09=09iv_item.len=20=3D=20nss_get_iv_size(pxc);=0A+=09}=0A= +=0A+=09cipher->params=20=3D=20= PK11_ParamFromIV(cipher->impl->mechanism.nss,=20&iv_item);=0A+=0A+=09/*=20= If=20we=20had=20to=20make=20a=20mock=20IV,=20free=20it=20once=20made=20= into=20a=20param=20*/=0A+=09if=20(!iv)=0A+=09=09pfree(iv_item_data);=0A+=0A= +=09if=20(cipher->params=20=3D=3D=20NULL)=0A+=09=09return=20= PXE_CIPHER_INIT;=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20int=0A= +nss_decrypt(PX_Cipher=20*pxc,=20const=20uint8=20*data,=20unsigned=20= dlen,=20uint8=20*res)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= (nss_cipher=20*)=20pxc->ptr;=0A+=09SECStatus=09status;=0A+=09int=20= outlen;=0A+=0A+=09if=20(!cipher->crypt_context)=0A+=09{=0A+=09=09= cipher->crypt_context=20=3D=0A+=09=09=09= PK11_CreateContextBySymKey(cipher->impl->mechanism.nss,=20CKA_DECRYPT,=0A= +=09=09=09=09=09=09=09=09=09=20=20=20cipher->decrypt_key,=20= cipher->params);=0A+=09}=0A+=0A+=09status=20=3D=20= PK11_CipherOp(cipher->crypt_context,=20res,=20&outlen,=20dlen,=20data,=20= dlen);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20= PXE_DECRYPT_FAILED;=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20int=0A= +nss_encrypt(PX_Cipher=20*pxc,=20const=20uint8=20*data,=20unsigned=20= dlen,=20uint8=20*res)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= (nss_cipher=20*)=20pxc->ptr;=0A+=09SECStatus=09status;=0A+=09int=20= outlen;=0A+=0A+=09if=20(!cipher->crypt_context)=0A+=09{=0A+=09=09= cipher->crypt_context=20=3D=0A+=09=09=09= PK11_CreateContextBySymKey(cipher->impl->mechanism.nss,=20CKA_ENCRYPT,=0A= +=09=09=09=09=09=09=09=09=09=20=20=20cipher->decrypt_key,=20= cipher->params);=0A+=09}=0A+=0A+=09status=20=3D=20= PK11_CipherOp(cipher->crypt_context,=20res,=20&outlen,=20dlen,=20data,=20= dlen);=0A+=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20= PXE_DECRYPT_FAILED;=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20void=0A= +nss_free(PX_Cipher=20*pxc)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= pxc->ptr;=0A+=09PRBool=09=09free_ctx=20=3D=20PR_TRUE;=0A+=0A+=09= PK11_FreeSymKey(cipher->encrypt_key);=0A+=09= PK11_FreeSymKey(cipher->decrypt_key);=0A+=09= PK11_DestroyContext(cipher->crypt_context,=20free_ctx);=0A+=09= NSS_ShutdownContext(cipher->context);=0A+=09pfree(cipher);=0A+=0A+=09= pfree(pxc);=0A+}=0A+=0A+static=20unsigned=0A= +nss_get_block_size(PX_Cipher=20*pxc)=0A+{=0A+=09nss_cipher=20*cipher=20= =3D=20pxc->ptr;=0A+=0A+=09return=20= PK11_GetBlockSize(cipher->impl->mechanism.nss,=20NULL);=0A+}=0A+=0A= +static=20unsigned=0A+nss_get_key_size(PX_Cipher=20*pxc)=0A+{=0A+=09= nss_cipher=20*cipher=20=3D=20pxc->ptr;=0A+=0A+=09return=20= cipher->impl->keylen;=0A+}=0A+=0A+static=20unsigned=0A= +nss_get_iv_size(PX_Cipher=20*pxc)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= pxc->ptr;=0A+=0A+=09return=20= PK11_GetIVLength(cipher->impl->mechanism.nss);=0A+}=0A+=0A+static=20= unsigned=0A+bf_get_block_size(PX_Cipher=20*pxc)=0A+{=0A+=09return=208;=0A= +}=0A+=0A+static=20unsigned=0A+bf_get_key_size(PX_Cipher=20*pxc)=0A+{=0A= +=09return=20448=20/=208;=0A+}=0A+=0A+static=20unsigned=0A= +bf_get_iv_size(PX_Cipher=20*pxc)=0A+{=0A+=09return=208;=0A+}=0A+=0A+/*=0A= +=20*=20Cipher=20Implementations=0A+=20*/=0A+static=20const=20= cipher_implementation=20nss_des_cbc=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES_CBC,=0A+=09.keylen=20=3D=20= 8,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_des_ecb=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES_ECB,=0A+=09.keylen=20=3D=20= 8,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_des3_cbc=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES3_CBC,=0A+=09.keylen=20=3D=20= 24,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_des3_ecb=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES3_ECB,=0A+=09.keylen=20=3D=20= 24,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_aes_cbc=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_AES_CBC,=0A+=09.keylen=20=3D=20= 32,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_aes_ecb=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_AES_ECB,=0A+=09.keylen=20=3D=20= 32,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_bf_ecb=20=3D=20{=0A+=09.init=20=3D=20= bf_init,=0A+=09.get_block_size=20=3D=20bf_get_block_size,=0A+=09= .get_key_size=20=3D=20bf_get_key_size,=0A+=09.get_iv_size=20=3D=20= bf_get_iv_size,=0A+=09.encrypt=20=3D=20bf_encrypt,=0A+=09.decrypt=20=3D=20= bf_decrypt,=0A+=09.free=20=3D=20bf_free,=0A+=09.mechanism.internal=20=3D=20= BLOWFISH_ECB,=0A+=09.keylen=20=3D=2056,=0A+=09.is_nss=20=3D=20false=0A= +};=0A+=0A+static=20const=20cipher_implementation=20nss_bf_cbc=20=3D=20{=0A= +=09.init=20=3D=20bf_init,=0A+=09.get_block_size=20=3D=20= bf_get_block_size,=0A+=09.get_key_size=20=3D=20bf_get_key_size,=0A+=09= .get_iv_size=20=3D=20bf_get_iv_size,=0A+=09.encrypt=20=3D=20bf_encrypt,=0A= +=09.decrypt=20=3D=20bf_decrypt,=0A+=09.free=20=3D=20bf_free,=0A+=09= .mechanism.internal=20=3D=20BLOWFISH_CBC,=0A+=09.keylen=20=3D=2056,=0A+=09= .is_nss=20=3D=20false=0A+};=0A+=0A+/*=0A+=20*=20Lookup=20table=20for=20= finding=20the=20implementation=20based=20on=20a=20name.=20CAST5=20as=20= well=0A+=20*=20as=20BLOWFISH=20are=20defined=20as=20cipher=20mechanisms=20= in=20NSS=20but=20error=20out=20with=0A+=20*=20= SEC_ERROR_INVALID_ALGORITHM.=20Blowfish=20is=20implemented=20using=20the=20= internal=0A+=20*=20implementation=20while=20CAST5=20isn't=20supported=20= at=20all=20at=20this=20time,=0A+=20*/=0A+static=20const=20nss_cipher_ref=20= nss_cipher_lookup[]=20=3D=20{=0A+=09{"des",=20&nss_des_cbc},=0A+=09= {"des-cbc",=20&nss_des_cbc},=0A+=09{"des-ecb",=20&nss_des_ecb},=0A+=09= {"des3-cbc",=20&nss_des3_cbc},=0A+=09{"3des",=20&nss_des3_cbc},=0A+=09= {"3des-cbc",=20&nss_des3_cbc},=0A+=09{"des3-ecb",=20&nss_des3_ecb},=0A+=09= {"3des-ecb",=20&nss_des3_ecb},=0A+=09{"aes",=20&nss_aes_cbc},=0A+=09= {"aes-cbc",=20&nss_aes_cbc},=0A+=09{"aes-ecb",=20&nss_aes_ecb},=0A+=09= {"rijndael",=20&nss_aes_cbc},=0A+=09{"rijndael-cbc",=20&nss_aes_cbc},=0A= +=09{"rijndael-ecb",=20&nss_aes_ecb},=0A+=09{"blowfish",=20&nss_bf_cbc},=0A= +=09{"blowfish-cbc",=20&nss_bf_cbc},=0A+=09{"blowfish-ecb",=20= &nss_bf_ecb},=0A+=09{"bf",=20&nss_bf_cbc},=0A+=09{"bf-cbc",=20= &nss_bf_cbc},=0A+=09{"bf-ecb",=20&nss_bf_ecb},=0A+=09{NULL}=0A+};=0A+=0A= +/*=0A+=20*=20px_find_cipher=0A+=20*=0A+=20*=20Search=20for=20the=20= requested=20cipher=20and=20see=20if=20there=20is=20support=20for=20it,=20= and=20if=0A+=20*=20so=20return=20an=20allocated=20object=20containing=20= the=20playbook=20for=20how=20to=20encrypt=0A+=20*=20and=20decrypt=20= using=20the=20cipher.=0A+=20*/=0A+int=0A+px_find_cipher(const=20char=20= *alias,=20PX_Cipher=20**res)=0A+{=0A+=09const=20nss_cipher_ref=20= *cipher_ref;=0A+=09PX_Cipher=20=20*px_cipher;=0A+=09NSSInitParameters=20= params;=0A+=09NSSInitContext=20*nss_context;=0A+=09nss_cipher=09*cipher;=0A= +=09internal_cipher=20*int_cipher;=0A+=0A+=09for=20(cipher_ref=20=3D=20= nss_cipher_lookup;=20cipher_ref->name;=20cipher_ref++)=0A+=09{=0A+=09=09= if=20(strcmp(cipher_ref->name,=20alias)=20=3D=3D=200)=0A+=09=09=09break;=0A= +=09}=0A+=0A+=09if=20(!cipher_ref->name)=0A+=09=09return=20= PXE_NO_CIPHER;=0A+=0A+=09/*=0A+=09=20*=20Fill=20in=20the=20PX_Cipher=20= to=20pass=20back=20to=20PX=20describing=20the=20operations=20to=0A+=09=20= *=20perform=20in=20order=20to=20use=20the=20cipher.=0A+=09=20*/=0A+=09= px_cipher=20=3D=20palloc(sizeof(*px_cipher));=0A+=09= px_cipher->block_size=20=3D=20cipher_ref->impl->get_block_size;=0A+=09= px_cipher->key_size=20=3D=20cipher_ref->impl->get_key_size;=0A+=09= px_cipher->iv_size=20=3D=20cipher_ref->impl->get_iv_size;=0A+=09= px_cipher->free=20=3D=20cipher_ref->impl->free;=0A+=09px_cipher->init=20= =3D=20cipher_ref->impl->init;=0A+=09px_cipher->encrypt=20=3D=20= cipher_ref->impl->encrypt;=0A+=09px_cipher->decrypt=20=3D=20= cipher_ref->impl->decrypt;=0A+=0A+=09/*=0A+=09=20*=20Set=20the=20private=20= data,=20which=20is=20different=20for=20NSS=20and=20internal=20ciphers=0A= +=09=20*/=0A+=09if=20(cipher_ref->impl->is_nss)=0A+=09{=0A+=09=09/*=0A+=09= =09=20*=20Initialize=20our=20own=20NSS=20context=20without=20a=20= database=20backing=20it.=20At=0A+=09=09=20*=20some=20point=20we=20might=20= want=20to=20allow=20users=20to=20use=20stored=20keys=20in=20the=0A+=09=09= =20*=20database=20rather=20than=20passing=20them=20via=20SELECT=20= encrypt(),=20and=20then=0A+=09=09=20*=20this=20need=20to=20be=20changed=20= to=20open=20a=20user=20specified=20database.=0A+=09=09=20*/=0A+=09=09= memset(¶ms,=200,=20sizeof(params));=0A+=09=09params.length=20=3D=20= sizeof(params);=0A+=09=09nss_context=20=3D=20NSS_InitContext("",=20"",=20= "",=20"",=20¶ms,=0A+=09=09=09=09=09=09=09=09=09=20=20= NSS_INIT_READONLY=20|=20NSS_INIT_NOCERTDB=20|=0A+=09=09=09=09=09=09=09=09= =09=20=20NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A+=09=09=09=09=09= =09=09=09=09=20=20NSS_INIT_NOROOTINIT=20|=20NSS_INIT_PK11RELOAD);=0A+=0A= +=09=09/*=20nss_cipher=20is=20the=20private=20state=20struct=20for=20the=20= operation=20*/=0A+=09=09cipher=20=3D=20palloc(sizeof(*cipher));=0A+=09=09= cipher->context=20=3D=20nss_context;=0A+=09=09cipher->impl=20=3D=20= cipher_ref->impl;=0A+=09=09cipher->crypt_context=20=3D=20NULL;=0A+=0A+=09= =09px_cipher->ptr=20=3D=20cipher;=0A+=09}=0A+=09else=0A+=09{=0A+=09=09= int_cipher=20=3D=20palloc0(sizeof(*int_cipher));=0A+=0A+=09=09= int_cipher->impl=20=3D=20cipher_ref->impl;=0A+=09=09px_cipher->ptr=20=3D=20= int_cipher;=0A+=09}=0A+=0A+=09*res=20=3D=20px_cipher;=0A+=09return=200;=0A= +}=0Adiff=20--git=20a/contrib/pgcrypto/px.c=20b/contrib/pgcrypto/px.c=0A= index=206a4681dae9..a243f575d3=20100644=0A---=20a/contrib/pgcrypto/px.c=0A= +++=20b/contrib/pgcrypto/px.c=0A@@=20-58,6=20+58,7=20@@=20static=20const=20= struct=20error_desc=20px_err_list[]=20=3D=20{=0A=20=09= {PXE_MCRYPT_INTERNAL,=20"mcrypt=20internal=20error"},=0A=20=09= {PXE_NO_RANDOM,=20"Failed=20to=20generate=20strong=20random=20bits"},=0A=20= =09{PXE_DECRYPT_FAILED,=20"Decryption=20failed"},=0A+=09= {PXE_ENCRYPT_FAILED,=20"Encryption=20failed"},=0A=20=09= {PXE_PGP_CORRUPT_DATA,=20"Wrong=20key=20or=20corrupt=20data"},=0A=20=09= {PXE_PGP_CORRUPT_ARMOR,=20"Corrupt=20ascii-armor"},=0A=20=09= {PXE_PGP_UNSUPPORTED_COMPR,=20"Unsupported=20compression=20algorithm"},=0A= diff=20--git=20a/contrib/pgcrypto/px.h=20b/contrib/pgcrypto/px.h=0Aindex=20= 5487923edb..17d6f22498=20100644=0A---=20a/contrib/pgcrypto/px.h=0A+++=20= b/contrib/pgcrypto/px.h=0A@@=20-61,6=20+61,7=20@@=0A=20#define=20= PXE_MCRYPT_INTERNAL=09=09=09-16=0A=20#define=20PXE_NO_RANDOM=09=09=09=09= -17=0A=20#define=20PXE_DECRYPT_FAILED=09=09=09-18=0A+#define=20= PXE_ENCRYPT_FAILED=09=09=09-19=0A=20=0A=20#define=20PXE_PGP_CORRUPT_DATA=09= =09-100=0A=20#define=20PXE_PGP_CORRUPT_ARMOR=09=09-101=0Adiff=20--git=20= a/contrib/sslinfo/sslinfo.c=20b/contrib/sslinfo/sslinfo.c=0Aindex=20= 5ba3988e27..84bb2c65b8=20100644=0A---=20a/contrib/sslinfo/sslinfo.c=0A= +++=20b/contrib/sslinfo/sslinfo.c=0A@@=20-9,9=20+9,11=20@@=0A=20=0A=20= #include=20"postgres.h"=0A=20=0A+#ifdef=20USE_OPENSSL=0A=20#include=20= =0A=20#include=20=0A=20#include=20= =0A+#endif=0A=20=0A=20#include=20"access/htup_details.h"=0A= =20#include=20"funcapi.h"=0A@@=20-21,8=20+23,8=20@@=0A=20=0A=20= PG_MODULE_MAGIC;=0A=20=0A+#ifdef=20USE_OPENSSL=0A=20static=20Datum=20= X509_NAME_field_to_text(X509_NAME=20*name,=20text=20*fieldName);=0A= -static=20Datum=20X509_NAME_to_text(X509_NAME=20*name);=0A=20static=20= Datum=20ASN1_STRING_to_text(ASN1_STRING=20*str);=0A=20=0A=20/*=0A@@=20= -32,6=20+34,7=20@@=20typedef=20struct=0A=20{=0A=20=09TupleDesc=09= tupdesc;=0A=20}=20SSLExtensionInfoContext;=0A+#endif=0A=20=0A=20/*=0A=20=20= *=20Indicates=20whether=20current=20session=20uses=20SSL=0A@@=20-54,9=20= +57,16=20@@=20PG_FUNCTION_INFO_V1(ssl_version);=0A=20Datum=0A=20= ssl_version(PG_FUNCTION_ARGS)=0A=20{=0A-=09if=20(MyProcPort->ssl=20=3D=3D=20= NULL)=0A+=09const=20char=20*version;=0A+=0A+=09if=20= (!MyProcPort->ssl_in_use)=0A+=09=09PG_RETURN_NULL();=0A+=0A+=09version=20= =3D=20be_tls_get_version(MyProcPort);=0A+=09if=20(version=20=3D=3D=20= NULL)=0A=20=09=09PG_RETURN_NULL();=0A-=09= PG_RETURN_TEXT_P(cstring_to_text(SSL_get_version(MyProcPort->ssl)));=0A+=0A= +=09PG_RETURN_TEXT_P(cstring_to_text(version));=0A=20}=0A=20=0A=20=0A@@=20= -67,9=20+77,16=20@@=20PG_FUNCTION_INFO_V1(ssl_cipher);=0A=20Datum=0A=20= ssl_cipher(PG_FUNCTION_ARGS)=0A=20{=0A-=09if=20(MyProcPort->ssl=20=3D=3D=20= NULL)=0A+=09const=20char=20*cipher;=0A+=0A+=09if=20= (!MyProcPort->ssl_in_use)=0A=20=09=09PG_RETURN_NULL();=0A-=09= PG_RETURN_TEXT_P(cstring_to_text(SSL_get_cipher(MyProcPort->ssl)));=0A+=0A= +=09cipher=20=3D=20be_tls_get_cipher(MyProcPort);=0A+=09if=20(cipher=20= =3D=3D=20NULL)=0A+=09=09PG_RETURN_NULL();=0A+=0A+=09= PG_RETURN_TEXT_P(cstring_to_text(cipher));=0A=20}=0A=20=0A=20=0A@@=20= -83,7=20+100,7=20@@=20PG_FUNCTION_INFO_V1(ssl_client_cert_present);=0A=20= Datum=0A=20ssl_client_cert_present(PG_FUNCTION_ARGS)=0A=20{=0A-=09= PG_RETURN_BOOL(MyProcPort->peer=20!=3D=20NULL);=0A+=09= PG_RETURN_BOOL(MyProcPort->peer_cert_valid);=0A=20}=0A=20=0A=20=0A@@=20= -99,29=20+116,26=20@@=20PG_FUNCTION_INFO_V1(ssl_client_serial);=0A=20= Datum=0A=20ssl_client_serial(PG_FUNCTION_ARGS)=0A=20{=0A+=09char=20= decimal[NAMEDATALEN];=0A=20=09Datum=09=09result;=0A-=09Port=09=20=20=20= *port=20=3D=20MyProcPort;=0A-=09X509=09=20=20=20*peer=20=3D=20= port->peer;=0A-=09ASN1_INTEGER=20*serial=20=3D=20NULL;=0A-=09BIGNUM=09=20= =20=20*b;=0A-=09char=09=20=20=20*decimal;=0A=20=0A-=09if=20(!peer)=0A+=09= if=20(!MyProcPort->ssl_in_use=20||=20!MyProcPort->peer_cert_valid)=0A+=09= =09PG_RETURN_NULL();=0A+=0A+=09be_tls_get_peer_serial(MyProcPort,=20= decimal,=20NAMEDATALEN);=0A+=0A+=09if=20(!*decimal)=0A=20=09=09= PG_RETURN_NULL();=0A-=09serial=20=3D=20X509_get_serialNumber(peer);=0A-=09= b=20=3D=20ASN1_INTEGER_to_BN(serial,=20NULL);=0A-=09decimal=20=3D=20= BN_bn2dec(b);=0A=20=0A-=09BN_free(b);=0A=20=09result=20=3D=20= DirectFunctionCall3(numeric_in,=0A=20=09=09=09=09=09=09=09=09=20= CStringGetDatum(decimal),=0A=20=09=09=09=09=09=09=09=09=20= ObjectIdGetDatum(0),=0A=20=09=09=09=09=09=09=09=09=20Int32GetDatum(-1));=0A= -=09OPENSSL_free(decimal);=0A=20=09return=20result;=0A=20}=0A=20=0A=20=0A= +#ifdef=20USE_OPENSSL=0A=20/*=0A=20=20*=20Converts=20OpenSSL=20= ASN1_STRING=20structure=20into=20text=0A=20=20*=0A@@=20-228,7=20+242,7=20= @@=20ssl_client_dn_field(PG_FUNCTION_ARGS)=0A=20=09text=09=20=20=20= *fieldname=20=3D=20PG_GETARG_TEXT_PP(0);=0A=20=09Datum=09=09result;=0A=20= =0A-=09if=20(!(MyProcPort->peer))=0A+=09if=20(!MyProcPort->ssl_in_use=20= ||=20!MyProcPort->peer_cert_valid)=0A=20=09=09PG_RETURN_NULL();=0A=20=0A=20= =09result=20=3D=20= X509_NAME_field_to_text(X509_get_subject_name(MyProcPort->peer),=20= fieldname);=0A@@=20-273,76=20+287,23=20@@=20= ssl_issuer_field(PG_FUNCTION_ARGS)=0A=20=09else=0A=20=09=09return=20= result;=0A=20}=0A+#endif=09=09=09=09=09=09=09/*=20USE_OPENSSL=20*/=0A=20=0A= -=0A-/*=0A-=20*=20Equivalent=20of=20X509_NAME_oneline=20that=20respects=20= encoding=0A-=20*=0A-=20*=20This=20function=20converts=20X509_NAME=20= structure=20to=20the=20text=20variable=0A-=20*=20converting=20all=20= textual=20data=20into=20current=20database=20encoding.=0A-=20*=0A-=20*=20= Parameter:=20X509_NAME=20*name=20X509_NAME=20structure=20to=20be=20= converted=0A-=20*=0A-=20*=20Returns:=20text=20datum=20which=20contains=20= string=20representation=20of=0A-=20*=20X509_NAME=0A-=20*/=0A-static=20= Datum=0A-X509_NAME_to_text(X509_NAME=20*name)=0A+#ifdef=20USE_NSS=0A= +PG_FUNCTION_INFO_V1(ssl_client_dn_field);=0A+Datum=0A= +ssl_client_dn_field(PG_FUNCTION_ARGS)=0A=20{=0A-=09BIO=09=09=20=20=20= *membuf=20=3D=20BIO_new(BIO_s_mem());=0A-=09int=09=09=09i,=0A-=09=09=09=09= nid,=0A-=09=09=09=09count=20=3D=20X509_NAME_entry_count(name);=0A-=09= X509_NAME_ENTRY=20*e;=0A-=09ASN1_STRING=20*v;=0A-=09const=20char=20= *field_name;=0A-=09size_t=09=09size;=0A-=09char=09=09nullterm;=0A-=09= char=09=20=20=20*sp;=0A-=09char=09=20=20=20*dp;=0A-=09text=09=20=20=20= *result;=0A-=0A-=09if=20(membuf=20=3D=3D=20NULL)=0A-=09=09ereport(ERROR,=0A= -=09=09=09=09(errcode(ERRCODE_OUT_OF_MEMORY),=0A-=09=09=09=09=20= errmsg("could=20not=20create=20OpenSSL=20BIO=20structure")));=0A-=0A-=09= (void)=20BIO_set_close(membuf,=20BIO_CLOSE);=0A-=09for=20(i=20=3D=200;=20= i=20<=20count;=20i++)=0A-=09{=0A-=09=09e=20=3D=20= X509_NAME_get_entry(name,=20i);=0A-=09=09nid=20=3D=20= OBJ_obj2nid(X509_NAME_ENTRY_get_object(e));=0A-=09=09if=20(nid=20=3D=3D=20= NID_undef)=0A-=09=09=09ereport(ERROR,=0A-=09=09=09=09=09= (errcode(ERRCODE_INVALID_PARAMETER_VALUE),=0A-=09=09=09=09=09=20= errmsg("could=20not=20get=20NID=20for=20ASN1_OBJECT=20object")));=0A-=09=09= v=20=3D=20X509_NAME_ENTRY_get_data(e);=0A-=09=09field_name=20=3D=20= OBJ_nid2sn(nid);=0A-=09=09if=20(field_name=20=3D=3D=20NULL)=0A-=09=09=09= field_name=20=3D=20OBJ_nid2ln(nid);=0A-=09=09if=20(field_name=20=3D=3D=20= NULL)=0A-=09=09=09ereport(ERROR,=0A-=09=09=09=09=09= (errcode(ERRCODE_INVALID_PARAMETER_VALUE),=0A-=09=09=09=09=09=20= errmsg("could=20not=20convert=20NID=20%d=20to=20an=20ASN1_OBJECT=20= structure",=20nid)));=0A-=09=09BIO_printf(membuf,=20"/%s=3D",=20= field_name);=0A-=09=09ASN1_STRING_print_ex(membuf,=20v,=0A-=09=09=09=09=09= =09=09=20((ASN1_STRFLGS_RFC2253=20&=20~ASN1_STRFLGS_ESC_MSB)=0A-=09=09=09= =09=09=09=09=20=20|=20ASN1_STRFLGS_UTF8_CONVERT));=0A-=09}=0A-=0A-=09/*=20= ensure=20null=20termination=20of=20the=20BIO's=20content=20*/=0A-=09= nullterm=20=3D=20'\0';=0A-=09BIO_write(membuf,=20&nullterm,=201);=0A-=09= size=20=3D=20BIO_get_mem_data(membuf,=20&sp);=0A-=09dp=20=3D=20= pg_any_to_server(sp,=20size=20-=201,=20PG_UTF8);=0A-=09result=20=3D=20= cstring_to_text(dp);=0A-=09if=20(dp=20!=3D=20sp)=0A-=09=09pfree(dp);=0A-=09= if=20(BIO_free(membuf)=20!=3D=201)=0A-=09=09elog(ERROR,=20"could=20not=20= free=20OpenSSL=20BIO=20structure");=0A+=09PG_RETURN_NULL();=0A+}=0A=20=0A= -=09PG_RETURN_TEXT_P(result);=0A+PG_FUNCTION_INFO_V1(ssl_issuer_field);=0A= +Datum=0A+ssl_issuer_field(PG_FUNCTION_ARGS)=0A+{=0A+=09= PG_RETURN_NULL();=0A=20}=0A+#endif=09=09=09=09=09=09=09/*=20USE_NSS=20*/=0A= =20=0A=20=0A=20/*=0A@@=20-358,9=20+319,17=20@@=20= PG_FUNCTION_INFO_V1(ssl_client_dn);=0A=20Datum=0A=20= ssl_client_dn(PG_FUNCTION_ARGS)=0A=20{=0A-=09if=20(!(MyProcPort->peer))=0A= +=09char=09=09subject[NAMEDATALEN];=0A+=0A+=09if=20= (!MyProcPort->ssl_in_use=20||=20!MyProcPort->peer_cert_valid)=0A+=09=09= PG_RETURN_NULL();=0A+=0A+=09be_tls_get_peer_subject_name(MyProcPort,=20= subject,=20NAMEDATALEN);=0A+=0A+=09if=20(!*subject)=0A=20=09=09= PG_RETURN_NULL();=0A-=09return=20= X509_NAME_to_text(X509_get_subject_name(MyProcPort->peer));=0A+=0A+=09= PG_RETURN_TEXT_P(cstring_to_text(subject));=0A=20}=0A=20=0A=20=0A@@=20= -377,12=20+346,21=20@@=20PG_FUNCTION_INFO_V1(ssl_issuer_dn);=0A=20Datum=0A= =20ssl_issuer_dn(PG_FUNCTION_ARGS)=0A=20{=0A-=09if=20= (!(MyProcPort->peer))=0A+=09char=09=09issuer[NAMEDATALEN];=0A+=0A+=09if=20= (!MyProcPort->ssl_in_use=20||=20!MyProcPort->peer_cert_valid)=0A+=09=09= PG_RETURN_NULL();=0A+=0A+=09be_tls_get_peer_issuer_name(MyProcPort,=20= issuer,=20NAMEDATALEN);=0A+=0A+=09if=20(!*issuer)=0A=20=09=09= PG_RETURN_NULL();=0A-=09return=20= X509_NAME_to_text(X509_get_issuer_name(MyProcPort->peer));=0A+=0A+=09= PG_RETURN_TEXT_P(cstring_to_text(issuer));=0A=20}=0A=20=0A=20=0A+#ifdef=20= USE_OPENSSL=0A=20/*=0A=20=20*=20Returns=20information=20about=20= available=20SSL=20extensions.=0A=20=20*=0A@@=20-516,3=20+494,13=20@@=20= ssl_extension_info(PG_FUNCTION_ARGS)=0A=20=09/*=20All=20done=20*/=0A=20=09= SRF_RETURN_DONE(funcctx);=0A=20}=0A+#endif=09=09=09=09=09=09=09/*=20= USE_OPENSSL=20*/=0A+=0A+#ifdef=20USE_NSS=0A= +PG_FUNCTION_INFO_V1(ssl_extension_info);=0A+Datum=0A= +ssl_extension_info(PG_FUNCTION_ARGS)=0A+{=0A+=09PG_RETURN_NULL();=0A+}=0A= +#endif=09=09=09=09=09=09=09/*=20USE_NSS=20*/=0Adiff=20--git=20= a/doc/src/sgml/pgcrypto.sgml=20b/doc/src/sgml/pgcrypto.sgml=0Aindex=20= 8748c64e2d..f03e1f5fcf=20100644=0A---=20a/doc/src/sgml/pgcrypto.sgml=0A= +++=20b/doc/src/sgml/pgcrypto.sgml=0A@@=20-45,8=20+45,9=20@@=20= digest(data=20bytea,=20type=20text)=20returns=20bytea=0A=20=20=20=20=20= sha224,=20sha256,=0A=20=20=20=20=20= sha384=20and=20sha512.=0A=20=20=20=20= =20If=20pgcrypto=20was=20built=20with=0A-=20=20=20=20= OpenSSL,=20more=20algorithms=20are=20= available,=20as=0A-=20=20=20=20detailed=20in=20.=0A+=20=20=20=20= OpenSSL=20or=20= NSS,=0A+=20=20=20=20more=20algorithms=20are=20= available,=20as=0A+=20=20=20=20detailed=20in=20.=0A=20=20=20=20=0A= =20=0A=20=20=20=20=0A@@=20-763,7=20+764,7=20@@=20= pgp_sym_encrypt(data,=20psw,=20'compress-algo=3D1,=20= cipher-algo=3Daes256')=0A=20=20=20=20=20Which=20cipher=20algorithm=20to=20= use.=0A=20=20=20=20=0A=20=0A-Values:=20bf,=20= aes128,=20aes192,=20aes256=20(OpenSSL-only:=203des,=20= cast5)=0A+Values:=20bf,=20aes128,=20aes192,=20aes256=20= (OpenSSL-only:=203des,=20cast5;=20= NSS-only:=203des)=0A=20Default:=20aes128=0A=20Applies=20= to:=20pgp_sym_encrypt,=20pgp_pub_encrypt=0A=20=0A@@=20= -1152,8=20+1153,8=20@@=20gen_random_uuid()=20returns=20uuid=0A=20=20=20=20= =0A=20=20=20=20=20pgcrypto=20configures=20= itself=20according=20to=20the=20findings=20of=20the=0A=20=20=20=20=20= main=20PostgreSQL=20configure=20script.=20=20The=20= options=20that=0A-=20=20=20=20affect=20it=20are=20= --with-zlib=20and=0A-=20=20=20=20= --with-openssl.=0A+=20=20=20=20affect=20it=20are=20= --with-zlib,=0A+=20=20=20=20= --with-openssl=20and=20--with-nss.=0A= =20=20=20=20=0A=20=0A=20=20=20=20=0A@@=20-1168,14=20= +1169,16=20@@=20gen_random_uuid()=20returns=20uuid=0A=20=20=20=20=20= BIGNUM=20functions.=0A=20=20=20=20=0A=20=0A-=20=20=20=0A-=20=20=20=20Summary=20of=20= Functionality=20with=20and=20without=20OpenSSL=0A-=20=20=20=20= =0A+=20=20=20=0A+=20=20=20=20Summary=20= of=20Functionality=20with=20and=20without=20external=20cryptographic=0A+=20= =20=20=20=20=20library=0A+=20=20=20=20=0A=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20= =20Functionality=0A=20=20=20=20=20=20=20=20= Built-in=0A=20=20=20=20=20=20=20=20With=20= OpenSSL=0A+=20=20=20=20=20=20=20With=20NSS=0A=20=20= =20=20=20=20=20=0A=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A@@=20-1183,51=20+1186,67=20@@=20gen_random_uuid()=20returns=20= uuid=0A=20=20=20=20=20=20=20=20MD5=0A=20=20=20=20=20=20=20= =20yes=0A=20=20=20=20=20=20=20=20yes=0A+=20= =20=20=20=20=20=20yes=0A=20=20=20=20=20=20=20=0A=20=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20=20SHA1=0A=20=20= =20=20=20=20=20=20yes=0A=20=20=20=20=20=20=20=20= yes=0A+=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20= SHA224/256/384/512=0A=20=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=20yes=0A+=20=20= =20=20=20=20=20yes=0A=20=20=20=20=20=20=20=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=20Other=20digest=20= algorithms=0A=20=20=20=20=20=20=20=20no=0A=20=20=20= =20=20=20=20=20yes=20(Note=201)=0A+=20=20=20=20=20=20=20= yes=20(Note=201)=0A=20=20=20=20=20=20=20=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=20Blowfish=0A=20= =20=20=20=20=20=20=20yes=0A=20=20=20=20=20=20=20=20= yes=0A+=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20= AES=0A=20=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=20yes=0A+=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20DES/3DES/CAST5=0A=20=20=20= =20=20=20=20=20no=0A=20=20=20=20=20=20=20=20= yes=0A+=20=20=20=20=20=20=20yes=0A+=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= CAST5=0A+=20=20=20=20=20=20=20no=0A+=20=20=20= =20=20=20=20yes=0A+=20=20=20=20=20=20=20no=0A= =20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20= =20=20=20Raw=20encryption=0A=20=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=20yes=0A+=20=20= =20=20=20=20=20yes=0A=20=20=20=20=20=20=20=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=20PGP=20Symmetric=20= encryption=0A=20=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=20yes=0A+=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20PGP=20Public-Key=20= encryption=0A=20=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=20yes=0A+=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A=20=20=20=20=20=0A@@=20-1240,7=20+1259,8=20@@=20= gen_random_uuid()=20returns=20uuid=0A=20=20=20=20=0A=20=20=20= =20=20=0A=20=20=20=20=20=20=0A-=20=20=20=20=20=20Any=20= digest=20algorithm=20OpenSSL=20supports=0A+=20= =20=20=20=20=20Any=20digest=20algorithm=20= OpenSSL=20and=0A+=20=20=20=20=20=20= NSS=20supports=0A=20=20=20=20=20=20=20is=20= automatically=20picked=20up.=0A=20=20=20=20=20=20=20This=20is=20not=20= possible=20with=20ciphers,=20which=20need=20to=20be=20supported=0A=20=20=20= =20=20=20=20explicitly.=0Adiff=20--git=20a/doc/src/sgml/sslinfo.sgml=20= b/doc/src/sgml/sslinfo.sgml=0Aindex=20e16f61b41d..e8a4e7b332=20100644=0A= ---=20a/doc/src/sgml/sslinfo.sgml=0A+++=20b/doc/src/sgml/sslinfo.sgml=0A= @@=20-22,7=20+22,8=20@@=0A=20=0A=20=20=0A=20=20=20This=20extension=20= won't=20build=20at=20all=20unless=20the=20installation=20was=0A-=20=20= configured=20with=20--with-openssl.=0A+=20=20= configured=20with=20SSL=20support,=20such=20as=20= --with-openssl=0A+=20=20or=20= --with-nss.=0A=20=20=0A=20=0A=20=20=0A= @@=20-208,6=20+209,9=20@@=20emailAddress=0A=20=20=20=20=20=20the=20X.500=20= and=20X.509=20standards,=20so=20you=20cannot=20just=20assign=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=20only=20available=20= when=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=20= ssl_client_dn_field,=20but=20for=20the=20= certificate=20issuer=0A=20=20=20=20=20=20rather=20than=20the=20= certificate=20subject.=0A=20=20=20=20=20=0A+=20=20=20=20=0A= +=20=20=20=20=20This=20function=20is=20only=20available=20when=20using=20= OpenSSL.=0A+=20=20=20=20=0A=20=20=20=20= =20=0A=20=20=20=20=0A=20=0A@@=20-238,6=20= +245,9=20@@=20emailAddress=0A=20=20=20=20=20=20Provide=20information=20= about=20extensions=20of=20client=20certificate:=20extension=20name,=0A=20= =20=20=20=20=20extension=20value,=20and=20if=20it=20is=20a=20critical=20= extension.=0A=20=20=20=20=20=0A+=20=20=20=20=0A+=20=20=20=20= =20This=20function=20is=20only=20available=20when=20using=20= OpenSSL.=0A+=20=20=20=20=0A=20=20=20=20= =20=0A=20=20=20=20=0A=20=20=20=0A= diff=20--git=20a/src/tools/msvc/Install.pm=20b/src/tools/msvc/Install.pm=0A= index=20ea3af48777..afe72a7e97=20100644=0A---=20= a/src/tools/msvc/Install.pm=0A+++=20b/src/tools/msvc/Install.pm=0A@@=20= -438,7=20+438,8=20@@=20sub=20CopyContribFiles=0A=20=09=09{=0A=20=09=09=09= #=20These=20configuration-based=20exclusions=20must=20match=20= vcregress.pl=0A=20=09=09=09next=20if=20($d=20eq=20"uuid-ossp"=20=20&&=20= !defined($config->{uuid}));=0A-=09=09=09next=20if=20($d=20eq=20"sslinfo"=20= =20=20=20&&=20!defined($config->{openssl}));=0A+=09=09=09next=20if=20($d=20= eq=20"sslinfo"=20=20=20=20&&=20!defined($config->{openssl})=0A+=09=09=09=20= =20&&=20!defined($config->{nss}));=0A=20=09=09=09next=20if=20($d=20eq=20= "xml2"=20=20=20=20=20=20=20&&=20!defined($config->{xml}));=0A=20=09=09=09= next=20if=20($d=20=3D~=20/_plperl$/=20=20=20&&=20= !defined($config->{perl}));=0A=20=09=09=09next=20if=20($d=20=3D~=20= /_plpython$/=20&&=20!defined($config->{python}));=0Adiff=20--git=20= a/src/tools/msvc/Mkvcbuild.pm=20b/src/tools/msvc/Mkvcbuild.pm=0Aindex=20= 29879b51af..379f861a56=20100644=0A---=20a/src/tools/msvc/Mkvcbuild.pm=0A= +++=20b/src/tools/msvc/Mkvcbuild.pm=0A@@=20-442,9=20+442,14=20@@=20sub=20= mkvcbuild=0A=20=09=09push=20@contrib_excludes,=20'xml2';=0A=20=09}=0A=20=0A= +=09if=20(!$solution->{options}->{openssl}=20&&=20= !$solution->{options}->{nss})=0A+=09{=0A+=09=09push=20@contrib_excludes,=20= 'sslinfo';=0A+=09}=0A+=0A=20=09if=20(!$solution->{options}->{openssl})=0A= =20=09{=0A-=09=09push=20@contrib_excludes,=20'sslinfo',=20= 'ssl_passphrase_callback';=0A+=09=09push=20@contrib_excludes,=20= 'ssl_passphrase_callback';=0A=20=09}=0A=20=0A=20=09if=20= (!$solution->{options}->{uuid})=0A@@=20-474,6=20+479,11=20@@=20sub=20= mkvcbuild=0A=20=09=09$pgcrypto->AddFiles('contrib/pgcrypto',=20= 'openssl.c',=0A=20=09=09=09'pgp-mpi-openssl.c');=0A=20=09}=0A+=09elsif=20= ($solution->{options}->{nss})=0A+=09{=0A+=09=09= $pgcrypto->AddFiles('contrib/pgcrypto',=20'nss.c',=0A+=09=09=09= 'pgp-mpi-internal.c',=20'imath.c',=20'blf.c');=0A+=09}=0A=20=09else=0A=20= =09{=0A=20=09=09$pgcrypto->AddFiles(=0A--=20=0A2.21.1=20(Apple=20= Git-122.3)=0A=0A= --Apple-Mail=_C39967DC-7CE2-4297-8DC3-75F0E858FBDB Content-Disposition: attachment; filename=v15-0006-NSS-to-be-submitted-separately.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v15-0006-NSS-to-be-submitted-separately.patch" Content-Transfer-Encoding: quoted-printable =46rom=20ef84f48a34d3076c4706b414033f1a388be8c990=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Wed,=2028=20Oct=202020=2011:35:06=20+0100=0ASubject:=20[PATCH=20= v15=206/6]=20NSS=20to=20be=20submitted=20separately=0A=0A---=0A=20= contrib/pgcrypto/openssl.c=20=20=20=20=20=20=20=20=20=20=20=20|=20=202=20= +-=0A=20doc/src/sgml/sslinfo.sgml=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=202=20+-=0A=20src/backend/libpq/be-secure-openssl.c=20|=2016=20= +++++++++++++++-=0A=203=20files=20changed,=2017=20insertions(+),=203=20= deletions(-)=0A=0Adiff=20--git=20a/contrib/pgcrypto/openssl.c=20= b/contrib/pgcrypto/openssl.c=0Aindex=20ed96e4ce53..5ebe213406=20100644=0A= ---=20a/contrib/pgcrypto/openssl.c=0A+++=20b/contrib/pgcrypto/openssl.c=0A= @@=20-400,7=20+400,7=20@@=20gen_ossl_encrypt(PX_Cipher=20*c,=20const=20= uint8=20*data,=20unsigned=20dlen,=0A=20=09}=0A=20=0A=20=09if=20= (!EVP_EncryptUpdate(od->evp_ctx,=20res,=20&outlen,=20data,=20dlen))=0A-=09= =09return=20PXE_ERR_GENERIC;=0A+=09=09return=20PXE_ENCRYPT_FAILED;=0A=20=0A= =20=09return=200;=0A=20}=0Adiff=20--git=20a/doc/src/sgml/sslinfo.sgml=20= b/doc/src/sgml/sslinfo.sgml=0Aindex=20e8a4e7b332..253bb697af=20100644=0A= ---=20a/doc/src/sgml/sslinfo.sgml=0A+++=20b/doc/src/sgml/sslinfo.sgml=0A= @@=20-55,7=20+55,7=20@@=0A=20=20=20=20=20=0A=20=20=20=20=20= =0A=20=20=20=20=20=20Returns=20the=20name=20of=20the=20protocol=20= used=20for=20the=20SSL=20connection=20(e.g.,=20TLSv1.0=0A-=20=20=20=20=20= TLSv1.1,=20or=20TLSv1.2).=0A+=20=20=20=20=20TLSv1.1,=20TLSv1.2=20or=20= TLSv1.3).=0A=20=20=20=20=20=0A=20=20=20=20=20=0A=20=20=20= =20=0Adiff=20--git=20= a/src/backend/libpq/be-secure-openssl.c=20= b/src/backend/libpq/be-secure-openssl.c=0Aindex=208b21ff4065..5962cffc0c=20= 100644=0A---=20a/src/backend/libpq/be-secure-openssl.c=0A+++=20= b/src/backend/libpq/be-secure-openssl.c=0A@@=20-1298,15=20+1298,28=20@@=20= X509_NAME_to_cstring(X509_NAME=20*name)=0A=20=09char=09=20=20=20*dp;=0A=20= =09char=09=20=20=20*result;=0A=20=0A+=09if=20(membuf=20=3D=3D=20NULL)=0A= +=09=09ereport(ERROR,=0A+=09=09=09=09(errcode(ERRCODE_OUT_OF_MEMORY),=0A= +=09=09=09=09=20errmsg("failed=20to=20create=20BIO")));=0A+=0A=20=09= (void)=20BIO_set_close(membuf,=20BIO_CLOSE);=0A=20=09for=20(i=20=3D=200;=20= i=20<=20count;=20i++)=0A=20=09{=0A=20=09=09e=20=3D=20= X509_NAME_get_entry(name,=20i);=0A=20=09=09nid=20=3D=20= OBJ_obj2nid(X509_NAME_ENTRY_get_object(e));=0A+=09=09if=20(nid=20=3D=3D=20= NID_undef)=0A+=09=09=09ereport(ERROR,=0A+=09=09=09=09=09= (errcode(ERRCODE_INVALID_PARAMETER_VALUE),=0A+=09=09=09=09=09=20= errmsg("could=20not=20get=20NID=20for=20ASN1_OBJECT=20object")));=0A=20=09= =09v=20=3D=20X509_NAME_ENTRY_get_data(e);=0A=20=09=09field_name=20=3D=20= OBJ_nid2sn(nid);=0A=20=09=09if=20(!field_name)=0A=20=09=09=09field_name=20= =3D=20OBJ_nid2ln(nid);=0A+=09=09if=20(field_name=20=3D=3D=20NULL)=0A+=09=09= =09ereport(ERROR,=0A+=09=09=09=09=09= (errcode(ERRCODE_INVALID_PARAMETER_VALUE),=0A+=09=09=09=09=09=20= errmsg("could=20not=20convert=20NID=20%d=20to=20an=20ASN1_OBJECT=20= structure",=20nid)));=0A=20=09=09BIO_printf(membuf,=20"/%s=3D",=20= field_name);=0A=20=09=09ASN1_STRING_print_ex(membuf,=20v,=0A=20=09=09=09=09= =09=09=09=20((ASN1_STRFLGS_RFC2253=20&=20~ASN1_STRFLGS_ESC_MSB)=0A@@=20= -1322,7=20+1335,8=20@@=20X509_NAME_to_cstring(X509_NAME=20*name)=0A=20=09= result=20=3D=20pstrdup(dp);=0A=20=09if=20(dp=20!=3D=20sp)=0A=20=09=09= pfree(dp);=0A-=09BIO_free(membuf);=0A+=09if=20(BIO_free(membuf)=20!=3D=20= 1)=0A+=09=09elog(ERROR,=20"could=20not=20free=20OpenSSL=20BIO=20= structure");=0A=20=0A=20=09return=20result;=0A=20}=0A--=20=0A2.21.1=20= (Apple=20Git-122.3)=0A=0A= --Apple-Mail=_C39967DC-7CE2-4297-8DC3-75F0E858FBDB--