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 1lEBJB-0000GM-7v for pgsql-hackers@arkaria.postgresql.org; Mon, 22 Feb 2021 13:31:30 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1lEBJ8-0003Sa-Iv for pgsql-hackers@arkaria.postgresql.org; Mon, 22 Feb 2021 13:31:26 +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 1lEBJ7-0003Pn-K7 for pgsql-hackers@lists.postgresql.org; Mon, 22 Feb 2021 13:31:26 +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 1lEBJ2-0001m2-8r for pgsql-hackers@lists.postgresql.org; Mon, 22 Feb 2021 13:31:24 +0000 Received: from s807.loopia.se (localhost [127.0.0.1]) by s807.loopia.se (Postfix) with ESMTP id BD70C10CBDD6 for ; Mon, 22 Feb 2021 14:31:15 +0100 (CET) Received: from s645.loopia.se (unknown [172.22.191.6]) by s807.loopia.se (Postfix) with ESMTP id 9B65E2E279C3; Mon, 22 Feb 2021 14:31:15 +0100 (CET) Received: from s475.loopia.se (unknown [172.22.191.5]) by s645.loopia.se (Postfix) with ESMTP id 7CBF11579EEE; Mon, 22 Feb 2021 14:31:15 +0100 (CET) X-Virus-Scanned: amavisd-new at amavis.loopia.se X-Spam-Flag: NO X-Spam-Score: -1 X-Spam-Level: X-Spam-Status: No, score=-1 tagged_above=-999 required=6.2 tests=[ALL_TRUSTED=-1] autolearn=disabled Received: from s499.loopia.se ([172.22.191.5]) by s475.loopia.se (s475.loopia.se [172.22.190.15]) (amavisd-new, port 10024) with UTF8LMTP id YyvhKJ2ISqlI; Mon, 22 Feb 2021 14:31:14 +0100 (CET) X-Loopia-Auth: user X-Loopia-User: daniel@yesql.se X-Loopia-Originating-IP: 89.255.232.193 Received: from [192.168.72.43] (customer-89-255-232-193.stosn.net [89.255.232.193]) (Authenticated sender: daniel@yesql.se) by s499.loopia.se (Postfix) with ESMTPSA id CA1C71CE61EB; Mon, 22 Feb 2021 14:31:13 +0100 (CET) From: Daniel Gustafsson Message-Id: Content-Type: multipart/mixed; boundary="Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5" Mime-Version: 1.0 (Mac OS X Mail 12.4 \(3445.104.17\)) Subject: Re: Support for NSS as a libpq TLS backend Date: Mon, 22 Feb 2021 14:31:13 +0100 In-Reply-To: <686dd2b189ec04b161f71481f1f726255ee8224f.camel@vmware.com> Cc: "michael@paquier.xyz" , "hlinnaka@iki.fi" , "pgsql-hackers@lists.postgresql.org" , "andrew.dunstan@2ndquadrant.com" , "thomas.munro@gmail.com" , "andres@anarazel.de" , "sfrost@snowman.net" To: Jacob Champion References: <8D7F95DB-8F8A-4300-BFDA-656FBAB30FE2@yesql.se> <5382CB4A-9CF3-4145-BA46-C802615935E0@yesql.se> <6C7A2D6A-3D05-4C3B-B1DA-C96E97F31AC6@yesql.se> <0F5CF84D-26F1-44D0-AEAE-E011D3CEC0E2@yesql.se> <686dd2b189ec04b161f71481f1f726255ee8224f.camel@vmware.com> X-Mailer: Apple Mail (2.3445.104.17) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii > On 18 Feb 2021, at 21:33, Jacob Champion wrote: >=20 > On Wed, 2021-02-17 at 22:35 +0100, Daniel Gustafsson wrote: >> Attached is a rebase on top of this and the recent cryptohash changes = to pass >> in buffer lengths to the _final function. On top of that, I fixed up = and >> expanded the documentation, improved SCRAM handling (by using NSS = digest >> operations which are better suited) and reworded and expanded = comments. This >> patch version is, I think, feature complete with the OpenSSL = implementation. >=20 > fe-secure-nss.c is no longer compiling as of this patchset; looks > like pgtls_open_client() has a truncated statement. Ouch, I had a local mismerge that snuck in as I moved the branch around = for submission here. The attached fixes that as well as implements the = sslcrldir support that was committed recently. The crldir parameter isn't = applicable to NSS per se since all CRL's are loaded into the NSS database, but it does = need to be supported for the tests. The crldir commit also made similar changes to the test harness as I had = done to support the NSS database, which made these incompatible. To fix that = I've implemented named parameters in switch_server_cert to make it less magic = with multiple optional parameters. -- Daniel Gustafsson https://vmware.com/ --Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5 Content-Disposition: attachment; filename=v28-0009-nss-Build-infrastructure.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v28-0009-nss-Build-infrastructure.patch" Content-Transfer-Encoding: quoted-printable =46rom=2035bf6312fb855d4dd18da3614d0c6b5881e4157d=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:55=20+0100=0ASubject:=20[PATCH=20= v28=209/9]=20nss:=20Build=20infrastructure=0A=0AFinally=20this=20adds=20= the=20infrastructure=20to=20build=20a=20postgres=20installation=0Awith=20= libnss=20support.=0A---=0A=20configure=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20294=20+++++++++++++++++++++++++++++++++-=0A= =20configure.ac=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20= =2031=20+++-=0A=20src/backend/libpq/Makefile=20=20=20=20|=20=20=204=20+=0A= =20src/common/Makefile=20=20=20=20=20=20=20=20=20=20=20|=20=20=206=20+=0A= =20src/include/pg_config.h.in=20=20=20=20|=20=2012=20++=0A=20= src/interfaces/libpq/Makefile=20|=20=20=205=20+=0A=20= src/tools/msvc/Install.pm=20=20=20=20=20|=20=20=203=20+-=0A=20= src/tools/msvc/Mkvcbuild.pm=20=20=20|=20=2039=20++++-=0A=20= src/tools/msvc/Solution.pm=20=20=20=20|=20=2020=20+++=0A=209=20files=20= changed,=20402=20insertions(+),=2012=20deletions(-)=0A=0Adiff=20--git=20= a/configure=20b/configure=0Aindex=20ce9ea36999..143726c79c=20100755=0A= ---=20a/configure=0A+++=20b/configure=0A@@=20-654,6=20+654,8=20@@=20= UUID_LIBS=0A=20LDAP_LIBS_BE=0A=20LDAP_LIBS_FE=0A=20with_ssl=0A= +NSPR_CONFIG=0A+NSS_CONFIG=0A=20PTHREAD_CFLAGS=0A=20PTHREAD_LIBS=0A=20= PTHREAD_CC=0A@@=20-1570,7=20+1572,7=20@@=20Optional=20Packages:=0A=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= use=20system=20time=20zone=20data=20in=20DIR=0A=20=20=20--without-zlib=20= =20=20=20=20=20=20=20=20=20do=20not=20use=20Zlib=0A=20=20=20= --with-gnu-ld=20=20=20=20=20=20=20=20=20=20=20assume=20the=20C=20= compiler=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=20support=20(openssl)=0A= +=20=20--with-ssl=3DLIB=20=20=20=20=20=20=20=20=20=20use=20LIB=20for=20= SSL/TLS=20support=20(openssl,=20nss)=0A=20=20=20--with-openssl=20=20=20=20= =20=20=20=20=20=20obsolete=20spelling=20of=20--with-ssl=3Dopenssl=0A=20=0A= =20Some=20influential=20environment=20variables:=0A@@=20-12462,8=20= +12464,274=20@@=20done=0A=20=0A=20$as_echo=20"#define=20USE_OPENSSL=201"=20= >>confdefs.h=0A=20=0A+elif=20test=20"$with_ssl"=20=3D=20nss=20;=20then=0A= +=20=20#=20TODO:=20fallback=20in=20case=20nss-config/nspr-config=20= aren't=20found.=0A+=20=20if=20test=20-z=20"$NSS_CONFIG";=20then=0A+=20=20= for=20ac_prog=20in=20nss-config=0A+do=0A+=20=20#=20Extract=20the=20first=20= word=20of=20"$ac_prog",=20so=20it=20can=20be=20a=20program=20name=20with=20= args.=0A+set=20dummy=20$ac_prog;=20ac_word=3D$2=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20$ac_word"=20>&5=0A= +$as_echo_n=20"checking=20for=20$ac_word...=20"=20>&6;=20}=0A+if=20= ${ac_cv_path_NSS_CONFIG+:}=20false;=20then=20:=0A+=20=20$as_echo_n=20= "(cached)=20"=20>&6=0A+else=0A+=20=20case=20$NSS_CONFIG=20in=0A+=20=20= [\\/]*=20|=20?:[\\/]*)=0A+=20=20ac_cv_path_NSS_CONFIG=3D"$NSS_CONFIG"=20= #=20Let=20the=20user=20override=20the=20test=20with=20a=20path.=0A+=20=20= ;;=0A+=20=20*)=0A+=20=20as_save_IFS=3D$IFS;=20IFS=3D$PATH_SEPARATOR=0A= +for=20as_dir=20in=20$PATH=0A+do=0A+=20=20IFS=3D$as_save_IFS=0A+=20=20= test=20-z=20"$as_dir"=20&&=20as_dir=3D.=0A+=20=20=20=20for=20ac_exec_ext=20= in=20''=20$ac_executable_extensions;=20do=0A+=20=20if=20= as_fn_executable_p=20"$as_dir/$ac_word$ac_exec_ext";=20then=0A+=20=20=20=20= ac_cv_path_NSS_CONFIG=3D"$as_dir/$ac_word$ac_exec_ext"=0A+=20=20=20=20= $as_echo=20"$as_me:${as_lineno-$LINENO}:=20found=20= $as_dir/$ac_word$ac_exec_ext"=20>&5=0A+=20=20=20=20break=202=0A+=20=20fi=0A= +done=0A+=20=20done=0A+IFS=3D$as_save_IFS=0A+=0A+=20=20;;=0A+esac=0A+fi=0A= +NSS_CONFIG=3D$ac_cv_path_NSS_CONFIG=0A+if=20test=20-n=20"$NSS_CONFIG";=20= then=0A+=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20= $NSS_CONFIG"=20>&5=0A+$as_echo=20"$NSS_CONFIG"=20>&6;=20}=0A+else=0A+=20=20= {=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20no"=20>&5=0A= +$as_echo=20"no"=20>&6;=20}=0A+fi=0A+=0A+=0A+=20=20test=20-n=20= "$NSS_CONFIG"=20&&=20break=0A+done=0A+=0A+else=0A+=20=20#=20Report=20the=20= value=20of=20NSS_CONFIG=20in=20configure's=20output=20in=20all=20cases.=0A= +=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20checking=20for=20= NSS_CONFIG"=20>&5=0A+$as_echo_n=20"checking=20for=20NSS_CONFIG...=20"=20= >&6;=20}=0A+=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20= $NSS_CONFIG"=20>&5=0A+$as_echo=20"$NSS_CONFIG"=20>&6;=20}=0A+fi=0A+=0A+=20= =20if=20test=20-z=20"$NSPR_CONFIG";=20then=0A+=20=20for=20ac_prog=20in=20= nspr-config=0A+do=0A+=20=20#=20Extract=20the=20first=20word=20of=20= "$ac_prog",=20so=20it=20can=20be=20a=20program=20name=20with=20args.=0A= +set=20dummy=20$ac_prog;=20ac_word=3D$2=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20$ac_word"=20>&5=0A= +$as_echo_n=20"checking=20for=20$ac_word...=20"=20>&6;=20}=0A+if=20= ${ac_cv_path_NSPR_CONFIG+:}=20false;=20then=20:=0A+=20=20$as_echo_n=20= "(cached)=20"=20>&6=0A+else=0A+=20=20case=20$NSPR_CONFIG=20in=0A+=20=20= [\\/]*=20|=20?:[\\/]*)=0A+=20=20ac_cv_path_NSPR_CONFIG=3D"$NSPR_CONFIG"=20= #=20Let=20the=20user=20override=20the=20test=20with=20a=20path.=0A+=20=20= ;;=0A+=20=20*)=0A+=20=20as_save_IFS=3D$IFS;=20IFS=3D$PATH_SEPARATOR=0A= +for=20as_dir=20in=20$PATH=0A+do=0A+=20=20IFS=3D$as_save_IFS=0A+=20=20= test=20-z=20"$as_dir"=20&&=20as_dir=3D.=0A+=20=20=20=20for=20ac_exec_ext=20= in=20''=20$ac_executable_extensions;=20do=0A+=20=20if=20= as_fn_executable_p=20"$as_dir/$ac_word$ac_exec_ext";=20then=0A+=20=20=20=20= ac_cv_path_NSPR_CONFIG=3D"$as_dir/$ac_word$ac_exec_ext"=0A+=20=20=20=20= $as_echo=20"$as_me:${as_lineno-$LINENO}:=20found=20= $as_dir/$ac_word$ac_exec_ext"=20>&5=0A+=20=20=20=20break=202=0A+=20=20fi=0A= +done=0A+=20=20done=0A+IFS=3D$as_save_IFS=0A+=0A+=20=20;;=0A+esac=0A+fi=0A= +NSPR_CONFIG=3D$ac_cv_path_NSPR_CONFIG=0A+if=20test=20-n=20= "$NSPR_CONFIG";=20then=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20$NSPR_CONFIG"=20>&5=0A= +$as_echo=20"$NSPR_CONFIG"=20>&6;=20}=0A+else=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20no"=20>&5=0A+$as_echo=20"no"=20= >&6;=20}=0A+fi=0A+=0A+=0A+=20=20test=20-n=20"$NSPR_CONFIG"=20&&=20break=0A= +done=0A+=0A+else=0A+=20=20#=20Report=20the=20value=20of=20NSPR_CONFIG=20= in=20configure's=20output=20in=20all=20cases.=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20NSPR_CONFIG"=20>&5=0A= +$as_echo_n=20"checking=20for=20NSPR_CONFIG...=20"=20>&6;=20}=0A+=20=20{=20= $as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20$NSPR_CONFIG"=20>&5=0A= +$as_echo=20"$NSPR_CONFIG"=20>&6;=20}=0A+fi=0A+=0A+=20=20if=20test=20-n=20= "$NSS_CONFIG";=20then=0A+=20=20=20=20NSS_LIBS=3D`$NSS_CONFIG=20--libs`=0A= +=09NSS_CFLAGS=3D`$NSS_CONFIG=20--cflags`=0A+=20=20fi=0A+=20=20if=20test=20= -n=20"$NSPR_CONFIG";=20then=0A+=09NSPR_LIBS=3D`$NSPR_CONFIG=20--libs`=0A= +=09NSPR_CFLAGS=3D`$NSPR_CONFIG=20--cflags`=0A+=20=20fi=0A+=0A+=20=20= LDFLAGS=3D"$LDFLAGS=20$NSS_LIBS=20$NSPR_LIBS"=0A+=20=20CFLAGS=3D"$CFLAGS=20= $NSS_CFLAGS=20$NSPR_CFLAGS"=0A+=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20NSS_InitContext=20in=20= -lnss3"=20>&5=0A+$as_echo_n=20"checking=20for=20NSS_InitContext=20in=20= -lnss3...=20"=20>&6;=20}=0A+if=20${ac_cv_lib_nss3_NSS_InitContext+:}=20= false;=20then=20:=0A+=20=20$as_echo_n=20"(cached)=20"=20>&6=0A+else=0A+=20= =20ac_check_lib_save_LIBS=3D$LIBS=0A+LIBS=3D"-lnss3=20=20$LIBS"=0A+cat=20= confdefs.h=20-=20<<_ACEOF=20>conftest.$ac_ext=0A+/*=20end=20confdefs.h.=20= =20*/=0A+=0A+/*=20Override=20any=20GCC=20internal=20prototype=20to=20= avoid=20an=20error.=0A+=20=20=20Use=20char=20because=20int=20might=20= match=20the=20return=20type=20of=20a=20GCC=0A+=20=20=20builtin=20and=20= then=20its=20argument=20prototype=20would=20still=20apply.=20=20*/=0A= +#ifdef=20__cplusplus=0A+extern=20"C"=0A+#endif=0A+char=20= NSS_InitContext=20();=0A+int=0A+main=20()=0A+{=0A+return=20= NSS_InitContext=20();=0A+=20=20;=0A+=20=20return=200;=0A+}=0A+_ACEOF=0A= +if=20ac_fn_c_try_link=20"$LINENO";=20then=20:=0A+=20=20= ac_cv_lib_nss3_NSS_InitContext=3Dyes=0A+else=0A+=20=20= ac_cv_lib_nss3_NSS_InitContext=3Dno=0A+fi=0A+rm=20-f=20core=20= conftest.err=20conftest.$ac_objext=20\=0A+=20=20=20=20conftest$ac_exeext=20= conftest.$ac_ext=0A+LIBS=3D$ac_check_lib_save_LIBS=0A+fi=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20= $ac_cv_lib_nss3_NSS_InitContext"=20>&5=0A+$as_echo=20= "$ac_cv_lib_nss3_NSS_InitContext"=20>&6;=20}=0A+if=20test=20= "x$ac_cv_lib_nss3_NSS_InitContext"=20=3D=20xyes;=20then=20:=0A+=20=20cat=20= >>confdefs.h=20<<_ACEOF=0A+#define=20HAVE_LIBNSS3=201=0A+_ACEOF=0A+=0A+=20= =20LIBS=3D"-lnss3=20$LIBS"=0A+=0A+else=0A+=20=20as_fn_error=20$?=20= "library=20'nss3'=20is=20required=20for=20NSS"=20"$LINENO"=205=0A+fi=0A+=0A= +=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20checking=20for=20= PR_GetDefaultIOMethods=20in=20-lnspr4"=20>&5=0A+$as_echo_n=20"checking=20= for=20PR_GetDefaultIOMethods=20in=20-lnspr4...=20"=20>&6;=20}=0A+if=20= ${ac_cv_lib_nspr4_PR_GetDefaultIOMethods+:}=20false;=20then=20:=0A+=20=20= $as_echo_n=20"(cached)=20"=20>&6=0A+else=0A+=20=20= ac_check_lib_save_LIBS=3D$LIBS=0A+LIBS=3D"-lnspr4=20=20$LIBS"=0A+cat=20= confdefs.h=20-=20<<_ACEOF=20>conftest.$ac_ext=0A+/*=20end=20confdefs.h.=20= =20*/=0A+=0A+/*=20Override=20any=20GCC=20internal=20prototype=20to=20= avoid=20an=20error.=0A+=20=20=20Use=20char=20because=20int=20might=20= match=20the=20return=20type=20of=20a=20GCC=0A+=20=20=20builtin=20and=20= then=20its=20argument=20prototype=20would=20still=20apply.=20=20*/=0A= +#ifdef=20__cplusplus=0A+extern=20"C"=0A+#endif=0A+char=20= PR_GetDefaultIOMethods=20();=0A+int=0A+main=20()=0A+{=0A+return=20= PR_GetDefaultIOMethods=20();=0A+=20=20;=0A+=20=20return=200;=0A+}=0A= +_ACEOF=0A+if=20ac_fn_c_try_link=20"$LINENO";=20then=20:=0A+=20=20= ac_cv_lib_nspr4_PR_GetDefaultIOMethods=3Dyes=0A+else=0A+=20=20= ac_cv_lib_nspr4_PR_GetDefaultIOMethods=3Dno=0A+fi=0A+rm=20-f=20core=20= conftest.err=20conftest.$ac_objext=20\=0A+=20=20=20=20conftest$ac_exeext=20= conftest.$ac_ext=0A+LIBS=3D$ac_check_lib_save_LIBS=0A+fi=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20= $ac_cv_lib_nspr4_PR_GetDefaultIOMethods"=20>&5=0A+$as_echo=20= "$ac_cv_lib_nspr4_PR_GetDefaultIOMethods"=20>&6;=20}=0A+if=20test=20= "x$ac_cv_lib_nspr4_PR_GetDefaultIOMethods"=20=3D=20xyes;=20then=20:=0A+=20= =20cat=20>>confdefs.h=20<<_ACEOF=0A+#define=20HAVE_LIBNSPR4=201=0A= +_ACEOF=0A+=0A+=20=20LIBS=3D"-lnspr4=20$LIBS"=0A+=0A+else=0A+=20=20= as_fn_error=20$?=20"library=20'nspr4'=20is=20required=20for=20NSS"=20= "$LINENO"=205=0A+fi=0A+=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20checking=20for=20= SSL_GetImplementedCiphers=20in=20-lssl3"=20>&5=0A+$as_echo_n=20"checking=20= for=20SSL_GetImplementedCiphers=20in=20-lssl3...=20"=20>&6;=20}=0A+if=20= ${ac_cv_lib_ssl3_SSL_GetImplementedCiphers+:}=20false;=20then=20:=0A+=20=20= $as_echo_n=20"(cached)=20"=20>&6=0A+else=0A+=20=20= ac_check_lib_save_LIBS=3D$LIBS=0A+LIBS=3D"-lssl3=20=20$LIBS"=0A+cat=20= confdefs.h=20-=20<<_ACEOF=20>conftest.$ac_ext=0A+/*=20end=20confdefs.h.=20= =20*/=0A+=0A+/*=20Override=20any=20GCC=20internal=20prototype=20to=20= avoid=20an=20error.=0A+=20=20=20Use=20char=20because=20int=20might=20= match=20the=20return=20type=20of=20a=20GCC=0A+=20=20=20builtin=20and=20= then=20its=20argument=20prototype=20would=20still=20apply.=20=20*/=0A= +#ifdef=20__cplusplus=0A+extern=20"C"=0A+#endif=0A+char=20= SSL_GetImplementedCiphers=20();=0A+int=0A+main=20()=0A+{=0A+return=20= SSL_GetImplementedCiphers=20();=0A+=20=20;=0A+=20=20return=200;=0A+}=0A= +_ACEOF=0A+if=20ac_fn_c_try_link=20"$LINENO";=20then=20:=0A+=20=20= ac_cv_lib_ssl3_SSL_GetImplementedCiphers=3Dyes=0A+else=0A+=20=20= ac_cv_lib_ssl3_SSL_GetImplementedCiphers=3Dno=0A+fi=0A+rm=20-f=20core=20= conftest.err=20conftest.$ac_objext=20\=0A+=20=20=20=20conftest$ac_exeext=20= conftest.$ac_ext=0A+LIBS=3D$ac_check_lib_save_LIBS=0A+fi=0A+{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20= $ac_cv_lib_ssl3_SSL_GetImplementedCiphers"=20>&5=0A+$as_echo=20= "$ac_cv_lib_ssl3_SSL_GetImplementedCiphers"=20>&6;=20}=0A+if=20test=20= "x$ac_cv_lib_ssl3_SSL_GetImplementedCiphers"=20=3D=20xyes;=20then=20:=0A= +=20=20cat=20>>confdefs.h=20<<_ACEOF=0A+#define=20HAVE_LIBSSL3=201=0A= +_ACEOF=0A+=0A+=20=20LIBS=3D"-lssl3=20$LIBS"=0A+=0A+else=0A+=20=20= as_fn_error=20$?=20"library=20'ssl3'=20is=20required=20for=20NSS"=20= "$LINENO"=205=0A+fi=0A+=0A+=0A+$as_echo=20"#define=20USE_NSS=201"=20= >>confdefs.h=0A+=0A=20elif=20test=20"$with_ssl"=20!=3D=20no=20;=20then=0A= -=20=20as_fn_error=20$?=20"--with-ssl=20must=20specify=20openssl"=20= "$LINENO"=205=0A+=20=20as_fn_error=20$?=20"--with-ssl=20must=20specify=20= one=20of=20openssl=20or=20nss"=20"$LINENO"=205=0A=20fi=0A=20=0A=20=0A@@=20= -13369,6=20+13637,23=20@@=20else=0A=20fi=0A=20=0A=20=0A+elif=20test=20= "$with_ssl"=20=3D=20nss=20;=20then=0A+=20=20ac_fn_c_check_header_mongrel=20= "$LINENO"=20"nss/ssl.h"=20"ac_cv_header_nss_ssl_h"=20= "$ac_includes_default"=0A+if=20test=20"x$ac_cv_header_nss_ssl_h"=20=3D=20= xyes;=20then=20:=0A+=0A+else=0A+=20=20as_fn_error=20$?=20"header=20file=20= =20is=20required=20for=20NSS"=20"$LINENO"=205=0A+fi=0A+=0A+=0A= +=20=20ac_fn_c_check_header_mongrel=20"$LINENO"=20"nss/nss.h"=20= "ac_cv_header_nss_nss_h"=20"$ac_includes_default"=0A+if=20test=20= "x$ac_cv_header_nss_nss_h"=20=3D=20xyes;=20then=20:=0A+=0A+else=0A+=20=20= as_fn_error=20$?=20"header=20file=20=20is=20required=20for=20= NSS"=20"$LINENO"=205=0A+fi=0A+=0A+=0A=20fi=0A=20=0A=20if=20test=20= "$with_pam"=20=3D=20yes=20;=20then=0A@@=20-18131,6=20+18416,9=20@@=20= $as_echo_n=20"checking=20which=20random=20number=20source=20to=20use...=20= "=20>&6;=20}=0A=20if=20test=20x"$with_ssl"=20=3D=20x"openssl"=20;=20then=0A= =20=20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20= OpenSSL"=20>&5=0A=20$as_echo=20"OpenSSL"=20>&6;=20}=0A+elif=20test=20= x"$with_ssl"=20=3D=20x"nss"=20;=20then=0A+=20=20{=20$as_echo=20= "$as_me:${as_lineno-$LINENO}:=20result:=20NSS"=20>&5=0A+$as_echo=20"NSS"=20= >&6;=20}=0A=20elif=20test=20x"$PORTNAME"=20=3D=20x"win32"=20;=20then=0A=20= =20=20{=20$as_echo=20"$as_me:${as_lineno-$LINENO}:=20result:=20Windows=20= native"=20>&5=0A=20$as_echo=20"Windows=20native"=20>&6;=20}=0A@@=20= -18160,7=20+18448,7=20@@=20fi=0A=20=20=20if=20test=20= x"$ac_cv_file__dev_urandom"=20=3D=20x"no"=20;=20then=0A=20=20=20=20=20= as_fn_error=20$?=20"=0A=20no=20source=20of=20strong=20random=20numbers=20= was=20found=0A-PostgreSQL=20can=20use=20OpenSSL,=20native=20Windows=20= API=20or=20/dev/urandom=20as=20a=20source=20of=20random=20numbers."=20= "$LINENO"=205=0A+PostgreSQL=20can=20use=20OpenSSL,=20NSS,=20native=20= Windows=20API=20or=20/dev/urandom=20as=20a=20source=20of=20random=20= numbers."=20"$LINENO"=205=0A=20=20=20fi=0A=20fi=0A=20=0Adiff=20--git=20= a/configure.ac=20b/configure.ac=0Aindex=20f54f65febe..5ec8970588=20= 100644=0A---=20a/configure.ac=0A+++=20b/configure.ac=0A@@=20-1201,7=20= +1201,7=20@@=20fi=0A=20#=0A=20#=20There=20is=20currently=20only=20one=20= supported=20SSL/TLS=20library:=20OpenSSL.=0A=20#=0A-PGAC_ARG_REQ(with,=20= ssl,=20[LIB],=20[use=20LIB=20for=20SSL/TLS=20support=20(openssl)])=0A= +PGAC_ARG_REQ(with,=20ssl,=20[LIB],=20[use=20LIB=20for=20SSL/TLS=20= support=20(openssl,=20nss)])=0A=20if=20test=20x"$with_ssl"=20=3D=20x""=20= ;=20then=0A=20=20=20with_ssl=3Dno=0A=20fi=0A@@=20-1235,8=20+1235,28=20@@=20= if=20test=20"$with_ssl"=20=3D=20openssl=20;=20then=0A=20=20=20#=20= function=20was=20removed.=0A=20=20=20AC_CHECK_FUNCS([CRYPTO_lock])=0A=20=20= =20AC_DEFINE([USE_OPENSSL],=201,=20[Define=20to=201=20to=20build=20with=20= OpenSSL=20support.=20(--with-ssl=3Dopenssl)])=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= NSS_InitContext,=20[],=20[AC_MSG_ERROR([library=20'nss3'=20is=20required=20= for=20NSS])])=0A+=20=20AC_CHECK_LIB(nspr4,=20PR_GetDefaultIOMethods,=20= [],=20[AC_MSG_ERROR([library=20'nspr4'=20is=20required=20for=20NSS])])=0A= +=20=20AC_CHECK_LIB(ssl3,=20SSL_GetImplementedCiphers,=20[],=20= [AC_MSG_ERROR([library=20'ssl3'=20is=20required=20for=20NSS])])=0A+=20=20= AC_DEFINE([USE_NSS],=201,=20[Define=20to=201=20if=20you=20have=20NSS=20= support,])=0A=20elif=20test=20"$with_ssl"=20!=3D=20no=20;=20then=0A-=20=20= AC_MSG_ERROR([--with-ssl=20must=20specify=20openssl])=0A+=20=20= AC_MSG_ERROR([--with-ssl=20must=20specify=20one=20of=20openssl=20or=20= nss])=0A=20fi=0A=20AC_SUBST(with_ssl)=0A=20=0A@@=20-1414,6=20+1434,9=20= @@=20fi=0A=20if=20test=20"$with_ssl"=20=3D=20openssl=20;=20then=0A=20=20=20= AC_CHECK_HEADER(openssl/ssl.h,=20[],=20[AC_MSG_ERROR([header=20file=20= =20is=20required=20for=20OpenSSL])])=0A=20=20=20= AC_CHECK_HEADER(openssl/err.h,=20[],=20[AC_MSG_ERROR([header=20file=20= =20is=20required=20for=20OpenSSL])])=0A+elif=20test=20= "$with_ssl"=20=3D=20nss=20;=20then=0A+=20=20AC_CHECK_HEADER(nss/ssl.h,=20= [],=20[AC_MSG_ERROR([header=20file=20=20is=20required=20for=20= NSS])])=0A+=20=20AC_CHECK_HEADER(nss/nss.h,=20[],=20= [AC_MSG_ERROR([header=20file=20=20is=20required=20for=20= NSS])])=0A=20fi=0A=20=0A=20if=20test=20"$with_pam"=20=3D=20yes=20;=20= then=0A@@=20-2170,6=20+2193,8=20@@=20fi=0A=20AC_MSG_CHECKING([which=20= random=20number=20source=20to=20use])=0A=20if=20test=20x"$with_ssl"=20=3D=20= x"openssl"=20;=20then=0A=20=20=20AC_MSG_RESULT([OpenSSL])=0A+elif=20test=20= x"$with_ssl"=20=3D=20x"nss"=20;=20then=0A+=20=20AC_MSG_RESULT([NSS])=0A=20= elif=20test=20x"$PORTNAME"=20=3D=20x"win32"=20;=20then=0A=20=20=20= AC_MSG_RESULT([Windows=20native])=0A=20else=0A@@=20-2179,7=20+2204,7=20= @@=20else=0A=20=20=20if=20test=20x"$ac_cv_file__dev_urandom"=20=3D=20= x"no"=20;=20then=0A=20=20=20=20=20AC_MSG_ERROR([=0A=20no=20source=20of=20= strong=20random=20numbers=20was=20found=0A-PostgreSQL=20can=20use=20= OpenSSL,=20native=20Windows=20API=20or=20/dev/urandom=20as=20a=20source=20= of=20random=20numbers.])=0A+PostgreSQL=20can=20use=20OpenSSL,=20NSS,=20= native=20Windows=20API=20or=20/dev/urandom=20as=20a=20source=20of=20= random=20numbers.])=0A=20=20=20fi=0A=20fi=0A=20=0Adiff=20--git=20= a/src/backend/libpq/Makefile=20b/src/backend/libpq/Makefile=0Aindex=20= 8d1d16b0fc..045d2c2f6b=20100644=0A---=20a/src/backend/libpq/Makefile=0A= +++=20b/src/backend/libpq/Makefile=0A@@=20-30,6=20+30,10=20@@=20OBJS=20=3D= =20\=0A=20=0A=20ifeq=20($(with_ssl),openssl)=0A=20OBJS=20+=3D=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/common/Makefile=20= b/src/common/Makefile=0Aindex=205422579a6a..57d44080b4=20100644=0A---=20= a/src/common/Makefile=0A+++=20b/src/common/Makefile=0A@@=20-85,12=20= +85,18=20@@=20OBJS_COMMON=20+=3D=20\=0A=20=09protocol_openssl.o=20\=0A=20= =09cryptohash_openssl.o=0A=20else=0A+ifeq=20($(with_ssl),nss)=0A= +OBJS_COMMON=20+=3D=20\=0A+=09cipher_nss.o=20\=0A+=09cryptohash_nss.o=0A= +else=0A=20OBJS_COMMON=20+=3D=20\=0A=20=09cryptohash.o=20\=0A=20=09md5.o=20= \=0A=20=09sha1.o=20\=0A=20=09sha2.o=0A=20endif=0A+endif=0A=20=0A=20#=20A=20= few=20files=20are=20currently=20only=20built=20for=20frontend,=20not=20= server=0A=20#=20(Mkvcbuild.pm=20has=20a=20copy=20of=20this=20list,=20= too).=20=20logging.c=20is=20excluded=0Adiff=20--git=20= a/src/include/pg_config.h.in=20b/src/include/pg_config.h.in=0Aindex=20= 04dc330119..474cc2655c=20100644=0A---=20a/src/include/pg_config.h.in=0A= +++=20b/src/include/pg_config.h.in=0A@@=20-322,6=20+322,12=20@@=0A=20/*=20= Define=20to=201=20if=20you=20have=20the=20`m'=20library=20(-lm).=20*/=0A=20= #undef=20HAVE_LIBM=0A=20=0A+/*=20Define=20to=201=20if=20you=20have=20the=20= `nspr4'=20library=20(-lnspr4).=20*/=0A+#undef=20HAVE_LIBNSPR4=0A+=0A+/*=20= Define=20to=201=20if=20you=20have=20the=20`nss3'=20library=20(-lnss3).=20= */=0A+#undef=20HAVE_LIBNSS3=0A+=0A=20/*=20Define=20to=201=20if=20you=20= have=20the=20`pam'=20library=20(-lpam).=20*/=0A=20#undef=20HAVE_LIBPAM=0A= =20=0A@@=20-334,6=20+340,9=20@@=0A=20/*=20Define=20to=201=20if=20you=20= have=20the=20`ssl'=20library=20(-lssl).=20*/=0A=20#undef=20HAVE_LIBSSL=0A= =20=0A+/*=20Define=20to=201=20if=20you=20have=20the=20`ssl3'=20library=20= (-lssl3).=20*/=0A+#undef=20HAVE_LIBSSL3=0A+=0A=20/*=20Define=20to=201=20= if=20you=20have=20the=20`wldap32'=20library=20(-lwldap32).=20*/=0A=20= #undef=20HAVE_LIBWLDAP32=0A=20=0A@@=20-899,6=20+908,9=20@@=0A=20/*=20= Define=20to=20select=20named=20POSIX=20semaphores.=20*/=0A=20#undef=20= USE_NAMED_POSIX_SEMAPHORES=0A=20=0A+/*=20Define=20to=201=20if=20you=20= have=20NSS=20support,=20*/=0A+#undef=20USE_NSS=0A+=0A=20/*=20Define=20to=20= 1=20to=20build=20with=20OpenSSL=20support.=20(--with-ssl=3Dopenssl)=20*/=0A= =20#undef=20USE_OPENSSL=0A=20=0Adiff=20--git=20= a/src/interfaces/libpq/Makefile=20b/src/interfaces/libpq/Makefile=0A= index=20f74677eaf9..e10d8bef42=20100644=0A---=20= a/src/interfaces/libpq/Makefile=0A+++=20b/src/interfaces/libpq/Makefile=0A= @@=20-56,6=20+56,11=20@@=20OBJS=20+=3D=20\=0A=20=09fe-secure-openssl.o=0A= =20endif=0A=20=0A+ifeq=20($(with_ssl),=20nss)=0A+OBJS=20+=3D=20\=0A+=09= fe-secure-nss.o=0A+endif=0A+=0A=20ifeq=20($(with_gssapi),yes)=0A=20OBJS=20= +=3D=20\=0A=20=09fe-gssapi-common.o=20\=0Adiff=20--git=20= a/src/tools/msvc/Install.pm=20b/src/tools/msvc/Install.pm=0Aindex=20= ea3af48777..afe72a7e97=20100644=0A---=20a/src/tools/msvc/Install.pm=0A= +++=20b/src/tools/msvc/Install.pm=0A@@=20-438,7=20+438,8=20@@=20sub=20= CopyContribFiles=0A=20=09=09{=0A=20=09=09=09#=20These=20= configuration-based=20exclusions=20must=20match=20vcregress.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= 49614106dc..53b5a71726=20100644=0A---=20a/src/tools/msvc/Mkvcbuild.pm=0A= +++=20b/src/tools/msvc/Mkvcbuild.pm=0A@@=20-132,6=20+132,11=20@@=20sub=20= mkvcbuild=0A=20=09=09push(@pgcommonallfiles,=20'cryptohash_openssl.c');=0A= =20=09=09push(@pgcommonallfiles,=20'protocol_openssl.c');=0A=20=09}=0A+=09= elsif=20($solution->{options}->{nss})=0A+=09{=0A+=09=09= push(@pgcommonallfiles,=20'cryptohash_nss.c');=0A+=09=09= push(@pgcommonallfiles,=20'cipher_nss.c');=0A+=09}=0A=20=09else=0A=20=09= {=0A=20=09=09push(@pgcommonallfiles,=20'cryptohash.c');=0A@@=20-196,12=20= +201,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= -259,12=20+271,19=20@@=20sub=20mkvcbuild=0A=20=09= $libpq->AddReference($libpgcommon,=20$libpgport);=0A=20=0A=20=09#=20The=20= OBJS=20scraper=20doesn't=20know=20about=20ifdefs,=20so=20remove=20= appropriate=20files=0A-=09#=20if=20building=20without=20OpenSSL.=0A-=09= if=20(!$solution->{options}->{openssl})=0A+=09#=20if=20building=20= without=20various=20options=0A+=09if=20(!$solution->{options}->{openssl}=20= &&=20!$solution->{options}->{nss})=0A=20=09{=0A=20=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-secure-common.c');=0A+=09}=0A= +=09if=20(!$solution->{options}->{openssl})=0A+=09{=0A=20=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-secure-openssl.c');=0A=20=09= }=0A+=09if=20(!$solution->{options}->{nss})=0A+=09{=0A+=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-secure-nss.c');=0A+=09}=0A=20= =09if=20(!$solution->{options}->{gss})=0A=20=09{=0A=20=09=09= $libpq->RemoveFile('src/interfaces/libpq/fe-gssapi-common.c');=0A@@=20= -432,9=20+451,14=20@@=20sub=20mkvcbuild=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=09= if=20(!$solution->{options}->{openssl})=0A=20=09{=0A-=09=09push=20= @contrib_excludes,=20'sslinfo',=20'ssl_passphrase_callback';=0A+=09=09= push=20@contrib_excludes,=20'ssl_passphrase_callback';=0A=20=09}=0A=20=0A= =20=09if=20(!$solution->{options}->{uuid})=0A@@=20-464,6=20+488,11=20@@=20= sub=20mkvcbuild=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(=0Adiff=20--git=20= a/src/tools/msvc/Solution.pm=20b/src/tools/msvc/Solution.pm=0Aindex=20= 2aa062b2c9..0b0fbffa5e=20100644=0A---=20a/src/tools/msvc/Solution.pm=0A= +++=20b/src/tools/msvc/Solution.pm=0A@@=20-488,6=20+488,7=20@@=20sub=20= GenerateFiles=0A=20=09=09USE_LLVM=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=3D>=20undef,=0A=20=09=09USE_NAMED_POSIX_SEMAPHORES=20=3D>=20= undef,=0A=20=09=09USE_OPENSSL=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=3D>=20undef,=0A+=09=09USE_NSS=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=3D>=20undef,=0A=20=09=09USE_PAM=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=3D>=20undef,=0A=20=09=09= USE_SLICING_BY_8_CRC32C=20=20=20=20=3D>=20undef,=0A=20=09=09= USE_SSE42_CRC32C=20=20=20=20=20=20=20=20=20=20=20=3D>=20undef,=0A@@=20= -540,6=20+541,10=20@@=20sub=20GenerateFiles=0A=20=09=09=09= $define{HAVE_OPENSSL_INIT_SSL}=20=20=20=20=20=20=3D=201;=0A=20=09=09}=0A=20= =09}=0A+=09if=20($self->{options}->{nss})=0A+=09{=0A+=09=09= $define{USE_NSS}=20=3D=201;=0A+=09}=0A=20=0A=20=09= $self->GenerateConfigHeader('src/include/pg_config.h',=20=20=20=20=20= \%define,=201);=0A=20=09= $self->GenerateConfigHeader('src/include/pg_config_ext.h',=20\%define,=20= 0);=0A@@=20-1008,6=20+1013,21=20@@=20sub=20AddProject=0A=20=09=09=09}=0A=20= =09=09}=0A=20=09}=0A+=09if=20($self->{options}->{nss})=0A+=09{=0A+=09=09= $proj->AddIncludeDir($self->{options}->{nss}=20.=20'\..\public\nss');=0A= +=09=09$proj->AddIncludeDir($self->{options}->{nss}=20.=20= '\include\nspr');=0A+=09=09foreach=20my=20$lib=20(qw(plds4=20plc4=20= nspr4))=0A+=09=09{=0A+=09=09=09$proj->AddLibrary($self->{options}->{nss}=20= .=0A+=09=09=09=09=09=09=09=20=20'\lib\lib'=20.=20"$lib.lib",=200);=0A+=09= =09}=0A+=09=09foreach=20my=20$lib=20(qw(ssl3=20smime3=20nss3))=0A+=09=09= {=0A+=09=09=09$proj->AddLibrary($self->{options}->{nss}=20.=0A+=09=09=09=09= =09=09=09=20=20'\lib'=20.=20"\\$lib.dll.lib",=200);=0A+=09=09}=0A+=09}=0A= =20=09if=20($self->{options}->{nls})=0A=20=09{=0A=20=09=09= $proj->AddIncludeDir($self->{options}->{nls}=20.=20'\include');=0A--=20=0A= 2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5 Content-Disposition: attachment; filename=v28-0008-nss-Support-NSS-in-cryptohash.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v28-0008-nss-Support-NSS-in-cryptohash.patch" Content-Transfer-Encoding: quoted-printable =46rom=20d658748c3c752b31720a2203aff848ac83123b65=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:51=20+0100=0ASubject:=20[PATCH=20= v28=208/9]=20nss:=20Support=20NSS=20in=20cryptohash=0A=0AThis=20adds=20= support=20for=20using=20libnss=20as=20a=20crypto=20backend=20for=20the=20= built-=0Ain=20cryptohash=20support.=20Much=20of=20this=20code=20is=20= similar=20to=20the=20pgcrypto=0Asupport.=0A---=0A=20= src/common/cryptohash_nss.c=20|=20264=20= ++++++++++++++++++++++++++++++++++++=0A=201=20file=20changed,=20264=20= insertions(+)=0A=20create=20mode=20100644=20src/common/cryptohash_nss.c=0A= =0Adiff=20--git=20a/src/common/cryptohash_nss.c=20= b/src/common/cryptohash_nss.c=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..59ba9c1697=0A---=20/dev/null=0A+++=20= b/src/common/cryptohash_nss.c=0A@@=20-0,0=20+1,264=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20cryptohash_nss.c=0A+=20*=09=20=20Set=20of=20wrapper=20= routines=20on=20top=20of=20NSS=20to=20support=20cryptographic=0A+=20*=09=20= =20hash=20functions.=0A+=20*=0A+=20*=20This=20should=20only=20be=20used=20= if=20code=20is=20compiled=20with=20NSS=20support.=0A+=20*=0A+=20*=20= Portions=20Copyright=20(c)=201996-2021,=20PostgreSQL=20Global=20= Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=201994,=20= Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=09=09=20=20src/common/cryptohash_nss.c=0A+=20*=0A= +=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#ifndef=20FRONTEND=0A+#include=20"postgres.h"=0A+#else=0A= +#include=20"postgres_fe.h"=0A+#endif=0A+=0A+#include=20"common/nss.h"=0A= +=0A+#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+=0A+#include=20= "common/cryptohash.h"=0A+#ifndef=20FRONTEND=0A+#include=20= "utils/memutils.h"=0A+#include=20"utils/resowner.h"=0A+#include=20= "utils/resowner_private.h"=0A+#endif=0A+=0A+/*=0A+=20*=20In=20the=20= backend,=20use=20an=20allocation=20in=20TopMemoryContext=20to=20count=20= for=0A+=20*=20resowner=20cleanup=20handling.=20=20In=20the=20frontend,=20= use=20malloc=20to=20be=20able=0A+=20*=20to=20return=20a=20failure=20= status=20back=20to=20the=20caller.=0A+=20*/=0A+#ifndef=20FRONTEND=0A= +#define=20ALLOC(size)=20MemoryContextAlloc(TopMemoryContext,=20size)=0A= +#define=20FREE(ptr)=20pfree(ptr)=0A+#else=0A+#define=20ALLOC(size)=20= malloc(size)=0A+#define=20FREE(ptr)=20free(ptr)=0A+#endif=0A+=0A+/*=0A+=20= *=20Internal=20pg_cryptohash_ctx=20structure.=0A+=20*/=0A+struct=20= pg_cryptohash_ctx=0A+{=0A+=09pg_cryptohash_type=20type;=0A+=0A+=09= PK11Context=20*pk11_context;=0A+=09HASH_HashType=20hash_type;=0A+=0A= +#ifndef=20FRONTEND=0A+=09ResourceOwner=20resowner;=0A+#endif=0A+};=0A+=0A= +/*=0A+=20*=20pg_cryptohash_create=0A+=20*=0A+=20*=20Create=20and=20= allocate=20a=20new=20hash=20context.=20Returns=20NULL=20on=20failure=20= in=20the=0A+=20*=20frontend,=20and=20raise=20error=20without=20returning=20= in=20the=20backend.=0A+=20*/=0A+pg_cryptohash_ctx=20*=0A= +pg_cryptohash_create(pg_cryptohash_type=20type)=0A+{=0A+=09= NSSInitParameters=20params;=0A+=09pg_cryptohash_ctx=20*ctx;=0A+=09= SECOidData=20*hash;=0A+=09SECStatus=20status;=0A+=0A+#ifndef=20FRONTEND=0A= +=09/*=0A+=09=20*=20Make=20sure=20that=20the=20resource=20owner=20has=20= space=20to=20remember=20this=20reference.=0A+=09=20*=20This=20can=20= error=20out=20with=20"out=20of=20memory",=20so=20do=20this=20before=20= any=20other=0A+=09=20*=20allocation=20to=20avoid=20leaking.=0A+=09=20*/=0A= +=09ResourceOwnerEnlargeCryptoHash(CurrentResourceOwner);=0A+#endif=0A+=0A= +=09ctx=20=3D=20ALLOC(sizeof(pg_cryptohash_ctx));=0A+=0A+=09if=20(!ctx)=0A= +=09=09goto=20error;=0A+=0A+=09switch(type)=0A+=09{=0A+=09=09case=20= PG_SHA1:=0A+=09=09=09ctx->hash_type=20=3D=20SEC_OID_SHA1;=0A+=09=09=09= break;=0A+=09=09case=20PG_MD5:=0A+=09=09=09ctx->hash_type=20=3D=20= SEC_OID_MD5;=0A+=09=09=09break;=0A+=09=09case=20PG_SHA224:=0A+=09=09=09= ctx->hash_type=20=3D=20SEC_OID_SHA224;=0A+=09=09=09break;=0A+=09=09case=20= PG_SHA256:=0A+=09=09=09ctx->hash_type=20=3D=20SEC_OID_SHA256;=0A+=09=09=09= break;=0A+=09=09case=20PG_SHA384:=0A+=09=09=09ctx->hash_type=20=3D=20= SEC_OID_SHA384;=0A+=09=09=09break;=0A+=09=09case=20PG_SHA512:=0A+=09=09=09= ctx->hash_type=20=3D=20SEC_OID_SHA512;=0A+=09=09=09break;=0A+=09}=0A+=0A= +=09/*=0A+=09=20*=20Initialize=20our=20own=20NSS=20context=20without=20a=20= database=20backing=20it.=0A+=09=20*/=0A+=09memset(¶ms,=200,=20= sizeof(params));=0A+=09params.length=20=3D=20sizeof(params);=0A+=09= status=20=3D=20NSS_NoDB_Init(".");=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09explicit_bzero(ctx,=20= sizeof(pg_cryptohash_ctx));=0A+=09=09FREE(ctx);=0A+=09=09goto=20error;=0A= +=09}=0A+=0A+=09ctx->type=20=3D=20type;=0A+=09hash=20=3D=20= SECOID_FindOIDByTag(ctx->hash_type);=0A+=09ctx->pk11_context=20=3D=20= PK11_CreateDigestContext(hash->offset);=0A+=09if=20(!ctx->pk11_context)=0A= +=09{=0A+=09=09explicit_bzero(ctx,=20sizeof(pg_cryptohash_ctx));=0A+=09=09= FREE(ctx);=0A+=09=09goto=20error;=0A+=09}=0A+=0A+#ifndef=20FRONTEND=0A+=09= ctx->resowner=20=3D=20CurrentResourceOwner;=0A+=09= ResourceOwnerRememberCryptoHash(CurrentResourceOwner,=0A+=09=09=09=09=09=09= =09=09=09PointerGetDatum(ctx));=0A+#endif=0A+=0A+=09return=20ctx;=0A+=0A= +error:=0A+#ifndef=20FRONTEND=0A+=09ereport(ERROR,=0A+=09=09=09= (errcode(ERRCODE_OUT_OF_MEMORY),=0A+=09=09=09=20errmsg("out=20of=20= memory")));=0A+#endif=0A+=09return=20NULL;=0A+}=0A+=0A+/*=0A+=20*=20= pg_cryptohash_init=0A+=20*=09=09=09Initialize=20the=20passed=20hash=20= context=0A+=20*=0A+=20*=20Returns=200=20on=20success,=20-1=20on=20= failure.=0A+=20*/=0A+int=0A+pg_cryptohash_init(pg_cryptohash_ctx=20*ctx)=0A= +{=0A+=09SECStatus=09=09status;=0A+=0A+=09status=20=3D=20= PK11_DigestBegin(ctx->pk11_context);=0A+=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09=09return=20-1;=0A+=09return=200;=0A+}=0A+=0A+/*=0A+=20= *=20pg_cryptohash_update=0A+=20*=0A+=20*=20Update=20a=20hash=20context.=20= =20Returns=200=20on=20success,=20-1=20on=20failure.=0A+=20*/=0A+int=0A= +pg_cryptohash_update(pg_cryptohash_ctx=20*ctx,=20const=20uint8=20*data,=20= size_t=20len)=0A+{=0A+=09SECStatus=09status;=0A+=0A+=09if=20(ctx=20=3D=3D=20= NULL)=0A+=09=09return=20-1;=0A+=0A+=09status=20=3D=20= PK11_DigestOp(ctx->pk11_context,=20data,=20len);=0A+=09if=20(status=20!=3D= =20SECSuccess)=0A+=09=09return=20-1;=0A+=0A+=09return=200;=0A+}=0A+=0A= +/*=0A+=20*=20pg_cryptohash_final=0A+=20*=0A+=20*=20Finalize=20a=20hash=20= context.=20=20Returns=200=20on=20success,=20-1=20on=20failure.=0A+=20*/=0A= +int=0A+pg_cryptohash_final(pg_cryptohash_ctx=20*ctx,=20uint8=20*dest,=20= size_t=20len)=0A+{=0A+=09SECStatus=09status;=0A+=09unsigned=20int=20= outlen;=0A+=0A+=09switch=20(ctx->type)=0A+=09{=0A+=09=09case=20PG_MD5:=0A= +=09=09=09if=20(len=20<=20MD5_LENGTH)=0A+=09=09=09=09return=20-1;=0A+=09=09= =09break;=0A+=09=09case=20PG_SHA1:=0A+=09=09=09if=20(len=20<=20= SHA1_LENGTH)=0A+=09=09=09=09return=20-1;=0A+=09=09=09break;=0A+=09=09= case=20PG_SHA224:=0A+=09=09=09if=20(len=20<=20SHA224_LENGTH)=0A+=09=09=09= =09return=20-1;=0A+=09=09=09break;=0A+=09=09case=20PG_SHA256:=0A+=09=09=09= if=20(len=20<=20SHA256_LENGTH)=0A+=09=09=09=09return=20-1;=0A+=09=09=09= break;=0A+=09=09case=20PG_SHA384:=0A+=09=09=09if=20(len=20<=20= SHA384_LENGTH)=0A+=09=09=09=09return=20-1;=0A+=09=09=09break;=0A+=09=09= case=20PG_SHA512:=0A+=09=09=09if=20(len=20<=20SHA512_LENGTH)=0A+=09=09=09= =09return=20-1;=0A+=09=09=09break;=0A+=09}=0A+=0A+=09status=20=3D=20= PK11_DigestFinal(ctx->pk11_context,=20dest,=20&outlen,=20len);=0A+=0A+=09= if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20-1;=0A+=0A+=09return=20= 0;=0A+}=0A+=0A+/*=0A+=20*=20pg_cryptohash_free=0A+=20*=0A+=20*=20Free=20= a=20hash=20context=20and=20the=20associated=20NSS=20context.=0A+=20*/=0A= +void=0A+pg_cryptohash_free(pg_cryptohash_ctx=20*ctx)=0A+{=0A+=09PRBool=09= =09free_context=20=3D=20PR_TRUE;=0A+=0A+=09if=20(!ctx)=0A+=09=09return;=0A= +=0A+=09PK11_DestroyContext(ctx->pk11_context,=20free_context);=0A= +#ifndef=20FRONTEND=0A+=09ResourceOwnerForgetCryptoHash(ctx->resowner,=20= PointerGetDatum(ctx));=0A+#endif=0A+=09explicit_bzero(ctx,=20= sizeof(pg_cryptohash_ctx));=0A+=09FREE(ctx);=0A+}=0A--=20=0A2.21.1=20= (Apple=20Git-122.3)=0A=0A= --Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5 Content-Disposition: attachment; filename=v28-0007-nss-Support-NSS-in-sslinfo.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v28-0007-nss-Support-NSS-in-sslinfo.patch" Content-Transfer-Encoding: quoted-printable =46rom=208c782dee692364d7ba03758b4c877452348e2b29=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:48=20+0100=0ASubject:=20[PATCH=20= v28=207/9]=20nss:=20Support=20NSS=20in=20sslinfo=0A=0ASince=20sslinfo=20= to=20a=20large=20extent=20use=20the=20be_tls_*=20API=20this=20mostly=0A= disables=20functionality=20which=20currently=20is=20OpenSSL=20specific.=0A= ---=0A=20contrib/sslinfo/sslinfo.c=20|=2032=20= ++++++++++++++++++++++++++++++++=0A=20doc/src/sgml/sslinfo.sgml=20|=2012=20= +++++++++++-=0A=202=20files=20changed,=2043=20insertions(+),=201=20= deletion(-)=0A=0Adiff=20--git=20a/contrib/sslinfo/sslinfo.c=20= b/contrib/sslinfo/sslinfo.c=0Aindex=2030cae0bb98..3aadd90aa6=20100644=0A= ---=20a/contrib/sslinfo/sslinfo.c=0A+++=20b/contrib/sslinfo/sslinfo.c=0A= @@=20-9,9=20+9,11=20@@=0A=20=0A=20#include=20"postgres.h"=0A=20=0A= +#ifdef=20USE_OPENSSL=0A=20#include=20=0A=20#include=20= =0A=20#include=20=0A+#endif=0A=20=0A=20= #include=20"access/htup_details.h"=0A=20#include=20"funcapi.h"=0A@@=20= -21,6=20+23,7=20@@=0A=20=0A=20PG_MODULE_MAGIC;=0A=20=0A+#ifdef=20= USE_OPENSSL=0A=20static=20Datum=20X509_NAME_field_to_text(X509_NAME=20= *name,=20text=20*fieldName);=0A=20static=20Datum=20= ASN1_STRING_to_text(ASN1_STRING=20*str);=0A=20=0A@@=20-31,6=20+34,7=20@@=20= typedef=20struct=0A=20{=0A=20=09TupleDesc=09tupdesc;=0A=20}=20= SSLExtensionInfoContext;=0A+#endif=0A=20=0A=20/*=0A=20=20*=20Indicates=20= whether=20current=20session=20uses=20SSL=0A@@=20-131,6=20+135,7=20@@=20= ssl_client_serial(PG_FUNCTION_ARGS)=0A=20}=0A=20=0A=20=0A+#ifdef=20= USE_OPENSSL=0A=20/*=0A=20=20*=20Converts=20OpenSSL=20ASN1_STRING=20= structure=20into=20text=0A=20=20*=0A@@=20-282,7=20+287,23=20@@=20= ssl_issuer_field(PG_FUNCTION_ARGS)=0A=20=09else=0A=20=09=09return=20= result;=0A=20}=0A+#endif=09=09=09=09=09=09=09/*=20USE_OPENSSL=20*/=0A=20=0A= +#ifdef=20USE_NSS=0A+PG_FUNCTION_INFO_V1(ssl_client_dn_field);=0A+Datum=0A= +ssl_client_dn_field(PG_FUNCTION_ARGS)=0A+{=0A+=09PG_RETURN_NULL();=0A+}=0A= +=0A+PG_FUNCTION_INFO_V1(ssl_issuer_field);=0A+Datum=0A= +ssl_issuer_field(PG_FUNCTION_ARGS)=0A+{=0A+=09PG_RETURN_NULL();=0A+}=0A= +#endif=09=09=09=09=09=09=09/*=20USE_NSS=20*/=0A=20=0A=20/*=0A=20=20*=20= Returns=20current=20client=20certificate=20subject=20as=20one=20string=0A= @@=20-338,6=20+359,7=20@@=20ssl_issuer_dn(PG_FUNCTION_ARGS)=0A=20}=0A=20=0A= =20=0A+#ifdef=20USE_OPENSSL=0A=20/*=0A=20=20*=20Returns=20information=20= about=20available=20SSL=20extensions.=0A=20=20*=0A@@=20-471,3=20+493,13=20= @@=20ssl_extension_info(PG_FUNCTION_ARGS)=0A=20=09/*=20All=20done=20*/=0A= =20=09SRF_RETURN_DONE(funcctx);=0A=20}=0A+#endif=09=09=09=09=09=09=09/*=20= USE_OPENSSL=20*/=0A+=0A+#ifdef=20USE_NSS=0A= +PG_FUNCTION_INFO_V1(ssl_extension_info);=0A+Datum=0A= +ssl_extension_info(PG_FUNCTION_ARGS)=0A+{=0A+=09PG_RETURN_NULL();=0A+}=0A= +#endif=09=09=09=09=09=09=09/*=20USE_NSS=20*/=0Adiff=20--git=20= a/doc/src/sgml/sslinfo.sgml=20b/doc/src/sgml/sslinfo.sgml=0Aindex=20= 2a9c45a111..f3ae2fc3b8=20100644=0A---=20a/doc/src/sgml/sslinfo.sgml=0A= +++=20b/doc/src/sgml/sslinfo.sgml=0A@@=20-22,7=20+22,8=20@@=0A=20=0A=20=20= =0A=20=20=20This=20extension=20won't=20build=20at=20all=20unless=20= the=20installation=20was=0A-=20=20configured=20with=20= --with-ssl=3Dopenssl.=0A+=20=20configured=20with=20= SSL=20support,=20such=20as=20--with-ssl=3Dopenssl=0A+=20= =20or=20--with-ssl=3Dnss.=0A=20=20=0A=20=0A=20=20= =0A@@=20-208,6=20+209,9=20@@=20emailAddress=0A=20=20=20=20=20=20= the=20X.500=20and=20X.509=20standards,=20so=20you=20cannot=20just=20= assign=20arbitrary=0A=20=20=20=20=20=20meaning=20to=20them.=0A=20=20=20=20= =20=0A+=20=20=20=20=0A+=20=20=20=20=20This=20function=20is=20= only=20available=20when=20using=20OpenSSL.=0A= +=20=20=20=20=0A=20=20=20=20=20=0A=20=20=20=20= =0A=20=0A@@=20-223,6=20+227,9=20@@=20emailAddress=0A=20=20= =20=20=20=20Same=20as=20ssl_client_dn_field,=20but=20= for=20the=20certificate=20issuer=0A=20=20=20=20=20=20rather=20than=20the=20= certificate=20subject.=0A=20=20=20=20=20=0A+=20=20=20=20=0A= +=20=20=20=20=20This=20function=20is=20only=20available=20when=20using=20= OpenSSL.=0A+=20=20=20=20=0A=20=20=20=20= =20=0A=20=20=20=20=0A=20=0A@@=20-238,6=20= +245,9=20@@=20emailAddress=0A=20=20=20=20=20=20Provide=20information=20= about=20extensions=20of=20client=20certificate:=20extension=20name,=0A=20= =20=20=20=20=20extension=20value,=20and=20if=20it=20is=20a=20critical=20= extension.=0A=20=20=20=20=20=0A+=20=20=20=20=0A+=20=20=20=20= =20This=20function=20is=20only=20available=20when=20using=20= OpenSSL.=0A+=20=20=20=20=0A=20=20=20=20= =20=0A=20=20=20=20=0A=20=20=20=0A= --=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5 Content-Disposition: attachment; filename=v28-0006-nss-Support-NSS-in-pgcrypto.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v28-0006-nss-Support-NSS-in-pgcrypto.patch" Content-Transfer-Encoding: quoted-printable =46rom=20420eca69c0b97560cd29a514555448a3c1d429f5=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:45=20+0100=0ASubject:=20[PATCH=20= v28=206/9]=20nss:=20Support=20NSS=20in=20pgcrypto=0A=0AThis=20extends=20= pgcrypto=20to=20be=20able=20to=20use=20libnss=20as=20a=20cryptographic=0A= backend=20for=20pgcrypto=20much=20like=20how=20OpenSSL=20is=20a=20= supported=20backend.=0ABlowfish=20is=20not=20a=20supported=20cipher=20in=20= NSS,=20so=20the=20implementation=0Afalls=20back=20on=20the=20built-in=20= BF=20code=20to=20be=20compatible=20in=20terms=20of=0Acipher=20support.=0A= ---=0A=20contrib/pgcrypto/Makefile=20=20|=20=20=207=20+-=0A=20= contrib/pgcrypto/nss.c=20=20=20=20=20|=20753=20= +++++++++++++++++++++++++++++++++++++=0A=20doc/src/sgml/pgcrypto.sgml=20= |=20=2038=20+-=0A=203=20files=20changed,=20787=20insertions(+),=2011=20= deletions(-)=0A=20create=20mode=20100644=20contrib/pgcrypto/nss.c=0A=0A= diff=20--git=20a/contrib/pgcrypto/Makefile=20b/contrib/pgcrypto/Makefile=0A= index=20c0b4f1fcf6..ede7a78146=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=20openssl,,$(with_ssl)),=20$(INT_SRCS),=20= $(OSSL_SRCS))=0A-CF_TESTS=20=3D=20$(if=20$(subst=20= openssl,,$(with_ssl)),=20$(INT_TESTS),=20$(OSSL_TESTS))=0A+CF_SRCS=20=3D=20= $(if=20$(findstring=20openssl,=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=20CF_PGP_TESTS=20=3D=20$(if=20$(subst=20= no,,$(with_zlib)),=20$(ZLIB_TST),=20$(ZLIB_OFF_TST))=0A=20=0A=20SRCS=20=3D= =20\=0Adiff=20--git=20a/contrib/pgcrypto/nss.c=20= b/contrib/pgcrypto/nss.c=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..d4fd4680ec=0A---=20/dev/null=0A+++=20= b/contrib/pgcrypto/nss.c=0A@@=20-0,0=20+1,753=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20nss.c=0A+=20*=09=20=20Wrapper=20for=20using=20NSS=20= as=20a=20backend=20for=20pgcrypto=20PX=0A+=20*=0A+=20*=0A+=20*=20= Portions=20Copyright=20(c)=201996-2021,=20PostgreSQL=20Global=20= Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=201994,=20= Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=09=20=20contrib/pgcrypto/nss.c=0A+=20*=0A+=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#include=20"postgres.h"=0A+=0A+#include=20"px.h"=0A= +#include=20"blf.h"=0A+#include=20"common/nss.h"=0A+#include=20= "utils/memutils.h"=0A+=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+=0A+/*=0A+=20*=20Define=20our=20own=20mechanisms=20for=20= Blowfish=20as=20it's=20not=20implemented=20by=20NSS.=0A+=20*/=0A+#define=20= BLOWFISH_CBC=09(1)=0A+#define=20BLOWFISH_ECB=09(2)=0A+=0A+/*=0A+=20*=20= Data=20structures=20for=20recording=20cipher=20implementations=20as=20= well=20as=20ongoing=0A+=20*=20cipher=20operations.=0A+=20*/=0A+typedef=20= struct=20nss_digest=0A+{=0A+=09NSSInitContext=20*context;=0A+=09= PK11Context=20*hash_context;=0A+=09HASH_HashType=20hash_type;=0A+}=09=09=09= nss_digest;=0A+=0A+typedef=20struct=20cipher_implementation=0A+{=0A+=09= /*=20Function=20pointers=20to=20cipher=20operations=20*/=0A+=09int=09=09=09= (*init)=20(PX_Cipher=20*pxc,=20const=20uint8=20*key,=20unsigned=20klen,=20= const=20uint8=20*iv);=0A+=09unsigned=09(*get_block_size)=20(PX_Cipher=20= *pxc);=0A+=09unsigned=09(*get_key_size)=20(PX_Cipher=20*pxc);=0A+=09= unsigned=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=20= dlen,=20uint8=20*res);=0A+=09int=09=09=09(*decrypt)=20(PX_Cipher=20*pxc,=20= const=20uint8=20*data,=20unsigned=20dlen,=20uint8=20*res);=0A+=09void=09=09= (*free)=20(PX_Cipher=20*pxc);=0A+=0A+=09/*=20The=20mechanism=20= describing=20the=20cipher=20used=20*/=0A+=09union=0A+=09{=0A+=09=09= CK_MECHANISM_TYPE=20nss;=0A+=09=09CK_ULONG=09internal;=0A+=09}=09=09=09= mechanism;=0A+=09int=09=09=09keylen;=0A+=09bool=09=09is_nss;=0A+}=09=09=09= cipher_implementation;=0A+=0A+typedef=20struct=20nss_cipher=0A+{=0A+=09= const=20cipher_implementation=20*impl;=0A+=09NSSInitContext=20*context;=0A= +=09PK11Context=20*crypt_context;=0A+=09SECItem=20=20=20=20*params;=0A+=0A= +=09PK11SymKey=20*encrypt_key;=0A+=09PK11SymKey=20*decrypt_key;=0A+}=09=09= =09nss_cipher;=0A+=0A+typedef=20struct=20internal_cipher=0A+{=0A+=09= const=20cipher_implementation=20*impl;=0A+=09BlowfishContext=20context;=0A= +}=09=09=09internal_cipher;=0A+=0A+typedef=20struct=20nss_cipher_ref=0A= +{=0A+=09const=20char=20*name;=0A+=09const=20cipher_implementation=20= *impl;=0A+}=09=09=09nss_cipher_ref;=0A+=0A+/*=0A+=20*=20Prototypes=0A+=20= */=0A+static=20unsigned=20nss_get_iv_size(PX_Cipher=20*pxc);=0A+static=20= unsigned=20nss_get_block_size(PX_Cipher=20*pxc);=0A+=0A+/*=0A+=20*=20= nss_GetHashOidTagByHashType=0A+=20*=0A+=20*=20Returns=20the=20= corresponding=20SECOidTag=20for=20the=20passed=20hash=20type.=20NSS=20= 3.43=0A+=20*=20includes=20HASH_GetHashOidTagByHashType=20for=20this=20= purpose,=20but=20at=20the=20time=20of=0A+=20*=20writing=20is=20not=20= commonly=20available=20so=20we=20need=20our=20own=20version=20till=20= then.=0A+=20*/=0A+static=20SECOidTag=0A= +nss_GetHashOidTagByHashType(HASH_HashType=20type)=0A+{=0A+=09if=20(type=20= =3D=3D=20HASH_AlgMD2)=0A+=09=09return=20SEC_OID_MD2;=0A+=09if=20(type=20= =3D=3D=20HASH_AlgMD5)=0A+=09=09return=20SEC_OID_MD5;=0A+=09if=20(type=20= =3D=3D=20HASH_AlgSHA1)=0A+=09=09return=20SEC_OID_SHA1;=0A+=09if=20(type=20= =3D=3D=20HASH_AlgSHA224)=0A+=09=09return=20SEC_OID_SHA224;=0A+=09if=20= (type=20=3D=3D=20HASH_AlgSHA256)=0A+=09=09return=20SEC_OID_SHA256;=0A+=09= if=20(type=20=3D=3D=20HASH_AlgSHA384)=0A+=09=09return=20SEC_OID_SHA384;=0A= +=09if=20(type=20=3D=3D=20HASH_AlgSHA512)=0A+=09=09return=20= SEC_OID_SHA512;=0A+=0A+=09return=20SEC_OID_UNKNOWN;=0A+}=0A+=0A+static=20= unsigned=0A+nss_digest_block_size(PX_MD=20*pxmd)=0A+{=0A+=09nss_digest=20= *digest=20=3D=20(nss_digest=20*)=20pxmd->p.ptr;=0A+=09const=20= SECHashObject=20*object;=0A+=0A+=09object=20=3D=20= HASH_GetHashObject(digest->hash_type);=0A+=09return=20= object->blocklength;=0A+}=0A+=0A+static=20unsigned=0A= +nss_digest_result_size(PX_MD=20*pxmd)=0A+{=0A+=09nss_digest=20*digest=20= =3D=20(nss_digest=20*)=20pxmd->p.ptr;=0A+=09const=20SECHashObject=20= *object;=0A+=0A+=09object=20=3D=20HASH_GetHashObject(digest->hash_type);=0A= +=09return=20object->length;=0A+}=0A+=0A+static=20void=0A= +nss_digest_free(PX_MD=20*pxmd)=0A+{=0A+=09nss_digest=20*digest=20=3D=20= (nss_digest=20*)=20pxmd->p.ptr;=0A+=09PRBool=09=09free_ctx=20=3D=20= PR_TRUE;=0A+=0A+=09PK11_DestroyContext(digest->hash_context,=20= free_ctx);=0A+=09NSS_ShutdownContext(digest->context);=0A+}=0A+=0A= +static=20void=0A+nss_digest_update(PX_MD=20*pxmd,=20const=20uint8=20= *data,=20unsigned=20dlen)=0A+{=0A+=09nss_digest=20*digest=20=3D=20= (nss_digest=20*)=20pxmd->p.ptr;=0A+=0A+=09= PK11_DigestOp(digest->hash_context,=20data,=20dlen);=0A+}=0A+=0A+static=20= void=0A+nss_digest_reset(PX_MD=20*pxmd)=0A+{=0A+=09nss_digest=20*digest=20= =3D=20(nss_digest=20*)=20pxmd->p.ptr;=0A+=0A+=09= PK11_DigestBegin(digest->hash_context);=0A+}=0A+=0A+static=20void=0A= +nss_digest_finish(PX_MD=20*pxmd,=20uint8=20*dst)=0A+{=0A+=09unsigned=20= int=20outlen;=0A+=09nss_digest=20*digest=20=3D=20(nss_digest=20*)=20= pxmd->p.ptr;=0A+=09const=20SECHashObject=20*object;=0A+=0A+=09object=20=3D= =20HASH_GetHashObject(digest->hash_type);=0A+=09= PK11_DigestFinal(digest->hash_context,=20dst,=20&outlen,=20= object->length);=0A+}=0A+=0A+int=0A+px_find_digest(const=20char=20*name,=20= PX_MD=20**res)=0A+{=0A+=09PX_MD=09=20=20=20*pxmd;=0A+=09= NSSInitParameters=20params;=0A+=09NSSInitContext=20*nss_context;=0A+=09= bool=09=09found=20=3D=20false;=0A+=09nss_digest=20*digest;=0A+=09= SECStatus=09status;=0A+=09SECOidData=20*hash;=0A+=09HASH_HashType=20t;=0A= +=0A+=09/*=0A+=09=20*=20Initialize=20our=20own=20NSS=20context=20without=20= a=20database=20backing=20it.=0A+=09=20*/=0A+=09memset(¶ms,=200,=20= sizeof(params));=0A+=09params.length=20=3D=20sizeof(params);=0A+=09= nss_context=20=3D=20NSS_InitContext("",=20"",=20"",=20"",=20¶ms,=0A+=09= =09=09=09=09=09=09=09=20=20NSS_INIT_READONLY=20|=20NSS_INIT_NOCERTDB=20|=0A= +=09=09=09=09=09=09=09=09=20=20NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20= |=0A+=09=09=09=09=09=09=09=09=20=20NSS_INIT_NOROOTINIT=20|=20= NSS_INIT_PK11RELOAD);=0A+=0A+=09/*=0A+=09=20*=20There=20is=20no=20API=20= function=20for=20looking=20up=20a=20digest=20algorithm=20from=20a=20name=0A= +=09=20*=20string,=20but=20there=20is=20a=20publicly=20accessible=20= array=20which=20can=20be=20scanned=0A+=09=20*=20for=20the=20name.=0A+=09=20= */=0A+=09for=20(t=20=3D=20HASH_AlgNULL=20+=201;=20t=20<=20HASH_AlgTOTAL;=20= t++)=0A+=09{=0A+=09=09SECOidTag=09hash_oid;=0A+=09=09char=09=20=20=20*p;=0A= +=0A+=09=09hash_oid=20=3D=20nss_GetHashOidTagByHashType(t);=0A+=0A+=09=09= if=20(hash_oid=20=3D=3D=20SEC_OID_UNKNOWN)=0A+=09=09=09return=20= PXE_NO_HASH;=0A+=0A+=09=09hash=20=3D=20SECOID_FindOIDByTag(hash_oid);=0A= +=09=09if=20(pg_strcasecmp(hash->desc,=20name)=20=3D=3D=200)=0A+=09=09{=0A= +=09=09=09found=20=3D=20true;=0A+=09=09=09break;=0A+=09=09}=0A+=0A+=09=09= /*=0A+=09=09=20*=20NSS=20saves=20the=20algorithm=20names=20using=20= SHA-xxx=20notation=20whereas=0A+=09=09=20*=20OpenSSL=20use=20SHAxxx.=20= To=20make=20sure=20the=20user=20finds=20the=20requested=0A+=09=09=20*=20= algorithm=20let's=20remove=20the=20dash=20and=20compare=20that=20= spelling=20as=20well.=0A+=09=09=20*/=0A+=09=09if=20((p=20=3D=20= strchr(hash->desc,=20'-'))=20!=3D=20NULL)=0A+=09=09{=0A+=09=09=09char=09=09= tmp[12];=0A+=0A+=09=09=09memcpy(tmp,=20hash->desc,=20p=20-=20= hash->desc);=0A+=09=09=09memcpy(tmp=20+=20(p=20-=20hash->desc),=20p=20+=20= 1,=20strlen(hash->desc)=20-=20(p=20-=20hash->desc)=20+=201);=0A+=09=09=09= if=20(pg_strcasecmp(tmp,=20name)=20=3D=3D=200)=0A+=09=09=09{=0A+=09=09=09= =09found=20=3D=20true;=0A+=09=09=09=09break;=0A+=09=09=09}=0A+=09=09}=0A= +=09}=0A+=0A+=09if=20(!found)=0A+=09=09return=20PXE_NO_HASH;=0A+=0A+=09= digest=20=3D=20palloc(sizeof(*digest));=0A+=0A+=09digest->context=20=3D=20= nss_context;=0A+=09digest->hash_context=20=3D=20= PK11_CreateDigestContext(hash->offset);=0A+=09digest->hash_type=20=3D=20= t;=0A+=09if=20(digest->hash_context=20=3D=3D=20NULL)=0A+=09{=0A+=09=09= pfree(digest);=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09status=20=3D=20= PK11_DigestBegin(digest->hash_context);=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09PK11_DestroyContext(digest->hash_context,=20= PR_TRUE);=0A+=09=09pfree(digest);=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09= pxmd=20=3D=20palloc(sizeof(*pxmd));=0A+=09pxmd->result_size=20=3D=20= nss_digest_result_size;=0A+=09pxmd->block_size=20=3D=20= nss_digest_block_size;=0A+=09pxmd->reset=20=3D=20nss_digest_reset;=0A+=09= pxmd->update=20=3D=20nss_digest_update;=0A+=09pxmd->finish=20=3D=20= nss_digest_finish;=0A+=09pxmd->free=20=3D=20nss_digest_free;=0A+=09= pxmd->p.ptr=20=3D=20(void=20*)=20digest;=0A+=0A+=09*res=20=3D=20pxmd;=0A= +=0A+=09return=200;=0A+}=0A+=0A+static=20int=0A+bf_init(PX_Cipher=20= *pxc,=20const=20uint8=20*key,=20unsigned=20klen,=20const=20uint8=20*iv)=0A= +{=0A+=09internal_cipher=20*cipher=20=3D=20(internal_cipher=20*)=20= pxc->ptr;=0A+=0A+=09blowfish_setkey(&cipher->context,=20key,=20klen);=0A= +=09if=20(iv)=0A+=09=09blowfish_setiv(&cipher->context,=20iv);=0A+=0A+=09= return=200;=0A+}=0A+=0A+static=20int=0A+bf_encrypt(PX_Cipher=20*pxc,=20= const=20uint8=20*data,=20unsigned=20dlen,=20uint8=20*res)=0A+{=0A+=09= internal_cipher=20*cipher=20=3D=20(internal_cipher=20*)=20pxc->ptr;=0A+=09= uint8=09=20=20=20*buf;=0A+=0A+=09if=20(dlen=20=3D=3D=200)=0A+=09=09= return=200;=0A+=0A+=09if=20(dlen=20&=207)=0A+=09=09return=20= PXE_NOTBLOCKSIZE;=0A+=0A+=09buf=20=3D=20palloc(dlen);=0A+=09memcpy(buf,=20= data,=20dlen);=0A+=0A+=09if=20(cipher->impl->mechanism.internal=20=3D=3D=20= BLOWFISH_ECB)=0A+=09=09blowfish_encrypt_ecb(buf,=20dlen,=20= &cipher->context);=0A+=09else=0A+=09=09blowfish_encrypt_cbc(buf,=20dlen,=20= &cipher->context);=0A+=0A+=09memcpy(res,=20buf,=20dlen);=0A+=09= pfree(buf);=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20int=0A= +bf_decrypt(PX_Cipher=20*pxc,=20const=20uint8=20*data,=20unsigned=20= dlen,=20uint8=20*res)=0A+{=0A+=09internal_cipher=20*cipher=20=3D=20= (internal_cipher=20*)=20pxc->ptr;=0A+=0A+=09if=20(dlen=20=3D=3D=200)=0A+=09= =09return=200;=0A+=0A+=09if=20(dlen=20&=207)=0A+=09=09return=20= PXE_NOTBLOCKSIZE;=0A+=0A+=09memcpy(res,=20data,=20dlen);=0A+=09if=20= (cipher->impl->mechanism.internal=20=3D=3D=20BLOWFISH_ECB)=0A+=09=09= blowfish_decrypt_ecb(res,=20dlen,=20&cipher->context);=0A+=09else=0A+=09=09= blowfish_decrypt_cbc(res,=20dlen,=20&cipher->context);=0A+=0A+=09return=20= 0;=0A+}=0A+=0A+static=20void=0A+bf_free(PX_Cipher=20*pxc)=0A+{=0A+=09= internal_cipher=20*cipher=20=3D=20(internal_cipher=20*)=20pxc->ptr;=0A+=0A= +=09pfree(cipher);=0A+=09pfree(pxc);=0A+}=0A+=0A+static=20int=0A= +nss_symkey_blockcipher_init(PX_Cipher=20*pxc,=20const=20uint8=20*key,=20= unsigned=20klen,=0A+=09=09=09=09=09=09=09const=20uint8=20*iv)=0A+{=0A+=09= nss_cipher=20*cipher=20=3D=20(nss_cipher=20*)=20pxc->ptr;=0A+=09SECItem=09= =09iv_item;=0A+=09unsigned=20char=20*iv_item_data;=0A+=09SECItem=09=09= key_item;=0A+=09int=09=09=09keylen;=0A+=09PK11SlotInfo=20*slot;=0A+=0A+=09= if=20(cipher->impl->mechanism.nss=20=3D=3D=20CKM_AES_CBC=20||=0A+=09=09= cipher->impl->mechanism.nss=20=3D=3D=20CKM_AES_ECB)=0A+=09{=0A+=09=09if=20= (klen=20<=3D=20128=20/=208)=0A+=09=09=09keylen=20=3D=20128=20/=208;=0A+=09= =09else=20if=20(klen=20<=3D=20192=20/=208)=0A+=09=09=09keylen=20=3D=20= 192=20/=208;=0A+=09=09else=20if=20(klen=20<=3D=20256=20/=208)=0A+=09=09=09= keylen=20=3D=20256=20/=208;=0A+=09=09else=0A+=09=09=09return=20= PXE_CIPHER_INIT;=0A+=09}=0A+=09else=0A+=09=09keylen=20=3D=20= cipher->impl->keylen;=0A+=0A+=09key_item.type=20=3D=20siBuffer;=0A+=09= key_item.data=20=3D=20(unsigned=20char=20*)=20key;=0A+=09key_item.len=20= =3D=20keylen;=0A+=0A+=09/*=0A+=09=20*=20If=20hardware=20acceleration=20= is=20configured=20in=20NSS=20one=20can=20theoretically=20get=0A+=09=20*=20= a=20better=20slot=20by=20calling=20PK11_GetBestSlot()=20with=20the=20= mechanism=20passed=0A+=09=20*=20to=20it.=20Unless=20there=20are=20= complaints,=20using=20the=20simpler=20API=20will=20make=0A+=09=20*=20= error=20handling=20easier=20though.=0A+=09=20*/=0A+=09slot=20=3D=20= PK11_GetInternalSlot();=0A+=09if=20(!slot)=0A+=09=09return=20= PXE_CIPHER_INIT;=0A+=0A+=09/*=0A+=09=20*=20The=20key=20must=20be=20set=20= up=20for=20the=20operation,=20and=20since=20we=20don't=20know=20at=0A+=09= =20*=20this=20point=20whether=20we=20are=20asked=20to=20encrypt=20or=20= decrypt=20we=20need=20to=20store=0A+=09=20*=20both=20versions.=0A+=09=20= */=0A+=09cipher->decrypt_key=20=3D=20PK11_ImportSymKey(slot,=20= cipher->impl->mechanism.nss,=0A+=09=09=09=09=09=09=09=09=09=09=09= PK11_OriginUnwrap,=0A+=09=09=09=09=09=09=09=09=09=09=09CKA_DECRYPT,=20= &key_item,=0A+=09=09=09=09=09=09=09=09=09=09=09NULL);=0A+=09= cipher->encrypt_key=20=3D=20PK11_ImportSymKey(slot,=20= cipher->impl->mechanism.nss,=0A+=09=09=09=09=09=09=09=09=09=09=09= PK11_OriginUnwrap,=0A+=09=09=09=09=09=09=09=09=09=09=09CKA_ENCRYPT,=20= &key_item,=0A+=09=09=09=09=09=09=09=09=09=09=09NULL);=0A+=09= PK11_FreeSlot(slot);=0A+=0A+=09if=20(!cipher->decrypt_key=20||=20= !cipher->encrypt_key)=0A+=09=09return=20PXE_CIPHER_INIT;=0A+=0A+=09if=20= (iv)=0A+=09{=0A+=09=09iv_item.type=20=3D=20siBuffer;=0A+=09=09= iv_item.data=20=3D=20(unsigned=20char=20*)=20iv;=0A+=09=09iv_item.len=20= =3D=20nss_get_iv_size(pxc);=0A+=09}=0A+=09else=0A+=09{=0A+=09=09/*=0A+=09= =09=20*=20The=20documentation=20states=20that=20either=20passing=20.data=20= =3D=200;=20.len=20=3D=200;=0A+=09=09=20*=20in=20the=20iv_item,=20or=20= NULL=20as=20iv_item,=20to=20PK11_ParamFromIV=20should=20be=0A+=09=09=20*=20= done=20when=20IV=20is=20missing.=20That=20however=20leads=20to=20= segfaults=20in=20the=0A+=09=09=20*=20library,=20the=20workaround=20that=20= works=20in=20modern=20=20library=20versions=20is=0A+=09=09=20*=20to=20= pass=20in=20a=20keysized=20zeroed=20out=20IV.=0A+=09=09=20*/=0A+=09=09= iv_item_data=20=3D=20palloc0(nss_get_iv_size(pxc));=0A+=09=09= iv_item.type=20=3D=20siBuffer;=0A+=09=09iv_item.data=20=3D=20= iv_item_data;=0A+=09=09iv_item.len=20=3D=20nss_get_iv_size(pxc);=0A+=09}=0A= +=0A+=09cipher->params=20=3D=20= PK11_ParamFromIV(cipher->impl->mechanism.nss,=20&iv_item);=0A+=0A+=09/*=20= If=20we=20had=20to=20make=20a=20mock=20IV,=20free=20it=20once=20made=20= into=20a=20param=20*/=0A+=09if=20(!iv)=0A+=09=09pfree(iv_item_data);=0A+=0A= +=09if=20(cipher->params=20=3D=3D=20NULL)=0A+=09=09return=20= PXE_CIPHER_INIT;=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20int=0A= +nss_decrypt(PX_Cipher=20*pxc,=20const=20uint8=20*data,=20unsigned=20= dlen,=20uint8=20*res)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= (nss_cipher=20*)=20pxc->ptr;=0A+=09SECStatus=09status;=0A+=09int=09=09=09= outlen;=0A+=0A+=09if=20(!cipher->crypt_context)=0A+=09{=0A+=09=09= cipher->crypt_context=20=3D=0A+=09=09=09= PK11_CreateContextBySymKey(cipher->impl->mechanism.nss,=20CKA_DECRYPT,=0A= +=09=09=09=09=09=09=09=09=09=20=20=20cipher->decrypt_key,=20= cipher->params);=0A+=09}=0A+=0A+=09status=20=3D=20= PK11_CipherOp(cipher->crypt_context,=20res,=20&outlen,=20dlen,=20data,=20= dlen);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20= PXE_DECRYPT_FAILED;=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20int=0A= +nss_encrypt(PX_Cipher=20*pxc,=20const=20uint8=20*data,=20unsigned=20= dlen,=20uint8=20*res)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= (nss_cipher=20*)=20pxc->ptr;=0A+=09SECStatus=09status;=0A+=09int=09=09=09= outlen;=0A+=0A+=09if=20(!cipher->crypt_context)=0A+=09{=0A+=09=09= cipher->crypt_context=20=3D=0A+=09=09=09= PK11_CreateContextBySymKey(cipher->impl->mechanism.nss,=20CKA_ENCRYPT,=0A= +=09=09=09=09=09=09=09=09=09=20=20=20cipher->decrypt_key,=20= cipher->params);=0A+=09}=0A+=0A+=09status=20=3D=20= PK11_CipherOp(cipher->crypt_context,=20res,=20&outlen,=20dlen,=20data,=20= dlen);=0A+=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20= PXE_DECRYPT_FAILED;=0A+=0A+=09return=200;=0A+}=0A+=0A+static=20void=0A= +nss_free(PX_Cipher=20*pxc)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= pxc->ptr;=0A+=09PRBool=09=09free_ctx=20=3D=20PR_TRUE;=0A+=0A+=09= PK11_FreeSymKey(cipher->encrypt_key);=0A+=09= PK11_FreeSymKey(cipher->decrypt_key);=0A+=09= PK11_DestroyContext(cipher->crypt_context,=20free_ctx);=0A+=09= NSS_ShutdownContext(cipher->context);=0A+=09pfree(cipher);=0A+=0A+=09= pfree(pxc);=0A+}=0A+=0A+static=20unsigned=0A= +nss_get_block_size(PX_Cipher=20*pxc)=0A+{=0A+=09nss_cipher=20*cipher=20= =3D=20pxc->ptr;=0A+=0A+=09return=20= PK11_GetBlockSize(cipher->impl->mechanism.nss,=20NULL);=0A+}=0A+=0A= +static=20unsigned=0A+nss_get_key_size(PX_Cipher=20*pxc)=0A+{=0A+=09= nss_cipher=20*cipher=20=3D=20pxc->ptr;=0A+=0A+=09return=20= cipher->impl->keylen;=0A+}=0A+=0A+static=20unsigned=0A= +nss_get_iv_size(PX_Cipher=20*pxc)=0A+{=0A+=09nss_cipher=20*cipher=20=3D=20= pxc->ptr;=0A+=0A+=09return=20= PK11_GetIVLength(cipher->impl->mechanism.nss);=0A+}=0A+=0A+static=20= unsigned=0A+bf_get_block_size(PX_Cipher=20*pxc)=0A+{=0A+=09return=208;=0A= +}=0A+=0A+static=20unsigned=0A+bf_get_key_size(PX_Cipher=20*pxc)=0A+{=0A= +=09return=20448=20/=208;=0A+}=0A+=0A+static=20unsigned=0A= +bf_get_iv_size(PX_Cipher=20*pxc)=0A+{=0A+=09return=208;=0A+}=0A+=0A+/*=0A= +=20*=20Cipher=20Implementations=0A+=20*/=0A+static=20const=20= cipher_implementation=20nss_des_cbc=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES_CBC,=0A+=09.keylen=20=3D=20= 8,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_des_ecb=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES_ECB,=0A+=09.keylen=20=3D=20= 8,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_des3_cbc=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES3_CBC,=0A+=09.keylen=20=3D=20= 24,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_des3_ecb=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_DES3_ECB,=0A+=09.keylen=20=3D=20= 24,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_aes_cbc=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_AES_CBC,=0A+=09.keylen=20=3D=20= 32,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_aes_ecb=20=3D=20{=0A+=09.init=20=3D=20= nss_symkey_blockcipher_init,=0A+=09.get_block_size=20=3D=20= nss_get_block_size,=0A+=09.get_key_size=20=3D=20nss_get_key_size,=0A+=09= .get_iv_size=20=3D=20nss_get_iv_size,=0A+=09.encrypt=20=3D=20= nss_encrypt,=0A+=09.decrypt=20=3D=20nss_decrypt,=0A+=09.free=20=3D=20= nss_free,=0A+=09.mechanism.nss=20=3D=20CKM_AES_ECB,=0A+=09.keylen=20=3D=20= 32,=0A+=09.is_nss=20=3D=20true=0A+};=0A+=0A+static=20const=20= cipher_implementation=20nss_bf_ecb=20=3D=20{=0A+=09.init=20=3D=20= bf_init,=0A+=09.get_block_size=20=3D=20bf_get_block_size,=0A+=09= .get_key_size=20=3D=20bf_get_key_size,=0A+=09.get_iv_size=20=3D=20= bf_get_iv_size,=0A+=09.encrypt=20=3D=20bf_encrypt,=0A+=09.decrypt=20=3D=20= bf_decrypt,=0A+=09.free=20=3D=20bf_free,=0A+=09.mechanism.internal=20=3D=20= BLOWFISH_ECB,=0A+=09.keylen=20=3D=2056,=0A+=09.is_nss=20=3D=20false=0A= +};=0A+=0A+static=20const=20cipher_implementation=20nss_bf_cbc=20=3D=20{=0A= +=09.init=20=3D=20bf_init,=0A+=09.get_block_size=20=3D=20= bf_get_block_size,=0A+=09.get_key_size=20=3D=20bf_get_key_size,=0A+=09= .get_iv_size=20=3D=20bf_get_iv_size,=0A+=09.encrypt=20=3D=20bf_encrypt,=0A= +=09.decrypt=20=3D=20bf_decrypt,=0A+=09.free=20=3D=20bf_free,=0A+=09= .mechanism.internal=20=3D=20BLOWFISH_CBC,=0A+=09.keylen=20=3D=2056,=0A+=09= .is_nss=20=3D=20false=0A+};=0A+=0A+/*=0A+=20*=20Lookup=20table=20for=20= finding=20the=20implementation=20based=20on=20a=20name.=20CAST5=20as=20= well=0A+=20*=20as=20BLOWFISH=20are=20defined=20as=20cipher=20mechanisms=20= in=20NSS=20but=20error=20out=20with=0A+=20*=20= SEC_ERROR_INVALID_ALGORITHM.=20Blowfish=20is=20implemented=20using=20the=20= internal=0A+=20*=20implementation=20while=20CAST5=20isn't=20supported=20= at=20all=20at=20this=20time,=0A+=20*/=0A+static=20const=20nss_cipher_ref=20= nss_cipher_lookup[]=20=3D=20{=0A+=09{"des",=20&nss_des_cbc},=0A+=09= {"des-cbc",=20&nss_des_cbc},=0A+=09{"des-ecb",=20&nss_des_ecb},=0A+=09= {"des3-cbc",=20&nss_des3_cbc},=0A+=09{"3des",=20&nss_des3_cbc},=0A+=09= {"3des-cbc",=20&nss_des3_cbc},=0A+=09{"des3-ecb",=20&nss_des3_ecb},=0A+=09= {"3des-ecb",=20&nss_des3_ecb},=0A+=09{"aes",=20&nss_aes_cbc},=0A+=09= {"aes-cbc",=20&nss_aes_cbc},=0A+=09{"aes-ecb",=20&nss_aes_ecb},=0A+=09= {"rijndael",=20&nss_aes_cbc},=0A+=09{"rijndael-cbc",=20&nss_aes_cbc},=0A= +=09{"rijndael-ecb",=20&nss_aes_ecb},=0A+=09{"blowfish",=20&nss_bf_cbc},=0A= +=09{"blowfish-cbc",=20&nss_bf_cbc},=0A+=09{"blowfish-ecb",=20= &nss_bf_ecb},=0A+=09{"bf",=20&nss_bf_cbc},=0A+=09{"bf-cbc",=20= &nss_bf_cbc},=0A+=09{"bf-ecb",=20&nss_bf_ecb},=0A+=09{NULL}=0A+};=0A+=0A= +/*=0A+=20*=20px_find_cipher=0A+=20*=0A+=20*=20Search=20for=20the=20= requested=20cipher=20and=20see=20if=20there=20is=20support=20for=20it,=20= and=20if=0A+=20*=20so=20return=20an=20allocated=20object=20containing=20= the=20playbook=20for=20how=20to=20encrypt=0A+=20*=20and=20decrypt=20= using=20the=20cipher.=0A+=20*/=0A+int=0A+px_find_cipher(const=20char=20= *alias,=20PX_Cipher=20**res)=0A+{=0A+=09const=20nss_cipher_ref=20= *cipher_ref;=0A+=09PX_Cipher=20=20*px_cipher;=0A+=09NSSInitParameters=20= params;=0A+=09NSSInitContext=20*nss_context;=0A+=09nss_cipher=20*cipher;=0A= +=09internal_cipher=20*int_cipher;=0A+=0A+=09for=20(cipher_ref=20=3D=20= nss_cipher_lookup;=20cipher_ref->name;=20cipher_ref++)=0A+=09{=0A+=09=09= if=20(strcmp(cipher_ref->name,=20alias)=20=3D=3D=200)=0A+=09=09=09break;=0A= +=09}=0A+=0A+=09if=20(!cipher_ref->name)=0A+=09=09return=20= PXE_NO_CIPHER;=0A+=0A+=09/*=0A+=09=20*=20Fill=20in=20the=20PX_Cipher=20= to=20pass=20back=20to=20PX=20describing=20the=20operations=20to=0A+=09=20= *=20perform=20in=20order=20to=20use=20the=20cipher.=0A+=09=20*/=0A+=09= px_cipher=20=3D=20palloc(sizeof(*px_cipher));=0A+=09= px_cipher->block_size=20=3D=20cipher_ref->impl->get_block_size;=0A+=09= px_cipher->key_size=20=3D=20cipher_ref->impl->get_key_size;=0A+=09= px_cipher->iv_size=20=3D=20cipher_ref->impl->get_iv_size;=0A+=09= px_cipher->free=20=3D=20cipher_ref->impl->free;=0A+=09px_cipher->init=20= =3D=20cipher_ref->impl->init;=0A+=09px_cipher->encrypt=20=3D=20= cipher_ref->impl->encrypt;=0A+=09px_cipher->decrypt=20=3D=20= cipher_ref->impl->decrypt;=0A+=0A+=09/*=0A+=09=20*=20Set=20the=20private=20= data,=20which=20is=20different=20for=20NSS=20and=20internal=20ciphers=0A= +=09=20*/=0A+=09if=20(cipher_ref->impl->is_nss)=0A+=09{=0A+=09=09/*=0A+=09= =09=20*=20Initialize=20our=20own=20NSS=20context=20without=20a=20= database=20backing=20it.=20At=0A+=09=09=20*=20some=20point=20we=20might=20= want=20to=20allow=20users=20to=20use=20stored=20keys=20in=20the=0A+=09=09= =20*=20database=20rather=20than=20passing=20them=20via=20SELECT=20= encrypt(),=20and=20then=0A+=09=09=20*=20this=20need=20to=20be=20changed=20= to=20open=20a=20user=20specified=20database.=0A+=09=09=20*/=0A+=09=09= memset(¶ms,=200,=20sizeof(params));=0A+=09=09params.length=20=3D=20= sizeof(params);=0A+=09=09nss_context=20=3D=20NSS_InitContext("",=20"",=20= "",=20"",=20¶ms,=0A+=09=09=09=09=09=09=09=09=09=20=20= NSS_INIT_READONLY=20|=20NSS_INIT_NOCERTDB=20|=0A+=09=09=09=09=09=09=09=09= =09=20=20NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A+=09=09=09=09=09= =09=09=09=09=20=20NSS_INIT_NOROOTINIT=20|=20NSS_INIT_PK11RELOAD);=0A+=0A= +=09=09/*=20nss_cipher=20is=20the=20private=20state=20struct=20for=20the=20= operation=20*/=0A+=09=09cipher=20=3D=20palloc(sizeof(*cipher));=0A+=09=09= cipher->context=20=3D=20nss_context;=0A+=09=09cipher->impl=20=3D=20= cipher_ref->impl;=0A+=09=09cipher->crypt_context=20=3D=20NULL;=0A+=0A+=09= =09px_cipher->ptr=20=3D=20cipher;=0A+=09}=0A+=09else=0A+=09{=0A+=09=09= int_cipher=20=3D=20palloc0(sizeof(*int_cipher));=0A+=0A+=09=09= int_cipher->impl=20=3D=20cipher_ref->impl;=0A+=09=09px_cipher->ptr=20=3D=20= int_cipher;=0A+=09}=0A+=0A+=09*res=20=3D=20px_cipher;=0A+=09return=200;=0A= +}=0Adiff=20--git=20a/doc/src/sgml/pgcrypto.sgml=20= b/doc/src/sgml/pgcrypto.sgml=0Aindex=20b6bb23de0f..bf486f0c07=20100644=0A= ---=20a/doc/src/sgml/pgcrypto.sgml=0A+++=20b/doc/src/sgml/pgcrypto.sgml=0A= @@=20-45,8=20+45,9=20@@=20digest(data=20bytea,=20type=20text)=20returns=20= bytea=0A=20=20=20=20=20sha224,=20= sha256,=0A=20=20=20=20=20sha384=20= and=20sha512.=0A=20=20=20=20=20If=20= pgcrypto=20was=20built=20with=0A-=20=20=20=20= OpenSSL,=20more=20algorithms=20are=20= available,=20as=0A-=20=20=20=20detailed=20in=20.=0A+=20=20=20=20= OpenSSL=20or=20= NSS,=0A+=20=20=20=20more=20algorithms=20are=20= available,=20as=0A+=20=20=20=20detailed=20in=20.=0A=20=20=20=20=0A= =20=0A=20=20=20=20=0A@@=20-764,7=20+765,7=20@@=20= pgp_sym_encrypt(data,=20psw,=20'compress-algo=3D1,=20= cipher-algo=3Daes256')=0A=20=20=20=20=20Which=20cipher=20algorithm=20to=20= use.=0A=20=20=20=20=0A=20=0A-Values:=20bf,=20= aes128,=20aes192,=20aes256=20(OpenSSL-only:=203des,=20= cast5)=0A+Values:=20bf,=20aes128,=20aes192,=20aes256=20= (OpenSSL-only:=203des,=20cast5;=20= NSS-only:=203des)=0A=20Default:=20aes128=0A=20Applies=20= to:=20pgp_sym_encrypt,=20pgp_pub_encrypt=0A=20=0A@@=20= -1153,8=20+1154,8=20@@=20gen_random_uuid()=20returns=20uuid=0A=20=20=20=20= =0A=20=20=20=20=20pgcrypto=20configures=20= itself=20according=20to=20the=20findings=20of=20the=0A=20=20=20=20=20= main=20PostgreSQL=20configure=20script.=20=20The=20= options=20that=0A-=20=20=20=20affect=20it=20are=20= --with-zlib=20and=0A-=20=20=20=20= --with-ssl=3Dopenssl.=0A+=20=20=20=20affect=20it=20= are=20--with-zlib,=0A+=20=20=20=20= --with-ssl=3Dopenssl=20and=20= --with-ssl=3Dnss.=0A=20=20=20=20=0A=20=0A=20=20= =20=20=0A@@=20-1169,14=20+1170,16=20@@=20gen_random_uuid()=20= returns=20uuid=0A=20=20=20=20=20BIGNUM=20functions.=0A=20=20=20=20= =0A=20=0A-=20=20=20=0A= -=20=20=20=20Summary=20of=20Functionality=20with=20and=20without=20= OpenSSL=0A-=20=20=20=20=0A+=20=20=20=0A+=20=20=20=20Summary=20= of=20Functionality=20with=20and=20without=20external=20cryptographic=0A+=20= =20=20=20=20=20library=0A+=20=20=20=20=0A=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20= =20Functionality=0A=20=20=20=20=20=20=20=20= Built-in=0A=20=20=20=20=20=20=20=20With=20= OpenSSL=0A+=20=20=20=20=20=20=20With=20NSS=0A=20=20= =20=20=20=20=20=0A=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A@@=20-1184,51=20+1187,67=20@@=20gen_random_uuid()=20returns=20= uuid=0A=20=20=20=20=20=20=20=20MD5=0A=20=20=20=20=20=20=20= =20yes=0A=20=20=20=20=20=20=20=20yes=0A+=20= =20=20=20=20=20=20yes=0A=20=20=20=20=20=20=20=0A=20=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20=20SHA1=0A=20=20= =20=20=20=20=20=20yes=0A=20=20=20=20=20=20=20=20= yes=0A+=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20= SHA224/256/384/512=0A=20=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=20yes=0A+=20=20= =20=20=20=20=20yes=0A=20=20=20=20=20=20=20=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=20Other=20digest=20= algorithms=0A=20=20=20=20=20=20=20=20no=0A=20=20=20= =20=20=20=20=20yes=20(Note=201)=0A+=20=20=20=20=20=20=20= yes=20(Note=201)=0A=20=20=20=20=20=20=20=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=20Blowfish=0A=20= =20=20=20=20=20=20=20yes=0A=20=20=20=20=20=20=20=20= yes=0A+=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20= AES=0A=20=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=20yes=0A+=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20DES/3DES/CAST5=0A=20=20=20= =20=20=20=20=20no=0A=20=20=20=20=20=20=20=20= yes=0A+=20=20=20=20=20=20=20yes=0A+=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= CAST5=0A+=20=20=20=20=20=20=20no=0A+=20=20=20= =20=20=20=20yes=0A+=20=20=20=20=20=20=20no=0A= =20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20= =20=20=20Raw=20encryption=0A=20=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=20yes=0A+=20=20= =20=20=20=20=20yes=0A=20=20=20=20=20=20=20=0A=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=20PGP=20Symmetric=20= encryption=0A=20=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=20yes=0A+=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20PGP=20Public-Key=20= encryption=0A=20=20=20=20=20=20=20=20yes=0A=20=20=20= =20=20=20=20=20yes=0A+=20=20=20=20=20=20=20= yes=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A=20=20=20=20=20=0A@@=20-1241,7=20+1260,8=20@@=20= gen_random_uuid()=20returns=20uuid=0A=20=20=20=20=0A=20=20=20= =20=20=0A=20=20=20=20=20=20=0A-=20=20=20=20=20=20Any=20= digest=20algorithm=20OpenSSL=20supports=0A+=20= =20=20=20=20=20Any=20digest=20algorithm=20= OpenSSL=20and=0A+=20=20=20=20=20=20= NSS=20supports=0A=20=20=20=20=20=20=20is=20= automatically=20picked=20up.=0A=20=20=20=20=20=20=20This=20is=20not=20= possible=20with=20ciphers,=20which=20need=20to=20be=20supported=0A=20=20=20= =20=20=20=20explicitly.=0A--=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5 Content-Disposition: attachment; filename=v28-0005-nss-Documentation.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v28-0005-nss-Documentation.patch" Content-Transfer-Encoding: quoted-printable =46rom=20b225e9706348314cdf7f382e0dbf03c47e1a5c25=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:42=20+0100=0ASubject:=20[PATCH=20= v28=205/9]=20nss:=20Documentation=0A=0ABasic=20documentation=20of=20the=20= new=20API=20(keypass=20hooks)=20as=20well=20as=20config=0Aparameters=20= and=20installation.=20Additionally=20there=20is=20a=20section=20on=20how=0A= to=20create=20certificate=20and=20keys=20using=20the=20NSS=20toolchain.=0A= ---=0A=20doc/src/sgml/acronyms.sgml=20=20=20=20=20|=20=2043=20+++++=0A=20= doc/src/sgml/config.sgml=20=20=20=20=20=20=20|=20=2028=20++-=0A=20= doc/src/sgml/installation.sgml=20|=20=2031=20++-=0A=20= doc/src/sgml/libpq.sgml=20=20=20=20=20=20=20=20|=20340=20= +++++++++++++++++++++++++--------=0A=20doc/src/sgml/runtime.sgml=20=20=20= =20=20=20|=20124=20+++++++++++-=0A=205=20files=20changed,=20476=20= insertions(+),=2090=20deletions(-)=0A=0Adiff=20--git=20= a/doc/src/sgml/acronyms.sgml=20b/doc/src/sgml/acronyms.sgml=0Aindex=20= 4e5ec983c0..7b02c8a622=20100644=0A---=20a/doc/src/sgml/acronyms.sgml=0A= +++=20b/doc/src/sgml/acronyms.sgml=0A@@=20-441,6=20+441,28=20@@=0A=20=20=20= =20=20=0A=20=20=20=20=0A=20=0A+=20=20=20= =0A+=20=20=20=20NSPR=0A+=20= =20=20=20=0A+=20=20=20=20=20=0A+=20=20=20=20=20=20=0A= +=20=20=20=20=20=20Netscape=20Portable=20Runtime=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A+=20= =20=20=0A+=20=20=20=20NSS=0A= +=20=20=20=20=0A+=20=20=20=20=20=0A+=20=20=20=20=20=20= =0A= +=20=20=20=20=20=20Network=20Security=20Services=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A=20=20= =20=20=0A=20=20=20=20=20= ODBC=0A=20=20=20=20=20=0A@@=20= -539,6=20+561,17=20@@=0A=20=20=20=20=20=0A=20=20=20=20= =0A=20=0A+=20=20=20=0A+=20=20=20=20= PKCS#12=0A+=20=20=20=20=0A+=20=20= =20=20=20=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20= Public-Key=20Cryptography=20Standards=20#12=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A=20=20= =20=20=0A=20=20=20=20=20PL=0A= =20=20=20=20=20=0A@@=20-684,6=20+717,16=20@@=0A=20=20=20=20=20= =0A=20=20=20=20=0A=20=0A+=20=20=20= =0A+=20=20=20=20TLS=0A+=20=20= =20=20=0A+=20=20=20=20=20=0A+=20=20=20=20=20=20=0A+=20=20= =20=20=20=20Transport=20Layer=20Security=0A+=20=20=20=20=20= =0A+=20=20=20=20=0A+=20=20=20=0A+=0A=20=20= =20=20=0A=20=20=20=20=20= TOAST=0A=20=20=20=20=20=0Adiff=20= --git=20a/doc/src/sgml/config.sgml=20b/doc/src/sgml/config.sgml=0Aindex=20= e81141e45c..7719f2914d=20100644=0A---=20a/doc/src/sgml/config.sgml=0A+++=20= b/doc/src/sgml/config.sgml=0A@@=20-1272,6=20+1272,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-1288,7=20+1305,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-1490,8=20+1509,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=2066ad4ba938..3cbd125d59=20100644=0A---=20= a/doc/src/sgml/installation.sgml=0A+++=20= b/doc/src/sgml/installation.sgml=0A@@=20-976,14=20+976,31=20@@=20= build-postgresql:=0A=20=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =20=20=20=0A=20=20=20=20=20=20=20=20=20=20Build=20with=20support=20= for=20SSL=20(encrypted)=0A-=20=20=20=20=20=20=20=20=20= connections.=20The=20only=20LIBRARY=0A-=20=20=20= =20=20=20=20=20=20supported=20is=20.=20This=20= requires=20the=0A-=20=20=20=20=20=20=20=20=20= OpenSSL=20package=20to=20be=20installed.=0A-=20= =20=20=20=20=20=20=20=20configure=20will=20check=20= for=20the=20required=0A-=20=20=20=20=20=20=20=20=20header=20files=20and=20= libraries=20to=20make=20sure=20that=20your=0A-=20=20=20=20=20=20=20=20=20= OpenSSL=20installation=20is=20sufficient=0A-=20= =20=20=20=20=20=20=20=20before=20proceeding.=20=0A+=20=20=20=20=20=20=20=20= =20connections.=20LIBRARY=20must=20be=20one=20= of:=0A=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= =20to=20build=20with=20= OpenSSL=20support.=0A+=20=20=20=20=20=20=20=20= =20=20=20=20This=20requires=20the=20OpenSSL=0A= +=20=20=20=20=20=20=20=20=20=20=20=20package=20to=20be=20installed.=20=20= configure=20will=20check=0A+=20=20=20=20=20=20=20=20= =20=20=20=20for=20the=20required=20header=20files=20and=20libraries=20to=20= make=20sure=20that=0A+=20=20=20=20=20=20=20=20=20=20=20=20your=20= OpenSSL=20installation=20is=20sufficient=0A+=20= =20=20=20=20=20=20=20=20=20=20=20before=20proceeding.=0A+=20=20=20=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=20=20=20=20=20to=20build=20with=20= libnss=20support.=0A+=20=20=20=20=20=20=20=20=20= =20=20=20This=20requires=20the=20NSS=20= package=20to=20be=20installed.=20Additionally,=0A+=20=20=20=20=20=20=20=20= =20=20=20=20NSS=20requires=20= NSPR=0A+=20=20=20=20=20=20=20=20=20=20=20=20= to=20be=20installed.=20configure=20will=20check=20= for=20the=0A+=20=20=20=20=20=20=20=20=20=20=20=20required=20header=20= files=20and=20libraries=20to=20make=20sure=20that=20your=0A+=20=20=20=20=20= =20=20=20=20=20=20=20NSS=20installation=20is=20= sufficient=20before=0A+=20=20=20=20=20=20=20=20=20=20=20=20proceeding.=0A= +=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=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=20b/doc/src/sgml/libpq.sgml=0Aindex=20= 5e25f20843..f84896470a=20100644=0A---=20a/doc/src/sgml/libpq.sgml=0A+++=20= b/doc/src/sgml/libpq.sgml=0A@@=20-830,6=20+830,12=20@@=20int=20= callback_fn(char=20*buf,=20int=20size,=20PGconn=20*conn);=0A=20=20=20=20=20= =20=20=20longjmp(...),=20etc.=20It=20must=20return=20= normally.=0A=20=20=20=20=20=20=20=0A=20=0A+=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20= PQsetSSLKeyPassHook_OpenSSL=20has=20no=20effect=20= unless=0A+=20=20=20=20=20=20=20=20the=20server=20was=20compiled=20with=20= OpenSSL=0A+=20=20=20=20=20=20=20=20support.=0A= +=20=20=20=20=20=20=0A+=0A=20=20=20=20=20=20=0A=20=20=20= =20=20=0A=20=0A@@=20-846,6=20+852,70=20@@=20= PQsslKeyPassHook_OpenSSL_type=20PQgetSSLKeyPassHook_OpenSSL(void);=0A=20= =0A=20=20=20=20=20=20=20=0A=20=0A+=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20= PQgetSSLKeyPassHook_OpenSSL=20has=20no=20effect=20= unless=0A+=20=20=20=20=20=20=20=20the=20server=20was=20compiled=20with=20= OpenSSL=0A+=20=20=20=20=20=20=20=20support.=0A= +=20=20=20=20=20=20=0A+=0A+=20=20=20=20=20=0A+=20=20=20= =20=0A+=0A+=20=20=20=20=0A+=20=20=20=20=20= PQsetSSLKeyPassHook_nssPQse= tSSLKeyPassHook_nss=0A+=20=20=20=20=20= =0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= PQsetSSLKeyPassHook_nss=20lets=20an=20application=20= override=0A+=20=20=20=20=20=20=20libpq's=20= default=20handling=20of=20password=20protected=0A+=20=20=20=20=20=20=20= objects=20in=20the=20NSS=20database=20using=0A= +=20=20=20=20=20=20=20=20= or=20interactive=20prompting.=0A+=0A+=0A+void=20= PQsetSSLKeyPassHook_nss(PQsslKeyPassHook_nss_type=20hook);=0A= +=0A+=0A+=20=20=20=20=20=20=20The=20application=20passes=20a=20= pointer=20to=20a=20callback=20function=20with=20signature:=0A= +=0A+char=20*callback_fn(PK11SlotInfo=20*slot,=20PRBool=20= retry,=20void=20*arg);=0A+=0A+=20=20=20=20=20=20=20= which=20libpq=20will=20call=0A+=20=20=20=20=20= =20=20instead=20of=20its=20default=0A+=20=20=20=20=20= =20=20PQdefaultSSLKeyPassHook_nss=20password=20= handler.=20The=0A+=20=20=20=20=20=20=20callback=20should=20determine=20= the=20password=20for=20the=20token=20and=20return=20a=0A+=20=20=20=20=20=20= =20pointer=20to=20it.=20The=20returned=20pointer=20should=20be=20= allocated=20with=20the=20NSS=0A+=20=20=20=20=20=20=20= PORT_Strdup=20function.=20The=20token=20for=20which=20= the=0A+=20=20=20=20=20=20=20password=20is=20requested=20is=20recorded=20= in=20the=20slot=20anc=20can=20be=20identified=20by=0A+=20=20=20=20=20=20=20= calling=20PK11_GetTokenName.=20If=20no=20password=20= is=0A+=20=20=20=20=20=20=20known,=20the=20callback=20should=20return=20= NULL.=20The=20memory=0A+=20=20=20=20=20=20=20will=20= be=20owned=20by=20NSS=20and=20should=20not=20= be=0A+=20=20=20=20=20=20=20freed.=0A+=20=20=20=20=20=20=0A+=0A+=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= PQsetSSLKeyPassHook_nss=20has=20no=20effect=20= unless=0A+=20=20=20=20=20=20=20=20the=20server=20was=20compiled=20with=20= NSS=20support.=0A+=20=20=20=20=20=20=0A= +=20=20=20=20=20=0A+=20=20=20=20=0A+=0A+=20=20=20= =20=0A+=20=20=20=20=20= PQgetSSLKeyPassHook_nssPQge= tSSLKeyPassHook_nss=0A+=20=20=20=20=20= =0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= PQgetSSLKeyPassHook_nss=20returns=20the=20current=0A= +=20=20=20=20=20=20=20NSS=20password=20hook,=20= or=20NULL=0A+=20=20=20=20=20=20=20if=20none=20has=20= been=20set.=0A+=0A+=0A+PQsslKeyPassHook_nss_type=20= PQgetSSLKeyPassHook_nss(void);=0A+=0A+=20=20=20=20=20=20= =0A+=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= PQgetSSLKeyPassHook_nss=20has=20no=20effect=20= unless=20the=0A+=20=20=20=20=20=20=20=20server=20was=20compiled=20with=20= nss=20support.=0A+=20=20=20=20=20=20=0A= +=0A=20=20=20=20=20=20=0A=20=20=20=20=20=0A=20=0A= @@=20-1623,21=20+1693,31=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20=20=20= If=20set=20to=201,=20data=20sent=20over=20SSL=20connections=20will=20be=20= compressed.=20=20If=0A=20=20=20=20=20=20=20=20=20set=20to=200,=20= compression=20will=20be=20disabled.=20=20The=20default=20is=200.=20=20= This=0A=20=20=20=20=20=20=20=20=20parameter=20is=20ignored=20if=20a=20= connection=20without=20SSL=20is=20made.=0A-=20=20=20=20=20=20=20=0A= -=0A-=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20=20SSL=20= compression=20is=20nowadays=20considered=20insecure=20and=20its=20use=20= is=20no=0A-=20=20=20=20=20=20=20=20longer=20recommended.=20=20= OpenSSL=201.1.0=20disables=0A-=20=20=20=20=20=20= =20=20compression=20by=20default,=20and=20many=20operating=20system=20= distributions=0A-=20=20=20=20=20=20=20=20disable=20it=20in=20prior=20= versions=20as=20well,=20so=20setting=20this=20parameter=20to=20on=0A-=20=20= =20=20=20=20=20=20will=20not=20have=20any=20effect=20if=20the=20server=20= does=20not=20accept=20compression.=0A-=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=20longer=20recommended.=0A+=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= OpenSSL:=201.1.0=20disables=20compression=20= by=0A+=20=20=20=20=20=20=20=20=20=20=20default,=20and=20many=20operating=20= system=20distributions=20disable=20it=20in=20prior=0A+=20=20=20=20=20=20=20= =20=20=20=20versions=20as=20well,=20so=20setting=20this=20parameter=20to=20= on=20will=20not=20have=20any=0A+=20=20=20=20=20=20=20=20=20=20=20effect=20= if=20the=20server=20does=20not=20accept=20compression.=0A+=20=20=20=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20= =20=20=20=20=20=20=20=20If=20security=20is=20not=20a=20primary=20= concern,=20compression=20can=20improve=0A+=20=20=20=20=20=20=20=20=20=20=20= throughput=20if=20the=20network=20is=20the=20bottleneck.=20=20Disabling=20= compression=0A+=20=20=20=20=20=20=20=20=20=20=20can=20improve=20response=20= time=20and=20throughput=20if=20CPU=20performance=20is=20the=0A+=20=20=20=20= =20=20=20=20=20=20=20limiting=20factor.=0A+=20=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=0A=20=0A-=20=20=20=20=20= =20=20=0A-=20=20=20=20=20=20=20=20If=20security=20is=20not=20a=20= primary=20concern,=20compression=20can=20improve=0A-=20=20=20=20=20=20=20= =20throughput=20if=20the=20network=20is=20the=20bottleneck.=20=20= Disabling=20compression=0A-=20=20=20=20=20=20=20=20can=20improve=20= response=20time=20and=20throughput=20if=20CPU=20performance=20is=20the=0A= -=20=20=20=20=20=20=20=20limiting=20factor.=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20=20=20=20NSS:=20SSL=20compression=20is=20= not=20supported=20in=0A+=20=20=20=20=20=20=20=20=20=20=20= NSS,=20this=20parameter=20has=20no=20effect.=0A= +=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A@@=20-1646,10=20+1726,24=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20= sslcert=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20=20=20= This=20parameter=20specifies=20the=20file=20name=20of=20the=20client=20= SSL=0A-=20=20=20=20=20=20=20=20certificate,=20replacing=20the=20default=0A= -=20=20=20=20=20=20=20=20= ~/.postgresql/postgresql.crt.=0A-=20=20=20=20=20=20=20= =20This=20parameter=20is=20ignored=20if=20an=20SSL=20connection=20is=20= not=20made.=0A+=20=20=20=20=20=20=20=20This=20parameter=20specifies=20= the=20name=20or=20location=20of=20the=20client=20SSL=0A+=20=20=20=20=20=20= =20=20certificate.=20=20This=20parameter=20is=20ignored=20if=20an=20SSL=20= connection=20is=20not=0A+=20=20=20=20=20=20=20=20made.=0A+=20=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=20=20= =20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= OpenSSL:=20can=20replace=20the=20default=0A+=20= =20=20=20=20=20=20=20=20=20=20= ~/.postgresql/postgresql.crt.=0A+=20=20=20=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=0A+=20=20=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=20=20=20=20NSS:=20the=20= nickname=20of=20the=20client=20SSL=0A+=20=20=20=20=20=20=20=20=20=20=20= certificate.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20=20=0A=20=20=20= =20=20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20= =20=0A@@=20-1658,15=20+1752,30=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20= sslkey=0A=20=20=20=20=20=20=20=0A= =20=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20=20=20This=20= parameter=20specifies=20the=20location=20for=20the=20secret=20key=20used=20= for=0A-=20=20=20=20=20=20=20=20the=20client=20certificate.=20It=20can=20= either=20specify=20a=20file=20name=20that=20will=0A-=20=20=20=20=20=20=20= =20be=20used=20instead=20of=20the=20default=0A-=20=20=20=20=20=20=20=20= ~/.postgresql/postgresql.key,=20or=20it=20can=20= specify=20a=20key=0A-=20=20=20=20=20=20=20=20obtained=20from=20an=20= external=20engine=20(engines=20are=0A-=20=20=20=20=20=20=20= =20OpenSSL=20loadable=20modules).=20=20An=20= external=20engine=0A-=20=20=20=20=20=20=20=20specification=20should=20= consist=20of=20a=20colon-separated=20engine=20name=20and=0A-=20=20=20=20=20= =20=20=20an=20engine-specific=20key=20identifier.=20=20This=20parameter=20= is=20ignored=20if=20an=0A-=20=20=20=20=20=20=20=20SSL=20connection=20is=20= not=20made.=0A+=20=20=20=20=20=20=20=20This=20parameter=20specifies=20= the=20name=20or=20location=20for=20the=20secret=20key=20used=0A+=20=20=20= =20=20=20=20=20for=20the=20client=20certificate.=20This=20parameter=20is=20= ignored=20if=20an=20SSL=0A+=20=20=20=20=20=20=20=20connection=20is=20not=20= made.=0A+=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= =20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20= =20=20=20=20=20OpenSSL:=20can=20either=20= specify=20a=20file=20name=0A+=20=20=20=20=20=20=20=20=20=20=20that=20= will=20be=20used=20instead=20of=20the=20default=0A+=20=20=20=20=20=20=20=20= =20=20=20~/.postgresql/postgresql.key,=20or=20it=20= can=20specify=0A+=20=20=20=20=20=20=20=20=20=20=20a=20key=20obtained=20= from=20an=20external=20engine=20(engines=20are=0A+=20=20=20= =20=20=20=20=20=20=20=20OpenSSL=20loadable=20= modules).=20=20An=20external=0A+=20=20=20=20=20=20=20=20=20=20=20engine=20= specification=20should=20consist=20of=20a=20colon-separated=20engine=20= name=0A+=20=20=20=20=20=20=20=20=20=20=20and=20an=20engine-specific=20= key=20identifier.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=20=20=0A+=0A+=20=20=20=20=20=20=20=20=20=0A= +=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= NSS:=20this=20parameter=20has=20no=20effect.=20= =20Keys=0A+=20=20=20=20=20=20=20=20=20=20=20should=20be=20loaded=20into=20= the=20NSS=0A+=20=20=20=20=20=20=20=20=20=20=20= database.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=20=0A=20=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A@@=20-1677,28=20+1786,44=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20=20This=20parameter=20specifies=20the=20= password=20for=20the=20secret=20key=20specified=20in=0A=20=20=20=20=20=20= =20=20=20sslkey,=20allowing=20client=20certificate=20= private=20keys=0A-=20=20=20=20=20=20=20=20to=20be=20stored=20in=20= encrypted=20form=20on=20disk=20even=20when=20interactive=20passphrase=0A= +=20=20=20=20=20=20=20=20to=20be=20stored=20in=20encrypted=20form=20even=20= when=20interactive=20passphrase=0A=20=20=20=20=20=20=20=20=20input=20is=20= not=20practical.=0A-=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20=20= =0A-=20=20=20=20=20=20=20=20Specifying=20this=20parameter=20with=20= any=20non-empty=20value=20suppresses=20the=0A-=20=20=20=20=20=20=20=20= Enter=20PEM=20pass=20phrase:=0A-=20=20=20=20=20=20=20=20= prompt=20that=20OpenSSL=20will=20emit=20by=20= default=0A-=20=20=20=20=20=20=20=20when=20an=20encrypted=20client=20= certificate=20key=20is=20provided=20to=0A-=20=20=20=20=20=20=20=20= libpq.=0A-=20=20=20=20=20=20=20=0A-=20=20=20=20= =20=20=20=0A-=20=20=20=20=20=20=20=20If=20the=20key=20is=20not=20= encrypted=20this=20parameter=20is=20ignored.=20The=20parameter=0A-=20=20=20= =20=20=20=20=20has=20no=20effect=20on=20keys=20specified=20by=20= OpenSSL=0A-=20=20=20=20=20=20=20=20engines=20= unless=20the=20engine=20uses=20the=20OpenSSL=0A= -=20=20=20=20=20=20=20=20password=20callback=20mechanism=20for=20= prompts.=0A-=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20=20=0A= -=20=20=20=20=20=20=20=20There=20is=20no=20environment=20variable=20= equivalent=20to=20this=20option,=20and=20no=0A-=20=20=20=20=20=20=20=20= facility=20for=20looking=20it=20up=20in=20.pgpass.=20= It=20can=20be=0A-=20=20=20=20=20=20=20=20used=20in=20a=20service=20file=20= connection=20definition.=20Users=20with=0A-=20=20=20=20=20=20=20=20more=20= sophisticated=20uses=20should=20consider=20using=20openssl=20engines=20= and=0A-=20=20=20=20=20=20=20=20tools=20like=20PKCS#11=20or=20USB=20= crypto=20offload=20devices.=0A+=20=20=20=20=20=20=20=20=0A= +=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=20=20= OpenSSL:=20specifying=20this=20parameter=20= with=0A+=20=20=20=20=20=20=20=20=20=20=20any=20non-empty=20value=20= suppresses=20the=0A+=20=20=20=20=20=20=20=20=20=20=20Enter=20= PEM=20pass=20phrase:=20prompt=20that=0A+=20=20=20=20=20=20=20=20= =20=20=20OpenSSL=20will=20emit=20by=20default=20= when=20an=0A+=20=20=20=20=20=20=20=20=20=20=20encrypted=20client=20= certificate=20key=20is=20provided=20to=0A+=20=20=20=20=20=20=20=20=20=20=20= libpq.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20If=20= the=20key=20is=20not=20encrypted=20this=20parameter=20is=20ignored.=20= The=20parameter=0A+=20=20=20=20=20=20=20=20=20=20=20has=20no=20effect=20= on=20keys=20specified=20by=20OpenSSL=0A+=20=20= =20=20=20=20=20=20=20=20=20engines=20unless=20the=20engine=20uses=20the=20= OpenSSL=0A+=20=20=20=20=20=20=20=20=20=20=20= password=20callback=20mechanism=20for=20prompts.=0A+=20=20=20=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=20=20=20=20There=20is=20no=20environment=20variable=20equivalent=20= to=20this=20option,=20and=20no=0A+=20=20=20=20=20=20=20=20=20=20=20= facility=20for=20looking=20it=20up=20in=20.pgpass.=20= It=20can=20be=0A+=20=20=20=20=20=20=20=20=20=20=20used=20in=20a=20= service=20file=20connection=20definition.=20Users=20with=0A+=20=20=20=20=20= =20=20=20=20=20=20more=20sophisticated=20uses=20should=20consider=20= using=0A+=20=20=20=20=20=20=20=20=20=20=20= OpenSSL=20engines=20and=20tools=20like=20= PKCS#11=20or=0A+=20=20=20=20=20=20=20=20=20=20=20USB=20crypto=20offload=20= devices.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20=20=0A+=0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20= =20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= NSS:=20specifying=20the=20parameter=20is=20= required=0A+=20=20=20=20=20=20=20=20=20=20=20in=20case=20any=20password=20= protected=20items=20are=20referenced=20in=20the=0A+=20=20=20=20=20=20=20=20= =20=20=20NSS=20database,=20or=20if=20the=20= database=20itself=0A+=20=20=20=20=20=20=20=20=20=20=20is=20password=20= protected.=20=20If=20multiple=20different=20objects=20are=20password=0A+=20= =20=20=20=20=20=20=20=20=20=20protected,=20the=20same=20password=20is=20= used=20for=20all.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=0A=20= =20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20= =20=20=20=0A@@=20-1707,11=20+1832,27=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20= sslrootcert=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20=20=20= This=20parameter=20specifies=20the=20name=20of=20a=20file=20containing=20= SSL=0A-=20=20=20=20=20=20=20=20certificate=20authority=20= (CA)=20certificate(s).=0A-=20=20=20=20=20=20=20=20If=20= the=20file=20exists,=20the=20server's=20certificate=20will=20be=20= verified=0A-=20=20=20=20=20=20=20=20to=20be=20signed=20by=20one=20of=20= these=20authorities.=20=20The=20default=20is=0A-=20=20=20=20=20=20=20=20= ~/.postgresql/root.crt.=0A+=20=20=20=20=20=20=20=20= This=20parameter=20specifies=20the=20name=20of=20SSL=20certificate=20= authority=0A+=20=20=20=20=20=20=20=20(CA)=20= certificate(s).=0A+=20=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20= =20=20=20=20=20=20=20=20=20OpenSSL:=20= specifies=20the=20name=20of=20a=20file=0A+=20=20=20=20=20=20=20=20=20=20=20= containing=20SSL=20certificate=20authority=20(CA)=0A+=20= =20=20=20=20=20=20=20=20=20=20certificate(s).=20=20If=20the=20file=20= exists,=20the=20server's=20certificate=20will=0A+=20=20=20=20=20=20=20=20= =20=20=20be=20verified=20to=20be=20signed=20by=20one=20of=20these=20= authorities.=20=20The=20default=20is=0A+=20=20=20=20=20=20=20=20=20=20=20= ~/.postgresql/root.crt.=0A+=20=20=20=20=20=20=20=20=20= =20=0A+=20=20=20=20=20=20=20=20=20=0A+=0A+=20=20=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20= =20=20=20=20=20=20=20=20NSS:=20this=20= parameter=20has=20no=20effect.=20=20CA=0A+=20=20=20=20=20=20=20=20=20=20=20= certificates=20should=20be=20loaded=20into=20the=20= NSS=0A+=20=20=20=20=20=20=20=20=20=20=20= database=20using=20the=20certutil=20tool.=0A+=20= =20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A@@=20-1721,13=20+1862,29=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20=20=20= This=20parameter=20specifies=20the=20file=20name=20of=20the=20SSL=20= certificate=0A-=20=20=20=20=20=20=20=20revocation=20list=20(CRL).=20=20= Certificates=20listed=20in=20this=20file,=20if=20it=0A-=20=20=20=20=20=20= =20=20exists,=20will=20be=20rejected=20while=20attempting=20to=20= authenticate=20the=0A-=20=20=20=20=20=20=20=20server's=20certificate.=20=20= If=20neither=0A-=20=20=20=20=20=20=20=20=20nor=0A-=20=20=20=20=20=20=20=20= =20is=20set,=20this=20= setting=20is=0A-=20=20=20=20=20=20=20=20taken=20as=0A-=20=20=20=20=20=20=20= =20~/.postgresql/root.crl.=0A+=20=20=20=20=20=20=20=20= revocation=20list=20(CRL).=20=20=0A+=0A+=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= OpenSSL:=20Certificates=20listed=20in=20this=20= file,=0A+=20=20=20=20=20=20=20=20=20=20=20if=20it=20exists,=20will=20be=20= rejected=20while=20attempting=20to=20authenticate=20the=0A+=20=20=20=20=20= =20=20=20=20=20=20server's=20certificate.=20=20If=20neither=0A+=20=20=20=20= =20=20=20=20=20=20=20=20nor=0A= +=20=20=20=20=20=20=20=20=20=20=20=20is=20set,=20this=20setting=20is=0A= +=20=20=20=20=20=20=20=20=20=20=20taken=20as=20= ~/.postgresql/root.crl.=20=0A+=20=20=20=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=0A+=20=20=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20= =20=20=20=20=20=20=20=20=20NSS:=20This=20= parameter=20has=20no=20effect.=20=20CRL=0A+=20=20=20=20=20=20=20=20=20=20= =20files=20should=20be=20loaded=20into=20the=20= NSS=0A+=20=20=20=20=20=20=20=20=20=20=20= database=20using=20the=20crlutil=20tool.=0A+=20= =20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=0A+=0A=20=20=20=20= =20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A@@=20-1740,18=20+1897,30=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20=20=20= revocation=20list=20(CRL).=20=20Certificates=20listed=20in=20the=20files=20= in=20this=0A=20=20=20=20=20=20=20=20=20directory,=20if=20it=20exists,=20= will=20be=20rejected=20while=20attempting=20to=0A=20=20=20=20=20=20=20=20= =20authenticate=20the=20server's=20certificate.=0A-=20=20=20=20=20=20=20= =0A=20=0A-=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20=20=20= The=20directory=20needs=20to=20be=20prepared=20with=20the=20OpenSSL=20= command=0A-=20=20=20=20=20=20=20=20openssl=20rehash=20= or=20c_rehash.=20=20See=0A-=20=20=20=20=20=20=20=20= its=20documentation=20for=20details.=0A-=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20=20=20=20OpenSSL:=20the=20directory=20= needs=20to=20be=0A+=20=20=20=20=20=20=20=20=20=20=20prepared=20with=20= the=20OpenSSL=20command=20openssl=20rehash=0A+=20=20=20= =20=20=20=20=20=20=20=20or=20c_rehash.=20=20See=20its=20= documentation=20for=20details.=0A+=20=20=20=20=20=20=20=20=20=20=0A= +=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= Both=20sslcrl=20and=20sslcrldir=20= can=0A+=20=20=20=20=20=20=20=20=20=20=20be=20specified=20together.=0A+=20= =20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A=20=0A-=20=20=20=20=20=20=20=0A-=20=20=20=20=20=20=20= =20Both=20sslcrl=20and=20sslcrldir=20= can=20be=0A-=20=20=20=20=20=20=20=20specified=20together.=0A+=20=20=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20= =20=20=20=20=20=20=20=20=20NSS:=20This=20= parameter=20has=20no=20effect.=20=20CRL=0A+=20=20=20=20=20=20=20=20=20=20= =20files=20should=20be=20loaded=20into=20the=20= NSS=0A+=20=20=20=20=20=20=20=20=20=20=20= database=20using=20the=20crlutil=20tool.=0A+=20= =20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =20=20=0A+=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20= =0A=20=0A@@=20-1786,8=20+1955,8=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20=20=20= for=20the=20connection.=20Valid=20values=20are=20= TLSv1,=0A=20=20=20=20=20=20=20=20=20= TLSv1.1,=20TLSv1.2=20and=0A=20=20=20= =20=20=20=20=20=20TLSv1.3.=20The=20supported=20= protocols=20depend=20on=20the=0A-=20=20=20=20=20=20=20=20version=20of=20= OpenSSL=20used,=20older=20versions=0A-=20=20=20= =20=20=20=20=20not=20supporting=20the=20most=20modern=20protocol=20= versions.=20If=20not=20specified,=0A+=20=20=20=20=20=20=20=20version=20= of=20the=20SSL=20library=20used,=20older=20versions=20may=20=0A+=20=20=20= =20=20=20=20=20not=20support=20the=20most=20modern=20protocol=20= versions.=20If=20not=20specified,=0A=20=20=20=20=20=20=20=20=20the=20= default=20is=20TLSv1.2,=20which=20satisfies=20= industry=0A=20=20=20=20=20=20=20=20=20best=20practices=20as=20of=20this=20= writing.=0A=20=20=20=20=20=20=20=20=0A@@=20-1802,8=20+1971,8=20@@=20= postgresql://%2Fvar%2Flib%2Fpostgresql/dbname=0A=20=20=20=20=20=20=20=20=20= for=20the=20connection.=20Valid=20values=20are=20= TLSv1,=0A=20=20=20=20=20=20=20=20=20= TLSv1.1,=20TLSv1.2=20and=0A=20=20=20= =20=20=20=20=20=20TLSv1.3.=20The=20supported=20= protocols=20depend=20on=20the=0A-=20=20=20=20=20=20=20=20version=20of=20= OpenSSL=20used,=20older=20versions=0A-=20=20=20= =20=20=20=20=20not=20supporting=20the=20most=20modern=20protocol=20= versions.=20If=20not=20set,=20this=0A+=20=20=20=20=20=20=20=20version=20= of=20the=20SSL=20library=20used,=20older=20versions=0A+=20=20=20=20=20=20= =20=20may=20not=20support=20the=20most=20modern=20protocol=20versions.=20= If=20not=20set,=20this=0A=20=20=20=20=20=20=20=20=20parameter=20is=20= ignored=20and=20the=20connection=20will=20use=20the=20maximum=20bound=0A=20= =20=20=20=20=20=20=20=20defined=20by=20the=20backend,=20if=20set.=20= Setting=20the=20maximum=20protocol=20version=0A=20=20=20=20=20=20=20=20=20= is=20mainly=20useful=20for=20testing=20or=20if=20some=20component=20has=20= issues=20working=0A@@=20-2523,6=20+2692,8=20@@=20void=20= *PQsslStruct(const=20PGconn=20*conn,=20const=20char=20*struct_name);=0A=20= =20=20=20=20=20=20=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20= =20=20=20The=20struct(s)=20available=20depend=20on=20the=20SSL=20= implementation=20in=20use.=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=0A=20=20=20=20=20=20=20=20For=20= OpenSSL,=20there=20is=20one=20struct,=0A=20=20= =20=20=20=20=20=20available=20under=20the=20name=20"OpenSSL",=20and=20it=20= returns=20a=20pointer=20to=20the=0A=20=20=20=20=20=20=20=20= OpenSSL=20SSL=20struct.=0A= @@=20-2546,9=20+2717,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-2575,6=20+2751,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-8008,6=20+8188,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= -8034,6=20+8219,11=20@@=20void=20PQinitSSL(int=20do_ssl);=0A=20=20=20=20=20= =20=20=20might=20be=20preferable=20for=20applications=20that=20need=20to=20= work=20with=20older=0A=20=20=20=20=20=20=20=20versions=20of=20= libpq.=0A=20=20=20=20=20=20=20=0A+=0A+=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20This=20function=20does=20= nothing=20when=20using=20NSS=20as=0A+=20=20=20= =20=20=20=20the=20SSL=20library.=0A+=20=20=20=20=20=20= =0A=20=20=20=20=20=20=0A=20=20=20=20=20=0A= =20=20=20=20=0Adiff=20--git=20a/doc/src/sgml/runtime.sgml=20= b/doc/src/sgml/runtime.sgml=0Aindex=20bf877c0e0c..1fcad17a51=20100644=0A= ---=20a/doc/src/sgml/runtime.sgml=0A+++=20b/doc/src/sgml/runtime.sgml=0A= @@=20-2185,15=20+2185,21=20@@=20pg_dumpall=20-p=205432=20|=20psql=20-d=20= postgres=20-p=205433=0A=20=0A=20=20=20=0A=20= =20=20=20SSL=0A+=20=20=20TLS=0A= =20=20=20=0A=20=0A=20=20=20=0A=20=20=20=20= PostgreSQL=20has=20native=20support=20for=20= using=0A=20=20=20=20SSL=20connections=20to=20encrypt=20= client/server=20communications=0A=20=20=20=20for=20increased=20security.=20= This=20requires=20that=0A-=20=20=20OpenSSL=20= is=20installed=20on=20both=20client=20and=0A+=20=20=20a=20supported=20= TLS=20library=20is=20installed=20on=20both=20client=20and=0A=20=20=20=20= server=20systems=20and=20that=20support=20in=20= PostgreSQL=20is=0A=20=20=20=20enabled=20at=20= build=20time=20(see=20).=0A+=20=20=20= Supported=20libraries=20are=20OpenSSL=20and=0A= +=20=20=20NSS.=20The=20terms=20= SSL=20and=0A+=20=20=20TLS=20are=20= often=20used=20interchangeably=20to=20mean=20a=20secure=0A+=20=20=20= connection=20using=20a=20TLS=20protocol,=20even=20= though=0A+=20=20=20SSL=20protocols=20are=20no=20= longer=20supported.=0A=20=20=20=0A=20=0A=20=20=20=0A@@=20-2213,8=20+2219,13=20@@=20pg_dumpall=20-p=20= 5432=20|=20psql=20-d=20postgres=20-p=205433=0A=20=20=20=0A=20=0A=20= =20=20=0A-=20=20=20To=20start=20in=20SSL=20= mode,=20files=20containing=20the=20server=20certificate=0A-=20=20=20and=20= private=20key=20must=20exist.=20=20By=20default,=20these=20files=20are=20= expected=20to=20be=0A+=20=20=20To=20start=20in=20SSL=20= mode,=20a=20server=20certificate=0A+=20=20=20and=20private=20key=20must=20= exist.=20The=20below=20sections=20on=20the=20different=20libraries=0A+=20= =20=20will=20discuss=20how=20to=20configure=20these.=0A+=20=20=0A= +=20=20=20=0A+=20=20=0A+=20=20=20By=20default,=20these=20files=20= are=20expected=20to=20be=0A=20=20=20=20named=20= server.crt=20and=20server.key,=20= respectively,=20in=0A=20=20=20=20the=20server's=20data=20directory,=20= but=20other=20names=20and=20locations=20can=20be=20specified=0A=20=20=20=20= using=20the=20configuration=20parameters=20=0A@@=20-2304,6=20+2315,18=20@@=20= pg_dumpall=20-p=205432=20|=20psql=20-d=20postgres=20-p=205433=0A=20=20=20= =0A=20=20=20=0A=20=0A+=20=20= =0A+=20=20=20NSS=20Configuration=0A+=0A+=20=20=0A+=20= =20=20PostgreSQL=20will=20look=20for=20= certificates=20and=20keys=0A+=20=20=20in=20the=20= NSS=20database=20specified=20by=20the=20= parameter=0A+=20=20=20=20in=20= postgresql.conf.=0A+=20=20=20The=20parameters=20for=20= certificate=20and=20key=20filenames=20are=20used=20to=20identify=20the=0A= +=20=20=20nicknames=20in=20the=20database.=0A+=20=20=0A+=20=20= =0A+=0A=20=20=20=0A=20=20= =20=20Using=20Client=20Certificates=0A=20=0A@@=20-2378,7=20= +2401,7=20@@=20pg_dumpall=20-p=205432=20|=20psql=20-d=20postgres=20-p=20= 5433=0A=20=20=20=0A=20=0A=20=20=20=0A-=20=20=20SSL=20Server=20File=20= Usage=0A+=20=20=20SSL=20Server=20File=20Parameter=20= Usage=0A=20=0A=20=20=20=20=0A=20=20=20=20=20=20summarizes=20the=20files=20that=20are=0A= @@=20-2425,6=20+2448,14=20@@=20pg_dumpall=20-p=205432=20|=20psql=20-d=20= postgres=20-p=205433=0A=20=20=20=20=20=20=20client=20certificate=20= must=20not=20be=20on=20this=20list=0A=20=20=20=20=20=20=0A=20= =0A+=20=20=20=20=20=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20=20= certificate=20database=0A+=20=20=20=20=20=20= contains=20server=20certificates,=20keys=20and=20revocation=20= lists;=20only=0A+=20=20=20=20=20=20used=20when=20= PostgreSQL=20is=20built=20with=20support=0A+=20= =20=20=20=20=20for=20NSS.=0A+=20=20=20= =20=20=0A+=0A=20=20=20=20=20=0A=20=20=20=20=0A=20=20= =20=0A@@=20-2448,7=20+2479,7=20@@=20pg_dumpall=20-p=205432=20|=20= psql=20-d=20postgres=20-p=205433=0A=20=20=20=0A=20=0A=20=20=20= =0A-=20=20=20Creating=20= Certificates=0A+=20=20=20Creating=20Certificates=20with=20= OpenSSL=0A=20=0A=20=20=20=20=0A=20=20=20=20=20=20To=20= create=20a=20simple=20self-signed=20certificate=20for=20the=20server,=20= valid=20for=20365=0A@@=20-2552,6=20+2583,89=20@@=20openssl=20x509=20-req=20= -in=20server.csr=20-text=20-days=20365=20\=0A=20=20=20=20=0A=20=20= =20=0A=20=0A+=20=20=0A+=20= =20=20NSS=20Certificate=20Databases=0A+=0A+=20=20=20= =0A+=20=20=20=20When=20using=20NSS,=20= all=20certificates=20and=20keys=20must=0A+=20=20=20=20be=20loaded=20into=20= an=20NSS=20certificate=20database.=0A+=20=20=20= =0A+=0A+=20=20=20=0A+=20=20=20=20To=20create=20a=20new=20= NSS=20certificate=20database=20and=0A+=20=20=20= =20load=20the=20certificates=20created=20in=20,=0A+=20=20=20=20use=20the=20= following=20NSS=20commands:=0A= +=0A+certutil=20-d=20"sql:server.db"=20-N=20= --empty-password=0A+certutil=20-d=20"sql:server.db"=20-A=20-n=20= server.crt=20-i=20server.crt=20-t=20"CT,C,C"=0A+certutil=20-d=20= "sql:server.db"=20-A=20-n=20root.crt=20-i=20root.crt=20-t=20"CT,C,C"=0A= +=0A+=20=20=20=20This=20will=20give=20the=20certificate=20= the=20filename=20as=20the=20nickname=20identifier=20in=0A+=20=20=20=20= the=20database=20which=20is=20created=20as=20= server.db.=0A+=20=20=20=0A+=20=20=20=0A= +=20=20=20=20Then=20load=20the=20server=20key,=20which=20require=20= converting=20it=20to=0A+=20=20=20=20PKCS#12=20format=20= using=20the=0A+=20=20=20=20OpenSSL=20tools:=0A= +=0A+openssl=20pkcs12=20-export=20-out=20server.pfx=20= -inkey=20server.key=20-in=20server.crt=20\=0A+=20=20-certfile=20root.crt=20= -passout=20pass:=0A+pk12util=20-i=20server.pfx=20-d=20server.db=20-W=20= ''=0A+=0A+=20=20=20=0A+=20=20=20=0A+=20=20=20= =20Finally=20a=20certificate=20revocation=20list=20can=20be=20loaded=20= with=20the=20following=0A+=20=20=20=20commands:=0A+=0A= +crlutil=20-I=20-i=20server.crl=20-d=20server.db=20-B=0A= +=0A+=20=20=20=0A+=20=20=0A+=0A+=20=20= =0A+=20=20=20= Creating=20Certificates=20with=20NSS=0A+=0A+=20=20=20= =0A+=20=20=20=20To=20create=20a=20simple=20self-signed=20CA=20and=20= certificate=20for=20the=20server,=20use=20the=0A+=20=20=20=20following=20= NSS=20commands.=20Replace=0A+=20=20=20=20= *.yourdomain.com=20with=20the=20server's=20= host=0A+=20=20=20=20name.=20Remove=20= --empty-password=20in=20order=20to=20set=0A+=20= =20=20=20a=20password=20protecting=20the=20databases.=20The=20password=20= can=20be=20passed=20to=0A+=20=20=20=20= certutil=20with=20the=20-f=20= parameter.=0A+=20=20=20=20First=20create=20a=20self-signed=20CA.=20To=20= use=20a=20different=20certificate=20validity=0A+=20=20=20=20time=20than=20= the=20default,=20use=20-v=20to=20specify=20= the=0A+=20=20=20=20number=20of=20months=20of=20validity.=0A= +=0A+mkdir=20root_ca.db=0A+certutil=20-N=20-d=20= "sql:root_ca.db/"=20--empty-password=0A+certutil=20-S=20-d=20= "sql:root_ca.db/"=20-n=20root_ca=20-s=20= "CN=3Dca.yourdomain.com"=20\=0A+=20=20-x=20-k=20= rsa=20-g=202048=20-m=205432=20-t=20= CTu,CTu,CTu=20\=0A+=20=20--keyUsage=20certSigning=20-2=20--nsCertType=20= sslCA,smimeCA,objectSigningCA=20\=0A+=20=20-Z=20SHA256=0A+certutil=20-L=20= -d=20"sql:root_ca.db/"=20-n=20root_ca=20-a=20>=20root_ca.pem=0A= +=0A+=20=20=20=20Now=20create=20a=20server=20= certificate=20database,=20and=20create=20a=20certificate=20signing=0A+=20= =20=20=20request=20for=20the=20CA.=20Then=20sign=20the=20request=20with=20= the=20already=20created=20CA=20and=0A+=20=20=20=20insert=20the=20= certificate=20chain=20into=20the=20certificate=20database.=0A= +=0A+mkdir=20server_cert.db=0A+certutil=20-N=20-d=20= "sql:server_cert.db/"=20--empty-password=0A+certutil=20-R=20-d=20= "sql:server_cert.db/"=20-s=20"CN=3Ddbhost.yourdomain.com"=20\=0A+=20=20= -o=20server_cert.csr=20-g=202048=20-Z=20SHA256=0A+=0A+certutil=20-C=20-d=20= "sql:root_ca.db/"=20-c=20root_ca=20-i=20server_cert.csr=20\=0A+=20=20-o=20= server_cert.der=20-m=205433=20\=0A+=20=20= --keyUsage=20keyEncipherment,dataEncipherment,digitalSignature=20\=0A+=20= =20--nsCertType=20sslServer=20-Z=20SHA256=0A+=0A+certutil=20-A=20-d=20= "sql:server_cert.db/"=20-n=20root_ca=20-t=20CTu,CTu,CTu=20-a=20-i=20= root_ca.pem=0A+certutil=20-A=20-d=20"sql:server_cert.db/"=20-n=20= server_cert=20-t=20CTu,CTu,CTu=20-i=20server_cert.der=0A= +=0A+=20=20=20=20The=20server=20certificate=20is=20= loaded=20into=20the=20certificate=20database=20as=20well=20as=0A+=20=20=20= =20the=20CA=20certificate=20in=20order=20to=20provide=20the=20chain=20of=20= certificates.=0A+=20=20=20=0A+=20=20=0A+=0A=20=20=0A= =20=0A=20=20=0A--=20=0A2.21.1=20(Apple=20= Git-122.3)=0A=0A= --Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5 Content-Disposition: attachment; filename=v28-0004-nss-pg_strong_random-support.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v28-0004-nss-pg_strong_random-support.patch" Content-Transfer-Encoding: quoted-printable =46rom=2092a89e2af330650b7307ac85447e07dd1f809b45=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:39=20+0100=0ASubject:=20[PATCH=20= v28=204/9]=20nss:=20pg_strong_random=20support=0A=0AThis=20adds=20= support=20for=20using=20the=20RNG=20in=20libnss=20as=20a=20backend=20for=0A= pg_strong_random.=0A---=0A=20src/port/pg_strong_random.c=20|=2050=20= ++++++++++++++++++++++++++++++++++++-=0A=201=20file=20changed,=2049=20= insertions(+),=201=20deletion(-)=0A=0Adiff=20--git=20= a/src/port/pg_strong_random.c=20b/src/port/pg_strong_random.c=0Aindex=20= 07f24c0089..40de237628=20100644=0A---=20a/src/port/pg_strong_random.c=0A= +++=20b/src/port/pg_strong_random.c=0A@@=20-137,7=20+137,55=20@@=20= pg_strong_random(void=20*buf,=20size_t=20len)=0A=20=09return=20false;=0A=20= }=0A=20=0A-#else=09=09=09=09=09=09=09/*=20not=20USE_OPENSSL=20or=20WIN32=20= */=0A+#elif=20defined(USE_NSS)=0A+=0A+#define=20pg_BITS_PER_BYTE=20= BITS_PER_BYTE=0A+#undef=20BITS_PER_BYTE=0A+#define=20NO_NSPR_10_SUPPORT=0A= +#include=20=0A+#include=20=0A+#if=20= defined(BITS_PER_BYTE)=0A+#if=20BITS_PER_BYTE=20!=3D=20pg_BITS_PER_BYTE=0A= +#error=20"incompatible=20byte=20widths=20between=20NSPR=20and=20= postgres"=0A+#endif=0A+#else=0A+#define=20BITS_PER_BYTE=20= pg_BITS_PER_BYTE=0A+#endif=0A+#undef=20pg_BITS_PER_BYTE=0A+=0A+void=0A= +pg_strong_random_init(void)=0A+{=0A+=09/*=20No=20initialization=20= needed=20on=20NSS=20*/=0A+}=0A+=0A+bool=0A+pg_strong_random(void=20*buf,=20= size_t=20len)=0A+{=0A+=09NSSInitParameters=20params;=0A+=09= NSSInitContext=20*nss_context;=0A+=09SECStatus=09status;=0A+=0A+=09= memset(¶ms,=200,=20sizeof(params));=0A+=09params.length=20=3D=20= sizeof(params);=0A+=09nss_context=20=3D=20NSS_InitContext("",=20"",=20= "",=20"",=20¶ms,=0A+=09=09=09=09=09=09=09=09=20=20NSS_INIT_READONLY=20= |=20NSS_INIT_NOCERTDB=20|=0A+=09=09=09=09=09=09=09=09=20=20= NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A+=09=09=09=09=09=09=09=09= =20=20NSS_INIT_NOROOTINIT=20|=20NSS_INIT_PK11RELOAD);=0A+=0A+=09if=20= (!nss_context)=0A+=09=09return=20false;=0A+=0A+=09status=20=3D=20= PK11_GenerateRandom(buf,=20len);=0A+=09NSS_ShutdownContext(nss_context);=0A= +=0A+=09if=20(status=20=3D=3D=20SECSuccess)=0A+=09=09return=20true;=0A+=0A= +=09return=20false;=0A+}=0A+=0A+#else=09=09=09=09=09=09=09/*=20not=20= USE_OPENSSL,=20USE_NSS=20or=20WIN32=20*/=0A=20=0A=20/*=0A=20=20*=20= Without=20OpenSSL=20or=20Win32=20support,=20just=20read=20/dev/urandom=20= ourselves.=0A--=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5 Content-Disposition: attachment; filename=v28-0003-nss-Add-NSS-specific-tests.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v28-0003-nss-Add-NSS-specific-tests.patch" Content-Transfer-Encoding: quoted-printable =46rom=2042f6b684ca1ae89c7a6aab3da74b6eeab583c51d=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:37=20+0100=0ASubject:=20[PATCH=20= v28=203/9]=20nss:=20Add=20NSS=20specific=20tests=0A=0AThis=20adds=20the=20= SSL/Backend/NSS=20which=20implements=20the=20setup=20and=20teardown=0A= required=20as=20well=20as=20adds=20the=20NSS=20configuration=20to=20the=20= existing=20tests.=0A=0AThe=20OpenSSL=20testfiles=20are=20reused=20by=20= repackaging=20them=20into=20NSS=20databases=0Ain=20order=20for=20the=20= tests=20to=20be=20cross-library.=20Additional=20testfiles=20are=0A= generated=20by=20using=20only=20the=20NSS=20toolchain=20as=20well=20as=20= rudimentary=20tests=0Ausing=20these.=0A---=0A=20src/test/ssl/Makefile=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20244=20= ++++++++++++++++++=0A=20src/test/ssl/t/001_ssltests.pl=20=20=20=20=20=20=20= =20|=20350=20++++++++++++++++++--------=0A=20src/test/ssl/t/002_scram.pl=20= =20=20=20=20=20=20=20=20=20=20|=20=2031=20++-=0A=20= src/test/ssl/t/SSL/Backend/NSS.pm=20=20=20=20=20|=20=2061=20+++++=0A=20= src/test/ssl/t/SSL/Backend/OpenSSL.pm=20|=20=2021=20+-=0A=20= src/test/ssl/t/SSL/Server.pm=20=20=20=20=20=20=20=20=20=20|=20=2044=20= +---=0A=206=20files=20changed,=20586=20insertions(+),=20165=20= deletions(-)=0A=20create=20mode=20100644=20= src/test/ssl/t/SSL/Backend/NSS.pm=0A=0Adiff=20--git=20= a/src/test/ssl/Makefile=20b/src/test/ssl/Makefile=0Aindex=20= 4b53fdf6c0..8d4afa9dd0=20100644=0A---=20a/src/test/ssl/Makefile=0A+++=20= b/src/test/ssl/Makefile=0A@@=20-33,6=20+33,36=20@@=20SSLFILES=20:=3D=20= $(CERTIFICATES:%=3Dssl/%.key)=20$(CERTIFICATES:%=3Dssl/%.crt)=20\=0A=20= SSLDIRS=20:=3D=20ssl/client-crldir=20ssl/server-crldir=20\=0A=20=09= ssl/root+client-crldir=20ssl/root+server-crldir=0A=20=0A+#=20Even=20= though=20we=20in=20practice=20could=20get=20away=20with=20far=20fewer=20= NSS=20databases,=20they=0A+#=20are=20generated=20to=20mimic=20the=20= setup=20for=20the=20OpenSSL=20tests=20in=20order=20to=20ensure=0A+#=20we=20= isolate=20the=20same=20behavior=20between=20the=20backends.=20The=20= database=20name=20should=0A+#=20contain=20the=20files=20included=20for=20= easier=20test=20suite=20code=20reading.=0A+NSSFILES=20:=3D=20= ssl/nss/client_ca.crt.db=20\=0A+=09ssl/nss/server_ca.crt.db=20\=0A+=09= ssl/nss/root+server_ca.crt.db=20\=0A+=09ssl/nss/root+client_ca.crt.db=20= \=0A+=09ssl/nss/client.crt__client.key.db=20\=0A+=09= ssl/nss/client-revoked.crt__client-revoked.key.db=20\=0A+=09= ssl/nss/server-cn-only.crt__server-password.key.db=20\=0A+=09= ssl/nss/server-cn-only.crt__server-cn-only.key.db=20\=0A+=09= ssl/nss/root.crl=20\=0A+=09ssl/nss/server.crl=20\=0A+=09= ssl/nss/client.crl=20\=0A+=09= ssl/nss/server-multiple-alt-names.crt__server-multiple-alt-names.key.db=20= \=0A+=09= ssl/nss/server-single-alt-name.crt__server-single-alt-name.key.db=20\=0A= +=09ssl/nss/server-cn-and-alt-names.crt__server-cn-and-alt-names.key.db=20= \=0A+=09ssl/nss/server-no-names.crt__server-no-names.key.db=20\=0A+=09= ssl/nss/server-revoked.crt__server-revoked.key.db=20\=0A+=09= ssl/nss/root+client.crl=20\=0A+=09= ssl/nss/client+client_ca.crt__client.key.db=20\=0A+=09= ssl/nss/client.crt__client-encrypted-pem.key.db=20\=0A+=09= ssl/nss/root+server_ca.crt__server.crl.db=20\=0A+=09= ssl/nss/root+server_ca.crt__root+server.crl.db=20\=0A+=09= ssl/nss/root+server_ca.crt__root+server.crldir.db=20\=0A+=09= ssl/nss/native_ca-root.db=20\=0A+=09ssl/nss/native_server-root.db=20\=0A= +=09ssl/nss/native_client-root.db=0A+=0A=20#=20This=20target=20= re-generates=20all=20the=20key=20and=20certificate=20files.=20Usually=20= we=20just=0A=20#=20use=20the=20ones=20that=20are=20committed=20to=20the=20= tree=20without=20rebuilding=20them.=0A=20#=0A@@=20-40,6=20+70,10=20@@=20= SSLDIRS=20:=3D=20ssl/client-crldir=20ssl/server-crldir=20\=0A=20#=0A=20= sslfiles:=20$(SSLFILES)=20$(SSLDIRS)=0A=20=0A+#=20Generate=20NSS=20= certificate=20databases=20corresponding=20to=20the=20OpenSSL=20= certificates.=0A+#=20This=20target=20will=20fail=20unless=20preceded=20= by=20nssfiles-clean.=0A+nssfiles:=20$(NSSFILES)=0A+=0A=20#=20OpenSSL=20= requires=20a=20directory=20to=20put=20all=20generated=20certificates=20= in.=20We=20don't=0A=20#=20use=20this=20for=20anything,=20but=20we=20need=20= a=20location.=0A=20ssl/new_certs_dir:=0A@@=20-67,6=20+101,35=20@@=20= ssl/%_ca.crt:=20ssl/%_ca.key=20%_ca.config=20ssl/root_ca.crt=20= ssl/new_certs_dir=0A=20=09rm=20ssl/temp_ca.crt=20ssl/temp_ca_signed.crt=0A= =20=09echo=20"01"=20>=20ssl/$*_ca.srl=0A=20=0A+ssl/nss/%_ca.crt.db:=20= ssl/%_ca.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20"sql:$@"=20-N=20= --empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20$*_ca.crt=20= -i=20ssl/$*_ca.crt=20-t=20"CT,C,C"=0A+=0A= +ssl/nss/root+server_ca.crt__server.crl.db:=20ssl/root+server_ca.crt=20= ssl/nss/server.crl=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20"sql:$@"=20= -N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= ssl/root+server_ca.crt=20-i=20ssl/root+server_ca.crt=20-t=20"CT,C,C"=0A+=09= crlutil=20-I=20-i=20ssl/nss/server.crl=20-d=20$@=20-B=0A+=0A= +ssl/nss/root+server_ca.crt__root+server.crl.db:=20= ssl/root+server_ca.crt=20ssl/nss/root.crl=20ssl/nss/server.crl=0A+=09= $(MKDIR_P)=20$@=0A+=09certutil=20-d=20"sql:$@"=20-N=20--empty-password=0A= +=09certutil=20-d=20"sql:$@"=20-A=20-n=20ssl/root+server_ca.crt=20-i=20= ssl/root+server_ca.crt=20-t=20"CT,C,C"=0A+=09crlutil=20-I=20-i=20= ssl/nss/root.crl=20-d=20$@=20-B=0A+=09crlutil=20-I=20-i=20= ssl/nss/server.crl=20-d=20$@=20-B=0A+=0A= +ssl/nss/root+server_ca.crt__root+server.crldir.db:=20= ssl/root+server_ca.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/root+server_ca.crt=20-i=20ssl/root+server_ca.crt=20-t=20= "CT,C,C"=0A+=09crlutil=20-I=20-i=20ssl/nss/root.crl=20-d=20$@=20-B=0A+=09= for=20c=20in=20$(shell=20ls=20ssl/root+server-crldir)=20;=20do=20\=0A+=09= =09echo=20$${c}=20;=20\=0A+=09=09openssl=20crl=20-in=20= ssl/root+server-crldir/$${c}=20-outform=20der=20-out=20ssl/nss/$${c}=20;=20= \=0A+=09=09crlutil=20-I=20-i=20ssl/nss/$${c}=20-d=20$@=20-B=20;=20\=0A+=09= done=0A+=0A=20#=20Server=20certificates,=20signed=20by=20server=20CA:=0A=20= ssl/server-%.crt:=20ssl/server-%.key=20ssl/server_ca.crt=20= server-%.config=0A=20=09openssl=20req=20-new=20-key=20ssl/server-$*.key=20= -out=20ssl/server-$*.csr=20-config=20server-$*.config=0A@@=20-80,6=20= +143,86=20@@=20ssl/server-ss.crt:=20ssl/server-cn-only.key=20= ssl/server-cn-only.crt=20server-cn-only.=0A=20=09openssl=20x509=20-req=20= -days=2010000=20-in=20ssl/server-ss.csr=20-signkey=20= ssl/server-cn-only.key=20-out=20ssl/server-ss.crt=20=20-extensions=20= v3_req=20-extfile=20server-cn-only.config=0A=20=09rm=20ssl/server-ss.csr=0A= =20=0A+#=20pk12util=20won't=20preserve=20the=20password=20when=20= importing=20the=20password=20protected=0A+#=20key,=20the=20password=20= must=20be=20set=20on=20the=20database=20*before*=20importing=20it=20as=20= the=0A+#=20password=20in=20the=20pkcs12=20envelope=20will=20be=20= dropped.=0A+ssl/nss/server-cn-only.crt__server-password.key.db:=20= ssl/server-cn-only.crt=0A+=09$(MKDIR_P)=20$@=0A+=09echo=20"secret1"=20>=20= password.txt=0A+=09certutil=20-d=20"sql:$@"=20-N=20-f=20password.txt=0A+=09= certutil=20-d=20"sql:$@"=20-A=20-n=20ssl/server-cn-only.crt=20-i=20= ssl/server-cn-only.crt=20-t=20"CT,C,C"=20-f=20password.txt=0A+=09= certutil=20-d=20"sql:$@"=20-A=20-n=20server_ca.crt=20-i=20= ssl/server_ca.crt=20-t=20"CT,C,C"=20-f=20password.txt=0A+=09certutil=20= -d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20ssl/root_ca.crt=20-t=20= "CT,C,C"=20-f=20password.txt=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20"CT,C,C"=20-f=20= password.txt=0A+=09openssl=20pkcs12=20-export=20-out=20= ssl/nss/server-password.pfx=20-inkey=20ssl/server-password.key=20-in=20= ssl/server-cn-only.crt=20-certfile=20ssl/server_ca.crt=20-passin=20= 'pass:secret1'=20-passout=20'pass:secret1'=0A+=09pk12util=20-i=20= ssl/nss/server-password.pfx=20-d=20"sql:$@"=20-W=20'secret1'=20-K=20= 'secret1'=0A+=0A+ssl/nss/server-cn-only.crt__server-cn-only.key.db:=20= ssl/server-cn-only.crt=20ssl/server-cn-only.key=0A+=09$(MKDIR_P)=20$@=0A= +=09certutil=20-d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20ssl/server-cn-only.crt=20-i=20= ssl/server-cn-only.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20= -A=20-n=20server_ca.crt=20-i=20ssl/server_ca.crt=20-t=20"CT,C,C"=0A+=09= certutil=20-d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20ssl/root_ca.crt=20= -t=20"CT,C,C"=0A+=09openssl=20pkcs12=20-export=20-out=20= ssl/nss/server-cn-only.pfx=20-inkey=20ssl/server-cn-only.key=20-in=20= ssl/server-cn-only.crt=20-certfile=20ssl/server_ca.crt=20-passout=20= pass:=0A+=09pk12util=20-i=20ssl/nss/server-cn-only.pfx=20-d=20"sql:$@"=20= -W=20''=0A+=0A+ssl/nss/server-cn-only.crt__server-cn-only.key.crldir.db:=20= ssl/nss/server-cn-only.crt__server-cn-only.key.db=0A+=09for=20c=20in=20= $(shell=20ls=20ssl/root+client-crldir)=20;=20do=20\=0A+=09=09echo=20= $${c}=20;=20\=0A+=09=09openssl=20crl=20-in=20= ssl/root+client-crldir/$${c}=20-outform=20der=20-out=20ssl/nss/$${c}=20;=20= \=0A+=09=09crlutil=20-I=20-i=20ssl/nss/$${c}=20-d=20$@=20-B=20;=20\=0A+=09= done=0A+=0A= +ssl/nss/server-multiple-alt-names.crt__server-multiple-alt-names.key.db:=20= ssl/server-multiple-alt-names.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20= -d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20= -A=20-n=20ssl/server-multiple-alt-names.crt=20-i=20= ssl/server-multiple-alt-names.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20server_ca.crt=20-i=20ssl/server_ca.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20= ssl/root_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20= pkcs12=20-export=20-out=20ssl/nss/server-multiple-alt-names.pfx=20-inkey=20= ssl/server-multiple-alt-names.key=20-in=20= ssl/server-multiple-alt-names.crt=20-certfile=20= ssl/server-multiple-alt-names.crt=20-passout=20pass:=0A+=09pk12util=20-i=20= ssl/nss/server-multiple-alt-names.pfx=20-d=20"sql:$@"=20-W=20''=0A+=0A= +ssl/nss/server-single-alt-name.crt__server-single-alt-name.key.db:=20= ssl/server-single-alt-name.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/server-single-alt-name.crt=20-i=20= ssl/server-single-alt-name.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20server_ca.crt=20-i=20ssl/server_ca.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20= ssl/root_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20= pkcs12=20-export=20-out=20ssl/nss/server-single-alt-name.pfx=20-inkey=20= ssl/server-single-alt-name.key=20-in=20ssl/server-single-alt-name.crt=20= -certfile=20ssl/server-single-alt-name.crt=20-passout=20pass:=0A+=09= pk12util=20-i=20ssl/nss/server-single-alt-name.pfx=20-d=20"sql:$@"=20-W=20= ''=0A+=0A= +ssl/nss/server-cn-and-alt-names.crt__server-cn-and-alt-names.key.db:=20= ssl/server-cn-and-alt-names.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20= -d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20= -A=20-n=20ssl/server-cn-and-alt-names.crt=20-i=20= ssl/server-cn-and-alt-names.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20= "sql:$@"=20-A=20-n=20server_ca.crt=20-i=20ssl/server_ca.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20root_ca.crt=20-i=20= ssl/root_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20= pkcs12=20-export=20-out=20ssl/nss/server-cn-and-alt-names.pfx=20-inkey=20= ssl/server-cn-and-alt-names.key=20-in=20ssl/server-cn-and-alt-names.crt=20= -certfile=20ssl/server-cn-and-alt-names.crt=20-passout=20pass:=0A+=09= pk12util=20-i=20ssl/nss/server-cn-and-alt-names.pfx=20-d=20$@=20-W=20''=0A= +=0A+ssl/nss/server-no-names.crt__server-no-names.key.db:=20= ssl/server-no-names.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/server-no-names.crt=20-i=20ssl/server-no-names.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20server_ca.crt=20-i=20= ssl/server_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20root_ca.crt=20-i=20ssl/root_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20= -d=20"sql:$@"=20-A=20-n=20client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20= "CT,C,C"=0A+=09openssl=20pkcs12=20-export=20-out=20= ssl/nss/server-no-names.pfx=20-inkey=20ssl/server-no-names.key=20-in=20= ssl/server-no-names.crt=20-certfile=20ssl/server-no-names.crt=20-passout=20= pass:=0A+=09pk12util=20-i=20ssl/nss/server-no-names.pfx=20-d=20"sql:$@"=20= -W=20''=0A+=0A+ssl/nss/server-revoked.crt__server-revoked.key.db:=20= ssl/server-revoked.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/server-revoked.crt=20-i=20ssl/server-revoked.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20server_ca.crt=20-i=20= ssl/server_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20root_ca.crt=20-i=20ssl/root_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20= -d=20"sql:$@"=20-A=20-n=20client_ca.crt=20-i=20ssl/client_ca.crt=20-t=20= "CT,C,C"=0A+=09openssl=20pkcs12=20-export=20-out=20= ssl/nss/server-revoked.pfx=20-inkey=20ssl/server-revoked.key=20-in=20= ssl/server-revoked.crt=20-certfile=20ssl/server-revoked.crt=20-passout=20= pass:=0A+=09pk12util=20-i=20ssl/nss/server-revoked.pfx=20-d=20"sql:$@"=20= -W=20''=0A+=0A=20#=20Password-protected=20version=20of=20= server-cn-only.key=0A=20ssl/server-password.key:=20= ssl/server-cn-only.key=0A=20=09openssl=20rsa=20-aes256=20-in=20$<=20-out=20= $@=20-passout=20'pass:secret1'=0A@@=20-91,6=20+234,27=20@@=20= ssl/client.crt:=20ssl/client.key=20ssl/client_ca.crt=0A=20=09openssl=20= x509=20-in=20ssl/temp.crt=20-out=20ssl/client.crt=20#=20to=20keep=20just=20= the=20PEM=20cert=0A=20=09rm=20ssl/client.csr=20ssl/temp.crt=0A=20=0A+#=20= Client=20certificate,=20signed=20by=20client=20CA=0A= +ssl/nss/client.crt__client.key.db:=20ssl/client.crt=0A+=09$(MKDIR_P)=20= $@=0A+=09certutil=20-d=20"sql:$@"=20-N=20--empty-password=0A+=09certutil=20= -d=20"sql:$@"=20-A=20-n=20ssl/client.crt=20-i=20ssl/client.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20client_ca.crt=20-i=20= ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20root+client_ca.crt=20-i=20ssl/root+client_ca.crt=20-t=20"CT,C,C"=0A= +=09openssl=20pkcs12=20-export=20-out=20ssl/nss/client.pfx=20-inkey=20= ssl/client.key=20-in=20ssl/client.crt=20-certfile=20ssl/client_ca.crt=20= -passout=20pass:=0A+=09pk12util=20-i=20ssl/nss/client.pfx=20-d=20= "sql:$@"=20-W=20''=0A+=0A+#=20Client=20certificate=20with=20encrypted=20= key,=20signed=20by=20client=20CA=0A= +ssl/nss/client.crt__client-encrypted-pem.key.db:=20ssl/client.crt=0A+=09= $(MKDIR_P)=20$@=0A+=09echo=20'dUmmyP^#+'=20>=20$@.pass=0A+=09certutil=20= -d=20"sql:$@"=20-N=20-f=20$@.pass=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -f=20$@.pass=20-n=20ssl/client.crt=20-i=20ssl/client.crt=20-t=20"CT,C,C"=0A= +=09certutil=20-d=20"sql:$@"=20-A=20-f=20$@.pass=20-n=20client_ca.crt=20= -i=20ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20= -A=20-f=20$@.pass=20-n=20root+server_ca.crt=20-i=20= ssl/root+server_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20pkcs12=20-export=20= -out=20ssl/nss/client-encrypted-pem.pfx=20-inkey=20= ssl/client-encrypted-pem.key=20-in=20ssl/client.crt=20-certfile=20= ssl/client_ca.crt=20-passin=20pass:'dUmmyP^#+'=20-passout=20= pass:'dUmmyP^#+'=0A+=09pk12util=20-i=20ssl/nss/client-encrypted-pem.pfx=20= -d=20"sql:$@"=20-W=20'dUmmyP^#+'=20-k=20$@.pass=0A+=0A=20#=20Another=20= client=20certificate,=20signed=20by=20the=20client=20CA.=20This=20one=20= is=20revoked.=0A=20ssl/client-revoked.crt:=20ssl/client-revoked.key=20= ssl/client_ca.crt=20client.config=0A=20=09openssl=20req=20-new=20-key=20= ssl/client-revoked.key=20-out=20ssl/client-revoked.csr=20-config=20= client.config=0A@@=20-98,6=20+262,14=20@@=20ssl/client-revoked.crt:=20= ssl/client-revoked.key=20ssl/client_ca.crt=20client.config=0A=20=09= openssl=20x509=20-in=20ssl/temp.crt=20-out=20ssl/client-revoked.crt=20#=20= to=20keep=20just=20the=20PEM=20cert=0A=20=09rm=20ssl/client-revoked.csr=20= ssl/temp.crt=0A=20=0A+ssl/nss/client-revoked.crt__client-revoked.key.db:=20= ssl/client-revoked.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/client-revoked.crt=20-i=20ssl/client-revoked.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20client_ca.crt=20-i=20= ssl/client_ca.crt=20-t=20"CT,C,C"=0A+=09openssl=20pkcs12=20-export=20= -out=20ssl/nss/client-revoked.pfx=20-inkey=20ssl/client-revoked.key=20= -in=20ssl/client-revoked.crt=20-certfile=20ssl/client_ca.crt=20-passout=20= pass:=0A+=09pk12util=20-i=20ssl/nss/client-revoked.pfx=20-d=20"sql:$@"=20= -W=20''=0A+=0A=20#=20Convert=20the=20key=20to=20DER,=20to=20test=20our=20= behaviour=20there=20too=0A=20ssl/client-der.key:=20ssl/client.key=0A=20=09= openssl=20rsa=20-in=20ssl/client.key=20-outform=20DER=20-out=20= ssl/client-der.key=0A@@=20-130,19=20+302,40=20@@=20= ssl/root+client_ca.crt:=20ssl/root_ca.crt=20ssl/client_ca.crt=0A=20= ssl/client+client_ca.crt:=20ssl/client.crt=20ssl/client_ca.crt=0A=20=09= cat=20$^=20>=20$@=0A=20=0A+#=20Client=20certificate,=20signed=20by=20= client=20CA=0A+ssl/nss/client+client_ca.crt__client.key.db:=20= ssl/client+client_ca.crt=0A+=09$(MKDIR_P)=20$@=0A+=09certutil=20-d=20= "sql:$@"=20-N=20--empty-password=0A+=09certutil=20-d=20"sql:$@"=20-A=20= -n=20ssl/client+client_ca.crt=20-i=20ssl/client+client_ca.crt=20-t=20= "CT,C,C"=0A+=09certutil=20-d=20"sql:$@"=20-A=20-n=20= ssl/root+server_ca.crt=20-i=20ssl/root+server_ca.crt=20-t=20"CT,C,C"=0A+=09= openssl=20pkcs12=20-export=20-out=20ssl/nss/client.pfx=20-inkey=20= ssl/client.key=20-in=20ssl/client.crt=20-certfile=20ssl/client_ca.crt=20= -passout=20pass:=0A+=09pk12util=20-i=20ssl/nss/client.pfx=20-d=20= "sql:$@"=20-W=20''=0A+=0A=20####=20CRLs=0A=20=0A=20ssl/client.crl:=20= ssl/client-revoked.crt=0A=20=09openssl=20ca=20-config=20cas.config=20= -name=20client_ca=20-revoke=20ssl/client-revoked.crt=0A=20=09openssl=20= ca=20-config=20cas.config=20-name=20client_ca=20-gencrl=20-out=20= ssl/client.crl=0A=20=0A+ssl/nss/client.crl:=20ssl/client.crl=0A+=09= openssl=20crl=20-in=20$^=20-outform=20der=20-out=20$@=0A+=0A=20= ssl/server.crl:=20ssl/server-revoked.crt=0A=20=09openssl=20ca=20-config=20= cas.config=20-name=20server_ca=20-revoke=20ssl/server-revoked.crt=0A=20=09= openssl=20ca=20-config=20cas.config=20-name=20server_ca=20-gencrl=20-out=20= ssl/server.crl=0A=20=0A+ssl/nss/server.crl:=20ssl/server.crl=0A+=09= openssl=20crl=20-in=20$^=20-outform=20der=20-out=20$@=0A+=0A=20= ssl/root.crl:=20ssl/root_ca.crt=0A=20=09openssl=20ca=20-config=20= cas.config=20-name=20root_ca=20-gencrl=20-out=20ssl/root.crl=0A=20=0A= +ssl/nss/root.crl:=20ssl/root.crl=0A+=09openssl=20crl=20-in=20$^=20= -outform=20der=20-out=20$@=0A+=0A+ssl/nss/root+client.crl:=20= ssl/root+client.crl=0A+=09openssl=20crl=20-in=20$^=20-outform=20der=20= -out=20$@=0A+=0A=20#=20If=20a=20CRL=20is=20used,=20OpenSSL=20requires=20= a=20CRL=20file=20for=20*all*=20the=20CAs=20in=20the=0A=20#=20chain,=20= even=20if=20some=20of=20them=20are=20empty.=0A=20ssl/root+server.crl:=20= ssl/root.crl=20ssl/server.crl=0A@@=20-168,14=20+361,65=20@@=20= ssl/client-crldir:=20ssl/client.crl=0A=20=09mkdir=20ssl/client-crldir=0A=20= =09cp=20ssl/client.crl=20ssl/client-crldir/`openssl=20crl=20-hash=20= -noout=20-in=20ssl/client.crl`.r0=0A=20=0A+####=20NSS=20specific=20= certificates=20and=20keys=0A+=0A+ssl/nss/native_ca-%.db:=0A+=09= $(MKDIR_P)=20ssl/nss/native_ca-$*.db=0A+=09certutil=20-N=20-d=20= "sql:ssl/nss/native_ca-$*.db/"=20--empty-password=0A+=09echo=20y=20>=20= nss_ca_params.txt=0A+=09echo=2010=20>>=20nss_ca_params.txt=0A+=09echo=20= y=20>>=20nss_ca_params.txt=0A+=09cat=20nss_ca_params.txt=20|=20certutil=20= -S=20-d=20"sql:ssl/nss/native_ca-$*.db/"=20-n=20ca-$*=20\=0A+=09-s=20= "CN=3DTest=20CA=20for=20PostgreSQL=20SSL=20regression=20= tests,OU=3DPostgreSQL=20test=20suite"=20\=0A+=09-x=20-k=20rsa=20-g=20= 2048=20-m=205432=20-t=20CTu,CTu,CTu=20\=0A+=09--keyUsage=20certSigning=20= -2=20--nsCertType=20sslCA,smimeCA,objectSigningCA=20\=0A+=09-z=20= Makefile=20-Z=20SHA256=0A+=09rm=20nss_ca_params.txt=0A+=0A= +ssl/nss/native_ca-%.pem:=20ssl/nss/native_ca-%.db=0A+=09certutil=20-L=20= -d=20"sql:ssl/nss/native_ca-$*.db/"=20-n=20ca-$*=20-a=20>=20= ssl/nss/native_ca-$*.pem=0A+=0A+#=20Create=20and=20sign=20a=20server=20= certificate=0A+ssl/nss/native_server-%.db:=20ssl/nss/native_ca-%.pem=0A+=09= $(MKDIR_P)=20ssl/nss/native_server-$*.db=0A+=09certutil=20-N=20-d=20= "sql:ssl/nss/native_server-$*.db/"=20--empty-password=0A+=09certutil=20= -R=20-d=20"sql:ssl/nss/native_server-$*.db/"=20\=0A+=09=09-s=20= "CN=3Dcommon-name.pg-ssltest.test,OU=3DPostgreSQL=20test=20suite"=20\=0A= +=09=09-o=20ssl/nss/native_server-$*.csr=20-g=202048=20-Z=20SHA256=20-z=20= Makefile=0A+=09echo=201=20>=20nss_server_params.txt=0A+=09echo=209=20>>=20= nss_server_params.txt=0A+=09cat=20nss_server_params.txt=20|=20certutil=20= -C=20-d=20"sql:ssl/nss/native_ca-$*.db/"=20-c=20ca-root=20-i=20= ssl/nss/native_server-$*.csr=20\=0A+=09=09-o=20= ssl/nss/native_server_$*.der=20-m=205433=20--keyUsage=20= dataEncipherment,digitalSignature,keyEncipherment=20\=0A+=09=09= --nsCertType=20sslServer=20--certVersion=201=20-Z=20SHA256=0A+=09= certutil=20-A=20-d=20"sql:ssl/nss/native_server-$*.db/"=20-n=20ca-$*=20= -t=20CTu,CTu,CTu=20-a=20-i=20ssl/nss/native_ca-$*.pem=0A+=09certutil=20= -A=20-d=20"sql:ssl/nss/native_server-$*.db/"=20-n=20= ssl/native_server-$*.crt=20-t=20CTu,CTu,CTu=20-i=20= ssl/nss/native_server_$*.der=0A+=09rm=20nss_server_params.txt=0A+=0A+#=20= Create=20and=20sign=20a=20client=20certificate=0A= +ssl/nss/native_client-%.db:=20ssl/nss/native_ca-%.pem=0A+=09$(MKDIR_P)=20= ssl/nss/native_client-$*.db=0A+=09certutil=20-N=20-d=20= "sql:ssl/nss/native_client-$*.db/"=20--empty-password=0A+=09certutil=20= -R=20-d=20"sql:ssl/nss/native_client-$*.db/"=20-s=20= "CN=3Dssltestuser,OU=3DPostgreSQL=20test=20suite"=20\=0A+=09=09-o=20= ssl/nss/native_client-$*.csr=20-g=202048=20-Z=20SHA256=20-z=20Makefile=0A= +=09certutil=20-C=20-d=20"sql:ssl/nss/native_ca-$*.db/"=20-c=20ca-$*=20= -i=20ssl/nss/native_client-$*.csr=20-o=20ssl/nss/native_client-$*.der=20= \=0A+=09=09-m=205434=20--keyUsage=20= keyEncipherment,dataEncipherment,digitalSignature=20--nsCertType=20= sslClient=20\=0A+=09=09--certVersion=201=20-Z=20SHA256=0A+=09certutil=20= -A=20-d=20"sql:ssl/nss/native_client-$*.db"=20-n=20ca-$*=20-t=20= CTu,CTu,CTu=20-a=20-i=20ssl/nss/native_ca-$*.pem=0A+=09certutil=20-A=20= -d=20"sql:ssl/nss/native_client-$*.db"=20-n=20native_client-$*=20-t=20= CTu,CTu,CTu=20-i=20ssl/nss/native_client-$*.der=0A+=0A=20.PHONY:=20= sslfiles-clean=0A=20sslfiles-clean:=0A=20=09rm=20-f=20$(SSLFILES)=20= ssl/client_ca.srl=20ssl/server_ca.srl=20ssl/client_ca-certindex*=20= ssl/server_ca-certindex*=20ssl/root_ca-certindex*=20ssl/root_ca.srl=20= ssl/temp_ca.crt=20ssl/temp_ca_signed.crt=0A=20=09rm=20-rf=20$(SSLDIRS)=0A= =20=0A+.PHONY:=20nssfiles-clean=0A+nssfiles-clean:=0A+=09rm=20-rf=20= ssl/nss=0A+=0A=20clean=20distclean=20maintainer-clean:=0A=20=09rm=20-rf=20= tmp_check=0A=20=09rm=20-rf=20ssl/*.old=20ssl/new_certs_dir=20= ssl/client*_tmp.key=0A+=09rm=20-rf=20ssl/nss=0A=20=0A=20#=20Doesn't=20= depend=20on=20$(SSLFILES)=20because=20we=20don't=20rebuild=20them=20by=20= default=0A=20check:=0Adiff=20--git=20a/src/test/ssl/t/001_ssltests.pl=20= b/src/test/ssl/t/001_ssltests.pl=0Aindex=2030b68bddbe..dbd49817da=20= 100644=0A---=20a/src/test/ssl/t/001_ssltests.pl=0A+++=20= b/src/test/ssl/t/001_ssltests.pl=0A@@=20-9,13=20+9,22=20@@=20use=20lib=20= $FindBin::RealBin;=0A=20=0A=20use=20SSL::Server;=0A=20=0A-if=20= ($ENV{with_ssl}=20ne=20'openssl')=0A+my=20$openssl;=0A+my=20$nss;=0A+=0A= +if=20($ENV{with_ssl}=20eq=20'openssl')=0A+{=0A+=09$openssl=20=3D=201;=0A= +=09plan=20tests=20=3D>=20100;=0A+}=0A+elsif=20($ENV{with_ssl}=20eq=20= 'nss')=0A=20{=0A-=09plan=20skip_all=20=3D>=20'OpenSSL=20not=20supported=20= by=20this=20build';=0A+=09$nss=20=3D=201;=0A+=09plan=20tests=20=3D>=20= 106;=0A=20}=0A=20else=0A=20{=0A-=09plan=20tests=20=3D>=20100;=0A+=09plan=20= skip_all=20=3D>=20'SSL=20not=20supported=20by=20this=20build';=0A=20}=0A=20= =0A=20####=20Some=20configuration=0A@@=20-51,19=20+60,78=20@@=20= configure_test_server_for_ssl($node,=20$SERVERHOSTADDR,=20= $SERVERHOSTCIDR,=0A=20=0A=20note=20"testing=20password-protected=20= keys";=0A=20=0A-set_server_cert($node,=20'server-cn-only',=20= 'root+client_ca',=0A-=09=09=09=09=20=20=20'server-password',=20'echo=20= wrongpassword');=0A-command_fails(=0A-=09[=20'pg_ctl',=20'-D',=20= $node->data_dir,=20'-l',=20$node->logfile,=20'restart'=20],=0A-=09= 'restart=20fails=20with=20password-protected=20key=20file=20with=20wrong=20= password');=0A-$node->_update_pid(0);=0A+#=20Since=20the=20passphrase=20= callbacks=20operate=20at=20different=20stages=20in=20OpenSSL=20and=0A+#=20= NSS=20we=20have=20two=20separate=20blocks=20for=20them=0A+SKIP:=0A+{=0A+=09= skip=20"Certificate=20passphrases=20aren't=20checked=20on=20server=20= restart=20in=20NSS",=202=0A+=09=20=20if=20($nss);=0A+=0A+=09= switch_server_cert($node,=0A+=09=09certfile=20=3D>=20'server-cn-only',=0A= +=09=09cafile=20=3D>=20'root+client_ca',=0A+=09=09keyfile=20=3D>=20= 'server-password',=0A+=09=09nssdatabase=20=3D>=20= 'server-cn-only.crt__server-password.key.db',=0A+=09=09passphrase_cmd=20= =3D>=20'echo=20wrongpassword');=0A+=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= +=09switch_server_cert($node,=0A+=09=09certfile=20=3D>=20= 'server-cn-only',=0A+=09=09cafile=20=3D>=20'root+client_ca',=0A+=09=09= keyfile=20=3D>=20'server-password',=0A+=09=09nssdatabase=20=3D>=20= 'server-cn-only.crt__server-password.key.db',=0A+=09=09passphrase_cmd=20= =3D>=20'echo=20secret1');=0A+=0A+=09command_ok(=0A+=09=09[=20'pg_ctl',=20= '-D',=20$node->data_dir,=20'-l',=20$node->logfile,=20'restart'=20],=0A+=09= =09'restart=20succeeds=20with=20password-protected=20key=20file');=0A+=09= $node->_update_pid(1);=0A+}=0A=20=0A-set_server_cert($node,=20= 'server-cn-only',=20'root+client_ca',=0A-=09=09=09=09'server-password',=20= 'echo=20secret1');=0A-command_ok(=0A-=09[=20'pg_ctl',=20'-D',=20= $node->data_dir,=20'-l',=20$node->logfile,=20'restart'=20],=0A-=09= 'restart=20succeeds=20with=20password-protected=20key=20file');=0A= -$node->_update_pid(1);=0A+SKIP:=0A+{=0A+=09skip=20"Certificate=20= passphrases=20are=20checked=20on=20connection=20in=20NSS",=205=0A+=09=20=20= if=20($openssl);=0A+=0A+=09switch_server_cert($node,=0A+=09=09certfile=20= =3D>=20'server-cn-only',=0A+=09=09cafile=20=3D>=20'root+client_ca',=0A+=09= =09keyfile=20=3D>=20'server-password',=0A+=09=09nssdatabase=20=3D>=20= 'server-cn-only.crt__server-password.key.db',=0A+=09=09passphrase_cmd=20= =3D>=20'echo=20wrongpassword');=0A+=0A+=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_fails(=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=09qr/\QSSL=20error\E/,=0A+=09=09"connect=20to=20= server=20with=20incorrect=20key=20password=20configured");=0A+=0A+=09= switch_server_cert($node,=0A+=09=09certfile=20=3D>=20'server-cn-only',=0A= +=09=09cafile=20=3D>=20'root+client_ca',=0A+=09=09keyfile=20=3D>=20= 'server-password',=0A+=09=09nssdatabase=20=3D>=20= 'server-cn-only.crt__server-password.key.db',=0A+=09=09passphrase_cmd=20= =3D>=20'echo=20secret1');=0A+=0A+=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=20key=20file=20with=20= wrong=20password');=0A+=09$node->_update_pid(1);=0A+=0A+=09= test_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-91,7=20+159,7=20@@=20command_ok(=0A=20=0A= =20note=20"running=20client=20tests";=0A=20=0A-switch_server_cert($node,=20= 'server-cn-only');=0A+switch_server_cert($node,=20certfile=20=3D>=20= 'server-cn-only',=20nssdatabase=20=3D>=20= 'server-cn-only.crt__server-cn-only.key.db');=0A=20=0A=20$common_connstr=20= =3D=0A=20=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= hostaddr=3D$SERVERHOSTADDR=20host=3Dcommon-name.pg-ssltest.test";=0A@@=20= -111,95=20+179,118=20@@=20test_connect_ok(=0A=20test_connect_fails(=0A=20= =09$common_connstr,=0A=20=09"sslrootcert=3Dinvalid=20sslmode=3Dverify-ca",= =0A-=09qr/root=20certificate=20file=20"invalid"=20does=20not=20exist/,=0A= +=09qr/root=20certificate=20file=20"invalid"=20does=20not=20exist|Peer's=20= certificate=20issuer=20has=20been=20marked=20as=20not=20trusted=20by=20= the=20user/,=0A=20=09"connect=20without=20server=20root=20cert=20= sslmode=3Dverify-ca");=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A= =20=09"sslrootcert=3Dinvalid=20sslmode=3Dverify-full",=0A-=09qr/root=20= certificate=20file=20"invalid"=20does=20not=20exist/,=0A+=09qr/root=20= certificate=20file=20"invalid"=20does=20not=20exist|Peer's=20certificate=20= issuer=20has=20been=20marked=20as=20not=20trusted=20by=20the=20user/,=0A=20= =09"connect=20without=20server=20root=20cert=20sslmode=3Dverify-full");=0A= =20=0A=20#=20Try=20with=20wrong=20root=20cert,=20should=20fail.=20(We're=20= using=20the=20client=20CA=20as=20the=0A=20#=20root,=20but=20the=20= server's=20key=20is=20signed=20by=20the=20server=20CA.)=0A= -test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Drequire",=0A-=09qr/SSL=20= error/,=20"connect=20with=20wrong=20server=20root=20cert=20= sslmode=3Drequire");=0A-test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-ca",=0A-=09qr/SSL=20= error/,=20"connect=20with=20wrong=20server=20root=20cert=20= sslmode=3Dverify-ca");=0A-test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-full",=0A-=09qr/SSL=20= error/,=20"connect=20with=20wrong=20server=20root=20cert=20= sslmode=3Dverify-full");=0A-=0A-#=20Try=20with=20just=20the=20server=20= CA's=20cert.=20This=20fails=20because=20the=20root=20file=0A-#=20must=20= contain=20the=20whole=20chain=20up=20to=20the=20root=20CA.=0A= -test_connect_fails($common_connstr,=0A-=09= "sslrootcert=3Dssl/server_ca.crt=20sslmode=3Dverify-ca",=0A-=09qr/SSL=20= error/,=20"connect=20with=20server=20CA=20cert,=20without=20root=20CA");=0A= +test_connect_fails(=0A+=09$common_connstr,=0A+=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Drequire=20= cert_database=3Dssl/nss/client_ca.crt.db",=0A+=09qr/SSL=20error/,=0A+=09= "connect=20with=20wrong=20server=20root=20cert=20sslmode=3Drequire");=0A= +test_connect_fails(=0A+=09$common_connstr,=0A+=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-ca=20= cert_database=3Dssl/nss/client_ca.crt.db",=0A+=09qr/SSL=20error/,=0A+=09= "connect=20with=20wrong=20server=20root=20cert=20sslmode=3Dverify-ca");=0A= +test_connect_fails(=0A+=09$common_connstr,=0A+=09= "sslrootcert=3Dssl/client_ca.crt=20sslmode=3Dverify-full=20= cert_database=3Dssl/nss/client_ca.crt.db",=0A+=09qr/SSL=20error/,=0A+=09= "connect=20with=20wrong=20server=20root=20cert=20sslmode=3Dverify-full");=0A= +=0A+SKIP:=0A+{=0A+=09#=20NSS=20supports=20partial=20chain=20validation,=20= so=20this=20test=20doesn't=20work=20there.=0A+=09#=20This=20is=20similar=20= to=20the=20OpenSSL=20option=20X509_V_FLAG_PARTIAL_CHAIN=20which=0A+=09#=20= we=20don't=20allow.=0A+=09skip=20"NSS=20support=20partial=20chain=20= validation",=202=20if=20($nss);=0A+=09#=20Try=20with=20just=20the=20= server=20CA's=20cert.=20This=20fails=20because=20the=20root=20file=0A+=09= #=20must=20contain=20the=20whole=20chain=20up=20to=20the=20root=20CA.=0A= +=09test_connect_fails($common_connstr,=0A+=09=09= "sslrootcert=3Dssl/server_ca.crt=20sslmode=3Dverify-ca",=0A+=09=09qr/SSL=20= error/,=20"connect=20with=20server=20CA=20cert,=20without=20root=20CA");=0A= +}=0A=20=0A=20#=20And=20finally,=20with=20the=20correct=20root=20cert.=0A= =20test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connect=20with=20= correct=20server=20CA=20cert=20file=20sslmode=3Drequire");=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connect=20with=20= correct=20server=20CA=20cert=20file=20sslmode=3Dverify-ca");=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-full",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-full=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connect=20with=20= correct=20server=20CA=20cert=20file=20sslmode=3Dverify-full");=0A=20=0A= -#=20Test=20with=20cert=20root=20file=20that=20contains=20two=20= certificates.=20The=20client=20should=0A-#=20be=20able=20to=20pick=20the=20= right=20one,=20regardless=20of=20the=20order=20in=20the=20file.=0A= -test_connect_ok(=0A-=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/both-cas-1.crt=20sslmode=3Dverify-ca",=0A-=09"cert=20= root=20file=20that=20contains=20two=20certificates,=20order=201");=0A= -test_connect_ok(=0A-=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/both-cas-2.crt=20sslmode=3Dverify-ca",=0A-=09"cert=20= root=20file=20that=20contains=20two=20certificates,=20order=202");=0A= +SKIP:=0A+{=0A+=09skip=20"CA=20ordering=20is=20irrelevant=20in=20NSS=20= databases",=202=20if=20($nss);=0A=20=0A+=09#=20Test=20with=20cert=20root=20= file=20that=20contains=20two=20certificates.=20The=20client=20should=0A+=09= #=20be=20able=20to=20pick=20the=20right=20one,=20regardless=20of=20the=20= order=20in=20the=20file.=0A+=09test_connect_ok(=0A+=09=09= $common_connstr,=0A+=09=09"sslrootcert=3Dssl/both-cas-1.crt=20= sslmode=3Dverify-ca",=0A+=09=09"cert=20root=20file=20that=20contains=20= two=20certificates,=20order=201");=0A+=0A+=09#=20How=20about=20import=20= the=20both-file=20into=20a=20database?=0A+=09test_connect_ok(=0A+=09=09= $common_connstr,=0A+=09=09"sslrootcert=3Dssl/both-cas-2.crt=20= sslmode=3Dverify-ca",=0A+=09=09"cert=20root=20file=20that=20contains=20= two=20certificates,=20order=202");=0A+}=0A=20#=20CRL=20tests=0A=20=0A=20= #=20Invalid=20CRL=20filename=20is=20the=20same=20as=20no=20CRL,=20= succeeds=0A=20test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrl=3Dinvalid",=0A+=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dinvalid=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"sslcrl=20option=20= with=20invalid=20file=20name");=0A=20=0A-#=20A=20CRL=20belonging=20to=20= a=20different=20CA=20is=20not=20accepted,=20fails=0A-test_connect_fails(=0A= -=09$common_connstr,=0A-=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrl=3Dssl/client.crl",=0A-=09qr/SSL=20error/,=0A= -=09"CRL=20belonging=20to=20a=20different=20CA");=0A+SKIP:=0A+{=0A+=09= skip=20"CRL's=20are=20verified=20when=20adding=20to=20NSS=20database",=20= 4=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=20=0A= -#=20The=20same=20for=20CRL=20directory=0A-test_connect_fails(=0A-=09= $common_connstr,=0A-=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrldir=3Dssl/client-crldir",=0A-=09qr/SSL=20= error/,=0A-=09"directory=20CRL=20belonging=20to=20a=20different=20CA");=0A= +=09#=20The=20same=20for=20CRL=20directory=0A+=09test_connect_fails(=0A+=09= =09$common_connstr,=0A+=09=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Dverify-ca=20sslcrldir=3Dssl/client-crldir",=0A+=09=09qr/SSL=20= error/,=0A+=09=09"directory=20CRL=20belonging=20to=20a=20different=20= CA");=0A+}=0A=20=0A=20#=20With=20the=20correct=20CRL,=20succeeds=20(this=20= cert=20is=20not=20revoked)=0A=20test_connect_ok(=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/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#=20The=20same=20for=20= CRL=20directory=0A=20test_connect_ok(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrldir=3Dssl/root+server-crldir",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrldir=3Dssl/root+server-crldir=20= cert_database=3Dssl/nss/root+server_ca.crt__root+server.crldir.db",=0A=20= =09"directory=20CRL=20with=20a=20non-revoked=20cert");=0A=20=0A=20#=20= Check=20that=20connecting=20with=20verify-full=20fails,=20when=20the=20= hostname=20doesn'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-212,14=20+303,14=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "sslmode=3Dverify-full=20host=3Dwronghost.test",=0A-=09qr/\Qserver=20= certificate=20for=20"common-name.pg-ssltest.test"=20does=20not=20match=20= host=20name=20"wronghost.test"\E/,=0A+=09qr/\Qserver=20certificate=20for=20= "common-name.pg-ssltest.test"=20does=20not=20match=20host=20name=20= "wronghost.test"\E|requested=20domain=20name=20does=20not=20match=20the=20= server's=20certificate/,=0A=20=09"mismatch=20between=20host=20name=20and=20= server=20certificate=20sslmode=3Dverify-full");=0A=20=0A=20#=20Test=20= Subject=20Alternative=20Names.=0A-switch_server_cert($node,=20= 'server-multiple-alt-names');=0A+switch_server_cert($node,=20certfile=20= =3D>=20'server-multiple-alt-names',=20nssdatabase=20=3D>=20= 'server-multiple-alt-names.crt__server-multiple-alt-names.key.db');=0A=20= =0A=20$common_connstr=20=3D=0A-=20=20"user=3Dssltestuser=20= dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= sslmode=3Dverify-full";=0A+=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR=20sslmode=3Dverify-full=20= cert_database=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-237,20=20+328,20=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "host=3Dwronghost.alt-name.pg-ssltest.test",=0A-=09qr/\Qserver=20= certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20= names)=20does=20not=20match=20host=20name=20= "wronghost.alt-name.pg-ssltest.test"\E/,=0A+=09qr/\Qserver=20certificate=20= for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20names)=20does=20= not=20match=20host=20name=20= "wronghost.alt-name.pg-ssltest.test"\E|requested=20domain=20name=20does=20= not=20match=20the=20server's=20certificate/,=0A=20=09"host=20name=20not=20= matching=20with=20X.509=20Subject=20Alternative=20Names");=0A=20= test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "host=3Ddeep.subdomain.wildcard.pg-ssltest.test",=0A-=09qr/\Qserver=20= certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20= names)=20does=20not=20match=20host=20name=20= "deep.subdomain.wildcard.pg-ssltest.test"\E/,=0A+=09qr/\Qserver=20= certificate=20for=20"dns1.alt-name.pg-ssltest.test"=20(and=202=20other=20= names)=20does=20not=20match=20host=20name=20= "deep.subdomain.wildcard.pg-ssltest.test"\E|requested=20domain=20name=20= does=20not=20match=20the=20server's=20certificate/,=0A=20=09"host=20name=20= not=20matching=20with=20X.509=20Subject=20Alternative=20Names=20= wildcard");=0A=20=0A=20#=20Test=20certificate=20with=20a=20single=20= Subject=20Alternative=20Name.=20(this=20gives=20a=0A=20#=20slightly=20= different=20error=20message,=20that's=20all)=0A= -switch_server_cert($node,=20'server-single-alt-name');=0A= +switch_server_cert($node,=20certfile=20=3D>=20'server-single-alt-name',=20= nssdatabase=20=3D>=20= 'server-single-alt-name.crt__server-single-alt-name.key.db');=0A=20=0A=20= $common_connstr=20=3D=0A-=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR=20sslmode=3Dverify-full";=0A+=20=20= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= sslmode=3Dverify-full=20cert_database=3Dssl/nss/root+server_ca.crt.db";=0A= =20=0A=20test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-260,21=20= +351,21=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|requested=20domain=20name=20= does=20not=20match=20the=20server's=20certificate/,=0A=20=09"host=20name=20= not=20matching=20with=20a=20single=20X.509=20Subject=20Alternative=20= Name");=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "host=3Ddeep.subdomain.wildcard.pg-ssltest.test",=0A-=09qr/\Qserver=20= certificate=20for=20"single.alt-name.pg-ssltest.test"=20does=20not=20= match=20host=20name=20"deep.subdomain.wildcard.pg-ssltest.test"\E/,=0A+=09= qr/\Qserver=20certificate=20for=20"single.alt-name.pg-ssltest.test"=20= does=20not=20match=20host=20name=20= "deep.subdomain.wildcard.pg-ssltest.test"\E|requested=20domain=20name=20= does=20not=20match=20the=20server's=20certificate/,=0A=20=09"host=20name=20= not=20matching=20with=20a=20single=20X.509=20Subject=20Alternative=20= Name=20wildcard"=0A=20);=0A=20=0A=20#=20Test=20server=20certificate=20= with=20a=20CN=20and=20SANs.=20Per=20RFCs=202818=20and=206125,=20the=20CN=0A= =20#=20should=20be=20ignored=20when=20the=20certificate=20has=20both.=0A= -switch_server_cert($node,=20'server-cn-and-alt-names');=0A= +switch_server_cert($node,=20certfile=20=3D>=20= 'server-cn-and-alt-names',=20nssdatabase=20=3D>=20= 'server-cn-and-alt-names.crt__server-cn-and-alt-names.key.db');=0A=20=0A=20= $common_connstr=20=3D=0A-=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR=20sslmode=3Dverify-full";=0A+=20=20= "user=3Dssltestuser=20dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= sslmode=3Dverify-full=20cert_database=3Dssl/nss/root+server_ca.crt.db";=0A= =20=0A=20test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-287,14=20= +378,14=20@@=20test_connect_ok(=0A=20test_connect_fails(=0A=20=09= $common_connstr,=0A=20=09"host=3Dcommon-name.pg-ssltest.test",=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/,=0A+=09qr/\Qserver=20certificate=20for=20= "dns1.alt-name.pg-ssltest.test"=20(and=201=20other=20name)=20does=20not=20= match=20host=20name=20"common-name.pg-ssltest.test"\E|requested=20domain=20= name=20does=20not=20match=20the=20server's=20certificate/,=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= -switch_server_cert($node,=20'server-no-names');=0A= +switch_server_cert($node,=20certfile=20=3D>=20'server-no-names',=20= nssdatabase=20=3D>=20'server-no-names.crt__server-no-names.key.db');=0A=20= $common_connstr=20=3D=0A-=20=20"user=3Dssltestuser=20dbname=3Dtrustdb=20= sslcert=3Dinvalid=20sslrootcert=3Dssl/root+server_ca.crt=20= hostaddr=3D$SERVERHOSTADDR";=0A+=20=20"user=3Dssltestuser=20= dbname=3Dtrustdb=20sslcert=3Dinvalid=20= sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/root+server_ca.crt.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A@@=20-303,11=20+394,11=20@@=20= test_connect_ok(=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A=20=09= "sslmode=3Dverify-full=20host=3Dcommon-name.pg-ssltest.test",=0A-=09= qr/could=20not=20get=20server's=20host=20name=20from=20server=20= certificate/,=0A+=09qr/could=20not=20get=20server's=20host=20name=20from=20= server=20certificate|requested=20domain=20name=20does=20not=20match=20= the=20server's=20certificate./,=0A=20=09"server=20certificate=20without=20= CN=20or=20SANs=20sslmode=3Dverify-full");=0A=20=0A=20#=20Test=20that=20= the=20CRL=20works=0A-switch_server_cert($node,=20'server-revoked');=0A= +switch_server_cert($node,=20certfile=20=3D>=20'server-revoked',=20= nssdatabase=20=3D>=20'server-revoked.crt__server-revoked.key.db');=0A=20=0A= =20$common_connstr=20=3D=0A=20=20=20"user=3Dssltestuser=20dbname=3Dtrustdb= =20sslcert=3Dinvalid=20hostaddr=3D$SERVERHOSTADDR=20= host=3Dcommon-name.pg-ssltest.test";=0A@@=20-315,16=20+406,16=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=20file");=0A=20test_connect_fails(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrldir=3Dssl/root+server-crldir",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Dverify-ca=20= sslcrldir=3Dssl/root+server-crldir=20= cert_database=3Dssl/nss/root+server_ca.crt__root+server.crldir.db",=0A=20= =09qr/SSL=20error/,=0A=20=09"does=20not=20connect=20with=20client-side=20= CRL=20directory");=0A=20=0A@@=20-345,32=20+436,50=20@@=20command_like(=0A= =20#=20Test=20min/max=20SSL=20protocol=20versions.=0A=20test_connect_ok(=0A= =20=09$common_connstr,=0A-=09"sslrootcert=3Dssl/root+server_ca.crt=20= sslmode=3Drequire=20ssl_min_protocol_version=3DTLSv1.2=20= ssl_max_protocol_version=3DTLSv1.2",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3DTLSv1.2=20ssl_max_protocol_version=3DTLSv1.2=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09"connection=20= success=20with=20correct=20range=20of=20TLS=20protocol=20versions");=0A=20= test_connect_fails(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3DTLSv1.2=20ssl_max_protocol_version=3DTLSv1.1",=0A= +=09"sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3DTLSv1.2=20ssl_max_protocol_version=3DTLSv1.1=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09qr/invalid=20SSL=20= protocol=20version=20range/,=0A=20=09"connection=20failure=20with=20= incorrect=20range=20of=20TLS=20protocol=20versions");=0A=20= test_connect_fails(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3Dincorrect_tls",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_min_protocol_version=3Dincorrect_tls=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09qr/invalid=20= ssl_min_protocol_version=20value/,=0A=20=09"connection=20failure=20with=20= an=20incorrect=20SSL=20protocol=20minimum=20bound");=0A=20= test_connect_fails(=0A=20=09$common_connstr,=0A-=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_max_protocol_version=3Dincorrect_tls",=0A+=09= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= ssl_max_protocol_version=3Dincorrect_tls=20= cert_database=3Dssl/nss/root+server_ca.crt.db",=0A=20=09qr/invalid=20= ssl_max_protocol_version=20value/,=0A=20=09"connection=20failure=20with=20= an=20incorrect=20SSL=20protocol=20maximum=20bound");=0A=20=0A+#=20tests=20= of=20NSS=20generated=20certificates/keys=0A+SKIP:=0A+{=0A+=09skip=20"NSS=20= specific=20tests",=20=20=20=20=20=20=20=20=20=20=20=201=20if=20= ($openssl);=0A+=0A+=09switch_server_cert($node,=20certfile=20=3D>=20= 'native_server-root',=20cafile=20=3D>=20'native_ca-root',=20nssdatabase=20= =3D>=20'native_server-root.db');=0A+=09$common_connstr=20=3D=0A+=09=20=20= "user=3Dssltestuser=20dbname=3Dtrustdb=20hostaddr=3D$SERVERHOSTADDR=20= host=3Dcommon-name.pg-ssltest.test";=0A+=0A+=09test_connect_ok(=0A+=09=09= $common_connstr,=0A+=09=09"sslmode=3Drequire=20user=3Dssltestuser",=0A+=09= =09"NSS=20generated=20certificates"=0A+=09);=0A+}=0A+=0A=20###=20= Server-side=20tests.=0A=20###=0A=20###=20Test=20certificate=20= authorization.=0A=20=0A+switch_server_cert($node,=20certfile=20=3D>=20= 'server-revoked',=20nssdatabase=20=3D>=20= 'server-revoked.crt__server-revoked.key.db');=0A+=0A=20note=20"running=20= server=20tests";=0A=20=0A=20$common_connstr=20=3D=0A-=20=20= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= dbname=3Dcertdb=20hostaddr=3D$SERVERHOSTADDR";=0A+=20=20= "sslrootcert=3Dssl/root+server_ca.crt=20sslmode=3Drequire=20= dbname=3Dcertdb=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/client.crt__client.key.db";=0A=20=0A=20#=20no=20= client=20cert=0A=20test_connect_fails(=0A@@=20-386,32=20+495,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-451,18=20+571,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-475,10=20+596,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-490,7=20+614,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-514,24=20+638,28=20@@=20= test_connect_ok(=0A=20);=0A=20=0A=20#=20intermediate=20client_ca.crt=20= is=20provided=20by=20client,=20and=20isn't=20in=20server's=20ssl_ca_file=0A= -switch_server_cert($node,=20'server-cn-only',=20'root_ca');=0A= +switch_server_cert($node,=20certfile=20=3D>=20'server-cn-only',=20= cafile=20=3D>=20'root_ca',=20nssdatabase=20=3D>=20= 'server-cn-only.crt__server-cn-only.key.db');=0A=20$common_connstr=20=3D=0A= -=20=20"user=3Dssltestuser=20dbname=3Dcertdb=20sslkey=3Dssl/client_tmp.key= =20sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR";=0A= +=20=20"user=3Dssltestuser=20dbname=3Dcertdb=20sslkey=3Dssl/client_tmp.key= =20sslrootcert=3Dssl/root+server_ca.crt=20hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/client+client_ca.crt__client.key.db";=0A=20=0A=20= test_connect_ok(=0A=20=09$common_connstr,=0A=20=09"sslmode=3Drequire=20= sslcert=3Dssl/client+client_ca.crt",=0A=20=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+=0A+test_connect_fails(=0A+=09= $common_connstr,=0A+=09"sslmode=3Drequire=20sslcert=3Dssl/client.crt",=0A= +=09qr/connection=20requires=20a=20valid=20client=20certificate|SSL=20= error/,=0A+=09"intermediate=20client=20certificate=20is=20missing");=0A=20= =0A=20#=20test=20server-side=20CRL=20directory=0A= -switch_server_cert($node,=20'server-cn-only',=20undef,=20undef,=20= 'root+client-crldir');=0A+switch_server_cert($node,=20certfile=20=3D>=20= 'server-cn-only',=20crldir=20=3D>=20'root+client-crldir',=20nssdatabase=20= =3D>=20'server-cn-only.crt__server-cn-only.key.crldir.db');=0A=20=0A=20#=20= revoked=20client=20cert=0A=20test_connect_fails(=0A=20=09= $common_connstr,=0A-=09"user=3Dssltestuser=20= sslcert=3Dssl/client-revoked.crt=20sslkey=3Dssl/client-revoked_tmp.key",=0A= +=09"user=3Dssltestuser=20sslcert=3Dssl/client-revoked.crt=20= sslkey=3Dssl/client-revoked_tmp.key=20= cert_database=3Dssl/nss/client-revoked.crt__client-revoked.key.db",=0A=20= =09qr/SSL=20error/,=0A=20=09"certificate=20authorization=20fails=20with=20= revoked=20client=20cert=20with=20server-side=20CRL=20directory");=0A=20=0A= diff=20--git=20a/src/test/ssl/t/002_scram.pl=20= b/src/test/ssl/t/002_scram.pl=0Aindex=203383b3e531..801c945e88=20100644=0A= ---=20a/src/test/ssl/t/002_scram.pl=0A+++=20= b/src/test/ssl/t/002_scram.pl=0A@@=20-13,7=20+13,26=20@@=20use=20lib=20= $FindBin::RealBin;=0A=20=0A=20use=20SSL::Server;=0A=20=0A-if=20= ($ENV{with_ssl}=20ne=20'openssl')=0A+my=20$openssl;=0A+my=20$nss;=0A+=0A= +my=20$supports_tls_server_end_point;=0A+=0A+if=20($ENV{with_ssl}=20eq=20= 'openssl')=0A+{=0A+=09$openssl=20=3D=201;=0A+=09#=20Determine=20whether=20= build=20supports=20tls-server-end-point.=0A+=09= $supports_tls_server_end_point=20=3D=0A+=09=09check_pg_config("#define=20= HAVE_X509_GET_SIGNATURE_NID=201");=0A+=09plan=20tests=20=3D>=20= $supports_tls_server_end_point=20?=209=20:=2010;=0A+}=0A+elsif=20= ($ENV{with_ssl}=20eq=20'nss')=0A+{=0A+=09$nss=20=3D=201;=0A+=09= $supports_tls_server_end_point=20=3D=201;=0A+=09plan=20tests=20=3D>=209;=0A= +}=0A+else=0A=20{=0A=20=09plan=20skip_all=20=3D>=20'SSL=20not=20= supported=20by=20this=20build';=0A=20}=0A@@=20-23,12=20+42,6=20@@=20my=20= $SERVERHOSTADDR=20=3D=20'127.0.0.1';=0A=20#=20This=20is=20the=20pattern=20= to=20use=20in=20pg_hba.conf=20to=20match=20incoming=20connections.=0A=20= my=20$SERVERHOSTCIDR=20=3D=20'127.0.0.1/32';=0A=20=0A-#=20Determine=20= whether=20build=20supports=20tls-server-end-point.=0A-my=20= $supports_tls_server_end_point=20=3D=0A-=20=20check_pg_config("#define=20= HAVE_X509_GET_SIGNATURE_NID=201");=0A-=0A-my=20$number_of_tests=20=3D=20= $supports_tls_server_end_point=20?=209=20:=2010;=0A-=0A=20#=20Allocation=20= of=20base=20connection=20string=20shared=20among=20multiple=20tests.=0A=20= my=20$common_connstr;=0A=20=0A@@=20-47,7=20+60,7=20@@=20$node->start;=0A=20= #=20Configure=20server=20for=20SSL=20connections,=20with=20password=20= handling.=0A=20configure_test_server_for_ssl($node,=20$SERVERHOSTADDR,=20= $SERVERHOSTCIDR,=0A=20=09"scram-sha-256",=20"pass",=20"scram-sha-256");=0A= -switch_server_cert($node,=20'server-cn-only');=0A= +switch_server_cert($node,=20certfile=20=3D>=20'server-cn-only',=20= nssdatabase=20=3D>=20'server-cn-only.crt__server-cn-only.key.db');=0A=20= $ENV{PGPASSWORD}=20=3D=20"pass";=0A=20$common_connstr=20=3D=0A=20=20=20= "dbname=3Dtrustdb=20sslmode=3Drequire=20sslcert=3Dinvalid=20= sslrootcert=3Dinvalid=20hostaddr=3D$SERVERHOSTADDR";=0A@@=20-97,7=20= +110,7=20@@=20my=20$client_tmp_key=20=3D=20"ssl/client_scram_tmp.key";=0A= =20copy("ssl/client.key",=20$client_tmp_key);=0A=20chmod=200600,=20= $client_tmp_key;=0A=20test_connect_fails(=0A-=09"sslcert=3Dssl/client.crt=20= sslkey=3D$client_tmp_key=20sslrootcert=3Dinvalid=20= hostaddr=3D$SERVERHOSTADDR",=0A+=09"sslcert=3Dssl/client.crt=20= sslkey=3D$client_tmp_key=20sslrootcert=3Dinvalid=20= hostaddr=3D$SERVERHOSTADDR=20= cert_database=3Dssl/nss/client.crt__client.key.db",=0A=20=09= "dbname=3Dcertdb=20user=3Dssltestuser=20channel_binding=3Drequire",=0A=20= =09qr/channel=20binding=20required,=20but=20server=20authenticated=20= client=20without=20channel=20binding/,=0A=20=09"Cert=20authentication=20= and=20channel_binding=3Drequire");=0Adiff=20--git=20= a/src/test/ssl/t/SSL/Backend/NSS.pm=20= b/src/test/ssl/t/SSL/Backend/NSS.pm=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..20633fe41b=0A---=20/dev/null=0A+++=20= b/src/test/ssl/t/SSL/Backend/NSS.pm=0A@@=20-0,0=20+1,61=20@@=0A+package=20= SSL::Backend::NSS;=0A+=0A+use=20strict;=0A+use=20warnings;=0A+use=20= Exporter;=0A+=0A+our=20@ISA=20=20=20=20=20=20=20=3D=20qw(Exporter);=0A= +our=20@EXPORT_OK=20=3D=20qw(get_new_nss_backend);=0A+=0A+sub=20new=0A+{=0A= +=09my=20($class)=20=3D=20@_;=0A+=0A+=09my=20$self=20=3D=20{=20_library=20= =3D>=20'NSS'=20};=0A+=0A+=09bless=20$self,=20$class;=0A+=0A+=09return=20= $self;=0A+}=0A+=0A+sub=20get_new_nss_backend=0A+{=0A+=09my=20$class=20=3D=20= 'SSL::Backend::NSS';=0A+=0A+=09return=20$class->new();=0A+}=0A+=0A+sub=20= init=0A+{=0A+=09#=20Make=20sure=20the=20certificate=20databases=20are=20= in=20place?=0A+}=0A+=0A+sub=20get_library=0A+{=0A+=09my=20($self)=20=3D=20= @_;=0A+=0A+=09return=20$self->{_library};=0A+}=0A+=0A+sub=20= set_server_cert=0A+{=0A+=09my=20$self=20=20=20=3D=20$_[0];=0A+=09my=20= $params=20=3D=20$_[1];=0A+=0A+=09$params->{cafile}=20=3D=20= 'root+client_ca'=20unless=20defined=20$params->{cafile};=0A+=0A+=09my=20= $sslconf=20=3D=0A+=09=20=20=20=20"ssl_ca_file=3D'$params->{cafile}.crt'\n"= =0A+=09=20=20.=20"ssl_cert_file=3D'ssl/$params->{certfile}.crt'\n"=0A+=09= =20=20.=20"ssl_crl_file=3D''\n"=0A+=09=20=20.=20= "ssl_database=3D'nss/$params->{nssdatabase}'\n";=0A+=0A+=09return=20= $sslconf;=0A+}=0A+=0A+sub=20cleanup=0A+{=0A+=09#=20Something?=0A+}=0A+=0A= +1;=0Adiff=20--git=20a/src/test/ssl/t/SSL/Backend/OpenSSL.pm=20= b/src/test/ssl/t/SSL/Backend/OpenSSL.pm=0Aindex=2062b11b7632..ecceaefe57=20= 100644=0A---=20a/src/test/ssl/t/SSL/Backend/OpenSSL.pm=0A+++=20= b/src/test/ssl/t/SSL/Backend/OpenSSL.pm=0A@@=20-71,18=20+71,19=20@@=20= sub=20init=0A=20#=20the=20server=20so=20that=20the=20configuration=20= takes=20effect.=0A=20sub=20set_server_cert=0A=20{=0A-=09my=20$self=20=20=20= =20=20=3D=20$_[0];=0A-=09my=20$certfile=20=3D=20$_[1];=0A-=09my=20= $cafile=20=20=20=3D=20$_[2]=20||=20"root+client_ca";=0A-=09my=20$keyfile=20= =20=3D=20$_[3]=20||=20$certfile;=0A+=09my=20$self=20=20=20=3D=20$_[0];=0A= +=09my=20$params=20=3D=20$_[1];=0A=20=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+=09$params->{cafile}=20=3D=20= 'root+client_ca'=20unless=20defined=20$params->{cafile};=0A+=09= $params->{crlfile}=20=3D=20'root+client.crl'=20unless=20defined=20= $params->{crlfile};=0A+=09$params->{keyfile}=20=3D=20$params->{certfile}=20= unless=20defined=20$params->{keyfile};=0A=20=0A-=09return=20$sslconf;=0A= +=09my=20$sslconf=20=3D=0A+=09=20=20=20=20= "ssl_ca_file=3D'$params->{cafile}.crt'\n"=0A+=09=20=20.=20= "ssl_cert_file=3D'$params->{certfile}.crt'\n"=0A+=09=20=20.=20= "ssl_key_file=3D'$params->{keyfile}.key'\n"=0A+=09=20=20.=20= "ssl_crl_file=3D'$params->{crlfile}'\n";=0A+=09$sslconf=20.=3D=20= "ssl_crl_dir=3D'$params->{crldir}'\n"=20if=20defined=20= $params->{crldir};=0A=20}=0A=20=0A=20sub=20get_library=0Adiff=20--git=20= a/src/test/ssl/t/SSL/Server.pm=20b/src/test/ssl/t/SSL/Server.pm=0Aindex=20= e59554f85b..da90b2c1d3=20100644=0A---=20a/src/test/ssl/t/SSL/Server.pm=0A= +++=20b/src/test/ssl/t/SSL/Server.pm=0A@@=20-55,7=20+55,6=20@@=20elsif=20= ($ENV{with_ssl}=20eq=20'nss')=0A=20use=20Exporter=20'import';=0A=20our=20= @EXPORT=20=3D=20qw(=0A=20=20=20configure_test_server_for_ssl=0A-=20=20= set_server_cert=0A=20=20=20switch_server_cert=0A=20=20=20= test_connect_fails=0A=20=20=20test_connect_ok=0A@@=20-202,46=20+201,21=20= @@=20sub=20cleanup=0A=20=09$backend->cleanup();=0A=20}=0A=20=0A-#=20= Change=20the=20configuration=20to=20use=20given=20server=20cert=20file,=0A= -sub=20set_server_cert=0A+#=20Change=20the=20configuration=20to=20use=20= the=20given=20set=20of=20certificate,=20key,=20ca=20and=0A+#=20CRL,=20= and=20potentially=20reload=20the=20server=20so=20that=20the=20= configuration=20takes=20effect.=0A+sub=20switch_server_cert=0A=20{=0A-=09= my=20$node=20=20=20=20=20=3D=20$_[0];=0A-=09my=20$certfile=20=3D=20= $_[1];=0A-=09my=20$cafile=20=20=20=3D=20$_[2]=20||=20"root+client_ca";=0A= -=09my=20$keyfile=20=20=3D=20$_[3]=20||=20'';=0A-=09my=20$pwcmd=20=20=20=20= =3D=20$_[4]=20||=20'';=0A-=09my=20$crlfile=20=20=3D=20"root+client.crl";=0A= -=09my=20$crldir;=0A-=09my=20$pgdata=20=20=20=3D=20$node->data_dir;=0A-=0A= -=09$keyfile=20=3D=20$certfile=20if=20$keyfile=20eq=20'';=0A-=0A-=09#=20= defaults=20to=20use=20crl=20file=0A-=09if=20(defined=20$_[3]=20||=20= defined=20$_[4])=0A-=09{=0A-=09=09$crlfile=20=3D=20$_[3];=0A-=09=09= $crldir=20=3D=20$_[4];=0A-=09}=0A+=09my=20$node=20=20=20=3D=20shift;=0A+=09= my=20%params=20=3D=20@_;=0A+=09my=20$pgdata=20=3D=20$node->data_dir;=0A=20= =0A=20=09open=20my=20$sslconf,=20'>',=20"$pgdata/sslconfig.conf";=0A=20=09= print=20$sslconf=20"ssl=3Don\n";=0A-=09print=20$sslconf=20= $backend->set_server_cert($certfile,=20$cafile,=20$keyfile);=0A-=09print=20= $sslconf=20"ssl_crl_file=3D'$crlfile'\n"=20if=20defined=20$crlfile;=0A-=09= print=20$sslconf=20"ssl_crl_dir=3D'$crldir'\n"=20if=20defined=20$crldir;=0A= -=09print=20$sslconf=20"ssl_passphrase_command=3D'$pwcmd'\n"=0A-=09=20=20= unless=20$pwcmd=20eq=20'';=0A+=09print=20$sslconf=20= $backend->set_server_cert(\%params);=0A+=09print=20$sslconf=20= "ssl_passphrase_command=3D'"=20.=20$params{passphrase_cmd}=20.=20"'\n"=0A= +=09=20=20if=20defined=20$params{passphrase_cmd};=0A=20=09close=20= $sslconf;=0A-=09return;=0A-}=0A=20=0A-#=20Change=20the=20configuration=20= to=20use=20given=20server=20cert=20file,=20and=20reload=0A-#=20the=20= server=20so=20that=20the=20configuration=20takes=20effect.=0A-#=20Takes=20= the=20same=20arguments=20as=20set_server_cert,=20which=20it=20calls=20to=20= do=20that=0A-#=20piece=20of=20the=20work.=0A-sub=20switch_server_cert=0A= -{=0A-=09my=20$node=20=3D=20$_[0];=0A-=09set_server_cert(@_);=0A=20=09= $node->restart;=0A=20=09return;=0A=20}=0A--=20=0A2.21.1=20(Apple=20= Git-122.3)=0A=0A= --Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5 Content-Disposition: attachment; filename=v28-0002-Refactor-SSL-testharness-for-multiple-library.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v28-0002-Refactor-SSL-testharness-for-multiple-library.patch" Content-Transfer-Encoding: quoted-printable =46rom=20da2520aec462b80609c318b6c196bcc24a61bf57=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:34=20+0100=0ASubject:=20[PATCH=20= v28=202/9]=20Refactor=20SSL=20testharness=20for=20multiple=20library=0A=0A= The=20SSL=20testharness=20was=20fully=20tied=20to=20OpenSSL=20in=20the=20= way=20the=20server=20was=0Aset=20up=20and=20reconfigured.=20This=20= refactors=20the=20SSLServer=20module=20into=20a=20SSL=0Alibrary=20= agnostic=20SSL/Server=20module=20which=20in=20turn=20use=20= SSL/Backend/=0Amodules=20for=20the=20implementation=20details.=0A=0A= No=20changes=20are=20done=20to=20the=20actual=20tests,=20this=20only=20= change=20how=20setup=20and=0Ateardown=20is=20performed.=0A---=0A=20= src/test/ssl/t/001_ssltests.pl=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20|=20=2056=20++--------=0A=20src/test/ssl/t/002_scram.pl=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=206=20+-=0A=20= src/test/ssl/t/SSL/Backend/OpenSSL.pm=20=20=20=20=20=20=20=20=20|=20103=20= ++++++++++++++++++=0A=20.../ssl/t/{SSLServer.pm=20=3D>=20SSL/Server.pm}=20= =20=20=20=20|=20=2083=20+++++++++++---=0A=204=20files=20changed,=20181=20= insertions(+),=2067=20deletions(-)=0A=20create=20mode=20100644=20= src/test/ssl/t/SSL/Backend/OpenSSL.pm=0A=20rename=20= src/test/ssl/t/{SSLServer.pm=20=3D>=20SSL/Server.pm}=20(78%)=0A=0Adiff=20= --git=20a/src/test/ssl/t/001_ssltests.pl=20= b/src/test/ssl/t/001_ssltests.pl=0Aindex=20864f6e209f..30b68bddbe=20= 100644=0A---=20a/src/test/ssl/t/001_ssltests.pl=0A+++=20= b/src/test/ssl/t/001_ssltests.pl=0A@@=20-4,12=20+4,10=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=20=0A=20if=20= ($ENV{with_ssl}=20ne=20'openssl')=0A=20{=0A@@=20-32,32=20+30,6=20@@=20my=20= $SERVERHOSTCIDR=20=3D=20'127.0.0.1/32';=0A=20#=20Allocation=20of=20base=20= connection=20string=20shared=20among=20multiple=20tests.=0A=20my=20= $common_connstr;=0A=20=0A-#=20The=20client's=20private=20key=20must=20= not=20be=20world-readable,=20so=20take=20a=20copy=0A-#=20of=20the=20key=20= stored=20in=20the=20code=20tree=20and=20update=20its=20permissions.=0A-#=0A= -#=20This=20changes=20ssl/client.key=20to=20ssl/client_tmp.key=20etc=20= for=20the=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,32=20+44,22=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-=0A+set_server_cert($node,=20'server-cn-only',=20= 'root+client_ca',=0A+=09=09=09=09=20=20=20'server-password',=20'echo=20= wrongpassword');=0A=20command_fails(=0A=20=09[=20'pg_ctl',=20'-D',=20= $node->data_dir,=20'-l',=20$node->logfile,=20'restart'=20],=0A=20=09= 'restart=20fails=20with=20password-protected=20key=20file=20with=20wrong=20= password');=0A=20$node->_update_pid(0);=0A=20=0A-open=20$sslconf,=20'>',=20= $node->data_dir=20.=20"/sslconfig.conf";=0A-print=20$sslconf=20= "ssl=3Don\n";=0A-print=20$sslconf=20= "ssl_cert_file=3D'server-cn-only.crt'\n";=0A-print=20$sslconf=20= "ssl_key_file=3D'server-password.key'\n";=0A-print=20$sslconf=20= "ssl_passphrase_command=3D'echo=20secret1'\n";=0A-close=20$sslconf;=0A-=0A= +set_server_cert($node,=20'server-cn-only',=20'root+client_ca',=0A+=09=09= =09=09'server-password',=20'echo=20secret1');=0A=20command_ok(=0A=20=09[=20= 'pg_ctl',=20'-D',=20$node->data_dir,=20'-l',=20$node->logfile,=20= 'restart'=20],=0A=20=09'restart=20succeeds=20with=20password-protected=20= key=20file');=0A@@=20-574,7=20+536,5=20@@=20test_connect_fails(=0A=20=09= "certificate=20authorization=20fails=20with=20revoked=20client=20cert=20= with=20server-side=20CRL=20directory");=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=20= a/src/test/ssl/t/002_scram.pl=20b/src/test/ssl/t/002_scram.pl=0Aindex=20= 410b9e910d..3383b3e531=20100644=0A---=20a/src/test/ssl/t/002_scram.pl=0A= +++=20b/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=20if=20= ($ENV{with_ssl}=20ne=20'openssl')=0A=20{=0A-=09plan=20skip_all=20=3D>=20= 'OpenSSL=20not=20supported=20by=20this=20build';=0A+=09plan=20skip_all=20= =3D>=20'SSL=20not=20supported=20by=20this=20build';=0A=20}=0A=20=0A=20#=20= This=20is=20the=20hostname=20used=20to=20connect=20to=20the=20server.=0A= @@=20-104,5=20+104,3=20@@=20test_connect_fails(=0A=20=0A=20#=20clean=20= up=0A=20unlink($client_tmp_key);=0A-=0A-done_testing($number_of_tests);=0A= diff=20--git=20a/src/test/ssl/t/SSL/Backend/OpenSSL.pm=20= b/src/test/ssl/t/SSL/Backend/OpenSSL.pm=0Anew=20file=20mode=20100644=0A= index=200000000000..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=205ec5e0dac8..e59554f85b=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,14=20+164,21=20@@=20sub=20= configure_test_server_for_ssl=0A=20=09close=20$sslconf;=0A=20=0A=20=09#=20= Copy=20all=20server=20certificates=20and=20keys,=20and=20client=20root=20= cert,=20to=20the=20data=20dir=0A-=09copy_files("ssl/server-*.crt",=20= $pgdata);=0A-=09copy_files("ssl/server-*.key",=20$pgdata);=0A-=09= chmod(0600,=20glob=20"$pgdata/server-*.key")=20or=20die=20$!;=0A-=09= copy_files("ssl/root+client_ca.crt",=20$pgdata);=0A-=09= copy_files("ssl/root_ca.crt",=20=20=20=20=20=20=20=20$pgdata);=0A-=09= copy_files("ssl/root+client.crl",=20=20=20=20$pgdata);=0A-=09= mkdir("$pgdata/root+client-crldir");=0A-=09= copy_files("ssl/root+client-crldir/*",=20"$pgdata/root+client-crldir/");=0A= +=09if=20(defined($openssl))=0A+=09{=0A+=09=09= copy_files("ssl/server-*.crt",=20$pgdata);=0A+=09=09= copy_files("ssl/server-*.key",=20$pgdata);=0A+=09=09chmod(0600,=20glob=20= "$pgdata/server-*.key")=20or=20die=20$!;=0A+=09=09= copy_files("ssl/root+client_ca.crt",=20$pgdata);=0A+=09=09= copy_files("ssl/root_ca.crt",=20=20=20=20=20=20=20=20$pgdata);=0A+=09=09= copy_files("ssl/root+client.crl",=20=20=20=20$pgdata);=0A+=09=09= mkdir("$pgdata/root+client-crldir");=0A+=09=09= copy_files("ssl/root+client-crldir/*",=20"$pgdata/root+client-crldir/");=0A= +=09}=0A+=09elsif=20(defined($nss))=0A+=09{=0A+=09=09= RecursiveCopy::copypath("ssl/nss",=20$pgdata=20.=20"/nss")=20if=20-e=20= "ssl/nss";=0A+=09}=0A=20=0A=20=09#=20Stop=20and=20restart=20server=20to=20= load=20new=20listen_addresses.=0A=20=09$node->restart;=0A@@=20-159,20=20= +186,36=20@@=20sub=20configure_test_server_for_ssl=0A=20=09#=20Change=20= pg_hba=20after=20restart=20because=20hostssl=20requires=20ssl=3Don=0A=20=09= configure_hba_for_ssl($node,=20$servercidr,=20$authmethod);=0A=20=0A+=09= #=20Finally,=20perform=20backend=20specific=20configuration=0A+=09= $backend->init();=0A+=0A=20=09return;=0A=20}=0A=20=0A-#=20Change=20the=20= configuration=20to=20use=20given=20server=20cert=20file,=20and=20reload=0A= -#=20the=20server=20so=20that=20the=20configuration=20takes=20effect.=0A= -sub=20switch_server_cert=0A+sub=20ssl_library=0A+{=0A+=09return=20= $backend->get_library();=0A+}=0A+=0A+sub=20cleanup=0A+{=0A+=09= $backend->cleanup();=0A+}=0A+=0A+#=20Change=20the=20configuration=20to=20= use=20given=20server=20cert=20file,=0A+sub=20set_server_cert=0A=20{=0A=20= =09my=20$node=20=20=20=20=20=3D=20$_[0];=0A=20=09my=20$certfile=20=3D=20= $_[1];=0A=20=09my=20$cafile=20=20=20=3D=20$_[2]=20||=20"root+client_ca";=0A= +=09my=20$keyfile=20=20=3D=20$_[3]=20||=20'';=0A+=09my=20$pwcmd=20=20=20=20= =3D=20$_[4]=20||=20'';=0A=20=09my=20$crlfile=20=20=3D=20= "root+client.crl";=0A=20=09my=20$crldir;=0A=20=09my=20$pgdata=20=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=09#=20defaults=20to=20use=20crl=20file=0A=20=09if=20= (defined=20$_[3]=20||=20defined=20$_[4])=0A=20=09{=0A@@=20-182,13=20= +225,23=20@@=20sub=20switch_server_cert=0A=20=0A=20=09open=20my=20= $sslconf,=20'>',=20"$pgdata/sslconfig.conf";=0A=20=09print=20$sslconf=20= "ssl=3Don\n";=0A-=09print=20$sslconf=20"ssl_ca_file=3D'$cafile.crt'\n";=0A= -=09print=20$sslconf=20"ssl_cert_file=3D'$certfile.crt'\n";=0A-=09print=20= $sslconf=20"ssl_key_file=3D'$certfile.key'\n";=0A+=09print=20$sslconf=20= $backend->set_server_cert($certfile,=20$cafile,=20$keyfile);=0A=20=09= print=20$sslconf=20"ssl_crl_file=3D'$crlfile'\n"=20if=20defined=20= $crlfile;=0A=20=09print=20$sslconf=20"ssl_crl_dir=3D'$crldir'\n"=20if=20= defined=20$crldir;=0A+=09print=20$sslconf=20= "ssl_passphrase_command=3D'$pwcmd'\n"=0A+=09=20=20unless=20$pwcmd=20eq=20= '';=0A=20=09close=20$sslconf;=0A+=09return;=0A+}=0A=20=0A+#=20Change=20= the=20configuration=20to=20use=20given=20server=20cert=20file,=20and=20= reload=0A+#=20the=20server=20so=20that=20the=20configuration=20takes=20= effect.=0A+#=20Takes=20the=20same=20arguments=20as=20set_server_cert,=20= which=20it=20calls=20to=20do=20that=0A+#=20piece=20of=20the=20work.=0A= +sub=20switch_server_cert=0A+{=0A+=09my=20$node=20=3D=20$_[0];=0A+=09= set_server_cert(@_);=0A=20=09$node->restart;=0A=20=09return;=0A=20}=0A--=20= =0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5 Content-Disposition: attachment; filename=v28-0001-nss-Support-libnss-as-TLS-library-in-libpq.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v28-0001-nss-Support-libnss-as-TLS-library-in-libpq.patch" Content-Transfer-Encoding: quoted-printable =46rom=206d6179180f41746c65ab139e4cf0e85fc5fb84bc=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20=0A= Date:=20Mon,=208=20Feb=202021=2023:52:22=20+0100=0ASubject:=20[PATCH=20= v28=201/9]=20nss:=20Support=20libnss=20as=20TLS=20library=20in=20libpq=0A= =0AThis=20commit=20contains=20the=20frontend=20and=20backend=20portion=20= of=20TLS=20support=0Ain=20libpq=20to=20allow=20encrypted=20connections.=20= The=20implementation=20is=20done=0Aas=20a=20drop-in=20replacement=20for=20= the=20OpenSSL=20support=20and=20leverages=20the=0Asame=20internal=20API=20= for=20abstracting=20library=20specific=20details.=0A=0AA=20new=20GUC,=20= ssl_database,=20is=20used=20to=20identify=20the=20NSS=20database=20used=20= for=0Athe=20serverside=20certificates=20and=20keys.=20The=20existing=20= certificate=20and=20key=0AGUCs=20are=20used=20for=20providing=20= certificate=20and=20key=20nicknames.=0A=0AClient=20side=20there=20is=20a=20= new=20connection=20parameter,=20cert_database,=20to=0Aidentify=20the=20= client=20cert=20and=20key.=20All=20existing=20sslmodes=20are=20supported=0A= in=20the=20same=20way=20as=20with=20OpenSSL.=0A=0AAuthors:=20Daniel=20= Gustafsson,=20Andrew=20Dunstan,=20Jacob=20Champion=0AReviewed-by:=20= Michael=20Paquier=0A---=0A=20.../postgres_fdw/expected/postgres_fdw.out=20= =20=20=20|=20=20=20=202=20+-=0A=20src/backend/libpq/auth.c=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=20=207=20+=0A=20= src/backend/libpq/be-secure-nss.c=20=20=20=20=20=20=20=20=20=20=20=20=20= |=201388=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/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=20src/common/cipher_nss.c=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20192=20+++=0A=20= src/include/common/nss.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20|=20=20=2049=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=2010=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_manual.h=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=20=202=20+-=0A=20= src/interfaces/libpq/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|=201088=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=2021=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=2025=20+-=0A=2015=20files=20changed,=202820=20insertions(+),=205=20= deletions(-)=0A=20create=20mode=20100644=20= src/backend/libpq/be-secure-nss.c=0A=20create=20mode=20100644=20= src/common/cipher_nss.c=0A=20create=20mode=20100644=20= src/include/common/nss.h=0A=20create=20mode=20100644=20= src/interfaces/libpq/fe-secure-nss.c=0A=0Adiff=20--git=20= a/contrib/postgres_fdw/expected/postgres_fdw.out=20= b/contrib/postgres_fdw/expected/postgres_fdw.out=0Aindex=20= 0649b6b81c..3d51a7c9b8=20100644=0A---=20= a/contrib/postgres_fdw/expected/postgres_fdw.out=0A+++=20= b/contrib/postgres_fdw/expected/postgres_fdw.out=0A@@=20-8946,7=20= +8946,7=20@@=20DO=20$d$=0A=20=20=20=20=20END;=0A=20$d$;=0A=20ERROR:=20=20= invalid=20option=20"password"=0A-HINT:=20=20Valid=20options=20in=20this=20= context=20are:=20service,=20passfile,=20channel_binding,=20= connect_timeout,=20dbname,=20host,=20hostaddr,=20port,=20options,=20= application_name,=20keepalives,=20keepalives_idle,=20= keepalives_interval,=20keepalives_count,=20tcp_user_timeout,=20sslmode,=20= sslcompression,=20sslcert,=20sslkey,=20sslrootcert,=20sslcrl,=20= sslcrldir,=20requirepeer,=20ssl_min_protocol_version,=20= ssl_max_protocol_version,=20gssencmode,=20krbsrvname,=20gsslib,=20= target_session_attrs,=20use_remote_estimate,=20fdw_startup_cost,=20= fdw_tuple_cost,=20extensions,=20updatable,=20fetch_size,=20batch_size=0A= +HINT:=20=20Valid=20options=20in=20this=20context=20are:=20service,=20= passfile,=20channel_binding,=20connect_timeout,=20dbname,=20host,=20= hostaddr,=20port,=20options,=20application_name,=20keepalives,=20= keepalives_idle,=20keepalives_interval,=20keepalives_count,=20= tcp_user_timeout,=20sslmode,=20sslcompression,=20sslcert,=20sslkey,=20= sslrootcert,=20sslcrl,=20sslcrldir,=20requirepeer,=20= ssl_min_protocol_version,=20ssl_max_protocol_version,=20gssencmode,=20= krbsrvname,=20gsslib,=20target_session_attrs,=20cert_database,=20= use_remote_estimate,=20fdw_startup_cost,=20fdw_tuple_cost,=20extensions,=20= updatable,=20fetch_size,=20batch_size=0A=20CONTEXT:=20=20SQL=20statement=20= "ALTER=20SERVER=20loopback_nopw=20OPTIONS=20(ADD=20password=20= 'dummypw')"=0A=20PL/pgSQL=20function=20inline_code_block=20line=203=20at=20= EXECUTE=0A=20--=20If=20we=20add=20a=20password=20for=20our=20user=20= mapping=20instead,=20we=20should=20get=20a=20different=0Adiff=20--git=20= a/src/backend/libpq/auth.c=20b/src/backend/libpq/auth.c=0Aindex=20= 545635f41a..09ad2ad063=20100644=0A---=20a/src/backend/libpq/auth.c=0A+++=20= b/src/backend/libpq/auth.c=0A@@=20-2849,7=20+2849,14=20@@=20= CheckCertAuth(Port=20*port)=0A=20{=0A=20=09int=09=09=09= status_check_usermap=20=3D=20STATUS_ERROR;=0A=20=0A+#if=20= defined(USE_OPENSSL)=0A=20=09Assert(port->ssl);=0A+#elif=20= defined(USE_NSS)=0A+=09/*=20TODO:=20should=20we=20rename=20pr_fd=20to=20= ssl,=20to=20keep=20consistency?=20*/=0A+=09Assert(port->pr_fd);=0A+#else=0A= +=09Assert(false);=0A+#endif=0A=20=0A=20=09/*=20Make=20sure=20we=20have=20= received=20a=20username=20in=20the=20certificate=20*/=0A=20=09if=20= (port->peer_cn=20=3D=3D=20NULL=20||=0Adiff=20--git=20= a/src/backend/libpq/be-secure-nss.c=20= b/src/backend/libpq/be-secure-nss.c=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..a17e6c7e5d=0A---=20/dev/null=0A+++=20= b/src/backend/libpq/be-secure-nss.c=0A@@=20-0,0=20+1,1388=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20be-secure-nss.c=0A+=20*=09=20=20functions=20for=20= supporting=20NSS=20as=20a=20TLS=20backend=0A+=20*=0A+=20*=0A+=20*=20= Portions=20Copyright=20(c)=201996-2021,=20PostgreSQL=20Global=20= Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=201994,=20= Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=09=20=20src/backend/libpq/be-secure-nss.c=0A+=20*=0A= +=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#include=20"postgres.h"=0A+=0A+#include=20=0A= +=0A+#include=20"common/nss.h"=0A+=0A+/*=0A+=20*=20The=20= nspr/obsolete/protypes.h=20NSPR=20header=20typedefs=20uint64=20and=20= int64=20with=0A+=20*=20colliding=20definitions=20from=20ours,=20causing=20= a=20much=20expected=20compiler=20error.=0A+=20*=20Remove=20backwards=20= compatibility=20with=20ancient=20NSPR=20versions=20to=20avoid=20this.=0A= +=20*/=0A+#define=20NO_NSPR_10_SUPPORT=0A+#include=20=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+#include=20=0A+=0A= +#include=20"lib/stringinfo.h"=0A+#include=20"libpq/libpq.h"=0A+#include=20= "nodes/pg_list.h"=0A+#include=20"miscadmin.h"=0A+#include=20= "storage/fd.h"=0A+#include=20"utils/guc.h"=0A+#include=20= "utils/memutils.h"=0A+=0A+=0A+/*=20default=20init=20hook=20can=20be=20= overridden=20by=20a=20shared=20library=20*/=0A+static=20void=20= default_nss_tls_init(bool=20isServerStart);=0A+nss_tls_init_hook_type=20= nss_tls_init_hook=20=3D=20default_nss_tls_init;=0A+=0A+static=20= PRDescIdentity=20pr_id;=0A+=0A+static=20PRIOMethods=20pr_iomethods;=0A= +static=20NSSInitContext=20*nss_context=20=3D=20NULL;=0A+static=20= SSLVersionRange=20desired_sslver;=0A+=0A+static=20char=20= *external_ssl_passphrase_cb(PK11SlotInfo=20*slot,=20PRBool=20retry,=20= void=20*arg);=0A+static=20SECStatus=20pg_SSLShutdownFunc(void=20= *private_data,=20void=20*nss_data);=0A+static=20bool=20= dummy_ssl_passwd_cb_called=20=3D=20false;=0A+static=20bool=20= ssl_is_server_start;=0A+=0A+/*=0A+=20*=20PR_ImportTCPSocket()=20is=20a=20= private=20API,=20but=20very=20widely=20used,=20as=20it's=20the=0A+=20*=20= only=20way=20to=20make=20NSS=20use=20an=20already=20set=20up=20POSIX=20= file=20descriptor=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+/*=20= NSS=20IO=20layer=20callback=20overrides=20*/=0A+static=20PRInt32=20= pg_ssl_read(PRFileDesc=20*fd,=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*fd,=20const=20void=20= *buf,=20PRInt32=20amount,=0A+=09=09=09=09=09=09=09PRIntn=20flags,=20= PRIntervalTime=20timeout);=0A+static=20PRStatus=20= pg_ssl_close(PRFileDesc=20*fd);=0A+/*=20Utility=20functions=20*/=0A= +static=20PRFileDesc=20*init_iolayer(Port=20*port);=0A+static=20uint16=20= ssl_protocol_version_to_nss(int=20v,=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*fd,=0A+=09=09=09=09=09=09= =09=09=09=20=20PRBool=20checksig,=20PRBool=20isServer);=0A+static=20= SECStatus=20pg_bad_cert_handler(void=20*arg,=20PRFileDesc=20*fd);=0A= +static=20char=20*dummy_ssl_passphrase_cb(PK11SlotInfo=20*slot,=20PRBool=20= retry,=20void=20*arg);=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09=09=09=09=20Public=20interface=09=09=09=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +/*=0A+=20*=20be_tls_init=0A+=20*=09=09=09Initialize=20the=20nss=20TLS=20= library=20in=20the=20postmaster=0A+=20*=0A+=20*=20The=20majority=20of=20= the=20setup=20needs=20to=20happen=20in=20be_tls_open_server=20since=20= the=0A+=20*=20NSPR=20initialization=20must=20happen=20after=20the=20= forking=20of=20the=20backend.=20We=20could=0A+=20*=20potentially=20move=20= some=20parts=20in=20under=20!isServerStart,=20but=20so=20far=20this=20is=20= the=0A+=20*=20separation=20chosen.=0A+=20*/=0A+int=0A+be_tls_init(bool=20= isServerStart)=0A+{=0A+=09SECStatus=09status;=0A+=09SSLVersionRange=20= supported_sslver;=0A+=0A+=09status=20=3D=20= SSL_ConfigServerSessionIDCacheWithOpt(0,=200,=20NULL,=201,=200,=200,=20= PR_FALSE);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09= ereport(isServerStart=20?=20FATAL=20:=20LOG,=0A+=09=09=09=09= (errmsg("unable=20to=20connect=20to=20TLS=20connection=20cache:=20%s",=0A= +=09=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20= -1;=0A+=09}=0A+=0A+=09if=20(!ssl_database=20||=20strlen(ssl_database)=20= =3D=3D=200)=0A+=09{=0A+=09=09ereport(isServerStart=20?=20FATAL=20:=20= LOG,=0A+=09=09=09=09(errmsg("no=20certificate=20database=20= specified")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20= We=20check=20for=20the=20desired=20TLS=20version=20range=20here,=20even=20= though=20we=20cannot=0A+=09=20*=20set=20it=20until=20be_open_server=20= such=20that=20we=20can=20be=20compatible=20with=20how=20the=0A+=09=20*=20= OpenSSL=20backend=20reports=20errors=20for=20incompatible=20range=20= configurations.=0A+=09=20*=20Set=20either=20the=20default=20supported=20= TLS=20version=20range,=20or=20the=20configured=0A+=09=20*=20range=20from=20= ssl_min_protocol_version=20and=20ssl_max_protocol=20version.=20In=0A+=09=20= *=20case=20the=20user=20hasn't=20defined=20the=20maximum=20allowed=20= version=20we=20fall=20back=0A+=09=20*=20to=20the=20highest=20version=20= TLS=20that=20the=20library=20supports.=0A+=09=20*/=0A+=09if=20= (SSL_VersionRangeGetSupported(ssl_variant_stream,=20&supported_sslver)=20= !=3D=20SECSuccess)=0A+=09{=0A+=09=09ereport(isServerStart=20?=20FATAL=20= :=20LOG,=0A+=09=09=09=09(errmsg("unable=20to=20get=20default=20protocol=20= support=20from=20NSS")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09/*=0A+=09= =20*=20Set=20the=20fallback=20versions=20for=20the=20TLS=20protocol=20= version=20range=20to=20a=0A+=09=20*=20combination=20of=20our=20minimal=20= requirement=20and=20the=20library=20maximum.=20Error=0A+=09=20*=20= messages=20should=20be=20kept=20identical=20to=20those=20in=20= be-secure-openssl.c=20to=0A+=09=20*=20make=20translations=20easier.=0A+=09= =20*/=0A+=09desired_sslver.min=20=3D=20SSL_LIBRARY_VERSION_TLS_1_0;=0A+=09= desired_sslver.max=20=3D=20supported_sslver.max;=0A+=0A+=09if=20= (ssl_min_protocol_version)=0A+=09{=0A+=09=09int=09=09=09ver=20=3D=20= ssl_protocol_version_to_nss(ssl_min_protocol_version,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=20=20"ssl_min_protocol_version");=0A+=0A+=09=09if=20= (ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09ereport(isServerStart=20?=20= FATAL=20:=20LOG,=0A+=09=09=09=09=09(errmsg("\"%s\"=20setting=20\"%s\"=20= not=20supported=20by=20this=20build",=0A+=09=09=09=09=09=09=09= "ssl_min_protocol_version",=0A+=09=09=09=09=09=09=09= GetConfigOption("ssl_min_protocol_version",=0A+=09=09=09=09=09=09=09=09=09= =09=09false,=20false))));=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=0A+=09=09= if=20(ver=20>=200)=0A+=09=09=09desired_sslver.min=20=3D=20ver;=0A+=09}=0A= +=0A+=09if=20(ssl_max_protocol_version)=0A+=09{=0A+=09=09int=09=09=09ver=20= =3D=20ssl_protocol_version_to_nss(ssl_max_protocol_version,=0A+=09=09=09=09= =09=09=09=09=09=09=09=09=09=20=20"ssl_max_protocol_version");=0A+=0A+=09=09= if=20(ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09ereport(isServerStart=20= ?=20FATAL=20:=20LOG,=0A+=09=09=09=09=09(errmsg("\"%s\"=20setting=20= \"%s\"=20not=20supported=20by=20this=20build",=0A+=09=09=09=09=09=09=09= "ssl_max_protocol_version",=0A+=09=09=09=09=09=09=09= GetConfigOption("ssl_max_protocol_version",=0A+=09=09=09=09=09=09=09=09=09= =09=09false,=20false))));=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=09=09= if=20(ver=20>=200)=0A+=09=09=09desired_sslver.max=20=3D=20ver;=0A+=0A+=09= =09if=20(ver=20<=20desired_sslver.min)=0A+=09=09{=0A+=09=09=09= ereport(isServerStart=20?=20FATAL=20:=20LOG,=0A+=09=09=09=09=09= (errmsg("could=20not=20set=20SSL=20protocol=20version=20range"),=0A+=09=09= =09=09=09=20errdetail("\"%s\"=20cannot=20be=20higher=20than=20\"%s\"",=0A= +=09=09=09=09=09=09=09=20=20=20"ssl_min_protocol_version",=0A+=09=09=09=09= =09=09=09=20=20=20"ssl_max_protocol_version")));=0A+=09=09=09return=20= -1;=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Set=20the=20passphrase=20= callback=20which=20will=20be=20used=20both=20to=20obtain=20the=0A+=09=20= *=20passphrase=20from=20the=20user,=20as=20well=20as=20by=20NSS=20to=20= obtain=20the=20phrase=0A+=09=20*=20repeatedly.=0A+=09=20*/=0A+=09= ssl_is_server_start=20=3D=20isServerStart;=0A+=09(*nss_tls_init_hook)=20= (isServerStart);=0A+=0A+=09return=200;=0A+}=0A+=0A+int=0A= +be_tls_open_server(Port=20*port)=0A+{=0A+=09SECStatus=09status;=0A+=09= PRFileDesc=20*model;=0A+=09PRFileDesc=20*pr_fd;=0A+=09PRFileDesc=20= *layer;=0A+=09CERTCertificate=20*server_cert;=0A+=09SECKEYPrivateKey=20= *private_key;=0A+=09CERTSignedCrl=20*crl;=0A+=09SECItem=09=09crlname;=0A= +=09char=09=20=20=20*cert_database;=0A+=09NSSInitParameters=20params;=0A= +=0A+=09/*=0A+=09=20*=20The=20NSPR=20documentation=20states=20that=20= runtime=20initialization=20via=20PR_Init=0A+=09=20*=20is=20no=20longer=20= required,=20as=20the=20first=20caller=20into=20NSPR=20will=20perform=20= the=0A+=09=20*=20initialization=20implicitly.=20The=20documentation=20= doesn't=20however=20clarify=0A+=09=20*=20from=20which=20version=20this=20= is=20holds=20true,=20so=20let's=20perform=20the=20potentially=0A+=09=20*=20= superfluous=20initialization=20anyways=20to=20avoid=20crashing=20on=20= older=20versions=0A+=09=20*=20of=20NSPR,=20as=20there=20is=20no=20= difference=20in=20overhead.=20=20The=20NSS=20documentation=0A+=09=20*=20= still=20states=20that=20PR_Init=20must=20be=20called=20in=20some=20way=20= (implicitly=20or=0A+=09=20*=20explicitly).=0A+=09=20*=0A+=09=20*=20The=20= below=20parameters=20are=20what=20the=20implicit=20initialization=20= would've=20done=0A+=09=20*=20for=20us,=20and=20should=20work=20even=20= for=20older=20versions=20where=20it=20might=20not=20be=0A+=09=20*=20done=20= automatically.=20The=20last=20parameter,=20maxPTDs,=20is=20set=20to=20= various=0A+=09=20*=20values=20in=20other=20codebases,=20but=20has=20been=20= unused=20since=20NSPR=202.1=20which=20was=0A+=09=20*=20released=20= sometime=20in=201998.=20In=20current=20versions=20of=20NSPR=20all=20= parameters=0A+=09=20*=20are=20ignored.=0A+=09=20*/=0A+=09= PR_Init(PR_USER_THREAD,=20PR_PRIORITY_NORMAL,=200=20/*=20maxPTDs=20*/=20= );=0A+=0A+=09/*=0A+=09=20*=20The=20certificate=20path=20(configdir)=20= must=20contain=20a=20valid=20NSS=20database.=20If=0A+=09=20*=20the=20= certificate=20path=20isn't=20a=20valid=20directory,=20NSS=20will=20fall=20= back=20on=20the=0A+=09=20*=20system=20certificate=20database.=20If=20the=20= certificate=20path=20is=20a=20directory=20but=0A+=09=20*=20is=20empty=20= then=20the=20initialization=20will=20fail.=20On=20the=20client=20side=20= this=20can=0A+=09=20*=20be=20allowed=20for=20any=20sslmode=20but=20the=20= verify-xxx=20ones.=0A+=09=20*=20= https://bugzilla.redhat.com/show_bug.cgi?id=3D728562=20For=20the=20= server=20side=0A+=09=20*=20we=20won't=20allow=20this=20to=20fail=20= however,=20as=20we=20require=20the=20certificate=20and=0A+=09=20*=20key=20= to=20exist.=0A+=09=20*=0A+=09=20*=20The=20original=20design=20of=20NSS=20= was=20for=20a=20single=20application=20to=20use=20a=20single=0A+=09=20*=20= copy=20of=20it,=20initialized=20with=20NSS_Initialize()=20which=20isn't=20= returning=20any=0A+=09=20*=20handle=20with=20which=20to=20refer=20to=20= NSS.=20NSS=20initialization=20and=20shutdown=20are=0A+=09=20*=20global=20= for=20the=20application,=20so=20a=20shutdown=20in=20another=20NSS=20= enabled=0A+=09=20*=20library=20would=20cause=20NSS=20to=20be=20stopped=20= for=20libpq=20as=20well.=20=20The=20fix=20has=0A+=09=20*=20been=20to=20= introduce=20NSS_InitContext=20which=20returns=20a=20context=20handle=20= to=0A+=09=20*=20pass=20to=20NSS_ShutdownContext.=20=20NSS_InitContext=20= was=20introduced=20in=20NSS=0A+=09=20*=203.12,=20but=20the=20use=20of=20= it=20is=20not=20very=20well=20documented.=0A+=09=20*=20= https://bugzilla.redhat.com/show_bug.cgi?id=3D738456=0A+=09=20*=0A+=09=20= *=20The=20InitParameters=20struct=20passed=20can=20be=20used=20to=20= override=20internal=0A+=09=20*=20values=20in=20NSS,=20but=20the=20usage=20= is=20not=20documented=20at=20all.=20When=20using=0A+=09=20*=20NSS_Init=20= initializations,=20the=20values=20are=20instead=20set=20via=20= PK11_Configure=0A+=09=20*=20calls=20so=20the=20PK11_Configure=20= documentation=20can=20be=20used=20to=20glean=20some=0A+=09=20*=20details=20= on=20these.=0A+=09=20*=0A+=09=20*=20= https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/PKCS11/Modul= e_Specs=0A+=09=20*/=0A+=09memset(¶ms,=20'\0',=20sizeof(params));=0A+=09= params.length=20=3D=20sizeof(params);=0A+=0A+=09if=20(!ssl_database=20||=20= strlen(ssl_database)=20=3D=3D=200)=0A+=09=09ereport(FATAL,=0A+=09=09=09=09= (errmsg("no=20certificate=20database=20specified")));=0A+=0A+=09= cert_database=20=3D=20psprintf("sql:%s",=20ssl_database);=0A+=09= nss_context=20=3D=20NSS_InitContext(cert_database,=20"",=20"",=20"",=0A+=09= =09=09=09=09=09=09=09=20=20¶ms,=0A+=09=09=09=09=09=09=09=09=20=20= NSS_INIT_READONLY=20|=20NSS_INIT_PK11RELOAD);=0A+=09= pfree(cert_database);=0A+=0A+=09if=20(!nss_context)=0A+=09=09= ereport(FATAL,=0A+=09=09=09=09(errmsg("unable=20to=20read=20certificate=20= database=20\"%s\":=20%s",=0A+=09=09=09=09=09=09ssl_database,=20= pg_SSLerrmessage(PR_GetError()))));=0A+=0A+=09/*=0A+=09=20*=20Import=20= the=20already=20opened=20socket=20as=20we=20don't=20want=20to=20use=20= NSPR=20functions=0A+=09=20*=20for=20opening=20the=20network=20socket=20= due=20to=20how=20the=20PostgreSQL=20protocol=20works=0A+=09=20*=20with=20= TLS=20connections.=20This=20function=20is=20not=20part=20of=20the=20NSPR=20= public=20API,=0A+=09=20*=20see=20the=20comment=20at=20the=20top=20of=20= the=20file=20for=20the=20rationale=20of=20still=20using=0A+=09=20*=20it.=0A= +=09=20*/=0A+=09pr_fd=20=3D=20PR_ImportTCPSocket(port->sock);=0A+=09if=20= (!pr_fd)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09= (errmsg("unable=20to=20connect=20to=20socket")));=0A+=09=09return=20-1;=0A= +=09}=0A+=0A+=09/*=0A+=09=20*=20Most=20of=20the=20documentation=20= available,=20and=20implementations=20of,=20NSS/NSPR=0A+=09=20*=20use=20= the=20PR_NewTCPSocket()=20function=20here,=20which=20has=20the=20= drawback=20that=20it=0A+=09=20*=20can=20only=20create=20IPv4=20sockets.=20= Instead=20use=20PR_OpenTCPSocket()=20which=0A+=09=20*=20copes=20with=20= IPv6=20as=20well.=0A+=09=20*=0A+=09=20*=20We=20use=20a=20model=20= filedescriptor=20here=20which=20is=20a=20construct=20in=20NSPR/NSS=20in=0A= +=09=20*=20order=20to=20create=20a=20configuration=20template=20for=20= sockets=20which=20can=20then=20be=0A+=09=20*=20applied=20to=20new=20= sockets=20created.=20This=20makes=20more=20sense=20in=20a=20server=20= which=0A+=09=20*=20accepts=20multiple=20connections=20and=20want=20to=20= perform=20the=20boilerplate=20just=0A+=09=20*=20once,=20but=20it=20does=20= provide=20a=20nice=20abstraction=20here=20as=20well=20in=20that=20we=0A+=09= =20*=20can=20error=20out=20early=20without=20having=20performed=20any=20= operation=20on=20the=20real=0A+=09=20*=20socket.=0A+=09=20*/=0A+=09model=20= =3D=20PR_OpenTCPSocket(port->laddr.addr.ss_family);=0A+=09if=20(!model)=0A= +=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= open=20socket")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20= Convert=20the=20NSPR=20socket=20to=20an=20SSL=20socket.=20Ensuring=20the=20= success=20of=20this=0A+=09=20*=20operation=20is=20critical=20as=20NSS=20= SSL_*=20functions=20may=20return=20SECSuccess=20on=0A+=09=20*=20the=20= socket=20even=20though=20SSL=20hasn't=20been=20enabled,=20which=20= introduce=20a=20risk=0A+=09=20*=20of=20silent=20downgrades.=0A+=09=20*/=0A= +=09model=20=3D=20SSL_ImportFD(NULL,=20model);=0A+=09if=20(!model)=0A+=09= {=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= enable=20TLS=20on=20socket")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09= /*=0A+=09=20*=20Configure=20basic=20settings=20for=20the=20connection=20= over=20the=20SSL=20socket=20in=0A+=09=20*=20order=20to=20set=20it=20up=20= as=20a=20server.=0A+=09=20*/=0A+=09if=20(SSL_OptionSet(model,=20= SSL_SECURITY,=20PR_TRUE)=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09= ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20configure=20TLS=20= connection")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09if=20= (SSL_OptionSet(model,=20SSL_HANDSHAKE_AS_SERVER,=20PR_TRUE)=20!=3D=20= SECSuccess=20||=0A+=09=09SSL_OptionSet(model,=20SSL_HANDSHAKE_AS_CLIENT,=20= PR_FALSE)=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09= =09=09=09(errmsg("unable=20to=20configure=20TLS=20connection=20as=20= server")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20= SSLv2=20is=20disabled=20by=20default,=20and=20SSLv3=20will=20be=20= excluded=20from=20the=20range=0A+=09=20*=20of=20allowed=20protocols=20= further=20down.=20Since=20we=20really=20don't=20want=20these=20to=0A+=09=20= *=20ever=20be=20enabled,=20let's=20use=20belts=20and=20suspenders=20and=20= explicitly=20turn=0A+=09=20*=20them=20off=20as=20well.=0A+=09=20*/=0A+=09= SSL_OptionSet(model,=20SSL_ENABLE_SSL2,=20PR_FALSE);=0A+=09= SSL_OptionSet(model,=20SSL_ENABLE_SSL3,=20PR_FALSE);=0A+=0A+#ifdef=20= SSL_CBC_RANDOM_IV=0A+=0A+=09/*=0A+=09=20*=20Enable=20protection=20= against=20the=20BEAST=20attack=20in=20case=20the=20NSS=20server=20has=0A= +=09=20*=20support=20for=20that.=20While=20SSLv3=20is=20disabled,=20we=20= may=20still=20allow=20TLSv1=0A+=09=20*=20which=20is=20affected.=20The=20= option=20isn't=20documented=20as=20an=20SSL=20option,=20but=20as=0A+=09=20= *=20an=20NSS=20environment=20variable.=0A+=09=20*/=0A+=09= SSL_OptionSet(model,=20SSL_CBC_RANDOM_IV,=20PR_TRUE);=0A+#endif=0A+=0A+=09= /*=0A+=09=20*=20Configure=20the=20allowed=20ciphers.=20If=20there=20are=20= no=20user=20preferred=20suites,=0A+=09=20*=20set=20the=20domestic=20= policy.=0A+=09=20*=0A+=09=20*=20Historically=20there=20were=20different=20= cipher=20policies=20based=20on=20export=20(and=0A+=09=20*=20import)=20= restrictions:=20Domestic,=20Export=20and=20France.=20These=20are=20since=20= long=0A+=09=20*=20removed=20with=20all=20ciphers=20being=20enabled=20by=20= default.=20Due=20to=20backwards=0A+=09=20*=20compatibility,=20the=20old=20= API=20is=20still=20used=20even=20though=20all=20three=20policies=0A+=09=20= *=20now=20do=20the=20same=20thing.=0A+=09=20*=0A+=09=20*=20If=20= SSLCipherSuites=20define=20a=20policy=20of=20the=20user,=20we=20set=20= that=20rather=20than=0A+=09=20*=20enabling=20all=20ciphers=20via=20= NSS_SetDomesticPolicy.=0A+=09=20*=0A+=09=20*=20TODO:=20while=20this=20= code=20works,=20the=20set=20of=20ciphers=20which=20can=20be=20set=20and=0A= +=09=20*=20still=20end=20up=20with=20a=20working=20socket=20is=20= woefully=20underdocumented=20for=0A+=09=20*=20anything=20more=20recent=20= than=20SSLv3=20(the=20code=20for=20TLS=20actually=20calls=20ssl3=0A+=09=20= *=20functions=20under=20the=20hood=20for=20SSL_CipherPrefSet),=20so=20= it's=20unclear=20if=0A+=09=20*=20this=20is=20helpful=20or=20not.=20Using=20= the=20policies=20works,=20but=20may=20be=20too=0A+=09=20*=20coarsely=20= grained.=0A+=09=20*=0A+=09=20*=20Another=20TODO:=20The=20= SSL_ImplementedCiphers=20table=20returned=20with=20calling=0A+=09=20*=20= SSL_GetImplementedCiphers=20is=20sorted=20in=20server=20preference=20= order.=20Sorting=0A+=09=20*=20SSLCipherSuites=20according=20to=20the=20= order=20of=20the=20ciphers=20therein=20could=20be=0A+=09=20*=20a=20way=20= to=20implement=20ssl_prefer_server_ciphers=20-=20if=20we=20at=20all=20= want=20to=20use=0A+=09=20*=20cipher=20selection=20for=20NSS=20like=20how=20= we=20do=20it=20for=20OpenSSL=20that=20is.=0A+=09=20*/=0A+=0A+=09/*=0A+=09= =20*=20If=20no=20ciphers=20are=20specified,=20enable=20them=20all.=0A+=09= =20*/=0A+=09if=20(!SSLCipherSuites=20||=20strlen(SSLCipherSuites)=20=3D=3D= =200)=0A+=09{=0A+=09=09status=20=3D=20NSS_SetDomesticPolicy();=0A+=09=09= if=20(status=20!=3D=20SECSuccess)=0A+=09=09{=0A+=09=09=09= ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("unable=20to=20set=20cipher=20= policy:=20%s",=0A+=09=09=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09=09=09return=20-1;=0A+=09=09}=0A= +=09}=0A+=09else=0A+=09{=0A+=09=09char=09=20=20=20*ciphers,=0A+=09=09=09=09= =20=20=20*c;=0A+=0A+=09=09char=09=20=20=20*sep=20=3D=20":;,=20";=0A+=09=09= PRUint16=09ciphercode;=0A+=09=09const=09=09PRUint16=20*nss_ciphers;=0A+=0A= +=09=09/*=0A+=09=09=20*=20If=20the=20user=20has=20specified=20a=20set=20= of=20preferred=20cipher=20suites=20we=20start=0A+=09=09=20*=20by=20= turning=20off=20all=20the=20existing=20suites=20to=20avoid=20the=20risk=20= of=20down-=0A+=09=09=20*=20grades=20to=20a=20weaker=20cipher=20than=20= expected.=0A+=09=09=20*/=0A+=09=09nss_ciphers=20=3D=20= SSL_GetImplementedCiphers();=0A+=09=09for=20(int=20i=20=3D=200;=20i=20<=20= SSL_GetNumImplementedCiphers();=20i++)=0A+=09=09=09= SSL_CipherPrefSet(model,=20nss_ciphers[i],=20PR_FALSE);=0A+=0A+=09=09= ciphers=20=3D=20pstrdup(SSLCipherSuites);=0A+=0A+=09=09for=20(c=20=3D=20= strtok(ciphers,=20sep);=20c;=20c=20=3D=20strtok(NULL,=20sep))=0A+=09=09{=0A= +=09=09=09if=20(!pg_find_cipher(c,=20&ciphercode))=0A+=09=09=09{=0A+=09=09= =09=09status=20=3D=20SSL_CipherPrefSet(model,=20ciphercode,=20PR_TRUE);=0A= +=09=09=09=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09=09=09{=0A+=09=09= =09=09=09ereport(COMMERROR,=0A+=09=09=09=09=09=09=09(errmsg("invalid=20= cipher-suite=20specified:=20%s",=20c)));=0A+=09=09=09=09=09return=20-1;=0A= +=09=09=09=09}=0A+=09=09=09}=0A+=09=09}=0A+=0A+=09=09pfree(ciphers);=0A+=09= }=0A+=0A+=09if=20(SSL_VersionRangeSet(model,=20&desired_sslver)=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09= (errmsg("unable=20to=20set=20requested=20SSL=20protocol=20version=20= range")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Set=20= up=20the=20custom=20IO=20layer.=0A+=09=20*/=0A+=09layer=20=3D=20= init_iolayer(port);=0A+=09if=20(!layer)=0A+=09=09return=20-1;=0A+=0A+=09= if=20(PR_PushIOLayer(pr_fd,=20PR_TOP_IO_LAYER,=20layer)=20!=3D=20= PR_SUCCESS)=0A+=09{=0A+=09=09PR_Close(layer);=0A+=09=09= ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20push=20IO=20= layer")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A+=09server_cert=20=3D=20= PK11_FindCertFromNickname(ssl_cert_file,=20(void=20*)=20port);=0A+=09if=20= (!server_cert)=0A+=09{=0A+=09=09if=20(dummy_ssl_passwd_cb_called)=0A+=09=09= {=0A+=09=09=09ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("unable=20to=20= load=20certificate=20for=20\"%s\":=20%s",=0A+=09=09=09=09=09=09=09= ssl_cert_file,=20pg_SSLerrmessage(PR_GetError())),=0A+=09=09=09=09=09=20= errhint("The=20certificate=20requires=20a=20password.")));=0A+=09=09=09= return=20-1;=0A+=09=09}=0A+=09=09else=0A+=09=09{=0A+=09=09=09= ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("unable=20to=20find=20= certificate=20for=20\"%s\":=20%s",=0A+=09=09=09=09=09=09=09= ssl_cert_file,=20pg_SSLerrmessage(PR_GetError()))));=0A+=09=09=09return=20= -1;=0A+=09=09}=0A+=09}=0A+=0A+=09private_key=20=3D=20= PK11_FindKeyByAnyCert(server_cert,=20(void=20*)=20port);=0A+=09if=20= (!private_key)=0A+=09{=0A+=09=09if=20(dummy_ssl_passwd_cb_called)=0A+=09=09= {=0A+=09=09=09ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("unable=20to=20= load=20private=20key=20for=20\"%s\":=20%s",=0A+=09=09=09=09=09=09=09= ssl_cert_file,=20pg_SSLerrmessage(PR_GetError())),=0A+=09=09=09=09=09=20= errhint("The=20private=20key=20requires=20a=20password.")));=0A+=09=09=09= return=20-1;=0A+=09=09}=0A+=09=09else=0A+=09=09{=0A+=09=09=09= ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("unable=20to=20find=20= private=20key=20for=20\"%s\":=20%s",=0A+=09=09=09=09=09=09=09= ssl_cert_file,=20pg_SSLerrmessage(PR_GetError()))));=0A+=09=09=09return=20= -1;=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20NSS=20doesn't=20use=20= CRL=20files=20on=20disk,=20so=20we=20use=20the=20ssl_crl_file=20guc=20to=0A= +=09=20*=20contain=20the=20CRL=20nickname=20for=20the=20current=20server=20= certificate=20in=20the=20NSS=0A+=09=20*=20certificate=20database.=20The=20= main=20difference=20from=20the=20OpenSSL=20backend=20is=0A+=09=20*=20= that=20NSS=20will=20use=20the=20CRL=20regardless,=20but=20being=20able=20= to=20make=20sure=20the=0A+=09=20*=20CRL=20is=20loaded=20seems=20like=20a=20= good=20feature.=0A+=09=20*/=0A+=09if=20(ssl_crl_file[0])=0A+=09{=0A+=09=09= SECITEM_CopyItem(NULL,=20&crlname,=20&server_cert->derSubject);=0A+=09=09= crl=20=3D=20SEC_FindCrlByName(CERT_GetDefaultCertDB(),=20&crlname,=20= SEC_CRL_TYPE);=0A+=09=09if=20(!crl)=0A+=09=09{=0A+=09=09=09= ereport(COMMERROR,=0A+=09=09=09=09=09(errmsg("specified=20CRL=20not=20= found=20in=20database")));=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=09=09= SEC_DestroyCrl(crl);=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Finally=20we=20= must=20configure=20the=20socket=20for=20being=20a=20server=20by=20= setting=20the=0A+=09=20*=20certificate=20and=20key.=20The=20NULL=20= parameter=20is=20an=20SSLExtraServerCertData=0A+=09=20*=20pointer=20with=20= the=20final=20parameter=20being=20the=20size=20of=20the=20extra=20server=0A= +=09=20*=20cert=20data=20structure=20pointed=20to.=20This=20is=20= typically=20only=20used=20for=0A+=09=20*=20credential=20delegation.=0A+=09= =20*/=0A+=09status=20=3D=20SSL_ConfigServerCert(model,=20server_cert,=20= private_key,=20NULL,=200);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09= {=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20= configure=20server=20for=20TLS=20server=20connections:=20%s",=0A+=09=09=09= =09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20-1;=0A+=09= }=0A+=0A+=09ssl_loaded_verify_locations=20=3D=20true;=0A+=0A+=09/*=0A+=09= =20*=20At=20this=20point,=20we=20no=20longer=20have=20use=20for=20the=20= certificate=20and=20private=0A+=09=20*=20key=20as=20they=20have=20been=20= copied=20into=20the=20context=20by=20NSS.=20Destroy=20our=0A+=09=20*=20= copies=20explicitly=20to=20clean=20out=20the=20memory=20as=20best=20we=20= can.=0A+=09=20*/=0A+=09CERT_DestroyCertificate(server_cert);=0A+=09= SECKEY_DestroyPrivateKey(private_key);=0A+=0A+=09/*=20Set=20up=20= certificate=20authentication=20callback=20*/=0A+=09status=20=3D=20= SSL_AuthCertificateHook(model,=20pg_cert_auth_handler,=20(void=20*)=20= port);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09= ereport(COMMERROR,=0A+=09=09=09=09(errmsg("unable=20to=20install=20= authcert=20hook:=20%s",=0A+=09=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20-1;=0A+=09}=0A+=09= SSL_BadCertHook(model,=20pg_bad_cert_handler,=20(void=20*)=20port);=0A+=09= SSL_OptionSet(model,=20SSL_REQUEST_CERTIFICATE,=20PR_TRUE);=0A+=09= SSL_OptionSet(model,=20SSL_REQUIRE_CERTIFICATE,=20PR_FALSE);=0A+=0A+=09= port->pr_fd=20=3D=20SSL_ImportFD(model,=20pr_fd);=0A+=09if=20= (!port->pr_fd)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09= (errmsg("unable=20to=20initialize")));=0A+=09=09return=20-1;=0A+=09}=0A+=0A= +=09PR_Close(model);=0A+=0A+=09/*=0A+=09=20*=20Force=20a=20handshake=20= on=20the=20next=20I/O=20request,=20the=20second=20parameter=20means=0A+=09= =20*=20that=20we=20are=20a=20server,=20PR_FALSE=20would=20indicate=20= being=20a=20client.=20NSPR=0A+=09=20*=20requires=20us=20to=20call=20= SSL_ResetHandshake=20since=20we=20imported=20an=20already=0A+=09=20*=20= established=20socket.=0A+=09=20*/=0A+=09status=20=3D=20= SSL_ResetHandshake(port->pr_fd,=20PR_TRUE);=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09= (errmsg("unable=20to=20initiate=20handshake:=20%s",=0A+=09=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20-1;=0A+=09}=0A+=09= status=20=3D=20SSL_ForceHandshake(port->pr_fd);=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09ereport(COMMERROR,=0A+=09=09=09=09= (errmsg("unable=20to=20handshake:=20%s",=0A+=09=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09=09return=20-1;=0A+=09}=0A+=0A= +=09port->ssl_in_use=20=3D=20true;=0A+=0A+=09/*=20Register=20out=20= shutdown=20callback=20*/=0A+=09NSS_RegisterShutdown(pg_SSLShutdownFunc,=20= port);=0A+=0A+=09return=200;=0A+}=0A+=0A+ssize_t=0A+be_tls_read(Port=20= *port,=20void=20*ptr,=20size_t=20len,=20int=20*waitfor)=0A+{=0A+=09= ssize_t=09=09n_read;=0A+=09PRErrorCode=20err;=0A+=0A+=09n_read=20=3D=20= PR_Read(port->pr_fd,=20ptr,=20len);=0A+=0A+=09if=20(n_read=20<=200)=0A+=09= {=0A+=09=09err=20=3D=20PR_GetError();=0A+=0A+=09=09if=20(err=20=3D=3D=20= PR_WOULD_BLOCK_ERROR)=0A+=09=09{=0A+=09=09=09*waitfor=20=3D=20= WL_SOCKET_READABLE;=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_read;=0A+}=0A+=0A+ssize_t=0A+be_tls_write(Port=20*port,=20= void=20*ptr,=20size_t=20len,=20int=20*waitfor)=0A+{=0A+=09ssize_t=09=09= n_write;=0A+=09PRErrorCode=20err;=0A+=09PRIntn=09=09flags=20=3D=200;=0A+=0A= +=09/*=0A+=09=20*=20The=20flags=20parameter=20to=20PR_Send=20is=20no=20= longer=20used=20and=20is,=20according=20to=0A+=09=20*=20the=20= documentation,=20required=20to=20be=20zero.=0A+=09=20*/=0A+=09n_write=20= =3D=20PR_Send(port->pr_fd,=20ptr,=20len,=20flags,=20= PR_INTERVAL_NO_WAIT);=0A+=0A+=09if=20(n_write=20<=200)=0A+=09{=0A+=09=09= err=20=3D=20PR_GetError();=0A+=0A+=09=09if=20(err=20=3D=3D=20= PR_WOULD_BLOCK_ERROR)=0A+=09=09{=0A+=09=09=09*waitfor=20=3D=20= WL_SOCKET_WRITEABLE;=0A+=09=09=09errno=20=3D=20EWOULDBLOCK;=0A+=09=09}=0A= +=09=09else=0A+=09=09=09errno=20=3D=20ECONNRESET;=0A+=09}=0A+=0A+=09= return=20n_write;=0A+}=0A+=0A+void=0A+be_tls_close(Port=20*port)=0A+{=0A= +=09if=20(!port)=0A+=09=09return;=0A+=0A+=09if=20(port->peer_cn)=0A+=09{=0A= +=09=09SSL_InvalidateSession(port->pr_fd);=0A+=09=09= pfree(port->peer_cn);=0A+=09=09port->peer_cn=20=3D=20NULL;=0A+=09}=0A+=0A= +=09PR_Close(port->pr_fd);=0A+=09port->pr_fd=20=3D=20NULL;=0A+=09= port->ssl_in_use=20=3D=20false;=0A+=0A+=09if=20(nss_context)=0A+=09{=0A+=09= =09NSS_ShutdownContext(nss_context);=0A+=09=09nss_context=20=3D=20NULL;=0A= +=09}=0A+}=0A+=0A+void=0A+be_tls_destroy(void)=0A+{=0A+=09/*=0A+=09=20*=20= It=20reads=20a=20bit=20odd=20to=20clear=20a=20session=20cache=20when=20= we=20are=20destroying=20the=0A+=09=20*=20context=20altogether,=20but=20= if=20the=20session=20cache=20isn't=20cleared=20before=0A+=09=20*=20= shutting=20down=20the=20context=20it=20will=20fail=20with=20= SEC_ERROR_BUSY.=0A+=09=20*/=0A+=09SSL_ClearSessionCache();=0A+}=0A+=0A= +int=0A+be_tls_get_cipher_bits(Port=20*port)=0A+{=0A+=09SECStatus=09= status;=0A+=09SSLChannelInfo=20channel;=0A+=09SSLCipherSuiteInfo=20= suite;=0A+=0A+=09status=20=3D=20SSL_GetChannelInfo(port->pr_fd,=20= &channel,=20sizeof(channel));=0A+=09if=20(status=20!=3D=20SECSuccess)=0A= +=09=09goto=20error;=0A+=0A+=09status=20=3D=20= SSL_GetCipherSuiteInfo(channel.cipherSuite,=20&suite,=20sizeof(suite));=0A= +=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09goto=20error;=0A+=0A+=09= return=20suite.effectiveKeyBits;=0A+=0A+error:=0A+=09ereport(WARNING,=0A= +=09=09=09(errmsg("unable=20to=20extract=20TLS=20session=20information:=20= %s",=0A+=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09return=20= 0;=0A+}=0A+=0A+/*=0A+=20*=20be_tls_get_compression=0A+=20*=0A+=20*=20NSS=20= disabled=20support=20for=20TLS=20compression=20in=20version=203.33=20and=20= removed=20the=0A+=20*=20code=20in=20a=20subsequent=20release.=20The=20= API=20for=20retrieving=20information=20about=0A+=20*=20compression=20as=20= well=20as=20enabling=20it=20is=20kept=20for=20backwards=20compatibility,=20= but=0A+=20*=20we=20don't=20need=20to=20consult=20it=20since=20it=20was=20= only=20available=20for=20SSLv3=20which=20we=0A+=20*=20don't=20support.=0A= +=20*=0A+=20*=20https://bugzilla.mozilla.org/show_bug.cgi?id=3D1409587=0A= +=20*/=0A+bool=0A+be_tls_get_compression(Port=20*port)=0A+{=0A+=09return=20= false;=0A+}=0A+=0A+/*=0A+=20*=20be_tls_get_version=0A+=20*=0A+=20*=20= Returns=20the=20protocol=20version=20used=20for=20the=20current=20= connection,=20or=20NULL=20in=0A+=20*=20case=20of=20errors.=0A+=20*/=0A= +const=20char=20*=0A+be_tls_get_version(Port=20*port)=0A+{=0A+=09= SECStatus=09status;=0A+=09SSLChannelInfo=20channel;=0A+=0A+=09status=20=3D= =20SSL_GetChannelInfo(port->pr_fd,=20&channel,=20sizeof(channel));=0A+=09= if=20(status=20!=3D=20SECSuccess)=0A+=09{=0A+=09=09ereport(WARNING,=0A+=09= =09=09=09(errmsg("unable=20to=20extract=20TLS=20session=20information:=20= %s",=0A+=09=09=09=09=09=09pg_SSLerrmessage(PR_GetError()))));=0A+=09=09= return=20NULL;=0A+=09}=0A+=0A+=09return=20= ssl_protocol_version_to_string(channel.protocolVersion);=0A+}=0A+=0A= +const=20char=20*=0A+be_tls_get_cipher(Port=20*port)=0A+{=0A+=09= SECStatus=09status;=0A+=09SSLChannelInfo=20channel;=0A+=09= SSLCipherSuiteInfo=20suite;=0A+=0A+=09status=20=3D=20= SSL_GetChannelInfo(port->pr_fd,=20&channel,=20sizeof(channel));=0A+=09if=20= (status=20!=3D=20SECSuccess)=0A+=09=09goto=20error;=0A+=0A+=09status=20=3D= =20SSL_GetCipherSuiteInfo(channel.cipherSuite,=20&suite,=20= sizeof(suite));=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09goto=20= error;=0A+=0A+=09return=20suite.cipherSuiteName;=0A+=0A+error:=0A+=09= ereport(WARNING,=0A+=09=09=09(errmsg("unable=20to=20extract=20TLS=20= session=20information:=20%s",=0A+=09=09=09=09=09= pg_SSLerrmessage(PR_GetError()))));=0A+=09return=20NULL;=0A+}=0A+=0A= +void=0A+be_tls_get_peer_subject_name(Port=20*port,=20char=20*ptr,=20= size_t=20len)=0A+{=0A+=09CERTCertificate=20*certificate;=0A+=0A+=09= certificate=20=3D=20SSL_PeerCertificate(port->pr_fd);=0A+=09if=20= (certificate)=0A+=09=09strlcpy(ptr,=20= CERT_NameToAscii(&certificate->subject),=20len);=0A+=09else=0A+=09=09= ptr[0]=20=3D=20'\0';=0A+}=0A+=0A+void=0A= +be_tls_get_peer_issuer_name(Port=20*port,=20char=20*ptr,=20size_t=20= len)=0A+{=0A+=09CERTCertificate=20*certificate;=0A+=0A+=09certificate=20= =3D=20SSL_PeerCertificate(port->pr_fd);=0A+=09if=20(certificate)=0A+=09=09= strlcpy(ptr,=20CERT_NameToAscii(&certificate->issuer),=20len);=0A+=09= else=0A+=09=09ptr[0]=20=3D=20'\0';=0A+}=0A+=0A+void=0A= +be_tls_get_peer_serial(Port=20*port,=20char=20*ptr,=20size_t=20len)=0A= +{=0A+=09CERTCertificate=20*certificate;=0A+=0A+=09certificate=20=3D=20= SSL_PeerCertificate(port->pr_fd);=0A+=09if=20(certificate)=0A+=09=09= snprintf(ptr,=20len,=20"%li",=20= DER_GetInteger(&(certificate->serialNumber)));=0A+=09else=0A+=09=09= ptr[0]=20=3D=20'\0';=0A+}=0A+=0A+char=20*=0A= +be_tls_get_certificate_hash(Port=20*port,=20size_t=20*len)=0A+{=0A+=09= CERTCertificate=20*certificate;=0A+=09SECOidTag=09signature_tag;=0A+=09= SECOidTag=09digest_alg;=0A+=09int=09=09=09digest_len;=0A+=09SECStatus=09= status;=0A+=09PLArenaPool=20*arena=20=3D=20NULL;=0A+=09SECItem=09=09= digest;=0A+=09char=09=20=20=20*ret;=0A+=09PK11Context=20*ctx=20=3D=20= NULL;=0A+=09unsigned=20int=20outlen;=0A+=0A+=09*len=20=3D=200;=0A+=09= certificate=20=3D=20SSL_LocalCertificate(port->pr_fd);=0A+=09if=20= (!certificate)=0A+=09=09return=20NULL;=0A+=0A+=09signature_tag=20=3D=20= SECOID_GetAlgorithmTag(&certificate->signature);=0A+=09if=20= (!pg_find_signature_algorithm(signature_tag,=20&digest_alg,=20= &digest_len))=0A+=09=09elog(ERROR,=20"could=20not=20find=20digest=20for=20= OID=20'%s'",=0A+=09=09=09=20= SECOID_FindOIDTagDescription(signature_tag));=0A+=0A+=09/*=0A+=09=20*=20= The=20TLS=20server's=20certificate=20bytes=20need=20to=20be=20hashed=20= with=20SHA-256=20if=0A+=09=20*=20its=20signature=20algorithm=20is=20MD5=20= or=20SHA-1=20as=20per=20RFC=205929=0A+=09=20*=20= (https://tools.ietf.org/html/rfc5929#section-4.1).=20=20If=20something=20= else=0A+=09=20*=20is=20used,=20the=20same=20hash=20as=20the=20signature=20= algorithm=20is=20used.=0A+=09=20*/=0A+=09if=20(digest_alg=20=3D=3D=20= SEC_OID_SHA1=20||=20digest_alg=20=3D=3D=20SEC_OID_MD5)=0A+=09{=0A+=09=09= digest_alg=20=3D=20SEC_OID_SHA256;=0A+=09=09digest_len=20=3D=20= SHA256_LENGTH;=0A+=09}=0A+=0A+=09ctx=20=3D=20= PK11_CreateDigestContext(digest_alg);=0A+=09if=20(!ctx)=0A+=09=09= elog(ERROR,=20"out=20of=20memory");=0A+=0A+=09arena=20=3D=20= PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);=0A+=09digest.data=20=3D=20= PORT_ArenaZAlloc(arena,=20sizeof(unsigned=20char)=20*=20digest_len);=0A+=09= digest.len=20=3D=20digest_len;=0A+=0A+=09status=20=3D=20SECSuccess;=0A+=09= status=20|=3D=20PK11_DigestBegin(ctx);=0A+=09status=20|=3D=20= PK11_DigestOp(ctx,=20certificate->derCert.data,=20= certificate->derCert.len);=0A+=09status=20|=3D=20PK11_DigestFinal(ctx,=20= digest.data,=20&outlen,=20digest_len);=0A+=0A+=09if=20(status=20!=3D=20= SECSuccess)=0A+=09{=0A+=09=09PORT_FreeArena(arena,=20PR_TRUE);=0A+=09=09= PK11_DestroyContext(ctx,=20PR_TRUE);=0A+=09=09elog(ERROR,=20"could=20not=20= generate=20server=20certificate=20hash");=0A+=09}=0A+=0A+=09ret=20=3D=20= palloc(digest.len);=0A+=09memcpy(ret,=20digest.data,=20digest.len);=0A+=09= *len=20=3D=20digest_len;=0A+=0A+=09PORT_FreeArena(arena,=20PR_TRUE);=0A+=09= PK11_DestroyContext(ctx,=20PR_TRUE);=0A+=0A+=09return=20ret;=0A+}=0A+=0A= +/*=20------------------------------------------------------------=20*/=0A= +/*=09=09=09=09=09=09Internal=20functions=09=09=09=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +/*=0A+=20*=20default_nss_tls_init=0A+=20*=0A+=20*=20The=20default=20TLS=20= init=20hook=20function=20which=20users=20can=20override=20for=20= installing=0A+=20*=20their=20own=20passphrase=20callbacks=20and=20= similar=20actions.=20In=20case=20no=20callback=20has=0A+=20*=20been=20= configured,=20or=20the=20callback=20isn't=20reload=20capable=20during=20= a=20server=0A+=20*=20reload,=20the=20dummy=20callback=20will=20be=20= installed.=0A+=20*=0A+=20*=20The=20private=20data=20for=20the=20callback=20= is=20set=20differently=20depending=20on=20how=20it's=0A+=20*=20invoked.=20= For=20calls=20which=20may=20invoke=20the=20callback=20deeper=20in=20the=20= callstack=0A+=20*=20the=20private=20data=20is=20set=20with=20= SSL_SetPKCS11PinArg.=20When=20the=20call=20is=20directly=0A+=20*=20= invoking=20the=20callback,=20like=20PK11_FindCertFromNickname,=20then=20= the=20private=0A+=20*=20data=20is=20passed=20as=20a=20parameter.=20= Setting=20the=20data=20with=20SSL_SetPKCS11PinArg=20is=0A+=20*=20thus=20= not=20required=20but=20good=20practice.=0A+=20*=0A+=20*=20NSS=20doesn't=20= provide=20a=20default=20callback=20like=20OpenSSL=20does,=20but=20a=20= callback=20is=0A+=20*=20required=20to=20be=20set.=20=20The=20password=20= callback=20can=20be=20installed=20at=20any=20time,=20but=0A+=20*=20= setting=20the=20private=20data=20with=20SSL_SetPKCS11PinArg=20requires=20= a=20PR=20Filedesc.=0A+=20*/=0A+static=20void=0A= +default_nss_tls_init(bool=20isServerStart)=0A+{=0A+=09/*=0A+=09=20*=20= No=20user-defined=20callback=20has=20been=20configured,=20install=20the=20= dummy=20call-=0A+=09=20*=20back=20since=20we=20must=20set=20something.=0A= +=09=20*/=0A+=09if=20(!ssl_passphrase_command[0])=0A+=09=09= PK11_SetPasswordFunc(dummy_ssl_passphrase_cb);=0A+=09else=0A+=09{=0A+=09=09= /*=0A+=09=09=20*=20There=20is=20a=20user-defined=20callback,=20set=20it=20= unless=20we=20are=20in=20a=20restart=0A+=09=09=20*=20and=20cannot=20= handle=20restarts=20due=20to=20an=20interactive=20callback.=0A+=09=09=20= */=0A+=09=09if=20(isServerStart)=0A+=09=09=09= PK11_SetPasswordFunc(external_ssl_passphrase_cb);=0A+=09=09else=0A+=09=09= {=0A+=09=09=09if=20(ssl_passphrase_command_supports_reload)=0A+=09=09=09=09= PK11_SetPasswordFunc(external_ssl_passphrase_cb);=0A+=09=09=09else=0A+=09= =09=09=09PK11_SetPasswordFunc(dummy_ssl_passphrase_cb);=0A+=09=09}=0A+=09= }=0A+}=0A+=0A+/*=0A+=20*=20external_ssl_passphrase_cb=0A+=20*=0A+=20*=20= Runs=20the=20callback=20configured=20by=20ssl_passphrase_command=20and=20= returns=20the=0A+=20*=20captured=20password=20back=20to=20NSS.=0A+=20*/=0A= +static=20char=20*=0A+external_ssl_passphrase_cb(PK11SlotInfo=20*slot,=20= PRBool=20retry,=20void=20*arg)=0A+{=0A+=09/*=0A+=09=20*=20NSS=20use=20a=20= hardcoded=20256=20byte=20buffer=20for=20reading=20the=20password=20so=20= set=20the=0A+=09=20*=20same=20limit=20for=20our=20callback=20buffer.=0A+=09= =20*/=0A+=09char=09=09buf[256];=0A+=09int=09=09=09len;=0A+=09char=09=20=20= =20*password=20=3D=20NULL;=0A+=09char=09=20=20=20*prompt;=0A+=0A+=09/*=0A= +=09=20*=20Since=20there=20is=20no=20password=20callback=20in=20NSS=20= when=20the=20server=20starts=20up,=0A+=09=20*=20it=20makes=20little=20= sense=20to=20create=20an=20interactive=20callback.=20Thus,=20if=20this=0A= +=09=20*=20is=20a=20retry=20attempt=20then=20give=20up=20immediately.=0A= +=09=20*/=0A+=09if=20(retry)=0A+=09=09return=20NULL;=0A+=0A+=09/*=0A+=09=20= *=20Construct=20the=20same=20prompt=20that=20NSS=20uses=20internally=20= even=20though=20it=20is=0A+=09=20*=20unlikely=20to=20serve=20much=20= purpose,=20but=20we=20must=20set=20a=20prompt=20so=20we=20might=20as=0A+=09= =20*=20well=20do=20it=20right.=0A+=09=20*/=0A+=09prompt=20=3D=20= psprintf("Enter=20Password=20or=20Pin=20for=20\"%s\":",=0A+=09=09=09=09=09= =20=20PK11_GetTokenName(slot));=0A+=0A+=09len=20=3D=20= run_ssl_passphrase_command(prompt,=20ssl_is_server_start,=20buf,=20= sizeof(buf));=0A+=09pfree(prompt);=0A+=0A+=09if=20(!len)=0A+=09=09return=20= NULL;=0A+=0A+=09/*=0A+=09=20*=20At=20least=20one=20byte=20with=20= password=20content=20was=20returned,=20and=20NSS=20requires=0A+=09=20*=20= that=20we=20return=20it=20allocated=20in=20NSS=20controlled=20memory.=20= If=20we=20fail=20to=0A+=09=20*=20allocate=20then=20abort=20without=20= passing=20back=20NULL=20and=20bubble=20up=20the=20error=0A+=09=20*=20on=20= the=20PG=20side.=0A+=09=20*/=0A+=09password=20=3D=20(char=20*)=20= PR_Malloc(len=20+=201);=0A+=09if=20(!password)=0A+=09{=0A+=09=09= explicit_bzero(buf,=20sizeof(buf));=0A+=09=09ereport(ERROR,=0A+=09=09=09=09= (errcode(ERRCODE_OUT_OF_MEMORY),=0A+=09=09=09=09=20errmsg("out=20of=20= memory")));=0A+=09}=0A+=09strlcpy(password,=20buf,=20sizeof(password));=0A= +=09explicit_bzero(buf,=20sizeof(buf));=0A+=0A+=09return=20password;=0A= +}=0A+=0A+/*=0A+=20*=20dummy_ssl_passphrase_cb=0A+=20*=0A+=20*=20Return=20= unsuccessful=20if=20we=20are=20asked=20to=20provide=20the=20passphrase=20= for=20a=20cert=20or=0A+=20*=20key,=20without=20having=20a=20passphrase=20= callback=20installed.=0A+=20*/=0A+static=20char=20*=0A= +dummy_ssl_passphrase_cb(PK11SlotInfo=20*slot,=20PRBool=20retry,=20void=20= *arg)=0A+{=0A+=09dummy_ssl_passwd_cb_called=20=3D=20true;=0A+=09return=20= NULL;=0A+}=0A+=0A+static=20SECStatus=0A+pg_bad_cert_handler(void=20*arg,=20= PRFileDesc=20*fd)=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+/*=0A+=20*=20raw_subject_common_name=0A+=20*=0A+=20= *=20Returns=20the=20Subject=20Common=20Name=20for=20the=20given=20= certificate=20as=20a=20raw=20char=0A+=20*=20buffer=20(that=20is,=20= without=20any=20form=20of=20escaping=20for=20unprintable=20characters=20= or=0A+=20*=20embedded=20nulls),=20with=20the=20length=20of=20the=20= buffer=20returned=20in=20the=20len=20param.=0A+=20*=20The=20buffer=20is=20= allocated=20in=20the=20TopMemoryContext=20and=20is=20given=20a=20NULL=0A= +=20*=20terminator=20so=20that=20callers=20are=20safe=20to=20call=20= strlen()=20on=20it.=0A+=20*=0A+=20*=20This=20is=20used=20instead=20of=20= CERT_GetCommonName(),=20which=20always=20performs=20quoting=0A+=20*=20= and/or=20escaping.=20NSS=20doesn't=20appear=20to=20give=20us=20a=20way=20= to=20easily=20unescape=20the=0A+=20*=20result,=20and=20we=20need=20to=20= store=20the=20raw=20CN=20into=20port->peer_cn=20for=20compatibility=0A+=20= *=20with=20the=20OpenSSL=20implementation.=0A+=20*/=0A+static=20char=20*=0A= +raw_subject_common_name(CERTCertificate=20*cert,=20unsigned=20int=20= *len)=0A+{=0A+=09CERTName=09subject=20=3D=20cert->subject;=0A+=09CERTRDN=09= =20=20**rdn;=0A+=0A+=09for=20(rdn=20=3D=20subject.rdns;=20*rdn;=20rdn++)=0A= +=09{=0A+=09=09CERTAVA=09=20=20**ava;=0A+=0A+=09=09for=20(ava=20=3D=20= (*rdn)->avas;=20*ava;=20ava++)=0A+=09=09{=0A+=09=09=09SECItem=09=20=20=20= *buf;=0A+=09=09=09char=09=20=20=20*cn;=0A+=0A+=09=09=09if=20= (CERT_GetAVATag(*ava)=20!=3D=20SEC_OID_AVA_COMMON_NAME)=0A+=09=09=09=09= continue;=0A+=0A+=09=09=09/*=20Found=20a=20CN,=20ecode=20and=20copy=20it=20= into=20a=20newly=20allocated=20buffer=20*/=0A+=09=09=09buf=20=3D=20= CERT_DecodeAVAValue(&(*ava)->value);=0A+=09=09=09if=20(!buf)=0A+=09=09=09= {=0A+=09=09=09=09/*=0A+=09=09=09=09=20*=20This=20failure=20case=20is=20= difficult=20to=20test.=20(Since=20this=20code=0A+=09=09=09=09=20*=20runs=20= after=20certificate=20authentication=20has=20otherwise=0A+=09=09=09=09=20= *=20succeeded,=20you'd=20need=20to=20convince=20a=20CA=20implementation=20= to=0A+=09=09=09=09=20*=20sign=20a=20corrupted=20certificate=20in=20order=20= to=20get=20here.)=0A+=09=09=09=09=20*=0A+=09=09=09=09=20*=20Follow=20the=20= behavior=20of=20CERT_GetCommonName()=20in=20this=20case=20and=0A+=09=09=09= =09=20*=20simply=20return=20NULL,=20as=20if=20a=20Common=20Name=20had=20= not=20been=20found.=0A+=09=09=09=09=20*/=0A+=09=09=09=09goto=20fail;=0A+=09= =09=09}=0A+=0A+=09=09=09cn=20=3D=20MemoryContextAlloc(TopMemoryContext,=20= buf->len=20+=201);=0A+=09=09=09memcpy(cn,=20buf->data,=20buf->len);=0A+=09= =09=09cn[buf->len]=20=3D=20'\0';=0A+=0A+=09=09=09*len=20=3D=20buf->len;=0A= +=0A+=09=09=09SECITEM_FreeItem(buf,=20PR_TRUE);=0A+=09=09=09return=20cn;=0A= +=09=09}=0A+=09}=0A+=0A+fail:=0A+=09/*=20Not=20found.=20*/=0A+=09*len=20= =3D=200;=0A+=09return=20NULL;=0A+}=0A+=0A+/*=0A+=20*=20= pg_cert_auth_handler=0A+=20*=0A+=20*=20Callback=20for=20validation=20of=20= incoming=20certificates.=20Returning=20SECFailure=20will=0A+=20*=20cause=20= NSS=20to=20terminate=20the=20connection=20immediately.=0A+=20*/=0A= +static=20SECStatus=0A+pg_cert_auth_handler(void=20*arg,=20PRFileDesc=20= *fd,=20PRBool=20checksig,=20PRBool=20isServer)=0A+{=0A+=09SECStatus=09= status;=0A+=09Port=09=20=20=20*port=20=3D=20(Port=20*)=20arg;=0A+=09= CERTCertificate=20*cert;=0A+=09char=09=20=20=20*peer_cn;=0A+=09unsigned=20= int=20len;=0A+=0A+=09status=20=3D=20= SSL_AuthCertificate(CERT_GetDefaultCertDB(),=20port->pr_fd,=20checksig,=20= PR_TRUE);=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20= status;=0A+=0A+=09port->peer_cn=20=3D=20NULL;=0A+=09= port->peer_cert_valid=20=3D=20false;=0A+=0A+=09cert=20=3D=20= SSL_PeerCertificate(port->pr_fd);=0A+=09if=20(!cert)=0A+=09{=0A+=09=09/*=20= Shouldn't=20be=20possible;=20why=20did=20we=20get=20a=20client=20cert=20= callback?=20*/=0A+=09=09Assert(cert=20!=3D=20NULL);=0A+=0A+=09=09= PR_SetError(SEC_ERROR_LIBRARY_FAILURE,=200);=0A+=09=09return=20= SECFailure;=0A+=09}=0A+=0A+=09peer_cn=20=3D=20= raw_subject_common_name(cert,=20&len);=0A+=09if=20(!peer_cn)=0A+=09{=0A+=09= =09/*=20No=20Common=20Name,=20but=20the=20certificate=20otherwise=20= checks=20out.=20*/=0A+=09=09port->peer_cert_valid=20=3D=20true;=0A+=0A+=09= =09status=20=3D=20SECSuccess;=0A+=09=09goto=20cleanup;=0A+=09}=0A+=0A+=09= /*=0A+=09=20*=20Reject=20embedded=20NULLs=20in=20certificate=20common=20= name=20to=20prevent=20attacks=20like=0A+=09=20*=20CVE-2009-4034.=0A+=09=20= */=0A+=09if=20(len=20!=3D=20strlen(peer_cn))=0A+=09{=0A+=09=09= ereport(COMMERROR,=0A+=09=09=09=09(errcode(ERRCODE_PROTOCOL_VIOLATION),=0A= +=09=09=09=09=20errmsg("SSL=20certificate's=20common=20name=20contains=20= embedded=20null")));=0A+=0A+=09=09pfree(peer_cn);=0A+=09=09= PR_SetError(SEC_ERROR_CERT_NOT_VALID,=200);=0A+=0A+=09=09status=20=3D=20= SECFailure;=0A+=09=09goto=20cleanup;=0A+=09}=0A+=0A+=09port->peer_cn=20=3D= =20peer_cn;=0A+=09port->peer_cert_valid=20=3D=20true;=0A+=0A+=09status=20= =3D=20SECSuccess;=0A+=0A+cleanup:=0A+=09CERT_DestroyCertificate(cert);=0A= +=09return=20status;=0A+}=0A+=0A+static=20PRInt32=0A= +pg_ssl_read(PRFileDesc=20*fd,=20void=20*buf,=20PRInt32=20amount,=20= PRIntn=20flags,=0A+=09=09=09PRIntervalTime=20timeout)=0A+{=0A+=09= PRRecvFN=09read_fn;=0A+=09PRInt32=09=09n_read;=0A+=0A+=09read_fn=20=3D=20= fd->lower->methods->recv;=0A+=09n_read=20=3D=20read_fn(fd->lower,=20buf,=20= amount,=20flags,=20timeout);=0A+=0A+=09return=20n_read;=0A+}=0A+=0A= +static=20PRInt32=0A+pg_ssl_write(PRFileDesc=20*fd,=20const=20void=20= *buf,=20PRInt32=20amount,=20PRIntn=20flags,=0A+=09=09=09=20= PRIntervalTime=20timeout)=0A+{=0A+=09PRSendFN=09send_fn;=0A+=09PRInt32=09= =09n_write;=0A+=0A+=09send_fn=20=3D=20fd->lower->methods->send;=0A+=09= n_write=20=3D=20send_fn(fd->lower,=20buf,=20amount,=20flags,=20timeout);=0A= +=0A+=09return=20n_write;=0A+}=0A+=0A+static=20PRStatus=0A= +pg_ssl_close(PRFileDesc=20*fd)=0A+{=0A+=09/*=0A+=09=20*=20Disconnect=20= our=20private=20Port=20from=20the=20fd=20before=20closing=20out=20the=20= stack.=0A+=09=20*=20(Debug=20builds=20of=20NSPR=20will=20assert=20if=20= we=20do=20not.)=0A+=09=20*/=0A+=09fd->secret=20=3D=20NULL;=0A+=09return=20= PR_GetDefaultIOMethods()->close(fd);=0A+}=0A+=0A+static=20PRFileDesc=20*=0A= +init_iolayer(Port=20*port)=0A+{=0A+=09const=09=09PRIOMethods=20= *default_methods;=0A+=09PRFileDesc=20*layer;=0A+=0A+=09/*=0A+=09=20*=20= Start=20by=20initializing=20our=20layer=20with=20all=20the=20default=20= methods=20so=20that=20we=0A+=09=20*=20can=20selectively=20override=20the=20= ones=20we=20want=20while=20still=20ensuring=20that=20we=0A+=09=20*=20= have=20a=20complete=20layer=20specification.=0A+=09=20*/=0A+=09= default_methods=20=3D=20PR_GetDefaultIOMethods();=0A+=09= memcpy(&pr_iomethods,=20default_methods,=20sizeof(PRIOMethods));=0A+=0A+=09= pr_iomethods.recv=20=3D=20pg_ssl_read;=0A+=09pr_iomethods.send=20=3D=20= pg_ssl_write;=0A+=09pr_iomethods.close=20=3D=20pg_ssl_close;=0A+=0A+=09= /*=0A+=09=20*=20Each=20IO=20layer=20must=20be=20identified=20by=20a=20= unique=20name,=20where=20uniqueness=20is=0A+=09=20*=20per=20connection.=20= Each=20connection=20in=20a=20postgres=20cluster=20can=20generate=20the=0A= +=09=20*=20identity=20from=20the=20same=20string=20as=20they=20will=20= create=20their=20IO=20layers=20on=0A+=09=20*=20different=20sockets.=20= Only=20one=20layer=20per=20socket=20can=20have=20the=20same=20name.=0A+=09= =20*/=0A+=09pr_id=20=3D=20PR_GetUniqueIdentity("PostgreSQL=20Server");=0A= +=09if=20(pr_id=20=3D=3D=20PR_INVALID_IO_LAYER)=0A+=09{=0A+=09=09= ereport(ERROR,=0A+=09=09=09=09(errmsg("out=20of=20memory=20when=20= setting=20up=20TLS=20connection")));=0A+=09=09return=20NULL;=0A+=09}=0A+=0A= +=09/*=0A+=09=20*=20Create=20the=20actual=20IO=20layer=20as=20a=20stub=20= such=20that=20it=20can=20be=20pushed=20onto=0A+=09=20*=20the=20layer=20= stack.=20The=20step=20via=20a=20stub=20is=20required=20as=20we=20define=20= custom=0A+=09=20*=20callbacks.=0A+=09=20*/=0A+=09layer=20=3D=20= PR_CreateIOLayerStub(pr_id,=20&pr_iomethods);=0A+=09if=20(!layer)=0A+=09= {=0A+=09=09ereport(ERROR,=0A+=09=09=09=09(errmsg("unable=20to=20create=20= NSS=20I/O=20layer")));=0A+=09=09return=20NULL;=0A+=09}=0A+=0A+=09/*=20= Store=20the=20Port=20as=20private=20data=20available=20in=20callbacks=20= */=0A+=09layer->secret=20=3D=20(void=20*)=20port;=0A+=0A+=09return=20= layer;=0A+}=0A+=0A+static=20char=20*=0A= +ssl_protocol_version_to_string(int=20v)=0A+{=0A+=09switch=20(v)=0A+=09{=0A= +=09=09=09/*=20SSL=20v2=20and=20v3=20are=20not=20supported=20*/=0A+=09=09= case=20SSL_LIBRARY_VERSION_2:=0A+=09=09case=20SSL_LIBRARY_VERSION_3_0:=0A= +=09=09=09Assert(false);=0A+=09=09=09break;=0A+=0A+=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_0:=0A+=09=09=09return=20pstrdup("TLSv1.0");=0A= +=09=09case=20SSL_LIBRARY_VERSION_TLS_1_1:=0A+=09=09=09return=20= pstrdup("TLSv1.1");=0A+=09=09case=20SSL_LIBRARY_VERSION_TLS_1_2:=0A+=09=09= =09return=20pstrdup("TLSv1.2");=0A+=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_3:=0A+=09=09=09return=20pstrdup("TLSv1.3");=0A= +=09}=0A+=0A+=09return=20pstrdup("unknown");=0A+}=0A+=0A+=0A+/*=0A+=20*=20= ssl_protocol_version_to_nss=0A+=20*=09=09=09Translate=20PostgreSQL=20TLS=20= version=20to=20NSS=20version=0A+=20*=0A+=20*=20Returns=20zero=20in=20= case=20the=20requested=20TLS=20version=20is=20undefined=20(PG_ANY)=20and=0A= +=20*=20should=20be=20set=20by=20the=20caller,=20or=20-1=20on=20failure.=0A= +=20*/=0A+static=20uint16=0A+ssl_protocol_version_to_nss(int=20v,=20= const=20char=20*guc_name)=0A+{=0A+=09switch=20(v)=0A+=09{=0A+=09=09=09/*=0A= +=09=09=09=20*=20There=20is=20no=20SSL_LIBRARY_=20macro=20defined=20in=20= NSS=20with=20the=20value=0A+=09=09=09=20*=20zero,=20so=20we=20use=20this=20= to=20signal=20the=20caller=20that=20the=20highest=0A+=09=09=09=20*=20= useful=20version=20should=20be=20set=20on=20the=20connection.=0A+=09=09=09= =20*/=0A+=09=09case=20PG_TLS_ANY:=0A+=09=09=09return=200;=0A+=0A+=09=09=09= /*=0A+=09=09=09=20*=20No=20guard=20is=20required=20here=20as=20there=20= are=20no=20versions=20of=20NSS=0A+=09=09=09=20*=20without=20support=20= for=20TLS1.=0A+=09=09=09=20*/=0A+=09=09case=20PG_TLS1_VERSION:=0A+=09=09=09= return=20SSL_LIBRARY_VERSION_TLS_1_0;=0A+=09=09case=20PG_TLS1_1_VERSION:=0A= +#ifdef=20SSL_LIBRARY_VERSION_TLS_1_1=0A+=09=09=09return=20= SSL_LIBRARY_VERSION_TLS_1_1;=0A+#else=0A+=09=09=09break;=0A+#endif=0A+=09= =09case=20PG_TLS1_2_VERSION:=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_2=0A+=09= =09=09return=20SSL_LIBRARY_VERSION_TLS_1_2;=0A+#else=0A+=09=09=09break;=0A= +#endif=0A+=09=09case=20PG_TLS1_3_VERSION:=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_3=0A+=09=09=09return=20= SSL_LIBRARY_VERSION_TLS_1_3;=0A+#else=0A+=09=09=09break;=0A+#endif=0A+=09= =09default:=0A+=09=09=09break;=0A+=09}=0A+=0A+=09return=20-1;=0A+}=0A+=0A= +/*=0A+=20*=20pg_SSLerrmessage=0A+=20*=09=09Create=20and=20return=20a=20= human=20readable=20error=20message=20given=0A+=20*=09=09the=20specified=20= error=20code=0A+=20*=0A+=20*=20PR_ErrorToName=20only=20converts=20the=20= enum=20identifier=20of=20the=20error=20to=20string,=0A+=20*=20but=20that=20= can=20be=20quite=20useful=20for=20debugging=20(and=20in=20case=20= PR_ErrorToString=20is=0A+=20*=20unable=20to=20render=20a=20message=20= then=20we=20at=20least=20have=20something).=0A+=20*/=0A+static=20char=20= *=0A+pg_SSLerrmessage(PRErrorCode=20errcode)=0A+{=0A+=09return=20= psprintf("%s=20(%s)",=0A+=09=09=09=09=09PR_ErrorToString(errcode,=20= PR_LANGUAGE_I_DEFAULT),=0A+=09=09=09=09=09PR_ErrorToName(errcode));=0A+}=0A= +=0A+/*=0A+=20*=20pg_SSLShutdownFunc=0A+=20*=09=09Callback=20for=20NSS=20= shutdown=0A+=20*=0A+=20*=20If=20NSS=20is=20terminated=20from=20the=20= outside=20when=20the=20connection=20is=20still=20in=20use=0A+=20*=20we=20= must=20treat=20this=20as=20potentially=20hostile=20and=20immediately=20= close=20to=20avoid=0A+=20*=20leaking=20the=20connection=20in=20any=20= way.=20Once=20this=20is=20called,=20NSS=20will=20shutdown=0A+=20*=20= regardless=20so=20we=20may=20as=20well=20clean=20up=20the=20best=20we=20= can.=20Returning=20SECFailure=0A+=20*=20will=20cause=20the=20NSS=20= shutdown=20to=20return=20with=20an=20error,=20but=20it=20will=20shutdown=0A= +=20*=20nevertheless.=20nss_data=20is=20reserved=20for=20future=20use=20= and=20is=20always=20NULL.=0A+=20*/=0A+static=20SECStatus=0A= +pg_SSLShutdownFunc(void=20*private_data,=20void=20*nss_data)=0A+{=0A+=09= Port=20*port=20=3D=20(Port=20*)=20private_data;=0A+=0A+=09if=20(!port=20= ||=20!port->ssl_in_use)=0A+=09=09return=20SECSuccess;=0A+=0A+=09/*=0A+=09= =20*=20There=20is=20a=20connection=20still=20open,=20close=20it=20and=20= signal=20to=20whatever=20that=0A+=09=20*=20called=20the=20shutdown=20= that=20it=20was=20erroneous.=0A+=09=20*/=0A+=09be_tls_close(port);=0A+=09= be_tls_destroy();=0A+=0A+=09return=20SECFailure;=0A+}=0Adiff=20--git=20= a/src/backend/libpq/be-secure.c=20b/src/backend/libpq/be-secure.c=0A= index=20d1545a2ad6..be583d7278=20100644=0A---=20= a/src/backend/libpq/be-secure.c=0A+++=20b/src/backend/libpq/be-secure.c=0A= @@=20-50,6=20+50,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/utils/misc/guc.c=20b/src/backend/utils/misc/guc.c=0Aindex=20= 260ec7b97e..40b9c2a883=20100644=0A---=20a/src/backend/utils/misc/guc.c=0A= +++=20b/src/backend/utils/misc/guc.c=0A@@=20-4308,7=20+4308,11=20@@=20= static=20struct=20config_string=20ConfigureNamesString[]=20=3D=0A=20=09=09= },=0A=20=09=09&ssl_library,=0A=20#ifdef=20USE_SSL=0A+#if=20= defined(USE_OPENSSL)=0A=20=09=09"OpenSSL",=0A+#elif=20defined(USE_NSS)=0A= +=09=09"NSS",=0A+#endif=0A=20#else=0A=20=09=09"",=0A=20#endif=0A@@=20= -4376,6=20+4380,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-4404,8=20= +4420,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/cipher_nss.c=20b/src/common/cipher_nss.c=0Anew=20file=20= mode=20100644=0Aindex=200000000000..9799fef32d=0A---=20/dev/null=0A+++=20= b/src/common/cipher_nss.c=0A@@=20-0,0=20+1,192=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20cipher_nss.c=0A+=20*=09=20=20NSS=20functionality=20= shared=20between=20frontend=20and=20backend=20for=20working=0A+=20*=09=20= =20with=20ciphers=0A+=20*=0A+=20*=20This=20should=20only=20bse=20used=20= if=20code=20is=20compiled=20with=20NSS=20support.=0A+=20*=0A+=20*=20= Portions=20Copyright=20(c)=201996-2021,=20PostgreSQL=20Global=20= Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=201994,=20= Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=20=20=20=20=20=20=20=20src/common/cipher_nss.c=0A= +=20*=0A+=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#ifndef=20FRONTEND=0A+#include=20"postgres.h"=0A+#else=0A= +#include=20"postgres_fe.h"=0A+#endif=0A+=0A+#include=20"common/nss.h"=0A= +=0A+#define=20INVALID_CIPHER=090xFFFF=0A+=0A+typedef=20struct=0A+{=0A+=09= SECOidTag=09signature;=0A+=09SECOidTag=09hash;=0A+=09int=09=09=09len;=0A= +}=09=09=09NSSSignatureAlgorithm;=0A+=0A+static=20const=20= NSSSignatureAlgorithm=20NSS_SCRAMDigestAlgorithm[]=20=3D=20{=0A+=0A+=09= {SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,=20SEC_OID_SHA256,=20= SHA256_LENGTH},=0A+=09{SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION,=20= SEC_OID_SHA256,=20SHA256_LENGTH},=0A+=09= {SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE,=20SEC_OID_SHA256,=20SHA256_LENGTH},=0A= +=09{SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE,=20SEC_OID_SHA256,=20= SHA256_LENGTH},=0A+=09{SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,=20= SEC_OID_SHA256,=20SHA256_LENGTH},=0A+=0A+=09= {SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE,=20SEC_OID_SHA224,=20= SHA224_LENGTH},=0A+=09{SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION,=20= SEC_OID_SHA224,=20SHA224_LENGTH},=0A+=09= {SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST,=20SEC_OID_SHA224,=20= SHA224_LENGTH},=0A+=0A+=09{SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE,=20= SEC_OID_SHA256,=20SHA256_LENGTH},=0A+=09= {SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION,=20SEC_OID_SHA256,=20= SHA256_LENGTH},=0A+=09{SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST,=20= SEC_OID_SHA256,=20SHA256_LENGTH},=0A+=0A+=09= {SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE,=20SEC_OID_SHA384,=20= SHA384_LENGTH},=0A+=09{SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION,=20= SEC_OID_SHA384,=20SHA384_LENGTH},=0A+=0A+=09= {SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE,=20SEC_OID_SHA512,=20= SHA512_LENGTH},=0A+=09{SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION,=20= SEC_OID_SHA512,=20SHA512_LENGTH},=0A+=0A+=09{0,=200}=0A+};=0A+=0A= +typedef=20struct=0A+{=0A+=09const=20char=20*name;=0A+=09PRUint16=09= number;=0A+}=09=09=09NSSCiphers;=0A+=0A+/*=0A+=20*=20This=20list=20is=20= a=20partial=20copy=20of=20the=20ciphers=20in=20NSS=20files=20= lib/ssl/sslproto.h=0A+=20*=20in=20order=20to=20provide=20a=20human=20= readable=20version=20of=20the=20ciphers.=20It=20would=20be=0A+=20*=20= nice=20to=20not=20have=20to=20have=20this,=20but=20NSS=20doesn't=20= provide=20any=20API=20addressing=0A+=20*=20the=20ciphers=20by=20name.=20= TODO:=20do=20we=20want=20more=20of=20the=20ciphers,=20or=20perhaps=20= less?=0A+=20*/=0A+static=20const=20NSSCiphers=20NSS_CipherList[]=20=3D=20= {=0A+=0A+=09{"TLS_NULL_WITH_NULL_NULL",=20TLS_NULL_WITH_NULL_NULL},=0A+=0A= +=09{"TLS_RSA_WITH_NULL_MD5",=20TLS_RSA_WITH_NULL_MD5},=0A+=09= {"TLS_RSA_WITH_NULL_SHA",=20TLS_RSA_WITH_NULL_SHA},=0A+=09= {"TLS_RSA_WITH_RC4_128_MD5",=20TLS_RSA_WITH_RC4_128_MD5},=0A+=09= {"TLS_RSA_WITH_RC4_128_SHA",=20TLS_RSA_WITH_RC4_128_SHA},=0A+=09= {"TLS_RSA_WITH_IDEA_CBC_SHA",=20TLS_RSA_WITH_IDEA_CBC_SHA},=0A+=09= {"TLS_RSA_WITH_DES_CBC_SHA",=20TLS_RSA_WITH_DES_CBC_SHA},=0A+=09= {"TLS_RSA_WITH_3DES_EDE_CBC_SHA",=20TLS_RSA_WITH_3DES_EDE_CBC_SHA},=0A+=0A= +=09{"TLS_DH_DSS_WITH_DES_CBC_SHA",=20TLS_DH_DSS_WITH_DES_CBC_SHA},=0A+=09= {"TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA",=20= TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA},=0A+=09{"TLS_DH_RSA_WITH_DES_CBC_SHA",=20= TLS_DH_RSA_WITH_DES_CBC_SHA},=0A+=09{"TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA",=20= TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA},=0A+=0A+=09= {"TLS_DHE_DSS_WITH_DES_CBC_SHA",=20TLS_DHE_DSS_WITH_DES_CBC_SHA},=0A+=09= {"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",=20= TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_DES_CBC_SHA",=20TLS_DHE_RSA_WITH_DES_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",=20= TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA},=0A+=0A+=09= {"TLS_DH_anon_WITH_RC4_128_MD5",=20TLS_DH_anon_WITH_RC4_128_MD5},=0A+=09= {"TLS_DH_anon_WITH_DES_CBC_SHA",=20TLS_DH_anon_WITH_DES_CBC_SHA},=0A+=09= {"TLS_DH_anon_WITH_3DES_EDE_CBC_SHA",=20= TLS_DH_anon_WITH_3DES_EDE_CBC_SHA},=0A+=0A+=09= {"TLS_RSA_WITH_AES_128_CBC_SHA",=20TLS_RSA_WITH_AES_128_CBC_SHA},=0A+=09= {"TLS_DH_DSS_WITH_AES_128_CBC_SHA",=20TLS_DH_DSS_WITH_AES_128_CBC_SHA},=0A= +=09{"TLS_DH_RSA_WITH_AES_128_CBC_SHA",=20= TLS_DH_RSA_WITH_AES_128_CBC_SHA},=0A+=09= {"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",=20= TLS_DHE_DSS_WITH_AES_128_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",=20= TLS_DHE_RSA_WITH_AES_128_CBC_SHA},=0A+=09= {"TLS_DH_anon_WITH_AES_128_CBC_SHA",=20= TLS_DH_anon_WITH_AES_128_CBC_SHA},=0A+=0A+=09= {"TLS_RSA_WITH_AES_256_CBC_SHA",=20TLS_RSA_WITH_AES_256_CBC_SHA},=0A+=09= {"TLS_DH_DSS_WITH_AES_256_CBC_SHA",=20TLS_DH_DSS_WITH_AES_256_CBC_SHA},=0A= +=09{"TLS_DH_RSA_WITH_AES_256_CBC_SHA",=20= TLS_DH_RSA_WITH_AES_256_CBC_SHA},=0A+=09= {"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",=20= TLS_DHE_DSS_WITH_AES_256_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",=20= TLS_DHE_RSA_WITH_AES_256_CBC_SHA},=0A+=09= {"TLS_DH_anon_WITH_AES_256_CBC_SHA",=20= TLS_DH_anon_WITH_AES_256_CBC_SHA},=0A+=09{"TLS_RSA_WITH_NULL_SHA256",=20= TLS_RSA_WITH_NULL_SHA256},=0A+=09{"TLS_RSA_WITH_AES_128_CBC_SHA256",=20= TLS_RSA_WITH_AES_128_CBC_SHA256},=0A+=09= {"TLS_RSA_WITH_AES_256_CBC_SHA256",=20TLS_RSA_WITH_AES_256_CBC_SHA256},=0A= +=0A+=09{"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",=20= TLS_DHE_DSS_WITH_AES_128_CBC_SHA256},=0A+=09= {"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_RSA_WITH_CAMELLIA_128_CBC_SHA},=0A+=09= {"TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA},=0A+=09= {"TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA},=0A+=09= {"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA},=0A+=09= {"TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",=20= TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA},=0A+=0A+=09= {"TLS_DHE_DSS_WITH_RC4_128_SHA",=20TLS_DHE_DSS_WITH_RC4_128_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",=20= TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},=0A+=09= {"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",=20= TLS_DHE_DSS_WITH_AES_256_CBC_SHA256},=0A+=09= {"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",=20= TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},=0A+=0A+=09= {"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_RSA_WITH_CAMELLIA_256_CBC_SHA},=0A+=09= {"TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA},=0A+=09= {"TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA},=0A+=09= {"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA},=0A+=09= {"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA},=0A+=09= {"TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",=20= TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA},=0A+=0A+=09= {"TLS_RSA_WITH_SEED_CBC_SHA",=20TLS_RSA_WITH_SEED_CBC_SHA},=0A+=0A+=09= {"TLS_RSA_WITH_AES_128_GCM_SHA256",=20TLS_RSA_WITH_AES_128_GCM_SHA256},=0A= +=09{"TLS_RSA_WITH_AES_256_GCM_SHA384",=20= TLS_RSA_WITH_AES_256_GCM_SHA384},=0A+=09= {"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",=20= TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},=0A+=09= {"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",=20= TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},=0A+=09= {"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",=20= TLS_DHE_DSS_WITH_AES_128_GCM_SHA256},=0A+=09= {"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",=20= TLS_DHE_DSS_WITH_AES_256_GCM_SHA384},=0A+=0A+=09= {"TLS_AES_128_GCM_SHA256",=20TLS_AES_128_GCM_SHA256},=0A+=09= {"TLS_AES_256_GCM_SHA384",=20TLS_AES_256_GCM_SHA384},=0A+=09= {"TLS_CHACHA20_POLY1305_SHA256",=20TLS_CHACHA20_POLY1305_SHA256},=0A+=09= {NULL,=200}=0A+};=0A+=0A+/*=0A+=20*=20pg_find_cipher=0A+=20*=09=09=09= Translate=20an=20NSS=20ciphername=20to=20the=20cipher=20code=0A+=20*=0A+=20= *=20Searches=20the=20configured=20ciphers=20for=20the=20corresponding=20= cipher=20code=20to=20the=0A+=20*=20name.=20Search=20is=20performed=20= case=20insensitive.=0A+=20*/=0A+bool=0A+pg_find_cipher(char=20*name,=20= PRUint16=20*cipher)=0A+{=0A+=09const=09=09NSSCiphers=20*cipher_list;=0A+=0A= +=09for=20(cipher_list=20=3D=20NSS_CipherList;=20cipher_list->name;=20= cipher_list++)=0A+=09{=0A+=09=09if=20(pg_strcasecmp(cipher_list->name,=20= name)=20=3D=3D=200)=0A+=09=09{=0A+=09=09=09*cipher=20=3D=20= cipher_list->number;=0A+=09=09=09return=20true;=0A+=09=09}=0A+=09}=0A+=0A= +=09return=20false;=0A+}=0A+=0A+bool=0A= +pg_find_signature_algorithm(SECOidTag=20signature,=20SECOidTag=20= *algorithm,=20int=20*len)=0A+{=0A+=09const=20NSSSignatureAlgorithm=20= *candidate;=0A+=0A+=09candidate=20=3D=20NSS_SCRAMDigestAlgorithm;=0A+=0A= +=09for=20(candidate=20=3D=20NSS_SCRAMDigestAlgorithm;=20= candidate->signature;=20candidate++)=0A+=09{=0A+=09=09if=20(signature=20= =3D=3D=20candidate->signature)=0A+=09=09{=0A+=09=09=09*algorithm=20=3D=20= candidate->hash;=0A+=09=09=09*len=20=3D=20candidate->len;=0A+=09=09=09= return=20true;=0A+=09=09}=0A+=09}=0A+=0A+=09return=20false;=0A+}=0Adiff=20= --git=20a/src/include/common/nss.h=20b/src/include/common/nss.h=0Anew=20= file=20mode=20100644=0Aindex=200000000000..a361dd1f68=0A---=20/dev/null=0A= +++=20b/src/include/common/nss.h=0A@@=20-0,0=20+1,49=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20nss.h=0A+=20*=09=20=20NSS=20supporting=20= functionality=20shared=20between=20frontend=20and=20backend=0A+=20*=0A+=20= *=20Portions=20Copyright=20(c)=201996-2021,=20PostgreSQL=20Global=20= Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=201994,=20= Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20*=20= IDENTIFICATION=0A+=20*=09=09=20=20src/include/common/nss.h=0A+=20*=0A+=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+#ifndef=20COMMON_NSS_H=0A+#define=20COMMON_NSS_H=0A+=0A= +#ifdef=20USE_NSS=0A+=0A+/*=0A+=20*=20BITS_PER_BYTE=20is=20also=20= defined=20in=20the=20NSPR=20header=20files,=20so=20we=20need=20to=20= undef=0A+=20*=20our=20version=20to=20avoid=20compiler=20warnings=20on=20= redefinition.=0A+=20*/=0A+#define=20pg_BITS_PER_BYTE=20BITS_PER_BYTE=0A= +#undef=20BITS_PER_BYTE=0A+/*=0A+=20*=20The=20nspr/obsolete/protypes.h=20= NSPR=20header=20typedefs=20uint64=20and=20int64=20with=0A+=20*=20= colliding=20definitions=20from=20ours,=20causing=20a=20much=20expected=20= compiler=20error.=0A+=20*=20Remove=20backwards=20compatibility=20with=20= ancient=20NSPR=20versions=20to=20avoid=20this.=0A+=20*/=0A+#define=20= NO_NSPR_10_SUPPORT=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+=0A+=0A+#include=20= =0A+#include=20=0A+#include=20=0A= +#include=20=0A+=0A+/*=20src/common/cipher_nss.c=20*/=0A= +bool=20pg_find_cipher(char=20*name,=20PRUint16=20*cipher);=0A+bool=20= pg_find_signature_algorithm(SECOidTag=20signature,=20SECOidTag=20= *digest,=20int=20*len);=0A+=0A+#endif=09=09=09=09=09=09=09/*=20USE_NSS=20= */=0A+=0A+#endif=09=09=09=09=09=09=09/*=20COMMON_NSS_H=20*/=0Adiff=20= --git=20a/src/include/libpq/libpq-be.h=20b/src/include/libpq/libpq-be.h=0A= index=207be1a67d69..eb00d9152b=20100644=0A---=20= a/src/include/libpq/libpq-be.h=0A+++=20b/src/include/libpq/libpq-be.h=0A= @@=20-200,6=20+200,10=20@@=20typedef=20struct=20Port=0A=20=09SSL=09=09=20= =20=20*ssl;=0A=20=09X509=09=20=20=20*peer;=0A=20#endif=0A+=0A+#ifdef=20= USE_NSS=0A+=09void=09=20=20=20*pr_fd;=0A+#endif=0A=20}=20Port;=0A=20=0A=20= #ifdef=20USE_SSL=0A@@=20-283,7=20+287,7=20@@=20extern=20void=20= be_tls_get_peer_serial(Port=20*port,=20char=20*ptr,=20size_t=20len);=0A=20= =20*=20This=20is=20not=20supported=20with=20old=20versions=20of=20= OpenSSL=20that=20don't=20have=0A=20=20*=20the=20X509_get_signature_nid()=20= function.=0A=20=20*/=0A-#if=20defined(USE_OPENSSL)=20&&=20= defined(HAVE_X509_GET_SIGNATURE_NID)=0A+#if=20defined(USE_NSS)=20||=20= (defined(USE_OPENSSL)=20&&=20defined(HAVE_X509_GET_SIGNATURE_NID))=0A=20= #define=20HAVE_BE_TLS_GET_CERTIFICATE_HASH=0A=20extern=20char=20= *be_tls_get_certificate_hash(Port=20*port,=20size_t=20*len);=0A=20#endif=0A= @@=20-293,6=20+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=20b41b10620a..ff67d0d20d=20100644=0A= ---=20a/src/include/libpq/libpq.h=0A+++=20b/src/include/libpq/libpq.h=0A= @@=20-89,6=20+89,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_manual.h=20b/src/include/pg_config_manual.h=0A= index=202a12071bad..7861b94290=20100644=0A---=20= a/src/include/pg_config_manual.h=0A+++=20= b/src/include/pg_config_manual.h=0A@@=20-178,7=20+178,7=20@@=0A=20=20*=20= USE_SSL=20code=20should=20be=20compiled=20only=20when=20compiling=20with=20= an=20SSL=0A=20=20*=20implementation.=0A=20=20*/=0A-#ifdef=20USE_OPENSSL=0A= +#if=20defined(USE_OPENSSL)=20||=20defined(USE_NSS)=0A=20#define=20= USE_SSL=0A=20#endif=0A=20=0Adiff=20--git=20= a/src/interfaces/libpq/fe-connect.c=20= b/src/interfaces/libpq/fe-connect.c=0Aindex=20db71fea169..40bc1cd348=20= 100644=0A---=20a/src/interfaces/libpq/fe-connect.c=0A+++=20= b/src/interfaces/libpq/fe-connect.c=0A@@=20-359,6=20+359,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..72b0c54d1c=0A---=20/dev/null=0A+++=20= b/src/interfaces/libpq/fe-secure-nss.c=0A@@=20-0,0=20+1,1088=20@@=0A= +/*-----------------------------------------------------------------------= --=0A+=20*=0A+=20*=20fe-secure-nss.c=0A+=20*=09=20=20functions=20for=20= supporting=20NSS=20as=20a=20TLS=20backend=20for=20frontend=20libpq=0A+=20= *=0A+=20*=20Portions=20Copyright=20(c)=201996-2021,=20PostgreSQL=20= Global=20Development=20Group=0A+=20*=20Portions=20Copyright=20(c)=20= 1994,=20Regents=20of=20the=20University=20of=20California=0A+=20*=0A+=20= *=20IDENTIFICATION=0A+=20*=09=20=20src/interfaces/libpq/fe-secure-nss.c=0A= +=20*=0A+=20= *-------------------------------------------------------------------------= =0A+=20*/=0A+=0A+#include=20"postgres_fe.h"=0A+=0A+#include=20= "libpq-fe.h"=0A+#include=20"fe-auth.h"=0A+#include=20= "fe-secure-common.h"=0A+#include=20"libpq-int.h"=0A+#include=20= "common/nss.h"=0A+=0A+/*=0A+=20*=20The=20nspr/obsolete/protypes.h=20NSPR=20= header=20typedefs=20uint64=20and=20int64=20with=0A+=20*=20colliding=20= definitions=20from=20ours,=20causing=20a=20much=20expected=20compiler=20= error.=0A+=20*=20Remove=20backwards=20compatibility=20with=20ancient=20= NSPR=20versions=20to=20avoid=20this.=0A+=20*/=0A+#define=20= NO_NSPR_10_SUPPORT=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+=0A+#include=20=0A+#include=20=0A= +#include=20=0A+#include=20=0A+#include=20= =0A+#include=20=0A+#include=20= =0A+#include=20=0A+=0A+static=20SECStatus=20= pg_load_nss_module(SECMODModule=20**module,=20const=20char=20*library,=20= const=20char=20*name);=0A+static=20SECStatus=20pg_bad_cert_handler(void=20= *arg,=20PRFileDesc=20*fd);=0A+static=20const=20char=20= *pg_SSLerrmessage(PRErrorCode=20errcode);=0A+static=20SECStatus=20= pg_client_auth_handler(void=20*arg,=20PRFileDesc=20*socket,=20= CERTDistNames=20*caNames,=0A+=09=09=09=09=09=09=09=09=09=09= CERTCertificate=20**pRetCert,=20SECKEYPrivateKey=20**pRetKey);=0A+static=20= SECStatus=20pg_cert_auth_handler(void=20*arg,=20PRFileDesc=20*fd,=20= PRBool=20checksig,=20PRBool=20isServer);=0A+static=20int=09= ssl_protocol_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*slot,=20PRBool=20retry,=20void=20*arg);=0A= +=0A+/*=0A+=20*=20PR_ImportTCPSocket()=20is=20a=20private=20API,=20but=20= very=20widely=20used,=20as=20it's=20the=0A+=20*=20only=20way=20to=20make=20= NSS=20use=20an=20already=20set=20up=20POSIX=20file=20descriptor=20rather=0A= +=20*=20than=20opening=20one=20itself.=20To=20quote=20the=20NSS=20= documentation:=0A+=20*=0A+=20*=09=09"In=20theory,=20code=20that=20uses=20= PR_ImportTCPSocket=20may=20break=20when=20NSPR's=0A+=20*=09=09= implementation=20changes.=20In=20practice,=20this=20is=20unlikely=20to=20= happen=20because=0A+=20*=09=09NSPR's=20implementation=20has=20been=20= stable=20for=20years=20and=20because=20of=20NSPR's=0A+=20*=09=09strong=20= commitment=20to=20backward=20compatibility."=0A+=20*=0A+=20*=20= https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/P= R_ImportTCPSocket=0A+=20*=0A+=20*=20The=20function=20is=20declared=20in=20= ,=20but=20as=20it=20is=20a=20header=20marked=0A+=20*=20= private=20we=20declare=20it=20here=20rather=20than=20including=20it.=0A+=20= */=0A+NSPR_API(PRFileDesc=20*)=20PR_ImportTCPSocket(int);=0A+=0A+static=20= SECMODModule=20*ca_trust=20=3D=20NULL;=0A+=0A+/*=0A+=20*=20This=20logic=20= exist=20in=20NSS=20as=20well,=20but=20it's=20only=20available=20for=20= when=20there=20is=0A+=20*=20a=20database=20to=20open,=20and=20not=20only=20= using=20the=20system=20trust=20store.=20Thus,=20we=0A+=20*=20need=20to=20= keep=20our=20own=20copy.=0A+=20*/=0A+#if=20defined(WIN32)=0A+static=20= const=20char=20*ca_trust_name=20=3D=20"nssckbi.dll";=0A+#elif=20= defined(__darwin__)=0A+static=20const=20char=20*ca_trust_name=20=3D=20= "libnssckbi.dylib";=0A+#else=0A+static=20const=20char=20*ca_trust_name=20= =3D=20"libnssckbi.so";=0A+#endif=0A+=0A+static=20= PQsslKeyPassHook_nss_type=20PQsslKeyPassHook=20=3D=20NULL;=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09=20Procedures=20common=20to=20all=20secure=20sessions=09=09=09*/=0A= +/*=20------------------------------------------------------------=20*/=0A= +=0A+/*=0A+=20*=20pgtls_init_library=0A+=20*=0A+=20*=20There=20is=20no=20= direct=20equivalent=20for=20PQinitOpenSSL=20in=20NSS/NSPR,=20with=20= PR_Init=0A+=20*=20being=20the=20closest=20match=20there=20is.=20PR_Init=20= is=20however=20already=20documented=20to=0A+=20*=20not=20be=20required=20= so=20simply=20making=20this=20a=20noop=20seems=20like=20the=20best=20= option.=0A+=20*/=0A+void=0A+pgtls_init_library(bool=20do_ssl,=20int=20= do_crypto)=0A+{=0A+=09/*=20noop=20*/=0A+}=0A+=0A+int=0A= +pgtls_init(PGconn=20*conn)=0A+{=0A+=09conn->nss_context=20=3D=20NULL;=0A= +=0A+=09conn->ssl_in_use=20=3D=20false;=0A+=09conn->has_password=20=3D=20= false;=0A+=0A+=09return=200;=0A+}=0A+=0A+void=0A+pgtls_close(PGconn=20= *conn)=0A+{=0A+=09if=20(conn->nss_context)=0A+=09{=0A+=09=09= NSS_ShutdownContext(conn->nss_context);=0A+=09=09conn->nss_context=20=3D=20= NULL;=0A+=09}=0A+}=0A+=0A+PostgresPollingStatusType=0A= +pgtls_open_client(PGconn=20*conn)=0A+{=0A+=09SECStatus=09status;=0A+=09= PRFileDesc=20*pr_fd;=0A+=09PRFileDesc=20*model;=0A+=09NSSInitParameters=20= params;=0A+=09SSLVersionRange=20desired_range;=0A+=0A+=09/*=0A+=09=20*=20= The=20NSPR=20documentation=20states=20that=20runtime=20initialization=20= via=20PR_Init=0A+=09=20*=20is=20no=20longer=20required,=20as=20the=20= first=20caller=20into=20NSPR=20will=20perform=20the=0A+=09=20*=20= initialization=20implicitly.=20See=20be-secure-nss.c=20for=20further=20= discussion=0A+=09=20*=20on=20PR_Init.=0A+=09=20*/=0A+=09= PR_Init(PR_USER_THREAD,=20PR_PRIORITY_NORMAL,=200);=0A+=0A+=09/*=0A+=09=20= *=20NSS=20initialization=20and=20the=20use=20of=20contexts=20is=20= further=20discussed=20in=0A+=09=20*=20be-secure-nss.c=0A+=09=20*/=0A+=09= memset(¶ms,=200,=20sizeof(params));=0A+=09params.length=20=3D=20= sizeof(params);=0A+=0A+=09if=20(conn->cert_database=20&&=20= strlen(conn->cert_database)=20>=200)=0A+=09{=0A+=09=09char=09=20=20=20= *cert_database_path=20=3D=20psprintf("sql:%s",=20conn->cert_database);=0A= +=0A+=09=09conn->nss_context=20=3D=20NSS_InitContext(cert_database_path,=20= "",=20"",=20"",=0A+=09=09=09=09=09=09=09=09=09=09=09¶ms,=0A+=09=09=09= =09=09=09=09=09=09=09=09NSS_INIT_READONLY=20|=20NSS_INIT_PK11RELOAD);=0A= +=09=09pfree(cert_database_path);=0A+=0A+=09=09if=20(!conn->nss_context)=0A= +=09=09{=0A+=09=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09= =09=09=09=20=20libpq_gettext("unable=20to=20open=20certificate=20= database=20\"%s\":=20%s"),=0A+=09=09=09=09=09=09=09=20=20= conn->cert_database,=0A+=09=09=09=09=09=09=09=20=20= pg_SSLerrmessage(PR_GetError()));=0A+=09=09=09return=20= PGRES_POLLING_FAILED;=0A+=09=09}=0A+=09}=0A+=09else=0A+=09{=0A+=09=09= conn->nss_context=20=3D=20NSS_InitContext("",=20"",=20"",=20"",=20= ¶ms,=0A+=09=09=09=09=09=09=09=09=09=09=09NSS_INIT_READONLY=20|=20= NSS_INIT_NOCERTDB=20|=0A+=09=09=09=09=09=09=09=09=09=09=09= NSS_INIT_NOMODDB=20|=20NSS_INIT_FORCEOPEN=20|=0A+=09=09=09=09=09=09=09=09= =09=09=09NSS_INIT_NOROOTINIT=20|=20NSS_INIT_PK11RELOAD);=0A+=09=09if=20= (!conn->nss_context)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20create=20certificate=20database:=20%s"),=0A= +=09=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09=09= return=20PGRES_POLLING_FAILED;=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20= *=20Configure=20cipher=20policy.=0A+=09=20*/=0A+=09status=20=3D=20= NSS_SetDomesticPolicy();=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09{=0A= +=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20configure=20cipher=20policy:=20%s"),=0A+=09=09= =09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20If=20we=20don't=20= have=20a=20certificate=20database,=20the=20system=20trust=20store=20is=20= the=0A+=09=20*=20fallback=20we=20can=20use.=20If=20we=20fail=20to=20= initialize=20that=20as=20well,=20we=20can=0A+=09=20*=20still=20attempt=20= a=20connection=20as=20long=20as=20the=20sslmode=20isn't=20verify*.=0A+=09= =20*/=0A+=09if=20(!conn->cert_database=20&&=20conn->sslmode[0]=20=3D=3D=20= 'v')=0A+=09{=0A+=09=09status=20=3D=20pg_load_nss_module(&ca_trust,=20= ca_trust_name,=20"\"Root=20Certificates\"");=0A+=09=09if=20(status=20!=3D=20= SECSuccess)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("WARNING:=20unable=20to=20load=20NSS=20trust=20module=20= \"%s\"=20:=20%s"),=0A+=09=09=09=09=09=09=09=20=20ca_trust_name,=0A+=09=09= =09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=0A+=09=09=09= return=20PGRES_POLLING_FAILED;=0A+=09=09}=0A+=09}=0A+=0A+=0A+=09= PK11_SetPasswordFunc(PQssl_passwd_cb);=0A+=0A+=09/*=0A+=09=20*=20Import=20= the=20already=20opened=20socket=20as=20we=20don't=20want=20to=20use=20= NSPR=20functions=0A+=09=20*=20for=20opening=20the=20network=20socket=20= due=20to=20how=20the=20PostgreSQL=20protocol=20works=0A+=09=20*=20with=20= TLS=20connections.=20This=20function=20is=20not=20part=20of=20the=20NSPR=20= public=20API,=0A+=09=20*=20see=20the=20comment=20at=20the=20top=20of=20= the=20file=20for=20the=20rationale=20of=20still=20using=0A+=09=20*=20it.=0A= +=09=20*/=0A+=09pr_fd=20=3D=20PR_ImportTCPSocket(conn->sock);=0A+=09if=20= (!pr_fd)=0A+=09{=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09= =09=09=09=09=20=20libpq_gettext("unable=20to=20attach=20to=20socket:=20= %s"),=0A+=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09= =09return=20PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Most=20= of=20the=20documentation=20available,=20and=20implementations=20of,=20= NSS/NSPR=0A+=09=20*=20use=20the=20PR_NewTCPSocket()=20function=20here,=20= which=20has=20the=20drawback=20that=20it=0A+=09=20*=20can=20only=20= create=20IPv4=20sockets.=20Instead=20use=20PR_OpenTCPSocket()=20which=0A= +=09=20*=20copes=20with=20IPv6=20as=20well.=0A+=09=20*/=0A+=09model=20=3D=20= SSL_ImportFD(NULL,=20PR_OpenTCPSocket(conn->laddr.addr.ss_family));=0A+=09= if=20(!model)=0A+=09{=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A= +=09=09=09=09=09=09=20=20libpq_gettext("unable=20to=20enable=20TLS:=20= %s"),=0A+=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09= =09return=20PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=20Disable=20old=20= protocol=20versions=20(SSLv2=20and=20SSLv3)=20*/=0A+=09= SSL_OptionSet(model,=20SSL_ENABLE_SSL2,=20PR_FALSE);=0A+=09= SSL_OptionSet(model,=20SSL_V2_COMPATIBLE_HELLO,=20PR_FALSE);=0A+=09= SSL_OptionSet(model,=20SSL_ENABLE_SSL3,=20PR_FALSE);=0A+=0A+#ifdef=20= SSL_CBC_RANDOM_IV=0A+=0A+=09/*=0A+=09=20*=20Enable=20protection=20= against=20the=20BEAST=20attack=20in=20case=20the=20NSS=20library=20has=0A= +=09=20*=20support=20for=20that.=20While=20SSLv3=20is=20disabled,=20we=20= may=20still=20allow=20TLSv1=0A+=09=20*=20which=20is=20affected.=20The=20= option=20isn't=20documented=20as=20an=20SSL=20option,=20but=20as=0A+=09=20= *=20an=20NSS=20environment=20variable.=0A+=09=20*/=0A+=09= SSL_OptionSet(model,=20SSL_CBC_RANDOM_IV,=20PR_TRUE);=0A+#endif=0A+=0A+=09= /*=20Set=20us=20up=20as=20a=20TLS=20client=20for=20the=20handshake=20*/=0A= +=09SSL_OptionSet(model,=20SSL_HANDSHAKE_AS_CLIENT,=20PR_TRUE);=0A+=0A+=09= /*=0A+=09=20*=20When=20setting=20the=20available=20protocols,=20we=20= either=20use=20the=20user=20defined=0A+=09=20*=20configuration=20values,=20= and=20if=20missing=20we=20accept=20whatever=20is=20the=20highest=0A+=09=20= *=20version=20supported=20by=20the=20library=20as=20the=20max=20and=20= only=20limit=20the=20range=20in=0A+=09=20*=20the=20other=20end=20at=20= TLSv1.0.=20ssl_variant_stream=20is=20a=20ProtocolVariant=20enum=0A+=09=20= *=20for=20Stream=20protocols,=20rather=20than=20datagram.=0A+=09=20*/=0A= +=09SSL_VersionRangeGetSupported(ssl_variant_stream,=20&desired_range);=0A= +=09desired_range.min=20=3D=20SSL_LIBRARY_VERSION_TLS_1_0;=0A+=0A+=09if=20= (conn->ssl_min_protocol_version=20&&=20= strlen(conn->ssl_min_protocol_version)=20>=200)=0A+=09{=0A+=09=09int=09=09= =09ssl_min_ver=20=3D=20= ssl_protocol_version_to_nss(conn->ssl_min_protocol_version);=0A+=0A+=09=09= if=20(ssl_min_ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("invalid=20value=20\"%s\"=20for=20minimum=20version=20of=20= SSL=20protocol\n"),=0A+=09=09=09=09=09=09=09=20=20= conn->ssl_min_protocol_version);=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=0A= +=09=09desired_range.min=20=3D=20ssl_min_ver;=0A+=09}=0A+=0A+=09if=20= (conn->ssl_max_protocol_version=20&&=20= strlen(conn->ssl_max_protocol_version)=20>=200)=0A+=09{=0A+=09=09int=09=09= =09ssl_max_ver=20=3D=20= ssl_protocol_version_to_nss(conn->ssl_max_protocol_version);=0A+=0A+=09=09= if=20(ssl_max_ver=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("invalid=20value=20\"%s\"=20for=20maximum=20version=20of=20= SSL=20protocol\n"),=0A+=09=09=09=09=09=09=09=20=20= conn->ssl_max_protocol_version);=0A+=09=09=09return=20-1;=0A+=09=09}=0A+=0A= +=09=09desired_range.max=20=3D=20ssl_max_ver;=0A+=09}=0A+=0A+=09if=20= (SSL_VersionRangeSet(model,=20&desired_range)=20!=3D=20SECSuccess)=0A+=09= {=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20= =20libpq_gettext("unable=20to=20set=20allowed=20SSL=20protocol=20version=20= range:=20%s"),=0A+=09=09=09=09=09=09=20=20= pg_SSLerrmessage(PR_GetError()));=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Set=20up=20= callback=20for=20verifying=20server=20certificates,=20as=20well=20as=20= for=20how=0A+=09=20*=20to=20handle=20failed=20verifications.=0A+=09=20*/=0A= +=09SSL_AuthCertificateHook(model,=20pg_cert_auth_handler,=20(void=20*)=20= conn);=0A+=09SSL_BadCertHook(model,=20pg_bad_cert_handler,=20(void=20*)=20= conn);=0A+=0A+=09/*=0A+=09=20*=20Convert=20the=20NSPR=20socket=20to=20an=20= SSL=20socket.=20Ensuring=20the=20success=20of=20this=0A+=09=20*=20= operation=20is=20critical=20as=20NSS=20SSL_*=20functions=20may=20return=20= SECSuccess=20on=0A+=09=20*=20the=20socket=20even=20though=20SSL=20hasn't=20= been=20enabled,=20which=20introduce=20a=20risk=0A+=09=20*=20of=20silent=20= downgrades.=0A+=09=20*/=0A+=09conn->pr_fd=20=3D=20SSL_ImportFD(model,=20= pr_fd);=0A+=09if=20(!conn->pr_fd)=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20configure=20client=20for=20TLS:=20%s"),=0A+=09= =09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20The=20model=20= can=20now=20we=20closed=20as=20we've=20applied=20the=20settings=20of=20= the=20model=0A+=09=20*=20onto=20the=20real=20socket.=20=46rom=20hereon=20= we=20should=20only=20use=20conn->pr_fd.=0A+=09=20*/=0A+=09= PR_Close(model);=0A+=0A+=09/*=20Set=20the=20private=20data=20to=20be=20= passed=20to=20the=20password=20callback=20*/=0A+=09= SSL_SetPKCS11PinArg(conn->pr_fd,=20(void=20*)=20conn);=0A+=0A+=09status=20= =3D=20SSL_ResetHandshake(conn->pr_fd,=20PR_FALSE);=0A+=09if=20(status=20= !=3D=20SECSuccess)=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20initiate=20handshake:=20%s"),=0A+=09=09=09=09= =09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09return=20= PGRES_POLLING_FAILED;=0A+=09}=0A+=0A+=09/*=20Set=20callback=20for=20= client=20authentication=20when=20requested=20by=20the=20server=20*/=0A+=09= SSL_GetClientAuthDataHook(conn->pr_fd,=20pg_client_auth_handler,=20(void=20= *)=20conn);=0A+=0A+=09/*=0A+=09=20*=20Specify=20which=20hostname=20we=20= are=20expecting=20to=20talk=20to.=20This=20is=20required,=0A+=09=20*=20= albeit=20mostly=20applies=20to=20when=20opening=20a=20connection=20to=20= a=20traditional=0A+=09=20*=20http=20server=20it=20seems.=0A+=09=20*/=0A+=09= SSL_SetURL(conn->pr_fd,=20(conn->connhost[conn->whichhost]).host);=0A+=0A= +=09do=0A+=09{=0A+=09=09status=20=3D=20SSL_ForceHandshake(conn->pr_fd);=0A= +=09}=0A+=09while=20(status=20!=3D=20SECSuccess=20&&=20PR_GetError()=20= =3D=3D=20PR_WOULD_BLOCK_ERROR);=0A+=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("SSL=20error:=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+=09conn->ssl_in_use=20=3D=20true;=0A= +=09return=20PGRES_POLLING_OK;=0A+}=0A+=0A+ssize_t=0A+pgtls_read(PGconn=20= *conn,=20void=20*ptr,=20size_t=20len)=0A+{=0A+=09PRInt32=09=09nread;=0A+=09= PRErrorCode=20status;=0A+=09int=09=09=09read_errno=20=3D=200;=0A+=0A+=09= /*=0A+=09=20*=20PR_Recv=20blocks=20until=20there=20is=20data=20to=20read=20= or=20the=20timeout=20expires.=20We=0A+=09=20*=20don't=20want=20to=20sit=20= blocked=20here,=20so=20the=20timeout=20is=20turned=20off=20by=20using=0A= +=09=20*=20PR_INTERVAL_NO_WAIT=20which=20means=20"return=20immediately",=20= =20Zero=20is=20returned=0A+=09=20*=20for=20closed=20connections,=20while=20= -1=20indicates=20an=20error=20within=20the=20ongoing=0A+=09=20*=20= connection.=0A+=09=20*/=0A+=09nread=20=3D=20PR_Recv(conn->pr_fd,=20ptr,=20= len,=200,=20PR_INTERVAL_NO_WAIT);=0A+=0A+=09if=20(nread=20=3D=3D=200)=0A= +=09{=0A+=09=09read_errno=20=3D=20ECONNRESET;=0A+=09=09nread=20=3D=20-1;=0A= +=09}=0A+=09else=20if=20(nread=20=3D=3D=20-1)=0A+=09{=0A+=09=09status=20= =3D=20PR_GetError();=0A+=0A+=09=09switch=20(status)=0A+=09=09{=0A+=09=09=09= case=20PR_IO_TIMEOUT_ERROR:=0A+=09=09=09=09/*=20No=20data=20available=20= yet.=20*/=0A+=09=09=09=09nread=20=3D=200;=0A+=09=09=09=09break;=0A+=0A+=09= =09=09case=20PR_WOULD_BLOCK_ERROR:=0A+=09=09=09=09read_errno=20=3D=20= EWOULDBLOCK;=0A+=09=09=09=09break;=0A+=0A+=09=09=09=09/*=0A+=09=09=09=09=20= *=20The=20error=20cases=20for=20PR_Recv=20are=20not=20documented,=20but=20= can=20be=0A+=09=09=09=09=20*=20reverse=20engineered=20from=20= _MD_unix_map_default_error()=20in=20the=0A+=09=09=09=09=20*=20NSPR=20= code,=20defined=20in=20pr/src/md/unix/unix_errors.c.=0A+=09=09=09=09=20= */=0A+=09=09=09case=20PR_NETWORK_UNREACHABLE_ERROR:=0A+=09=09=09case=20= PR_CONNECT_RESET_ERROR:=0A+=09=09=09=09read_errno=20=3D=20ECONNRESET;=0A= +=09=09=09=09break;=0A+=0A+=09=09=09default:=0A+=09=09=09=09break;=0A+=09= =09}=0A+=0A+=09=09if=20(nread=20=3D=3D=20-1)=0A+=09=09{=0A+=09=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=09=20=20= libpq_gettext("TLS=20read=20error:=20%s"),=0A+=09=09=09=09=09=09=09=20=20= pg_SSLerrmessage(status));=0A+=09=09}=0A+=09}=0A+=0A+=09= SOCK_ERRNO_SET(read_errno);=0A+=09return=20(ssize_t)=20nread;=0A+}=0A+=0A= +/*=0A+=20*=20pgtls_read_pending=0A+=20*=09=09Check=20for=20the=20= existence=20of=20data=20to=20be=20read.=0A+=20*=0A+=20*=20This=20is=20= part=20of=20the=20PostgreSQL=20TLS=20backend=20API.=0A+=20*/=0A+bool=0A= +pgtls_read_pending(PGconn=20*conn)=0A+{=0A+=09unsigned=20char=20c;=0A+=09= int=09=09=09n;=0A+=0A+=09/*=0A+=09=20*=20PR_Recv=20peeks=20into=20the=20= stream=20with=20the=20timeount=20turned=20off,=20to=20see=20if=0A+=09=20= *=20there=20is=20another=20byte=20to=20read=20off=20the=20wire.=20There=20= is=20an=20NSS=20function=0A+=09=20*=20SSL_DataPending()=20which=20might=20= seem=20like=20a=20better=20fit,=20but=20it=20will=20only=0A+=09=20*=20= check=20already=20encrypted=20data=20in=20the=20SSL=20buffer,=20not=20= still=20unencrypted=0A+=09=20*=20data,=20thus=20it=20doesn't=20guarantee=20= that=20a=20subsequent=20call=20to=0A+=09=20*=20PR_Read/PR_Recv=20won't=20= block.=0A+=09=20*/=0A+=09n=20=3D=20PR_Recv(conn->pr_fd,=20&c,=201,=20= PR_MSG_PEEK,=20PR_INTERVAL_NO_WAIT);=0A+=09return=20(n=20>=200);=0A+}=0A= +=0A+ssize_t=0A+pgtls_write(PGconn=20*conn,=20const=20void=20*ptr,=20= size_t=20len)=0A+{=0A+=09PRInt32=09=09n;=0A+=09PRErrorCode=20status;=0A+=09= int=09=09=09write_errno=20=3D=200;=0A+=0A+=09n=20=3D=20= PR_Write(conn->pr_fd,=20ptr,=20len);=0A+=0A+=09if=20(n=20<=200)=0A+=09{=0A= +=09=09status=20=3D=20PR_GetError();=0A+=0A+=09=09switch=20(status)=0A+=09= =09{=0A+=09=09=09case=20PR_WOULD_BLOCK_ERROR:=0A+#ifdef=20EAGAIN=0A+=09=09= =09=09write_errno=20=3D=20EAGAIN;=0A+#else=0A+=09=09=09=09write_errno=20= =3D=20EINTR;=0A+#endif=0A+=09=09=09=09break;=0A+=0A+=09=09=09default:=0A= +=09=09=09=09printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09= =09=09=20=20libpq_gettext("TLS=20write=20error:=20%s"),=0A+=09=09=09=09=09= =09=09=09=20=20pg_SSLerrmessage(status));=0A+=09=09=09=09write_errno=20=3D= =20ECONNRESET;=0A+=09=09=09=09break;=0A+=09=09}=0A+=09}=0A+=0A+=09= SOCK_ERRNO_SET(write_errno);=0A+=09return=20(ssize_t)=20n;=0A+}=0A+=0A= +char=20*=0A+pgtls_get_peer_certificate_hash(PGconn=20*conn,=20size_t=20= *len)=0A+{=0A+=09CERTCertificate=20*server_cert;=0A+=09SECOidTag=09= signature_tag;=0A+=09SECOidTag=09digest_alg;=0A+=09int=09=09=09= digest_len;=0A+=09PLArenaPool=20*arena;=0A+=09SECItem=09=09digest;=0A+=09= char=09=20=20=20*ret;=0A+=09SECStatus=09status;=0A+=0A+=09*len=20=3D=20= 0;=0A+=0A+=09server_cert=20=3D=20SSL_PeerCertificate(conn->pr_fd);=0A+=09= if=20(!server_cert)=0A+=09=09return=20NULL;=0A+=0A+=09signature_tag=20=3D=20= SECOID_GetAlgorithmTag(&server_cert->signature);=0A+=09if=20= (!pg_find_signature_algorithm(signature_tag,=20&digest_alg,=20= &digest_len))=0A+=09{=0A+=09=09printfPQExpBuffer(&conn->errorMessage,=0A= +=09=09=09=09=09=09=20=20libpq_gettext("could=20not=20find=20digest=20= for=20OID=20'%s'\n"),=0A+=09=09=09=09=09=09=20=20= SECOID_FindOIDTagDescription(signature_tag));=0A+=09=09return=20NULL;=0A= +=09}=0A+=0A+=09arena=20=3D=20= PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);=0A+=09digest.data=20=3D=20= PORT_ArenaZAlloc(arena,=20sizeof(unsigned=20char)=20*=20digest_len);=0A+=09= digest.len=20=3D=20digest_len;=0A+=0A+=09status=20=3D=20= PK11_HashBuf(digest_alg,=20digest.data,=20server_cert->derCert.data,=0A+=09= =09=09=09=09=09=20=20server_cert->derCert.len);=0A+=0A+=09if=20(status=20= !=3D=20SECSuccess)=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20generate=20peer=20certificate=20digest:=20= %s"),=0A+=09=09=09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09= =09PORT_FreeArena(arena,=20PR_TRUE);=0A+=09=09return=20NULL;=0A+=09}=0A+=0A= +=09ret=20=3D=20pg_malloc(digest.len);=0A+=09memcpy(ret,=20digest.data,=20= digest.len);=0A+=09*len=20=3D=20digest_len;=0A+=09PORT_FreeArena(arena,=20= PR_TRUE);=0A+=0A+=09return=20ret;=0A+}=0A+=0A+/*=0A+=20*=09Verify=20that=20= the=20server=20certificate=20matches=20the=20hostname=20we=20connected=20= to.=0A+=20*=0A+=20*=20The=20certificate's=20Common=20Name=20and=20= Subject=20Alternative=20Names=20are=20considered.=0A+=20*/=0A+int=0A= +pgtls_verify_peer_name_matches_certificate_guts(PGconn=20*conn,=0A+=09=09= =09=09=09=09=09=09=09=09=09=09int=20*names_examined,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09char=20**first_name)=0A+{=0A+=09char=09=20=20=20= *server_hostname=20=3D=20NULL;=0A+=09CERTCertificate=20*server_cert=20=3D=20= NULL;=0A+=09SECStatus=09status=20=3D=20SECSuccess;=0A+=09SECItem=09=09= altname_item;=0A+=09PLArenaPool=20*arena=20=3D=20NULL;=0A+=09= CERTGeneralName=20*san_list;=0A+=09CERTGeneralName=20*cn;=0A+=0A+=09= server_hostname=20=3D=20SSL_RevealURL(conn->pr_fd);=0A+=09if=20= (!server_hostname=20||=20server_hostname[0]=20=3D=3D=20'\0')=0A+=09=09= goto=20done;=0A+=0A+=09/*=0A+=09=20*=20CERT_VerifyCertName=20will=20= internally=20perform=20RFC=202818=20SubjectAltName=0A+=09=20*=20= verification.=0A+=09=20*/=0A+=09server_cert=20=3D=20= SSL_PeerCertificate(conn->pr_fd);=0A+=09status=20=3D=20= CERT_VerifyCertName(server_cert,=20server_hostname);=0A+=09if=20(status=20= !=3D=20SECSuccess)=0A+=09{=0A+=09=09= printfPQExpBuffer(&conn->errorMessage,=0A+=09=09=09=09=09=09=20=20= libpq_gettext("unable=20to=20verify=20server=20hostname:=20%s"),=0A+=09=09= =09=09=09=09=20=20pg_SSLerrmessage(PR_GetError()));=0A+=09=09goto=20= done;=0A+=09}=0A+=0A+=09status=20=3D=20= CERT_FindCertExtension(server_cert,=20SEC_OID_X509_SUBJECT_ALT_NAME,=0A+=09= =09=09=09=09=09=09=09=09&altname_item);=0A+=09if=20(status=20=3D=3D=20= SECSuccess)=0A+=09{=0A+=09=09arena=20=3D=20= PORT_NewArena(DER_DEFAULT_CHUNKSIZE);=0A+=09=09if=20(!arena)=0A+=09=09{=0A= +=09=09=09status=20=3D=20SECFailure;=0A+=09=09=09goto=20done;=0A+=09=09}=0A= +=09=09san_list=20=3D=20CERT_DecodeAltNameExtension(arena,=20= &altname_item);=0A+=09=09if=20(!san_list)=0A+=09=09{=0A+=09=09=09status=20= =3D=20SECFailure;=0A+=09=09=09goto=20done;=0A+=09=09}=0A+=0A+=09=09for=20= (cn=20=3D=20san_list;=20cn=20!=3D=20san_list;=20cn=20=3D=20= CERT_GetNextGeneralName(cn))=0A+=09=09{=0A+=09=09=09char=09=20=20=20= *alt_name;=0A+=09=09=09int=09=09=09rv;=0A+=09=09=09char=09=09tmp[512];=0A= +=0A+=09=09=09status=20=3D=20CERT_RFC1485_EscapeAndQuote(tmp,=20= sizeof(tmp),=0A+=09=09=09=09=09=09=09=09=09=09=09=09=20(char=20*)=20= cn->name.other.data,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=20= cn->name.other.len);=0A+=0A+=09=09=09if=20(status=20!=3D=20SECSuccess)=0A= +=09=09=09=09goto=20done;=0A+=0A+=09=09=09rv=20=3D=20= pq_verify_peer_name_matches_certificate_name(conn,=20tmp,=0A+=09=09=09=09= =09=09=09=09=09=09=09=09=09=09=09=20=20strlen(tmp),=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=20=20&alt_name);=0A+=09=09=09if=20(alt_name)=0A= +=09=09=09{=0A+=09=09=09=09if=20(!*first_name)=0A+=09=09=09=09=09= *first_name=20=3D=20alt_name;=0A+=09=09=09=09else=0A+=09=09=09=09=09= free(alt_name);=0A+=09=09=09}=0A+=0A+=09=09=09if=20(rv=20=3D=3D=201)=0A+=09= =09=09=09status=20=3D=20SECSuccess;=0A+=09=09=09else=0A+=09=09=09{=0A+=09= =09=09=09status=20=3D=20SECFailure;=0A+=09=09=09=09break;=0A+=09=09=09}=0A= +=09=09}=0A+=09}=0A+=09else=20if=20(PORT_GetError()=20=3D=3D=20= SEC_ERROR_EXTENSION_NOT_FOUND)=0A+=09=09status=20=3D=20SECSuccess;=0A+=09= else=0A+=09=09status=20=3D=20SECSuccess;=0A+=0A+done:=0A+=09/*=20= san_list=20will=20be=20freed=20by=20freeing=20the=20arena=20it=20was=20= allocated=20in=20*/=0A+=09if=20(arena)=0A+=09=09PORT_FreeArena(arena,=20= PR_TRUE);=0A+=09PR_Free(server_hostname);=0A+=0A+=09if=20(status=20=3D=3D=20= SECSuccess)=0A+=09=09return=201;=0A+=0A+=09return=200;=0A+}=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09PostgreSQL=20specific=20TLS=20support=20functions=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +static=20const=20char=20*=0A+pg_SSLerrmessage(PRErrorCode=20errcode)=0A= +{=0A+=09const=20char=20*error;=0A+=0A+=09/*=0A+=09=20*=20Try=20to=20get=20= the=20user=20friendly=20error=20description,=20and=20if=20that=20fails=20= try=0A+=09=20*=20to=20fall=20back=20on=20the=20name=20of=20the=20= PRErrorCode.=0A+=09=20*/=0A+=09error=20=3D=20PR_ErrorToString(errcode,=20= PR_LANGUAGE_I_DEFAULT);=0A+=09if=20(!error)=0A+=09=09error=20=3D=20= PR_ErrorToName(errcode);=0A+=09if=20(error)=0A+=09=09return=20error;=0A+=0A= +=09return=20"unknown=20TLS=20error";=0A+}=0A+=0A+static=20SECStatus=0A= +pg_load_nss_module(SECMODModule=20**module,=20const=20char=20*library,=20= const=20char=20*name)=0A+{=0A+=09SECMODModule=20*mod;=0A+=09char=09=20=20= =20*modulespec;=0A+=0A+=09modulespec=20=3D=20psprintf("library=3D\"%s\",=20= name=3D\"%s\"",=20library,=20name);=0A+=0A+=09/*=0A+=09=20*=20Attempt=20= to=20load=20the=20specified=20module.=20The=20second=20parameter=20is=20= "parent"=0A+=09=20*=20which=20should=20always=20be=20NULL=20for=20= application=20code.=20The=20third=20parameter=0A+=09=20*=20defines=20if=20= loading=20should=20recurse=20which=20is=20only=20applicable=20when=20= loading=0A+=09=20*=20a=20module=20from=20within=20another=20module.=20= This=20hierarchy=20would=20have=20to=20be=0A+=09=20*=20defined=20in=20= the=20modulespec,=20and=20since=20we=20don't=20support=20anything=20but=0A= +=09=20*=20directly=20addressed=20modules=20we=20should=20pass=20= PR_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/*=0A= +=09=20*=20VerifyCertificateNow=20verifies=20the=20validity=20using=20= PR_now=20from=20NSPR=20as=20a=0A+=09=20*=20timestamp=20and=20will=20= perform=20CRL=20and=20OSCP=20revocation=20checks.=20conn->sslcrl=0A+=09=20= *=20does=20not=20impact=20NSS=20connections=20as=20any=20CRL=20in=20the=20= NSS=20database=20will=20be=0A+=09=20*=20used=20automatically.=0A+=09=20= */=0A+=09status=20=3D=20CERT_VerifyCertificateNow((CERTCertDBHandle=20*)=20= CERT_GetDefaultCertDB(),=0A+=09=09=09=09=09=09=09=09=09=20=20=20= server_cert,=0A+=09=09=09=09=09=09=09=09=09=20=20=20checksig,=0A+=09=09=09= =09=09=09=09=09=09=20=20=20certificateUsageSSLServer,=0A+=09=09=09=09=09=09= =09=09=09=20=20=20pin,=0A+=09=09=09=09=09=09=09=09=09=20=20=20NULL);=0A+=0A= +=09/*=0A+=09=20*=20If=20we've=20already=20failed=20validation=20then=20= there=20is=20no=20point=20in=20also=0A+=09=20*=20performing=20the=20= hostname=20check=20for=20verify-full.=0A+=09=20*/=0A+=09if=20(status=20= =3D=3D=20SECSuccess)=0A+=09{=0A+=09=09if=20= (!pq_verify_peer_name_matches_certificate(conn))=0A+=09=09=09status=20=3D=20= SECFailure;=0A+=09}=0A+=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*socket,=20= CERTDistNames=20*caNames,=0A+=09=09=09=09=09=20=20=20CERTCertificate=20= **pRetCert,=20SECKEYPrivateKey=20**pRetKey)=0A+{=0A+=09PGconn=09=20=20=20= *conn=20=3D=20(PGconn=20*)=20arg;=0A+=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*fd)=0A+{=0A= +=09PGconn=09=20=20=20*conn=20=3D=20(PGconn=20*)=20arg;=0A+=09= PRErrorCode=20err;=0A+=0A+=09/*=0A+=09=20*=20This=20really=20shouldn't=20= happen,=20as=20we've=20set=20the=20PGconn=20object=20as=20our=0A+=09=20*=20= callback=20data,=20and=20at=20the=20callsite=20we=20know=20it=20will=20= be=20populated.=20That=0A+=09=20*=20being=20said,=20the=20NSS=20code=20= itself=20performs=20this=20check=20even=20when=20it=20should=0A+=09=20*=20= not=20be=20required=20so=20let's=20use=20the=20same=20belts=20with=20our=20= suspenders.=0A+=09=20*/=0A+=09if=20(!arg)=0A+=09=09return=20SECFailure;=0A= +=0A+=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&&=0A= +=09=09=09strlen(conn->cert_database)=20>=200=20&&=0A+=09=09=09= cert_database_has_CA(conn))=0A+=09=09=09return=20SECFailure;=0A+=09}=0A+=09= if=20(conn->sslmode[0]=20=3D=3D=20'v')=0A+=09=09return=20SECFailure;=0A+=0A= +=09err=20=3D=20PORT_GetError();=0A+=0A+=09/*=0A+=09=20*=20TODO:=20these=20= are=20relevant=20error=20codes=20that=20can=20occur=20in=20certificate=0A= +=09=20*=20validation,=20figure=20out=20which=20we=20don't=20want=20for=20= require/prefer=20etc.=0A+=09=20*/=0A+=09switch=20(err)=0A+=09{=0A+=09=09= case=20SEC_ERROR_INVALID_AVA:=0A+=09=09case=20SEC_ERROR_INVALID_TIME:=0A= +=09=09case=20SEC_ERROR_BAD_SIGNATURE:=0A+=09=09case=20= SEC_ERROR_EXPIRED_CERTIFICATE:=0A+=09=09case=20SEC_ERROR_UNKNOWN_ISSUER:=0A= +=09=09case=20SEC_ERROR_UNTRUSTED_ISSUER:=0A+=09=09case=20= SEC_ERROR_UNTRUSTED_CERT:=0A+=09=09case=20SEC_ERROR_CERT_VALID:=0A+=09=09= case=20SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:=0A+=09=09case=20= SEC_ERROR_CRL_EXPIRED:=0A+=09=09case=20SEC_ERROR_CRL_BAD_SIGNATURE:=0A+=09= =09case=20SEC_ERROR_EXTENSION_VALUE_INVALID:=0A+=09=09case=20= SEC_ERROR_CA_CERT_INVALID:=0A+=09=09case=20= SEC_ERROR_CERT_USAGES_INVALID:=0A+=09=09case=20= SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:=0A+=09=09=09return=20SECSuccess;=0A= +=09=09=09break;=0A+=09=09default:=0A+=09=09=09return=20SECFailure;=0A+=09= =09=09break;=0A+=09}=0A+=0A+=09/*=20Unreachable=20*/=0A+=09return=20= SECSuccess;=0A+}=0A+=0A+/*=20= ------------------------------------------------------------=20*/=0A+/*=09= =09=09=09=09SSL=20information=20functions=09=09=09=09=09*/=0A+/*=20= ------------------------------------------------------------=20*/=0A+=0A= +/*=0A+=20*=20PQgetssl=0A+=20*=0A+=20*=20Return=20NULL=20as=20this=20is=20= legacy=20and=20defined=20to=20always=20be=20equal=20to=20calling=0A+=20*=20= PQsslStruct(conn,=20"OpenSSL");=20This=20should=20ideally=20trigger=20a=20= logged=20warning=0A+=20*=20somewhere=20as=20it's=20nonsensical=20to=20= run=20in=20a=20non-OpenSSL=20build.=0A+=20*/=0A+void=20*=0A= +PQgetssl(PGconn=20*conn)=0A+{=0A+=09return=20NULL;=0A+}=0A+=0A+void=20*=0A= +PQsslStruct(PGconn=20*conn,=20const=20char=20*struct_name)=0A+{=0A+=09= if=20(!conn)=0A+=09=09return=20NULL;=0A+=0A+=09/*=0A+=09=20*=20Return=20= the=20underlying=20PRFileDesc=20which=20can=20be=20used=20to=20access=0A= +=09=20*=20information=20on=20the=20connection=20details.=20There=20is=20= no=20SSL=20context=20per=20se.=0A+=09=20*/=0A+=09if=20= (strcmp(struct_name,=20"NSS")=20=3D=3D=200)=0A+=09=09return=20= conn->pr_fd;=0A+=09return=20NULL;=0A+}=0A+=0A+const=20char=20*const=20*=0A= +PQsslAttributeNames(PGconn=20*conn)=0A+{=0A+=09static=20const=20char=20= *const=20result[]=20=3D=20{=0A+=09=09"library",=0A+=09=09"cipher",=0A+=09= =09"protocol",=0A+=09=09"key_bits",=0A+=09=09"compression",=0A+=09=09= NULL=0A+=09};=0A+=0A+=09return=20result;=0A+}=0A+=0A+const=20char=20*=0A= +PQsslAttribute(PGconn=20*conn,=20const=20char=20*attribute_name)=0A+{=0A= +=09SECStatus=09status;=0A+=09SSLChannelInfo=20channel;=0A+=09= SSLCipherSuiteInfo=20suite;=0A+=0A+=09if=20(!conn=20||=20!conn->pr_fd)=0A= +=09=09return=20NULL;=0A+=0A+=09if=20(strcmp(attribute_name,=20= "library")=20=3D=3D=200)=0A+=09=09return=20"NSS";=0A+=0A+=09status=20=3D=20= SSL_GetChannelInfo(conn->pr_fd,=20&channel,=20sizeof(channel));=0A+=09if=20= (status=20!=3D=20SECSuccess)=0A+=09=09return=20NULL;=0A+=0A+=09status=20= =3D=20SSL_GetCipherSuiteInfo(channel.cipherSuite,=20&suite,=20= sizeof(suite));=0A+=09if=20(status=20!=3D=20SECSuccess)=0A+=09=09return=20= NULL;=0A+=0A+=09if=20(strcmp(attribute_name,=20"cipher")=20=3D=3D=200)=0A= +=09=09return=20suite.cipherSuiteName;=0A+=0A+=09if=20= (strcmp(attribute_name,=20"key_bits")=20=3D=3D=200)=0A+=09{=0A+=09=09= static=20char=20key_bits_str[8];=0A+=0A+=09=09snprintf(key_bits_str,=20= sizeof(key_bits_str),=20"%i",=20suite.effectiveKeyBits);=0A+=09=09return=20= key_bits_str;=0A+=09}=0A+=0A+=09if=20(strcmp(attribute_name,=20= "protocol")=20=3D=3D=200)=0A+=09{=0A+=09=09switch=20= (channel.protocolVersion)=0A+=09=09{=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_3=0A+=09=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_3:=0A+=09=09=09=09return=20"TLSv1.3";=0A= +#endif=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_2=0A+=09=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_2:=0A+=09=09=09=09return=20"TLSv1.2";=0A= +#endif=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_1=0A+=09=09=09case=20= SSL_LIBRARY_VERSION_TLS_1_1:=0A+=09=09=09=09return=20"TLSv1.1";=0A= +#endif=0A+=09=09=09case=20SSL_LIBRARY_VERSION_TLS_1_0:=0A+=09=09=09=09= return=20"TLSv1.0";=0A+=09=09=09default:=0A+=09=09=09=09return=20= "unknown";=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20NSS=20disabled=20= support=20for=20compression=20in=20version=203.33,=20and=20it=20was=20= only=0A+=09=20*=20available=20for=20SSLv3=20at=20that=20point=20anyways,=20= so=20we=20can=20safely=20return=20off=0A+=09=20*=20here=20without=20= checking.=0A+=09=20*/=0A+=09if=20(strcmp(attribute_name,=20= "compression")=20=3D=3D=200)=0A+=09=09return=20"off";=0A+=0A+=09return=20= NULL;=0A+}=0A+=0A+static=20int=0A+ssl_protocol_version_to_nss(const=20= char=20*protocol)=0A+{=0A+=09if=20(pg_strcasecmp("TLSv1",=20protocol)=20= =3D=3D=200)=0A+=09=09return=20SSL_LIBRARY_VERSION_TLS_1_0;=0A+=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_1=0A+=09if=20(pg_strcasecmp("TLSv1.1",=20= protocol)=20=3D=3D=200)=0A+=09=09return=20SSL_LIBRARY_VERSION_TLS_1_1;=0A= +#endif=0A+=0A+#ifdef=20SSL_LIBRARY_VERSION_TLS_1_2=0A+=09if=20= (pg_strcasecmp("TLSv1.2",=20protocol)=20=3D=3D=200)=0A+=09=09return=20= SSL_LIBRARY_VERSION_TLS_1_2;=0A+#endif=0A+=0A+#ifdef=20= SSL_LIBRARY_VERSION_TLS_1_3=0A+=09if=20(pg_strcasecmp("TLSv1.3",=20= protocol)=20=3D=3D=200)=0A+=09=09return=20SSL_LIBRARY_VERSION_TLS_1_3;=0A= +#endif=0A+=0A+=09return=20-1;=0A+}=0A+=0A+/*=0A+=20*=20= cert_database_has_CA=0A+=20*=09=09=20Check=20for=20the=20presence=20of=20= a=20CA=20certificate=0A+=20*=0A+=20*=20Returns=20true=20in=20case=20= there=20is=20a=20CA=20certificate=20in=20the=20database=20connected=0A+=20= *=20to=20in=20the=20conn=20object,=20else=20false.=20This=20function=20= only=20checks=20for=20the=0A+=20*=20presence=20of=20a=20CA=20= certificate,=20not=20it's=20validity=20and/or=20usefulness.=0A+=20*/=0A= +static=20bool=0A+cert_database_has_CA(PGconn=20*conn)=0A+{=0A+=09= CERTCertList=20*certificates;=0A+=09bool=09=09hasCA;=0A+=0A+=09/*=0A+=09=20= *=20If=20the=20certificate=20database=20has=20a=20password=20we=20must=20= provide=20it,=20since=0A+=09=20*=20this=20API=20doesn't=20invoke=20the=20= standard=20password=20callback.=0A+=09=20*/=0A+=09if=20= (conn->has_password)=0A+=09=09certificates=20=3D=20= PK11_ListCerts(PK11CertListCA,=20PQssl_passwd_cb(NULL,=20PR_FALSE,=20= (void=20*)=20conn));=0A+=09else=0A+=09=09certificates=20=3D=20= PK11_ListCerts(PK11CertListCA,=20NULL);=0A+=09hasCA=20=3D=20= !CERT_LIST_EMPTY(certificates);=0A+=09= CERT_DestroyCertList(certificates);=0A+=0A+=09return=20hasCA;=0A+}=0A+=0A= +PQsslKeyPassHook_nss_type=0A+PQgetSSLKeyPassHook_nss(void)=0A+{=0A+=09= return=20PQsslKeyPassHook;=0A+}=0A+=0A+void=0A= +PQsetSSLKeyPassHook_nss(PQsslKeyPassHook_nss_type=20hook)=0A+{=0A+=09= PQsslKeyPassHook=20=3D=20hook;=0A+}=0A+=0A+/*=0A+=20*=20PQssl_passwd_cb=0A= +=20*=09=09=20Supply=20a=20password=20to=20decrypt=20an=20object=0A+=20*=0A= +=20*=20If=20an=20object=20in=20the=20NSS=20database=20is=20password=20= protected,=20or=20if=20the=20entire=0A+=20*=20NSS=20database=20is=20= itself=20password=20protected,=20this=20callback=20will=20be=20invoked.=0A= +=20*=0A+=20*=20This=20must=20match=20NSS=20type=20PK11PasswordFunc.=0A+=20= */=0A+static=20char=20*=0A+PQssl_passwd_cb(PK11SlotInfo=20*slot,=20= PRBool=20retry,=20void=20*arg)=0A+{=0A+=09PGconn=09=20=20=20*conn=20=3D=20= (PGconn=20*)=20arg;=0A+=0A+=09conn->has_password=20=3D=20true;=0A+=0A+=09= if=20(PQsslKeyPassHook)=0A+=09=09return=20PQsslKeyPassHook(slot,=20= (PRBool)=20retry,=20arg);=0A+=09else=0A+=09=09return=20= PQdefaultSSLKeyPassHook_nss(slot,=20retry,=20arg);=0A+}=0A+=0A+/*=0A+=20= *=20PQdefaultSSLKeyPassHook_nss=0A+=20*=20=09=09=20Default=20password=20= handler=20callback=0A+=20*=0A+=20*=20If=20no=20user=20defined=20password=20= callback=20has=20been=20set=20up,=20the=20callback=20below=0A+=20*=20= will=20try=20the=20password=20set=20by=20the=20sslpassword=20parameter.=20= Since=20we=20by=20legacy=0A+=20*=20only=20have=20support=20for=20a=20= single=20password,=20there=20is=20little=20reason=20to=20inspect=0A+=20*=20= the=20slot=20for=20the=20object=20in=20question.=20A=20TODO=20is=20to=20= support=20different=0A+=20*=20passwords=20for=20different=20objects,=20= either=20via=20a=20DSL=20in=20sslpassword=20or=20with=20a=0A+=20*=20new=20= key/value=20style=20parameter.=20Users=20can=20supply=20their=20own=20= password=20hook=20to=0A+=20*=20do=20this=20of=20course,=20but=20it=20= would=20be=20nice=20to=20support=20something=20in=20core=20too.=0A+=20*/=0A= +char=20*=0A+PQdefaultSSLKeyPassHook_nss(PK11SlotInfo=20*slot,=20PRBool=20= retry,=20void=20*arg)=0A+{=0A+=09PGconn=09=20=20=20*conn=20=3D=20(PGconn=20= *)=20arg;=0A+=0A+=09/*=0A+=09=20*=20If=20the=20password=20didn't=20work=20= the=20first=20time=20there=20is=20no=20point=20in=0A+=09=20*=20retrying=20= as=20it=20hasn't=20changed.=0A+=09=20*/=0A+=09if=20(retry=20!=3D=20= PR_TRUE=20&&=20conn->sslpassword=20&&=20strlen(conn->sslpassword)=20>=20= 0)=0A+=09=09return=20PORT_Strdup(conn->sslpassword);=0A+=0A+=09return=20= NULL;=0A+}=0Adiff=20--git=20a/src/interfaces/libpq/fe-secure.c=20= b/src/interfaces/libpq/fe-secure.c=0Aindex=20c601071838..7f10da3010=20= 100644=0A---=20a/src/interfaces/libpq/fe-secure.c=0A+++=20= b/src/interfaces/libpq/fe-secure.c=0A@@=20-448,6=20+448,27=20@@=20= PQdefaultSSLKeyPassHook_OpenSSL(char=20*buf,=20int=20size,=20PGconn=20= *conn)=0A=20}=0A=20#endif=09=09=09=09=09=09=09/*=20USE_OPENSSL=20*/=0A=20= =0A+#ifndef=20USE_NSS=0A+=0A+PQsslKeyPassHook_nss_type=0A= +PQgetSSLKeyPassHook_nss(void)=0A+{=0A+=09return=20NULL;=0A+}=0A+=0A= +void=0A+PQsetSSLKeyPassHook_nss(PQsslKeyPassHook_nss_type=20hook)=0A+{=0A= +=09return;=0A+}=0A+=0A+char=20*=0A= +PQdefaultSSLKeyPassHook_nss(PK11SlotInfo=20*=20slot,=20PRBool=20retry,=20= void=20*arg)=0A+{=0A+=09return=20NULL;=0A+}=0A+#endif=09=09=09=09=09=09=09= /*=20USE_NSS=20*/=0A+=0A=20/*=20Dummy=20version=20of=20GSSAPI=20= information=20functions,=20when=20built=20without=20GSS=20support=20*/=0A= =20#ifndef=20ENABLE_GSS=0A=20=0Adiff=20--git=20= a/src/interfaces/libpq/libpq-fe.h=20b/src/interfaces/libpq/libpq-fe.h=0A= index=20effe0ccf85..aba32e6635=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*slot,=20PRBool=20retry,=20void=20*arg);=0A+extern=20= PQsslKeyPassHook_nss_type=20PQgetSSLKeyPassHook_nss(void);=0A+extern=20= void=20PQsetSSLKeyPassHook_nss(PQsslKeyPassHook_nss_type=20hook);=0A= +extern=20char=20*PQdefaultSSLKeyPassHook_nss(PK11SlotInfo=20*slot,=20= PRBool=20retry,=20void=20*arg);=0A+=0A=20#ifdef=20__cplusplus=0A=20}=0A=20= #endif=0Adiff=20--git=20a/src/interfaces/libpq/libpq-int.h=20= b/src/interfaces/libpq/libpq-int.h=0Aindex=20ce36aabd25..d7103f0bf2=20= 100644=0A---=20a/src/interfaces/libpq/libpq-int.h=0A+++=20= b/src/interfaces/libpq/libpq-int.h=0A@@=20-363,6=20+363,7=20@@=20struct=20= pg_conn=0A=20=09char=09=20=20=20*sslrootcert;=09/*=20root=20certificate=20= filename=20*/=0A=20=09char=09=20=20=20*sslcrl;=09=09=09/*=20certificate=20= revocation=20list=20filename=20*/=0A=20=09char=09=20=20=20*sslcrldir;=09=09= /*=20certificate=20revocation=20list=20directory=20name=20*/=0A+=09char=09= =20=20=20*cert_database;=09/*=20NSS=20certificate/key=20database=20*/=0A=20= =09char=09=20=20=20*requirepeer;=09/*=20required=20peer=20credentials=20= for=20local=20sockets=20*/=0A=20=09char=09=20=20=20*gssencmode;=09=09/*=20= GSS=20mode=20(require,prefer,disable)=20*/=0A=20=09char=09=20=20=20= *krbsrvname;=09=09/*=20Kerberos=20service=20name=20*/=0A@@=20-486,6=20= +487,28=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+/*=0A+=20*=20The=20NSS/NSPR=20specific=20= types=20aren't=20used=20to=20avoid=20pulling=20in=20the=20required=0A+=20= *=20headers=20here,=20as=20they=20are=20causing=20conflicts=20with=20PG=20= definitions.=0A+=20*/=0A+#ifdef=20USE_NSS=0A+=09void=09=20=20=20= *nss_context;=09/*=20NSS=20connection=20specific=20context=20*/=0A+=09= void=09=20=20=20*pr_fd;=09=09=09/*=20NSPR=20file=20descriptor=20for=20= the=20connection=20*/=0A+=0A+=09/*=0A+=09=20*=20Track=20whether=20the=20= NSS=20database=20has=20a=20password=20set=20or=20not.=20There=20is=20no=0A= +=09=20*=20API=20function=20for=20retrieving=20password=20status=20of=20= a=20database,=20but=20we=20need=0A+=09=20*=20to=20know=20since=20some=20= NSS=20API=20calls=20require=20the=20password=20passed=20in=20(they=0A+=09= =20*=20don't=20call=20the=20callback=20themselves).=20To=20track,=20we=20= simply=20flip=20this=20to=0A+=09=20*=20true=20in=20case=20NSS=20invoked=20= the=20password=20callback=20-=20as=20that=20will=20only=0A+=09=20*=20= happen=20in=20case=20there=20is=20a=20password.=20The=20reason=20for=20= tracking=20this=20is=0A+=09=20*=20that=20there=20are=20calls=20which=20= require=20a=20password=20parameter,=20but=20doesn't=0A+=09=20*=20use=20= the=20callbacks=20provided,=20so=20we=20must=20call=20the=20callback=20= on=20behalf=20of=0A+=09=20*=20these.=0A+=09=20*/=0A+=09bool=09=09= has_password;=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=20= ENABLE_GSS=0A@@=20-760,7=20+783,7=20@@=20extern=20ssize_t=20= pgtls_write(PGconn=20*conn,=20const=20void=20*ptr,=20size_t=20len);=0A=20= =20*=20This=20is=20not=20supported=20with=20old=20versions=20of=20= OpenSSL=20that=20don't=20have=0A=20=20*=20the=20X509_get_signature_nid()=20= function.=0A=20=20*/=0A-#if=20defined(USE_OPENSSL)=20&&=20= defined(HAVE_X509_GET_SIGNATURE_NID)=0A+#if=20defined(USE_NSS)=20||=20= (defined(USE_OPENSSL)=20&&=20defined(HAVE_X509_GET_SIGNATURE_NID))=0A=20= #define=20HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH=0A=20extern=20char=20= *pgtls_get_peer_certificate_hash(PGconn=20*conn,=20size_t=20*len);=0A=20= #endif=0A--=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_7600E0A4-7DC9-42B3-8E52-7D25F61B1EB5--