The Samba-Bugzilla – Attachment 17181 Details for
Bug 14995
Use Heimdal 8.0 (pre) rather than an earlier snapshot
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patches for v4-16-test
bfixes-tmp416.txt (text/plain), 1.43 MB, created by
Stefan Metzmacher
on 2022-03-02 08:08:43 UTC
(
hide
)
Description:
Patches for v4-16-test
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2022-03-02 08:08:43 UTC
Size:
1.43 MB
patch
obsolete
>From 427af907b41aed7742faf50605e24c880ae6b661 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 25 Feb 2022 07:40:17 +0100 >Subject: [PATCH 01/22] s4:sam: Don't use talloc_steal for msg attributes in > authsam_make_user_info_dc() > >This is most likely not a problem for the current callers, >but that it is unexpected and will likely cause problems with future >changes. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14993 >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit f6fe86924c2ca756083d3628d5dbace0b12d06b0) >--- > source4/auth/sam.c | 19 ++++++++++++++----- > 1 file changed, 14 insertions(+), 5 deletions(-) > >diff --git a/source4/auth/sam.c b/source4/auth/sam.c >index 93b41be3b210..8b233bab3ad8 100644 >--- a/source4/auth/sam.c >+++ b/source4/auth/sam.c >@@ -454,12 +454,15 @@ _PUBLIC_ NTSTATUS authsam_make_user_info_dc(TALLOC_CTX *mem_ctx, > user_info_dc->info = info = talloc_zero(user_info_dc, struct auth_user_info); > NT_STATUS_HAVE_NO_MEMORY(user_info_dc->info); > >- info->account_name = talloc_steal(info, >- ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL)); >+ str = ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL); >+ info->account_name = talloc_strdup(info, str); >+ if (info->account_name == NULL) { >+ TALLOC_FREE(user_info_dc); >+ return NT_STATUS_NO_MEMORY; >+ } > >- info->user_principal_name = talloc_steal(info, >- ldb_msg_find_attr_as_string(msg, "userPrincipalName", NULL)); >- if (info->user_principal_name == NULL && dns_domain_name != NULL) { >+ str = ldb_msg_find_attr_as_string(msg, "userPrincipalName", NULL); >+ if (str == NULL && dns_domain_name != NULL) { > info->user_principal_name = talloc_asprintf(info, "%s@%s", > info->account_name, > dns_domain_name); >@@ -468,6 +471,12 @@ _PUBLIC_ NTSTATUS authsam_make_user_info_dc(TALLOC_CTX *mem_ctx, > return NT_STATUS_NO_MEMORY; > } > info->user_principal_constructed = true; >+ } else if (str != NULL) { >+ info->user_principal_name = talloc_strdup(info, str); >+ if (info->user_principal_name == NULL) { >+ TALLOC_FREE(user_info_dc); >+ return NT_STATUS_NO_MEMORY; >+ } > } > > info->domain_name = talloc_strdup(info, domain_name); >-- >2.25.1 > > >From 3ede4a087c41455a86925b0273454303e77c7bb7 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 22 Feb 2022 14:15:43 +1300 >Subject: [PATCH 02/22] auth: Cope with NULL upn_name in PAC > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit ef95fb439237910b945b8d6a3ad4a140a8d6d1ea) >--- > auth/auth_sam_reply.c | 12 +++++++----- > 1 file changed, 7 insertions(+), 5 deletions(-) > >diff --git a/auth/auth_sam_reply.c b/auth/auth_sam_reply.c >index b5b6362dc93b..fda014c87d5c 100644 >--- a/auth/auth_sam_reply.c >+++ b/auth/auth_sam_reply.c >@@ -616,11 +616,13 @@ NTSTATUS make_user_info_dc_pac(TALLOC_CTX *mem_ctx, > } > > if (pac_upn_dns_info != NULL) { >- user_info_dc->info->user_principal_name = >- talloc_strdup(user_info_dc->info, >- pac_upn_dns_info->upn_name); >- if (user_info_dc->info->user_principal_name == NULL) { >- return NT_STATUS_NO_MEMORY; >+ if (pac_upn_dns_info->upn_name != NULL) { >+ user_info_dc->info->user_principal_name = >+ talloc_strdup(user_info_dc->info, >+ pac_upn_dns_info->upn_name); >+ if (user_info_dc->info->user_principal_name == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } > } > > user_info_dc->info->dns_domain_name = >-- >2.25.1 > > >From eefa0d127244baabc761e319b48e7eadbf31e1a4 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 22 Feb 2022 15:30:17 +1300 >Subject: [PATCH 03/22] third_party/heimdal_build: Add KDC_LIB macro > definitions > >This is an adaptation to Heimdal: > >commit 7bb00a40eabbed2bc1c268f5244bfb9736d9bebe >Author: Luke Howard <lukeh@padl.com> >Date: Tue Jan 4 13:08:35 2022 +1100 > > kdc: fix Windows build > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 6d8fec7006e8eadf5967a6f2f5add7d3c2c7bd3e) >--- > third_party/heimdal_build/wscript_build | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/third_party/heimdal_build/wscript_build b/third_party/heimdal_build/wscript_build >index 7780f9c13246..cf7c2b9a3428 100644 >--- a/third_party/heimdal_build/wscript_build >+++ b/third_party/heimdal_build/wscript_build >@@ -445,7 +445,7 @@ if not bld.CONFIG_SET("USING_SYSTEM_KDC"): > includes='../heimdal/kdc', > deps='roken krb5 hdb asn1 HEIMDAL_DIGEST_ASN1 HEIMDAL_KX509_ASN1 heimntlm hcrypto com_err wind heimbase gssapi gss_preauth', > version_script='kdc/version-script.map') >- HEIMDAL_AUTOPROTO('kdc/kdc-protos.h', KDC_SOURCE) >+ HEIMDAL_AUTOPROTO('kdc/kdc-protos.h', KDC_SOURCE, options='-E KDC_LIB -q -P comment -o') > HEIMDAL_AUTOPROTO_PRIVATE('kdc/kdc-private.h', KDC_SOURCE) > > if not bld.CONFIG_SET("USING_SYSTEM_HEIMNTLM"): >-- >2.25.1 > > >From 8eef2f08b6d932228471c28c8f0d54b03747f7cf Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Thu, 24 Feb 2022 15:30:17 +1300 >Subject: [PATCH 04/22] s4:kdc: Don't pass empty PAC buffers to > krb5_pac_add_buffer() > >Heimdal will no longer allow us to pass a dummy zero-length buffer to >krb5_pac_add_buffer(), so we have to pass a buffer of length 1 instead. > >This is an adaption to Heimdal: > >commit 190263bb7a56fc775b50a6cd0dc91820d2b2e5eb >Author: Jeffrey Altman <jaltman@secure-endpoints.com> >Date: Wed Jan 19 22:55:33 2022 -0500 > > assert non-NULL ptrs before calling mem funcs > > The definitions of memcpy(), memmove(), and memset() state that > the behaviour is undefined if any of the pointer arguments are > NULL, and some compilers are known to make use of this to > optimise away existing NULL checks in the source. > > Change-Id: I489bc256e3eac7ff41d91becb0b43aba73dbb3f9 > Link: https://www.imperialviolet.org/2016/06/26/nonnull.html > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 9936038fae72fb440864be543e9afd500444d502) >--- > source4/kdc/pac-glue.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > >diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c >index eac1612ca2b3..dc6db122865f 100644 >--- a/source4/kdc/pac-glue.c >+++ b/source4/kdc/pac-glue.c >@@ -517,9 +517,10 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, > krb5_data deleg_data; > krb5_error_code ret; > #ifdef SAMBA4_USES_HEIMDAL >+ char null_byte = '\0'; > krb5_data null_data = { >- .length = 0, >- .data = NULL, >+ .length = 1, >+ .data = &null_byte, > }; > #endif > >-- >2.25.1 > > >From 519964dc463efeb5b0b3dce98c61d030251635b9 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Thu, 24 Feb 2022 15:24:13 +1300 >Subject: [PATCH 05/22] third_party/heimdal_build: Determine whether time_t is > signed > >Without this, Heimdal will assume time_t is unsigned, and a wrong >assumption will cause 'infinite' ticket lifetimes to be reckoned as from >the past, and thus requests will fail with KDC_ERR_NEVER_VALID. > >This is an adaptation to Heimdal: > >commit 9ae9902249732237aa1711591604a6adf24963fe >Author: Nicolas Williams <nico@twosigma.com> >Date: Tue Feb 15 17:01:00 2022 -0600 > > cf: Check if time_t is signed > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> > >Autobuild-User(master): Stefan Metzmacher <metze@samba.org> >Autobuild-Date(master): Tue Mar 1 18:07:50 UTC 2022 on sn-devel-184 > >(cherry picked from commit 9eb27f296ae2b797803fffbb7f4cb34d8eb06f34) >--- > buildtools/wafsamba/samba_autoconf.py | 17 +++++++++++++++++ > third_party/heimdal_build/wscript_configure | 2 ++ > 2 files changed, 19 insertions(+) > >diff --git a/buildtools/wafsamba/samba_autoconf.py b/buildtools/wafsamba/samba_autoconf.py >index 8b4998252302..78927d851937 100644 >--- a/buildtools/wafsamba/samba_autoconf.py >+++ b/buildtools/wafsamba/samba_autoconf.py >@@ -343,6 +343,23 @@ def CHECK_SIZEOF(conf, vars, headers=None, define=None, critical=True): > sys.exit(1) > return ret > >+@conf >+def CHECK_SIGN(conf, v, headers=None): >+ '''check the sign of a type''' >+ define_name = v.upper().replace(' ', '_') >+ for op, signed in [('<', 'signed'), >+ ('>', 'unsigned')]: >+ if CHECK_CODE(conf, >+ f'static int test_array[1 - 2 * !((({v})-1) {op} 0)];', >+ define=f'{define_name}_{signed.upper()}', >+ quote=False, >+ headers=headers, >+ local_include=False, >+ msg=f"Checking if '{v}' is {signed}"): >+ return True >+ >+ return False >+ > @conf > def CHECK_VALUEOF(conf, v, headers=None, define=None): > '''check the value of a variable/define''' >diff --git a/third_party/heimdal_build/wscript_configure b/third_party/heimdal_build/wscript_configure >index 023935d98c0d..0021cd328ecf 100644 >--- a/third_party/heimdal_build/wscript_configure >+++ b/third_party/heimdal_build/wscript_configure >@@ -206,3 +206,5 @@ if conf.CONFIG_SET('USING_EMBEDDED_HEIMDAL'): > conf.define('HAVE_KRB5_ADDLOG_FUNC_NEED_CONTEXT', 1) > else: > pass # TODO >+ >+conf.CHECK_SIGN('time_t') >-- >2.25.1 > > >From f11bc828b0eed6b119ebef446171d63541237f24 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 22 Feb 2022 16:41:52 +1300 >Subject: [PATCH 06/22] third_party/heimdal_build: Define fallthrough macro for > switch statements > >This is an adaptation to Heimdal: > >commit ddc61136100b32346c4c4efa2bb6ddb5baedfb3e >Author: Nicolas Williams <nico@twosigma.com> >Date: Fri Jan 14 16:32:04 2022 -0600 > > Use fallthrough statement attribute > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit fccf9859786dfb50b317ea2296c2494997f0ae09) >--- > third_party/heimdal_build/config.h | 2 ++ > 1 file changed, 2 insertions(+) > >diff --git a/third_party/heimdal_build/config.h b/third_party/heimdal_build/config.h >index d9ba31b3b45e..42b11ace11f5 100644 >--- a/third_party/heimdal_build/config.h >+++ b/third_party/heimdal_build/config.h >@@ -64,4 +64,6 @@ > #define HAVE_STRSEP 1 > #endif > >+#define fallthrough FALL_THROUGH >+ > #endif >-- >2.25.1 > > >From 2792109ddcab2d43348fd0546650a69312d91fea Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 1 Mar 2022 14:17:54 +1300 >Subject: [PATCH 07/22] third_party/heimdal: import > lorikeet-heimdal-202203010107 (commit > 0e7a12404c388e831fe6933fcc3c86e7eb334825) > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 51569b3152a952d07fddaa3a70d60c920618c704) >--- > .../heimdal/.github/workflows/build.yml | 67 - > third_party/heimdal/.gitignore | 236 ++- > third_party/heimdal/Makefile.am | 1 - > third_party/heimdal/README.md | 9 +- > third_party/heimdal/admin/change.c | 1 - > third_party/heimdal/appl/afsutil/afslog.c | 2 +- > third_party/heimdal/appl/gssmask/gssmask.c | 2 + > third_party/heimdal/appl/kf/kf.c | 4 +- > third_party/heimdal/appl/otp/otp.c | 12 +- > third_party/heimdal/appl/test/gssapi_server.c | 23 +- > third_party/heimdal/appl/test/uu_server.c | 7 + > third_party/heimdal/appveyor.yml | 72 +- > third_party/heimdal/cf/Makefile.am.common | 19 +- > third_party/heimdal/cf/ax_check_sign.m4 | 54 + > third_party/heimdal/cf/check-compile-flag.m4 | 53 + > third_party/heimdal/cf/db.m4 | 6 +- > third_party/heimdal/cf/krb-prog-yacc.m4 | 12 +- > third_party/heimdal/cf/roken-frag.m4 | 6 - > third_party/heimdal/configure.ac | 38 +- > third_party/heimdal/import-lorikeet.sh | 22 +- > third_party/heimdal/include/Makefile.am | 33 +- > third_party/heimdal/include/bits.c | 51 +- > third_party/heimdal/include/config.h.w32 | 37 +- > third_party/heimdal/kadmin/add-random-users.c | 2 +- > third_party/heimdal/kadmin/add_enctype.c | 4 +- > third_party/heimdal/kadmin/ank.c | 40 +- > third_party/heimdal/kadmin/cpw.c | 16 +- > third_party/heimdal/kadmin/del.c | 12 +- > third_party/heimdal/kadmin/ext.c | 2 +- > third_party/heimdal/kadmin/get.c | 2 + > third_party/heimdal/kadmin/init.c | 202 ++- > third_party/heimdal/kadmin/kadm_conn.c | 9 +- > third_party/heimdal/kadmin/kadmin.1 | 33 +- > third_party/heimdal/kadmin/kadmind.c | 2 + > third_party/heimdal/kadmin/load.c | 54 +- > third_party/heimdal/kadmin/mod.c | 15 +- > third_party/heimdal/kadmin/rpc.c | 4 +- > third_party/heimdal/kadmin/server.c | 315 ++-- > third_party/heimdal/kadmin/stash.c | 5 +- > third_party/heimdal/kcm/cache.c | 10 +- > third_party/heimdal/kcm/client.c | 37 + > third_party/heimdal/kcm/glue.c | 2 +- > third_party/heimdal/kcm/protocol.c | 24 +- > third_party/heimdal/kdc/Makefile.am | 14 +- > third_party/heimdal/kdc/NTMakefile | 18 +- > .../kdc/altsecid_gss_preauth_authorizer.c | 85 +- > third_party/heimdal/kdc/bx509d.c | 170 ++- > third_party/heimdal/kdc/ca.c | 4 +- > .../heimdal/kdc/cjwt_token_validator.c | 9 +- > third_party/heimdal/kdc/config.c | 2 +- > third_party/heimdal/kdc/connect.c | 19 +- > third_party/heimdal/kdc/csr_authorizer.c | 2 +- > third_party/heimdal/kdc/default_config.c | 5 +- > third_party/heimdal/kdc/digest-service.c | 9 +- > third_party/heimdal/kdc/digest.c | 46 +- > third_party/heimdal/kdc/fast.c | 35 +- > third_party/heimdal/kdc/gss_preauth.c | 78 +- > .../kdc/gss_preauth_authorizer_plugin.h | 6 +- > third_party/heimdal/kdc/headers.h | 3 +- > third_party/heimdal/kdc/hprop.8 | 1 - > third_party/heimdal/kdc/hprop.c | 23 +- > third_party/heimdal/kdc/hprop.h | 18 +- > third_party/heimdal/kdc/hpropd.8 | 3 - > third_party/heimdal/kdc/hpropd.c | 11 +- > third_party/heimdal/kdc/httpkadmind.c | 73 +- > third_party/heimdal/kdc/ipc_csr_authorizer.c | 20 +- > third_party/heimdal/kdc/kdc-accessors.h | 349 +++++ > third_party/heimdal/kdc/{rx.h => kdc-audit.h} | 68 +- > third_party/heimdal/kdc/kdc-plugin.c | 658 +++++++++ > third_party/heimdal/kdc/kdc-plugin.h | 136 ++ > third_party/heimdal/kdc/kdc-replay.c | 2 + > third_party/heimdal/kdc/kdc.h | 168 +-- > third_party/heimdal/kdc/kdc_locl.h | 109 +- > third_party/heimdal/kdc/kerberos5.c | 691 ++++----- > third_party/heimdal/kdc/krb5tgs.c | 946 ++++-------- > third_party/heimdal/kdc/kstash.c | 2 + > third_party/heimdal/kdc/kx509.c | 130 +- > third_party/heimdal/kdc/libkdc-exports.def | 83 +- > third_party/heimdal/kdc/log.c | 10 +- > third_party/heimdal/kdc/misc.c | 103 +- > third_party/heimdal/kdc/mit_dump.c | 6 +- > third_party/heimdal/kdc/mssfu.c | 568 ++++++++ > .../heimdal/kdc/negotiate_token_validator.c | 2 - > third_party/heimdal/kdc/pkinit.c | 30 +- > third_party/heimdal/kdc/process.c | 204 ++- > third_party/heimdal/kdc/set_dbinfo.c | 2 +- > .../heimdal/kdc/simple_csr_authorizer.c | 24 +- > third_party/heimdal/kdc/string2key.c | 6 +- > third_party/heimdal/kdc/test_kdc_ca.c | 5 +- > third_party/heimdal/kdc/token_validator.c | 2 +- > third_party/heimdal/kdc/version-script.map | 78 +- > third_party/heimdal/kdc/windc.c | 252 ---- > third_party/heimdal/kdc/windc_plugin.h | 92 -- > third_party/heimdal/kpasswd/kpasswdd.c | 2 + > third_party/heimdal/kuser/generate-requests.c | 2 +- > third_party/heimdal/kuser/kgetcred.c | 3 + > third_party/heimdal/kuser/kimpersonate.c | 27 +- > third_party/heimdal/kuser/kinit.c | 34 +- > third_party/heimdal/kuser/klist.c | 15 +- > third_party/heimdal/kuser/kswitch.c | 5 +- > third_party/heimdal/kuser/kuser_locl.h | 4 + > third_party/heimdal/lib/asn1/MANUAL.md | 1287 +++++++++++++++++ > third_party/heimdal/lib/asn1/Makefile.am | 361 ++--- > third_party/heimdal/lib/asn1/NTMakefile | 281 ++-- > third_party/heimdal/lib/asn1/README.md | 326 +++-- > third_party/heimdal/lib/asn1/asn1-template.h | 75 +- > third_party/heimdal/lib/asn1/asn1_compile.1 | 263 +++- > third_party/heimdal/lib/asn1/asn1_print.c | 32 +- > third_party/heimdal/lib/asn1/asn1parse.y | 141 +- > third_party/heimdal/lib/asn1/check-common.h | 3 +- > third_party/heimdal/lib/asn1/check-der.c | 2 + > third_party/heimdal/lib/asn1/check-gen.c | 144 +- > third_party/heimdal/lib/asn1/check-gen.h | 9 + > third_party/heimdal/lib/asn1/check-template.c | 13 + > third_party/heimdal/lib/asn1/der_copy.c | 103 +- > third_party/heimdal/lib/asn1/der_get.c | 92 +- > third_party/heimdal/lib/asn1/der_put.c | 68 +- > third_party/heimdal/lib/asn1/extra.c | 8 +- > third_party/heimdal/lib/asn1/gen.c | 186 ++- > third_party/heimdal/lib/asn1/gen_copy.c | 47 +- > third_party/heimdal/lib/asn1/gen_decode.c | 6 +- > third_party/heimdal/lib/asn1/gen_encode.c | 29 +- > third_party/heimdal/lib/asn1/gen_free.c | 55 +- > third_party/heimdal/lib/asn1/gen_glue.c | 11 +- > third_party/heimdal/lib/asn1/gen_locl.h | 17 +- > third_party/heimdal/lib/asn1/gen_template.c | 172 ++- > third_party/heimdal/lib/asn1/krb5.asn1 | 46 +- > third_party/heimdal/lib/asn1/krb5.opt | 2 + > .../heimdal/lib/asn1/libasn1-exports.def | 6 + > third_party/heimdal/lib/asn1/main.c | 240 ++- > third_party/heimdal/lib/asn1/oid_resolution.c | 75 +- > third_party/heimdal/lib/asn1/symbol.h | 5 +- > third_party/heimdal/lib/asn1/template.c | 56 +- > third_party/heimdal/lib/asn1/test.asn1 | 12 +- > third_party/heimdal/lib/asn1/test.opt | 6 + > third_party/heimdal/lib/base/array.c | 4 +- > third_party/heimdal/lib/base/bsearch.c | 24 +- > third_party/heimdal/lib/base/data.c | 9 +- > third_party/heimdal/lib/base/db.c | 24 +- > third_party/heimdal/lib/base/dict.c | 8 +- > third_party/heimdal/lib/base/dll.c | 3 +- > third_party/heimdal/lib/base/error.c | 4 +- > third_party/heimdal/lib/base/error_string.c | 7 +- > third_party/heimdal/lib/base/expand_path.c | 58 +- > third_party/heimdal/lib/base/heimbase-svc.h | 8 +- > third_party/heimdal/lib/base/heimbase.c | 35 +- > third_party/heimdal/lib/base/heimbase.h | 9 +- > third_party/heimdal/lib/base/heimbasepriv.h | 3 +- > third_party/heimdal/lib/base/log.c | 363 ++++- > third_party/heimdal/lib/base/number.c | 22 +- > third_party/heimdal/lib/base/plugin.c | 16 +- > third_party/heimdal/lib/base/string.c | 6 +- > third_party/heimdal/lib/base/test_base.c | 6 +- > .../heimdal/lib/base/version-script.map | 7 + > third_party/heimdal/lib/com_err/Makefile.am | 2 +- > .../heimdal/lib/gss_preauth/pa_client.c | 3 +- > .../heimdal/lib/gss_preauth/pa_common.c | 5 - > third_party/heimdal/lib/gssapi/Makefile.am | 55 +- > third_party/heimdal/lib/gssapi/NTMakefile | 38 +- > third_party/heimdal/lib/gssapi/gss-token.c | 11 +- > .../heimdal/lib/gssapi/gssapi/gssapi.h | 16 +- > .../heimdal/lib/gssapi/gssapi/gssapi_krb5.h | 2 + > .../lib/gssapi/krb5/accept_sec_context.c | 140 +- > .../heimdal/lib/gssapi/krb5/acquire_cred.c | 52 +- > third_party/heimdal/lib/gssapi/krb5/arcfour.c | 13 +- > .../heimdal/lib/gssapi/krb5/copy_ccache.c | 5 +- > .../lib/gssapi/krb5/export_sec_context.c | 2 +- > .../heimdal/lib/gssapi/krb5/external.c | 19 +- > .../heimdal/lib/gssapi/krb5/import_name.c | 35 +- > .../lib/gssapi/krb5/init_sec_context.c | 41 +- > .../heimdal/lib/gssapi/krb5/name_attrs.c | 1171 +++++++++++++++ > .../heimdal/lib/gssapi/krb5/store_cred.c | 5 +- > .../heimdal/lib/gssapi/krb5/test_kcred.c | 6 +- > .../heimdal/lib/gssapi/libgssapi-exports.def | 2 +- > .../lib/gssapi/mech/gss_compare_name.c | 10 +- > .../heimdal/lib/gssapi/mech/gss_cred.c | 6 +- > .../lib/gssapi/mech/gss_export_sec_context.c | 4 + > .../heimdal/lib/gssapi/mech/gss_import_name.c | 82 +- > .../lib/gssapi/mech/gss_import_sec_context.c | 6 +- > .../heimdal/lib/gssapi/mech/gss_krb5.c | 7 +- > .../heimdal/lib/gssapi/mech/gss_mech_switch.c | 47 +- > .../lib/gssapi/mech/gss_pname_to_uid.c | 4 + > .../heimdal/lib/gssapi/mech/mech_locl.h | 11 +- > .../lib/gssapi/ntlm/accept_sec_context.c | 2 + > third_party/heimdal/lib/gssapi/ntlm/creds.c | 4 - > third_party/heimdal/lib/gssapi/ntlm/crypto.c | 5 +- > .../lib/gssapi/ntlm/delete_sec_context.c | 6 + > .../lib/gssapi/ntlm/init_sec_context.c | 22 +- > third_party/heimdal/lib/gssapi/ntlm/kdc.c | 1 + > .../heimdal/lib/gssapi/sanon/import_name.c | 25 +- > .../lib/gssapi/spnego/accept_sec_context.c | 1 + > .../heimdal/lib/gssapi/spnego/negoex_ctx.c | 28 +- > third_party/heimdal/lib/gssapi/test_context.c | 168 ++- > third_party/heimdal/lib/gssapi/test_kcred.c | 18 +- > third_party/heimdal/lib/gssapi/test_names.c | 464 +++++- > .../heimdal/lib/gssapi/version-script.map | 2 +- > third_party/heimdal/lib/hcrypto/Makefile.am | 27 +- > third_party/heimdal/lib/hcrypto/bn.c | 8 +- > third_party/heimdal/lib/hcrypto/des.c | 1 + > third_party/heimdal/lib/hcrypto/dh-ltm.c | 57 +- > third_party/heimdal/lib/hcrypto/dh.c | 2 +- > third_party/heimdal/lib/hcrypto/engine.c | 35 +- > third_party/heimdal/lib/hcrypto/evp.c | 9 +- > third_party/heimdal/lib/hcrypto/hmac.c | 28 +- > third_party/heimdal/lib/hcrypto/hmac.h | 2 +- > .../lib/hcrypto/libtommath/bn_mp_set_double.c | 2 +- > .../libtommath/bn_s_mp_rand_platform.c | 2 +- > .../lib/hcrypto/libtommath/demo/test.c | 2 +- > .../heimdal/lib/hcrypto/libtommath/etc/tune.c | 2 +- > third_party/heimdal/lib/hcrypto/rsa-ltm.c | 7 +- > third_party/heimdal/lib/hcrypto/rsa.c | 7 +- > third_party/heimdal/lib/hcrypto/test_hmac.c | 6 +- > third_party/heimdal/lib/hcrypto/validate.c | 3 +- > third_party/heimdal/lib/hdb/Makefile.am | 67 +- > third_party/heimdal/lib/hdb/NTMakefile | 12 +- > third_party/heimdal/lib/hdb/common.c | 375 +++-- > third_party/heimdal/lib/hdb/db.c | 22 +- > third_party/heimdal/lib/hdb/db3.c | 22 +- > third_party/heimdal/lib/hdb/ext.c | 4 +- > third_party/heimdal/lib/hdb/hdb-keytab.c | 22 +- > third_party/heimdal/lib/hdb/hdb-ldap.c | 363 ++--- > third_party/heimdal/lib/hdb/hdb-mdb.c | 22 +- > third_party/heimdal/lib/hdb/hdb-mitdb.c | 89 +- > third_party/heimdal/lib/hdb/hdb-sqlite.c | 39 +- > third_party/heimdal/lib/hdb/hdb.asn1 | 2 +- > third_party/heimdal/lib/hdb/hdb.c | 98 +- > third_party/heimdal/lib/hdb/hdb.h | 175 +-- > third_party/heimdal/lib/hdb/hdb.opt | 5 + > third_party/heimdal/lib/hdb/keys.c | 2 +- > third_party/heimdal/lib/hdb/keytab.c | 50 +- > .../heimdal/lib/hdb/libhdb-exports.def | 1 - > third_party/heimdal/lib/hdb/ndbm.c | 53 +- > third_party/heimdal/lib/hdb/print.c | 20 +- > .../heimdal/lib/hdb/test_concurrency.c | 58 +- > third_party/heimdal/lib/hdb/test_namespace.c | 162 +-- > .../heimdal/lib/hdb/version-script.map | 1 - > third_party/heimdal/lib/hx509/Makefile.am | 3 +- > third_party/heimdal/lib/hx509/ca.c | 21 +- > third_party/heimdal/lib/hx509/cert.c | 42 +- > third_party/heimdal/lib/hx509/cms.c | 6 +- > third_party/heimdal/lib/hx509/collector.c | 3 +- > third_party/heimdal/lib/hx509/crypto.c | 4 + > third_party/heimdal/lib/hx509/error.c | 66 +- > third_party/heimdal/lib/hx509/file.c | 12 +- > third_party/heimdal/lib/hx509/hxtool.c | 28 +- > third_party/heimdal/lib/hx509/keyset.c | 5 +- > third_party/heimdal/lib/hx509/ks_file.c | 29 +- > third_party/heimdal/lib/hx509/name.c | 71 +- > third_party/heimdal/lib/hx509/print.c | 5 + > third_party/heimdal/lib/hx509/req.c | 22 +- > third_party/heimdal/lib/hx509/revoke.c | 4 + > third_party/heimdal/lib/hx509/sel-gram.y | 4 + > third_party/heimdal/lib/hx509/softp11.c | 8 +- > third_party/heimdal/lib/ipc/Makefile.am | 4 + > third_party/heimdal/lib/ipc/server.c | 15 +- > third_party/heimdal/lib/kadm5/ad.c | 2 + > third_party/heimdal/lib/kadm5/chpass_s.c | 56 +- > third_party/heimdal/lib/kadm5/context_s.c | 16 +- > third_party/heimdal/lib/kadm5/create_s.c | 32 +- > third_party/heimdal/lib/kadm5/delete_s.c | 8 +- > third_party/heimdal/lib/kadm5/ent_setup.c | 78 +- > third_party/heimdal/lib/kadm5/get_princs_s.c | 8 +- > third_party/heimdal/lib/kadm5/get_s.c | 143 +- > third_party/heimdal/lib/kadm5/init_c.c | 12 +- > third_party/heimdal/lib/kadm5/init_s.c | 6 +- > third_party/heimdal/lib/kadm5/iprop-log.c | 67 +- > third_party/heimdal/lib/kadm5/ipropd_common.c | 1 + > third_party/heimdal/lib/kadm5/ipropd_master.c | 31 +- > third_party/heimdal/lib/kadm5/ipropd_slave.c | 8 +- > third_party/heimdal/lib/kadm5/log.c | 172 ++- > third_party/heimdal/lib/kadm5/marshall.c | 254 ++-- > third_party/heimdal/lib/kadm5/modify_s.c | 12 +- > third_party/heimdal/lib/kadm5/prune_s.c | 10 +- > third_party/heimdal/lib/kadm5/randkey_c.c | 2 +- > third_party/heimdal/lib/kadm5/randkey_s.c | 26 +- > third_party/heimdal/lib/kadm5/rename_s.c | 32 +- > third_party/heimdal/lib/kadm5/set_keys.c | 2 + > third_party/heimdal/lib/kadm5/setkey3_s.c | 28 +- > third_party/heimdal/lib/kafs/Makefile.am | 2 + > third_party/heimdal/lib/kafs/afskrb5.c | 2 - > third_party/heimdal/lib/kafs/afssys.c | 2 + > third_party/heimdal/lib/kafs/rxkad_kdf.c | 8 +- > third_party/heimdal/lib/krb5/Makefile.am | 4 +- > third_party/heimdal/lib/krb5/NTMakefile | 2 + > third_party/heimdal/lib/krb5/acache.c | 27 +- > third_party/heimdal/lib/krb5/acl.c | 2 +- > third_party/heimdal/lib/krb5/addr_families.c | 19 +- > third_party/heimdal/lib/krb5/aes-test.c | 22 +- > third_party/heimdal/lib/krb5/asn1_glue.c | 94 +- > third_party/heimdal/lib/krb5/auth_context.c | 5 +- > third_party/heimdal/lib/krb5/cache.c | 25 +- > third_party/heimdal/lib/krb5/context.c | 15 +- > third_party/heimdal/lib/krb5/crypto-evp.c | 7 +- > third_party/heimdal/lib/krb5/crypto.c | 7 +- > third_party/heimdal/lib/krb5/data.c | 7 +- > third_party/heimdal/lib/krb5/dcache.c | 14 +- > third_party/heimdal/lib/krb5/deprecated.c | 10 +- > third_party/heimdal/lib/krb5/enomem.c | 2 +- > third_party/heimdal/lib/krb5/error_string.c | 19 +- > third_party/heimdal/lib/krb5/expand_path.c | 4 +- > third_party/heimdal/lib/krb5/fast.c | 13 +- > third_party/heimdal/lib/krb5/fcache.c | 15 +- > .../heimdal/lib/krb5/generate_subkey.c | 2 +- > third_party/heimdal/lib/krb5/get_cred.c | 54 +- > third_party/heimdal/lib/krb5/get_in_tkt.c | 2 +- > third_party/heimdal/lib/krb5/init_creds_pw.c | 147 +- > third_party/heimdal/lib/krb5/kcm.c | 267 +++- > third_party/heimdal/lib/krb5/keytab.c | 68 +- > third_party/heimdal/lib/krb5/keytab_file.c | 3 +- > third_party/heimdal/lib/krb5/keytab_keyfile.c | 2 +- > third_party/heimdal/lib/krb5/krb5.conf.5 | 6 - > third_party/heimdal/lib/krb5/krb5.h | 116 +- > third_party/heimdal/lib/krb5/krb5_locl.h | 2 + > third_party/heimdal/lib/krb5/krbhst-test.c | 17 +- > third_party/heimdal/lib/krb5/krbhst.c | 24 +- > third_party/heimdal/lib/krb5/krcache.c | 31 +- > third_party/heimdal/lib/krb5/kx509.c | 62 +- > .../heimdal/lib/krb5/libkrb5-exports.def.in | 7 + > third_party/heimdal/lib/krb5/mcache.c | 4 +- > third_party/heimdal/lib/krb5/mk_cred.c | 15 +- > third_party/heimdal/lib/krb5/pac.c | 137 +- > third_party/heimdal/lib/krb5/pkinit.c | 21 +- > third_party/heimdal/lib/krb5/principal.c | 33 +- > third_party/heimdal/lib/krb5/rd_cred.c | 2 +- > third_party/heimdal/lib/krb5/rd_req.c | 66 +- > third_party/heimdal/lib/krb5/replay.c | 4 +- > third_party/heimdal/lib/krb5/salt-arcfour.c | 6 +- > third_party/heimdal/lib/krb5/scache.c | 91 +- > third_party/heimdal/lib/krb5/send_to_kdc.c | 14 +- > third_party/heimdal/lib/krb5/sp800-108-kdf.c | 5 +- > third_party/heimdal/lib/krb5/store.c | 24 +- > third_party/heimdal/lib/krb5/store_emem.c | 25 +- > third_party/heimdal/lib/krb5/store_stdio.c | 2 + > third_party/heimdal/lib/krb5/test_alname.c | 2 +- > third_party/heimdal/lib/krb5/test_ap-req.c | 1 + > third_party/heimdal/lib/krb5/test_cc.c | 10 +- > third_party/heimdal/lib/krb5/test_hostname.c | 4 +- > third_party/heimdal/lib/krb5/test_rfc3961.c | 1 + > third_party/heimdal/lib/krb5/test_set_kvno0.c | 5 +- > third_party/heimdal/lib/krb5/ticket.c | 91 +- > third_party/heimdal/lib/krb5/transited.c | 19 +- > third_party/heimdal/lib/krb5/verify_user.c | 13 +- > .../heimdal/lib/krb5/version-script.map | 7 + > third_party/heimdal/lib/ntlm/digest.c | 2 +- > third_party/heimdal/lib/ntlm/ntlm.c | 75 +- > third_party/heimdal/lib/otp/otp_md.c | 4 +- > third_party/heimdal/lib/roken/Makefile.am | 6 +- > third_party/heimdal/lib/roken/base32-test.c | 3 +- > third_party/heimdal/lib/roken/base32.c | 12 +- > third_party/heimdal/lib/roken/base64-test.c | 3 +- > third_party/heimdal/lib/roken/base64.c | 4 +- > third_party/heimdal/lib/roken/copyhostent.c | 3 +- > third_party/heimdal/lib/roken/detach.c | 3 +- > third_party/heimdal/lib/roken/dirent-test.c | 6 +- > third_party/heimdal/lib/roken/environment.c | 15 +- > third_party/heimdal/lib/roken/fnmatch.c | 2 +- > third_party/heimdal/lib/roken/freeaddrinfo.c | 2 +- > third_party/heimdal/lib/roken/freehostent.c | 2 +- > third_party/heimdal/lib/roken/getaddrinfo.c | 10 +- > third_party/heimdal/lib/roken/getcap.c | 996 ------------- > .../heimdal/lib/roken/getipnodebyaddr.c | 2 +- > .../heimdal/lib/roken/getipnodebyname.c | 2 +- > third_party/heimdal/lib/roken/getnameinfo.c | 8 +- > third_party/heimdal/lib/roken/getuserinfo.c | 30 +- > third_party/heimdal/lib/roken/hex-test.c | 35 +- > third_party/heimdal/lib/roken/hex.c | 28 +- > third_party/heimdal/lib/roken/mergesort_r.c | 4 +- > third_party/heimdal/lib/roken/ndbm_wrap.c | 2 + > third_party/heimdal/lib/roken/net_write.c | 7 +- > third_party/heimdal/lib/roken/resolve-test.c | 2 +- > third_party/heimdal/lib/roken/roken-common.h | 6 + > third_party/heimdal/lib/roken/roken.h.in | 60 +- > third_party/heimdal/lib/roken/snprintf.c | 2 +- > third_party/heimdal/lib/roken/socket.c | 29 +- > third_party/heimdal/lib/roken/strftime.c | 7 +- > third_party/heimdal/lib/roken/strptime.c | 2 +- > third_party/heimdal/lib/roken/strtoll.c | 3 + > third_party/heimdal/lib/roken/strtoull.c | 3 + > .../heimdal/lib/roken/test-getuserinfo.c | 3 +- > .../heimdal/lib/roken/test-mini_inetd.c | 2 +- > third_party/heimdal/lib/roken/timeval.c | 215 ++- > .../heimdal/lib/roken/version-script.map | 5 +- > third_party/heimdal/lib/roken/vis.c | 17 +- > third_party/heimdal/lib/sl/Makefile.am | 2 +- > third_party/heimdal/lib/sl/sl.c | 2 + > third_party/heimdal/lib/sl/slc-gram.y | 1 + > third_party/heimdal/lib/wind/idn-lookup.c | 6 +- > third_party/heimdal/lib/wind/utf8.c | 18 +- > .../packages/windows/installer/NTMakefile | 33 +- > .../windows/installer/heimdal-installer.wxs | 20 +- > third_party/heimdal/tests/bin/setup-env.in | 1 + > third_party/heimdal/tests/gss/Makefile.am | 2 + > third_party/heimdal/tests/gss/check-basic.in | 4 +- > .../heimdal/tests/gss/check-context.in | 12 +- > .../heimdal/tests/gss/check-gssmask.in | 4 +- > third_party/heimdal/tests/gss/check-ntlm.in | 4 +- > third_party/heimdal/tests/gss/check-spnego.in | 4 +- > third_party/heimdal/tests/gss/krb5.conf.in | 15 + > third_party/heimdal/tests/java/check-kinit.in | 2 +- > third_party/heimdal/tests/kdc/Makefile.am | 32 +- > third_party/heimdal/tests/kdc/check-bx509.in | 5 +- > third_party/heimdal/tests/kdc/check-canon.in | 2 +- > third_party/heimdal/tests/kdc/check-cc.in | 47 +- > .../heimdal/tests/kdc/check-delegation.in | 2 +- > third_party/heimdal/tests/kdc/check-des.in | 2 +- > third_party/heimdal/tests/kdc/check-digest.in | 2 +- > third_party/heimdal/tests/kdc/check-fast.in | 2 +- > .../heimdal/tests/kdc/check-hdb-mitdb.in | 2 +- > .../heimdal/tests/kdc/check-httpkadmind.in | 2 +- > third_party/heimdal/tests/kdc/check-iprop.in | 2 +- > third_party/heimdal/tests/kdc/check-kadmin.in | 2 +- > third_party/heimdal/tests/kdc/check-kdc.in | 9 +- > third_party/heimdal/tests/kdc/check-kinit.in | 2 +- > .../heimdal/tests/kdc/check-kpasswdd.in | 2 +- > third_party/heimdal/tests/kdc/check-pkinit.in | 4 +- > .../heimdal/tests/kdc/check-referral.in | 2 +- > third_party/heimdal/tests/kdc/check-tester.in | 3 + > third_party/heimdal/tests/kdc/check-uu.in | 2 +- > .../heimdal/tests/kdc/krb5-kcm.conf.in | 165 +++ > third_party/heimdal/tests/kdc/krb5.conf.in | 3 + > third_party/heimdal/tests/ldap/check-ldap.in | 2 +- > third_party/heimdal/tests/plugin/Makefile.am | 6 +- > third_party/heimdal/tests/plugin/check-pac.in | 6 +- > .../heimdal/tests/plugin/kdc_test_plugin.c | 207 +++ > third_party/heimdal/tests/plugin/krb5.conf.in | 15 + > third_party/heimdal/tests/plugin/windc.c | 161 --- > third_party/heimdal/windows/NTMakefile.sdk | 130 ++ > third_party/heimdal/windows/NTMakefile.w32 | 7 +- > 428 files changed, 14519 insertions(+), 7392 deletions(-) > delete mode 100644 third_party/heimdal/.github/workflows/build.yml > create mode 100644 third_party/heimdal/cf/ax_check_sign.m4 > create mode 100644 third_party/heimdal/cf/check-compile-flag.m4 > create mode 100644 third_party/heimdal/kdc/kdc-accessors.h > rename third_party/heimdal/kdc/{rx.h => kdc-audit.h} (50%) > create mode 100644 third_party/heimdal/kdc/kdc-plugin.c > create mode 100644 third_party/heimdal/kdc/kdc-plugin.h > create mode 100644 third_party/heimdal/kdc/mssfu.c > delete mode 100644 third_party/heimdal/kdc/windc.c > delete mode 100644 third_party/heimdal/kdc/windc_plugin.h > create mode 100644 third_party/heimdal/lib/asn1/MANUAL.md > create mode 100644 third_party/heimdal/lib/asn1/check-gen.h > create mode 100644 third_party/heimdal/lib/gssapi/krb5/name_attrs.c > create mode 100644 third_party/heimdal/lib/hdb/hdb.opt > delete mode 100644 third_party/heimdal/lib/roken/getcap.c > create mode 100644 third_party/heimdal/tests/kdc/krb5-kcm.conf.in > create mode 100644 third_party/heimdal/tests/plugin/kdc_test_plugin.c > delete mode 100644 third_party/heimdal/tests/plugin/windc.c > create mode 100644 third_party/heimdal/windows/NTMakefile.sdk > >diff --git a/third_party/heimdal/.github/workflows/build.yml b/third_party/heimdal/.github/workflows/build.yml >deleted file mode 100644 >index c9d4d9e79815..000000000000 >--- a/third_party/heimdal/.github/workflows/build.yml >+++ /dev/null >@@ -1,67 +0,0 @@ >-name: Build >- >-on: >- push: {paths: [src/**, .github/workflows/build.yml]} >- pull_request: {paths: [src/**, .github/workflows/build.yml]} >- >-jobs: >- >- unix: >- runs-on: ${{ matrix.os }} >- strategy: >- fail-fast: false >- matrix: >- name: [linux-clang, linux-gcc] >- include: >- - name: linux-clang >- os: ubuntu-18.04 >- compiler: clang >- - name: linux-gcc >- os: ubuntu-18.04 >- compiler: gcc >- steps: >- - name: Clone repository >- uses: actions/checkout@v1 >- - name: Install packages >- if: startsWith(matrix.os, 'ubuntu') >- run: | >- sudo apt-get update -qq >- sudo apt-get install -y bison comerr-dev flex libcap-ng-dev libdb-dev libedit-dev libjson-perl libldap2-dev libncurses5-dev libperl4-corelibs-perl libsqlite3-dev libkeyutils-dev pkg-config python ss-dev texinfo unzip netbase keyutils ldap-utils gdb apport curl libmicrohttpd-dev jq valgrind >- # Temporary workaround for: >- # https://github.com/actions/virtual-environments/issues/3185 >- sudo hostname localhost >- - name: Build >- env: >- CC: ${{ matrix.compiler }} >- MAKEVARS: ${{ matrix.makevars }} >- CONFIGURE_OPTS: ${{ matrix.configureopts }} >- run: | >- /bin/sh ./autogen.sh >- mkdir build >- cd build >- ../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst CFLAGS="-Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations" >- ulimit -c unlimited >- make -j4 >- make check >- make install >- - name: Valgrind output >- run: | >- find . -name \*.log -print0|xargs -0 grep '^==[1-9]' || true >- - name: Core dump stacks >- run: | >- echo "thread apply all bt" > /tmp/x >- find . -name core -print | while read core; do gdb -batch -x x `file "$core"|sed -e "s/^[^']*'//" -e "s/[ '].*$//"` "$core"; done >- if [ "$(find . -name core -print | wc -l)" -gt 0 ]; then false; fi >- - name: Test logs >- if: ${{ failure() }} >- run: | >- find build -name \*.trs|xargs grep -lw FAIL|sed -e 's/trs$/log/'|xargs cat >- - name: distclean >- run: | >- cd build >- make distclean >- if [ "$(git ls-files -o|grep -v ^build/ | wc -l)" -ne 0 ]; then >- echo "Files not removed by make distclean:" >- git ls-files -o|grep -v ^build/ >- fi >- >diff --git a/third_party/heimdal/.gitignore b/third_party/heimdal/.gitignore >index 2a09f94ac80d..e5b52468af54 100644 >--- a/third_party/heimdal/.gitignore >+++ b/third_party/heimdal/.gitignore >@@ -15,20 +15,17 @@ > Makefile > Makefile.in > rs_state.ini >-asn1_*.[cx] > tags > !/lib/asn1/asn1_gen.c > !/lib/asn1/asn1_print.c > !/lib/krb5/asn1_glue.c > *_asn1.h > !/lib/asn1/heim_asn1.h >-*_asn1.hx > *_asn1-priv.h >-*_asn1-priv.hx >-*_asn1-template.c >-*_asn1-template.x >+asn1_*_asn1.c > *_asn1_files > *_asn1_oids.x >+*_asn1_syms.x > *_err.[ch] > !/lib/com_err/com_err.[ch] > *-commands.[ch] >@@ -153,6 +150,9 @@ tags > /kdc/kdc-tester > /kdc/kstash > /kdc/string2key >+/kdc/test_csr_authorizer >+/kdc/test_kdc_ca >+/kdc/test_token_validator > /kpasswd/kpasswd > /kpasswd/kpasswd-generator > /kpasswd/kpasswdd >@@ -176,13 +176,106 @@ tags > /lib/asn1/check-ber > /lib/asn1/check-der > /lib/asn1/check-gen >+/lib/asn1/check-gen-template > /lib/asn1/check-template > /lib/asn1/check-timegm >-/lib/asn1/der-protos.h >+/lib/asn1/cms_asn1.json >+/lib/asn1/cms_asn1_oids.c >+/lib/asn1/cms_asn1_syms.c >+/lib/asn1/cms_template_asn1.json >+/lib/asn1/cms_template_asn1_oids.c >+/lib/asn1/cms_template_asn1_syms.c >+/lib/asn1/crmf_asn1.json >+/lib/asn1/crmf_asn1_oids.c >+/lib/asn1/crmf_asn1_syms.c >+/lib/asn1/crmf_template_asn1.json >+/lib/asn1/crmf_template_asn1_oids.c >+/lib/asn1/crmf_template_asn1_syms.c > /lib/asn1/der-private.h >+/lib/asn1/der-protos.h >+/lib/asn1/digest_asn1.json >+/lib/asn1/digest_asn1_oids.c >+/lib/asn1/digest_asn1_syms.c >+/lib/asn1/digest_template_asn1.json >+/lib/asn1/digest_template_asn1_oids.c >+/lib/asn1/digest_template_asn1_syms.c >+/lib/asn1/krb5_asn1.json >+/lib/asn1/krb5_asn1_oids.c >+/lib/asn1/krb5_asn1_syms.c >+/lib/asn1/krb5_template_asn1.json >+/lib/asn1/krb5_template_asn1_oids.c >+/lib/asn1/krb5_template_asn1_syms.c >+/lib/asn1/kx509_asn1.json >+/lib/asn1/kx509_asn1_oids.c >+/lib/asn1/kx509_asn1_syms.c >+/lib/asn1/kx509_template_asn1.json >+/lib/asn1/kx509_template_asn1_oids.c >+/lib/asn1/kx509_template_asn1_syms.c > /lib/asn1/lex.c >+/lib/asn1/ocsp_asn1.json >+/lib/asn1/ocsp_asn1_oids.c >+/lib/asn1/ocsp_asn1_syms.c >+/lib/asn1/ocsp_template_asn1.json >+/lib/asn1/ocsp_template_asn1_oids.c >+/lib/asn1/ocsp_template_asn1_syms.c >+/lib/asn1/pkcs10_asn1.json >+/lib/asn1/pkcs10_asn1_oids.c >+/lib/asn1/pkcs10_asn1_syms.c >+/lib/asn1/pkcs10_template_asn1.json >+/lib/asn1/pkcs10_template_asn1_oids.c >+/lib/asn1/pkcs10_template_asn1_syms.c >+/lib/asn1/pkcs12_asn1.json >+/lib/asn1/pkcs12_asn1_oids.c >+/lib/asn1/pkcs12_asn1_syms.c >+/lib/asn1/pkcs12_template_asn1.json >+/lib/asn1/pkcs12_template_asn1_oids.c >+/lib/asn1/pkcs12_template_asn1_syms.c >+/lib/asn1/pkcs8_asn1.json >+/lib/asn1/pkcs8_asn1_oids.c >+/lib/asn1/pkcs8_asn1_syms.c >+/lib/asn1/pkcs8_template_asn1.json >+/lib/asn1/pkcs8_template_asn1_oids.c >+/lib/asn1/pkcs8_template_asn1_syms.c >+/lib/asn1/pkcs9_asn1.json >+/lib/asn1/pkcs9_asn1_oids.c >+/lib/asn1/pkcs9_asn1_syms.c >+/lib/asn1/pkcs9_template_asn1.json >+/lib/asn1/pkcs9_template_asn1_oids.c >+/lib/asn1/pkcs9_template_asn1_syms.c >+/lib/asn1/pkinit_asn1.json >+/lib/asn1/pkinit_asn1_oids.c >+/lib/asn1/pkinit_asn1_syms.c >+/lib/asn1/pkinit_template_asn1.json >+/lib/asn1/pkinit_template_asn1_oids.c >+/lib/asn1/pkinit_template_asn1_syms.c >+/lib/asn1/rfc2459_asn1.json >+/lib/asn1/rfc2459_asn1_oids.c >+/lib/asn1/rfc2459_asn1_syms.c >+/lib/asn1/rfc2459_template_asn1.json >+/lib/asn1/rfc2459_template_asn1_oids.c >+/lib/asn1/rfc2459_template_asn1_syms.c >+/lib/asn1/rfc4108_asn1.json >+/lib/asn1/rfc4108_asn1_oids.c >+/lib/asn1/rfc4108_asn1_syms.c >+/lib/asn1/rfc4108_template_asn1.json >+/lib/asn1/rfc4108_template_asn1_oids.c >+/lib/asn1/rfc4108_template_asn1_syms.c >+/lib/asn1/test_asn1.json >+/lib/asn1/test_asn1_oids.c >+/lib/asn1/test_asn1_syms.c >+/lib/asn1/test_template_asn1.json >+/lib/asn1/test_template_asn1_oids.c >+/lib/asn1/test_template_asn1_syms.c >+/lib/asn1/x690sample_asn1.json >+/lib/asn1/x690sample_asn1_oids.c >+/lib/asn1/x690sample_asn1_syms.c >+/lib/asn1/x690sample_template_asn1.json >+/lib/asn1/x690sample_template_asn1_oids.c >+/lib/asn1/x690sample_template_asn1_syms.c > /lib/auth/Makefile.in > /lib/base/base64.c >+/lib/base/heimbase-protos.h >+/lib/base/json-journal > /lib/base/test_base > /lib/base/test_db.json > /lib/com_err/compile_et >@@ -191,12 +284,31 @@ tags > /lib/com_err/parse.h > /lib/com_err/snprintf.c > /lib/com_err/strlcpy.c >-/lib/gssapi/gss >+/lib/gssapi/asn1_ContextFlags.c >+/lib/gssapi/asn1_GSSAPIContextToken.c >+/lib/gssapi/asn1_MechType.c >+/lib/gssapi/asn1_MechTypeList.c >+/lib/gssapi/asn1_NegHints.c >+/lib/gssapi/asn1_NegStateEnum.c >+/lib/gssapi/asn1_NegTokenInit.c >+/lib/gssapi/asn1_NegTokenInit2.c >+/lib/gssapi/asn1_NegTokenResp.c >+/lib/gssapi/asn1_NegotiationToken.c >+/lib/gssapi/asn1_NegotiationToken2.c >+/lib/gssapi/gss-token >+/lib/gssapi/gssapi_asn1-template.c >+/lib/gssapi/gssapi_asn1.json >+/lib/gssapi/gssapi_asn1_oids.c >+/lib/gssapi/gssapi_asn1_syms.c > /lib/gssapi/gsstool > /lib/gssapi/krb5/gsskrb5-private.h > /lib/gssapi/ntlm/ntlm-private.h > /lib/gssapi/sanon/sanon-private.h > /lib/gssapi/spnego/spnego-private.h >+/lib/gssapi/spnego_asn1-template.c >+/lib/gssapi/spnego_asn1.json >+/lib/gssapi/spnego_asn1_oids.c >+/lib/gssapi/spnego_asn1_syms.c > /lib/gssapi/test_acquire_cred > /lib/gssapi/test_add_store_cred > /lib/gssapi/test_cfx >@@ -239,12 +351,44 @@ tags > /lib/hcrypto/test_rsa > /lib/hcrypto/unix > /lib/hcrypto/libtommath/callgraph.txt >-/lib/hdb/hdb-protos.h >+/lib/hdb/asn1_Event.c >+/lib/hdb/asn1_GENERATION.c >+/lib/hdb/asn1_HDBFlags.c >+/lib/hdb/asn1_HDB_EncTypeList.c >+/lib/hdb/asn1_HDB_EntryOrAlias.c >+/lib/hdb/asn1_HDB_Ext_Aliases.c >+/lib/hdb/asn1_HDB_Ext_Constrained_delegation_acl.c >+/lib/hdb/asn1_HDB_Ext_KeyRotation.c >+/lib/hdb/asn1_HDB_Ext_KeySet.c >+/lib/hdb/asn1_HDB_Ext_Lan_Manager_OWF.c >+/lib/hdb/asn1_HDB_Ext_PKINIT_acl.c >+/lib/hdb/asn1_HDB_Ext_PKINIT_cert.c >+/lib/hdb/asn1_HDB_Ext_PKINIT_hash.c >+/lib/hdb/asn1_HDB_Ext_Password.c >+/lib/hdb/asn1_HDB_entry.c >+/lib/hdb/asn1_HDB_entry_alias.c >+/lib/hdb/asn1_HDB_extension.c >+/lib/hdb/asn1_HDB_extensions.c >+/lib/hdb/asn1_HDB_keyset.c >+/lib/hdb/asn1_Key.c >+/lib/hdb/asn1_KeyRotation.c >+/lib/hdb/asn1_KeyRotationFlags.c >+/lib/hdb/asn1_Keys.c >+/lib/hdb/asn1_Salt.c > /lib/hdb/hdb-private.h >+/lib/hdb/hdb-protos.h >+/lib/hdb/hdb_asn1-template.c >+/lib/hdb/hdb_asn1.json >+/lib/hdb/hdb_asn1_oids.c >+/lib/hdb/hdb_asn1_syms.c >+/lib/hdb/test_concurrency > /lib/hdb/test_dbinfo > /lib/hdb/test_hdbkeys >-/lib/hdb/test_namespace > /lib/hdb/test_mkey >+/lib/hdb/test_namespace >+/lib/hdb/testhdb-*-shm >+/lib/hdb/testhdb-*-wal >+/lib/hx509/actual > /lib/hx509/PKITS_data/ > /lib/hx509/cert-ca.der > /lib/hx509/cert-ca.pem >@@ -258,6 +402,7 @@ tags > /lib/hx509/data/*.srl > /lib/hx509/data/*.req > /lib/hx509/data/sub-ca-combined.crt >+/lib/hx509/expected > /lib/hx509/ev.data > /lib/hx509/ev.data.out > /lib/hx509/hx509-private.h >@@ -341,6 +486,7 @@ tags > /lib/krb5/test_hostname > /lib/krb5/test_keytab > /lib/krb5/test_mem >+/lib/krb5/test_mkforwardable > /lib/krb5/test_pac > /lib/krb5/test_pkinit_dh2key > /lib/krb5/test_pknistkdf >@@ -369,10 +515,10 @@ tags > /lib/otp/strlcpy.c > /lib/otp/strlwr.c > /lib/otp/strncasecmp.c >+/lib/roken/base32-test > /lib/roken/base64-test > /lib/roken/getaddrinfo-test > /lib/roken/getifaddrs-test >-/lib/roken/glob.h > /lib/roken/hex-test > /lib/roken/make-roken > /lib/roken/make-roken.c >@@ -380,10 +526,13 @@ tags > /lib/roken/parse_reply-test > /lib/roken/parse_time-test > /lib/roken/resolve-test >+/lib/roken/rkbase32 >+/lib/roken/rkbase64 > /lib/roken/rkpty >+/lib/roken/rkvis > /lib/roken/roken.h >+/lib/roken/rtbl > /lib/roken/snprintf-test >-/lib/roken/snprintf-test.trs > /lib/roken/strpftime-test > /lib/roken/test-auxval > /lib/roken/test-detach >@@ -415,6 +564,7 @@ tags > /lib/wind/normalize_table.h > /lib/wind/punycode_examples.c > /lib/wind/punycode_examples.h >+/lib/wind/__pycache__/ > /lib/wind/test-bidi > /lib/wind/test-ldap > /lib/wind/test-map >@@ -453,33 +603,29 @@ tags > /tests/gss/check-context > /tests/gss/check-gss > /tests/gss/check-gssmask >+/tests/gss/check-negoex > /tests/gss/check-ntlm > /tests/gss/check-spnego > /tests/gss/current-db.db > /tests/gss/foopassword > /tests/gss/krb5.conf >-/tests/gss/krb5ccfile* >-/tests/gss/krb5ccfile2* >-/tests/gss/krb5ccfile-ds* >+/tests/gss/krb5ccfile >+/tests/gss/krb5ccfile-ds >+/tests/gss/krb5ccfile2 >+/tests/gss/mech >+/tests/gss/new_clients_k5.conf > /tests/gss/server.keytab > /tests/gss/tempfile >-/tests/java/KerberosInit$1.class >-/tests/java/KerberosInit$TestCallBackHandler.class >-/tests/java/KerberosInit.class > /tests/java/check-kinit >-/tests/java/current-db.db >-/tests/java/foopassword >-/tests/java/jgssapi_server.class >-/tests/java/server.keytab > /tests/java/krb5.conf >-/tests/kdc/acache.krb5* >+/tests/kdc/acache.krb5 > /tests/kdc/barpassword >-/tests/kdc/ca.crt >-/tests/kdc/cache.krb5* >-/tests/kdc/cache1.krb5* >-/tests/kdc/cache2.krb5* >+/tests/kdc/bx509.pem >+/tests/kdc/cache.krb5 >+/tests/kdc/cc_dir/ > /tests/kdc/cdigest-reply > /tests/kdc/check-authz >+/tests/kdc/check-bx509 > /tests/kdc/check-canon > /tests/kdc/check-cc > /tests/kdc/check-delegation >@@ -487,6 +633,7 @@ tags > /tests/kdc/check-digest > /tests/kdc/check-fast > /tests/kdc/check-hdb-mitdb >+/tests/kdc/check-httpkadmind > /tests/kdc/check-iprop > /tests/kdc/check-kadmin > /tests/kdc/check-kdc >@@ -498,51 +645,62 @@ tags > /tests/kdc/check-tester > /tests/kdc/check-uu > /tests/kdc/current-db.db >-/tests/kdc/current.log.save > /tests/kdc/current-db.sqlite3 >+/tests/kdc/current-db.sqlite3-shm >+/tests/kdc/current-db.sqlite3-wal >+/tests/kdc/current.log.save >+/tests/kdc/email.pem > /tests/kdc/foopassword > /tests/kdc/foopassword.rkpty >+/tests/kdc/icache.krb5 > /tests/kdc/iprop-stats >+/tests/kdc/iprop-stats2 > /tests/kdc/iprop.keytab > /tests/kdc/ipropd.dumpfile >-/tests/kdc/kdc.crt >+/tests/kdc/k.der > /tests/kdc/kdc-tester4.json >+/tests/kdc/kdc.pid > /tests/kdc/krb5-authz.conf > /tests/kdc/krb5-authz2.conf >+/tests/kdc/krb5-bx509.conf > /tests/kdc/krb5-canon.conf > /tests/kdc/krb5-canon2.conf >+/tests/kdc/krb5-cccol.conf > /tests/kdc/krb5-hdb-mitdb.conf >+/tests/kdc/krb5-httpkadmind.conf >+/tests/kdc/krb5-master2.conf > /tests/kdc/krb5-pkinit-win.conf > /tests/kdc/krb5-pkinit.conf >+/tests/kdc/krb5-pkinit2.conf > /tests/kdc/krb5-slave.conf > /tests/kdc/krb5-slave2.conf > /tests/kdc/krb5-weak.conf > /tests/kdc/krb5.conf >-/tests/kdc/krb5-cc.conf > /tests/kdc/krb5.conf.keys >-/tests/kdc/kx509-template.crt >-/tests/kdc/kx509.pem > /tests/kdc/localname >+/tests/kdc/messages.log2 >+/tests/kdc/mixed-issuer.pem > /tests/kdc/notfoopassword > /tests/kdc/o2cache.krb5 > /tests/kdc/ocache.krb5 >-/tests/kdc/pkinit.crt >-/tests/kdc/pkinit2.crt >-/tests/kdc/pkinit3.crt >-/tests/kdc/pkinit4.crt >-/tests/kdc/req-kdc.der >-/tests/kdc/req-pkinit.der >-/tests/kdc/req-pkinit2.der >+/tests/kdc/pkinit-anchor.pem >+/tests/kdc/req > /tests/kdc/s2digest-reply >+/tests/kdc/sdb > /tests/kdc/sdigest-init > /tests/kdc/sdigest-reply >+/tests/kdc/server-issuer.pem > /tests/kdc/server.keytab >+/tests/kdc/server.pem >+/tests/kdc/simple_csr_authz/ > /tests/kdc/tempfile > /tests/kdc/test-rc-file.rc >+/tests/kdc/trivial.pem >+/tests/kdc/user-issuer.pem > /tests/ldap/check-ldap > /tests/ldap/krb5.conf > /tests/ldap/slapd-init >-/tests/plugin/cache.krb5* >+/tests/plugin/cache.krb5 > /tests/plugin/check-pac > /tests/plugin/current-db.db > /tests/plugin/foopassword >diff --git a/third_party/heimdal/Makefile.am b/third_party/heimdal/Makefile.am >index 7fb69fdf4e08..b9bdcf4995e5 100644 >--- a/third_party/heimdal/Makefile.am >+++ b/third_party/heimdal/Makefile.am >@@ -45,7 +45,6 @@ EXTRA_DIST = \ > cf/ChangeLog \ > cf/have-pragma-weak.m4 \ > cf/have-types.m4 \ >- cf/krb-func-getcwd-broken.m4 \ > cf/krb-prog-ranlib.m4 \ > cf/krb-prog-yacc.m4 \ > cf/krb-sys-aix.m4 \ >diff --git a/third_party/heimdal/README.md b/third_party/heimdal/README.md >index bf9fca2a7be9..5e49fd0e1a4d 100644 >--- a/third_party/heimdal/README.md >+++ b/third_party/heimdal/README.md >@@ -1,4 +1,6 @@ >-[![Travis-CI build (Linux, OS X)](https://travis-ci.org/heimdal/heimdal.svg?branch=master)](https://travis-ci.org/heimdal/heimdal#) >+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/linux.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Alinux) >+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/osx.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Aosx) >+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/windows.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Awindows) > [![Appveyor-CI build (Windows)](https://ci.appveyor.com/api/projects/status/6j0k0m7kd6jjj4tw/branch/master?svg=true)](https://ci.appveyor.com/project/heimdal/heimdal/branch/master) > [![Coverage Status](https://coveralls.io/repos/github/heimdal/heimdal/badge.svg?branch=master)](https://coveralls.io/github/heimdal/heimdal?branch=master) > >@@ -30,5 +32,8 @@ respectively to subscribe. > Build Status > ============ > >-[![Travis-CI build (Linux, OS X)](https://travis-ci.org/heimdal/heimdal.svg?branch=master)](https://travis-ci.org/heimdal/heimdal#) >+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/linux.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Alinux) >+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/osx.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Aosx) >+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/windows.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Awindows) > [![Appveyor-CI build (Windows)](https://ci.appveyor.com/api/projects/status/6j0k0m7kd6jjj4tw/branch/master?svg=true)](https://ci.appveyor.com/project/heimdal/heimdal/branch/master) >+[![Coverage Status](https://coveralls.io/repos/github/heimdal/heimdal/badge.svg?branch=master)](https://coveralls.io/github/heimdal/heimdal?branch=master) >diff --git a/third_party/heimdal/admin/change.c b/third_party/heimdal/admin/change.c >index a46d484c18f0..b9d0e830d388 100644 >--- a/third_party/heimdal/admin/change.c >+++ b/third_party/heimdal/admin/change.c >@@ -261,7 +261,6 @@ kt_change(struct change_options *opt, int argc, char **argv) > krb5_kt_end_seq_get(context, keytab, &cursor); > > if (ret == KRB5_KT_END) { >- ret = 0; > for (i = 0; i < j; i++) { > if (verbose_flag) { > char *client_name; >diff --git a/third_party/heimdal/appl/afsutil/afslog.c b/third_party/heimdal/appl/afsutil/afslog.c >index f2ade9425ea8..05078ee8e1fe 100644 >--- a/third_party/heimdal/appl/afsutil/afslog.c >+++ b/third_party/heimdal/appl/afsutil/afslog.c >@@ -118,7 +118,7 @@ expand_cell_name(const char *cell) > if(c) > return c; > } >- return cell; >+ return NULL; > } > > static void >diff --git a/third_party/heimdal/appl/gssmask/gssmask.c b/third_party/heimdal/appl/gssmask/gssmask.c >index 35c548979a6f..44b59fe5eb90 100644 >--- a/third_party/heimdal/appl/gssmask/gssmask.c >+++ b/third_party/heimdal/appl/gssmask/gssmask.c >@@ -951,7 +951,9 @@ HandleOP(WrapExt) > memcpy(p, iov[4].buffer.value, iov[4].buffer.length); > p += iov[4].buffer.length; > memcpy(p, iov[5].buffer.value, iov[5].buffer.length); >+#if 0 /* Would be needed to keep going, but presently unused */ > p += iov[5].buffer.length; >+#endif > > gss_release_iov_buffer(NULL, iov, iov_len); > >diff --git a/third_party/heimdal/appl/kf/kf.c b/third_party/heimdal/appl/kf/kf.c >index ecef93965ac1..fd4f174988ea 100644 >--- a/third_party/heimdal/appl/kf/kf.c >+++ b/third_party/heimdal/appl/kf/kf.c >@@ -312,7 +312,9 @@ doit (const char *hostname, int port, const char *svc, > continue; > } > freeaddrinfo (ai); >- return proto (s, hostname, svc, message, len); >+ error = proto(s, hostname, svc, message, len); >+ close(s); >+ return error; > } > warnx ("failed to contact %s", hostname); > freeaddrinfo (ai); >diff --git a/third_party/heimdal/appl/otp/otp.c b/third_party/heimdal/appl/otp/otp.c >index 1ca6a1f61bb8..deb7d303c66b 100644 >--- a/third_party/heimdal/appl/otp/otp.c >+++ b/third_party/heimdal/appl/otp/otp.c >@@ -118,16 +118,22 @@ verify_user_otp(char *username) > { > OtpContext ctx; > char passwd[OTP_MAX_PASSPHRASE + 1]; >- char prompt[128], ss[256]; >+ char ss[256]; >+ char *prompt = NULL; > > if (otp_challenge (&ctx, username, ss, sizeof(ss)) != 0) { > warnx("no otp challenge found for %s", username); > return 1; > } > >- snprintf (prompt, sizeof(prompt), "%s's %s Password: ", username, ss); >- if(UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)) >+ if (asprintf(&prompt, "%s's %s Password: ", username, ss) == -1 || >+ prompt == NULL) >+ err(1, "out of memory"); >+ if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)) { >+ free(prompt); > return 1; >+ } >+ free(prompt); > return otp_verify_user (&ctx, passwd); > } > >diff --git a/third_party/heimdal/appl/test/gssapi_server.c b/third_party/heimdal/appl/test/gssapi_server.c >index 5d2a39dd7c43..baf13ecff5fb 100644 >--- a/third_party/heimdal/appl/test/gssapi_server.c >+++ b/third_party/heimdal/appl/test/gssapi_server.c >@@ -159,6 +159,8 @@ process_it(int sock, > input_token, > NULL, > output_token); >+ if (GSS_ERROR(maj_stat)) >+ gss_err(1, min_stat, "gss_wrap"); > > write_token (sock, output_token); > gss_release_buffer (&min_stat, output_token); >@@ -184,7 +186,7 @@ proto (int sock, const char *service) > gss_name_t client_name; > struct gss_channel_bindings_struct input_chan_bindings; > gss_cred_id_t delegated_cred_handle = NULL; >- krb5_ccache ccache; >+ krb5_ccache ccache = NULL; > u_char init_buf[4]; > u_char acct_buf[4]; > gss_OID mech_oid; >@@ -270,15 +272,21 @@ proto (int sock, const char *service) > printf("Using mech: %s\n", mech); > > if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) { >- krb5_context context; >+ krb5_context context = NULL; > > printf("Delegated cred found\n"); > >- maj_stat = krb5_init_context(&context); >- maj_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache); >- maj_stat = gss_krb5_copy_ccache(&min_stat, >- delegated_cred_handle, >- ccache); >+ min_stat = krb5_init_context(&context); >+ if (min_stat) >+ gss_err(1, min_stat, "krb5_init_context"); >+ if (min_stat == 0) >+ min_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache); >+ if (min_stat == 0) >+ maj_stat = gss_krb5_copy_ccache(&min_stat, >+ delegated_cred_handle, >+ ccache); >+ else >+ maj_stat = GSS_S_FAILURE; > if (maj_stat == 0) { > krb5_principal p; > maj_stat = krb5_cc_get_principal(context, ccache, &p); >@@ -293,6 +301,7 @@ proto (int sock, const char *service) > } > } > krb5_cc_close(context, ccache); >+ krb5_free_context(context); > gss_release_cred(&min_stat, &delegated_cred_handle); > } > >diff --git a/third_party/heimdal/appl/test/uu_server.c b/third_party/heimdal/appl/test/uu_server.c >index 64a2b1279fae..6e046990b165 100644 >--- a/third_party/heimdal/appl/test/uu_server.c >+++ b/third_party/heimdal/appl/test/uu_server.c >@@ -102,6 +102,8 @@ proto (int sock, const char *service) > &in_creds, &out_creds); > if(status) > krb5_err(context, 1, status, "krb5_get_credentials"); >+ krb5_cc_close(context, ccache); >+ ccache = NULL; > > status = krb5_cc_default(context, &ccache); > if(status) >@@ -120,6 +122,8 @@ proto (int sock, const char *service) > NULL, > NULL, > NULL); >+ krb5_cc_close(context, ccache); >+ ccache = NULL; > > if (status) > krb5_err(context, 1, status, "krb5_sendauth"); >@@ -134,6 +138,9 @@ proto (int sock, const char *service) > free(str); > } > >+ krb5_free_principal(context, in_creds.client); >+ krb5_free_principal(context, in_creds.server); >+ > krb5_data_zero (&data); > krb5_data_zero (&packet); > >diff --git a/third_party/heimdal/appveyor.yml b/third_party/heimdal/appveyor.yml >index bb1e12123e5b..fa56c4c59a66 100644 >--- a/third_party/heimdal/appveyor.yml >+++ b/third_party/heimdal/appveyor.yml >@@ -4,55 +4,51 @@ > # users, and is free for public repositories. > # > >+version: '1.0.{build}' >+ >+image: >+ - Visual Studio 2019 >+ > install: > # HACK -- pacman installation in Appveyor seems broken > # Taken from https://github.com/johnkerl/miller/blob/master/appveyor.yml >- - set PATH=C:\msys64\usr\bin;%PATH% >- - bash -lc "curl -Lo pacman-5.2.1-6-x86_64.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/pacman-5.2.1-6-x86_64.pkg.tar.xz.sig" >- - bash -lc "curl -Lo pacman-5.2.1-6-x86_64.pkg.tar.xz http://repo.msys2.org/msys/x86_64/pacman-5.2.1-6-x86_64.pkg.tar.xz" >- - bash -lc "curl -Lo zstd-1.4.4-2-x86_64.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/zstd-1.4.4-2-x86_64.pkg.tar.xz.sig" >- - bash -lc "curl -Lo zstd-1.4.4-2-x86_64.pkg.tar.xz http://repo.msys2.org/msys/x86_64/zstd-1.4.4-2-x86_64.pkg.tar.xz" >- - bash -lc "curl -Lo autoconf-2.69-5-any.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/autoconf-2.69-5-any.pkg.tar.xz.sig" >- - bash -lc "curl -Lo autoconf-2.69-5-any.pkg.tar.xz http://repo.msys2.org/msys/x86_64/autoconf-2.69-5-any.pkg.tar.xz" >- - bash -lc "curl -Lo automake1.16-1.16.2-2-any.pkg.tar.zst.sig http://repo.msys2.org/msys/x86_64/automake1.16-1.16.2-2-any.pkg.tar.zst.sig" >- - bash -lc "curl -Lo automake1.16-1.16.2-2-any.pkg.tar.zst http://repo.msys2.org/msys/x86_64/automake1.16-1.16.2-2-any.pkg.tar.zst" >- - bash -lc "curl -Lo bison-3.5.4-1-x86_64.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/bison-3.5.4-1-x86_64.pkg.tar.xz.sig" >- - bash -lc "curl -Lo bison-3.5.4-1-x86_64.pkg.tar.xz http://repo.msys2.org/msys/x86_64/bison-3.5.4-1-x86_64.pkg.tar.xz" >- - bash -lc "curl -Lo flex-2.6.4-1-x86_64.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/flex-2.6.4-1-x86_64.pkg.tar.xz.sig" >- - bash -lc "curl -Lo flex-2.6.4-1-x86_64.pkg.tar.xz http://repo.msys2.org/msys/x86_64/flex-2.6.4-1-x86_64.pkg.tar.xz" >- - bash -lc "curl -Lo perl-5.30.2-1-x86_64.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/perl-5.30.2-1-x86_64.pkg.tar.xz.sig" >- - bash -lc "curl -Lo perl-5.30.2-1-x86_64.pkg.tar.xz http://repo.msys2.org/msys/x86_64/perl-5.30.2-1-x86_64.pkg.tar.xz" >- - bash -lc "curl -Lo perl-JSON-4.02-1-any.pkg.tar.zst.sig http://repo.msys2.org/msys/x86_64/perl-JSON-4.02-1-any.pkg.tar.zst.sig" >- - bash -lc "curl -Lo perl-JSON-4.02-1-any.pkg.tar.zst http://repo.msys2.org/msys/x86_64/perl-JSON-4.02-1-any.pkg.tar.zst" >+ # (which is gone) >+ #- ps: dir 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows' -Recurse >+ - set "PATH=C:\msys64\usr\bin;%PATH%" >+ - set "PATH=C:\%MSYS2_DIR%\%MSYSTEM%\bin;C:\%MSYS2_DIR%\usr\bin;%PATH%" >+ - bash -lc "mkdir -p /var/lib/pacman/sync/" >+ - bash -lc "pacman-key --init" >+ - bash -lc "pacman-key --populate msys2" >+ - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-1~20211228-1-any.pkg.tar.zst" >+ - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-1~20211228-1-any.pkg.tar.zst.sig" >+ - bash -lc "pacman --noconfirm -U --config <(echo) msys2-keyring-1~20211228-1-any.pkg.tar.zst" >+ - bash -lc "mkdir -p /var/lib/pacman/sync/" > - bash -lc "pacman-key --init" > - bash -lc "pacman-key --populate msys2" >- - bash -lc "pwd; ls -l" >- - bash -lc "pacman-key --verify pacman-5.2.1-6-x86_64.pkg.tar.xz.sig" >- - bash -lc "pacman --noconfirm -S zstd || pacman --ask 20 -U file://$PWD/zstd-1.4.4-2-x86_64.pkg.tar.xz" >- #- bash -lc "pacman --ask 20 -U file://$PWD/pacman-5.2.1-6-x86_64.pkg.tar.xz" >- #- bash -lc "pacman-key --populate zstd" >- #- bash -lc "pacman-key --verify zstd-1.4.4-2-x86_64.pkg.tar.xz.sig" >- #- bash -lc "pacman --ask 20 -U file://$PWD/zstd-1.4.4-2-x86_64.pkg.tar.xz" >- - bash -lc "pacman --noconfirm -S autoconf || pacman --ask 20 -U file://$PWD/autoconf-2.69-5-any.pkg.tar.xz.sig" >- - bash -lc "pacman --noconfirm -S automake || pacman --ask 20 -U file://$PWD/automake1.16-1.16.2-2-any.pkg.tar.zst" >- - bash -lc "pacman --noconfirm -S flex || pacman --ask 20 -U file://$PWD/flex-2.6.4-1-x86_64.pkg.tar.xz" >- - bash -lc "pacman --noconfirm -S bison || pacman --ask 20 -U file://$PWD/bison-3.5.4-1-x86_64.pkg.tar.xz" >- - bash -lc "pacman --noconfirm -S perl || pacman --ask 20 -U file://$PWD/perl-5.30.2-1-x86_64.pkg.tar.xz" >- - bash -lc "pacman --noconfirm -S perl-JSON || pacman --ask 20 -U file://$PWD/perl-JSON-4.02-1-any.pkg.tar.zst" >+ - bash -lc "pacman -S --noconfirm --refresh pacman" >+ - bash -lc "pacman -S --needed --noconfirm pacman-mirrors" >+ - bash -lc "pacman -S --needed --noconfirm mingw-w64-x86_64-toolchain autoconf automake libtool make patch mingw-w64-x86_64-libtool" >+ - bash -lc "pacman -S --needed --noconfirm bison flex" >+ - bash -lc "pacman -S --needed --noconfirm perl perl-JSON" > > build_script: >- - set PSDKDir=C:\Program Files\Microsoft SDKs\Windows\v7.1 >- - call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.Cmd" /xp /x64 /Release >- - set WIXDIR="c:\Program Files (x86)\Windows Installer XML v3.5" >+ # build using Windows 10 SDK >+ - set "WINSDKVER=10.0.22000.0" >+ - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64 %WINSDKVER% >+ - set "WIXDIR=c:\Program Files (x86)\Windows Installer XML v3.5" > # We're not doing any codesigning in the Appveyor build yet. >- - SET CODESIGN_PKT=0000000000000000 >- - set PATH=%PATH%;C:\Python26;C:\Perl64\bin;C:\tools\cygwin\bin;C:\Program Files (x86)\HTML Help Workshop >- - set PATH=%PATH%;C:/msys64/usr/bin >- - set PATH=%PATH%;C:\program files (x86)\windows installer xml v3.5\bin;C:\cygwin\bin >+ - SET "CODESIGN_PKT=0000000000000000" >+ - set "PATH=%PATH%;C:\Perl64\bin;C:\tools\cygwin\bin;C:\Program Files (x86)\HTML Help Workshop" >+ - set "PATH=%PATH%;C:/msys64/usr/bin" >+ - set "PATH=%PATH%;C:\program files (x86)\windows installer xml v3.5\bin;C:\cygwin\bin" >+ # double check this, should it be x86 or x64? >+ - set "PATH=%PATH%;%WindowsSdkVerBinPath%\x86" >+ - set "PATH=C:\Python310-x64;%PATH%" > - set dbg__type=Debug > - title Heimdal Build %CPU% %dbg__type% > - echo PATH=%PATH% >- - C:\msys64\usr\bin\bash -lc "cp /c/Windows/System32/msvcr100d.dll /c/projects/heimdal" >+ # target Windows 10 API >+ - set APPVER=10.0 > # Newer texinfo has no .exe's, so we have to invoke it as > # "perl ...\makeinfo ...". See doc/NTMakefile. > - nmake /f NTMakefile APPVEYOR=1 MAKEINFO=makeinfo NO_INSTALLERS=1 >diff --git a/third_party/heimdal/cf/Makefile.am.common b/third_party/heimdal/cf/Makefile.am.common >index 1b134f5b77f6..90921fe46b96 100644 >--- a/third_party/heimdal/cf/Makefile.am.common >+++ b/third_party/heimdal/cf/Makefile.am.common >@@ -12,6 +12,8 @@ endif > > AM_CFLAGS = $(WFLAGS) > >+CLANG_FORMAT_STYLE = '{BasedOnStyle: Mozilla, AlwaysBreakAfterReturnType: TopLevelDefinitions, IndentWidth: 4, SortIncludes: false}' >+ > CP = cp > > ## set build_HEADERZ to headers that should just be installed in build tree >@@ -139,22 +141,7 @@ check-local:: > test "$$failed" -eq 0 || exit 1; \ > fi > >-SUFFIXES += .x .z .hx >- >-# It's useful for debugging to format generated sources. The default for all >-# clang-format styles is to sort includes, but in many cases in-tree we really >-# don't want to do that. >-.x.c: >- @if [ ! -x "$(CLANG_FORMAT)" ]; then \ >- cmp -s $< $@ 2> /dev/null || cp $< $@; \ >- else \ >- cp $< $@.tmp.c; \ >- $(CLANG_FORMAT) -style='{BasedOnStyle: Mozilla, AlwaysBreakAfterReturnType: TopLevelDefinitions, IndentWidth: 4, SortIncludes: false}' -i $@.tmp.c; \ >- cmp -s $@.tmp.c $@ 2> /dev/null || mv $@.tmp.c $@; \ >- fi >- >-.hx.h: >- @cmp -s $< $@ 2> /dev/null || cp $< $@; >+SUFFIXES += .x .z > > SUFFIXES += .1 .3 .5 .7 .8 .cat1 .cat3 .cat5 .cat7 .cat8 > >diff --git a/third_party/heimdal/cf/ax_check_sign.m4 b/third_party/heimdal/cf/ax_check_sign.m4 >new file mode 100644 >index 000000000000..bc2c3f034ce7 >--- /dev/null >+++ b/third_party/heimdal/cf/ax_check_sign.m4 >@@ -0,0 +1,54 @@ >+# =========================================================================== >+# https://www.gnu.org/software/autoconf-archive/ax_check_sign.html >+# =========================================================================== >+# >+# SYNOPSIS >+# >+# AX_CHECK_SIGN (TYPE, [ACTION-IF-SIGNED], [ACTION-IF-UNSIGNED], [INCLUDES]) >+# >+# DESCRIPTION >+# >+# Checks whether TYPE is signed or not. If no INCLUDES are specified, the >+# default includes are used. If ACTION-IF-SIGNED is given, it is >+# additional shell code to execute when the type is signed. If >+# ACTION-IF-UNSIGNED is given, it is executed when the type is unsigned. >+# >+# This macro assumes that the type exists. Therefore the existence of the >+# type should be checked before calling this macro. For example: >+# >+# AC_CHECK_HEADERS([wchar.h]) >+# AC_CHECK_TYPE([wchar_t],,[ AC_MSG_ERROR([Type wchar_t not found.]) ]) >+# AX_CHECK_SIGN([wchar_t], >+# [ AC_DEFINE(WCHAR_T_SIGNED, 1, [Define if wchar_t is signed]) ], >+# [ AC_DEFINE(WCHAR_T_UNSIGNED, 1, [Define if wchar_t is unsigned]) ], [ >+# #ifdef HAVE_WCHAR_H >+# #include <wchar.h> >+# #endif >+# ]) >+# >+# LICENSE >+# >+# Copyright (c) 2008 Ville Laurikari <vl@iki.fi> >+# >+# Copying and distribution of this file, with or without modification, are >+# permitted in any medium without royalty provided the copyright notice >+# and this notice are preserved. This file is offered as-is, without any >+# warranty. >+ >+#serial 7 >+ >+AU_ALIAS([VL_CHECK_SIGN], [AX_CHECK_SIGN]) >+AC_DEFUN([AX_CHECK_SIGN], [ >+ typename=`echo $1 | sed "s/@<:@^a-zA-Z0-9_@:>@/_/g"` >+ AC_CACHE_CHECK([whether $1 is signed], ax_cv_decl_${typename}_signed, [ >+ AC_TRY_COMPILE([$4], >+ [ int foo @<:@ 1 - 2 * !((($1) -1) < 0) @:>@ ], >+ [ eval "ax_cv_decl_${typename}_signed=\"yes\"" ], >+ [ eval "ax_cv_decl_${typename}_signed=\"no\"" ])]) >+ symbolname=`echo $1 | sed "s/@<:@^a-zA-Z0-9_@:>@/_/g" | tr "a-z" "A-Z"` >+ if eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"yes\""; then >+ $2 >+ elif eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"no\""; then >+ $3 >+ fi >+])dnl >diff --git a/third_party/heimdal/cf/check-compile-flag.m4 b/third_party/heimdal/cf/check-compile-flag.m4 >new file mode 100644 >index 000000000000..bd753b34d7dc >--- /dev/null >+++ b/third_party/heimdal/cf/check-compile-flag.m4 >@@ -0,0 +1,53 @@ >+# =========================================================================== >+# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html >+# =========================================================================== >+# >+# SYNOPSIS >+# >+# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) >+# >+# DESCRIPTION >+# >+# Check whether the given FLAG works with the current language's compiler >+# or gives an error. (Warnings, however, are ignored) >+# >+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on >+# success/failure. >+# >+# If EXTRA-FLAGS is defined, it is added to the current language's default >+# flags (e.g. CFLAGS) when the check is done. The check is thus made with >+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to >+# force the compiler to issue an error when a bad flag is given. >+# >+# INPUT gives an alternative input source to AC_COMPILE_IFELSE. >+# >+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this >+# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. >+# >+# LICENSE >+# >+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> >+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> >+# >+# Copying and distribution of this file, with or without modification, are >+# permitted in any medium without royalty provided the copyright notice >+# and this notice are preserved. This file is offered as-is, without any >+# warranty. >+ >+#serial 6 >+ >+AC_DEFUN([AX_CHECK_COMPILE_FLAG], >+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF >+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl >+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ >+ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS >+ _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" >+ AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], >+ [AS_VAR_SET(CACHEVAR,[yes])], >+ [AS_VAR_SET(CACHEVAR,[no])]) >+ _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) >+AS_VAR_IF(CACHEVAR,yes, >+ [m4_default([$2], :)], >+ [m4_default([$3], :)]) >+AS_VAR_POPDEF([CACHEVAR])dnl >+])dnl AX_CHECK_COMPILE_FLAGS >diff --git a/third_party/heimdal/cf/db.m4 b/third_party/heimdal/cf/db.m4 >index cf5e3a88c997..c0b4510b6297 100644 >--- a/third_party/heimdal/cf/db.m4 >+++ b/third_party/heimdal/cf/db.m4 >@@ -57,9 +57,9 @@ AS_IF([test "x$with_berkeley_db" != xno], > db.h \ > ])]) > >-dnl db_create is used by db3 and db4 and db5 >+dnl db_create is used by db3 and db4 and db5 and db6 > >- AC_FIND_FUNC_NO_LIBS(db_create, [$dbheader] db-5 db5 db4 db3 db, [ >+ AC_FIND_FUNC_NO_LIBS(db_create, [$dbheader] db-6 db-5 db4 db3 db, [ > #include <stdio.h> > #ifdef HAVE_DBHEADER > #include <$dbheader/db.h> >@@ -83,7 +83,7 @@ dnl db_create is used by db3 and db4 and db5 > else > DB3LIB="" > fi >- AC_DEFINE(HAVE_DB3, 1, [define if you have a berkeley db3/4/5 library]) >+ AC_DEFINE(HAVE_DB3, 1, [define if you have a berkeley db3/4/5/6 library]) > fi > > dnl dbopen is used by db1/db2 >diff --git a/third_party/heimdal/cf/krb-prog-yacc.m4 b/third_party/heimdal/cf/krb-prog-yacc.m4 >index 380412ec7a0d..4c0afd9b7c33 100644 >--- a/third_party/heimdal/cf/krb-prog-yacc.m4 >+++ b/third_party/heimdal/cf/krb-prog-yacc.m4 >@@ -1,12 +1,18 @@ > dnl $Id$ > dnl > dnl >-dnl We prefer byacc or yacc because they do not use `alloca' >+dnl OLD: We prefer byacc or yacc because they do not use `alloca' >+dnl >+dnl CURRENT: We don't mind `alloca', but we do mind `bison -y' because >+dnl newer versions of `bison', with `-y' complain about %expect and >+dnl anything that yacc didn't document. Because `bison' typically >+dnl also installs a `yacc' link that acts like `bison y', we put >+dnl `yacc' last in this list. > dnl > > AC_DEFUN([AC_KRB_PROG_YACC], >-[AC_CHECK_PROGS(YACC, byacc yacc 'bison -y') >+[AC_CHECK_PROGS(YACC, 'bison -d' 'byacc -d' yacc) > if test "$YACC" = ""; then >- AC_MSG_WARN([yacc not found - some stuff will not build]) >+ AC_MSG_WARN([byacc and bison not found - some stuff will not build]) > fi > ]) >diff --git a/third_party/heimdal/cf/roken-frag.m4 b/third_party/heimdal/cf/roken-frag.m4 >index 1dfcb1860b5a..2c2ef834e7a3 100644 >--- a/third_party/heimdal/cf/roken-frag.m4 >+++ b/third_party/heimdal/cf/roken-frag.m4 >@@ -183,7 +183,6 @@ AC_CHECK_FUNCS([ \ > asnprintf \ > asprintf \ > atexit \ >- cgetent \ > getauxval \ > getconfattr \ > getprogname \ >@@ -216,11 +215,6 @@ AC_CHECK_FUNCS([ \ > vis \ > ]) > >-if test "$ac_cv_func_cgetent" = no; then >- AC_LIBOBJ(getcap) >-fi >-AM_CONDITIONAL(have_cgetent, test "$ac_cv_func_cgetent" = yes) >- > AC_REQUIRE([AC_FUNC_GETLOGIN]) > > AC_REQUIRE([AC_FUNC_MMAP]) >diff --git a/third_party/heimdal/configure.ac b/third_party/heimdal/configure.ac >index 37a2275c283a..8c0b746ba5ce 100644 >--- a/third_party/heimdal/configure.ac >+++ b/third_party/heimdal/configure.ac >@@ -20,6 +20,7 @@ AM_PROG_CC_C_O > AC_PROG_CPP > AM_PATH_PYTHON > AC_CHECK_PROG(CLANG_FORMAT, clang-format, [clang-format], [no]) >+test "$CLANG_FORMAT" = no && CLANG_FORMAT=true > > m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) > >@@ -58,8 +59,8 @@ if ! test -f "$srcdir/lib/asn1/der-protos.h" || > AC_KRB_PERL_MOD(JSON) > fi > >-dnl AC_KRB_PROG_YACC >-AC_PROG_YACC >+AC_KRB_PROG_YACC >+dnl AC_PROG_YACC > AM_PROG_LEX > AS_IF([$LEX --nounput -V > /dev/null 2>&1 && test $? -eq 0], > [AC_SUBST([FLEXNOUNPUTARGS], ["--nounput"])], >@@ -87,8 +88,6 @@ dnl > dnl Helper bits for cross compiling > dnl > >- >- > AM_CONDITIONAL(CROSS_COMPILE, test "${cross_compiling}" = yes) > > AC_ARG_WITH(cross-tools, >@@ -117,6 +116,14 @@ else > > fi > >+AX_CHECK_COMPILE_FLAG([-Wno-error=enum-conversion], >+ [WFLAGS_ENUM_CONV=-Wno-error=enum-conversion], >+ [WFLAGS_ENUM_CONV=], [-Werror]) >+AX_CHECK_COMPILE_FLAG([-Wno-unused-but-set-variable], >+ [WFLAGS_UNUSED_BUT_SET_VAR=-Wno-unused-but-set-variable], >+ [WFLAGS_UNUSED_BUT_SET_VAR=], [-Werror]) >+ >+AC_SUBST([WFLAGS_ENUM_CONV]) > AC_SUBST([ASN1_COMPILE]) > AC_SUBST([ASN1_COMPILE_DEP]) > AC_SUBST([SLC]) >@@ -496,6 +503,20 @@ dnl export symbols > rk_WIN32_EXPORT(BUILD_KRB5_LIB, KRB5_LIB) > rk_WIN32_EXPORT(BUILD_ROKEN_LIB, ROKEN_LIB) > rk_WIN32_EXPORT(BUILD_GSSAPI_LIB, GSSAPI_LIB) >+rk_WIN32_EXPORT(BUILD_KDC_LIB, KDC_LIB) >+ >+dnl Deal with switch FALLTHROUGH >+AH_TOP([ >+#if defined(__GNUC__) >+#if __GNUC__ >= 7 >+# define fallthrough __attribute__((fallthrough)) >+#else >+# define fallthrough do {} while (0) /* fallthrough */ >+#endif >+#else >+# define fallthrough do {} while (0) /* fallthrough */ >+#endif >+]) > > dnl Checks for libraries. > >@@ -605,6 +626,15 @@ AM_CONDITIONAL(HAVE_KEYUTILS, test "$ac_cv_func_keyctl_get_persistent" = yes) > > AC_CHECK_SIZEOF([time_t]) > >+AX_CHECK_SIGN([time_t], >+ [ AC_DEFINE(TIME_T_SIGNED, 1, [Define if time_t is signed]) ], >+ [ AC_DEFINE(TIME_T_UNSIGNED, 1, [Define if time_t is unsigned]) ], [ >+#ifdef HAVE_TIME_H >+#include <time.h> >+#endif >+]) >+ >+ > AC_CHECK_TYPES([int8_t, int16_t, int32_t, int64_t, > u_int8_t, u_int16_t, u_int32_t, u_int64_t, > uint8_t, uint16_t, uint32_t, uint64_t],,,[ >diff --git a/third_party/heimdal/import-lorikeet.sh b/third_party/heimdal/import-lorikeet.sh >index 6d36ced6c3fd..45a5888f721b 100755 >--- a/third_party/heimdal/import-lorikeet.sh >+++ b/third_party/heimdal/import-lorikeet.sh >@@ -101,33 +101,33 @@ samba_create() { > echo "git clean -d -x -f" > git clean -d -x -f > echo "git read-tree..." >- git read-tree -u --prefix=source4/heimdal-new/ local-heimdal/$lorikeet_branch || bailout $? >+ git read-tree -u --prefix=third_party/heimdal-new/ local-heimdal/$lorikeet_branch || bailout $? > echo "git reset --mixed HEAD" > git reset --mixed HEAD > echo "swap old -> new" >- mv source4/heimdal source4/heimdal-old || bailout $? >- rsync -a source4/heimdal-new/ source4/heimdal || bailout $? >+ mv third_party/heimdal third_party/heimdal-old || bailout $? >+ rsync -a third_party/heimdal-new/ third_party/heimdal || bailout $? > # echo "PS1=\"'import-heimdal shell'>\"" > ../.bashrc.samba_create > # bash --rcfile ../.bashrc.samba_create > # bailout 255 > echo "add changed files to the index" >- git add -u source4/heimdal >+ git add -u third_party/heimdal > echo "commit the changed files blindly" >- git commit --no-verify -m "s4:heimdal: import $lorikeet_branch (commit $lorikeet_commit)" >- echo "cleanup source4/heimdal" >- rm -rf source4/heimdal >- git checkout source4/heimdal >+ git commit --no-verify -m "third_party/heimdal: import $lorikeet_branch (commit $lorikeet_commit)" >+ echo "cleanup third_party/heimdal" >+ rm -rf third_party/heimdal >+ git checkout third_party/heimdal > echo "try to build samba" > build_samba || { > echo "" > echo "Now build the tree and make it compile." >- echo "Missing files can be copied from source4/heimdal-new/" >+ echo "Missing files can be copied from third_party/heimdal-new/" > echo "Also run make test!" > } > echo "" >- echo "Then do a 'git add source4/heimdal' and a 'git commit --amend'" >+ echo "Then do a 'git add third_party/heimdal' and a 'git commit --amend'" > echo "and write a useful commit message..." >- echo "Then commit all needed changes outside of source4/heimdal" >+ echo "Then commit all needed changes outside of third_party/heimdal" > echo "maybe splitted into multiple commits." > echo "" > echo "!!!!!!!!!" >diff --git a/third_party/heimdal/include/Makefile.am b/third_party/heimdal/include/Makefile.am >index 16dd2250c20c..43ebe7069472 100644 >--- a/third_party/heimdal/include/Makefile.am >+++ b/third_party/heimdal/include/Makefile.am >@@ -36,21 +36,28 @@ CLEANFILES = \ > base64.h \ > ccache_plugin.h \ > cms_asn1.h \ >+ cms_template_asn1.h \ > com_err.h \ > com_right.h \ >+ common_plugin.h \ > crmf_asn1.h \ >+ crmf_template_asn1.h \ > db_plugin.h \ > der-private.h \ > der-protos.h \ > der.h \ > digest_asn1.h \ >+ digest_template_asn1.h \ > editline.h \ > err.h \ > getarg.h \ > glob.h \ >+ gss-preauth-protos.h \ >+ gss-preauth-private.h \ > gssapi.h \ > gssapi_asn1.h \ > gssapi_mech.h \ >+ gssapi/gssapi_preauth.h \ > hdb-private.h \ > hdb-protos.h \ > hdb.h \ >@@ -60,6 +67,8 @@ CLEANFILES = \ > heim_asn1.h \ > heim_err.h \ > heimbase.h \ >+ heimbase-svc.h \ >+ heimbase-protos.h \ > heimntlm-protos.h \ > heimntlm.h \ > hex.h \ >@@ -79,26 +88,38 @@ CLEANFILES = \ > krb5-types.h \ > krb5.h \ > krb5_asn1.h \ >+ krb5_template_asn1.h \ > krb5_ccapi.h \ > krb5_err.h \ > krb_err.h \ >+ kuserok_plugin.h \ > kx509_asn1.h \ >+ kx509_template_asn1.h \ > kx509_err.h \ > locate_plugin.h \ > login-protos.h \ > ntlm_err.h \ > ocsp_asn1.h \ >+ ocsp_template_asn1.h \ > otp.h \ > parse_bytes.h \ > parse_time.h \ > parse_units.h \ > pkcs10_asn1.h \ >+ pkcs10_template_asn1.h \ > pkcs12_asn1.h \ >+ pkcs12_template_asn1.h \ > pkcs8_asn1.h \ >+ pkcs8_template_asn1.h \ > pkcs9_asn1.h \ >+ pkcs9_template_asn1.h \ > pkinit_asn1.h \ >+ pkinit_template_asn1.h \ > resolve.h \ > rfc2459_asn1.h \ >+ rfc2459_template_asn1.h \ >+ rfc4108_asn1.h \ >+ rfc4108_template_asn1.h \ > roken-common.h \ > roken.h \ > rtbl.h \ >@@ -111,8 +132,16 @@ CLEANFILES = \ > vis.h \ > wind.h \ > wind_err.h \ >- windc_plugin.h \ >- xdbm.h >+ kdc-plugin.h \ >+ kdc-accessors.h \ >+ kdc-audit.h \ >+ csr_authorizer_plugin.h \ >+ gss_preauth_authorizer_plugin.h \ >+ token_validator_plugin.h \ >+ xdbm.h \ >+ x25519_ref10.h \ >+ x690sample_asn1.h \ >+ x690sample_template_asn1.h > > DISTCLEANFILES = \ > version.h \ >diff --git a/third_party/heimdal/include/bits.c b/third_party/heimdal/include/bits.c >index 326b67b7cc90..6abdb15c9113 100644 >--- a/third_party/heimdal/include/bits.c >+++ b/third_party/heimdal/include/bits.c >@@ -46,23 +46,42 @@ RCSID("$Id$"); > #include <ws2tcpip.h> > #endif > >-#define BITSIZE(TYPE) \ >-{ \ >- int b = 0; TYPE x = 1, zero = 0; const char *pre = "u"; \ >- char tmp[128], tmp2[128]; \ >- while(x){ x <<= 1; b++; if(x < zero) pre=""; } \ >- if(b >= len){ \ >- size_t tabs; \ >- sprintf(tmp, "%sint%d_t" , pre, len); \ >- sprintf(tmp2, "typedef %s %s;", #TYPE, tmp); \ >- tabs = 5 - strlen(tmp2) / 8; \ >- fprintf(f, "%s", tmp2); \ >- while(tabs-- > 0) fprintf(f, "\t"); \ >- fprintf(f, "/* %2d bits */\n", b); \ >- return; \ >- } \ >+#ifdef HAVE_SNPRINTF >+#define BITSIZE(TYPE) \ >+{ \ >+ int b = 0; TYPE x = 1, zero = 0; const char *pre = "u"; \ >+ char tmp[128]; \ >+ while(x){ x <<= 1; b++; if(x < zero) pre=""; } \ >+ if(b >= len){ \ >+ size_t tabs; \ >+ snprintf(tmp, sizeof(tmp), "typedef %s %sint%d_t;", #TYPE, \ >+ pre, len); \ >+ tabs = 5 - strlen(tmp) / 8; \ >+ fprintf(f, "%s", tmp); \ >+ while(tabs-- > 0) fprintf(f, "\t"); \ >+ fprintf(f, "/* %2d bits */\n", b); \ >+ return; \ >+ } \ > } >- >+#else >+#define BITSIZE(TYPE) \ >+{ \ >+ int b = 0; TYPE x = 1, zero = 0; const char *pre = "u"; \ >+ char tmp[128], tmp2[128]; \ >+ while(x){ x <<= 1; b++; if(x < zero) pre=""; } \ >+ if(b >= len){ \ >+ size_t tabs; \ >+ sprintf(tmp, "%sint%d_t" , pre, len); \ >+ sprintf(tmp2, "typedef %s %s;", #TYPE, tmp); \ >+ tabs = 5 - strlen(tmp2) / 8; \ >+ fprintf(f, "%s", tmp2); \ >+ while(tabs-- > 0) \ >+ fprintf(f, "\t"); \ >+ fprintf(f, "/* %2d bits */\n", b); \ >+ return; \ >+ } \ >+} >+#endif > #ifndef HAVE___ATTRIBUTE__ > #define __attribute__(x) > #endif >diff --git a/third_party/heimdal/include/config.h.w32 b/third_party/heimdal/include/config.h.w32 >index 2d03bf264207..5521181d27cc 100644 >--- a/third_party/heimdal/include/config.h.w32 >+++ b/third_party/heimdal/include/config.h.w32 >@@ -32,6 +32,8 @@ > #ifndef __CONFIG_H__ > #define __CONFIG_H__ > >+#define fallthrough do {} while(0) /* fallthrough */ >+ > #ifndef RCSID > #define RCSID(msg) \ > static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg } >@@ -122,6 +124,24 @@ static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg } > #endif > #endif > >+ >+#ifdef BUILD_KDC_LIB >+#ifndef KDC_LIB >+#ifdef _WIN32 >+#define KDC_LIB_FUNCTION >+#define KDC_LIB_NORETURN_FUNCTION __declspec(noreturn) >+#define KDC_LIB_CALL __stdcall >+#define KDC_LIB_VARIABLE >+#else >+#define KDC_LIB_FUNCTION >+#define KDC_LIB_NORETURN_FUNCTION >+#define KDC_LIB_CALL >+#define KDC_LIB_VARIABLE >+#endif >+#endif >+#endif >+ >+ > /* Feature macros */ > > @FEATURE_DEFS@ >@@ -199,9 +219,6 @@ static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg } > /* Define to 1 if you have the `cap_set_proc' function. */ > /* #undef HAVE_CAP_SET_PROC */ > >-/* Define to 1 if you have the `cgetent' function. */ >-/* #undef HAVE_CGETENT */ >- > /* Define if the system defines 'CHAR' type */ > #define HAVE_CHAR 1 > >@@ -793,9 +810,6 @@ static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg } > /* Define to 1 if you have the `setstate' function. */ > /* #define HAVE_SETSTATE 1 */ > >-/* Define to 1 if you have the `sgi_getcapabilitybyname' function. */ >-/* #undef HAVE_SGI_GETCAPABILITYBYNAME */ >- > /* Define to 1 if you have the <sgtty.h> header file. */ > /* #undef HAVE_SGTTY_H */ > >@@ -887,6 +901,17 @@ static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg } > /* Define if you have the function `strtok_r'. */ > /* #define HAVE_STRTOK_R 1 */ > >+#if defined(__has_include) >+# if __has_include(<corecrt.h>) >+# define HAVE_UCRT 1 >+# endif >+#endif >+ >+#ifdef HAVE_UCRT >+#define HAVE_STRTOLL 1 >+#define HAVE_STRTOULL 1 >+#endif >+ > /* Define to 1 if the system has the type `struct addrinfo'. */ > #define HAVE_STRUCT_ADDRINFO 1 > >diff --git a/third_party/heimdal/kadmin/add-random-users.c b/third_party/heimdal/kadmin/add-random-users.c >index b3d6d581d9b3..e2dc303b8dc9 100644 >--- a/third_party/heimdal/kadmin/add-random-users.c >+++ b/third_party/heimdal/kadmin/add-random-users.c >@@ -58,7 +58,7 @@ read_words (const char *filename, char ***ret_w) > buf[strcspn(buf, "\r\n")] = '\0'; > if (n >= alloc) { > alloc = max(alloc + 16, alloc * 2); >- w = erealloc (w, alloc * sizeof(char **)); >+ w = erealloc (w, alloc * sizeof(char *)); > } > len = strlen(buf); > if (wptr + len + 1 >= wend) { >diff --git a/third_party/heimdal/kadmin/add_enctype.c b/third_party/heimdal/kadmin/add_enctype.c >index 0ababf4f1976..d128ab7f49ef 100644 >--- a/third_party/heimdal/kadmin/add_enctype.c >+++ b/third_party/heimdal/kadmin/add_enctype.c >@@ -46,7 +46,7 @@ add_enctype(struct add_enctype_options*opt, int argc, char **argv) > krb5_error_code ret; > const char *princ_name; > int i, j; >- krb5_key_data *new_key_data; >+ krb5_key_data *new_key_data = NULL; > int n_etypes; > krb5_enctype *etypes; > >@@ -108,7 +108,6 @@ add_enctype(struct add_enctype_options*opt, int argc, char **argv) > /* XXX Should this be an error? The admin can del_enctype... */ > krb5_warnx(context, "enctype %d already exists", > (int)etypes[j]); >- free(new_key_data); > goto out; > } > } >@@ -163,6 +162,7 @@ add_enctype(struct add_enctype_options*opt, int argc, char **argv) > if (ret) > krb5_warn(context, ret, "kadm5_modify_principal"); > out: >+ free(new_key_data); > krb5_free_principal (context, princ_ent); > kadm5_free_principal_ent(kadm_handle, &princ); > out2: >diff --git a/third_party/heimdal/kadmin/ank.c b/third_party/heimdal/kadmin/ank.c >index 1e5cd6117dcf..4b89ca6eedd4 100644 >--- a/third_party/heimdal/kadmin/ank.c >+++ b/third_party/heimdal/kadmin/ank.c >@@ -89,6 +89,7 @@ add_one_principal(const char *name, > int mask = 0; > int default_mask = 0; > char pwbuf[1024]; >+ char *princ_name = NULL; > > memset(&princ, 0, sizeof(princ)); > ret = krb5_parse_name(context, name, &princ_ent); >@@ -96,6 +97,14 @@ add_one_principal(const char *name, > krb5_warn(context, ret, "krb5_parse_name"); > return ret; > } >+ >+ if (rand_password) { >+ ret = krb5_unparse_name(context, princ_ent, &princ_name); >+ if (ret) { >+ krb5_warn(context, ret, "krb5_parse_name"); >+ goto out; >+ } >+ } > princ.principal = princ_ent; > mask |= KADM5_PRINCIPAL; > >@@ -129,7 +138,6 @@ add_one_principal(const char *name, > random_password (pwbuf, sizeof(pwbuf)); > password = pwbuf; > } else if(password == NULL) { >- char *princ_name; > char *prompt; > int aret; > >@@ -137,7 +145,6 @@ add_one_principal(const char *name, > if (ret) > goto out; > aret = asprintf (&prompt, "%s's Password: ", princ_name); >- free (princ_name); > if (aret == -1) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "out of memory"); >@@ -205,18 +212,17 @@ add_one_principal(const char *name, > kadm5_modify_principal(kadm_handle, &princ, > KADM5_PW_EXPIRATION | KADM5_ATTRIBUTES); > } else if (rand_password) { >- char *princ_name; >- >- krb5_unparse_name(context, princ_ent, &princ_name); > printf ("added %s with password \"%s\"\n", princ_name, password); >- free (princ_name); > } > out: >+ free(princ_name); > kadm5_free_principal_ent(kadm_handle, &princ); /* frees princ_ent */ > if(default_ent) > kadm5_free_principal_ent (kadm_handle, default_ent); >- if (password != NULL) >- memset (password, 0, strlen(password)); >+ if (password != NULL) { >+ size_t len = strlen(password); >+ memset_s(password, len, 0, len); >+ } > return ret; > } > >@@ -354,7 +360,6 @@ add_one_namespace(const char *name, > { > krb5_error_code ret; > kadm5_principal_ent_rec princ; >- kadm5_principal_ent_rec *default_ent = NULL; > krb5_principal princ_ent = NULL; > int mask = 0; > int default_mask = 0; >@@ -391,6 +396,8 @@ add_one_namespace(const char *name, > ret = krb5_parse_name(context, name, &princ_ent); > if (ret) > krb5_warn(context, ret, "krb5_parse_name"); >+ else >+ princ.principal = princ_ent; > } > if (ret != 0) > return ret; >@@ -449,7 +456,6 @@ add_one_namespace(const char *name, > } > > if (ret == 0) { >- princ.principal = princ_ent; > mask |= KADM5_PRINCIPAL | KADM5_KVNO; > > ret = set_entry(context, &princ, &mask, >@@ -457,21 +463,21 @@ add_one_namespace(const char *name, > "never", "never", attributes, NSPOLICY); > } > if (ret == 0) >- ret = edit_entry(&princ, &mask, default_ent, default_mask); >+ ret = edit_entry(&princ, &mask, NULL, default_mask); > > if (ret == 0) > ret = kstuple2etypes(&princ, &mask, nkstuple, kstuple); > > /* XXX Shouldn't need a password for this */ > random_password(pwbuf, sizeof(pwbuf)); >- ret = kadm5_create_principal_3(kadm_handle, &princ, mask, >- nkstuple, kstuple, pwbuf); >- if (ret) >- krb5_warn(context, ret, "kadm5_create_principal_3"); >+ if (ret == 0) { >+ ret = kadm5_create_principal_3(kadm_handle, &princ, mask, >+ nkstuple, kstuple, pwbuf); >+ if (ret) >+ krb5_warn(context, ret, "kadm5_create_principal_3"); >+ } > > kadm5_free_principal_ent(kadm_handle, &princ); /* frees princ_ent */ >- if (default_ent) >- kadm5_free_principal_ent(kadm_handle, default_ent); > memset(pwbuf, 0, sizeof(pwbuf)); > return ret; > } >diff --git a/third_party/heimdal/kadmin/cpw.c b/third_party/heimdal/kadmin/cpw.c >index d254add4482d..2f3c1c1bcd74 100644 >--- a/third_party/heimdal/kadmin/cpw.c >+++ b/third_party/heimdal/kadmin/cpw.c >@@ -65,17 +65,17 @@ set_random_password (krb5_principal principal, int keepold) > { > krb5_error_code ret; > char pw[128]; >+ char *princ_name; > >- random_password (pw, sizeof(pw)); >- ret = kadm5_chpass_principal_3(kadm_handle, principal, keepold, 0, NULL, pw); >- if (ret == 0) { >- char *princ_name; >- >- krb5_unparse_name(context, principal, &princ_name); >+ ret = krb5_unparse_name(context, principal, &princ_name); >+ if (ret) >+ return ret; > >+ random_password(pw, sizeof(pw)); >+ ret = kadm5_chpass_principal_3(kadm_handle, principal, keepold, 0, NULL, pw); >+ if (ret == 0) > printf ("%s's password set to \"%s\"\n", princ_name, pw); >- free (princ_name); >- } >+ free(princ_name); > memset_s(pw, sizeof(pw), 0, sizeof(pw)); > return ret; > } >diff --git a/third_party/heimdal/kadmin/del.c b/third_party/heimdal/kadmin/del.c >index 089ee8b0d805..a066f56ea387 100644 >--- a/third_party/heimdal/kadmin/del.c >+++ b/third_party/heimdal/kadmin/del.c >@@ -61,12 +61,15 @@ do_del_ns_entry(krb5_principal nsp, void *data) > krb5_principal p = NULL; > const char *comp0 = krb5_principal_get_comp_string(context, nsp, 0); > const char *comp1 = krb5_principal_get_comp_string(context, nsp, 1); >- char *unsp = NULL; > > if (krb5_principal_get_num_comp(context, nsp) != 2) { >- (void) krb5_unparse_name(context, nsp, &unsp); >- krb5_warn(context, ret = EINVAL, "Not a valid namespace name %s", >- unsp ? unsp : "<Out of memory>"); >+ char *unsp = NULL; >+ >+ ret = krb5_unparse_name(context, nsp, &unsp); >+ krb5_warn(context, ret, >+ "Not a valid namespace name (component count is not 2): %s", >+ unsp ? unsp : "<out of memory>"); >+ free(unsp); > return EINVAL; > } > >@@ -80,7 +83,6 @@ do_del_ns_entry(krb5_principal nsp, void *data) > if (ret == 0) > ret = kadm5_delete_principal(kadm_handle, p); > krb5_free_principal(context, p); >- free(unsp); > return ret; > } > >diff --git a/third_party/heimdal/kadmin/ext.c b/third_party/heimdal/kadmin/ext.c >index 01725d96e207..adb2e28518aa 100644 >--- a/third_party/heimdal/kadmin/ext.c >+++ b/third_party/heimdal/kadmin/ext.c >@@ -148,7 +148,7 @@ do_ext_keytab(krb5_principal principal, void *data) > } > free(unparsed); > free(keys); >- return 0; >+ return ret; > } > > int >diff --git a/third_party/heimdal/kadmin/get.c b/third_party/heimdal/kadmin/get.c >index 35766aa1bfc5..a884e11e96be 100644 >--- a/third_party/heimdal/kadmin/get.c >+++ b/third_party/heimdal/kadmin/get.c >@@ -349,6 +349,7 @@ format_field(struct get_entry_data *data, > if (i) > strlcat(buf, ",", buf_len); > strlcat(buf, str, buf_len); >+ krb5_xfree(str); > } > } > free_HDB_EncTypeList(&etypes); >@@ -632,6 +633,7 @@ list_princs(struct list_options *opt, int argc, char **argv) > krb5_warnx(context, "programmer error: sizeof(struct get_options) != sizeof(struct list_options)"); > return 0; > } >+ memset(&get_opt, 0, sizeof(get_opt)); > get_opt.long_flag = opt->long_flag; > get_opt.short_flag = opt->short_flag; > get_opt.terse_flag = opt->terse_flag; >diff --git a/third_party/heimdal/kadmin/init.c b/third_party/heimdal/kadmin/init.c >index 8b025e112f8a..8a3725e3c49c 100644 >--- a/third_party/heimdal/kadmin/init.c >+++ b/third_party/heimdal/kadmin/init.c >@@ -73,7 +73,20 @@ create_random_entry(krb5_principal princ, > ent.attributes |= attributes | KRB5_KDB_DISALLOW_ALL_TIX; > mask |= KADM5_ATTRIBUTES | KADM5_KEY_DATA; > >- /* Create the entry with no keys or password */ >+ /* >+ * Create the entry with no keys or password. >+ * >+ * XXX Note that using kadm5_s_*() here means that `kadmin init` must >+ * always be local (`kadmin -l init`). This might seem like a very >+ * obvious thing, but since our KDC daemons support multiple realms >+ * there is no reason that `init SOME.REALM.EXAMPLE` couldn't be >+ * remoted. >+ * >+ * Granted, one might want all such operations to be local anyways -- >+ * perhaps for authorization reasons, since we don't really have that >+ * great a story for authorization in kadmind at this time, especially >+ * for realm creation. >+ */ > ret = kadm5_s_create_principal_with_key(kadm_handle, &ent, mask); > if(ret) { > if (ret == KADM5_DUP && (flags & CRE_DUP_OK)) >@@ -127,21 +140,21 @@ init(struct init_options *opt, int argc, char **argv) > > if (!local_flag) { > krb5_warnx(context, "init is only available in local (-l) mode"); >- return 0; >+ return 1; > } > > if (opt->realm_max_ticket_life_string) { > if (str2deltat (opt->realm_max_ticket_life_string, &max_life) != 0) { > krb5_warnx (context, "unable to parse \"%s\"", > opt->realm_max_ticket_life_string); >- return 0; >+ return 1; > } > } > if (opt->realm_max_renewable_life_string) { > if (str2deltat (opt->realm_max_renewable_life_string, &max_rlife) != 0) { > krb5_warnx (context, "unable to parse \"%s\"", > opt->realm_max_renewable_life_string); >- return 0; >+ return 1; > } > } > >@@ -150,107 +163,164 @@ init(struct init_options *opt, int argc, char **argv) > ret = db->hdb_open(context, db, O_RDWR | O_CREAT, 0600); > if(ret){ > krb5_warn(context, ret, "hdb_open"); >- return 0; >+ return 1; > } > ret = kadm5_log_reinit(kadm_handle, 0); >- if (ret) >- krb5_err(context, 1, ret, "Failed iprop log initialization"); >- kadm5_log_end(kadm_handle); >+ if (ret) { >+ krb5_warn(context, ret, "Failed iprop log initialization"); >+ return 1; >+ } >+ ret = kadm5_log_end(kadm_handle); > db->hdb_close(context, db); >+ if (ret) { >+ krb5_warn(context, ret, "Failed iprop log initialization"); >+ return 1; >+ } >+ > for(i = 0; i < argc; i++){ >- krb5_principal princ; >+ krb5_principal princ = NULL; > const char *realm = argv[i]; > > if (opt->realm_max_ticket_life_string == NULL) { > max_life = 0; > if(edit_deltat ("Realm max ticket life", &max_life, NULL, 0)) { >- return 0; >+ return 1; > } > } > if (opt->realm_max_renewable_life_string == NULL) { > max_rlife = 0; > if(edit_deltat("Realm max renewable ticket life", &max_rlife, > NULL, 0)) { >- return 0; >+ return 1; > } > } > > /* Create `krbtgt/REALM' */ > ret = krb5_make_principal(context, &princ, realm, > KRB5_TGS_NAME, realm, NULL); >- if(ret) >- return 0; >- >- create_random_entry(princ, max_life, max_rlife, 0, 0); >+ if (ret == 0) >+ ret = create_random_entry(princ, max_life, max_rlife, 0, 0); > krb5_free_principal(context, princ); >+ if (ret) { >+ krb5_warn(context, ret, "Failed to create %s@%s", KRB5_TGS_NAME, >+ realm); >+ return 1; >+ } > > if (opt->bare_flag) > continue; > > /* Create `kadmin/changepw' */ >- krb5_make_principal(context, &princ, realm, >- "kadmin", "changepw", NULL); >+ ret = krb5_make_principal(context, &princ, realm, "kadmin", >+ "changepw", NULL); > /* > * The Windows XP (at least) password changing protocol > * request the `kadmin/changepw' ticket with `renewable_ok, > * renewable, forwardable' and so fails if we disallow > * forwardable here. > */ >- create_random_entry(princ, 5*60, 5*60, >- KRB5_KDB_DISALLOW_TGT_BASED| >- KRB5_KDB_PWCHANGE_SERVICE| >- KRB5_KDB_DISALLOW_POSTDATED| >- KRB5_KDB_DISALLOW_RENEWABLE| >- KRB5_KDB_DISALLOW_PROXIABLE| >- KRB5_KDB_REQUIRES_PRE_AUTH, >- 0); >+ if (ret == 0) >+ ret = create_random_entry(princ, 5*60, 5*60, >+ KRB5_KDB_DISALLOW_TGT_BASED| >+ KRB5_KDB_PWCHANGE_SERVICE| >+ KRB5_KDB_DISALLOW_POSTDATED| >+ KRB5_KDB_DISALLOW_RENEWABLE| >+ KRB5_KDB_DISALLOW_PROXIABLE| >+ KRB5_KDB_REQUIRES_PRE_AUTH, >+ 0); > krb5_free_principal(context, princ); >+ if (ret) { >+ krb5_warn(context, ret, "Failed to create kadmin/changepw@%s", >+ realm); >+ return 1; >+ } > > /* Create `kadmin/admin' */ >- krb5_make_principal(context, &princ, realm, >- "kadmin", "admin", NULL); >- create_random_entry(princ, 60*60, 60*60, KRB5_KDB_REQUIRES_PRE_AUTH, 0); >+ ret = krb5_make_principal(context, &princ, realm, >+ "kadmin", "admin", NULL); >+ if (ret == 0) >+ ret = create_random_entry(princ, 60*60, 60*60, >+ KRB5_KDB_REQUIRES_PRE_AUTH, 0); > krb5_free_principal(context, princ); >+ if (ret) { >+ krb5_warn(context, ret, "Failed to create kadmin/admin@%s", realm); >+ return 1; >+ } > > /* Create `changepw/kerberos' (for v4 compat) */ >- krb5_make_principal(context, &princ, realm, >- "changepw", "kerberos", NULL); >- create_random_entry(princ, 60*60, 60*60, >- KRB5_KDB_DISALLOW_TGT_BASED| >- KRB5_KDB_PWCHANGE_SERVICE, 0); >- >+ ret = krb5_make_principal(context, &princ, realm, >+ "changepw", "kerberos", NULL); >+ if (ret == 0) >+ ret = create_random_entry(princ, 60*60, 60*60, >+ KRB5_KDB_DISALLOW_TGT_BASED| >+ KRB5_KDB_PWCHANGE_SERVICE, 0); > krb5_free_principal(context, princ); >+ if (ret) { >+ krb5_warn(context, ret, "Failed to create changepw/kerberos@%s", >+ realm); >+ return 1; >+ } > > /* Create `kadmin/hprop' for database propagation */ >- krb5_make_principal(context, &princ, realm, >- "kadmin", "hprop", NULL); >- create_random_entry(princ, 60*60, 60*60, >- KRB5_KDB_REQUIRES_PRE_AUTH| >- KRB5_KDB_DISALLOW_TGT_BASED, 0); >+ ret = krb5_make_principal(context, &princ, realm, >+ "kadmin", "hprop", NULL); >+ if (ret == 0) >+ ret = create_random_entry(princ, 60*60, 60*60, >+ KRB5_KDB_REQUIRES_PRE_AUTH| >+ KRB5_KDB_DISALLOW_TGT_BASED, 0); > krb5_free_principal(context, princ); >+ if (ret) { >+ krb5_warn(context, ret, "Failed to create kadmin/hprop@%s", realm); >+ return 1; >+ } > > /* Create `WELLKNOWN/ANONYMOUS' for anonymous as-req */ >- krb5_make_principal(context, &princ, realm, >- KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL); >- create_random_entry(princ, 60*60, 60*60, >- KRB5_KDB_REQUIRES_PRE_AUTH, 0); >+ ret = krb5_make_principal(context, &princ, realm, KRB5_WELLKNOWN_NAME, >+ KRB5_ANON_NAME, NULL); >+ if (ret == 0) >+ ret = create_random_entry(princ, 60*60, 60*60, >+ KRB5_KDB_REQUIRES_PRE_AUTH, 0); > krb5_free_principal(context, princ); >+ if (ret) { >+ krb5_warn(context, ret, "Failed to create %s/%s@%s", >+ KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, realm); >+ return 1; >+ } > >- /* Create `WELLKNOWN/FEDERATED' for GSS preauth */ >- krb5_make_principal(context, &princ, realm, >- KRB5_WELLKNOWN_NAME, KRB5_FEDERATED_NAME, NULL); >- create_random_entry(princ, 60*60, 60*60, >- KRB5_KDB_REQUIRES_PRE_AUTH, 0); >- krb5_free_principal(context, princ); >+ /* Create `WELLKNOWN/FEDERATED' for GSS preauth */ >+ ret = krb5_make_principal(context, &princ, realm, >+ KRB5_WELLKNOWN_NAME, KRB5_FEDERATED_NAME, NULL); >+ if (ret == 0) >+ ret = create_random_entry(princ, 60*60, 60*60, >+ KRB5_KDB_REQUIRES_PRE_AUTH, 0); >+ krb5_free_principal(context, princ); >+ if (ret) { >+ krb5_warn(context, ret, "Failed to create %s/%s@%s", >+ KRB5_WELLKNOWN_NAME, KRB5_FEDERATED_NAME, realm); >+ return 1; >+ } > >- /* Create `WELLKNONW/org.h5l.fast-cookie@WELLKNOWN:ORG.H5L' for FAST cookie */ >- krb5_make_principal(context, &princ, KRB5_WELLKNOWN_ORG_H5L_REALM, >- KRB5_WELLKNOWN_NAME, "org.h5l.fast-cookie", NULL); >- create_random_entry(princ, 60*60, 60*60, >- KRB5_KDB_REQUIRES_PRE_AUTH| >- KRB5_KDB_DISALLOW_TGT_BASED| >- KRB5_KDB_DISALLOW_ALL_TIX, CRE_DUP_OK); >- krb5_free_principal(context, princ); >+ /* >+ * Create `WELLKNONW/org.h5l.fast-cookie@WELLKNOWN:ORG.H5L' for FAST cookie. >+ * >+ * There can be only one. >+ */ >+ if (i == 0) { >+ ret = krb5_make_principal(context, &princ, KRB5_WELLKNOWN_ORG_H5L_REALM, >+ KRB5_WELLKNOWN_NAME, "org.h5l.fast-cookie", NULL); >+ if (ret == 0) >+ ret = create_random_entry(princ, 60*60, 60*60, >+ KRB5_KDB_REQUIRES_PRE_AUTH| >+ KRB5_KDB_DISALLOW_TGT_BASED| >+ KRB5_KDB_DISALLOW_ALL_TIX, CRE_DUP_OK); >+ krb5_free_principal(context, princ); >+ if (ret && ret != KADM5_DUP) { >+ krb5_warn(context, ret, >+ "Failed to create %s/org.h5l.fast-cookie@%s", >+ KRB5_WELLKNOWN_NAME, KRB5_WELLKNOWN_ORG_H5L_REALM); >+ return 1; >+ } >+ } > > /* Create `default' */ > { >@@ -259,18 +329,20 @@ init(struct init_options *opt, int argc, char **argv) > > memset (&ent, 0, sizeof(ent)); > mask |= KADM5_PRINCIPAL; >- krb5_make_principal(context, &ent.principal, realm, >- "default", NULL); > mask |= KADM5_MAX_LIFE; >- ent.max_life = 24 * 60 * 60; > mask |= KADM5_MAX_RLIFE; >+ mask |= KADM5_ATTRIBUTES; >+ ent.max_life = 24 * 60 * 60; > ent.max_renewable_life = 7 * ent.max_life; > ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX; >- mask |= KADM5_ATTRIBUTES; >- >- ret = kadm5_create_principal(kadm_handle, &ent, mask, ""); >- if (ret) >- krb5_err (context, 1, ret, "kadm5_create_principal"); >+ ret = krb5_make_principal(context, &ent.principal, realm, >+ "default", NULL); >+ if (ret == 0) >+ ret = kadm5_create_principal(kadm_handle, &ent, mask, ""); >+ if (ret) { >+ krb5_warn(context, ret, "Failed to create default@%s", realm); >+ return 1; >+ } > > krb5_free_principal(context, ent.principal); > } >diff --git a/third_party/heimdal/kadmin/kadm_conn.c b/third_party/heimdal/kadmin/kadm_conn.c >index 0817b7c93aa4..0eeaf508da84 100644 >--- a/third_party/heimdal/kadmin/kadm_conn.c >+++ b/third_party/heimdal/kadmin/kadm_conn.c >@@ -261,12 +261,9 @@ start_server(krb5_context contextp, const char *port_str) > for(ap = ai; ap; ap = ap->ai_next) > i++; > tmp = realloc(socks, (num_socks + i) * sizeof(*socks)); >- if(tmp == NULL) { >- krb5_warnx(contextp, "failed to reallocate %lu bytes", >- (unsigned long)(num_socks + i) * sizeof(*socks)); >- freeaddrinfo(ai); >- continue; >- } >+ if(tmp == NULL) >+ krb5_err(contextp, 1, errno, "failed to reallocate %lu bytes", >+ (unsigned long)(num_socks + i) * sizeof(*socks)); > socks = tmp; > for(ap = ai; ap; ap = ap->ai_next) { > krb5_socket_t s = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol); >diff --git a/third_party/heimdal/kadmin/kadmin.1 b/third_party/heimdal/kadmin/kadmin.1 >index 401b6a9f6ba0..b0e852931c6b 100644 >--- a/third_party/heimdal/kadmin/kadmin.1 >+++ b/third_party/heimdal/kadmin/kadmin.1 >@@ -166,13 +166,20 @@ and > sub-commands rather than having to edit the KDC's configuration > file and having to restart the KDC. > .Pp >-However, there is currently no way to alias namespaces via HDB >-entry aliases. >-To issue referrals for entire namespaces use the >+There are two methods for issuing referrals for entire namespaces >+of hostnames. >+An alias of the form >+.Ar WELLKNOWN/HOSTBASED-NAMESPACE/service/namespace-fqdn@REALM >+(see >+.Nm add_namespace >+below) will cause all requests for host-based principals in the >+given namespace to be referred to the given realm. >+Alternatively, the KDC will issue referrals for all host-based >+service principals whose hostname component matches a > .Ar [domain_realm] >-section of the KDC's >+entry in the KDC's > .Ar krb5.conf >-file. >+file referring to a different realm. > .Ed > .Pp > .Nm add_namespace >@@ -182,18 +189,23 @@ file. > .Op Fl Fl max-ticket-life= Ns Ar lifetime > .Op Fl Fl max-renewable-life= Ns Ar lifetime > .Op Fl Fl attributes= Ns Ar attributes >-.Ar principal... >+.Ar host-based-principal... > .Bd -ragged -offset indent > Adds a new namespace of virtual host-based or domain-based > principals to the database, whose keys will be automatically > derived from base keys stored in the namespace record, and which > keys will be rotated automatically. >-The namespace names should look like >-.Ar hostname@REALM >+The namespace names are of the same form as host-based principal >+names: >+.Ar service/hostname@REALM > and these will match all host-based or domain-based service names > where hostname component of such a principal ends in the labels > of the hostname in the namespace name. > .Pp >+The service name component may be a wild-card (underscore, >+.Ar _ ), >+in which case it will match any service. >+.Pp > For example, > .Ar bar.baz.example@BAZ.EXAMPLE > will match >@@ -223,6 +235,11 @@ The default enctypes is as for the > .Nm add > command. > .Pp >+Note that namespaces are stored as principals whose names are of the form >+.Ar WELLKNOWN/HOSTBASED-NAMESPACE/service/namespace.fqdn@REALM , >+with the >+.Ar service >+.Pp > This command has the following alias: > .Nm add_ns . > .Ed >diff --git a/third_party/heimdal/kadmin/kadmind.c b/third_party/heimdal/kadmin/kadmind.c >index 10bbea840576..444950623f0b 100644 >--- a/third_party/heimdal/kadmin/kadmind.c >+++ b/third_party/heimdal/kadmin/kadmind.c >@@ -134,6 +134,8 @@ main(int argc, char **argv) > > argc -= optidx; > argv += optidx; >+ if (argc != 0) >+ usage(1); > > if (config_file == NULL) { > int aret; >diff --git a/third_party/heimdal/kadmin/load.c b/third_party/heimdal/kadmin/load.c >index 971c24793c05..f62f8b96dcc0 100644 >--- a/third_party/heimdal/kadmin/load.c >+++ b/third_party/heimdal/kadmin/load.c >@@ -367,7 +367,7 @@ my_fgetln(FILE *f, char **bufp, size_t *szp, size_t *lenp) > size_t len; > size_t sz = *szp; > char *buf = *bufp; >- char *p, *n; >+ char *n; > > if (!buf) { > buf = malloc(sz ? sz : 8192); >@@ -378,7 +378,7 @@ my_fgetln(FILE *f, char **bufp, size_t *szp, size_t *lenp) > } > > len = 0; >- while ((p = fgets(&buf[len], sz-len, f)) != NULL) { >+ while (fgets(&buf[len], sz-len, f) != NULL) { > len += strlen(&buf[len]); > if (buf[len-1] == '\n') > break; >@@ -418,7 +418,7 @@ doit(const char *filename, int mergep) > int lineno; > int flags = O_RDWR; > struct entry e; >- hdb_entry_ex ent; >+ hdb_entry ent; > HDB *db = _kadm5_s_get_db(kadm_handle); > > f = fopen(filename, "r"); >@@ -506,7 +506,7 @@ doit(const char *filename, int mergep) > skip_next(p); > > memset(&ent, 0, sizeof(ent)); >- ret2 = krb5_parse_name(context, e.principal, &ent.entry.principal); >+ ret2 = krb5_parse_name(context, e.principal, &ent.principal); > if (ret2) { > const char *msg = krb5_get_error_message(context, ret); > fprintf(stderr, "%s:%d:%s (%s)\n", >@@ -516,92 +516,92 @@ doit(const char *filename, int mergep) > continue; > } > >- if (parse_keys(&ent.entry, e.key)) { >+ if (parse_keys(&ent, e.key)) { > fprintf (stderr, "%s:%d:error parsing keys (%s)\n", > filename, lineno, e.key); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > ret = 1; > continue; > } > >- if (parse_event(&ent.entry.created_by, e.created) == -1) { >+ if (parse_event(&ent.created_by, e.created) == -1) { > fprintf (stderr, "%s:%d:error parsing created event (%s)\n", > filename, lineno, e.created); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > ret = 1; > continue; > } >- if (parse_event_alloc (&ent.entry.modified_by, e.modified) == -1) { >+ if (parse_event_alloc (&ent.modified_by, e.modified) == -1) { > fprintf (stderr, "%s:%d:error parsing event (%s)\n", > filename, lineno, e.modified); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > ret = 1; > continue; > } >- if (parse_time_string_alloc (&ent.entry.valid_start, e.valid_start) == -1) { >+ if (parse_time_string_alloc (&ent.valid_start, e.valid_start) == -1) { > fprintf (stderr, "%s:%d:error parsing time (%s)\n", > filename, lineno, e.valid_start); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > ret = 1; > continue; > } >- if (parse_time_string_alloc (&ent.entry.valid_end, e.valid_end) == -1) { >+ if (parse_time_string_alloc (&ent.valid_end, e.valid_end) == -1) { > fprintf (stderr, "%s:%d:error parsing time (%s)\n", > filename, lineno, e.valid_end); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > ret = 1; > continue; > } >- if (parse_time_string_alloc (&ent.entry.pw_end, e.pw_end) == -1) { >+ if (parse_time_string_alloc (&ent.pw_end, e.pw_end) == -1) { > fprintf (stderr, "%s:%d:error parsing time (%s)\n", > filename, lineno, e.pw_end); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > ret = 1; > continue; > } > >- if (parse_integer_alloc (&ent.entry.max_life, e.max_life) == -1) { >+ if (parse_integer_alloc (&ent.max_life, e.max_life) == -1) { > fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n", > filename, lineno, e.max_life); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > ret = 1; > continue; > > } >- if (parse_integer_alloc (&ent.entry.max_renew, e.max_renew) == -1) { >+ if (parse_integer_alloc (&ent.max_renew, e.max_renew) == -1) { > fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n", > filename, lineno, e.max_renew); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > ret = 1; > continue; > } > >- if (parse_hdbflags2int (&ent.entry.flags, e.flags) != 1) { >+ if (parse_hdbflags2int (&ent.flags, e.flags) != 1) { > fprintf (stderr, "%s:%d:error parsing flags (%s)\n", > filename, lineno, e.flags); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > ret = 1; > continue; > } > >- if(parse_generation(e.generation, &ent.entry.generation) == -1) { >+ if(parse_generation(e.generation, &ent.generation) == -1) { > fprintf (stderr, "%s:%d:error parsing generation (%s)\n", > filename, lineno, e.generation); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > ret = 1; > continue; > } > >- if (parse_extensions(&e.extensions, &ent.entry.extensions) == -1) { >+ if (parse_extensions(&e.extensions, &ent.extensions) == -1) { > fprintf (stderr, "%s:%d:error parsing extension (%s)\n", > filename, lineno, e.extensions); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > ret = 1; > continue; > } > > ret2 = db->hdb_store(context, db, HDB_F_REPLACE, &ent); >- hdb_free_entry (context, &ent); >+ hdb_free_entry (context, db, &ent); > if (ret2) { > krb5_warn(context, ret2, "db_store"); > break; >diff --git a/third_party/heimdal/kadmin/mod.c b/third_party/heimdal/kadmin/mod.c >index 9541c6efcb41..7c7b2dd7ce44 100644 >--- a/third_party/heimdal/kadmin/mod.c >+++ b/third_party/heimdal/kadmin/mod.c >@@ -123,7 +123,7 @@ static void > add_aliases(krb5_context contextp, kadm5_principal_ent_rec *princ, > struct getarg_strings *strings) > { >- krb5_error_code ret; >+ krb5_error_code ret = 0; > HDB_extension ext; > krb5_data buf; > krb5_principal p; >@@ -144,9 +144,16 @@ add_aliases(krb5_context contextp, kadm5_principal_ent_rec *princ, > sizeof(ext.data.u.aliases.aliases.val[0])); > ext.data.u.aliases.aliases.len = strings->num_strings; > >- for (i = 0; i < strings->num_strings; i++) { >+ for (i = 0; ret == 0 && i < strings->num_strings; i++) { > ret = krb5_parse_name(contextp, strings->strings[i], &p); >- ret = copy_Principal(p, &ext.data.u.aliases.aliases.val[i]); >+ if (ret) >+ krb5_err(contextp, 1, ret, "Could not parse alias %s", >+ strings->strings[i]); >+ if (ret == 0) >+ ret = copy_Principal(p, &ext.data.u.aliases.aliases.val[i]); >+ if (ret) >+ krb5_err(contextp, 1, ret, "Could not copy parsed alias %s", >+ strings->strings[i]); > krb5_free_principal(contextp, p); > } > } >@@ -224,6 +231,7 @@ add_etypes(krb5_context contextp, > if (ret) { > krb5_warn(contextp, ret, "Could not parse enctype %s", > strings->strings[i]); >+ free(etypes.val); > return ret; > } > etypes.val[i] = etype; >@@ -236,6 +244,7 @@ add_etypes(krb5_context contextp, > if (ret || buf.length != size) > abort(); > add_tl(princ, KRB5_TL_ETYPES, &buf); >+ free(etypes.val); > return 0; > } > >diff --git a/third_party/heimdal/kadmin/rpc.c b/third_party/heimdal/kadmin/rpc.c >index 6ddb9dfa8654..1ae10f1af7ca 100644 >--- a/third_party/heimdal/kadmin/rpc.c >+++ b/third_party/heimdal/kadmin/rpc.c >@@ -142,7 +142,7 @@ parse_name(const unsigned char *p, size_t len, > /* MECHNAME_LEN */ > if (len < 4) > return 1; >- l = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; >+ l = (unsigned long)p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; > len -= 4; > p += 4; > >@@ -972,7 +972,7 @@ process_stream(krb5_context contextp, > INSIST(gctx.ctx == NULL); > > gctx.inprogress = 1; >- /* FALLTHROUGH */ >+ fallthrough; > case RPG_CONTINUE_INIT: { > gss_name_t src_name = GSS_C_NO_NAME; > krb5_data in; >diff --git a/third_party/heimdal/kadmin/server.c b/third_party/heimdal/kadmin/server.c >index cbe16948c06c..52f20202e7fb 100644 >--- a/third_party/heimdal/kadmin/server.c >+++ b/third_party/heimdal/kadmin/server.c >@@ -42,7 +42,8 @@ static kadm5_ret_t > kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > krb5_data *in, krb5_data *out, int readonly) > { >- kadm5_ret_t ret; >+ kadm5_ret_t ret = 0; >+ kadm5_ret_t ret_sp = 0; > int32_t cmd, mask, kvno, tmp; > kadm5_server_context *contextp = kadm_handlep; > char client[128], name[128], name2[128]; >@@ -58,19 +59,31 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > char **princs; > int n_princs; > int keys_ok = 0; >+ krb5_storage *rsp; /* response goes here */ > krb5_storage *sp; > int len; > >- krb5_unparse_name_fixed(contextp->context, contextp->caller, >- client, sizeof(client)); >+ memset(&ent, 0, sizeof(ent)); >+ memset(&ent_prev, 0, sizeof(ent_prev)); >+ krb5_data_zero(out); >+ >+ rsp = krb5_storage_emem(); >+ if (rsp == NULL) >+ return krb5_enomem(contextp->context); > > sp = krb5_storage_from_data(in); > if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >+ krb5_storage_free(rsp); >+ return krb5_enomem(contextp->context); > } > >- krb5_ret_int32(sp, &cmd); >+ ret = krb5_unparse_name_fixed(contextp->context, contextp->caller, >+ client, sizeof(client)); >+ if (ret == 0) >+ ret = krb5_ret_int32(sp, &cmd); >+ if (ret) >+ goto fail; >+ > switch(cmd){ > case kadm_get:{ > op = "GET"; >@@ -121,20 +134,14 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > } > > ret = kadm5_get_principal(kadm_handlep, princ, &ent, mask); >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, ret); >- if (ret == 0){ >- if (keys_ok) >- kadm5_store_principal_ent(sp, &ent); >- else >- kadm5_store_principal_ent_nokeys(sp, &ent); >- kadm5_free_principal_ent(kadm_handlep, &ent); >+ ret_sp = krb5_store_int32(rsp, ret); >+ if (ret == 0) { >+ if (ret_sp == 0 && keys_ok) >+ ret_sp = kadm5_store_principal_ent(rsp, &ent); >+ else if (ret_sp == 0) >+ ret_sp = kadm5_store_principal_ent_nokeys(rsp, &ent); > } >+ kadm5_free_principal_ent(kadm_handlep, &ent); > break; > } > case kadm_delete:{ >@@ -144,27 +151,21 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > goto fail; > } > ret = krb5_ret_principal(sp, &princ); >- if (ret) >- goto fail; >- krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); >- krb5_warnx(contextp->context, "%s: %s %s", client, op, name); >- ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_DELETE, princ); >- if (ret) >- goto fail; >+ if (ret == 0) >+ ret = krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); >+ if (ret == 0) { >+ ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_DELETE, princ); >+ krb5_warnx(contextp->context, "%s: %s %s (%s)", client, op, name, >+ ret == 0 ? "granted" : "denied"); >+ } > > /* > * There's no need to check that the caller has permission to > * delete the victim principal's aliases. > */ >- >- ret = kadm5_delete_principal(kadm_handlep, princ); >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, ret); >+ if (ret == 0) >+ ret = kadm5_delete_principal(kadm_handlep, princ); >+ ret_sp = krb5_store_int32(rsp, ret); > break; > } > case kadm_create:{ >@@ -209,13 +210,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > ret = kadm5_create_principal(kadm_handlep, &ent, > mask, password); > kadm5_free_principal_ent(kadm_handlep, &ent); >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, ret); >+ ret_sp = krb5_store_int32(rsp, ret); > break; > } > case kadm_modify:{ >@@ -262,13 +257,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > } > ret = kadm5_modify_principal(kadm_handlep, &ent, mask); > kadm5_free_principal_ent(kadm_handlep, &ent); >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, ret); >+ ret_sp = krb5_store_int32(rsp, ret); > break; > } > case kadm_prune:{ >@@ -293,13 +282,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > goto fail; > > ret = kadm5_prune_principal(kadm_handlep, princ, kvno); >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, ret); >+ ret_sp = krb5_store_int32(rsp, ret); > break; > } > case kadm_rename:{ >@@ -342,13 +325,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > goto fail; > > ret = kadm5_rename_principal(kadm_handlep, princ, princ2); >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, ret); >+ ret_sp = krb5_store_int32(sp, ret); > break; > } > case kadm_chpass:{ >@@ -360,18 +337,19 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > goto fail; > } > ret = krb5_ret_principal(sp, &princ); >+ if (ret == 0) >+ ret = krb5_ret_string(sp, &password); >+ if (ret == 0) >+ ret = krb5_ret_int32(sp, &keepold); >+ if (ret == HEIM_ERR_EOF) >+ ret = 0; >+ if (ret == 0) { >+ ret = krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); >+ if (ret == 0) >+ krb5_warnx(contextp->context, "%s: %s %s", client, op, name); >+ } > if (ret) > goto fail; >- ret = krb5_ret_string(sp, &password); >- if (ret) >- goto fail; >- >- ret = krb5_ret_int32(sp, &keepold); >- if (ret && ret != HEIM_ERR_EOF) >- goto fail; >- >- krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); >- krb5_warnx(contextp->context, "%s: %s %s", client, op, name); > > /* > * Change password requests are subject to ACLs unless the principal is >@@ -391,13 +369,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > > ret = kadm5_chpass_principal_3(kadm_handlep, princ, keepold, 0, NULL, > password); >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, ret); >+ ret_sp = krb5_store_int32(rsp, ret); > break; > } > case kadm_chpass_with_key:{ >@@ -411,16 +383,16 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > goto fail; > } > ret = krb5_ret_principal(sp, &princ); >- if(ret) >- goto fail; >- ret = krb5_ret_int32(sp, &n_key_data); >+ if (ret == 0) >+ ret = krb5_ret_int32(sp, &n_key_data); >+ if (ret == 0) { >+ ret = krb5_ret_int32(sp, &keepold); >+ if (ret == HEIM_ERR_EOF) >+ ret = 0; >+ } > if (ret) > goto fail; > >- ret = krb5_ret_int32(sp, &keepold); >- if (ret && ret != HEIM_ERR_EOF) >- goto fail; >- > /* n_key_data will be squeezed into an int16_t below. */ > if (n_key_data < 0 || n_key_data >= 1 << 16 || > (size_t)n_key_data > UINT_MAX/sizeof(*key_data)) { >@@ -445,15 +417,16 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > } > } > >- krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); >- krb5_warnx(contextp->context, "%s: %s %s", client, op, name); >- > /* > * The change is only allowed if the user is on the CPW ACL, > * this it to force password quality check on the user. > */ > > ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ); >+ ret_sp = krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); >+ if (ret_sp == 0) >+ krb5_warnx(contextp->context, "%s: %s %s (%s)", client, op, name, >+ ret ? "denied" : "granted"); > if(ret) { > int16_t dummy = n_key_data; > >@@ -468,13 +441,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > kadm5_free_key_data (contextp, &dummy, key_data); > } > free (key_data); >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, ret); >+ ret_sp = krb5_store_int32(rsp, ret); > break; > } > case kadm_randkey:{ >@@ -537,7 +504,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > ret = EOVERFLOW; > goto fail; > } >- >+ free(ks_tuple); > if ((ks_tuple = calloc(n_ks_tuple, sizeof (*ks_tuple))) == NULL) { > ret = errno; > goto fail; >@@ -560,18 +527,12 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > &n_keys); > free(ks_tuple); > >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, ret); >- if (ret == 0){ >- krb5_store_int32(sp, n_keys); >+ ret_sp = krb5_store_int32(rsp, ret); >+ if (ret == 0 && ret_sp == 0){ >+ ret_sp = krb5_store_int32(rsp, n_keys); > for (i = 0; i < n_keys; i++){ >- if (ret == 0) >- ret = krb5_store_keyblock(sp, new_keys[i]); >+ if (ret_sp == 0) >+ ret_sp = krb5_store_keyblock(rsp, new_keys[i]); > krb5_free_keyblock_contents(contextp->context, &new_keys[i]); > } > free(new_keys); >@@ -581,15 +542,8 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > case kadm_get_privs:{ > uint32_t privs; > ret = kadm5_get_privs(kadm_handlep, &privs); >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, ret); >- if(ret == 0) >- krb5_store_uint32(sp, privs); >+ if (ret == 0) >+ ret_sp = krb5_store_uint32(sp, privs); > break; > } > case kadm_get_princs:{ >@@ -612,62 +566,42 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, > } > ret = kadm5_get_principals(kadm_handlep, expression, &princs, &n_princs); > free(expression); >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, ret); >- if(ret == 0){ >+ ret_sp = krb5_store_int32(rsp, ret); >+ if (ret == 0) { > int i; >- krb5_store_int32(sp, n_princs); >- for(i = 0; i < n_princs; i++) >- krb5_store_string(sp, princs[i]); >+ >+ ret_sp = krb5_store_int32(sp, n_princs); >+ for (i = 0; ret_sp == 0 && i < n_princs; i++) >+ ret_sp = krb5_store_string(sp, princs[i]); > kadm5_free_name_list(kadm_handlep, princs, &n_princs); > } > break; > } > default: > krb5_warnx(contextp->context, "%s: UNKNOWN OP %d", client, cmd); >- krb5_storage_free(sp); >- sp = krb5_storage_emem(); >- if (sp == NULL) { >- ret = krb5_enomem(contextp->context); >- goto fail; >- } >- krb5_store_int32(sp, KADM5_FAILURE); >+ ret_sp = krb5_store_int32(sp, KADM5_FAILURE); > break; > } >- if (password != NULL) { >- len = strlen(password); >- memset_s(password, len, 0, len); >- free(password); >- } >- krb5_storage_to_data(sp, out); >- krb5_storage_free(sp); >- if (princ != NULL) >- krb5_free_principal(contextp->context, princ); >- if (princ2 != NULL) >- krb5_free_principal(contextp->context, princ2); >- return 0; >+ > fail: > if (password != NULL) { > len = strlen(password); > memset_s(password, len, 0, len); > free(password); > } >- krb5_warn(contextp->context, ret, "%s", op); >- if (sp != NULL) { >- krb5_storage_seek(sp, 0, SEEK_SET); >- krb5_store_int32(sp, ret); >- krb5_storage_to_data(sp, out); >- krb5_storage_free(sp); >- } >- if (princ != NULL) >- krb5_free_principal(contextp->context, princ); >- if (princ2 != NULL) >- krb5_free_principal(contextp->context, princ2); >+ krb5_storage_to_data(rsp, out); >+ krb5_storage_free(rsp); >+ krb5_storage_free(sp); >+ krb5_free_principal(contextp->context, princ); >+ krb5_free_principal(contextp->context, princ2); >+ if (ret) >+ krb5_warn(contextp->context, ret, "%s", op); >+ if (out->length == 0) >+ krb5_warn(contextp->context, ret, "%s: reply failed", op); >+ else if (ret_sp) >+ krb5_warn(contextp->context, ret, "%s: reply incomplete", op); >+ if (ret_sp) >+ return ret_sp; > return 0; > } > >@@ -691,6 +625,10 @@ iter_aliases(kadm5_principal_ent_rec *from, > > if (ctx->done > 0) > return 0; >+ if (from == NULL) { >+ ctx->done = 1; >+ return 0; >+ } > > if (ctx->done == 0) { > if (ctx->alias_idx < ctx->aliases.aliases.len) { >@@ -841,7 +779,6 @@ handle_v5(krb5_context contextp, > void *kadm_handlep; > krb5_boolean initial; > krb5_auth_context ac = NULL; >- > unsigned kadm_version = 1; > kadm5_config_params realm_params; > >@@ -849,35 +786,51 @@ handle_v5(krb5_context contextp, > match_appl_version, &kadm_version, > NULL, KRB5_RECVAUTH_IGNORE_VERSION, > keytab, &ticket); >- if (ret) >+ if (ret) { > krb5_err(contextp, 1, ret, "krb5_recvauth"); >- >- ret = krb5_unparse_name (contextp, ticket->server, &server_name); >- if (ret) >- krb5_err (contextp, 1, ret, "krb5_unparse_name"); >- >- if (strncmp (server_name, KADM5_ADMIN_SERVICE, >- strlen(KADM5_ADMIN_SERVICE)) != 0) >- krb5_errx (contextp, 1, "ticket for strange principal (%s)", >- server_name); >- >- free (server_name); >+ return; >+ } >+ ret = krb5_unparse_name(contextp, ticket->server, &server_name); >+ if (ret) { >+ krb5_err(contextp, 1, ret, "krb5_unparse_name"); >+ krb5_free_ticket(contextp, ticket); >+ return; >+ } >+ if (strncmp(server_name, KADM5_ADMIN_SERVICE, >+ strlen(KADM5_ADMIN_SERVICE)) != 0) { >+ krb5_errx(contextp, 1, "ticket for strange principal (%s)", server_name); >+ krb5_free_ticket(contextp, ticket); >+ free(server_name); >+ return; >+ } >+ free(server_name); > > memset(&realm_params, 0, sizeof(realm_params)); > > if(kadm_version == 1) { > krb5_data params; > ret = krb5_read_priv_message(contextp, ac, &fd, ¶ms); >- if(ret) >+ if (ret) { > krb5_err(contextp, 1, ret, "krb5_read_priv_message"); >- _kadm5_unmarshal_params(contextp, ¶ms, &realm_params); >+ krb5_free_ticket(contextp, ticket); >+ return; >+ } >+ ret = _kadm5_unmarshal_params(contextp, ¶ms, &realm_params); >+ if (ret) { >+ krb5_err(contextp, 1, ret, >+ "Could not read or parse kadm5 parameters"); >+ krb5_free_ticket(contextp, ticket); >+ return; >+ } > } > > initial = ticket->ticket.flags.initial; > ret = krb5_unparse_name(contextp, ticket->client, &client); >- if (ret) >- krb5_err (contextp, 1, ret, "krb5_unparse_name"); >- krb5_free_ticket (contextp, ticket); >+ krb5_free_ticket(contextp, ticket); >+ if (ret) { >+ krb5_err(contextp, 1, ret, "krb5_unparse_name"); >+ return; >+ } > ret = kadm5_s_init_with_password_ctx(contextp, > client, > NULL, >@@ -885,9 +838,11 @@ handle_v5(krb5_context contextp, > &realm_params, > 0, 0, > &kadm_handlep); >- if(ret) >- krb5_err (contextp, 1, ret, "kadm5_init_with_password_ctx"); >- v5_loop (contextp, ac, initial, kadm_handlep, fd, readonly); >+ if (ret) { >+ krb5_err(contextp, 1, ret, "kadm5_init_with_password_ctx"); >+ return; >+ } >+ v5_loop(contextp, ac, initial, kadm_handlep, fd, readonly); > } > > krb5_error_code >diff --git a/third_party/heimdal/kadmin/stash.c b/third_party/heimdal/kadmin/stash.c >index 785de43f872e..c33623038ce4 100644 >--- a/third_party/heimdal/kadmin/stash.c >+++ b/third_party/heimdal/kadmin/stash.c >@@ -106,7 +106,10 @@ stash(struct stash_options *opt, int argc, char **argv) > } > } > ret = krb5_string_to_key_salt(context, enctype, buf, salt, &key); >- ret = hdb_add_master_key(context, &key, &mkey); >+ if (ret == 0) >+ ret = hdb_add_master_key(context, &key, &mkey); >+ if (ret) >+ krb5_warn(context, errno, "setting master key"); > krb5_free_keyblock_contents(context, &key); > } > >diff --git a/third_party/heimdal/kcm/cache.c b/third_party/heimdal/kcm/cache.c >index 02624dfd1c83..b11812769b67 100644 >--- a/third_party/heimdal/kcm/cache.c >+++ b/third_party/heimdal/kcm/cache.c >@@ -168,9 +168,9 @@ krb5_error_code kcm_debug_ccache(krb5_context context) > ncreds++; > > if (p->client != NULL) >- krb5_unparse_name(context, p->client, &cpn); >+ (void) krb5_unparse_name(context, p->client, &cpn); > if (p->server != NULL) >- krb5_unparse_name(context, p->server, &spn); >+ (void) krb5_unparse_name(context, p->server, &spn); > > kcm_log(7, "cache %08x: name %s refcnt %d flags %04x mode %04o " > "uid %d gid %d client %s server %s ncreds %d", >@@ -179,10 +179,8 @@ krb5_error_code kcm_debug_ccache(krb5_context context) > (spn == NULL) ? "<none>" : spn, > ncreds); > >- if (cpn != NULL) >- free(cpn); >- if (spn != NULL) >- free(spn); >+ free(cpn); >+ free(spn); > } > > return 0; >diff --git a/third_party/heimdal/kcm/client.c b/third_party/heimdal/kcm/client.c >index 09c94b6e8ddd..061d4e972676 100644 >--- a/third_party/heimdal/kcm/client.c >+++ b/third_party/heimdal/kcm/client.c >@@ -46,6 +46,43 @@ kcm_ccache_resolve_client(krb5_context context, > const char *estr; > > ret = kcm_ccache_resolve(context, name, ccache); >+ if (ret) { >+ char *uid = NULL; >+ >+ /* >+ * Both MIT and Heimdal are unable to, in krb5_cc_default(), call to >+ * KCM (or CCAPI, or LSA, or...) to get the user's default ccache name >+ * in their collection. Instead, the default ccache name is obtained >+ * in a static way, and for KCM that's "%{UID}". When we >+ * krb5_cc_switch(), we simply maintain a pointer to the name of the >+ * ccache that was made the default, but klist can't make use of this >+ * because krb5_cc_default() can't. >+ * >+ * The solution here is to first try resolving the ccache name given by >+ * the client, and if that fails but the name happens to be what would >+ * be the library's default KCM ccache name for that user, then try >+ * resolving it through the default ccache name pointer saved at switch >+ * time. >+ */ >+ if (asprintf(&uid, "%llu", (unsigned long long)client->uid) == -1 || >+ uid == NULL) >+ return ENOMEM; >+ >+ if (strcmp(name, uid) == 0) { >+ struct kcm_default_cache *c; >+ >+ for (c = default_caches; c != NULL; c = c->next) { >+ if (kcm_is_same_session(client, c->uid, c->session)) { >+ if (strcmp(c->name, name) != 0) { >+ ret = kcm_ccache_resolve(context, c->name, ccache); >+ break; >+ } >+ } >+ } >+ } >+ free(uid); >+ } >+ > if (ret) { > estr = krb5_get_error_message(context, ret); > kcm_log(1, "Failed to resolve cache %s: %s", name, estr); >diff --git a/third_party/heimdal/kcm/glue.c b/third_party/heimdal/kcm/glue.c >index 713af7f8650c..0895f48f051c 100644 >--- a/third_party/heimdal/kcm/glue.c >+++ b/third_party/heimdal/kcm/glue.c >@@ -55,7 +55,7 @@ kcmss_get_name_2(krb5_context context, > *name = CACHENAME(id); > if (col) > *col = NULL; >- if (name) >+ if (sub) > *sub = CACHENAME(id); > return 0; > } >diff --git a/third_party/heimdal/kcm/protocol.c b/third_party/heimdal/kcm/protocol.c >index c36bbe9c6c67..31f17623d01d 100644 >--- a/third_party/heimdal/kcm/protocol.c >+++ b/third_party/heimdal/kcm/protocol.c >@@ -423,7 +423,7 @@ kcm_op_get_principal(krb5_context context, > free(name); > kcm_release_ccache(context, ccache); > >- return 0; >+ return ret; > } > > /* >@@ -1537,13 +1537,6 @@ kcm_op_do_ntlm(krb5_context context, > } > > free(tmpsesskey.data); >- if (ret) { >- if (type3.lm.data) >- free(type3.lm.data); >- if (type3.ntlm.data) >- free(type3.ntlm.data); >- goto error; >- } > flags |= NTLM_FLAG_SESSIONKEY; > #if 0 > } else { >@@ -1754,6 +1747,7 @@ kcm_dispatch(krb5_context context, > krb5_storage *resp_sp = NULL; > uint16_t opcode; > >+ krb5_data_zero(resp_data); > resp_sp = krb5_storage_emem(); > if (resp_sp == NULL) { > return ENOMEM; >@@ -1803,11 +1797,17 @@ out: > krb5_storage_free(req_sp); > } > >- krb5_storage_seek(resp_sp, 0, SEEK_SET); >- krb5_store_int32(resp_sp, ret); >+ if (resp_sp) { >+ krb5_error_code ret2; > >- ret = krb5_storage_to_data(resp_sp, resp_data); >- krb5_storage_free(resp_sp); >+ krb5_storage_seek(resp_sp, 0, SEEK_SET); >+ ret2 = krb5_store_int32(resp_sp, ret); >+ if (ret2 == 0) >+ ret2 = krb5_storage_to_data(resp_sp, resp_data); >+ krb5_storage_free(resp_sp); >+ if (ret2) >+ ret = ret2; >+ } > > return ret; > } >diff --git a/third_party/heimdal/kdc/Makefile.am b/third_party/heimdal/kdc/Makefile.am >index 54382a842bf4..c7f57251f7c8 100644 >--- a/third_party/heimdal/kdc/Makefile.am >+++ b/third_party/heimdal/kdc/Makefile.am >@@ -2,6 +2,8 @@ > > include $(top_srcdir)/Makefile.am.common > >+WFLAGS += $(WFLAGS_ENUM_CONV) >+ > AM_CPPFLAGS += $(INCLUDE_libintl) $(INCLUDE_openssl_crypto) -I$(srcdir)/../lib/krb5 > > lib_LTLIBRARIES = simple_csr_authorizer.la ipc_csr_authorizer.la \ >@@ -112,6 +114,8 @@ altsecid_gss_preauth_authorizer_la_LDFLAGS = -module \ > $(LIB_openldap) > endif > >+libkdc_la_CPPFLAGS = -DBUILD_KDC_LIB $(AM_CPPFLAGS) >+ > libkdc_la_SOURCES = \ > default_config.c \ > ca.c \ >@@ -123,15 +127,15 @@ libkdc_la_SOURCES = \ > krb5tgs.c \ > pkinit.c \ > pkinit-ec.c \ >+ mssfu.c \ > log.c \ > misc.c \ > kx509.c \ > token_validator.c \ > csr_authorizer.c \ > process.c \ >- windc.c \ >- gss_preauth.c \ >- rx.h >+ kdc-plugin.c \ >+ gss_preauth.c > > KDC_PROTOS = $(srcdir)/kdc-protos.h $(srcdir)/kdc-private.h > >@@ -168,7 +172,7 @@ endif > $(libkdc_la_OBJECTS): $(srcdir)/version-script.map > > $(srcdir)/kdc-protos.h: $(libkdc_la_SOURCES) >- cd $(srcdir) && perl ../cf/make-proto.pl -q -P comment -o kdc-protos.h $(libkdc_la_SOURCES) || rm -f kdc-protos.h >+ cd $(srcdir) && perl ../cf/make-proto.pl -E KDC_LIB -q -P comment -o kdc-protos.h $(libkdc_la_SOURCES) || rm -f kdc-protos.h > > $(srcdir)/kdc-private.h: $(libkdc_la_SOURCES) > cd $(srcdir) && perl ../cf/make-proto.pl -q -P comment -p kdc-private.h $(libkdc_la_SOURCES) || rm -f kdc-private.h >@@ -240,7 +244,7 @@ include_HEADERS = kdc.h $(srcdir)/kdc-protos.h > noinst_HEADERS = $(srcdir)/kdc-private.h > > krb5dir = $(includedir)/krb5 >-krb5_HEADERS = windc_plugin.h token_validator_plugin.h csr_authorizer_plugin.h >+krb5_HEADERS = kdc-audit.h kdc-plugin.h kdc-accessors.h token_validator_plugin.h csr_authorizer_plugin.h gss_preauth_authorizer_plugin.h > > build_HEADERZ = $(krb5_HEADERS) # XXX > >diff --git a/third_party/heimdal/kdc/NTMakefile b/third_party/heimdal/kdc/NTMakefile >index 58eb7577141e..aca65b104ae8 100644 >--- a/third_party/heimdal/kdc/NTMakefile >+++ b/third_party/heimdal/kdc/NTMakefile >@@ -33,7 +33,7 @@ RELDIR=kdc > > !include ../windows/NTMakefile.w32 > >-intcflags=-I$(OBJ) -I$(SRC)\lib\gssapi -I$(OBJDIR)\lib\gssapi -I$(OBJDIR)\lib\gss_preauth >+intcflags=-I$(OBJ) -I$(SRC)\lib\gssapi -I$(OBJDIR)\lib\gssapi -I$(OBJDIR)\lib\gss_preauth -DBUILD_KDC_LIB > > BINPROGRAMS=$(BINDIR)\string2key.exe > >@@ -51,7 +51,9 @@ INCFILES=\ > $(INCDIR)\kdc.h \ > $(INCDIR)\kdc-protos.h \ > $(INCDIR)\kdc-private.h \ >- $(INCDIR)\krb5\windc_plugin.h >+ $(INCDIR)\krb5\kdc-audit.h \ >+ $(INCDIR)\krb5\kdc-plugin.h \ >+ $(INCDIR)\krb5\kdc-accessors.h > > all:: $(INCFILES) $(LIBKDC) $(BINPROGRAMS) $(SBINPROGRAMS) $(LIBEXECPROGRAMS) > >@@ -103,13 +105,14 @@ LIBKDC_OBJS=\ > $(OBJ)\krb5tgs.obj \ > $(OBJ)\pkinit.obj \ > $(OBJ)\pkinit-ec.obj \ >+ $(OBJ)\mssfu.obj \ > $(OBJ)\log.obj \ > $(OBJ)\misc.obj \ > $(OBJ)\kx509.obj \ > $(OBJ)\token_validator.obj \ > $(OBJ)\csr_authorizer.obj \ > $(OBJ)\process.obj \ >- $(OBJ)\windc.obj \ >+ $(OBJ)\kdc-plugin.obj \ > $(OBJ)\gss_preauth.obj > > LIBKDC_LIBS=\ >@@ -144,18 +147,19 @@ libkdc_la_SOURCES = \ > krb5tgs.c \ > pkinit.c \ > pkinit-ec.c \ >+ mssfu.c \ > log.c \ > misc.c \ > kx509.c \ > token_validator.c \ > csr_authorizer.c \ > process.c \ >- windc.c \ >- gss_preauth.c \ >- rx.h >+ kdc-plugin.c \ >+ gss_preauth.c > > $(OBJ)\kdc-protos.h: $(libkdc_la_SOURCES) >- $(PERL) ..\cf\make-proto.pl -q -P remove -o $@ $(libkdc_la_SOURCES) \ >+ cd $(SRCDIR) >+ $(PERL) ..\cf\make-proto.pl -E KDC_LIB -q -P remove -o $@ $(libkdc_la_SOURCES) \ > || $(RM) $@ > > $(OBJ)\kdc-private.h: $(libkdc_la_SOURCES) >diff --git a/third_party/heimdal/kdc/altsecid_gss_preauth_authorizer.c b/third_party/heimdal/kdc/altsecid_gss_preauth_authorizer.c >index 961ced0db9a6..d48ea584bc8e 100644 >--- a/third_party/heimdal/kdc/altsecid_gss_preauth_authorizer.c >+++ b/third_party/heimdal/kdc/altsecid_gss_preauth_authorizer.c >@@ -272,7 +272,7 @@ ad_lookup(krb5_context context, > gss_const_name_t initiator_name, > gss_const_OID mech_type, > krb5_principal *canon_principal, >- krb5_data *requestor_sid) >+ kdc_data_t *requestor_sid) > { > krb5_error_code ret; > OM_uint32 minor; >@@ -286,7 +286,8 @@ ad_lookup(krb5_context context, > struct berval **values = NULL; > > *canon_principal = NULL; >- krb5_data_zero(requestor_sid); >+ if (requestor_sid) >+ *requestor_sid = NULL; > > mech_type_str = gss_oid_to_name(mech_type); > if (mech_type_str == NULL) { >@@ -335,25 +336,29 @@ ad_lookup(krb5_context context, > if (m0 == NULL) > goto out; > >+ values = ldap_get_values_len(server->ld, m0, "sAMAccountName"); >+ if (values == NULL || >+ ldap_count_values_len(values) == 0) >+ goto out; >+ >+ ret = krb5_make_principal(context, canon_principal, realm, >+ values[0]->bv_val, NULL); >+ if (ret) >+ goto out; >+ > if (requestor_sid) { >+ ldap_value_free_len(values); >+ > values = ldap_get_values_len(server->ld, m0, "objectSid"); > if (values == NULL || > ldap_count_values_len(values) == 0) > goto out; > >- if (krb5_data_copy(requestor_sid, values[0]->bv_val, values[0]->bv_len) != 0) >+ *requestor_sid = kdc_data_create(values[0]->bv_val, values[0]->bv_len); >+ if (*requestor_sid == NULL) > goto enomem; >- >- ldap_value_free_len(values); > } > >- values = ldap_get_values_len(server->ld, m0, "sAMAccountName"); >- if (values == NULL || >- ldap_count_values_len(values) == 0) >- goto out; >- >- ret = krb5_make_principal(context, canon_principal, realm, >- values[0]->bv_val, NULL); > goto out; > > enomem: >@@ -361,6 +366,16 @@ enomem: > goto out; > > out: >+ if (ret) { >+ krb5_free_principal(context, *canon_principal); >+ *canon_principal = NULL; >+ >+ if (requestor_sid) { >+ kdc_object_release(*requestor_sid); >+ *requestor_sid = NULL; >+ } >+ } >+ > ldap_value_free_len(values); > ldap_msgfree(m); > ldap_memfree(basedn); >@@ -377,25 +392,27 @@ authorize(void *ctx, > gss_const_OID mech_type, > OM_uint32 ret_flags, > krb5_boolean *authorized, >- krb5_principal *mapped_name, >- krb5_data *requestor_sid) >+ krb5_principal *mapped_name) > { > struct altsecid_gss_preauth_authorizer_context *c = ctx; > struct ad_server_tuple *server = NULL; > krb5_error_code ret; >- krb5_const_realm realm = krb5_principal_get_realm(r->context, r->client->entry.principal); >+ krb5_context context = kdc_request_get_context((kdc_request_t)r); >+ const hdb_entry *client = kdc_request_get_client(r); >+ krb5_const_principal server_princ = kdc_request_get_server_princ(r); >+ krb5_const_realm realm = krb5_principal_get_realm(context, client->principal); > krb5_boolean reconnect_p = FALSE; > krb5_boolean is_tgs; >+ kdc_data_t requestor_sid = NULL; > > *authorized = FALSE; > *mapped_name = NULL; >- krb5_data_zero(requestor_sid); > >- if (!krb5_principal_is_federated(r->context, r->client->entry.principal) || >+ if (!krb5_principal_is_federated(context, client->principal) || > (ret_flags & GSS_C_ANON_FLAG)) > return KRB5_PLUGIN_NO_HANDLE; > >- is_tgs = krb5_principal_is_krbtgt(r->context, r->server_princ); >+ is_tgs = krb5_principal_is_krbtgt(context, server_princ); > > HEIM_TAILQ_FOREACH(server, &c->servers, link) { > if (strcmp(realm, server->realm) == 0) >@@ -405,12 +422,12 @@ authorize(void *ctx, > if (server == NULL) { > server = calloc(1, sizeof(*server)); > if (server == NULL) >- return krb5_enomem(r->context); >+ return krb5_enomem(context); > > server->realm = strdup(realm); > if (server->realm == NULL) { > free(server); >- return krb5_enomem(r->context); >+ return krb5_enomem(context); > } > > HEIM_TAILQ_INSERT_HEAD(&c->servers, server, link); >@@ -418,14 +435,14 @@ authorize(void *ctx, > > do { > if (server->ld == NULL) { >- ret = ad_connect(r->context, realm, server); >+ ret = ad_connect(context, realm, server); > if (ret) > return ret; > } > >- ret = ad_lookup(r->context, realm, server, >+ ret = ad_lookup(context, realm, server, > initiator_name, mech_type, >- mapped_name, is_tgs ? requestor_sid : NULL); >+ mapped_name, is_tgs ? &requestor_sid : NULL); > if (ret == KRB5KDC_ERR_SVC_UNAVAILABLE) { > ldap_unbind_ext_s(server->ld, NULL, NULL); > server->ld = NULL; >@@ -437,17 +454,29 @@ authorize(void *ctx, > *authorized = (ret == 0); > } while (reconnect_p); > >+ if (requestor_sid) { >+ kdc_request_set_attribute((kdc_request_t)r, >+ HSTR("org.h5l.gss-pa-requestor-sid"), requestor_sid); >+ kdc_object_release(requestor_sid); >+ } >+ > return ret; > } > > static KRB5_LIB_CALL krb5_error_code >-finalize_pac(void *ctx, astgs_request_t r, krb5_data *requestor_sid) >+finalize_pac(void *ctx, astgs_request_t r) > { >- if (requestor_sid->length == 0) >+ kdc_data_t requestor_sid; >+ >+ requestor_sid = kdc_request_get_attribute((kdc_request_t)r, >+ HSTR("org.h5l.gss-pa-requestor-sid")); >+ if (requestor_sid == NULL) > return 0; > >- return krb5_pac_add_buffer(r->context, r->pac, >- PAC_REQUESTOR_SID, requestor_sid); >+ kdc_audit_setkv_object((kdc_request_t)r, "gss_requestor_sid", requestor_sid); >+ >+ return kdc_request_add_pac_buffer(r, PAC_REQUESTOR_SID, >+ kdc_data_get_data(requestor_sid)); > } > > static KRB5_LIB_CALL krb5_error_code >@@ -494,8 +523,6 @@ altsecid_gss_preauth_authorizer_get_instance(const char *libname) > return krb5_get_instance(libname); > if (strcmp(libname, "kdc") == 0) > return kdc_get_instance(libname); >- if (strcmp(libname, "gssapi") == 0) >- return gss_get_instance(libname); > return 0; > } > >diff --git a/third_party/heimdal/kdc/bx509d.c b/third_party/heimdal/kdc/bx509d.c >index 2f30744bf31d..064c424b7c29 100644 >--- a/third_party/heimdal/kdc/bx509d.c >+++ b/third_party/heimdal/kdc/bx509d.c >@@ -112,6 +112,22 @@ > #define heim_pconfig krb5_context > #include <heimbase-svc.h> > >+#if MHD_VERSION < 0x00097002 || defined(MHD_YES) >+/* libmicrohttpd changed these from int valued macros to an enum in 0.9.71 */ >+#ifdef MHD_YES >+#undef MHD_YES >+#undef MHD_NO >+#endif >+enum MHD_Result { MHD_NO = 0, MHD_YES = 1 }; >+#define MHD_YES 1 >+#define MHD_NO 0 >+typedef int heim_mhd_result; >+#else >+typedef enum MHD_Result heim_mhd_result; >+#endif >+ >+enum k5_creds_kind { K5_CREDS_EPHEMERAL, K5_CREDS_CACHED }; >+ > typedef struct bx509_request_desc { > HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS; > >@@ -122,6 +138,7 @@ typedef struct bx509_request_desc { > const char *for_cname; > const char *target; > const char *redir; >+ enum k5_creds_kind cckind; > char *pkix_store; > char *ccname; > char *freeme1; >@@ -485,8 +502,8 @@ bad_reqv(struct bx509_request_desc *r, > char *formatted = NULL; > char *msg = NULL; > >- heim_audit_addkv((heim_svc_req_desc)r, 0, "http-status-code", "%d", >- http_status_code); >+ heim_audit_setkv_number((heim_svc_req_desc)r, "http-status-code", >+ http_status_code); > (void) gettimeofday(&r->tv_end, NULL); > if (code == ENOMEM) { > if (r->context) >@@ -511,7 +528,7 @@ bad_reqv(struct bx509_request_desc *r, > msg = formatted; > formatted = NULL; > } >- heim_audit_addreason((heim_svc_req_desc)r, "%s", formatted); >+ heim_audit_addreason((heim_svc_req_desc)r, "%s", msg); > audit_trail(r, code); > krb5_free_error_message(context, k5msg); > >@@ -606,10 +623,20 @@ static krb5_error_code > good_bx509(struct bx509_request_desc *r) > { > krb5_error_code ret; >+ const char *fn; > size_t bodylen; > void *body; > >- ret = rk_undumpdata(strchr(r->pkix_store, ':') + 1, &body, &bodylen); >+ /* >+ * This `fn' thing is just to quiet linters that think "hey, strchr() can >+ * return NULL so...", but here we've build `r->pkix_store' and know it has >+ * a ':'. >+ */ >+ if (r->pkix_store == NULL) >+ return bad_503(r, EINVAL, "Internal error"); /* Quiet warnings */ >+ fn = strchr(r->pkix_store, ':'); >+ fn = fn ? fn + 1 : r->pkix_store; >+ ret = rk_undumpdata(fn, &body, &bodylen); > if (ret) > return bad_503(r, ret, "Could not recover issued certificate " > "from PKIX store"); >@@ -621,7 +648,7 @@ good_bx509(struct bx509_request_desc *r) > return ret; > } > >-static int >+static heim_mhd_result > bx509_param_cb(void *d, > enum MHD_ValueKind kind, > const char *key, >@@ -633,53 +660,53 @@ bx509_param_cb(void *d, > if (strcmp(key, "eku") == 0 && val) { > heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS, "requested_eku", > "%s", val); >- r->ret = der_parse_heim_oid(val, ".", &oid); >- if (r->ret == 0) >- r->ret = hx509_request_add_eku(r->context->hx509ctx, r->req, &oid); >+ r->error_code = der_parse_heim_oid(val, ".", &oid); >+ if (r->error_code == 0) >+ r->error_code = hx509_request_add_eku(r->context->hx509ctx, r->req, &oid); > der_free_oid(&oid); > } else if (strcmp(key, "dNSName") == 0 && val) { > heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS, > "requested_dNSName", "%s", val); >- r->ret = hx509_request_add_dns_name(r->context->hx509ctx, r->req, val); >+ r->error_code = hx509_request_add_dns_name(r->context->hx509ctx, r->req, val); > } else if (strcmp(key, "rfc822Name") == 0 && val) { > heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS, > "requested_rfc822Name", "%s", val); >- r->ret = hx509_request_add_email(r->context->hx509ctx, r->req, val); >+ r->error_code = hx509_request_add_email(r->context->hx509ctx, r->req, val); > } else if (strcmp(key, "xMPPName") == 0 && val) { > heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS, > "requested_xMPPName", "%s", val); >- r->ret = hx509_request_add_xmpp_name(r->context->hx509ctx, r->req, >+ r->error_code = hx509_request_add_xmpp_name(r->context->hx509ctx, r->req, > val); > } else if (strcmp(key, "krb5PrincipalName") == 0 && val) { > heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS, > "requested_krb5PrincipalName", "%s", val); >- r->ret = hx509_request_add_pkinit(r->context->hx509ctx, r->req, >+ r->error_code = hx509_request_add_pkinit(r->context->hx509ctx, r->req, > val); > } else if (strcmp(key, "ms-upn") == 0 && val) { > heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS, > "requested_ms_upn", "%s", val); >- r->ret = hx509_request_add_ms_upn_name(r->context->hx509ctx, r->req, >+ r->error_code = hx509_request_add_ms_upn_name(r->context->hx509ctx, r->req, > val); > } else if (strcmp(key, "registeredID") == 0 && val) { > heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS, > "requested_registered_id", "%s", val); >- r->ret = der_parse_heim_oid(val, ".", &oid); >- if (r->ret == 0) >- r->ret = hx509_request_add_registered(r->context->hx509ctx, r->req, >+ r->error_code = der_parse_heim_oid(val, ".", &oid); >+ if (r->error_code == 0) >+ r->error_code = hx509_request_add_registered(r->context->hx509ctx, r->req, > &oid); > der_free_oid(&oid); > } else if (strcmp(key, "csr") == 0 && val) { >- heim_audit_addkv((heim_svc_req_desc)r, 0, "requested_csr", "true"); >- r->ret = 0; /* Handled upstairs */ >+ heim_audit_setkv_bool((heim_svc_req_desc)r, "requested_csr", TRUE); >+ r->error_code = 0; /* Handled upstairs */ > } else if (strcmp(key, "lifetime") == 0 && val) { > r->req_life = parse_time(val, "day"); > } else { > /* Produce error for unknown params */ >- heim_audit_addkv((heim_svc_req_desc)r, 0, "requested_unknown", "true"); >- krb5_set_error_message(r->context, r->ret = ENOTSUP, >+ heim_audit_setkv_bool((heim_svc_req_desc)r, "requested_unknown", TRUE); >+ krb5_set_error_message(r->context, r->error_code = ENOTSUP, > "Query parameter %s not supported", key); > } >- return r->ret == 0 ? MHD_YES : MHD_NO /* Stop iterating */; >+ return r->error_code == 0 ? MHD_YES : MHD_NO /* Stop iterating */; > } > > static krb5_error_code >@@ -693,10 +720,10 @@ authorize_CSR(struct bx509_request_desc *r, > if (ret) > return bad_req(r, ret, MHD_HTTP_SERVICE_UNAVAILABLE, > "Could not parse CSR"); >- r->ret = 0; >+ r->error_code = 0; > (void) MHD_get_connection_values(r->connection, MHD_GET_ARGUMENT_KIND, > bx509_param_cb, r); >- ret = r->ret; >+ ret = r->error_code; > if (ret) > return bad_req(r, ret, MHD_HTTP_SERVICE_UNAVAILABLE, > "Could not handle query parameters"); >@@ -771,6 +798,7 @@ do_CA(struct bx509_request_desc *r, const char *csr) > /* Set CSR */ > if ((d.data = malloc(strlen(csr2))) == NULL) { > krb5_free_principal(r->context, p); >+ free(csr2); > return bad_enomem(r, ENOMEM); > } > >@@ -818,11 +846,9 @@ do_CA(struct bx509_request_desc *r, const char *csr) > > ret = store_certs(r->context->hx509ctx, r->pkix_store, certs, NULL); > hx509_certs_free(&certs); >- if (ret) { >- (void) unlink(strchr(r->pkix_store, ':') + 1); >- return bad_500(r, ret, >- "Failed convert issued certificate and chain to PEM"); >- } >+ if (ret) >+ return bad_500(r, ret, "Failed to convert issued" >+ " certificate and chain to PEM"); > return 0; > } > >@@ -864,7 +890,7 @@ set_req_desc(struct MHD_Connection *connection, > r->from = r->frombuf; > r->tgt_addresses.len = 0; > r->tgt_addresses.val = 0; >- r->hcontext = r->context->hcontext; >+ r->hcontext = r->context ? r->context->hcontext : NULL; > r->config = NULL; > r->logf = logfac; > r->reqtype = url; >@@ -880,8 +906,11 @@ set_req_desc(struct MHD_Connection *connection, > r->addr = NULL; > r->req = NULL; > r->req_life = 0; >- r->ret = 0; >- r->kv = heim_array_create(); >+ r->error_code = ret; >+ r->kv = heim_dict_create(10); >+ r->attributes = heim_dict_create(1); >+ if (ret == 0 && (r->kv == NULL || r->attributes == NULL)) >+ r->error_code = ret = ENOMEM; > ci = MHD_get_connection_info(connection, > MHD_CONNECTION_INFO_CLIENT_ADDRESS); > if (ci) { >@@ -905,10 +934,6 @@ set_req_desc(struct MHD_Connection *connection, > > } > >- if (ret == 0 && r->kv == NULL) { >- krb5_log_msg(r->context, logfac, 1, NULL, "Out of memory"); >- ret = ENOMEM; >- } > return ret; > } > >@@ -917,12 +942,28 @@ clean_req_desc(struct bx509_request_desc *r) > { > if (!r) > return; >- if (r->pkix_store) >- (void) unlink(strchr(r->pkix_store, ':') + 1); >+ if (r->pkix_store) { >+ const char *fn = strchr(r->pkix_store, ':'); >+ >+ /* >+ * This `fn' thing is just to quiet linters that think "hey, strchr() can >+ * return NULL so...", but here we've build `r->pkix_store' and know it has >+ * a ':'. >+ */ >+ fn = fn ? fn + 1 : r->pkix_store; >+ (void) unlink(fn); >+ } > krb5_free_addresses(r->context, &r->tgt_addresses); > hx509_request_free(&r->req); > heim_release(r->reason); > heim_release(r->kv); >+ if (r->ccname && r->cckind == K5_CREDS_EPHEMERAL) { >+ const char *fn = r->ccname; >+ >+ if (strncmp(fn, "FILE:", sizeof("FILE:") - 1) == 0) >+ fn += sizeof("FILE:") - 1; >+ (void) unlink(fn); >+ } > free(r->pkix_store); > free(r->freeme1); > free(r->ccname); >@@ -966,6 +1007,8 @@ bx509(struct bx509_request_desc *r) > * '~' and '.' also get encoded, and '@' does not. > * > * A corresponding decoder is not needed. >+ * >+ * XXX Maybe use krb5_cc_default_for()! > */ > static size_t > princ_fs_encode_sz(const char *in) >@@ -1045,8 +1088,10 @@ find_ccache(krb5_context context, const char *princ, char **ccname) > */ > if ((s = princ_fs_encode(princ)) == NULL || > asprintf(ccname, "FILE:%s/%s.cc", cache_dir, s) == -1 || >- *ccname == NULL) >+ *ccname == NULL) { >+ free(s); > return ENOMEM; >+ } > free(s); > > if ((ret = krb5_cc_resolve(context, *ccname, &cc))) { >@@ -1067,13 +1112,10 @@ find_ccache(krb5_context context, const char *princ, char **ccname) > return ret ? ret : ENOENT; > } > >-enum k5_creds_kind { K5_CREDS_EPHEMERAL, K5_CREDS_CACHED }; >- > static krb5_error_code > get_ccache(struct bx509_request_desc *r, krb5_ccache *cc, int *won) > { > krb5_error_code ret = 0; >- struct stat st1, st2; > char *temp_ccname = NULL; > const char *fn = NULL; > time_t life; >@@ -1103,6 +1145,7 @@ get_ccache(struct bx509_request_desc *r, krb5_ccache *cc, int *won) > if (ret == 0) > fn = temp_ccname + sizeof("FILE:") - 1; > if (ret == 0) do { >+ struct stat st1, st2; > /* > * Open and flock the temp ccache file. > * >@@ -1115,6 +1158,8 @@ get_ccache(struct bx509_request_desc *r, krb5_ccache *cc, int *won) > fd = -1; > } > errno = 0; >+ memset(&st1, 0, sizeof(st1)); >+ memset(&st2, 0xff, sizeof(st2)); > if (ret == 0 && > ((fd = open(fn, O_RDWR | O_CREAT, 0600)) == -1 || > flock(fd, LOCK_EX) == -1 || >@@ -1186,7 +1231,8 @@ do_pkinit(struct bx509_request_desc *r, enum k5_creds_kind kind) > ret = krb5_cc_new_unique(r->context, "FILE", NULL, &temp_cc); > } > >- ret = krb5_parse_name(r->context, cname, &p); >+ if (ret == 0) >+ ret = krb5_parse_name(r->context, cname, &p); > if (ret == 0) > crealm = krb5_principal_get_realm(r->context, p); > if (ret == 0) >@@ -1304,7 +1350,7 @@ k5_do_CA(struct bx509_request_desc *r) > if (ret == 0) > ret = krb5_parse_name(r->context, cname, &p); > if (ret == 0) >- hx509_private_key2SPKI(r->context->hx509ctx, key, &spki); >+ ret = hx509_private_key2SPKI(r->context->hx509ctx, key, &spki); > if (ret == 0) > hx509_request_set_SubjectPublicKeyInfo(r->context->hx509ctx, req, > &spki); >@@ -1366,6 +1412,7 @@ k5_get_creds(struct bx509_request_desc *r, enum k5_creds_kind kind) > const char *cname = r->for_cname ? r->for_cname : r->cname; > > /* If we have a live ccache for `cprinc', we're done */ >+ r->cckind = kind; > if (kind == K5_CREDS_CACHED && > (ret = find_ccache(r->context, cname, &r->ccname)) == 0) > return ret; /* Success */ >@@ -1638,8 +1685,7 @@ bnegotiate(struct bx509_request_desc *r) > if (ret == 0) { > heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS, "target", "%s", > r->target ? r->target : "<unknown>"); >- heim_audit_addkv((heim_svc_req_desc)r, 0, "redir", "%s", >- r->redir ? "yes" : "no"); >+ heim_audit_setkv_bool((heim_svc_req_desc)r, "redir", !!r->redir); > ret = validate_token(r); > } > /* bnegotiate_get_target() and validate_token() call bad_req() */ >@@ -1688,7 +1734,8 @@ authorize_TGT_REQ(struct bx509_request_desc *r) > return 0; > > ret = krb5_parse_name(r->context, r->cname, &p); >- ret = hx509_request_init(r->context->hx509ctx, &r->req); >+ if (ret == 0) >+ ret = hx509_request_init(r->context->hx509ctx, &r->req); > if (ret) > return bad_500(r, ret, "Out of resources"); > heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS, >@@ -1707,7 +1754,7 @@ authorize_TGT_REQ(struct bx509_request_desc *r) > return ret; > } > >-static int >+static heim_mhd_result > get_tgt_param_cb(void *d, > enum MHD_ValueKind kind, > const char *key, >@@ -1719,15 +1766,15 @@ get_tgt_param_cb(void *d, > if (!krb5_config_get_bool_default(r->context, NULL, > FALSE, > "get-tgt", "allow_addresses", NULL)) { >- krb5_set_error_message(r->context, r->ret = ENOTSUP, >+ krb5_set_error_message(r->context, r->error_code = ENOTSUP, > "Query parameter %s not allowed", key); > } else { > krb5_addresses addresses; > >- r->ret = _krb5_parse_address_no_lookup(r->context, val, >+ r->error_code = _krb5_parse_address_no_lookup(r->context, val, > &addresses); >- if (r->ret == 0) >- r->ret = krb5_append_addresses(r->context, &r->tgt_addresses, >+ if (r->error_code == 0) >+ r->error_code = krb5_append_addresses(r->context, &r->tgt_addresses, > &addresses); > krb5_free_addresses(r->context, &addresses); > } >@@ -1738,11 +1785,11 @@ get_tgt_param_cb(void *d, > r->req_life = parse_time(val, "day"); > } else { > /* Produce error for unknown params */ >- heim_audit_addkv((heim_svc_req_desc)r, 0, "requested_unknown", "true"); >- krb5_set_error_message(r->context, r->ret = ENOTSUP, >+ heim_audit_setkv_bool((heim_svc_req_desc)r, "requested_unknown", TRUE); >+ krb5_set_error_message(r->context, r->error_code = ENOTSUP, > "Query parameter %s not supported", key); > } >- return r->ret == 0 ? MHD_YES : MHD_NO /* Stop iterating */; >+ return r->error_code == 0 ? MHD_YES : MHD_NO /* Stop iterating */; > } > > /* >@@ -1772,13 +1819,14 @@ get_tgt(struct bx509_request_desc *r) > if (ret) > return ret; > >- r->ret = 0; >+ r->error_code = 0; > (void) MHD_get_connection_values(r->connection, MHD_GET_ARGUMENT_KIND, > get_tgt_param_cb, r); >- ret = r->ret; >+ ret = r->error_code; > > /* k5_get_creds() calls bad_req() */ >- ret = k5_get_creds(r, K5_CREDS_EPHEMERAL); >+ if (ret == 0) >+ ret = k5_get_creds(r, K5_CREDS_EPHEMERAL); > if (ret) > return ret; > >@@ -1786,10 +1834,8 @@ get_tgt(struct bx509_request_desc *r) > if (fn == NULL) > return bad_500(r, ret, "Impossible error"); > fn++; >- if ((errno = rk_undumpdata(fn, &body, &bodylen))) { >- (void) unlink(fn); >+ if ((errno = rk_undumpdata(fn, &body, &bodylen))) > return bad_503(r, ret, "Could not get TGT"); >- } > > ret = resp(r, MHD_HTTP_OK, MHD_RESPMEM_MUST_COPY, > "application/x-krb5-ccache", body, bodylen, NULL); >@@ -1811,7 +1857,7 @@ health(const char *method, struct bx509_request_desc *r) > } > > /* Implements the entirety of this REST service */ >-static int >+static heim_mhd_result > route(void *cls, > struct MHD_Connection *connection, > const char *url, >@@ -2013,6 +2059,8 @@ main(int argc, char **argv) > > argc -= optidx; > argv += optidx; >+ if (argc != 0) >+ usage(1); > > if ((errno = pthread_key_create(&k5ctx, k5_free_context))) > err(1, "Could not create thread-specific storage"); >diff --git a/third_party/heimdal/kdc/ca.c b/third_party/heimdal/kdc/ca.c >index 0d92ca7fc89f..4402c44677fb 100644 >--- a/third_party/heimdal/kdc/ca.c >+++ b/third_party/heimdal/kdc/ca.c >@@ -97,7 +97,7 @@ get_cf(krb5_context context, > /* > * Build a certifate for `principal' and its CSR. > */ >-krb5_error_code >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL > kdc_issue_certificate(krb5_context context, > const char *app_name, > krb5_log_facility *logf, >@@ -129,5 +129,5 @@ kdc_issue_certificate(krb5_context context, > out); > if (ret == EACCES) > ret = KRB5KDC_ERR_POLICY; >- return (ret == EACCES) ? KRB5KDC_ERR_POLICY : ret; >+ return ret; > } >diff --git a/third_party/heimdal/kdc/cjwt_token_validator.c b/third_party/heimdal/kdc/cjwt_token_validator.c >index 68fe01594f8e..93742e5ddd55 100644 >--- a/third_party/heimdal/kdc/cjwt_token_validator.c >+++ b/third_party/heimdal/kdc/cjwt_token_validator.c >@@ -107,13 +107,13 @@ get_issuer_pubkeys(krb5_context context, > if (!previous->length && !current->length && !next->length) > krb5_set_error_message(context, save_ret, > "Could not read jwk issuer public key files"); >- if (current->length == next->length && >+ if (current->length && current->length == next->length && > memcmp(current->data, next->data, next->length) == 0) { > free(next->data); > next->data = 0; > next->length = 0; > } >- if (current->length == previous->length && >+ if (current->length && current->length == previous->length && > memcmp(current->data, previous->data, previous->length) == 0) { > free(previous->data); > previous->data = 0; >@@ -255,6 +255,11 @@ validate(void *ctx, > tokstr = NULL; > switch (ret) { > case 0: >+ if (jwt == NULL) { >+ krb5_set_error_message(context, EINVAL, "JWT validation failed"); >+ free(defrealm); >+ return EPERM; >+ } > if (jwt->header.alg == alg_none) { > krb5_set_error_message(context, EINVAL, "JWT signature algorithm " > "not supported"); >diff --git a/third_party/heimdal/kdc/config.c b/third_party/heimdal/kdc/config.c >index 507cb195af3f..e217b9dadfa5 100644 >--- a/third_party/heimdal/kdc/config.c >+++ b/third_party/heimdal/kdc/config.c >@@ -309,7 +309,7 @@ configure(krb5_context context, int argc, char **argv, int *optidx) > krb5_enctype_disable(context, ETYPE_DES_PCBC_NONE); > } > >- krb5_kdc_windc_init(context); >+ krb5_kdc_plugin_init(context); > > krb5_kdc_pkinit_config(context, config); > >diff --git a/third_party/heimdal/kdc/connect.c b/third_party/heimdal/kdc/connect.c >index 975f24cb269a..ba8c8ad7ba54 100644 >--- a/third_party/heimdal/kdc/connect.c >+++ b/third_party/heimdal/kdc/connect.c >@@ -263,7 +263,8 @@ init_socket(krb5_context context, > #if defined(HAVE_SETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_REUSEADDR) > { > int one = 1; >- setsockopt(d->s, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)); >+ (void) setsockopt(d->s, SOL_SOCKET, SO_REUSEADDR, (void *)&one, >+ sizeof(one)); > } > #endif > d->type = type; >@@ -620,15 +621,22 @@ handle_vanilla_tcp (krb5_context context, > krb5_kdc_configuration *config, > struct descr *d) > { >+ krb5_error_code ret; > krb5_storage *sp; > uint32_t len; > >+ if (d->len < 4) >+ return 0; > sp = krb5_storage_from_mem(d->buf, d->len); > if (sp == NULL) { > kdc_log (context, config, 1, "krb5_storage_from_mem failed"); > return -1; > } >- krb5_ret_uint32(sp, &len); >+ ret = krb5_ret_uint32(sp, &len); >+ if (ret) { >+ kdc_log(context, config, 4, "failed to read request length"); >+ return -1; >+ } > krb5_storage_free(sp); > if(d->len - 4 >= len) { > memmove(d->buf, d->buf + 4, d->len - 4); >@@ -1064,7 +1072,7 @@ reap_kid(krb5_context context, krb5_kdc_configuration *config, > pid_t *pids, int max_kids, int options) > { > pid_t pid; >- char *what; >+ char *what = "untracked"; > int status; > int i = 0; /* quiet warnings */ > int ret = 0; >@@ -1090,7 +1098,6 @@ reap_kid(krb5_context context, krb5_kdc_configuration *config, > > if (i == max_kids) { > /* should not happen */ >- what = "untracked"; > sev = "warning: "; > level = 2; > } >@@ -1156,7 +1163,7 @@ start_kdc(krb5_context context, > #endif > > #ifdef __APPLE__ >- if (do_bonjour > 0) >+ if (!testing_flag && do_bonjour > 0) > bonjour_kid(context, config, argv0, NULL); > #endif > >@@ -1191,7 +1198,7 @@ start_kdc(krb5_context context, > #ifdef HAVE_FORK > > # ifdef __APPLE__ >- if (do_bonjour < 0) >+ if (!testing_flag && do_bonjour < 0) > bonjour_kid(context, config, argv0, islive); > # endif > >diff --git a/third_party/heimdal/kdc/csr_authorizer.c b/third_party/heimdal/kdc/csr_authorizer.c >index fa20519d73a6..52bc37c42965 100644 >--- a/third_party/heimdal/kdc/csr_authorizer.c >+++ b/third_party/heimdal/kdc/csr_authorizer.c >@@ -65,7 +65,7 @@ static struct heim_plugin_data csr_authorizer_data = { > * Invoke a plugin to validate a JWT/SAML/OIDC token and partially-evaluate > * access control. > */ >-krb5_error_code >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL > kdc_authorize_csr(krb5_context context, > const char *app, > hx509_request csr, >diff --git a/third_party/heimdal/kdc/default_config.c b/third_party/heimdal/kdc/default_config.c >index 627dc74f4580..01f8f7b54a69 100644 >--- a/third_party/heimdal/kdc/default_config.c >+++ b/third_party/heimdal/kdc/default_config.c >@@ -69,7 +69,7 @@ load_kdc_plugins_once(void *ctx) > #endif > } > >-krb5_error_code >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL > krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) > { > static heim_base_once_t load_kdc_plugins = HEIM_BASE_ONCE_INIT; >@@ -93,7 +93,6 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) > c->preauth_use_strongest_session_key = FALSE; > c->svc_use_strongest_session_key = FALSE; > c->use_strongest_server_key = TRUE; >- c->autodetect_referrals = TRUE; > c->check_ticket_addresses = TRUE; > c->warn_ticket_addresses = FALSE; > c->allow_null_ticket_addresses = TRUE; >@@ -392,7 +391,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) > return 0; > } > >-krb5_error_code >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL > krb5_kdc_pkinit_config(krb5_context context, krb5_kdc_configuration *config) > { > #ifdef PKINIT >diff --git a/third_party/heimdal/kdc/digest-service.c b/third_party/heimdal/kdc/digest-service.c >index 3a4f4c551db6..4ea76dbe7e28 100644 >--- a/third_party/heimdal/kdc/digest-service.c >+++ b/third_party/heimdal/kdc/digest-service.c >@@ -60,7 +60,8 @@ ntlm_service(void *ctx, const heim_idata *req, > unsigned char sessionkey[16]; > heim_idata rep = { 0, NULL }; > krb5_context context = ctx; >- hdb_entry_ex *user = NULL; >+ hdb_entry *user = NULL; >+ HDB *db = NULL; > Key *key = NULL; > NTLMReply ntp; > size_t size; >@@ -113,12 +114,12 @@ ntlm_service(void *ctx, const heim_idata *req, > krb5_principal_set_type(context, client, KRB5_NT_NTLM); > > ret = _kdc_db_fetch(context, config, client, >- HDB_F_GET_CLIENT, NULL, NULL, &user); >+ HDB_F_GET_CLIENT, NULL, &db, &user); > krb5_free_principal(context, client); > if (ret) > goto failed; > >- ret = hdb_enctype2key(context, &user->entry, NULL, >+ ret = hdb_enctype2key(context, user, NULL, > ETYPE_ARCFOUR_HMAC_MD5, &key); > if (ret) { > krb5_set_error_message(context, ret, "NTLM missing arcfour key"); >@@ -213,7 +214,7 @@ ntlm_service(void *ctx, const heim_idata *req, > > free_NTLMRequest2(&ntq); > if (user) >- _kdc_free_ent (context, user); >+ _kdc_free_ent (context, db, user); > } > > static int help_flag; >diff --git a/third_party/heimdal/kdc/digest.c b/third_party/heimdal/kdc/digest.c >index a8652891f535..092b4a75a4be 100644 >--- a/third_party/heimdal/kdc/digest.c >+++ b/third_party/heimdal/kdc/digest.c >@@ -57,7 +57,7 @@ const struct units _kdc_digestunits[] = { > static krb5_error_code > get_digest_key(krb5_context context, > krb5_kdc_configuration *config, >- hdb_entry_ex *server, >+ hdb_entry *server, > krb5_crypto *crypto) > { > krb5_error_code ret; >@@ -81,12 +81,12 @@ get_digest_key(krb5_context context, > > static char * > get_ntlm_targetname(krb5_context context, >- hdb_entry_ex *client) >+ hdb_entry *client) > { > char *targetname, *p; > > targetname = strdup(krb5_principal_get_realm(context, >- client->entry.principal)); >+ client->principal)); > if (targetname == NULL) > return NULL; > >@@ -101,7 +101,7 @@ get_ntlm_targetname(krb5_context context, > static krb5_error_code > fill_targetinfo(krb5_context context, > char *targetname, >- hdb_entry_ex *client, >+ hdb_entry *client, > krb5_data *data) > { > struct ntlm_targetinfo ti; >@@ -113,7 +113,7 @@ fill_targetinfo(krb5_context context, > memset(&ti, 0, sizeof(ti)); > > ti.domainname = targetname; >- p = client->entry.principal; >+ p = client->principal; > str = krb5_principal_get_comp_string(context, p, 0); > if (str != NULL && > (strcmp("host", str) == 0 || >@@ -168,7 +168,7 @@ get_password_entry(krb5_context context, > { > krb5_principal clientprincipal; > krb5_error_code ret; >- hdb_entry_ex *user; >+ hdb_entry *user; > HDB *db; > > /* get username */ >@@ -182,7 +182,7 @@ get_password_entry(krb5_context context, > if (ret) > return ret; > >- ret = hdb_entry_get_password(context, db, &user->entry, password); >+ ret = hdb_entry_get_password(context, db, user, password); > if (ret || password == NULL) { > if (ret == 0) { > ret = EINVAL; >@@ -190,7 +190,7 @@ get_password_entry(krb5_context context, > } > memset(user, 0, sizeof(*user)); > } >- _kdc_free_ent (context, user); >+ _kdc_free_ent (context, db, user); > return ret; > } > >@@ -217,8 +217,10 @@ _kdc_do_digest(krb5_context context, > size_t size; > krb5_storage *sp = NULL; > Checksum res; >- hdb_entry_ex *server = NULL, *user = NULL; >- hdb_entry_ex *client = NULL; >+ HDB *serverdb, *userdb; >+ hdb_entry *server = NULL, *user = NULL; >+ HDB *clientdb; >+ hdb_entry *client = NULL; > char *client_name = NULL, *password = NULL; > krb5_data serverNonce; > >@@ -292,7 +294,7 @@ _kdc_do_digest(krb5_context context, > krb5_clear_error_message(context); > > ret = _kdc_db_fetch(context, config, principal, >- HDB_F_GET_SERVER, NULL, NULL, &server); >+ HDB_F_GET_SERVER, NULL, &serverdb, &server); > if (ret) > goto out; > >@@ -314,12 +316,12 @@ _kdc_do_digest(krb5_context context, > } > > ret = _kdc_db_fetch(context, config, principal, >- HDB_F_GET_CLIENT, NULL, NULL, &client); >+ HDB_F_GET_CLIENT, NULL, &clientdb, &client); > krb5_free_principal(context, principal); > if (ret) > goto out; > >- if (client->entry.flags.allow_digest == 0) { >+ if (client->flags.allow_digest == 0) { > kdc_log(context, config, 2, > "Client %s tried to use digest " > "but is not allowed to", >@@ -877,7 +879,7 @@ _kdc_do_digest(krb5_context context, > goto failed; > > ret = _kdc_db_fetch(context, config, clientprincipal, >- HDB_F_GET_CLIENT, NULL, NULL, &user); >+ HDB_F_GET_CLIENT, NULL, &userdb, &user); > krb5_free_principal(context, clientprincipal); > if (ret) { > krb5_set_error_message(context, ret, >@@ -886,7 +888,7 @@ _kdc_do_digest(krb5_context context, > goto failed; > } > >- ret = hdb_enctype2key(context, &user->entry, NULL, >+ ret = hdb_enctype2key(context, user, NULL, > ETYPE_ARCFOUR_HMAC_MD5, &key); > if (ret) { > krb5_set_error_message(context, ret, >@@ -1163,7 +1165,7 @@ _kdc_do_digest(krb5_context context, > goto failed; > > ret = _kdc_db_fetch(context, config, clientprincipal, >- HDB_F_GET_CLIENT, NULL, NULL, &user); >+ HDB_F_GET_CLIENT, NULL, &userdb, &user); > krb5_free_principal(context, clientprincipal); > if (ret) { > krb5_set_error_message(context, ret, "NTLM user %s not in database", >@@ -1214,7 +1216,7 @@ _kdc_do_digest(krb5_context context, > goto out; > } > >- ret = hdb_enctype2key(context, &user->entry, NULL, >+ ret = hdb_enctype2key(context, user, NULL, > ETYPE_ARCFOUR_HMAC_MD5, &key); > if (ret) { > krb5_set_error_message(context, ret, "NTLM missing arcfour key"); >@@ -1466,6 +1468,10 @@ _kdc_do_digest(krb5_context context, > ret = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_DIGEST_ENCRYPT, > buf.data, buf.length, 0, > &rep.innerRep); >+ if (ret) { >+ krb5_prepend_error_message(context, ret, "Failed to encrypt digest: "); >+ goto out; >+ } > > ASN1_MALLOC_ENCODE(DigestREP, reply->data, reply->length, &rep, &size, ret); > if (ret) { >@@ -1490,11 +1496,11 @@ _kdc_do_digest(krb5_context context, > if (sp) > krb5_storage_free(sp); > if (user) >- _kdc_free_ent (context, user); >+ _kdc_free_ent (context, userdb, user); > if (server) >- _kdc_free_ent (context, server); >+ _kdc_free_ent (context, serverdb, server); > if (client) >- _kdc_free_ent (context, client); >+ _kdc_free_ent (context, clientdb, client); > if (password) { > memset(password, 0, strlen(password)); > free (password); >diff --git a/third_party/heimdal/kdc/fast.c b/third_party/heimdal/kdc/fast.c >index d4cd650284b8..25cab3096b7f 100644 >--- a/third_party/heimdal/kdc/fast.c >+++ b/third_party/heimdal/kdc/fast.c >@@ -108,7 +108,8 @@ get_fastuser_crypto(astgs_request_t r, > krb5_crypto *crypto) > { > krb5_principal fast_princ; >- hdb_entry_ex *fast_user = NULL; >+ HDB *fast_db; >+ hdb_entry *fast_user = NULL; > Key *cookie_key = NULL; > krb5_crypto fast_crypto = NULL; > krb5_error_code ret; >@@ -122,7 +123,7 @@ get_fastuser_crypto(astgs_request_t r, > goto out; > > ret = _kdc_db_fetch(r->context, r->config, fast_princ, >- HDB_F_GET_FAST_COOKIE, NULL, NULL, &fast_user); >+ HDB_F_GET_FAST_COOKIE, NULL, &fast_db, &fast_user); > if (ret) > goto out; > >@@ -130,7 +131,7 @@ get_fastuser_crypto(astgs_request_t r, > ret = _kdc_get_preferred_key(r->context, r->config, fast_user, > "fast-cookie", &enctype, &cookie_key); > else >- ret = hdb_enctype2key(r->context, &fast_user->entry, NULL, >+ ret = hdb_enctype2key(r->context, fast_user, NULL, > enctype, &cookie_key); > if (ret) > goto out; >@@ -148,7 +149,7 @@ get_fastuser_crypto(astgs_request_t r, > > out: > if (fast_user) >- _kdc_free_ent(r->context, fast_user); >+ _kdc_free_ent(r->context, fast_db, fast_user); > if (fast_crypto) > krb5_crypto_destroy(r->context, fast_crypto); > krb5_free_principal(r->context, fast_princ); >@@ -457,7 +458,7 @@ fast_unwrap_request(astgs_request_t r, > krb5_principal armor_server_principal = NULL; > char *armor_client_principal_name = NULL; > char *armor_server_principal_name = NULL; >- PA_FX_FAST_REQUEST fxreq = {0}; >+ PA_FX_FAST_REQUEST fxreq; > krb5_auth_context ac = NULL; > krb5_ticket *ticket = NULL; > krb5_flags ap_req_options; >@@ -466,12 +467,15 @@ fast_unwrap_request(astgs_request_t r, > krb5_boolean explicit_armor; > krb5_error_code ret; > krb5_ap_req ap_req; >- KrbFastReq fastreq = {0}; >+ KrbFastReq fastreq; > const PA_DATA *pa; > krb5_data data; > size_t len; > int i = 0; > >+ memset(&fxreq, 0, sizeof(fxreq)); >+ memset(&fastreq, 0, sizeof(fastreq)); >+ > pa = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FX_FAST); > if (pa == NULL) { > if (tgs_ac && r->fast_asserted) { >@@ -548,7 +552,7 @@ fast_unwrap_request(astgs_request_t r, > ret = _kdc_db_fetch(r->context, r->config, armor_server_principal, > HDB_F_GET_KRBTGT | HDB_F_DELAY_NEW_KEYS, > (krb5uint32 *)ap_req.ticket.enc_part.kvno, >- NULL, &r->armor_server); >+ &r->armor_serverdb, &r->armor_server); > if(ret == HDB_ERR_NOT_FOUND_HERE) { > free_AP_REQ(&ap_req); > kdc_log(r->context, r->config, 5, >@@ -561,7 +565,7 @@ fast_unwrap_request(astgs_request_t r, > goto out; > } > >- ret = hdb_enctype2key(r->context, &r->armor_server->entry, NULL, >+ ret = hdb_enctype2key(r->context, r->armor_server, NULL, > ap_req.ticket.enc_part.etype, > &r->armor_key); > if (ret) { >@@ -591,8 +595,8 @@ fast_unwrap_request(astgs_request_t r, > &r->armor_ticket->ticket, > armor_server_principal_name); > if (ret) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Armor TGT expired or invalid"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Armor TGT expired or invalid"); > goto out; > } > ticket = r->armor_ticket; >@@ -603,8 +607,8 @@ fast_unwrap_request(astgs_request_t r, > } > > krb5_unparse_name(r->context, ticket->client, &armor_client_principal_name); >- _kdc_audit_addkv((kdc_request_t)r, 0, "armor_client_name", "%s", >- armor_client_principal_name ? armor_client_principal_name : "<unknown>"); >+ kdc_audit_addkv((kdc_request_t)r, 0, "armor_client_name", "%s", >+ armor_client_principal_name ? armor_client_principal_name : "<unknown>"); > > if (ac->remote_subkey == NULL) { > krb5_auth_con_free(r->context, ac); >@@ -833,7 +837,8 @@ _kdc_fast_check_armor_pac(astgs_request_t r) > krb5_boolean ad_kdc_issued = FALSE; > krb5_pac mspac = NULL; > krb5_principal armor_client_principal = NULL; >- hdb_entry_ex *armor_client = NULL; >+ HDB *armor_db; >+ hdb_entry *armor_client = NULL; > char *armor_client_principal_name = NULL; > > flags = HDB_F_FOR_TGS_REQ; >@@ -856,7 +861,7 @@ _kdc_fast_check_armor_pac(astgs_request_t r) > > ret = _kdc_db_fetch_client(r->context, r->config, flags, > armor_client_principal, armor_client_principal_name, >- r->req.req_body.realm, NULL, &armor_client); >+ r->req.req_body.realm, &armor_db, &armor_client); > if (ret) > goto out; > >@@ -885,7 +890,7 @@ _kdc_fast_check_armor_pac(astgs_request_t r) > out: > krb5_xfree(armor_client_principal_name); > if (armor_client) >- _kdc_free_ent(r->context, armor_client); >+ _kdc_free_ent(r->context, armor_db, armor_client); > krb5_free_principal(r->context, armor_client_principal); > krb5_pac_free(r->context, mspac); > >diff --git a/third_party/heimdal/kdc/gss_preauth.c b/third_party/heimdal/kdc/gss_preauth.c >index ce62a29afccc..d8a2a24fd941 100644 >--- a/third_party/heimdal/kdc/gss_preauth.c >+++ b/third_party/heimdal/kdc/gss_preauth.c >@@ -51,7 +51,6 @@ struct gss_client_params { > OM_uint32 flags; > OM_uint32 lifetime; > krb5_checksum req_body_checksum; >- krb5_data pac_data; > }; > > static void >@@ -66,6 +65,9 @@ pa_gss_display_name(gss_name_t name, > gss_buffer_t namebuf, > gss_const_buffer_t *namebuf_p); > >+static void HEIM_CALLCONV >+pa_gss_dealloc_client_params(void *ptr); >+ > /* > * Create a checksum over KDC-REQ-BODY (without the nonce), used to > * assert the request is invariant within the preauth conversation. >@@ -132,6 +134,7 @@ pa_gss_decode_context_state(astgs_request_t r, > krb5_storage *sp; > size_t cksumsize; > krb5_data data; >+ int32_t cksumtype; > > memset(req_body_checksum, 0, sizeof(*req_body_checksum)); > sec_context_token->length = 0; >@@ -152,10 +155,12 @@ pa_gss_decode_context_state(astgs_request_t r, > if (ret) > goto out; > >- ret = krb5_ret_int32(sp, &req_body_checksum->cksumtype); >+ ret = krb5_ret_int32(sp, &cksumtype); > if (ret) > goto out; > >+ req_body_checksum->cksumtype = (CKSUMTYPE)cksumtype; >+ > if (req_body_checksum->cksumtype == CKSUMTYPE_NONE || > krb5_checksum_is_keyed(r->context, req_body_checksum->cksumtype)) { > ret = KRB5KDC_ERR_SUMTYPE_NOSUPP; >@@ -271,7 +276,7 @@ pa_gss_encode_context_state(astgs_request_t r, > if (ret) > goto out; > >- ret = krb5_store_int32(sp, req_body_checksum->cksumtype); >+ ret = krb5_store_int32(sp, (int32_t)req_body_checksum->cksumtype); > if (ret) > goto out; > >@@ -421,7 +426,7 @@ _kdc_gss_rd_padata(astgs_request_t r, > goto out; > } > >- gcp = calloc(1, sizeof(*gcp)); >+ gcp = kdc_object_alloc(sizeof(*gcp), "pa-gss-client-params", pa_gss_dealloc_client_params); > if (gcp == NULL) { > ret = krb5_enomem(r->context); > goto out; >@@ -471,7 +476,7 @@ out: > if (gcp && gcp->major != GSS_S_NO_CONTEXT) > *pgcp = gcp; > else >- _kdc_gss_free_client_param(r, gcp); >+ kdc_object_release(gcp); > > return ret; > } >@@ -498,7 +503,6 @@ struct pa_gss_authorize_plugin_ctx { > struct gss_client_params *gcp; > krb5_boolean authorized; > krb5_principal initiator_princ; >- krb5_data pac_data; > }; > > static krb5_error_code KRB5_LIB_CALL >@@ -516,8 +520,7 @@ pa_gss_authorize_cb(krb5_context context, > pa_gss_authorize_plugin_ctx->gcp->mech_type, > pa_gss_authorize_plugin_ctx->gcp->flags, > &pa_gss_authorize_plugin_ctx->authorized, >- &pa_gss_authorize_plugin_ctx->initiator_princ, >- &pa_gss_authorize_plugin_ctx->pac_data); >+ &pa_gss_authorize_plugin_ctx->initiator_princ); > } > > static const char *plugin_deps[] = { >@@ -542,8 +545,7 @@ pa_gss_authorize_plugin(astgs_request_t r, > struct gss_client_params *gcp, > gss_const_buffer_t display_name, > krb5_boolean *authorized, >- krb5_principal *initiator_princ, >- krb5_data *pac_data) >+ krb5_principal *initiator_princ) > { > krb5_error_code ret; > struct pa_gss_authorize_plugin_ctx ctx; >@@ -552,7 +554,6 @@ pa_gss_authorize_plugin(astgs_request_t r, > ctx.gcp = gcp; > ctx.authorized = 0; > ctx.initiator_princ = NULL; >- krb5_data_zero(&ctx.pac_data); > > krb5_clear_error_message(r->context); > ret = _krb5_plugin_run_f(r->context, &gss_preauth_authorizer_data, >@@ -573,7 +574,6 @@ pa_gss_authorize_plugin(astgs_request_t r, > > *authorized = ctx.authorized; > *initiator_princ = ctx.initiator_princ; >- *pac_data = ctx.pac_data; > > return ret; > } >@@ -583,12 +583,11 @@ pa_gss_authorize_default(astgs_request_t r, > struct gss_client_params *gcp, > gss_const_buffer_t display_name, > krb5_boolean *authorized, >- krb5_principal *initiator_princ, >- krb5_data *pac_data) >+ krb5_principal *initiator_princ) > { > krb5_error_code ret; > krb5_principal principal; >- krb5_const_realm realm = r->server->entry.principal->realm; >+ krb5_const_realm realm = r->server->principal->realm; > int flags = 0, cross_realm_allowed = 0, unauth_anon; > > /* >@@ -684,16 +683,15 @@ _kdc_gss_check_client(astgs_request_t r, > { > krb5_error_code ret; > krb5_principal initiator_princ = NULL; >- hdb_entry_ex *initiator = NULL; >+ hdb_entry *initiator = NULL; > krb5_boolean authorized = FALSE; >- krb5_data pac_data; >+ HDB *clientdb = r->clientdb; > > OM_uint32 minor; > gss_buffer_desc display_name = GSS_C_EMPTY_BUFFER; > gss_const_buffer_t display_name_p; > > *client_name = NULL; >- krb5_data_zero(&pac_data); > > pa_gss_display_name(gcp->initiator_name, &display_name, &display_name_p); > >@@ -702,10 +700,10 @@ _kdc_gss_check_client(astgs_request_t r, > * are authorized as the directly corresponding Kerberos principal. > */ > ret = pa_gss_authorize_plugin(r, gcp, display_name_p, >- &authorized, &initiator_princ, &pac_data); >+ &authorized, &initiator_princ); > if (ret == KRB5_PLUGIN_NO_HANDLE) > ret = pa_gss_authorize_default(r, gcp, display_name_p, >- &authorized, &initiator_princ, &pac_data); >+ &authorized, &initiator_princ); > if (ret == 0 && !authorized) > ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; > if (ret) >@@ -745,15 +743,15 @@ _kdc_gss_check_client(astgs_request_t r, > * two principals must match, noting that GSS pre-authentication is > * for authentication, not general purpose impersonation. > */ >- if (krb5_principal_is_federated(r->context, r->client->entry.principal)) { >- initiator->entry.flags.force_canonicalize = 1; >+ if (krb5_principal_is_federated(r->context, r->client->principal)) { >+ initiator->flags.force_canonicalize = 1; > >- _kdc_free_ent(r->context, r->client); >+ _kdc_free_ent(r->context, clientdb, r->client); > r->client = initiator; > initiator = NULL; > } else if (!krb5_principal_compare(r->context, >- r->client->entry.principal, >- initiator->entry.principal)) { >+ r->client->principal, >+ initiator->principal)) { > kdc_log(r->context, r->config, 2, > "GSS %s initiator %.*s does not match principal %s", > gss_oid_to_name(gcp->mech_type), >@@ -763,14 +761,10 @@ _kdc_gss_check_client(astgs_request_t r, > goto out; > } > >- gcp->pac_data = pac_data; >- krb5_data_zero(&pac_data); >- > out: > krb5_free_principal(r->context, initiator_princ); > if (initiator) >- _kdc_free_ent(r->context, initiator); >- krb5_data_free(&pac_data); >+ _kdc_free_ent(r->context, r->clientdb, initiator); > gss_release_buffer(&minor, &display_name); > > return ret; >@@ -864,10 +858,10 @@ _kdc_gss_mk_composite_name_ad(astgs_request_t r, > return ret; > } > >-void >-_kdc_gss_free_client_param(astgs_request_t r, >- gss_client_params *gcp) >+static void HEIM_CALLCONV >+pa_gss_dealloc_client_params(void *ptr) > { >+ gss_client_params *gcp = ptr; > OM_uint32 minor; > > if (gcp == NULL) >@@ -877,9 +871,7 @@ _kdc_gss_free_client_param(astgs_request_t r, > gss_release_name(&minor, &gcp->initiator_name); > gss_release_buffer(&minor, &gcp->output_token); > free_Checksum(&gcp->req_body_checksum); >- krb5_data_free(&gcp->pac_data); > memset(gcp, 0, sizeof(*gcp)); >- free(gcp); > } > > krb5_error_code >@@ -1013,11 +1005,6 @@ pa_gss_display_name(gss_name_t name, > *namebuf_p = namebuf; > } > >-struct pa_gss_finalize_pac_plugin_ctx { >- astgs_request_t r; >- krb5_data *pac_data; >-}; >- > static krb5_error_code KRB5_LIB_CALL > pa_gss_finalize_pac_cb(krb5_context context, > const void *plug, >@@ -1025,11 +1012,8 @@ pa_gss_finalize_pac_cb(krb5_context context, > void *userctx) > { > const krb5plugin_gss_preauth_authorizer_ftable *authorizer = plug; >- struct pa_gss_finalize_pac_plugin_ctx *pa_gss_finalize_pac_ctx = userctx; > >- return authorizer->finalize_pac(plugctx, >- pa_gss_finalize_pac_ctx->r, >- pa_gss_finalize_pac_ctx->pac_data); >+ return authorizer->finalize_pac(plugctx, userctx); > } > > >@@ -1038,14 +1022,10 @@ _kdc_gss_finalize_pac(astgs_request_t r, > gss_client_params *gcp) > { > krb5_error_code ret; >- struct pa_gss_finalize_pac_plugin_ctx ctx; >- >- ctx.r = r; >- ctx.pac_data = &gcp->pac_data; > > krb5_clear_error_message(r->context); > ret = _krb5_plugin_run_f(r->context, &gss_preauth_authorizer_data, >- 0, &ctx, pa_gss_finalize_pac_cb); >+ 0, r, pa_gss_finalize_pac_cb); > > if (ret == KRB5_PLUGIN_NO_HANDLE) > ret = 0; >diff --git a/third_party/heimdal/kdc/gss_preauth_authorizer_plugin.h b/third_party/heimdal/kdc/gss_preauth_authorizer_plugin.h >index 69bd5fc1ae5b..293e59da47ba 100644 >--- a/third_party/heimdal/kdc/gss_preauth_authorizer_plugin.h >+++ b/third_party/heimdal/kdc/gss_preauth_authorizer_plugin.h >@@ -69,11 +69,9 @@ typedef struct krb5plugin_gss_preauth_authorizer_ftable_desc { > gss_const_OID, /*mech_type*/ > OM_uint32, /*ret_flags*/ > krb5_boolean *, /*authorized*/ >- krb5_principal *, /*mapped_name*/ >- krb5_data *); /*pac_data*/ >+ krb5_principal *); /*mapped_name*/ > krb5_error_code (KRB5_LIB_CALL *finalize_pac)(void *, /*plug_ctx*/ >- astgs_request_t, /*r*/ >- krb5_data *); /*pac_data*/ >+ astgs_request_t); /*r*/ > } krb5plugin_gss_preauth_authorizer_ftable; > > #endif /* HEIMDAL_KDC_GSS_PREAUTH_AUTHORIZER_PLUGIN_H */ >diff --git a/third_party/heimdal/kdc/headers.h b/third_party/heimdal/kdc/headers.h >index 6f4d56ae95cb..ffe49c8bdfd6 100644 >--- a/third_party/heimdal/kdc/headers.h >+++ b/third_party/heimdal/kdc/headers.h >@@ -104,7 +104,8 @@ > #include <heimntlm.h> > #endif > #include <kdc.h> >-#include <windc_plugin.h> >+#include <kdc-plugin.h> >+#include <kdc-audit.h> > > #include <heimbase.h> > >diff --git a/third_party/heimdal/kdc/hprop.8 b/third_party/heimdal/kdc/hprop.8 >index 2746e1d8fccc..acf66bcd6147 100644 >--- a/third_party/heimdal/kdc/hprop.8 >+++ b/third_party/heimdal/kdc/hprop.8 >@@ -50,7 +50,6 @@ > .Oc > .Op Fl Fl source= Ns Ar heimdal|mit-dump > .Oo Fl r Ar string \*(Ba Xo >-.Fl Fl v4-realm= Ns Ar string > .Xc > .Oc > .Oo Fl c Ar cell \*(Ba Xo >diff --git a/third_party/heimdal/kdc/hprop.c b/third_party/heimdal/kdc/hprop.c >index 880a6f746406..c1db11b978ec 100644 >--- a/third_party/heimdal/kdc/hprop.c >+++ b/third_party/heimdal/kdc/hprop.c >@@ -87,28 +87,28 @@ open_socket(krb5_context context, const char *hostname, const char *port) > } > > krb5_error_code >-v5_prop(krb5_context context, HDB *db, hdb_entry_ex *entry, void *appdata) >+v5_prop(krb5_context context, HDB *db, hdb_entry *entry, void *appdata) > { > krb5_error_code ret; > struct prop_data *pd = appdata; > krb5_data data; > > if(encrypt_flag) { >- ret = hdb_seal_keys_mkey(context, &entry->entry, mkey5); >+ ret = hdb_seal_keys_mkey(context, entry, mkey5); > if (ret) { > krb5_warn(context, ret, "hdb_seal_keys_mkey"); > return ret; > } > } > if(decrypt_flag) { >- ret = hdb_unseal_keys_mkey(context, &entry->entry, mkey5); >+ ret = hdb_unseal_keys_mkey(context, entry, mkey5); > if (ret) { > krb5_warn(context, ret, "hdb_unseal_keys_mkey"); > return ret; > } > } > >- ret = hdb_entry2value(context, &entry->entry, &data); >+ ret = hdb_entry2value(context, entry, &data); > if(ret) { > krb5_warn(context, ret, "hdb_entry2value"); > return ret; >@@ -316,9 +316,18 @@ propagate_database (krb5_context context, int type, > > if (local_realm) { > krb5_realm my_realm; >- krb5_get_default_realm(context,&my_realm); >- krb5_principal_set_realm(context,server,my_realm); >- krb5_xfree(my_realm); >+ ret = krb5_get_default_realm(context,&my_realm); >+ if (ret == 0) { >+ ret = krb5_principal_set_realm(context,server,my_realm); >+ krb5_xfree(my_realm); >+ } >+ if (ret) { >+ failed++; >+ krb5_warn(context, ret, "unable to obtain default or set realm"); >+ krb5_free_principal(context, server); >+ close(fd); >+ continue; >+ } > } > > auth_context = NULL; >diff --git a/third_party/heimdal/kdc/hprop.h b/third_party/heimdal/kdc/hprop.h >index 426bf6ed7fd5..59c39ea47847 100644 >--- a/third_party/heimdal/kdc/hprop.h >+++ b/third_party/heimdal/kdc/hprop.h >@@ -53,23 +53,7 @@ struct prop_data{ > #define NEVERDATE ((1U << 31) - 1) > #endif > >-krb5_error_code v5_prop(krb5_context, HDB*, hdb_entry_ex*, void*); >+krb5_error_code v5_prop(krb5_context, HDB*, hdb_entry*, void*); > int mit_prop_dump(void*, const char*); > >-struct v4_principal { >- char name[64]; >- char instance[64]; >- DES_cblock key; >- int kvno; >- int mkvno; >- time_t exp_date; >- time_t mod_date; >- char mod_name[64]; >- char mod_instance[64]; >- int max_life; >-}; >- >-int v4_prop(void*, struct v4_principal*); >-int v4_prop_dump(void *arg, const char*); >- > #endif /* __HPROP_H__ */ >diff --git a/third_party/heimdal/kdc/hpropd.8 b/third_party/heimdal/kdc/hpropd.8 >index 31b44e28a59c..9056b05a8d24 100644 >--- a/third_party/heimdal/kdc/hpropd.8 >+++ b/third_party/heimdal/kdc/hpropd.8 >@@ -51,7 +51,6 @@ > .Fl Fl keytab= Ns Ar keytab > .Xc > .Oc >-.Op Fl 4 | Fl Fl v4dump > .Ek > .Sh DESCRIPTION > .Nm >@@ -83,8 +82,6 @@ print dump to stdout > not started from inetd > .It Fl k Ar keytab , Fl Fl keytab= Ns Ar keytab > keytab to use for authentication >-.It Fl 4 , Fl Fl v4dump >-create v4 type DB > .El > .Sh SEE ALSO > .Xr hprop 8 >diff --git a/third_party/heimdal/kdc/hpropd.c b/third_party/heimdal/kdc/hpropd.c >index fd9df08e8d78..fa06a1fd4019 100644 >--- a/third_party/heimdal/kdc/hpropd.c >+++ b/third_party/heimdal/kdc/hpropd.c >@@ -125,6 +125,7 @@ main(int argc, char **argv) > krb5_ticket *ticket; > char *server; > >+ memset(&ss, 0, sizeof(ss)); > sock = STDIN_FILENO; > #ifdef SUPPORT_INETD > if (inetd_flag == -1) { >@@ -146,7 +147,7 @@ main(int argc, char **argv) > if (getpeername(sock, sa, &sin_len) < 0) > krb5_err(context, 1, errno, "getpeername"); > >- if (inet_ntop(ss.ss_family, >+ if (inet_ntop(sa->sa_family, > socket_get_address (sa), > addr_name, > sizeof(addr_name)) == NULL) >@@ -225,7 +226,7 @@ main(int argc, char **argv) > nprincs = 0; > while (1){ > krb5_data data; >- hdb_entry_ex entry; >+ hdb_entry entry; > > if (from_stdin) { > ret = krb5_read_message(context, &sock, &data); >@@ -254,7 +255,7 @@ main(int argc, char **argv) > break; > } > memset(&entry, 0, sizeof(entry)); >- ret = hdb_value2entry(context, &data, &entry.entry); >+ ret = hdb_value2entry(context, &data, &entry); > krb5_data_free(&data); > if (ret) > krb5_err(context, 1, ret, "hdb_value2entry"); >@@ -268,7 +269,7 @@ main(int argc, char **argv) > ret = db->hdb_store(context, db, 0, &entry); > if (ret == HDB_ERR_EXISTS) { > char *s; >- ret = krb5_unparse_name(context, entry.entry.principal, &s); >+ ret = krb5_unparse_name(context, entry.principal, &s); > if (ret) > s = strdup(unparseable_name); > krb5_warnx(context, "Entry exists: %s", s); >@@ -278,7 +279,7 @@ main(int argc, char **argv) > else > nprincs++; > } >- hdb_free_entry(context, &entry); >+ hdb_free_entry(context, db, &entry); > } > if (!print_dump) > krb5_log(context, fac, 0, "Received %d principals", nprincs); >diff --git a/third_party/heimdal/kdc/httpkadmind.c b/third_party/heimdal/kdc/httpkadmind.c >index 3dfb365186af..0e31b4044c3c 100644 >--- a/third_party/heimdal/kdc/httpkadmind.c >+++ b/third_party/heimdal/kdc/httpkadmind.c >@@ -80,6 +80,20 @@ > #define heim_pconfig krb5_context > #include <heimbase-svc.h> > >+#if MHD_VERSION < 0x00097002 || defined(MHD_YES) >+/* libmicrohttpd changed these from int valued macros to an enum in 0.9.71 */ >+#ifdef MHD_YES >+#undef MHD_YES >+#undef MHD_NO >+#endif >+enum MHD_Result { MHD_NO = 0, MHD_YES = 1 }; >+#define MHD_YES 1 >+#define MHD_NO 0 >+typedef int heim_mhd_result; >+#else >+typedef enum MHD_Result heim_mhd_result; >+#endif >+ > #define BODYLEN_IS_STRLEN (~0) > > /* >@@ -565,7 +579,7 @@ redirect_uri_appends(struct redirect_uri *redirect, > redirect->len += len; > } > >-static int >+static heim_mhd_result > make_redirect_uri_param_cb(void *d, > enum MHD_ValueKind kind, > const char *key, >@@ -700,9 +714,10 @@ bad_reqv(kadmin_request_desc r, > if (r && r->context) > context = r->context; > if (r && r->hcontext && r->kv) >- heim_audit_addkv((heim_svc_req_desc)r, 0, "http-status-code", "%d", >- http_status_code); >- (void) gettimeofday(&r->tv_end, NULL); >+ heim_audit_setkv_number((heim_svc_req_desc)r, "http-status-code", >+ http_status_code); >+ if (r) >+ (void) gettimeofday(&r->tv_end, NULL); > if (code == ENOMEM) { > if (context) > krb5_log_msg(context, logfac, 1, NULL, "Out of memory"); >@@ -881,7 +896,7 @@ check_service_name(kadmin_request_desc r, const char *name) > return EACCES; > } > >-static int >+static heim_mhd_result > param_cb(void *d, > enum MHD_ValueKind kind, > const char *key, >@@ -1046,12 +1061,12 @@ param_cb(void *d, > #endif > } else { > /* Produce error for unknown params */ >- heim_audit_addkv((heim_svc_req_desc)r, 0, "requested_unknown", "true"); >+ heim_audit_setkv_bool((heim_svc_req_desc)r, "requested_unknown", TRUE); > krb5_set_error_message(r->context, ret = ENOTSUP, > "Query parameter %s not supported", key); > } >- if (ret && !r->ret) >- r->ret = ret; >+ if (ret && !r->error_code) >+ r->error_code = ret; > heim_release(s); > return ret ? MHD_NO /* Stop iterating */ : MHD_YES; > } >@@ -1067,7 +1082,7 @@ authorize_req(kadmin_request_desc r) > return bad_enomem(r, ret); > (void) MHD_get_connection_values(r->connection, MHD_GET_ARGUMENT_KIND, > param_cb, r); >- ret = r->ret; >+ ret = r->error_code; > if (ret == EACCES) > return bad_403(r, ret, "Not authorized to requested principal(s)"); > if (ret) >@@ -1189,7 +1204,7 @@ make_kstuple(krb5_context context, > > if (p->n_key_data < 1) > return 0; >- *kstuple = calloc(p->n_key_data, sizeof (*kstuple)); >+ *kstuple = calloc(p->n_key_data, sizeof (**kstuple)); > for (i = 0; *kstuple && i < p->n_key_data; i++) { > if (p->key_data[i].key_data_kvno == p->kvno) { > (*kstuple)[i].ks_enctype = p->key_data[i].key_data_type[0]; >@@ -1417,6 +1432,8 @@ get_keysN(kadmin_request_desc r, const char *method) > ret = heim_array_append_value(r->service_names, s); > heim_release(s); > nsvcs = 1; >+ if (ret) >+ return bad_503(r, ret, "Out of memory"); > } > > /* FIXME: Make this configurable */ >@@ -1528,7 +1545,8 @@ set_req_desc(struct MHD_Connection *connection, > r->sname = NULL; > r->cname = NULL; > r->addr = NULL; >- r->kv = heim_array_create(); >+ r->kv = heim_dict_create(10); >+ r->attributes = heim_dict_create(1); > /* Our fields */ > r->connection = connection; > r->kadm_handle = NULL; >@@ -1570,7 +1588,7 @@ set_req_desc(struct MHD_Connection *connection, > > if (ret == 0 && r->kv == NULL) { > krb5_log_msg(r->context, logfac, 1, NULL, "Out of memory"); >- ret = r->ret = ENOMEM; >+ ret = r->error_code = ENOMEM; > } > return ret; > } >@@ -1643,6 +1661,8 @@ get_config(kadmin_request_desc r) > > ret = get_kadm_handle(r->context, r->realm ? r->realm : realm, > 0 /* want_write */, &r->kadm_handle); >+ if (ret) >+ return bad_503(r, ret, "Could not access KDC database"); > > memset(&princ, 0, sizeof(princ)); > princ.key_data = NULL; >@@ -1665,7 +1685,7 @@ get_config(kadmin_request_desc r) > break; > } > } else { >- r->ret = ret; >+ r->error_code = ret; > return bad_404(r, "/get-config"); > } > } >@@ -1725,15 +1745,22 @@ mac_csrf_token(kadmin_request_desc r, krb5_storage *sp) > ret = krb5_enomem(r->context); > /* HMAC the token body and the client principal name */ > if (ret == 0) { >- HMAC_Init_ex(ctx, princ.key_data[i].key_data_contents[0], princ.key_data[i].key_data_length[0], EVP_sha256(), NULL); >- HMAC_Update(ctx, data.data, data.length); >- HMAC_Update(ctx, r->cname, strlen(r->cname)); >- HMAC_Final(ctx, mac, &maclen); >- krb5_data_free(&data); >- data.length = maclen; >- data.data = mac; >- if (krb5_storage_write(sp, mac, maclen) != maclen) >+ if (HMAC_Init_ex(ctx, princ.key_data[i].key_data_contents[0], >+ princ.key_data[i].key_data_length[0], EVP_sha256(), >+ NULL) == 0) { >+ HMAC_CTX_cleanup(ctx); > ret = krb5_enomem(r->context); >+ } else { >+ HMAC_Update(ctx, data.data, data.length); >+ HMAC_Update(ctx, r->cname, strlen(r->cname)); >+ HMAC_Final(ctx, mac, &maclen); >+ HMAC_CTX_cleanup(ctx); >+ krb5_data_free(&data); >+ data.length = maclen; >+ data.data = mac; >+ if (krb5_storage_write(sp, mac, maclen) != maclen) >+ ret = krb5_enomem(r->context); >+ } > } > krb5_free_principal(r->context, p); > if (freeit) >@@ -1874,7 +1901,7 @@ health(const char *method, kadmin_request_desc r) > } > > /* Implements the entirety of this REST service */ >-static int >+static heim_mhd_result > route(void *cls, > struct MHD_Connection *connection, > const char *url, >@@ -2100,6 +2127,8 @@ main(int argc, char **argv) > > argc -= optidx; > argv += optidx; >+ if (argc != 0) >+ usage(1); > > if ((errno = pthread_key_create(&k5ctx, k5_free_context))) > err(1, "Could not create thread-specific storage"); >diff --git a/third_party/heimdal/kdc/ipc_csr_authorizer.c b/third_party/heimdal/kdc/ipc_csr_authorizer.c >index fad3919a2a6b..7d77e7f812a4 100644 >--- a/third_party/heimdal/kdc/ipc_csr_authorizer.c >+++ b/third_party/heimdal/kdc/ipc_csr_authorizer.c >@@ -169,6 +169,7 @@ cmd_append(struct rk_strpool **cmd, const char *s0, ...) > { > va_list ap; > const char *arg; >+ int ret = 0; > > if ((*cmd = rk_strpoolprintf(*cmd, "%s", s0)) == NULL) > return ENOMEM; >@@ -177,14 +178,23 @@ cmd_append(struct rk_strpool **cmd, const char *s0, ...) > while ((arg = va_arg(ap, const char *))) { > char *s; > >- if ((s = string_encode(arg)) == NULL) >- return rk_strpoolfree(*cmd), *cmd = NULL, ENOMEM; >+ if ((s = string_encode(arg)) == NULL) { >+ rk_strpoolfree(*cmd); >+ *cmd = NULL; >+ ret = ENOMEM; >+ goto out; >+ } > *cmd = rk_strpoolprintf(*cmd, "%s", s); > free(s); >- if (*cmd == NULL) >- return ENOMEM; >+ if (*cmd == NULL) { >+ ret = ENOMEM; >+ goto out; >+ } > } >- return 0; >+ >+ out: >+ va_end(ap); >+ return ret; > } > > static int >diff --git a/third_party/heimdal/kdc/kdc-accessors.h b/third_party/heimdal/kdc/kdc-accessors.h >new file mode 100644 >index 000000000000..81c03d2f2227 >--- /dev/null >+++ b/third_party/heimdal/kdc/kdc-accessors.h >@@ -0,0 +1,349 @@ >+/* >+ * Copyright (c) 2022, PADL Software Pty Ltd. >+ * All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * 3. Neither the name of PADL Software nor the names of its contributors >+ * may be used to endorse or promote products derived from this software >+ * without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND >+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >+ * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE >+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >+ * SUCH DAMAGE. >+ */ >+ >+#ifndef HEIMDAL_KDC_KDC_ACCESSORS_H >+#define HEIMDAL_KDC_KDC_ACCESSORS_H 1 >+ >+/* read-only accessor */ >+#ifndef _KDC_REQUEST_GET_ACCESSOR >+#define _KDC_REQUEST_GET_ACCESSOR(R, T, f) \ >+ KDC_LIB_FUNCTION T KDC_LIB_CALL \ >+ kdc_request_get_ ## f(R); >+#endif >+ >+#ifndef _KDC_REQUEST_SET_ACCESSOR >+#define _KDC_REQUEST_SET_ACCESSOR(R, T, f) \ >+ KDC_LIB_FUNCTION void KDC_LIB_CALL \ >+ kdc_request_set_ ## f(R, T); >+#endif >+ >+#ifndef KDC_REQUEST_GET_ACCESSOR >+#define KDC_REQUEST_GET_ACCESSOR(T, f) \ >+ _KDC_REQUEST_GET_ACCESSOR(kdc_request_t, T, f) >+#endif >+ >+#ifndef KDC_REQUEST_SET_ACCESSOR >+#define KDC_REQUEST_SET_ACCESSOR(T, f) \ >+ _KDC_REQUEST_SET_ACCESSOR(kdc_request_t, T, f) >+#endif >+ >+#ifndef ASTGS_REQUEST_GET_ACCESSOR >+#define ASTGS_REQUEST_GET_ACCESSOR(T, f) \ >+ _KDC_REQUEST_GET_ACCESSOR(astgs_request_t, T, f) >+#endif >+ >+#ifndef ASTGS_REQUEST_SET_ACCESSOR >+#define ASTGS_REQUEST_SET_ACCESSOR(T, f) \ >+ _KDC_REQUEST_SET_ACCESSOR(astgs_request_t, T, f) >+#endif >+ >+/* get/set accessor for pointer type */ >+#ifndef _KDC_REQUEST_GET_ACCESSOR_PTR >+#define _KDC_REQUEST_GET_ACCESSOR_PTR(R, T, f) \ >+ KDC_LIB_FUNCTION const T KDC_LIB_CALL \ >+ kdc_request_get_ ## f(R); >+#endif >+ >+#ifndef _KDC_REQUEST_SET_ACCESSOR_PTR >+#define _KDC_REQUEST_SET_ACCESSOR_PTR(R, T, t, f) \ >+ KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL \ >+ kdc_request_set_ ## f(R, const T); >+#endif >+ >+#ifndef KDC_REQUEST_GET_ACCESSOR_PTR >+#define KDC_REQUEST_GET_ACCESSOR_PTR(T, f) \ >+ _KDC_REQUEST_GET_ACCESSOR_PTR(kdc_request_t, T, f) >+#endif >+ >+#ifndef KDC_REQUEST_SET_ACCESSOR_PTR >+#define KDC_REQUEST_SET_ACCESSOR_PTR(T, t, f) \ >+ _KDC_REQUEST_SET_ACCESSOR_PTR(kdc_request_t, T, t, f) >+#endif >+ >+#ifndef ASTGS_REQUEST_GET_ACCESSOR_PTR >+#define ASTGS_REQUEST_GET_ACCESSOR_PTR(T, f) \ >+ _KDC_REQUEST_GET_ACCESSOR_PTR(astgs_request_t, T, f) >+#endif >+ >+#ifndef ASTGS_REQUEST_SET_ACCESSOR_PTR >+#define ASTGS_REQUEST_SET_ACCESSOR_PTR(T, t, f) \ >+ _KDC_REQUEST_SET_ACCESSOR_PTR(astgs_request_t, T, t, f) >+#endif >+ >+/* get/set accessor for struct type */ >+#ifndef _KDC_REQUEST_GET_ACCESSOR_STRUCT >+#define _KDC_REQUEST_GET_ACCESSOR_STRUCT(R, T, f) \ >+ KDC_LIB_FUNCTION const T * KDC_LIB_CALL \ >+ kdc_request_get_ ## f(R); >+#endif >+ >+#ifndef _KDC_REQUEST_SET_ACCESSOR_STRUCT >+#define _KDC_REQUEST_SET_ACCESSOR_STRUCT(R, T, t, f) \ >+ KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL \ >+ kdc_request_set_ ## f(R, const T *); >+#endif >+ >+#ifndef KDC_REQUEST_GET_ACCESSOR_STRUCT >+#define KDC_REQUEST_GET_ACCESSOR_STRUCT(T, f) \ >+ _KDC_REQUEST_GET_ACCESSOR_STRUCT(kdc_request_t, T, f) >+#endif >+ >+#ifndef KDC_REQUEST_SET_ACCESSOR_STRUCT >+#define KDC_REQUEST_SET_ACCESSOR_STRUCT(T, t, f) \ >+ _KDC_REQUEST_SET_ACCESSOR_STRUCT(kdc_request_t, T, t, f) >+#endif >+ >+#ifndef ASTGS_REQUEST_GET_ACCESSOR_STRUCT >+#define ASTGS_REQUEST_GET_ACCESSOR_STRUCT(T, f) \ >+ _KDC_REQUEST_GET_ACCESSOR_STRUCT(astgs_request_t, T, f) >+#endif >+ >+#ifndef ASTGS_REQUEST_SET_ACCESSOR_STRUCT >+#define ASTGS_REQUEST_SET_ACCESSOR_STRUCT(T, t, f) \ >+ _KDC_REQUEST_SET_ACCESSOR_STRUCT(astgs_request_t, T, t, f) >+#endif >+ >+/* >+ * krb5_context >+ * kdc_request_get_context(kdc_request_t); >+ */ >+ >+KDC_REQUEST_GET_ACCESSOR(krb5_context, context) >+ >+/* >+ * krb5_kdc_configuration * >+ * kdc_request_get_config(kdc_request_t); >+ */ >+ >+KDC_REQUEST_GET_ACCESSOR(krb5_kdc_configuration *, config) >+ >+/* >+ * heim_log_facility * >+ * kdc_request_get_logf(kdc_request_t); >+ */ >+ >+KDC_REQUEST_GET_ACCESSOR(heim_log_facility *, logf) >+ >+/* >+ * const char * >+ * kdc_request_get_from(kdc_request_t); >+ */ >+ >+KDC_REQUEST_GET_ACCESSOR_PTR(char *, from) >+ >+/* >+ * const struct sockaddr * >+ * kdc_request_get_addr(kdc_request_t); >+ */ >+ >+KDC_REQUEST_GET_ACCESSOR_PTR(struct sockaddr *, addr) >+ >+/* >+ * krb5_data >+ * kdc_request_get_request(kdc_request_t); >+ */ >+ >+KDC_REQUEST_GET_ACCESSOR(krb5_data, request) >+ >+/* >+ * struct timeval >+ * kdc_request_get_tv_start(kdc_request_t); >+ */ >+ >+KDC_REQUEST_GET_ACCESSOR(struct timeval, tv_start) >+ >+/* >+ * struct timeval >+ * kdc_request_get_tv_end(kdc_request_t); >+ */ >+ >+KDC_REQUEST_GET_ACCESSOR(struct timeval, tv_end) >+ >+/* >+ * krb5_error_code >+ * kdc_request_get_error_code(kdc_request_t); >+ */ >+KDC_REQUEST_GET_ACCESSOR(krb5_error_code, error_code) >+ >+/* >+ * void >+ * kdc_request_set_error_code(kdc_request_t, krb5_error_code); >+ */ >+KDC_REQUEST_SET_ACCESSOR(krb5_error_code, error_code) >+ >+/* >+ * const KDC_REQ * >+ * kdc_request_get_req(astgs_request_t); >+ */ >+ >+ASTGS_REQUEST_GET_ACCESSOR_STRUCT(KDC_REQ, req) >+ >+/* >+ * const KDC_REP * >+ * kdc_request_get_rep(astgs_request_t); >+ */ >+ >+ASTGS_REQUEST_GET_ACCESSOR_STRUCT(KDC_REP, rep) >+ >+/* >+ * krb5_error_code >+ * kdc_request_set_rep(astgs_request_t, const KDC_REP *); >+ */ >+ >+ASTGS_REQUEST_SET_ACCESSOR_STRUCT(KDC_REP, KDC_REP, rep) >+ >+/* >+ * const char * >+ * kdc_request_get_cname(kdc_request_t); >+ */ >+ >+KDC_REQUEST_GET_ACCESSOR_PTR(char *, cname) >+ >+/* >+ * krb5_error_code >+ * kdc_request_set_cname(kdc_request_t, const char *); >+ */ >+ >+KDC_REQUEST_SET_ACCESSOR_PTR(char *, string_ptr, cname) >+ >+/* >+ * const Principal * >+ * kdc_request_get_client_princ(astgs_request_t); >+ */ >+ >+ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, client_princ) >+ >+/* >+ * krb5_error_code >+ * kdc_request_set_client_princ(astgs_request_t, const Principal *); >+ */ >+ >+ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, client_princ) >+ >+/* >+ * const Principal * >+ * kdc_request_get_canon_client_princ(astgs_request_t); >+ */ >+ >+ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, canon_client_princ) >+ >+/* >+ * krb5_error_code >+ * kdc_request_set_canon_client_princ(astgs_request_t, const Principal *); >+ */ >+ >+ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, canon_client_princ) >+ >+/* >+ * const HDB * >+ * kdc_request_get_clientdb(astgs_request_t); >+ */ >+ >+ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, clientdb) >+ >+/* >+ * const hdb_entry * >+ * kdc_request_get_client(astgs_request_t); >+ */ >+ >+ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, client) >+ >+/* >+ * See client accessors >+ */ >+ >+KDC_REQUEST_GET_ACCESSOR_PTR(char *, sname) >+KDC_REQUEST_SET_ACCESSOR_PTR(char *, string_ptr, sname) >+ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, server_princ) >+ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, server_princ) >+ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, serverdb) >+ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, server) >+ >+/* >+ * See client accessors >+ */ >+ >+ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, krbtgt_princ) >+ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, krbtgt_princ) >+ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, krbtgtdb) >+ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, krbtgt) >+ >+/* >+ * krb5_ticket * >+ * kdc_request_get_ticket(astgs_request_t); >+ */ >+ >+ASTGS_REQUEST_GET_ACCESSOR(krb5_ticket *, ticket) >+ >+/* >+ * const krb5_keyblock * >+ * kdc_request_get_reply_key(astgs_request_t); >+ */ >+ >+ASTGS_REQUEST_GET_ACCESSOR_STRUCT(krb5_keyblock, reply_key) >+ >+/* >+ * krb5_error_code >+ * kdc_request_set_reply_key(astgs_request_t, const krb5_keyblock *); >+ */ >+ >+ASTGS_REQUEST_SET_ACCESSOR_STRUCT(krb5_keyblock, keyblock, reply_key) >+ >+/* >+ * krb5_const_pac >+ * kdc_request_get_pac(astgs_request_t); >+ */ >+ >+ASTGS_REQUEST_GET_ACCESSOR_PTR(struct krb5_pac_data *, pac) >+ >+/* >+ * krb5_error_code >+ * kdc_request_set_pac(astgs_request_t, krb5_const_pac); >+ */ >+ >+ASTGS_REQUEST_SET_ACCESSOR_PTR(struct krb5_pac_data *, pac, pac) >+ >+/* >+ * uint64_t >+ * kdc_request_get_pac_attributes(astgs_request_t); >+ */ >+ >+ASTGS_REQUEST_GET_ACCESSOR(uint64_t, pac_attributes) >+ >+/* >+ * void >+ * kdc_request_set_pac_attributes(astgs_request_t, uint64_t); >+ */ >+ >+ASTGS_REQUEST_SET_ACCESSOR(uint64_t, pac_attributes) >+ >+#endif /* HEIMDAL_KDC_KDC_ACCESSORS_H */ >diff --git a/third_party/heimdal/kdc/rx.h b/third_party/heimdal/kdc/kdc-audit.h >similarity index 50% >rename from third_party/heimdal/kdc/rx.h >rename to third_party/heimdal/kdc/kdc-audit.h >index f914e93e6efc..4b2203f22679 100644 >--- a/third_party/heimdal/kdc/rx.h >+++ b/third_party/heimdal/kdc/kdc-audit.h >@@ -1,5 +1,5 @@ > /* >- * Copyright (c) 1997 Kungliga Tekniska Högskolan >+ * Copyright (c) 2006 Kungliga Tekniska Högskolan > * (Royal Institute of Technology, Stockholm, Sweden). > * All rights reserved. > * >@@ -33,47 +33,35 @@ > > /* $Id$ */ > >-#ifndef __RX_H__ >-#define __RX_H__ >+#ifndef HEIMDAL_KDC_KDC_AUDIT_H >+#define HEIMDAL_KDC_KDC_AUDIT_H 1 > >-/* header of a RPC packet */ >- >-enum rx_header_type { >- HT_DATA = 1, >- HT_ACK = 2, >- HT_BUSY = 3, >- HT_ABORT = 4, >- HT_ACKALL = 5, >- HT_CHAL = 6, >- HT_RESP = 7, >- HT_DEBUG = 8 >-}; >- >-/* For flags in header */ >+/* >+ * KDC auditing >+ */ > >-enum rx_header_flag { >- HF_CLIENT_INITIATED = 1, >- HF_REQ_ACK = 2, >- HF_LAST = 4, >- HF_MORE = 8 >-}; >+/* auth event type enumeration, currently for AS only */ >+#define KDC_AUTH_EVENT_INVALID 0 /* no event logged */ >+#define KDC_AUTH_EVENT_CLIENT_AUTHORIZED 1 /* all authn/authz checks passed */ >+#define KDC_AUTH_EVENT_CLIENT_UNKNOWN 2 /* client unknown */ >+#define KDC_AUTH_EVENT_CLIENT_LOCKED_OUT 3 /* client locked out */ >+#define KDC_AUTH_EVENT_CLIENT_TIME_SKEW 4 /* client time skew */ >+#define KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY 5 /* PA failed to validate long term key */ >+#define KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY 6 /* PA validated long term key */ >+#define KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED 7 /* couldn't map GSS/PKINIT name to principal */ >+#define KDC_AUTH_EVENT_PREAUTH_FAILED 8 /* generic PA failure */ >+#define KDC_AUTH_EVENT_PREAUTH_SUCCEEDED 9 /* generic (non-long term key) PA success */ > >-struct rx_header { >- uint32_t epoch; >- uint32_t connid; /* And channel ID */ >- uint32_t callid; >- uint32_t seqno; >- uint32_t serialno; >- u_char type; >- u_char flags; >- u_char status; >- u_char secindex; >- uint16_t reserved; /* ??? verifier? */ >- uint16_t serviceid; >-/* This should be the other way around according to everything but */ >-/* tcpdump */ >-}; >+/* >+ * Audit keys to be queried using kdc_audit_getkv(). There are other keys >+ * intended for logging that are not defined below; the constants below are >+ * there to ease migration from the older auth_status HDB API. >+ */ > >-#define RX_HEADER_SIZE 28 >+#define KDC_REQUEST_KV_AUTH_EVENT "#auth_event" /* heim_number_t */ >+#define KDC_REQUEST_KV_PA_NAME "pa" /* heim_string_t */ >+#define KDC_REQUEST_KV_PA_ETYPE "pa-etype" /* heim_number_t */ >+#define KDC_REQUEST_KV_GSS_INITIATOR "gss_initiator" /* heim_string_t */ >+#define KDC_REQUEST_KV_PKINIT_CLIENT_CERT "pkinit_client_cert" /* heim_string_t */ > >-#endif /* __RX_H__ */ >+#endif /* HEIMDAL_KDC_KDC_AUDIT_H */ >diff --git a/third_party/heimdal/kdc/kdc-plugin.c b/third_party/heimdal/kdc/kdc-plugin.c >new file mode 100644 >index 000000000000..8759893a9560 >--- /dev/null >+++ b/third_party/heimdal/kdc/kdc-plugin.c >@@ -0,0 +1,658 @@ >+/* >+ * Copyright (c) 2007 Kungliga Tekniska Högskolan >+ * (Royal Institute of Technology, Stockholm, Sweden). >+ * All rights reserved. >+ * >+ * Portions (c) 2021, 2022 PADL Software Pty Ltd. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * 3. Neither the name of the Institute nor the names of its contributors >+ * may be used to endorse or promote products derived from this software >+ * without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND >+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE >+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >+ * SUCH DAMAGE. >+ */ >+ >+#include "kdc_locl.h" >+ >+static int have_plugin = 0; >+ >+/* >+ * Pick the first KDC plugin module that we find. >+ */ >+ >+static const char *kdc_plugin_deps[] = { >+ "kdc", >+ "krb5", >+ "hdb", >+ NULL >+}; >+ >+static struct heim_plugin_data kdc_plugin_data = { >+ "krb5", >+ "kdc", >+ KRB5_PLUGIN_KDC_VERSION_10, >+ kdc_plugin_deps, >+ kdc_get_instance >+}; >+ >+static krb5_error_code KRB5_LIB_CALL >+load(krb5_context context, const void *plug, void *plugctx, void *userctx) >+{ >+ have_plugin = 1; >+ return KRB5_PLUGIN_NO_HANDLE; >+} >+ >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL >+krb5_kdc_plugin_init(krb5_context context) >+{ >+ (void)_krb5_plugin_run_f(context, &kdc_plugin_data, 0, NULL, load); >+ >+ return 0; >+} >+ >+struct generate_uc { >+ krb5_kdc_configuration *config; >+ hdb_entry *client; >+ hdb_entry *server; >+ const krb5_keyblock *reply_key; >+ uint64_t pac_attributes; >+ krb5_pac *pac; >+}; >+ >+static krb5_error_code KRB5_LIB_CALL >+generate(krb5_context context, const void *plug, void *plugctx, void *userctx) >+{ >+ const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug; >+ struct generate_uc *uc = (struct generate_uc *)userctx; >+ >+ if (ft->pac_generate == NULL) >+ return KRB5_PLUGIN_NO_HANDLE; >+ >+ return ft->pac_generate((void *)plug, >+ context, >+ uc->config, >+ uc->client, >+ uc->server, >+ uc->reply_key, >+ uc->pac_attributes, >+ uc->pac); >+} >+ >+ >+krb5_error_code >+_kdc_pac_generate(krb5_context context, >+ krb5_kdc_configuration *config, >+ hdb_entry *client, >+ hdb_entry *server, >+ const krb5_keyblock *reply_key, >+ uint64_t pac_attributes, >+ krb5_pac *pac) >+{ >+ krb5_error_code ret = 0; >+ struct generate_uc uc; >+ >+ *pac = NULL; >+ >+ if (krb5_config_get_bool_default(context, NULL, FALSE, "realms", >+ client->principal->realm, >+ "disable_pac", NULL)) >+ return 0; >+ >+ if (have_plugin) { >+ uc.config = config; >+ uc.client = client; >+ uc.server = server; >+ uc.reply_key = reply_key; >+ uc.pac = pac; >+ uc.pac_attributes = pac_attributes; >+ >+ ret = _krb5_plugin_run_f(context, &kdc_plugin_data, >+ 0, &uc, generate); >+ if (ret != KRB5_PLUGIN_NO_HANDLE) >+ return ret; >+ ret = 0; >+ } >+ >+ if (*pac == NULL) >+ ret = krb5_pac_init(context, pac); >+ >+ return ret; >+} >+ >+struct verify_uc { >+ krb5_kdc_configuration *config; >+ krb5_principal client_principal; >+ krb5_principal delegated_proxy_principal; >+ hdb_entry *client; >+ hdb_entry *server; >+ hdb_entry *krbtgt; >+ krb5_pac *pac; >+}; >+ >+static krb5_error_code KRB5_LIB_CALL >+verify(krb5_context context, const void *plug, void *plugctx, void *userctx) >+{ >+ const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug; >+ struct verify_uc *uc = (struct verify_uc *)userctx; >+ krb5_error_code ret; >+ >+ if (ft->pac_verify == NULL) >+ return KRB5_PLUGIN_NO_HANDLE; >+ >+ ret = ft->pac_verify((void *)plug, >+ context, >+ uc->config, >+ uc->client_principal, >+ uc->delegated_proxy_principal, >+ uc->client, uc->server, uc->krbtgt, uc->pac); >+ return ret; >+} >+ >+krb5_error_code >+_kdc_pac_verify(krb5_context context, >+ krb5_kdc_configuration *config, >+ const krb5_principal client_principal, >+ const krb5_principal delegated_proxy_principal, >+ hdb_entry *client, >+ hdb_entry *server, >+ hdb_entry *krbtgt, >+ krb5_pac *pac) >+{ >+ struct verify_uc uc; >+ >+ if (!have_plugin) >+ return KRB5_PLUGIN_NO_HANDLE; >+ >+ uc.config = config; >+ uc.client_principal = client_principal; >+ uc.delegated_proxy_principal = delegated_proxy_principal; >+ uc.client = client; >+ uc.server = server; >+ uc.krbtgt = krbtgt; >+ uc.pac = pac; >+ >+ return _krb5_plugin_run_f(context, &kdc_plugin_data, >+ 0, &uc, verify); >+} >+ >+static krb5_error_code KRB5_LIB_CALL >+check(krb5_context context, const void *plug, void *plugctx, void *userctx) >+{ >+ const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug; >+ >+ if (ft->client_access == NULL) >+ return KRB5_PLUGIN_NO_HANDLE; >+ return ft->client_access((void *)plug, userctx); >+} >+ >+krb5_error_code >+_kdc_check_access(astgs_request_t r) >+{ >+ krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE; >+ >+ if (have_plugin) { >+ ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, >+ 0, r, check); >+ } >+ >+ if (ret == KRB5_PLUGIN_NO_HANDLE) >+ return kdc_check_flags(r, r->req.msg_type == krb_as_req, >+ r->client, r->server); >+ return ret; >+} >+ >+static krb5_error_code KRB5_LIB_CALL >+referral_policy(krb5_context context, const void *plug, void *plugctx, void *userctx) >+{ >+ const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug; >+ >+ if (ft->referral_policy == NULL) >+ return KRB5_PLUGIN_NO_HANDLE; >+ return ft->referral_policy((void *)plug, userctx); >+} >+ >+krb5_error_code >+_kdc_referral_policy(astgs_request_t r) >+{ >+ krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE; >+ >+ if (have_plugin) >+ ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, 0, r, referral_policy); >+ >+ return ret; >+} >+ >+static krb5_error_code KRB5_LIB_CALL >+finalize_reply(krb5_context context, const void *plug, void *plugctx, void *userctx) >+{ >+ const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug; >+ >+ if (ft->finalize_reply == NULL) >+ return KRB5_PLUGIN_NO_HANDLE; >+ return ft->finalize_reply((void *)plug, userctx); >+} >+ >+krb5_error_code >+_kdc_finalize_reply(astgs_request_t r) >+{ >+ krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE; >+ >+ if (have_plugin) >+ ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, 0, r, finalize_reply); >+ >+ if (ret == KRB5_PLUGIN_NO_HANDLE) >+ ret = 0; >+ >+ return ret; >+} >+ >+static krb5_error_code KRB5_LIB_CALL >+audit(krb5_context context, const void *plug, void *plugctx, void *userctx) >+{ >+ const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug; >+ >+ if (ft->audit == NULL) >+ return KRB5_PLUGIN_NO_HANDLE; >+ return ft->audit((void *)plug, userctx); >+} >+ >+krb5_error_code >+_kdc_plugin_audit(astgs_request_t r) >+{ >+ krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE; >+ >+ if (have_plugin) >+ ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, 0, r, audit); >+ >+ if (ret == KRB5_PLUGIN_NO_HANDLE) >+ ret = 0; >+ >+ return ret; >+} >+ >+KDC_LIB_FUNCTION uintptr_t KDC_LIB_CALL >+kdc_get_instance(const char *libname) >+{ >+ static const char *instance = "libkdc"; >+ >+ if (strcmp(libname, "kdc") == 0) >+ return (uintptr_t)instance; >+ else if (strcmp(libname, "hdb") == 0) >+ return hdb_get_instance(libname); >+ else if (strcmp(libname, "krb5") == 0) >+ return krb5_get_instance(libname); >+ >+ return 0; >+} >+ >+/* >+ * Minimum API surface wrapper for libheimbase object types so it >+ * may remain a private interface, yet plugins can interact with >+ * objects. >+ */ >+ >+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL >+kdc_object_alloc(size_t size, const char *name, kdc_type_dealloc dealloc) >+{ >+ return heim_alloc(size, name, dealloc); >+} >+ >+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL >+kdc_object_retain(kdc_object_t o) >+{ >+ return heim_retain(o); >+} >+ >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_object_release(kdc_object_t o) >+{ >+ heim_release(o); >+} >+ >+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL >+kdc_bool_create(krb5_boolean v) >+{ >+ return heim_bool_create(v); >+} >+ >+KDC_LIB_FUNCTION krb5_boolean KDC_LIB_CALL >+kdc_bool_get_value(kdc_object_t o) >+{ >+ return heim_bool_val(o); >+} >+ >+struct kdc_array_iterator_trampoline_data { >+ kdc_array_iterator_t iter; >+ void *data; >+}; >+ >+/* >+ * Calling convention shim to avoid needing to update all internal >+ * consumers of heim_array_iterate_f() >+ */ >+static void >+_kdc_array_iterator_trampoline(kdc_object_t o, void *data, int *stop) >+{ >+ struct kdc_array_iterator_trampoline_data *t = data; >+ >+ t->iter(o, t->data, stop); >+} >+ >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_array_iterate(kdc_array_t a, void *d, kdc_array_iterator_t iter) >+{ >+ struct kdc_array_iterator_trampoline_data t; >+ >+ t.iter = iter; >+ t.data = d; >+ >+ heim_array_iterate_f((heim_array_t)a, &t, _kdc_array_iterator_trampoline); >+} >+ >+KDC_LIB_FUNCTION size_t KDC_LIB_CALL >+kdc_array_get_length(kdc_array_t a) >+{ >+ return heim_array_get_length((heim_array_t)a); >+} >+ >+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL >+kdc_array_get_value(heim_array_t a, size_t i) >+{ >+ return heim_array_get_value((heim_array_t)a, i); >+} >+ >+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL >+kdc_array_copy_value(heim_array_t a, size_t i) >+{ >+ return heim_array_copy_value((heim_array_t)a, i); >+} >+ >+KDC_LIB_FUNCTION kdc_string_t KDC_LIB_CALL >+kdc_string_create(const char *s) >+{ >+ return (kdc_string_t)heim_string_create(s); >+} >+ >+KDC_LIB_FUNCTION const char * KDC_LIB_CALL >+kdc_string_get_utf8(kdc_string_t s) >+{ >+ return heim_string_get_utf8((heim_string_t)s); >+} >+ >+KDC_LIB_FUNCTION kdc_data_t >+kdc_data_create(const void *d, size_t len) >+{ >+ return (kdc_data_t)heim_data_create(d, len); >+} >+ >+KDC_LIB_FUNCTION const krb5_data * KDC_LIB_CALL >+kdc_data_get_data(kdc_data_t d) >+{ >+ return heim_data_get_data((heim_data_t)d); >+} >+ >+KDC_LIB_FUNCTION kdc_number_t KDC_LIB_CALL >+kdc_number_create(int64_t v) >+{ >+ return (kdc_number_t)heim_number_create(v); >+} >+ >+KDC_LIB_FUNCTION int64_t KDC_LIB_CALL >+kdc_number_get_value(kdc_number_t n) >+{ >+ return heim_number_get_long((heim_number_t)n); >+} >+ >+/* >+ * Plugin accessors >+ */ >+ >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL >+kdc_request_add_reply_padata(astgs_request_t r, PA_DATA *md) >+{ >+ heim_assert(r->rep.padata != NULL, "reply padata not allocated"); >+ return add_METHOD_DATA(r->rep.padata, md); >+} >+ >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL >+kdc_request_add_encrypted_padata(astgs_request_t r, PA_DATA *md) >+{ >+ if (r->ek.encrypted_pa_data == NULL) { >+ r->ek.encrypted_pa_data = calloc(1, sizeof *(r->ek.encrypted_pa_data)); >+ if (r->ek.encrypted_pa_data == NULL) { >+ return ENOMEM; >+ } >+ } >+ >+ return add_METHOD_DATA(r->ek.encrypted_pa_data, md); >+} >+ >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL >+kdc_request_add_pac_buffer(astgs_request_t r, >+ uint32_t pactype, >+ const krb5_data *d) >+{ >+ krb5_error_code ret; >+ krb5_pac pac; >+ >+ if (r->pac == NULL) { >+ ret = krb5_pac_init(r->context, &pac); >+ if (ret) >+ return ret; >+ } else >+ pac = heim_retain(r->pac); >+ >+ ret = krb5_pac_add_buffer(r->context, pac, pactype, d); >+ if (ret == 0 && r->pac == NULL) >+ r->pac = pac; >+ else >+ heim_release(pac); >+ >+ return ret; >+} >+ >+#undef _KDC_REQUEST_GET_ACCESSOR >+#define _KDC_REQUEST_GET_ACCESSOR(R, T, f) \ >+ KDC_LIB_FUNCTION T KDC_LIB_CALL \ >+ kdc_request_get_ ## f(R r) \ >+ { \ >+ return r->f; \ >+ } >+ >+#undef _KDC_REQUEST_SET_ACCESSOR >+#define _KDC_REQUEST_SET_ACCESSOR(R, T, f) \ >+ KDC_LIB_FUNCTION void KDC_LIB_CALL \ >+ kdc_request_set_ ## f(R r, T v) \ >+ { \ >+ r->f = v; \ >+ } >+ >+#undef _KDC_REQUEST_GET_ACCESSOR_PTR >+#define _KDC_REQUEST_GET_ACCESSOR_PTR(R, T, f) \ >+ KDC_LIB_FUNCTION const T KDC_LIB_CALL \ >+ kdc_request_get_ ## f(R r) \ >+ { \ >+ return r->f; \ >+ } >+ >+#undef _KDC_REQUEST_SET_ACCESSOR_PTR >+#define _KDC_REQUEST_SET_ACCESSOR_PTR(R, T, t, f) \ >+ KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL \ >+ kdc_request_set_ ## f(R r, const T v) \ >+ { \ >+ krb5_error_code ret; \ >+ T tmp; \ >+ \ >+ if (v == r->f) \ >+ return 0; \ >+ else if (v) { \ >+ ret = copy_##t(v, &tmp); \ >+ if (ret) \ >+ return ret; \ >+ } else \ >+ tmp = NULL; \ >+ \ >+ free_##t(r->f); \ >+ r->f = tmp; \ >+ \ >+ return 0; \ >+ } >+ >+#undef _KDC_REQUEST_GET_ACCESSOR_STRUCT >+#define _KDC_REQUEST_GET_ACCESSOR_STRUCT(R, T, f) \ >+ KDC_LIB_FUNCTION const T * KDC_LIB_CALL \ >+ kdc_request_get_ ## f(R r) \ >+ { \ >+ return &r->f; \ >+ } >+ >+#undef _KDC_REQUEST_SET_ACCESSOR_STRUCT >+#define _KDC_REQUEST_SET_ACCESSOR_STRUCT(R, T, t, f) \ >+ KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL \ >+ kdc_request_set_ ## f(R r, const T *v) \ >+ { \ >+ krb5_error_code ret; \ >+ T tmp; \ >+ \ >+ if (v == NULL) \ >+ return EINVAL; \ >+ else if (v == &r->f) \ >+ return 0; \ >+ \ >+ ret = copy_##t(v, &tmp); \ >+ if (ret) \ >+ return ret; \ >+ \ >+ free_##t(&r->f); \ >+ r->f = tmp; \ >+ \ >+ return 0; \ >+ } >+ >+static krb5_error_code >+copy_string_ptr(const char *src, char **dst) >+{ >+ *dst = strdup(src); >+ if (*dst == NULL) >+ return ENOMEM; >+ >+ return 0; >+} >+ >+static void >+free_string_ptr(char *s) >+{ >+ free(s); >+} >+ >+static krb5_error_code >+copy_Principal_ptr(krb5_const_principal src, krb5_principal *dst) >+{ >+ krb5_error_code ret; >+ krb5_principal p; >+ >+ *dst = NULL; >+ >+ p = calloc(1, sizeof(*p)); >+ if (p == NULL) >+ return ENOMEM; >+ >+ ret = copy_Principal(src, p); >+ if (ret == 0) >+ *dst = p; >+ else >+ free(p); >+ >+ return ret; >+} >+ >+static void >+free_Principal_ptr(krb5_principal p) >+{ >+ if (p) { >+ free_Principal(p); >+ free(p); >+ } >+} >+ >+static krb5_error_code >+copy_pac(const struct krb5_pac_data *src, struct krb5_pac_data **dst) >+{ >+ /* FIXME use heim_copy() when it exists */ >+ *dst = (krb5_pac)heim_retain((heim_object_t)src); >+ return 0; >+} >+ >+static void >+free_pac(struct krb5_pac_data *o) >+{ >+ heim_release(o); >+} >+ >+static krb5_error_code >+copy_keyblock(const EncryptionKey *src, EncryptionKey *dst) >+{ >+ return copy_EncryptionKey(src, dst); >+} >+ >+static void >+free_keyblock(EncryptionKey *key) >+{ >+ krb5_free_keyblock_contents(NULL, key); >+} >+ >+#undef HEIMDAL_KDC_KDC_ACCESSORS_H >+#include "kdc-accessors.h" >+ >+#undef _KDC_REQUEST_GET_ACCESSOR >+#undef _KDC_REQUEST_SET_ACCESSOR >+ >+#undef _KDC_REQUEST_GET_ACCESSOR_PTR >+#undef _KDC_REQUEST_SET_ACCESSOR_PTR >+#define _KDC_REQUEST_SET_ACCESSOR_PTR(R, T, t, f) \ >+ void \ >+ _kdc_request_set_ ## f ## _nocopy(R r, T *v) \ >+ { \ >+ if (*v != r->f) { \ >+ free_##t(r->f); \ >+ r->f = *v; \ >+ } \ >+ *v = NULL; \ >+ } >+ >+#undef _KDC_REQUEST_GET_ACCESSOR_STRUCT >+#undef _KDC_REQUEST_SET_ACCESSOR_STRUCT >+#define _KDC_REQUEST_SET_ACCESSOR_STRUCT(R, T, t, f) \ >+ void \ >+ _kdc_request_set_ ## f ## _nocopy(R r, T *v) \ >+ { \ >+ if (v != &r->f) { \ >+ free_##t(&r->f); \ >+ r->f = *v; \ >+ } \ >+ memset(v, 0, sizeof(*v)); \ >+ } >+ >+#undef HEIMDAL_KDC_KDC_ACCESSORS_H >+#include "kdc-accessors.h" >diff --git a/third_party/heimdal/kdc/kdc-plugin.h b/third_party/heimdal/kdc/kdc-plugin.h >new file mode 100644 >index 000000000000..efe8dd6abe0e >--- /dev/null >+++ b/third_party/heimdal/kdc/kdc-plugin.h >@@ -0,0 +1,136 @@ >+/* >+ * Copyright (c) 2006 Kungliga Tekniska Högskolan >+ * (Royal Institute of Technology, Stockholm, Sweden). >+ * All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * 3. Neither the name of the Institute nor the names of its contributors >+ * may be used to endorse or promote products derived from this software >+ * without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND >+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE >+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >+ * SUCH DAMAGE. >+ */ >+ >+/* $Id$ */ >+ >+#ifndef HEIMDAL_KDC_KDC_PLUGIN_H >+#define HEIMDAL_KDC_KDC_PLUGIN_H 1 >+ >+#include <krb5.h> >+#include <kdc.h> >+#include <kdc-accessors.h> >+#include <hdb.h> >+ >+/* >+ * Allocate a PAC for the given client with krb5_pac_init(), >+ * and fill its contents in with krb5_pac_add_buffer(). >+ */ >+ >+typedef krb5_error_code >+(KRB5_CALLCONV *krb5plugin_kdc_pac_generate)(void *, >+ krb5_context, /* context */ >+ krb5_kdc_configuration *, /* configuration */ >+ hdb_entry *, /* client */ >+ hdb_entry *, /* server */ >+ const krb5_keyblock *, /* pk_replykey */ >+ uint64_t, /* pac_attributes */ >+ krb5_pac *); >+ >+/* >+ * Verify the PAC KDC signatures by fetching the appropriate TGS key >+ * and calling krb5_pac_verify() with that key. Optionally update the >+ * PAC buffers on success. >+ */ >+ >+typedef krb5_error_code >+(KRB5_CALLCONV *krb5plugin_kdc_pac_verify)(void *, >+ krb5_context, /* context */ >+ krb5_kdc_configuration *, /* configuration */ >+ const krb5_principal, /* new ticket client */ >+ const krb5_principal, /* delegation proxy */ >+ hdb_entry *,/* client */ >+ hdb_entry *,/* server */ >+ hdb_entry *,/* krbtgt */ >+ krb5_pac *); >+ >+/* >+ * Authorize the client principal's access to the Authentication Service (AS). >+ * This function is called after any pre-authentication has completed. >+ */ >+ >+typedef krb5_error_code >+(KRB5_CALLCONV *krb5plugin_kdc_client_access)(void *, astgs_request_t); >+ >+/* >+ * A referral policy plugin can either rewrite the server principal >+ * by resetting priv->server_princ, or it can disable referral >+ * processing entirely by returning an error. >+ * >+ * The error code from the previous server lookup is available as r->ret. >+ * >+ * If the function returns KRB5_PLUGIN_NO_HANDLE, the TGS will continue >+ * with its default referral handling. >+ * >+ * Note well: the plugin should free priv->server_princ is replacing. >+ */ >+ >+typedef krb5_error_code >+(KRB5_CALLCONV *krb5plugin_kdc_referral_policy)(void *, astgs_request_t); >+ >+/* >+ * Update the AS or TGS reply immediately prior to encoding. >+ */ >+ >+typedef krb5_error_code >+(KRB5_CALLCONV *krb5plugin_kdc_finalize_reply)(void *, astgs_request_t); >+ >+/* >+ * Audit an AS or TGS request. This function is called after encoding the >+ * reply (on success), or before encoding the error message. If a HDB audit >+ * function is also present, it is called after this one. >+ * >+ * The request should not be modified by the plugin. >+ */ >+ >+typedef krb5_error_code >+(KRB5_CALLCONV *krb5plugin_kdc_audit)(void *, astgs_request_t); >+ >+/* >+ * Plugins should carefully check API contract notes for changes >+ * between plugin API versions. >+ */ >+#define KRB5_PLUGIN_KDC_VERSION_10 10 >+ >+typedef struct krb5plugin_kdc_ftable { >+ int minor_version; >+ krb5_error_code (KRB5_CALLCONV *init)(krb5_context, void **); >+ void (KRB5_CALLCONV *fini)(void *); >+ krb5plugin_kdc_pac_generate pac_generate; >+ krb5plugin_kdc_pac_verify pac_verify; >+ krb5plugin_kdc_client_access client_access; >+ krb5plugin_kdc_referral_policy referral_policy; >+ krb5plugin_kdc_finalize_reply finalize_reply; >+ krb5plugin_kdc_audit audit; >+} krb5plugin_kdc_ftable; >+ >+#endif /* HEIMDAL_KDC_KDC_PLUGIN_H */ >diff --git a/third_party/heimdal/kdc/kdc-replay.c b/third_party/heimdal/kdc/kdc-replay.c >index af4e55c356d9..29190f7837f8 100644 >--- a/third_party/heimdal/kdc/kdc-replay.c >+++ b/third_party/heimdal/kdc/kdc-replay.c >@@ -184,6 +184,8 @@ main(int argc, char **argv) > unsigned int tag2; > ret = der_get_tag (r.data, r.length, > &cl, &ty, &tag2, NULL); >+ if (ret) >+ krb5_err(context, 1, ret, "Could not decode replay data"); > if (MAKE_TAG(cl, ty, 0) != clty) > krb5_errx(context, 1, "class|type mismatch: %d != %d", > (int)MAKE_TAG(cl, ty, 0), (int)clty); >diff --git a/third_party/heimdal/kdc/kdc.h b/third_party/heimdal/kdc/kdc.h >index cbf4f5117382..e3709ada6b0a 100644 >--- a/third_party/heimdal/kdc/kdc.h >+++ b/third_party/heimdal/kdc/kdc.h >@@ -1,5 +1,5 @@ > /* >- * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan >+ * Copyright (c) 1997-2022 Kungliga Tekniska Högskolan > * (Royal Institute of Technology, Stockholm, Sweden). > * > * Copyright (c) 2005 Andrew Bartlett <abartlet@samba.org> >@@ -46,120 +46,27 @@ > #include <kx509_asn1.h> > #include <gssapi/gssapi.h> > >-#define heim_pcontext krb5_context >-#define heim_pconfig krb5_kdc_configuration * >-#include <heimbase-svc.h> >- > enum krb5_kdc_trpolicy { > TRPOLICY_ALWAYS_CHECK, > TRPOLICY_ALLOW_PER_PRINCIPAL, > TRPOLICY_ALWAYS_HONOUR_REQUEST > }; > >-typedef struct krb5_kdc_configuration { >- krb5_boolean require_preauth; /* require preauth for all principals */ >- time_t kdc_warn_pwexpire; /* time before expiration to print a warning */ >- >- struct HDB **db; >- int num_db; >- >- int num_kdc_processes; >- >- krb5_boolean encode_as_rep_as_tgs_rep; /* bug compatibility */ >- >- /* >- * Windows 2019 (and earlier versions) always sends the salt >- * and Samba has testsuites that check this behaviour, so a >- * Samba AD DC will set this flag to match the AS-REP packet >- * exactly. >- */ >- krb5_boolean force_include_pa_etype_salt; >- >- krb5_boolean tgt_use_strongest_session_key; >- krb5_boolean preauth_use_strongest_session_key; >- krb5_boolean svc_use_strongest_session_key; >- krb5_boolean use_strongest_server_key; >- >- krb5_boolean check_ticket_addresses; >- krb5_boolean warn_ticket_addresses; >- krb5_boolean allow_null_ticket_addresses; >- krb5_boolean allow_anonymous; >- krb5_boolean historical_anon_realm; >- krb5_boolean strict_nametypes; >- enum krb5_kdc_trpolicy trpolicy; >- >- krb5_boolean require_pac; >- krb5_boolean enable_armored_pa_enc_timestamp; >- krb5_boolean enable_unarmored_pa_enc_timestamp; >- >- krb5_boolean autodetect_referrals; >- >- krb5_boolean enable_pkinit; >- krb5_boolean pkinit_princ_in_cert; >- const char *pkinit_kdc_identity; >- const char *pkinit_kdc_anchors; >- const char *pkinit_kdc_friendly_name; >- const char *pkinit_kdc_ocsp_file; >- char **pkinit_kdc_cert_pool; >- char **pkinit_kdc_revoke; >- int pkinit_dh_min_bits; >- /* XXX Turn these into bit-fields */ >- int pkinit_require_binding; >- int pkinit_allow_proxy_certs; >- int synthetic_clients; >- int pkinit_max_life_from_cert_extension; >- krb5_timestamp pkinit_max_life_from_cert; >- krb5_timestamp pkinit_max_life_bound; >- krb5_timestamp synthetic_clients_max_life; >- krb5_timestamp synthetic_clients_max_renew; >- >- krb5_log_facility *logf; >- >- int enable_digest; >- int digests_allowed; >- >- int enable_gss_preauth; >- int enable_gss_auth_data; >- gss_OID_set gss_mechanisms_allowed; >- gss_OID_set gss_cross_realm_mechanisms_allowed; >- >- size_t max_datagram_reply_length; >- >- int enable_kx509; >- >- const char *app; >-} krb5_kdc_configuration; >- >-#define ASTGS_REQUEST_DESC_COMMON_ELEMENTS \ >- HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS; \ >- \ >- KDC_REQ req; \ >- \ >- KDC_REP rep; \ >- EncTicketPart et; \ >- EncKDCRepPart ek; \ >- \ >- /* princ requested by client (AS) or canon princ (TGT) */ \ >- krb5_principal client_princ; \ >- hdb_entry_ex *client; \ >- HDB *clientdb; \ >- \ >- krb5_principal server_princ; \ >- hdb_entry_ex *server; \ >- \ >- krb5_keyblock reply_key; \ >- \ >- krb5_pac pac; \ >- uint64_t pac_attributes; >+struct krb5_kdc_configuration; >+typedef struct krb5_kdc_configuration krb5_kdc_configuration; > >-#ifndef __KDC_LOCL_H__ >-struct astgs_request_desc { >- ASTGS_REQUEST_DESC_COMMON_ELEMENTS >-}; >-#endif >+/* >+ * Access to request fields by plugins and other out-of-tree >+ * consumers should be via the functions in kdc-accessors.h. >+ */ > >+struct kdc_request_desc; > typedef struct kdc_request_desc *kdc_request_t; >+ >+struct astgs_request_desc; > typedef struct astgs_request_desc *astgs_request_t; >+ >+struct kx509_req_context_desc; > typedef struct kx509_req_context_desc *kx509_req_context; > > struct krb5_kdc_service { >@@ -170,9 +77,54 @@ struct krb5_kdc_service { > krb5_error_code (*process)(kdc_request_t *, int *claim); > }; > >-#include <kdc-protos.h> >+/* >+ * The following fields are guaranteed stable within a major >+ * release of Heimdal and can be manipulated by applications >+ * that manage KDC requests themselves using libkdc. >+ * >+ * Applications can make custom KDC configuration available >+ * to libkdc by using krb5_set_config(). >+ */ > >-#undef heim_pcontext >-#undef heim_pconfig >+#define KRB5_KDC_CONFIGURATION_COMMON_ELEMENTS \ >+ krb5_log_facility *logf; \ >+ struct HDB **db; \ >+ size_t num_db; \ >+ const char *app; \ >+ \ >+ /* \ >+ * Windows 2019 (and earlier versions) always sends the salt\ >+ * and Samba has testsuites that check this behaviour, so a \ >+ * Samba AD DC will set this flag to match the AS-REP packet\ >+ * exactly. \ >+ */ \ >+ unsigned int force_include_pa_etype_salt : 1; \ >+ \ >+ unsigned int tgt_use_strongest_session_key : 1; \ >+ unsigned int preauth_use_strongest_session_key : 1; \ >+ unsigned int svc_use_strongest_session_key : 1; \ >+ unsigned int use_strongest_server_key : 1; \ >+ \ >+ unsigned int require_pac : 1; \ >+ unsigned int enable_armored_pa_enc_timestamp : 1 > >+#ifndef __KDC_LOCL_H__ >+struct krb5_kdc_configuration { >+ KRB5_KDC_CONFIGURATION_COMMON_ELEMENTS; >+}; > #endif >+ >+typedef void *kdc_object_t; >+typedef struct kdc_array_data *kdc_array_t; >+typedef struct kdc_dict_data *kdc_dict_t; >+typedef struct kdc_string_data *kdc_string_t; >+typedef struct kdc_data_data *kdc_data_t; >+typedef struct kdc_number_data *kdc_number_t; >+ >+typedef void (KRB5_CALLCONV *kdc_array_iterator_t)(kdc_object_t, void *, int *); >+ >+typedef void (KRB5_CALLCONV *kdc_type_dealloc)(kdc_object_t); >+ >+#include <kdc-protos.h> >+ >+#endif /* __KDC_H__ */ >diff --git a/third_party/heimdal/kdc/kdc_locl.h b/third_party/heimdal/kdc/kdc_locl.h >index e7b86151def0..8418a91a0a4b 100644 >--- a/third_party/heimdal/kdc/kdc_locl.h >+++ b/third_party/heimdal/kdc/kdc_locl.h >@@ -64,15 +64,95 @@ struct kdc_request_desc { > HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS; > }; > >-struct as_request_pa_state; > struct kdc_patypes; > >+struct krb5_kdc_configuration { >+ KRB5_KDC_CONFIGURATION_COMMON_ELEMENTS; >+ >+ int num_kdc_processes; >+ >+ size_t max_datagram_reply_length; >+ >+ time_t kdc_warn_pwexpire; /* time before expiration to print a warning */ >+ >+ unsigned int require_preauth : 1; /* require preauth for all principals */ >+ unsigned int encode_as_rep_as_tgs_rep : 1; /* bug compatibility */ >+ >+ unsigned int check_ticket_addresses : 1; >+ unsigned int warn_ticket_addresses : 1; >+ unsigned int allow_null_ticket_addresses : 1; >+ unsigned int allow_anonymous : 1; >+ unsigned int historical_anon_realm : 1; >+ unsigned int strict_nametypes : 1; >+ enum krb5_kdc_trpolicy trpolicy; >+ >+ unsigned int enable_unarmored_pa_enc_timestamp : 1; >+ >+ unsigned int enable_pkinit : 1; >+ unsigned int pkinit_princ_in_cert : 1; >+ const char *pkinit_kdc_identity; >+ const char *pkinit_kdc_anchors; >+ const char *pkinit_kdc_friendly_name; >+ const char *pkinit_kdc_ocsp_file; >+ char **pkinit_kdc_cert_pool; >+ char **pkinit_kdc_revoke; >+ int pkinit_dh_min_bits; >+ unsigned int pkinit_require_binding : 1; >+ unsigned int pkinit_allow_proxy_certs : 1; >+ unsigned int synthetic_clients : 1; >+ unsigned int pkinit_max_life_from_cert_extension : 1; >+ krb5_timestamp pkinit_max_life_from_cert; >+ krb5_timestamp pkinit_max_life_bound; >+ krb5_timestamp synthetic_clients_max_life; >+ krb5_timestamp synthetic_clients_max_renew; >+ >+ int digests_allowed; >+ unsigned int enable_digest : 1; >+ >+ unsigned int enable_kx509 : 1; >+ >+ unsigned int enable_gss_preauth : 1; >+ unsigned int enable_gss_auth_data : 1; >+ gss_OID_set gss_mechanisms_allowed; >+ gss_OID_set gss_cross_realm_mechanisms_allowed; >+ >+}; >+ > struct astgs_request_desc { >- ASTGS_REQUEST_DESC_COMMON_ELEMENTS; >+ HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS; >+ >+ /* AS-REQ or TGS-REQ */ >+ KDC_REQ req; >+ >+ /* AS-REP or TGS-REP */ >+ KDC_REP rep; >+ EncTicketPart et; >+ EncKDCRepPart ek; >+ >+ /* client principal (AS) or TGT/S4U principal (TGS) */ >+ krb5_principal client_princ; >+ hdb_entry *client; >+ HDB *clientdb; >+ krb5_principal canon_client_princ; >+ >+ /* server principal */ >+ krb5_principal server_princ; >+ HDB *serverdb; >+ hdb_entry *server; >+ >+ /* presented ticket in TGS-REQ (unused by AS) */ >+ krb5_principal krbtgt_princ; >+ hdb_entry *krbtgt; >+ HDB *krbtgtdb; >+ krb5_ticket *ticket; >+ >+ krb5_keyblock reply_key; >+ >+ krb5_pac pac; >+ uint64_t pac_attributes; > > /* Only AS */ > const struct kdc_patypes *pa_used; >- struct as_request_pa_state *pa_state; > > /* PA methods can affect both the reply key and the session key (pkinit) */ > krb5_enctype sessionetype; >@@ -89,7 +169,8 @@ struct astgs_request_desc { > unsigned int fast_asserted : 1; > > krb5_crypto armor_crypto; >- hdb_entry_ex *armor_server; >+ hdb_entry *armor_server; >+ HDB *armor_serverdb; > krb5_ticket *armor_ticket; > Key *armor_key; > >@@ -148,4 +229,24 @@ configure(krb5_context context, int argc, char **argv, int *optidx); > void bonjour_announce(krb5_context, krb5_kdc_configuration *); > #endif > >+/* no-copy setters */ >+ >+#undef _KDC_REQUEST_GET_ACCESSOR >+#undef _KDC_REQUEST_SET_ACCESSOR >+ >+#undef _KDC_REQUEST_GET_ACCESSOR_PTR >+#undef _KDC_REQUEST_SET_ACCESSOR_PTR >+#define _KDC_REQUEST_SET_ACCESSOR_PTR(R, T, t, f) \ >+ void \ >+ _kdc_request_set_ ## f ## _nocopy(R r, T *v); >+ >+#undef _KDC_REQUEST_GET_ACCESSOR_STRUCT >+#undef _KDC_REQUEST_SET_ACCESSOR_STRUCT >+#define _KDC_REQUEST_SET_ACCESSOR_STRUCT(R, T, t, f) \ >+ void \ >+ _kdc_request_set_ ## f ## _nocopy(R r, T *v); >+ >+#undef HEIMDAL_KDC_KDC_ACCESSORS_H >+#include "kdc-accessors.h" >+ > #endif /* __KDC_LOCL_H__ */ >diff --git a/third_party/heimdal/kdc/kerberos5.c b/third_party/heimdal/kdc/kerberos5.c >index ee7e56c5f27d..b30d321f6f14 100644 >--- a/third_party/heimdal/kdc/kerberos5.c >+++ b/third_party/heimdal/kdc/kerberos5.c >@@ -33,44 +33,26 @@ > > #include "kdc_locl.h" > >-#define MAX_TIME ((time_t)((1U << 31) - 1)) >+#ifdef TIME_T_SIGNED >+#if SIZEOF_TIME_T == 4 >+#define MAX_TIME ((time_t)INT32_MAX) >+#elif SIZEOF_TIME_T == 8 >+#define MAX_TIME ((time_t)INT64_MAX) >+#else >+#error "Unexpected sizeof(time_t)" >+#endif >+#else >+ >+#if SIZEOF_TIME_T == 4 >+#define MAX_TIME ((time_t)UINT32_MAX) >+#else >+#define MAX_TIME ((time_t)UINT64_MAX) >+#endif >+#endif > > #undef __attribute__ > #define __attribute__(X) > >-struct kdc_pa_auth_status { >- int auth_status; >- const char *auth_details; >- void *free_ptr; >-}; >- >-static krb5_error_code >-_kdc_audit_auth_status(astgs_request_t r, >- struct kdc_pa_auth_status *status, >- const char *pa_type) >-{ >- struct HDB *hdb; >- krb5_error_code ret = 0; >- >- if (r->clientdb) >- hdb = r->clientdb; >- else >- hdb = r->config->db[0]; >- >- if (hdb && hdb->hdb_auth_status) >- ret = hdb->hdb_auth_status(r->context, >- hdb, >- r->client, >- &r->tv_start, >- r->addr, >- r->cname, >- status->auth_status, >- status->auth_details, >- pa_type); >- >- return ret; >-} >- > void > _kdc_fix_time(time_t **t) > { >@@ -104,10 +86,10 @@ set_salt_padata(krb5_context context, > krb5_kdc_configuration *config, > METHOD_DATA *md, Key *key) > { >- if (key->salt) >- return get_pa_etype_info2(context, config, md, key, TRUE); >+ if (!key->salt) >+ return 0; > >- return 0; >+ return get_pa_etype_info2(context, config, md, key, TRUE); > } > > const PA_DATA* >@@ -134,9 +116,9 @@ _kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype) > { > if (principal->name.name_string.len > 0 && > strcmp(principal->name.name_string.val[0], "afs") == 0 && >- (etype == (krb5_enctype)ETYPE_DES_CBC_CRC >- || etype == (krb5_enctype)ETYPE_DES_CBC_MD4 >- || etype == (krb5_enctype)ETYPE_DES_CBC_MD5)) >+ (etype == ETYPE_DES_CBC_CRC >+ || etype == ETYPE_DES_CBC_MD4 >+ || etype == ETYPE_DES_CBC_MD5)) > return TRUE; > return FALSE; > } >@@ -153,7 +135,7 @@ is_default_salt_p(const krb5_salt *default_salt, const Key *key) > return TRUE; > if (default_salt->salttype != key->salt->type) > return FALSE; >- if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt)) >+ if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt) != 0) > return FALSE; > return TRUE; > } >@@ -170,11 +152,11 @@ is_default_salt_p(const krb5_salt *default_salt, const Key *key) > static krb5_boolean > is_good_salt_p(const krb5_salt *default_salt, const Key *key) > { >- if (key->key.keytype != (krb5_enctype)ETYPE_DES_CBC_CRC) >- return TRUE; >- return is_default_salt_p(default_salt, key); >-} >+ if (key->key.keytype == KRB5_ENCTYPE_DES_CBC_CRC) >+ return is_default_salt_p(default_salt, key); > >+ return TRUE; >+} > > krb5_boolean > _kdc_is_anon_request(const KDC_REQ *req) >@@ -217,25 +199,25 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags, > krb5_boolean use_strongest_session_key; > krb5_boolean is_preauth = flags & KFE_IS_PREAUTH; > krb5_boolean is_tgs = flags & KFE_IS_TGS; >- hdb_entry_ex *princ; >+ hdb_entry *princ; > krb5_principal request_princ; > krb5_error_code ret; > krb5_salt def_salt; >- krb5_enctype enctype = (krb5_enctype)ETYPE_NULL; >+ krb5_enctype enctype = ETYPE_NULL; > const krb5_enctype *p; > Key *key = NULL; > size_t i, k, m; > > if (is_preauth && (flags & KFE_USE_CLIENT) && >- r->client->entry.flags.synthetic) >+ r->client->flags.synthetic) > return KRB5KDC_ERR_ETYPE_NOSUPP; > >- if ((flags & KFE_USE_CLIENT) && !r->client->entry.flags.synthetic) { >+ if ((flags & KFE_USE_CLIENT) && !r->client->flags.synthetic) { > princ = r->client; > request_princ = r->client_princ; > } else { > princ = r->server; >- request_princ = r->server->entry.principal; >+ request_princ = r->server->principal; > } > > use_strongest_session_key = >@@ -280,14 +262,14 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags, > /* drive the search with local supported enctypes list */ > p = krb5_kerberos_enctypes(r->context); > for (i = 0; >- p[i] != (krb5_enctype)ETYPE_NULL && enctype == (krb5_enctype)ETYPE_NULL; >+ p[i] != ETYPE_NULL && enctype == ETYPE_NULL; > i++) { > if (krb5_enctype_valid(r->context, p[i]) != 0 && >- !_kdc_is_weak_exception(princ->entry.principal, p[i])) >+ !_kdc_is_weak_exception(princ->principal, p[i])) > continue; > > /* check that the client supports it too */ >- for (k = 0; k < len && enctype == (krb5_enctype)ETYPE_NULL; k++) { >+ for (k = 0; k < len && enctype == ETYPE_NULL; k++) { > > if (p[i] != etypes[k]) > continue; >@@ -304,15 +286,15 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags, > > /* check target princ support */ > key = NULL; >- if (!(flags & KFE_USE_CLIENT) && princ->entry.etypes) { >+ if (!is_preauth && !(flags & KFE_USE_CLIENT) && princ->etypes) { > /* > * Use the etypes list from the server's HDB entry instead > * of deriving it from its long-term keys. This allows an > * entry to have just one long-term key but record support > * for multiple enctypes. > */ >- for (m = 0; m < princ->entry.etypes->len; m++) { >- if (p[i] == princ->entry.etypes->val[m]) { >+ for (m = 0; m < princ->etypes->len; m++) { >+ if (p[i] == princ->etypes->val[m]) { > ret = 0; > break; > } >@@ -324,7 +306,7 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags, > * PA-ETYPE-INFO* or because we're selecting a session key > * enctype. > */ >- while (hdb_next_enctype2key(r->context, &princ->entry, NULL, >+ while (hdb_next_enctype2key(r->context, princ, NULL, > p[i], &key) == 0) { > if (key->key.keyvalue.length == 0) { > ret = KRB5KDC_ERR_NULL_KEY; >@@ -352,12 +334,12 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags, > for(i = 0; ret != 0 && i < len; i++) { > > if (krb5_enctype_valid(r->context, etypes[i]) != 0 && >- !_kdc_is_weak_exception(princ->entry.principal, etypes[i])) >+ !_kdc_is_weak_exception(princ->principal, etypes[i])) > continue; > > key = NULL; > while (ret != 0 && >- hdb_next_enctype2key(r->context, &princ->entry, NULL, >+ hdb_next_enctype2key(r->context, princ, NULL, > etypes[i], &key) == 0) { > if (key->key.keyvalue.length == 0) { > ret = KRB5KDC_ERR_NULL_KEY; >@@ -372,14 +354,14 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags, > } > } > >- if (enctype == (krb5_enctype)ETYPE_NULL) { >+ if (ret == 0 && enctype == ETYPE_NULL) { > /* > * if the service principal is one for which there is a known 1DES > * exception and no other enctype matches both the client request and > * the service key list, provide a DES-CBC-CRC key. > */ > if (ret_key == NULL && >- _kdc_is_weak_exception(princ->entry.principal, ETYPE_DES_CBC_CRC)) { >+ _kdc_is_weak_exception(princ->principal, ETYPE_DES_CBC_CRC)) { > ret = 0; > enctype = ETYPE_DES_CBC_CRC; > } else { >@@ -498,15 +480,13 @@ _kdc_log_timestamp(astgs_request_t r, const char *type, > endtime_str[100], renewtime_str[100]; > > if (authtime) >- _kdc_audit_addkv((kdc_request_t)r, 0, "auth", "%ld", (long)authtime); >+ kdc_audit_setkv_number((kdc_request_t)r, "auth", authtime); > if (starttime && *starttime) >- _kdc_audit_addkv((kdc_request_t)r, 0, "start", "%ld", >- (long)*starttime); >+ kdc_audit_setkv_number((kdc_request_t)r, "start", *starttime); > if (endtime) >- _kdc_audit_addkv((kdc_request_t)r, 0, "end", "%ld", (long)endtime); >+ kdc_audit_setkv_number((kdc_request_t)r, "end", endtime); > if (renew_till && *renew_till) >- _kdc_audit_addkv((kdc_request_t)r, 0, "renew", "%ld", >- (long)*renew_till); >+ kdc_audit_setkv_number((kdc_request_t)r, "renew", *renew_till); > > krb5_format_time(r->context, authtime, > authtime_str, sizeof(authtime_str), TRUE); >@@ -535,9 +515,7 @@ _kdc_log_timestamp(astgs_request_t r, const char *type, > #ifdef PKINIT > > static krb5_error_code >-pa_pkinit_validate(astgs_request_t r, >- const PA_DATA *pa, >- struct kdc_pa_auth_status *auth_status) >+pa_pkinit_validate(astgs_request_t r, const PA_DATA *pa) > { > pk_client_params *pkp = NULL; > char *client_cert = NULL; >@@ -548,22 +526,23 @@ pa_pkinit_validate(astgs_request_t r, > ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; > _kdc_r_log(r, 4, "Failed to decode PKINIT PA-DATA -- %s", > r->cname); >- auth_status->auth_status = HDB_AUTHSTATUS_PKINIT_FAILURE; > goto out; > } > > ret = _kdc_pk_check_client(r, pkp, &client_cert); >+ if (client_cert) >+ kdc_audit_addkv((kdc_request_t)r, 0, KDC_REQUEST_KV_PKINIT_CLIENT_CERT, >+ "%s", client_cert); > if (ret) { > _kdc_set_e_text(r, "PKINIT certificate not allowed to " > "impersonate principal"); >- auth_status->auth_status = HDB_AUTHSTATUS_PKINIT_FAILURE; >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED); > goto out; > } >- auth_status->auth_details = client_cert; >- auth_status->free_ptr = client_cert; > > r->pa_endtime = _kdc_pk_endtime(pkp); >- if (!r->client->entry.flags.synthetic) >+ if (!r->client->flags.synthetic) > r->pa_max_life = _kdc_pk_max_life(pkp); > > _kdc_r_log(r, 4, "PKINIT pre-authentication succeeded -- %s using %s", >@@ -577,10 +556,13 @@ pa_pkinit_validate(astgs_request_t r, > ret = _kdc_add_initial_verified_cas(r->context, r->config, > pkp, &r->et); > >- auth_status->auth_status = HDB_AUTHSTATUS_PKINIT_SUCCESS; >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_PREAUTH_SUCCEEDED); >+ > out: > if (pkp) > _kdc_pk_free_client_param(r->context, pkp); >+ free(client_cert); > > return ret; > } >@@ -588,9 +570,7 @@ pa_pkinit_validate(astgs_request_t r, > #endif /* PKINIT */ > > static krb5_error_code >-pa_gss_validate(astgs_request_t r, >- const PA_DATA *pa, >- struct kdc_pa_auth_status *auth_status) >+pa_gss_validate(astgs_request_t r, const PA_DATA *pa) > { > gss_client_params *gcp = NULL; > char *client_name = NULL; >@@ -603,19 +583,23 @@ pa_gss_validate(astgs_request_t r, > > if (open) { > ret = _kdc_gss_check_client(r, gcp, &client_name); >+ if (client_name) >+ kdc_audit_addkv((kdc_request_t)r, 0, KDC_REQUEST_KV_GSS_INITIATOR, >+ "%s", client_name); > if (ret) { > _kdc_set_e_text(r, "GSS-API client not allowed to " > "impersonate principal"); >- auth_status->auth_status = HDB_AUTHSTATUS_GSS_FAILURE; >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED); > goto out; > } >- auth_status->auth_details = client_name; >- auth_status->free_ptr = client_name; > > r->pa_endtime = _kdc_gss_endtime(r, gcp); > > _kdc_r_log(r, 4, "GSS pre-authentication succeeded -- %s using %s", > r->cname, client_name); >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_PREAUTH_SUCCEEDED); > > ret = _kdc_gss_mk_composite_name_ad(r, gcp); > if (ret) { >@@ -628,19 +612,17 @@ pa_gss_validate(astgs_request_t r, > if (ret) { > if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED) > _kdc_set_e_text(r, "Failed to build GSS pre-authentication reply"); >- > goto out; > } > >- auth_status->auth_status = HDB_AUTHSTATUS_GSS_SUCCESS; >- >- heim_assert(r->pa_state == NULL, "already have PA state, should be NULL"); >- r->pa_state = (struct as_request_pa_state *)gcp; >- gcp = NULL; >+ ret = kdc_request_set_attribute((kdc_request_t)r, >+ HSTR("org.h5l.pa-gss-client-params"), gcp); >+ if (ret) >+ goto out; > > out: >- if (gcp) >- _kdc_gss_free_client_param(r, gcp); >+ kdc_object_release(gcp); >+ free(client_name); > > return ret; > } >@@ -648,28 +630,17 @@ out: > static krb5_error_code > pa_gss_finalize_pac(astgs_request_t r) > { >- gss_client_params *gcp = (gss_client_params *)r->pa_state; >+ gss_client_params *gcp; >+ >+ gcp = kdc_request_get_attribute((kdc_request_t)r, HSTR("org.h5l.pa-gss-client-params")); > > heim_assert(gcp != NULL, "invalid GSS-API client params"); > > return _kdc_gss_finalize_pac(r, gcp); > } > >-static void >-pa_gss_cleanup(astgs_request_t r) >-{ >- gss_client_params *gcp = (gss_client_params *)r->pa_state; >- >- if (gcp) { >- _kdc_gss_free_client_param(r, gcp); >- r->pa_state = NULL; >- } >-} >- > static krb5_error_code >-pa_enc_chal_validate(astgs_request_t r, >- const PA_DATA *pa, >- struct kdc_pa_auth_status *auth_status) >+pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa) > { > krb5_data pepper1, pepper2; > int invalidPassword = 0; >@@ -688,11 +659,12 @@ pa_enc_chal_validate(astgs_request_t r, > return ret; > } > >- if (r->client->entry.flags.locked_out) { >+ if (r->client->flags.locked_out) { > ret = KRB5KDC_ERR_CLIENT_REVOKED; > kdc_log(r->context, r->config, 0, > "Client (%s) is locked out", r->cname); >- auth_status->auth_status = HDB_AUTHSTATUS_CLIENT_LOCKED_OUT; >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_CLIENT_LOCKED_OUT); > return ret; > } > >@@ -716,11 +688,11 @@ pa_enc_chal_validate(astgs_request_t r, > > kdc_log(r->context, r->config, 5, "FAST armor enctype is: %d", (int)aenctype); > >- for (i = 0; i < r->client->entry.keys.len; i++) { >+ for (i = 0; i < r->client->keys.len; i++) { > krb5_crypto challengecrypto, longtermcrypto; > krb5_keyblock challengekey; > >- k = &r->client->entry.keys.val[i]; >+ k = &r->client->keys.val[i]; > > ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto); > if (ret) >@@ -813,20 +785,21 @@ pa_enc_chal_validate(astgs_request_t r, > if (ret) > goto out; > >- ret = set_salt_padata(r->context, r->config, >- r->rep.padata, k); >- if (ret) >- goto out; >+ if (ret == 0) >+ ret = set_salt_padata(r->context, r->config, >+ r->rep.padata, k); > > /* > * Success > */ >- auth_status->auth_status = HDB_AUTHSTATUS_CORRECT_PASSWORD; >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY); > goto out; > } > > if (invalidPassword) { >- auth_status->auth_status = HDB_AUTHSTATUS_WRONG_PASSWORD; >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY); > ret = KRB5KDC_ERR_PREAUTH_FAILED; > } else { > ret = KRB5KDC_ERR_ETYPE_NOSUPP; >@@ -838,9 +811,7 @@ pa_enc_chal_validate(astgs_request_t r, > } > > static krb5_error_code >-pa_enc_ts_validate(astgs_request_t r, >- const PA_DATA *pa, >- struct kdc_pa_auth_status *auth_status) >+pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa) > { > EncryptedData enc_data; > krb5_error_code ret; >@@ -863,11 +834,12 @@ pa_enc_ts_validate(astgs_request_t r, > return ret; > } > >- if (r->client->entry.flags.locked_out) { >+ if (r->client->flags.locked_out) { > ret = KRB5KDC_ERR_CLIENT_REVOKED; > kdc_log(r->context, r->config, 0, > "Client (%s) is locked out", r->cname); >- auth_status->auth_status = HDB_AUTHSTATUS_CLIENT_LOCKED_OUT; >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_CLIENT_LOCKED_OUT); > return ret; > } > >@@ -882,7 +854,7 @@ pa_enc_ts_validate(astgs_request_t r, > goto out; > } > >- ret = hdb_enctype2key(r->context, &r->client->entry, NULL, >+ ret = hdb_enctype2key(r->context, r->client, NULL, > enc_data.etype, &pa_key); > if(ret){ > char *estr; >@@ -935,14 +907,13 @@ pa_enc_ts_validate(astgs_request_t r, > _kdc_r_log(r, 2, "Failed to decrypt PA-DATA -- %s " > "(enctype %s) error %s", > r->cname, str ? str : "unknown enctype", msg); >+ krb5_xfree(str); > krb5_free_error_message(r->context, msg); >- >- free(auth_status->free_ptr); >- auth_status->auth_status = HDB_AUTHSTATUS_WRONG_PASSWORD; >- auth_status->auth_details = str ? str : "unknown enctype"; >- auth_status->free_ptr = str; >- >- if(hdb_next_enctype2key(r->context, &r->client->entry, NULL, >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE, >+ pa_key->key.keytype); >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY); >+ if(hdb_next_enctype2key(r->context, r->client, NULL, > enc_data.etype, &pa_key) == 0) > goto try_next_key; > >@@ -952,10 +923,6 @@ pa_enc_ts_validate(astgs_request_t r, > goto out; > } > free_EncryptedData(&enc_data); >- free(auth_status->free_ptr); >- auth_status->auth_status = HDB_AUTHSTATUS_INVALID; >- auth_status->auth_details = NULL; >- auth_status->free_ptr = NULL; > ret = decode_PA_ENC_TS_ENC(ts_data.data, > ts_data.length, > &p, >@@ -980,7 +947,8 @@ pa_enc_ts_validate(astgs_request_t r, > (unsigned)labs(kdc_time - p.patimestamp), > r->context->max_skew, > r->cname); >- auth_status->auth_details = "AP_ERR_SKEW"; >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_CLIENT_TIME_SKEW); > > /* > * The following is needed to make windows clients to >@@ -995,10 +963,8 @@ pa_enc_ts_validate(astgs_request_t r, > > ret = set_salt_padata(r->context, r->config, > r->rep.padata, pa_key); >- if (ret) >- return ret; >- >- ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key); >+ if (ret == 0) >+ ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key); > if (ret) > return ret; > >@@ -1007,11 +973,11 @@ pa_enc_ts_validate(astgs_request_t r, > str = NULL; > _kdc_r_log(r, 4, "ENC-TS Pre-authentication succeeded -- %s using %s", > r->cname, str ? str : "unknown enctype"); >- _kdc_audit_addkv((kdc_request_t)r, 0, "pa-etype", "%d", >- (int)pa_key->key.keytype); >- auth_status->auth_status = HDB_AUTHSTATUS_CORRECT_PASSWORD; >- auth_status->auth_details = str ? str : "unknown enctype"; >- auth_status->free_ptr = str; >+ krb5_xfree(str); >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE, >+ pa_key->key.keytype); >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY); > > ret = 0; > >@@ -1029,9 +995,7 @@ struct kdc_patypes { > #define PA_SYNTHETIC_OK 4 > #define PA_REPLACE_REPLY_KEY 8 /* PA mech replaces reply key */ > #define PA_USES_LONG_TERM_KEY 16 /* PA mech uses client's long-term key */ >- krb5_error_code (*validate)(astgs_request_t, >- const PA_DATA *pa, >- struct kdc_pa_auth_status *auth_status); >+ krb5_error_code (*validate)(astgs_request_t, const PA_DATA *pa); > krb5_error_code (*finalize_pac)(astgs_request_t r); > void (*cleanup)(astgs_request_t r); > }; >@@ -1074,7 +1038,7 @@ static const struct kdc_patypes pat[] = { > { > KRB5_PADATA_GSS , "GSS", > PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY, >- pa_gss_validate, pa_gss_finalize_pac, pa_gss_cleanup >+ pa_gss_validate, pa_gss_finalize_pac, NULL > }, > }; > >@@ -1107,8 +1071,8 @@ log_patypes(astgs_request_t r, METHOD_DATA *padata) > > str = rk_strpoolcollect(p); > kdc_log(r->context, config, 4, "Client sent patypes: %s", str); >- _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, >- "client-pa", "%s", str); >+ kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, >+ "client-pa", "%s", str); > free(str); > } > >@@ -1273,25 +1237,29 @@ _kdc_encode_reply(krb5_context context, > return ret; > } > if(rep->msg_type == krb_as_rep) { >- krb5_encrypt_EncryptedData(context, >- crypto, >- KRB5_KU_AS_REP_ENC_PART, >- buf, >- len, >- ckvno, >- &rep->enc_part); >- free(buf); >- ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret); >+ ret = krb5_encrypt_EncryptedData(context, >+ crypto, >+ KRB5_KU_AS_REP_ENC_PART, >+ buf, >+ len, >+ ckvno, >+ &rep->enc_part); >+ free(buf); >+ if (ret == 0) >+ ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret); > } else { >- krb5_encrypt_EncryptedData(context, >- crypto, >- rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION, >- buf, >- len, >- ckvno, >- &rep->enc_part); >- free(buf); >- ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret); >+ ret = krb5_encrypt_EncryptedData(context, >+ crypto, >+ rk_is_subkey ? >+ KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : >+ KRB5_KU_TGS_REP_ENC_PART_SESSION, >+ buf, >+ len, >+ ckvno, >+ &rep->enc_part); >+ free(buf); >+ if (ret == 0) >+ ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret); > } > krb5_crypto_destroy(context, crypto); > if(ret) { >@@ -1315,57 +1283,6 @@ _kdc_encode_reply(krb5_context context, > * > */ > >-static krb5_error_code >-make_etype_info_entry(krb5_context context, >- ETYPE_INFO_ENTRY *ent, >- Key *key, >- krb5_boolean include_salt) >-{ >- ent->etype = key->key.keytype; >- if (key->salt && include_salt){ >-#if 0 >- ALLOC(ent->salttype); >- >- if(key->salt->type == hdb_pw_salt) >- *ent->salttype = 0; /* or 1? or NULL? */ >- else if(key->salt->type == hdb_afs3_salt) >- *ent->salttype = 2; >- else { >- kdc_log(context, config, 4, "unknown salt-type: %d", >- key->salt->type); >- return KRB5KRB_ERR_GENERIC; >- } >- /* according to `the specs', we can't send a salt if >- we have AFS3 salted key, but that requires that you >- *know* what cell you are using (e.g by assuming >- that the cell is the same as the realm in lower >- case) */ >-#elif 0 >- ALLOC(ent->salttype); >- *ent->salttype = key->salt->type; >-#else >- /* >- * We shouldn't sent salttype since it is incompatible with the >- * specification and it breaks windows clients. The afs >- * salting problem is solved by using KRB5-PADATA-AFS3-SALT >- * implemented in Heimdal 0.7 and later. >- */ >- ent->salttype = NULL; >-#endif >- krb5_copy_data(context, &key->salt->salt, >- &ent->salt); >- } else { >- /* we return no salt type at all, as that should indicate >- * the default salt type and make everybody happy. some >- * systems (like w2k) dislike being told the salt type >- * here. */ >- >- ent->salttype = NULL; >- ent->salt = NULL; >- } >- return 0; >-} >- > static krb5_error_code > get_pa_etype_info(krb5_context context, > krb5_kdc_configuration *config, >@@ -1373,35 +1290,51 @@ get_pa_etype_info(krb5_context context, > krb5_boolean include_salt) > { > krb5_error_code ret = 0; >- ETYPE_INFO pa; >- unsigned char *buf; >+ ETYPE_INFO_ENTRY eie; /* do not free this one */ >+ ETYPE_INFO ei; >+ PA_DATA pa; > size_t len; > >+ /* >+ * Code moved here from what used to be make_etype_info_entry() because >+ * using the ASN.1 compiler-generated SEQUENCE OF add functions makes that >+ * old function's body and this one's small and clean. >+ * >+ * The following comment blocks were there: >+ * >+ * According to `the specs', we can't send a salt if we have AFS3 salted >+ * key, but that requires that you *know* what cell you are using (e.g by >+ * assuming that the cell is the same as the realm in lower case) >+ * >+ * We shouldn't sent salttype since it is incompatible with the >+ * specification and it breaks windows clients. The afs salting problem >+ * is solved by using KRB5-PADATA-AFS3-SALT implemented in Heimdal 0.7 and >+ * later. >+ * >+ * We return no salt type at all, as that should indicate the default salt >+ * type and make everybody happy. some systems (like w2k) dislike being >+ * told the salt type here. >+ */ > >- pa.len = 1; >- pa.val = calloc(1, sizeof(pa.val[0])); >- if(pa.val == NULL) >- return ENOMEM; >- >- ret = make_etype_info_entry(context, &pa.val[0], ckey, include_salt); >- if (ret) { >- free_ETYPE_INFO(&pa); >- return ret; >- } >- >- ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret); >- free_ETYPE_INFO(&pa); >- if(ret) >- return ret; >- ret = realloc_method_data(md); >- if(ret) { >- free(buf); >- return ret; >- } >- md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO; >- md->val[md->len - 1].padata_value.length = len; >- md->val[md->len - 1].padata_value.data = buf; >- return 0; >+ pa.padata_type = KRB5_PADATA_ETYPE_INFO; >+ pa.padata_value.data = NULL; >+ pa.padata_value.length = 0; >+ ei.len = 0; >+ ei.val = NULL; >+ eie.etype = ckey->key.keytype; >+ eie.salttype = NULL; >+ eie.salt = NULL; >+ if (include_salt && ckey->salt) >+ eie.salt = &ckey->salt->salt; >+ ret = add_ETYPE_INFO(&ei, &eie); >+ if (ret == 0) >+ ASN1_MALLOC_ENCODE(ETYPE_INFO, pa.padata_value.data, pa.padata_value.length, >+ &ei, &len, ret); >+ if (ret == 0) >+ add_METHOD_DATA(md, &pa); >+ free_ETYPE_INFO(&ei); >+ free_PA_DATA(&pa); >+ return ret; > } > > /* >@@ -1642,8 +1575,8 @@ _log_astgs_req(astgs_request_t r, krb5_enctype setype) > > str = rk_strpoolcollect(s); > if (str) >- _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, "etypes", "%s", >- str); >+ kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, "etypes", "%s", >+ str); > free(str); > > ret = krb5_enctype_to_string(r->context, cetype, &cet); >@@ -1664,7 +1597,7 @@ _log_astgs_req(astgs_request_t r, krb5_enctype setype) > _kdc_r_log(r, 4, "%s", str); > free(str); > >- _kdc_audit_addkv((kdc_request_t)r, 0, "etype", "%d/%d", cetype, setype); >+ kdc_audit_addkv((kdc_request_t)r, 0, "etype", "%d/%d", cetype, setype); > > { > char fixedstr[128]; >@@ -1674,8 +1607,8 @@ _log_astgs_req(astgs_request_t r, krb5_enctype setype) > fixedstr, sizeof(fixedstr)); > if (result > 0) { > _kdc_r_log(r, 4, "Requested flags: %s", fixedstr); >- _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, >- "flags", "%s", fixedstr); >+ kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, >+ "flags", "%s", fixedstr); > } > } > } >@@ -1686,30 +1619,28 @@ _log_astgs_req(astgs_request_t r, krb5_enctype setype) > * and error code otherwise. > */ > >-krb5_error_code >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL > kdc_check_flags(astgs_request_t r, > krb5_boolean is_as_req, >- hdb_entry_ex *client_ex, >- hdb_entry_ex *server_ex) >+ hdb_entry *client, >+ hdb_entry *server) > { >- if (client_ex != NULL) { >- hdb_entry *client = &client_ex->entry; >- >+ if (client != NULL) { > /* check client */ > if (client->flags.locked_out) { >- _kdc_audit_addreason((kdc_request_t)r, "Client is locked out"); >+ kdc_audit_addreason((kdc_request_t)r, "Client is locked out"); > return KRB5KDC_ERR_CLIENT_REVOKED; > } > > if (client->flags.invalid) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Client has invalid bit set"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Client has invalid bit set"); > return KRB5KDC_ERR_POLICY; > } > > if (!client->flags.client) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Principal may not act as client"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Principal may not act as client"); > return KRB5KDC_ERR_POLICY; > } > >@@ -1717,8 +1648,8 @@ kdc_check_flags(astgs_request_t r, > char starttime_str[100]; > krb5_format_time(r->context, *client->valid_start, > starttime_str, sizeof(starttime_str), TRUE); >- _kdc_audit_addreason((kdc_request_t)r, "Client not yet valid " >- "until %s", starttime_str); >+ kdc_audit_addreason((kdc_request_t)r, "Client not yet valid " >+ "until %s", starttime_str); > return KRB5KDC_ERR_CLIENT_NOTYET; > } > >@@ -1726,49 +1657,47 @@ kdc_check_flags(astgs_request_t r, > char endtime_str[100]; > krb5_format_time(r->context, *client->valid_end, > endtime_str, sizeof(endtime_str), TRUE); >- _kdc_audit_addreason((kdc_request_t)r, "Client expired at %s", >- endtime_str); >+ kdc_audit_addreason((kdc_request_t)r, "Client expired at %s", >+ endtime_str); > return KRB5KDC_ERR_NAME_EXP; > } > > if (client->flags.require_pwchange && >- (server_ex == NULL || !server_ex->entry.flags.change_pw)) >+ (server == NULL || !server->flags.change_pw)) > return KRB5KDC_ERR_KEY_EXPIRED; > > if (client->pw_end && *client->pw_end < kdc_time >- && (server_ex == NULL || !server_ex->entry.flags.change_pw)) { >+ && (server == NULL || !server->flags.change_pw)) { > char pwend_str[100]; > krb5_format_time(r->context, *client->pw_end, > pwend_str, sizeof(pwend_str), TRUE); >- _kdc_audit_addreason((kdc_request_t)r, "Client's key has expired " >- "at %s", pwend_str); >+ kdc_audit_addreason((kdc_request_t)r, "Client's key has expired " >+ "at %s", pwend_str); > return KRB5KDC_ERR_KEY_EXPIRED; > } > } > > /* check server */ > >- if (server_ex != NULL) { >- hdb_entry *server = &server_ex->entry; >- >+ if (server != NULL) { > if (server->flags.locked_out) { >- _kdc_audit_addreason((kdc_request_t)r, "Server locked out"); >+ kdc_audit_addreason((kdc_request_t)r, "Server locked out"); > return KRB5KDC_ERR_SERVICE_REVOKED; > } > if (server->flags.invalid) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Server has invalid flag set"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Server has invalid flag set"); > return KRB5KDC_ERR_POLICY; > } > if (!server->flags.server) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Principal may not act as server"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Principal may not act as server"); > return KRB5KDC_ERR_POLICY; > } > > if (!is_as_req && server->flags.initial) { >- _kdc_audit_addreason((kdc_request_t)r, >- "AS-REQ is required for server"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "AS-REQ is required for server"); > return KRB5KDC_ERR_POLICY; > } > >@@ -1776,8 +1705,8 @@ kdc_check_flags(astgs_request_t r, > char starttime_str[100]; > krb5_format_time(r->context, *server->valid_start, > starttime_str, sizeof(starttime_str), TRUE); >- _kdc_audit_addreason((kdc_request_t)r, "Server not yet valid " >- "until %s", starttime_str); >+ kdc_audit_addreason((kdc_request_t)r, "Server not yet valid " >+ "until %s", starttime_str); > return KRB5KDC_ERR_SERVICE_NOTYET; > } > >@@ -1785,8 +1714,8 @@ kdc_check_flags(astgs_request_t r, > char endtime_str[100]; > krb5_format_time(r->context, *server->valid_end, > endtime_str, sizeof(endtime_str), TRUE); >- _kdc_audit_addreason((kdc_request_t)r, "Server expired at %s", >- endtime_str); >+ kdc_audit_addreason((kdc_request_t)r, "Server expired at %s", >+ endtime_str); > return KRB5KDC_ERR_SERVICE_EXP; > } > >@@ -1794,8 +1723,8 @@ kdc_check_flags(astgs_request_t r, > char pwend_str[100]; > krb5_format_time(r->context, *server->pw_end, > pwend_str, sizeof(pwend_str), TRUE); >- _kdc_audit_addreason((kdc_request_t)r, "Server's key has expired " >- "at %s", pwend_str); >+ kdc_audit_addreason((kdc_request_t)r, "Server's key has expired " >+ "at %s", pwend_str); > return KRB5KDC_ERR_KEY_EXPIRED; > } > } >@@ -1861,8 +1790,8 @@ krb5_error_code > _kdc_check_anon_policy(astgs_request_t r) > { > if (!r->config->allow_anonymous) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Anonymous tickets denied by local policy"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Anonymous tickets denied by local policy"); > return KRB5KDC_ERR_POLICY; > } > >@@ -1914,8 +1843,8 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey, > krb5_const_principal canon_princ = NULL; > > r->pac_attributes = get_pac_attributes(r->context, &r->req); >- _kdc_audit_addkv((kdc_request_t)r, 0, "pac_attributes", "%lx", >- (long)r->pac_attributes); >+ kdc_audit_setkv_number((kdc_request_t)r, "pac_attributes", >+ r->pac_attributes); > > if (!is_tgs && !(r->pac_attributes & (KRB5_PAC_WAS_REQUESTED | KRB5_PAC_WAS_GIVEN_IMPLICITLY))) > return 0; >@@ -1928,6 +1857,7 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey, > */ > > ret = _kdc_pac_generate(r->context, >+ r->config, > r->client, > r->server, > r->pa_used && !pa_used_flag_isset(r, PA_USES_LONG_TERM_KEY) >@@ -1942,7 +1872,7 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey, > if (r->pac == NULL) > return 0; > >- rodc_id = r->server->entry.kvno >> 16; >+ rodc_id = r->server->kvno >> 16; > > /* libkrb5 expects ticket and PAC client names to match */ > ret = _krb5_principalname2krb5_principal(r->context, &client, >@@ -1956,14 +1886,14 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey, > * impersonate any realm. Windows always canonicalizes the realm, > * but Heimdal permits aliases between realms.) > */ >- if (krb5_realm_compare(r->context, client, r->client->entry.principal)) { >+ if (krb5_realm_compare(r->context, client, r->canon_client_princ)) { > char *cpn = NULL; > >- canon_princ = r->client->entry.principal; >+ canon_princ = r->canon_client_princ; > >- krb5_unparse_name(r->context, canon_princ, &cpn); >- _kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s", >- cpn ? cpn : "<unknown>"); >+ (void) krb5_unparse_name(r->context, canon_princ, &cpn); >+ kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s", >+ cpn ? cpn : "<unknown>"); > krb5_xfree(cpn); > } > >@@ -2027,8 +1957,8 @@ static int > require_preauth_p(astgs_request_t r) > { > return r->config->require_preauth >- || r->client->entry.flags.require_preauth >- || r->server->entry.flags.require_preauth; >+ || r->client->flags.require_preauth >+ || r->server->flags.require_preauth; > } > > >@@ -2099,11 +2029,13 @@ static krb5_error_code > get_local_tgs(krb5_context context, > krb5_kdc_configuration *config, > krb5_const_realm realm, >- hdb_entry_ex **krbtgt) >+ HDB **krbtgtdb, >+ hdb_entry **krbtgt) > { > krb5_error_code ret; > krb5_principal tgs_name; > >+ *krbtgtdb = NULL; > *krbtgt = NULL; > > ret = krb5_make_principal(context, >@@ -2116,7 +2048,7 @@ get_local_tgs(krb5_context context, > return ret; > > ret = _kdc_db_fetch(context, config, tgs_name, >- HDB_F_GET_KRBTGT, NULL, NULL, krbtgt); >+ HDB_F_GET_KRBTGT, NULL, krbtgtdb, krbtgt); > krb5_free_principal(context, tgs_name); > > return ret; >@@ -2143,7 +2075,6 @@ _kdc_as_rep(astgs_request_t r) > const PA_DATA *pa; > krb5_boolean is_tgs; > const char *msg; >- hdb_entry_ex *krbtgt = NULL; > Key *krbtgt_key; > > memset(rep, 0, sizeof(*rep)); >@@ -2227,7 +2158,7 @@ _kdc_as_rep(astgs_request_t r) > case HDB_ERR_WRONG_REALM: { > char *fixed_client_name = NULL; > >- ret = krb5_unparse_name(r->context, r->client->entry.principal, >+ ret = krb5_unparse_name(r->context, r->client->principal, > &fixed_client_name); > if (ret) { > goto out; >@@ -2240,26 +2171,26 @@ _kdc_as_rep(astgs_request_t r) > r->e_text = NULL; > ret = _kdc_fast_mk_error(r, r->rep.padata, r->armor_crypto, > &req->req_body, >- r->ret = KRB5_KDC_ERR_WRONG_REALM, >- r->client->entry.principal, r->server_princ, >+ r->error_code = KRB5_KDC_ERR_WRONG_REALM, >+ r->client->principal, r->server_princ, > NULL, NULL, r->reply); > goto out; > } > default: > { >- struct kdc_pa_auth_status auth_status = {HDB_AUTHSTATUS_CLIENT_UNKNOWN, NULL, NULL}; > msg = krb5_get_error_message(r->context, ret); > kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->cname, msg); > krb5_free_error_message(r->context, msg); > ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; >- _kdc_audit_auth_status(r, &auth_status, NULL); >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_CLIENT_UNKNOWN); > goto out; > } > } > ret = _kdc_db_fetch(r->context, config, r->server_princ, > HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS | > flags | (is_tgs ? HDB_F_GET_KRBTGT : 0), >- NULL, NULL, &r->server); >+ NULL, &r->serverdb, &r->server); > switch (ret) { > case 0: /* Success */ > break; >@@ -2313,28 +2244,24 @@ _kdc_as_rep(astgs_request_t r) > i = 0; > pa = _kdc_find_padata(req, &i, pat[n].type); > if (pa) { >- struct kdc_pa_auth_status auth_status = {HDB_AUTHSTATUS_INVALID, NULL, NULL}; >- >- if (r->client->entry.flags.synthetic && >+ if (r->client->flags.synthetic && > !(pat[n].flags & PA_SYNTHETIC_OK)) { > kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname); >- ret = HDB_ERR_NOENTRY; >+ ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; > goto out; > } >- _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s", >- pat[n].name); >- ret = pat[n].validate(r, pa, &auth_status); >+ kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s", >+ pat[n].name); >+ ret = pat[n].validate(r, pa); > if (ret != 0) { > krb5_error_code ret2; > Key *ckey = NULL; > krb5_boolean default_salt; > >- if (auth_status.auth_status == HDB_AUTHSTATUS_INVALID) >- auth_status.auth_status = HDB_AUTHSTATUS_GENERIC_FAILURE; >- _kdc_audit_auth_status(r, >- &auth_status, >- pat[n].name); >- free(auth_status.free_ptr); >+ if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED && >+ !kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT)) >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_PREAUTH_FAILED); > > /* > * If there is a client key, send ETYPE_INFO{,2} >@@ -2350,17 +2277,14 @@ _kdc_as_rep(astgs_request_t r) > } > goto out; > } >+ if (!kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT)) >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_PREAUTH_SUCCEEDED); > kdc_log(r->context, config, 4, > "%s pre-authentication succeeded -- %s", > pat[n].name, r->cname); > found_pa = 1; > r->pa_used = &pat[n]; >- >- if (auth_status.auth_status == HDB_AUTHSTATUS_INVALID) >- auth_status.auth_status = HDB_AUTHSTATUS_GENERIC_SUCCESS; >- >- _kdc_audit_auth_status(r, &auth_status, r->pa_used->name); >- free(auth_status.free_ptr); > r->et.flags.pre_authent = 1; > } > } >@@ -2371,9 +2295,9 @@ _kdc_as_rep(astgs_request_t r) > size_t n; > krb5_boolean default_salt; > >- if (r->client->entry.flags.synthetic) { >+ if (r->client->flags.synthetic) { > kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname); >- ret = HDB_ERR_NOENTRY; >+ ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; > goto out; > } > >@@ -2430,6 +2354,8 @@ _kdc_as_rep(astgs_request_t r) > goto out; > } > >+ r->canon_client_princ = r->client->principal; >+ > /* > * Verify flags after the user been required to prove its identity > * with in a preauth mech. >@@ -2449,14 +2375,8 @@ _kdc_as_rep(astgs_request_t r) > r->et.flags.anonymous = 1; > } > >- { >- struct kdc_pa_auth_status auth_status >- = {HDB_AUTHSTATUS_AUTHORIZATION_SUCCESS, >- NULL, >- NULL}; >- >- _kdc_audit_auth_status(r, &auth_status, NULL); >- } >+ kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, >+ KDC_AUTH_EVENT_CLIENT_AUTHORIZED); > > /* > * Select the best encryption type for the KDC with out regard to >@@ -2474,11 +2394,11 @@ _kdc_as_rep(astgs_request_t r) > krbtgt_key = skey; > } else { > ret = get_local_tgs(r->context, config, r->server_princ->realm, >- &krbtgt); >+ &r->krbtgtdb, &r->krbtgt); > if (ret) > goto out; > >- ret = _kdc_get_preferred_key(r->context, config, krbtgt, >+ ret = _kdc_get_preferred_key(r->context, config, r->krbtgt, > r->server_princ->realm, > NULL, &krbtgt_key); > if (ret) >@@ -2501,31 +2421,31 @@ _kdc_as_rep(astgs_request_t r) > _kdc_is_anonymous(r->context, r->client_princ)) { > Realm anon_realm = KRB5_ANON_REALM; > ret = copy_Realm(&anon_realm, &rep->crealm); >- } else if (f.canonicalize || r->client->entry.flags.force_canonicalize) >- ret = copy_Realm(&r->client->entry.principal->realm, &rep->crealm); >+ } else if (f.canonicalize || r->client->flags.force_canonicalize) >+ ret = copy_Realm(&r->canon_client_princ->realm, &rep->crealm); > else > ret = copy_Realm(&r->client_princ->realm, &rep->crealm); > if (ret) > goto out; > if (r->et.flags.anonymous) > ret = _kdc_make_anonymous_principalname(&rep->cname); >- else if (f.canonicalize || r->client->entry.flags.force_canonicalize) >- ret = _krb5_principal2principalname(&rep->cname, r->client->entry.principal); >+ else if (f.canonicalize || r->client->flags.force_canonicalize) >+ ret = _krb5_principal2principalname(&rep->cname, r->canon_client_princ); > else > ret = _krb5_principal2principalname(&rep->cname, r->client_princ); > if (ret) > goto out; > > rep->ticket.tkt_vno = 5; >- if (f.canonicalize || r->server->entry.flags.force_canonicalize) >- ret = copy_Realm(&r->server->entry.principal->realm, &rep->ticket.realm); >+ if (f.canonicalize || r->server->flags.force_canonicalize) >+ ret = copy_Realm(&r->server->principal->realm, &rep->ticket.realm); > else > ret = copy_Realm(&r->server_princ->realm, &rep->ticket.realm); > if (ret) > goto out; >- if (f.canonicalize || r->server->entry.flags.force_canonicalize) >+ if (f.canonicalize || r->server->flags.force_canonicalize) > _krb5_principal2principalname(&rep->ticket.sname, >- r->server->entry.principal); >+ r->server->principal); > else > _krb5_principal2principalname(&rep->ticket.sname, > r->server_princ); >@@ -2540,16 +2460,16 @@ _kdc_as_rep(astgs_request_t r) > #undef CNT > > r->et.flags.initial = 1; >- if(r->client->entry.flags.forwardable && r->server->entry.flags.forwardable) >+ if(r->client->flags.forwardable && r->server->flags.forwardable) > r->et.flags.forwardable = f.forwardable; >- if(r->client->entry.flags.proxiable && r->server->entry.flags.proxiable) >+ if(r->client->flags.proxiable && r->server->flags.proxiable) > r->et.flags.proxiable = f.proxiable; > else if (f.proxiable) { > _kdc_set_e_text(r, "Ticket may not be proxiable"); > ret = KRB5KDC_ERR_POLICY; > goto out; > } >- if(r->client->entry.flags.postdate && r->server->entry.flags.postdate) >+ if(r->client->flags.postdate && r->server->flags.postdate) > r->et.flags.may_postdate = f.allow_postdate; > else if (f.allow_postdate){ > _kdc_set_e_text(r, "Ticket may not be postdate"); >@@ -2558,12 +2478,12 @@ _kdc_as_rep(astgs_request_t r) > } > > if (b->addresses) >- _kdc_audit_addaddrs((kdc_request_t)r, b->addresses, "reqaddrs"); >+ kdc_audit_addaddrs((kdc_request_t)r, b->addresses, "reqaddrs"); > > /* check for valid set of addresses */ > if (!_kdc_check_addresses(r, b->addresses, r->addr)) { > if (r->config->warn_ticket_addresses) { >- _kdc_audit_addkv((kdc_request_t)r, 0, "wrongaddr", "yes"); >+ kdc_audit_setkv_bool((kdc_request_t)r, "wrongaddr", TRUE); > } else { > _kdc_set_e_text(r, "Request from wrong address"); > ret = KRB5KRB_AP_ERR_BADADDR; >@@ -2596,24 +2516,26 @@ _kdc_as_rep(astgs_request_t r) > /* be careful not overflowing */ > > /* >- * Pre-auth can override r->client->entry.max_life if configured. >+ * Pre-auth can override r->client->max_life if configured. > * > * See pre-auth methods, specifically PKINIT, which can get or derive > * this from the client's certificate. > */ > if (r->pa_max_life > 0) >- t = start + min(t - start, r->pa_max_life); >- else if (r->client->entry.max_life) >- t = start + min(t - start, *r->client->entry.max_life); >+ t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_max_life)); >+ else if (r->client->max_life && *r->client->max_life) >+ t = rk_time_add(start, min(rk_time_sub(t, start), >+ *r->client->max_life)); > >- if (r->server->entry.max_life) >- t = start + min(t - start, *r->server->entry.max_life); >+ if (r->server->max_life && *r->server->max_life) >+ t = rk_time_add(start, min(rk_time_sub(t, start), >+ *r->server->max_life)); > > /* Pre-auth can bound endtime as well */ > if (r->pa_endtime > 0) >- t = start + min(t - start, r->pa_endtime); >+ t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_endtime)); > #if 0 >- t = min(t, start + realm->max_life); >+ t = min(t, rk_time_add(start, realm->max_life)); > #endif > r->et.endtime = t; > if(f.renewable_ok && r->et.endtime < *b->till){ >@@ -2629,12 +2551,14 @@ _kdc_as_rep(astgs_request_t r) > t = *b->rtime; > if(t == 0) > t = MAX_TIME; >- if(r->client->entry.max_renew) >- t = start + min(t - start, *r->client->entry.max_renew); >- if(r->server->entry.max_renew) >- t = start + min(t - start, *r->server->entry.max_renew); >+ if(r->client->max_renew && *r->client->max_renew) >+ t = rk_time_add(start, min(rk_time_sub(t, start), >+ *r->client->max_renew)); >+ if(r->server->max_renew && *r->server->max_renew) >+ t = rk_time_add(start, min(rk_time_sub(t, start), >+ *r->server->max_renew)); > #if 0 >- t = min(t, start + realm->max_renew); >+ t = min(t, rk_time_add(start, realm->max_renew)); > #endif > ALLOC(r->et.renew_till); > *r->et.renew_till = t; >@@ -2665,16 +2589,16 @@ _kdc_as_rep(astgs_request_t r) > goto out; > } > r->ek.last_req.len = 0; >- if (r->client->entry.pw_end >+ if (r->client->pw_end > && (config->kdc_warn_pwexpire == 0 >- || kdc_time + config->kdc_warn_pwexpire >= *r->client->entry.pw_end)) { >+ || kdc_time + config->kdc_warn_pwexpire >= *r->client->pw_end)) { > r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_PW_EXPTIME; >- r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.pw_end; >+ r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->pw_end; > ++r->ek.last_req.len; > } >- if (r->client->entry.valid_end) { >+ if (r->client->valid_end) { > r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_ACCT_EXPTIME; >- r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.valid_end; >+ r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->valid_end; > ++r->ek.last_req.len; > } > if (r->ek.last_req.len == 0) { >@@ -2683,16 +2607,16 @@ _kdc_as_rep(astgs_request_t r) > ++r->ek.last_req.len; > } > r->ek.nonce = b->nonce; >- if (r->client->entry.valid_end || r->client->entry.pw_end) { >+ if (r->client->valid_end || r->client->pw_end) { > ALLOC(r->ek.key_expiration); >- if (r->client->entry.valid_end) { >- if (r->client->entry.pw_end) >- *r->ek.key_expiration = min(*r->client->entry.valid_end, >- *r->client->entry.pw_end); >+ if (r->client->valid_end) { >+ if (r->client->pw_end) >+ *r->ek.key_expiration = min(*r->client->valid_end, >+ *r->client->pw_end); > else >- *r->ek.key_expiration = *r->client->entry.valid_end; >+ *r->ek.key_expiration = *r->client->valid_end; > } else >- *r->ek.key_expiration = *r->client->entry.pw_end; >+ *r->ek.key_expiration = *r->client->pw_end; > } else > r->ek.key_expiration = NULL; > r->ek.flags = r->et.flags; >@@ -2746,7 +2670,7 @@ _kdc_as_rep(astgs_request_t r) > generate_pac(r, skey, krbtgt_key, is_tgs); > } > >- if (r->client->entry.flags.synthetic) { >+ if (r->client->flags.synthetic) { > ret = add_synthetic_princ_ad(r); > if (ret) > goto out; >@@ -2803,8 +2727,8 @@ _kdc_as_rep(astgs_request_t r) > > ret = _kdc_encode_reply(r->context, config, > r, req->req_body.nonce, setype, >- r->server->entry.kvno, &skey->key, >- pa_used_flag_isset(r, PA_REPLACE_REPLY_KEY) ? 0 : r->client->entry.kvno, >+ r->server->kvno, &skey->key, >+ pa_used_flag_isset(r, PA_REPLACE_REPLY_KEY) ? 0 : r->client->kvno, > 0, r->reply); > if (ret) > goto out; >@@ -2819,6 +2743,9 @@ _kdc_as_rep(astgs_request_t r) > } > > out: >+ r->error_code = ret; >+ _kdc_audit_request(r); >+ > /* > * In case of a non proxy error, build an error message. > */ >@@ -2827,7 +2754,7 @@ out: > r->rep.padata, > r->armor_crypto, > &req->req_body, >- r->ret = ret, >+ r->error_code, > r->client_princ, > r->server_princ, > NULL, NULL, >@@ -2850,11 +2777,11 @@ out: > r->server_princ = NULL; > } > if (r->client) >- _kdc_free_ent(r->context, r->client); >+ _kdc_free_ent(r->context, r->clientdb, r->client); > if (r->server) >- _kdc_free_ent(r->context, r->server); >- if (krbtgt) >- _kdc_free_ent(r->context, krbtgt); >+ _kdc_free_ent(r->context, r->serverdb, r->server); >+ if (r->krbtgt) >+ _kdc_free_ent(r->context, r->krbtgtdb, r->krbtgt); > if (r->armor_crypto) { > krb5_crypto_destroy(r->context, r->armor_crypto); > r->armor_crypto = NULL; >@@ -2862,7 +2789,7 @@ out: > if (r->armor_ticket) > krb5_free_ticket(r->context, r->armor_ticket); > if (r->armor_server) >- _kdc_free_ent(r->context, r->armor_server); >+ _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server); > krb5_free_keyblock_contents(r->context, &r->reply_key); > krb5_free_keyblock_contents(r->context, &r->session_key); > krb5_free_keyblock_contents(r->context, &r->strengthen_key); >diff --git a/third_party/heimdal/kdc/krb5tgs.c b/third_party/heimdal/kdc/krb5tgs.c >index c9878dd6af52..39d42106e01e 100644 >--- a/third_party/heimdal/kdc/krb5tgs.c >+++ b/third_party/heimdal/kdc/krb5tgs.c >@@ -80,10 +80,10 @@ _kdc_check_pac(krb5_context context, > krb5_kdc_configuration *config, > const krb5_principal client_principal, > const krb5_principal delegated_proxy_principal, >- hdb_entry_ex *client, >- hdb_entry_ex *server, >- hdb_entry_ex *krbtgt, >- hdb_entry_ex *ticket_server, >+ hdb_entry *client, >+ hdb_entry *server, >+ hdb_entry *krbtgt, >+ hdb_entry *ticket_server, > const EncryptionKey *server_check_key, > const EncryptionKey *krbtgt_check_key, > EncTicketPart *tkt, >@@ -139,7 +139,8 @@ _kdc_check_pac(krb5_context context, > } > > /* Verify the KDC signatures. */ >- ret = _kdc_pac_verify(context, client_principal, delegated_proxy_principal, >+ ret = _kdc_pac_verify(context, config, >+ client_principal, delegated_proxy_principal, > client, server, krbtgt, &pac); > if (ret == 0) { > if (pac == NULL) { >@@ -151,8 +152,8 @@ _kdc_check_pac(krb5_context context, > * We can't verify the KDC signatures if the ticket was issued by > * another realm's KDC. > */ >- if (krb5_realm_compare(context, server->entry.principal, >- ticket_server->entry.principal)) { >+ if (krb5_realm_compare(context, server->principal, >+ ticket_server->principal)) { > ret = krb5_pac_verify(context, pac, 0, NULL, NULL, > krbtgt_check_key); > if (ret) { >@@ -173,7 +174,7 @@ _kdc_check_pac(krb5_context context, > > *kdc_issued = signedticket || > krb5_principal_is_krbtgt(context, >- ticket_server->entry.principal); >+ ticket_server->principal); > *ppac = pac; > > return 0; >@@ -210,35 +211,35 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b, > > if(f.validate){ > if (!tgt->flags.invalid || tgt->starttime == NULL) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Bad request to validate ticket"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Bad request to validate ticket"); > return KRB5KDC_ERR_BADOPTION; > } > if(*tgt->starttime > kdc_time){ >- _kdc_audit_addreason((kdc_request_t)r, >- "Early request to validate ticket"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Early request to validate ticket"); > return KRB5KRB_AP_ERR_TKT_NYV; > } > /* XXX tkt = tgt */ > et->flags.invalid = 0; > } else if (tgt->flags.invalid) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Ticket-granting ticket has INVALID flag set"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Ticket-granting ticket has INVALID flag set"); > return KRB5KRB_AP_ERR_TKT_INVALID; > } > > if(f.forwardable){ > if (!tgt->flags.forwardable) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Bad request for forwardable ticket"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Bad request for forwardable ticket"); > return KRB5KDC_ERR_BADOPTION; > } > et->flags.forwardable = 1; > } > if(f.forwarded){ > if (!tgt->flags.forwardable) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Request to forward non-forwardable ticket"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Request to forward non-forwardable ticket"); > return KRB5KDC_ERR_BADOPTION; > } > et->flags.forwarded = 1; >@@ -249,16 +250,16 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b, > > if(f.proxiable){ > if (!tgt->flags.proxiable) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Bad request for proxiable ticket"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Bad request for proxiable ticket"); > return KRB5KDC_ERR_BADOPTION; > } > et->flags.proxiable = 1; > } > if(f.proxy){ > if (!tgt->flags.proxiable) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Request to proxy non-proxiable ticket"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Request to proxy non-proxiable ticket"); > return KRB5KDC_ERR_BADOPTION; > } > et->flags.proxy = 1; >@@ -269,16 +270,16 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b, > > if(f.allow_postdate){ > if (!tgt->flags.may_postdate) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Bad request for post-datable ticket"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Bad request for post-datable ticket"); > return KRB5KDC_ERR_BADOPTION; > } > et->flags.may_postdate = 1; > } > if(f.postdated){ > if (!tgt->flags.may_postdate) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Bad request for postdated ticket"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Bad request for postdated ticket"); > return KRB5KDC_ERR_BADOPTION; > } > if(b->from) >@@ -286,15 +287,15 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b, > et->flags.postdated = 1; > et->flags.invalid = 1; > } else if (b->from && *b->from > kdc_time + r->context->max_skew) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Ticket cannot be postdated"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Ticket cannot be postdated"); > return KRB5KDC_ERR_CANNOT_POSTDATE; > } > > if(f.renewable){ > if (!tgt->flags.renewable || tgt->renew_till == NULL) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Bad request for renewable ticket"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Bad request for renewable ticket"); > return KRB5KDC_ERR_BADOPTION; > } > et->flags.renewable = 1; >@@ -305,8 +306,8 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b, > if(f.renew){ > time_t old_life; > if (!tgt->flags.renewable || tgt->renew_till == NULL) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Request to renew non-renewable ticket"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Request to renew non-renewable ticket"); > return KRB5KDC_ERR_BADOPTION; > } > old_life = tgt->endtime; >@@ -325,8 +326,8 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b, > */ > if (tgt->flags.anonymous && > !_kdc_is_anonymous(r->context, tgt_name)) { >- _kdc_audit_addreason((kdc_request_t)r, >- "Anonymous ticket flag set without " >+ kdc_audit_addreason((kdc_request_t)r, >+ "Anonymous ticket flag set without " > "anonymous principal"); > return KRB5KDC_ERR_BADOPTION; > } >@@ -342,63 +343,6 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b, > return 0; > } > >-/* >- * Determine if constrained delegation is allowed from this client to this server >- */ >- >-static krb5_error_code >-check_constrained_delegation(krb5_context context, >- krb5_kdc_configuration *config, >- HDB *clientdb, >- hdb_entry_ex *client, >- hdb_entry_ex *server, >- krb5_const_principal target) >-{ >- const HDB_Ext_Constrained_delegation_acl *acl; >- krb5_error_code ret; >- size_t i; >- >- /* >- * constrained_delegation (S4U2Proxy) only works within >- * the same realm. We use the already canonicalized version >- * of the principals here, while "target" is the principal >- * provided by the client. >- */ >- if(!krb5_realm_compare(context, client->entry.principal, server->entry.principal)) { >- ret = KRB5KDC_ERR_BADOPTION; >- kdc_log(context, config, 4, >- "Bad request for constrained delegation"); >- return ret; >- } >- >- if (clientdb->hdb_check_constrained_delegation) { >- ret = clientdb->hdb_check_constrained_delegation(context, clientdb, client, target); >- if (ret == 0) >- return 0; >- } else { >- /* if client delegates to itself, that ok */ >- if (krb5_principal_compare(context, client->entry.principal, server->entry.principal) == TRUE) >- return 0; >- >- ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl); >- if (ret) { >- krb5_clear_error_message(context); >- return ret; >- } >- >- if (acl) { >- for (i = 0; i < acl->len; i++) { >- if (krb5_principal_compare(context, target, &acl->val[i]) == TRUE) >- return 0; >- } >- } >- ret = KRB5KDC_ERR_BADOPTION; >- } >- kdc_log(context, config, 4, >- "Bad request for constrained delegation"); >- return ret; >-} >- > /* > * Determine if s4u2self is allowed from this client to this server > * >@@ -412,13 +356,13 @@ check_constrained_delegation(krb5_context context, > * alias of client, then it's safe. > */ > >-static krb5_error_code >-check_client_matches_target_service(krb5_context context, >- krb5_kdc_configuration *config, >- HDB *clientdb, >- hdb_entry_ex *client, >- hdb_entry_ex *target_server, >- krb5_const_principal target_server_principal) >+krb5_error_code >+_kdc_check_client_matches_target_service(krb5_context context, >+ krb5_kdc_configuration *config, >+ HDB *clientdb, >+ hdb_entry *client, >+ hdb_entry *target_server, >+ krb5_const_principal target_server_principal) > { > krb5_error_code ret; > >@@ -435,7 +379,7 @@ check_client_matches_target_service(krb5_context context, > if (ret == 0) > return 0; > } else if (krb5_principal_compare(context, >- client->entry.principal, >+ client->principal, > target_server_principal) == TRUE) { > /* if client does a s4u2self to itself, and there is no plugin, that is ok */ > return 0; >@@ -587,17 +531,12 @@ fix_transited_encoding(krb5_context context, > > static krb5_error_code > tgs_make_reply(astgs_request_t r, >- krb5_principal tgt_name, > const EncTicketPart *tgt, > const EncryptionKey *serverkey, > const EncryptionKey *krbtgtkey, > const krb5_keyblock *sessionkey, > krb5_kvno kvno, > AuthorizationData *auth_data, >- hdb_entry_ex *server, >- krb5_principal server_principal, >- hdb_entry_ex *client, >- krb5_principal client_principal, > const char *tgt_realm, > uint16_t rodc_id, > krb5_boolean add_ticket_sig) >@@ -611,6 +550,8 @@ tgs_make_reply(astgs_request_t r, > krb5_error_code ret; > int is_weak = 0; > >+ heim_assert(r->client_princ != NULL, "invalid client name passed to tgs_make_reply"); >+ > rep->pvno = 5; > rep->msg_type = krb_tgs_rep; > >@@ -620,7 +561,7 @@ tgs_make_reply(astgs_request_t r, > ALLOC(et->starttime); > *et->starttime = kdc_time; > >- ret = check_tgs_flags(r, b, tgt_name, tgt, et); >+ ret = check_tgs_flags(r, b, r->client_princ, tgt, et); > if(ret) > goto out; > >@@ -646,24 +587,39 @@ tgs_make_reply(astgs_request_t r, > ret = fix_transited_encoding(r->context, r->config, > !f.disable_transited_check || > GLOBAL_FORCE_TRANSITED_CHECK || >- PRINCIPAL_FORCE_TRANSITED_CHECK(server) || >+ PRINCIPAL_FORCE_TRANSITED_CHECK(r->server) || > !((GLOBAL_ALLOW_PER_PRINCIPAL && >- PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) || >+ PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(r->server)) || > GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK), > &tgt->transited, et, >- krb5_principal_get_realm(r->context, client_principal), >- krb5_principal_get_realm(r->context, server->entry.principal), >+ krb5_principal_get_realm(r->context, r->client_princ), >+ krb5_principal_get_realm(r->context, r->server->principal), > tgt_realm); >- if(ret) >- goto out; > >- ret = copy_Realm(&server_principal->realm, &rep->ticket.realm); >- if (ret) >- goto out; >- _krb5_principal2principalname(&rep->ticket.sname, server_principal); >- ret = copy_Realm(&tgt_name->realm, &rep->crealm); >+ { >+ /* >+ * RFC 6806 notes that names MUST NOT be changed in the response to a >+ * TGS request. Hence we ignore the setting of the canonicalize KDC >+ * option. However, for legacy interoperability we do allow the backend >+ * to override this by setting the force-canonicalize HDB flag in the >+ * server entry. >+ */ >+ krb5_const_principal rsp; >+ >+ if (r->server->flags.force_canonicalize) >+ rsp = r->server->principal; >+ else >+ rsp = r->server_princ; >+ if (ret == 0) >+ ret = copy_Realm(&rsp->realm, &rep->ticket.realm); >+ if (ret == 0) >+ ret = _krb5_principal2principalname(&rep->ticket.sname, rsp); >+ } >+ >+ if (ret == 0) >+ ret = copy_Realm(&r->client_princ->realm, &rep->crealm); > if (ret) >- goto out; >+ goto out; > > /* > * RFC 8062 states "if the ticket in the TGS request is an anonymous >@@ -674,7 +630,7 @@ tgs_make_reply(astgs_request_t r, > if (et->flags.anonymous && !tgt->flags.anonymous) > _kdc_make_anonymous_principalname(&rep->cname); > else >- ret = copy_PrincipalName(&tgt_name->name, &rep->cname); >+ ret = copy_PrincipalName(&r->client_princ->name, &rep->cname); > if (ret) > goto out; > rep->ticket.tkt_vno = 5; >@@ -684,10 +640,10 @@ tgs_make_reply(astgs_request_t r, > { > time_t life; > life = et->endtime - *et->starttime; >- if(client && client->entry.max_life) >- life = min(life, *client->entry.max_life); >- if(server->entry.max_life) >- life = min(life, *server->entry.max_life); >+ if(r->client && r->client->max_life) >+ life = min(life, *r->client->max_life); >+ if(r->server->max_life) >+ life = min(life, *r->server->max_life); > et->endtime = *et->starttime + life; > } > if(f.renewable_ok && tgt->flags.renewable && >@@ -701,10 +657,10 @@ tgs_make_reply(astgs_request_t r, > if(et->renew_till){ > time_t renew; > renew = *et->renew_till - *et->starttime; >- if(client && client->entry.max_renew) >- renew = min(renew, *client->entry.max_renew); >- if(server->entry.max_renew) >- renew = min(renew, *server->entry.max_renew); >+ if(r->client && r->client->max_renew) >+ renew = min(renew, *r->client->max_renew); >+ if(r->server->max_renew) >+ renew = min(renew, *r->server->max_renew); > *et->renew_till = *et->starttime + renew; > } > >@@ -728,12 +684,12 @@ tgs_make_reply(astgs_request_t r, > > et->flags.pre_authent = tgt->flags.pre_authent; > et->flags.hw_authent = tgt->flags.hw_authent; >- et->flags.ok_as_delegate = server->entry.flags.ok_as_delegate; >+ et->flags.ok_as_delegate = r->server->flags.ok_as_delegate; > > /* See MS-KILE 3.3.5.1 */ >- if (!server->entry.flags.forwardable) >+ if (!r->server->flags.forwardable) > et->flags.forwardable = 0; >- if (!server->entry.flags.proxiable) >+ if (!r->server->flags.proxiable) > et->flags.proxiable = 0; > > if (auth_data) { >@@ -785,18 +741,18 @@ tgs_make_reply(astgs_request_t r, > et->endtime, et->renew_till); > > if (krb5_enctype_valid(r->context, serverkey->keytype) != 0 >- && _kdc_is_weak_exception(server->entry.principal, serverkey->keytype)) >+ && _kdc_is_weak_exception(r->server->principal, serverkey->keytype)) > { > krb5_enctype_enable(r->context, serverkey->keytype); > is_weak = 1; > } > >- if (r->client_princ) { >+ if (r->canon_client_princ) { > char *cpn; > >- krb5_unparse_name(r->context, r->client_princ, &cpn); >- _kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s", >- cpn ? cpn : "<unknown>"); >+ (void) krb5_unparse_name(r->context, r->canon_client_princ, &cpn); >+ kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s", >+ cpn ? cpn : "<unknown>"); > krb5_xfree(cpn); > } > >@@ -807,8 +763,8 @@ tgs_make_reply(astgs_request_t r, > * is implementation dependent. > */ > if (r->pac && !et->flags.anonymous) { >- _kdc_audit_addkv((kdc_request_t)r, 0, "pac_attributes", "%lx", >- (long)r->pac_attributes); >+ kdc_audit_setkv_number((kdc_request_t)r, "pac_attributes", >+ r->pac_attributes); > > /* > * PACs are included when issuing TGTs, if there is no PAC_ATTRIBUTES >@@ -817,10 +773,10 @@ tgs_make_reply(astgs_request_t r, > */ > if (_kdc_include_pac_p(r)) { > krb5_boolean is_tgs = >- krb5_principal_is_krbtgt(r->context, server->entry.principal); >+ krb5_principal_is_krbtgt(r->context, r->server->principal); > >- ret = _krb5_kdc_pac_sign_ticket(r->context, r->pac, tgt_name, serverkey, >- krbtgtkey, rodc_id, NULL, r->client_princ, >+ ret = _krb5_kdc_pac_sign_ticket(r->context, r->pac, r->client_princ, serverkey, >+ krbtgtkey, rodc_id, NULL, r->canon_client_princ, > add_ticket_sig, et, > is_tgs ? &r->pac_attributes : NULL); > if (ret) >@@ -865,7 +821,12 @@ tgs_check_authenticator(krb5_context context, > krb5_error_code ret; > krb5_crypto crypto; > >- krb5_auth_con_getauthenticator(context, ac, &auth); >+ ret = krb5_auth_con_getauthenticator(context, ac, &auth); >+ if (ret) { >+ kdc_log(context, config, 2, >+ "Out of memory checking PA-TGS Authenticator"); >+ goto out; >+ } > if(auth->cksum == NULL){ > kdc_log(context, config, 4, "No authenticator in request"); > ret = KRB5KRB_AP_ERR_INAPP_CKSUM; >@@ -922,23 +883,7 @@ need_referral(krb5_context context, krb5_kdc_configuration *config, > > if (server->name.name_string.len == 1) > name = server->name.name_string.val[0]; >- else if (server->name.name_string.len == 3) { >- /* >- This is used to give referrals for the >- E3514235-4B06-11D1-AB04-00C04FC2DCD2/NTDSGUID/DNSDOMAIN >- SPN form, which is used for inter-domain communication in AD >- */ >- name = server->name.name_string.val[2]; >- kdc_log(context, config, 4, "Giving 3 part referral for %s", name); >- *realms = malloc(sizeof(char *)*2); >- if (*realms == NULL) { >- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); >- return FALSE; >- } >- (*realms)[0] = strdup(name); >- (*realms)[1] = NULL; >- return TRUE; >- } else if (server->name.name_string.len > 1) >+ else if (server->name.name_string.len > 1) > name = server->name.name_string.val[1]; > else > return FALSE; >@@ -978,9 +923,7 @@ validate_fast_ad(astgs_request_t r, krb5_authdata *auth_data) > static krb5_error_code > tgs_parse_request(astgs_request_t r, > const PA_DATA *tgs_req, >- hdb_entry_ex **krbtgt, > krb5_enctype *krbtgt_etype, >- krb5_ticket **ticket, > const char *from, > const struct sockaddr *from_addr, > time_t **csec, >@@ -1032,7 +975,7 @@ tgs_parse_request(astgs_request_t r, > > krbtgt_kvno = ap_req.ticket.enc_part.kvno ? *ap_req.ticket.enc_part.kvno : 0; > ret = _kdc_db_fetch(r->context, config, princ, HDB_F_GET_KRBTGT, >- &krbtgt_kvno, NULL, krbtgt); >+ &krbtgt_kvno, &r->krbtgtdb, &r->krbtgt); > > if (ret == HDB_ERR_NOT_FOUND_HERE) { > /* XXX Factor out this unparsing of the same princ all over */ >@@ -1090,12 +1033,12 @@ tgs_parse_request(astgs_request_t r, > goto out; > } > >- krbtgt_kvno_try = krbtgt_kvno ? krbtgt_kvno : (*krbtgt)->entry.kvno; >+ krbtgt_kvno_try = krbtgt_kvno ? krbtgt_kvno : r->krbtgt->kvno; > *krbtgt_etype = ap_req.ticket.enc_part.etype; > > next_kvno: >- krbtgt_keys = hdb_kvno2keys(r->context, &(*krbtgt)->entry, krbtgt_kvno_try); >- ret = hdb_enctype2key(r->context, &(*krbtgt)->entry, krbtgt_keys, >+ krbtgt_keys = hdb_kvno2keys(r->context, r->krbtgt, krbtgt_kvno_try); >+ ret = hdb_enctype2key(r->context, r->krbtgt, krbtgt_keys, > ap_req.ticket.enc_part.etype, &tkey); > if (ret && krbtgt_kvno == 0 && kvno_search_tries > 0) { > kvno_search_tries--; >@@ -1129,13 +1072,13 @@ next_kvno: > &tkey->key, > verify_ap_req_flags, > &ap_req_options, >- ticket, >+ &r->ticket, > KRB5_KU_TGS_REQ_AUTH); >- if (*ticket && (*ticket)->ticket.caddr) >- _kdc_audit_addaddrs((kdc_request_t)r, (*ticket)->ticket.caddr, "tixaddrs"); >+ if (r->ticket && r->ticket->ticket.caddr) >+ kdc_audit_addaddrs((kdc_request_t)r, r->ticket->ticket.caddr, "tixaddrs"); > if (r->config->warn_ticket_addresses && ret == KRB5KRB_AP_ERR_BADADDR && >- *ticket != NULL) { >- _kdc_audit_addkv((kdc_request_t)r, 0, "wrongaddr", "yes"); >+ r->ticket != NULL) { >+ kdc_audit_setkv_bool((kdc_request_t)r, "wrongaddr", TRUE); > ret = 0; > } > if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY && kvno_search_tries > 0) { >@@ -1181,8 +1124,7 @@ next_kvno: > } > } > >- ret = tgs_check_authenticator(r->context, config, ac, b, >- &(*ticket)->ticket.key); >+ ret = tgs_check_authenticator(r->context, config, ac, b, &r->ticket->ticket.key); > if (ret) { > krb5_auth_con_free(r->context, ac); > goto out; >@@ -1267,7 +1209,7 @@ next_kvno: > } > } > >- ret = validate_fast_ad(r, (*ticket)->ticket.authorization_data); >+ ret = validate_fast_ad(r, r->ticket->ticket.authorization_data); > if (ret) > goto out; > >@@ -1276,7 +1218,7 @@ next_kvno: > * Check for FAST request > */ > >- ret = _kdc_fast_unwrap_request(r, *ticket, ac); >+ ret = _kdc_fast_unwrap_request(r, r->ticket, ac); > if (ret) > goto out; > >@@ -1376,10 +1318,10 @@ _kdc_db_fetch_client(krb5_context context, > const char *cpn, > const char *krbtgt_realm, > HDB **clientdb, >- hdb_entry_ex **client_out) >+ hdb_entry **client_out) > { > krb5_error_code ret; >- hdb_entry_ex *client = NULL; >+ hdb_entry *client = NULL; > > *client_out = NULL; > >@@ -1408,9 +1350,9 @@ _kdc_db_fetch_client(krb5_context context, > msg = krb5_get_error_message(context, ret); > kdc_log(context, config, 4, "Client not found in database: %s", msg); > krb5_free_error_message(context, msg); >- } else if (client->entry.flags.invalid || !client->entry.flags.client) { >+ } else if (client->flags.invalid || !client->flags.client) { > kdc_log(context, config, 4, "Client has invalid bit set"); >- _kdc_free_ent(context, client); >+ _kdc_free_ent(context, *clientdb, client); > return KRB5KDC_ERR_POLICY; > } > >@@ -1421,29 +1363,25 @@ _kdc_db_fetch_client(krb5_context context, > > static krb5_error_code > tgs_build_reply(astgs_request_t priv, >- hdb_entry_ex *krbtgt, > krb5_enctype krbtgt_etype, >- krb5_ticket *ticket, > AuthorizationData **auth_data, > const struct sockaddr *from_addr) > { > krb5_context context = priv->context; > krb5_kdc_configuration *config = priv->config; >- KDC_REQ *req = &priv->req; > KDC_REQ_BODY *b = &priv->req.req_body; > const char *from = priv->from; > krb5_error_code ret, ret2; >- krb5_principal cp = NULL, sp = NULL, rsp = NULL, tp = NULL, dp = NULL; > krb5_principal krbtgt_out_principal = NULL; > krb5_principal user2user_princ = NULL; >- char *spn = NULL, *cpn = NULL, *tpn = NULL, *dpn = NULL, *krbtgt_out_n = NULL; >+ char *spn = NULL, *cpn = NULL, *krbtgt_out_n = NULL; > char *user2user_name = NULL; >- hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL; >- hdb_entry_ex *user2user_krbtgt = NULL; >- HDB *clientdb, *s4u2self_impersonated_clientdb; >+ HDB *user2user_krbtgtdb; >+ hdb_entry *user2user_krbtgt = NULL; >+ HDB *clientdb; > HDB *serverdb = NULL; > krb5_realm ref_realm = NULL; >- EncTicketPart *tgt = &ticket->ticket; >+ EncTicketPart *tgt = &priv->ticket->ticket; > const EncryptionKey *ekey; > krb5_keyblock sessionkey; > krb5_kvno kvno; >@@ -1451,13 +1389,14 @@ tgs_build_reply(astgs_request_t priv, > uint16_t rodc_id; > krb5_boolean add_ticket_sig = FALSE; > const char *tgt_realm = /* Realm of TGT issuer */ >- krb5_principal_get_realm(context, krbtgt->entry.principal); >+ krb5_principal_get_realm(context, priv->krbtgt->principal); > const char *our_realm = /* Realm of this KDC */ >- krb5_principal_get_comp_string(context, krbtgt->entry.principal, 1); >+ krb5_principal_get_comp_string(context, priv->krbtgt->principal, 1); > char **capath = NULL; > size_t num_capath = 0; > >- hdb_entry_ex *krbtgt_out = NULL; >+ HDB *krbtgt_outdb; >+ hdb_entry *krbtgt_out = NULL; > > PrincipalName *s; > Realm r; >@@ -1491,13 +1430,14 @@ tgs_build_reply(astgs_request_t priv, > goto out; > } > >- _krb5_principalname2krb5_principal(context, &sp, *s, r); >- ret = krb5_unparse_name(context, sp, &priv->sname); >+ _krb5_principalname2krb5_principal(context, &priv->server_princ, *s, r); >+ ret = krb5_unparse_name(context, priv->server_princ, &priv->sname); > if (ret) > goto out; > spn = priv->sname; >- _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm); >- ret = krb5_unparse_name(context, cp, &priv->cname); >+ _krb5_principalname2krb5_principal(context, &priv->client_princ, >+ tgt->cname, tgt->crealm); >+ ret = krb5_unparse_name(context, priv->client_princ, &priv->cname); > if (ret) > goto out; > cpn = priv->cname; >@@ -1517,21 +1457,20 @@ tgs_build_reply(astgs_request_t priv, > */ > > server_lookup: >+ if (priv->server) >+ _kdc_free_ent(context, serverdb, priv->server); > priv->server = NULL; >- if (server) >- _kdc_free_ent(context, server); >- server = NULL; >- ret = _kdc_db_fetch(context, config, sp, >+ ret = _kdc_db_fetch(context, config, priv->server_princ, > HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS | flags, >- NULL, &serverdb, &server); >- priv->server = server; >+ NULL, &serverdb, &priv->server); >+ priv->serverdb = serverdb; > if (ret == HDB_ERR_NOT_FOUND_HERE) { > kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", spn); >- _kdc_audit_addreason((kdc_request_t)priv, "Target not found here"); >+ kdc_audit_addreason((kdc_request_t)priv, "Target not found here"); > goto out; > } else if (ret == HDB_ERR_WRONG_REALM) { > free(ref_realm); >- ref_realm = strdup(server->entry.principal->realm); >+ ref_realm = strdup(priv->server->principal->realm); > if (ref_realm == NULL) { > ret = krb5_enomem(context); > goto out; >@@ -1541,15 +1480,15 @@ server_lookup: > "Returning a referral to realm %s for " > "server %s.", > ref_realm, spn); >- krb5_free_principal(context, sp); >- sp = NULL; >- ret = krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, >+ krb5_free_principal(context, priv->server_princ); >+ priv->server_princ = NULL; >+ ret = krb5_make_principal(context, &priv->server_princ, r, KRB5_TGS_NAME, > ref_realm, NULL); > if (ret) > goto out; > free(priv->sname); > priv->sname = NULL; >- ret = krb5_unparse_name(context, sp, &priv->sname); >+ ret = krb5_unparse_name(context, priv->server_princ, &priv->sname); > if (ret) > goto out; > spn = priv->sname; >@@ -1560,17 +1499,26 @@ server_lookup: > Realm req_rlm; > krb5_realm *realms; > >- if (!config->autodetect_referrals) { >- /* noop */ >- } else if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) { >+ priv->error_code = ret; /* advise policy plugin of failure reason */ >+ ret2 = _kdc_referral_policy(priv); >+ if (ret2 == 0) { >+ krb5_xfree(priv->sname); >+ priv->sname = NULL; >+ ret = krb5_unparse_name(context, priv->server_princ, &priv->sname); >+ if (ret) >+ goto out; >+ goto server_lookup; >+ } else if (ret2 != KRB5_PLUGIN_NO_HANDLE) { >+ ret = ret2; >+ } else if ((req_rlm = get_krbtgt_realm(&priv->server_princ->name)) != NULL) { > if (capath == NULL) { > /* With referalls, hierarchical capaths are always enabled */ > ret2 = _krb5_find_capath(context, tgt->crealm, our_realm, > req_rlm, TRUE, &capath, &num_capath); > if (ret2) { > ret = ret2; >- _kdc_audit_addreason((kdc_request_t)priv, >- "No trusted path from client realm to ours"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "No trusted path from client realm to ours"); > goto out; > } > } >@@ -1587,31 +1535,31 @@ server_lookup: > goto out; > } > >- krb5_free_principal(context, sp); >- sp = NULL; >- krb5_make_principal(context, &sp, r, >+ krb5_free_principal(context, priv->server_princ); >+ priv->server_princ = NULL; >+ krb5_make_principal(context, &priv->server_princ, r, > KRB5_TGS_NAME, ref_realm, NULL); > free(priv->sname); > priv->sname = NULL; >- ret = krb5_unparse_name(context, sp, &priv->sname); >+ ret = krb5_unparse_name(context, priv->server_princ, &priv->sname); > if (ret) > goto out; > spn = priv->sname; > goto server_lookup; > } >- } else if (need_referral(context, config, &b->kdc_options, sp, &realms)) { >- if (strcmp(realms[0], sp->realm) != 0) { >+ } else if (need_referral(context, config, &b->kdc_options, priv->server_princ, &realms)) { >+ if (strcmp(realms[0], priv->server_princ->realm) != 0) { > kdc_log(context, config, 4, > "Returning a referral to realm %s for " > "server %s that was not found", > realms[0], spn); >- krb5_free_principal(context, sp); >- sp = NULL; >- krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, >+ krb5_free_principal(context, priv->server_princ); >+ priv->server_princ = NULL; >+ krb5_make_principal(context, &priv->server_princ, r, KRB5_TGS_NAME, > realms[0], NULL); > free(priv->sname); > priv->sname = NULL; >- ret = krb5_unparse_name(context, sp, &priv->sname); >+ ret = krb5_unparse_name(context, priv->server_princ, &priv->sname); > if (ret) { > krb5_free_host_realm(context, realms); > goto out; >@@ -1632,23 +1580,11 @@ server_lookup: > krb5_free_error_message(context, msg); > if (ret == HDB_ERR_NOENTRY) > ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; >- _kdc_audit_addreason((kdc_request_t)priv, >- "Service principal unknown"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "Service principal unknown"); > goto out; > } > >- /* >- * RFC 6806 notes that names MUST NOT be changed in the response to >- * a TGS request. Hence we ignore the setting of the canonicalize >- * KDC option. However, for legacy interoperability we do allow the >- * backend to override this by setting the force-canonicalize HDB >- * flag in the server entry. >- */ >- if (server->entry.flags.force_canonicalize) >- rsp = server->entry.principal; >- else >- rsp = sp; >- > /* > * Now refetch the primary krbtgt, and get the current kvno (the > * sign check may have been on an old kvno, and the server may >@@ -1676,10 +1612,10 @@ server_lookup: > } > > ret = _kdc_db_fetch(context, config, krbtgt_out_principal, >- HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out); >+ HDB_F_GET_KRBTGT, NULL, &krbtgt_outdb, &krbtgt_out); > if (ret) { > char *ktpn = NULL; >- ret = krb5_unparse_name(context, krbtgt->entry.principal, &ktpn); >+ ret = krb5_unparse_name(context, priv->krbtgt->principal, &ktpn); > kdc_log(context, config, 4, > "No such principal %s (needed for authz-data signature keys) " > "while processing TGS-REQ for service %s with krbtg %s", >@@ -1703,24 +1639,26 @@ server_lookup: > krb5uint32 second_kvno = 0; > krb5uint32 *kvno_ptr = NULL; > size_t i; >- hdb_entry_ex *user2user_client = NULL; >+ HDB *user2user_db; >+ hdb_entry *user2user_client = NULL; > krb5_boolean user2user_kdc_issued = FALSE; >+ char *tpn; > > if(b->additional_tickets == NULL || > b->additional_tickets->len == 0){ > ret = KRB5KDC_ERR_BADOPTION; /* ? */ > kdc_log(context, config, 4, > "No second ticket present in user-to-user request"); >- _kdc_audit_addreason((kdc_request_t)priv, >- "No second ticket present in user-to-user request"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "No second ticket present in user-to-user request"); > goto out; > } > t = &b->additional_tickets->val[0]; > if(!get_krbtgt_realm(&t->sname)){ > kdc_log(context, config, 4, > "Additional ticket is not a ticket-granting ticket"); >- _kdc_audit_addreason((kdc_request_t)priv, >- "Additional ticket is not a ticket-granting ticket"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "Additional ticket is not a ticket-granting ticket"); > ret = KRB5KDC_ERR_POLICY; > goto out; > } >@@ -1737,36 +1675,41 @@ server_lookup: > } > ret = _kdc_db_fetch(context, config, p, > HDB_F_GET_KRBTGT, kvno_ptr, >- NULL, &user2user_krbtgt); >+ &user2user_krbtgtdb, &user2user_krbtgt); > krb5_free_principal(context, p); > if(ret){ > if (ret == HDB_ERR_NOENTRY) > ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; >- _kdc_audit_addreason((kdc_request_t)priv, >- "User-to-user service principal (TGS) unknown"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "User-to-user service principal (TGS) unknown"); >+ krb5_xfree(tpn); > goto out; > } >- ret = hdb_enctype2key(context, &user2user_krbtgt->entry, NULL, >+ ret = hdb_enctype2key(context, user2user_krbtgt, NULL, > t->enc_part.etype, &uukey); > if(ret){ > ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ >- _kdc_audit_addreason((kdc_request_t)priv, >- "User-to-user enctype not supported"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "User-to-user enctype not supported"); >+ krb5_xfree(tpn); > goto out; > } > ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0); > if(ret) { >- _kdc_audit_addreason((kdc_request_t)priv, >- "User-to-user TGT decrypt failure"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "User-to-user TGT decrypt failure"); >+ krb5_xfree(tpn); > goto out; > } > > ret = _kdc_verify_flags(context, config, &adtkt, tpn); > if (ret) { >- _kdc_audit_addreason((kdc_request_t)priv, >- "User-to-user TGT expired or invalid"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "User-to-user TGT expired or invalid"); >+ krb5_xfree(tpn); > goto out; > } >+ krb5_xfree(tpn); > > /* Fetch the name from the TGT. */ > ret = _krb5_principalname2krb5_principal(context, &user2user_princ, >@@ -1786,7 +1729,7 @@ server_lookup: > */ > ret = _kdc_db_fetch(context, config, user2user_princ, > HDB_F_GET_CLIENT | flags, >- NULL, NULL, &user2user_client); >+ NULL, &user2user_db, &user2user_client); > if (ret == HDB_ERR_NOENTRY) > ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; > if (ret) >@@ -1807,7 +1750,7 @@ server_lookup: > user2user_client, > NULL); > if (ret) { >- _kdc_free_ent(context, user2user_client); >+ _kdc_free_ent(context, user2user_db, user2user_client); > goto out; > } > >@@ -1815,14 +1758,14 @@ server_lookup: > * Also check that the account is the same one specified in the > * request. > */ >- ret = check_client_matches_target_service(context, >- config, >- serverdb, >- server, >- user2user_client, >- user2user_princ); >+ ret = _kdc_check_client_matches_target_service(context, >+ config, >+ serverdb, >+ priv->server, >+ user2user_client, >+ user2user_princ); > if (ret) { >- _kdc_free_ent(context, user2user_client); >+ _kdc_free_ent(context, user2user_db, user2user_client); > goto out; > } > >@@ -1831,7 +1774,7 @@ server_lookup: > user2user_client, user2user_krbtgt, user2user_krbtgt, user2user_krbtgt, > &uukey->key, &priv->ticket_key->key, &adtkt, > &user2user_kdc_issued, &user2user_pac, NULL, NULL); >- _kdc_free_ent(context, user2user_client); >+ _kdc_free_ent(context, user2user_db, user2user_client); > if (ret) { > const char *msg = krb5_get_error_message(context, ret); > kdc_log(context, config, 0, >@@ -1860,8 +1803,8 @@ server_lookup: > "Addition ticket have not matching etypes"); > krb5_clear_error_message(context); > ret = KRB5KDC_ERR_ETYPE_NOSUPP; >- _kdc_audit_addreason((kdc_request_t)priv, >- "No matching enctypes for 2nd ticket"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "No matching enctypes for 2nd ticket"); > goto out; > } > etype = b->etype.val[i]; >@@ -1869,28 +1812,28 @@ server_lookup: > } else { > Key *skey; > >- ret = _kdc_find_etype(priv, krb5_principal_is_krbtgt(context, sp) >+ ret = _kdc_find_etype(priv, krb5_principal_is_krbtgt(context, priv->server_princ) > ? KFE_IS_TGS : 0, > b->etype.val, b->etype.len, &etype, NULL, > NULL); > if(ret) { > kdc_log(context, config, 4, > "Server (%s) has no support for etypes", spn); >- _kdc_audit_addreason((kdc_request_t)priv, >- "Enctype not supported"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "Enctype not supported"); > goto out; > } >- ret = _kdc_get_preferred_key(context, config, server, spn, >+ ret = _kdc_get_preferred_key(context, config, priv->server, spn, > NULL, &skey); > if(ret) { > kdc_log(context, config, 4, > "Server (%s) has no supported etypes", spn); >- _kdc_audit_addreason((kdc_request_t)priv, >- "Enctype not supported"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "Enctype not supported"); > goto out; > } > ekey = &skey->key; >- kvno = server->entry.kvno; >+ kvno = priv->server->kvno; > } > > ret = krb5_generate_random_keyblock(context, etype, &sessionkey); >@@ -1911,17 +1854,17 @@ server_lookup: > * the DB to possibly correct the case of the realm (Samba4 does > * this) before the strcmp() > */ >- if (strcmp(krb5_principal_get_realm(context, server->entry.principal), >- krb5_principal_get_realm(context, krbtgt_out->entry.principal)) != 0) { >+ if (strcmp(krb5_principal_get_realm(context, priv->server->principal), >+ krb5_principal_get_realm(context, krbtgt_out->principal)) != 0) { > char *ktpn; >- ret = krb5_unparse_name(context, krbtgt_out->entry.principal, &ktpn); >+ ret = krb5_unparse_name(context, krbtgt_out->principal, &ktpn); > kdc_log(context, config, 4, > "Request with wrong krbtgt: %s", > (ret == 0) ? ktpn : "<unknown>"); > if(ret == 0) > free(ktpn); > ret = KRB5KRB_AP_ERR_NOT_US; >- _kdc_audit_addreason((kdc_request_t)priv, "Request with wrong TGT"); >+ kdc_audit_addreason((kdc_request_t)priv, "Request with wrong TGT"); > goto out; > } > >@@ -1930,38 +1873,39 @@ server_lookup: > if (ret) { > kdc_log(context, config, 4, > "Failed to find key for krbtgt PAC signature"); >- _kdc_audit_addreason((kdc_request_t)priv, >- "Failed to find key for krbtgt PAC signature"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "Failed to find key for krbtgt PAC signature"); > goto out; > } >- ret = hdb_enctype2key(context, &krbtgt_out->entry, NULL, >+ ret = hdb_enctype2key(context, krbtgt_out, NULL, > tkey_sign->key.keytype, &tkey_sign); > if(ret) { > kdc_log(context, config, 4, > "Failed to find key for krbtgt PAC signature"); >- _kdc_audit_addreason((kdc_request_t)priv, >- "Failed to find key for krbtgt PAC signature"); >+ kdc_audit_addreason((kdc_request_t)priv, >+ "Failed to find key for krbtgt PAC signature"); > goto out; > } > >- if (_kdc_synthetic_princ_used_p(context, ticket)) >+ if (_kdc_synthetic_princ_used_p(context, priv->ticket)) > flags |= HDB_F_SYNTHETIC_OK; > >- ret = _kdc_db_fetch_client(context, config, flags, cp, cpn, our_realm, >- &clientdb, &client); >+ ret = _kdc_db_fetch_client(context, config, flags, priv->client_princ, >+ cpn, our_realm, &clientdb, &priv->client); > if (ret) > goto out; > flags &= ~HDB_F_SYNTHETIC_OK; >- priv->client = client; >- >- heim_assert(priv->client_princ == NULL, "client_princ should be NULL for TGS"); >+ priv->clientdb = clientdb; > >- ret = _kdc_check_pac(context, config, cp, NULL, client, server, krbtgt, krbtgt, >+ ret = _kdc_check_pac(context, config, priv->client_princ, NULL, >+ priv->client, priv->server, >+ priv->krbtgt, priv->krbtgt, > &priv->ticket_key->key, &priv->ticket_key->key, tgt, >- &kdc_issued, &priv->pac, &priv->client_princ, &priv->pac_attributes); >+ &kdc_issued, &priv->pac, &priv->canon_client_princ, >+ &priv->pac_attributes); > if (ret) { > const char *msg = krb5_get_error_message(context, ret); >- _kdc_audit_addreason((kdc_request_t)priv, "PAC check failed"); >+ kdc_audit_addreason((kdc_request_t)priv, "PAC check failed"); > kdc_log(context, config, 4, > "Verify PAC failed for %s (%s) from %s with %s", > spn, cpn, from, msg); >@@ -1973,352 +1917,13 @@ server_lookup: > * Process request > */ > >- /* by default the tgt principal matches the client principal */ >- tp = cp; >- tpn = cpn; >- >- if (client) { >- const PA_DATA *sdata; >- int i = 0; >- >- sdata = _kdc_find_padata(req, &i, KRB5_PADATA_FOR_USER); >- if (sdata) { >- krb5_crypto crypto; >- krb5_data datack; >- PA_S4U2Self self; >- const char *str; >- >- ret = decode_PA_S4U2Self(sdata->padata_value.data, >- sdata->padata_value.length, >- &self, NULL); >- if (ret) { >- _kdc_audit_addreason((kdc_request_t)priv, >- "Failed to decode PA-S4U2Self"); >- kdc_log(context, config, 4, "Failed to decode PA-S4U2Self"); >- goto out; >- } >- >- if (!krb5_checksum_is_keyed(context, self.cksum.cksumtype)) { >- free_PA_S4U2Self(&self); >- _kdc_audit_addreason((kdc_request_t)priv, >- "PA-S4U2Self with unkeyed checksum"); >- kdc_log(context, config, 4, "Reject PA-S4U2Self with unkeyed checksum"); >- ret = KRB5KRB_AP_ERR_INAPP_CKSUM; >- goto out; >- } >- >- ret = _krb5_s4u2self_to_checksumdata(context, &self, &datack); >- if (ret) >- goto out; >- >- ret = krb5_crypto_init(context, &tgt->key, 0, &crypto); >- if (ret) { >- const char *msg = krb5_get_error_message(context, ret); >- free_PA_S4U2Self(&self); >- krb5_data_free(&datack); >- kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg); >- krb5_free_error_message(context, msg); >- goto out; >- } >- >- /* Allow HMAC_MD5 checksum with any key type */ >- if (self.cksum.cksumtype == CKSUMTYPE_HMAC_MD5) { >- struct krb5_crypto_iov iov; >- unsigned char csdata[16]; >- Checksum cs; >- >- cs.checksum.length = sizeof(csdata); >- cs.checksum.data = &csdata; >- >- iov.data.data = datack.data; >- iov.data.length = datack.length; >- iov.flags = KRB5_CRYPTO_TYPE_DATA; >- >- ret = _krb5_HMAC_MD5_checksum(context, NULL, &crypto->key, >- KRB5_KU_OTHER_CKSUM, &iov, 1, >- &cs); >- if (ret == 0 && >- krb5_data_ct_cmp(&cs.checksum, &self.cksum.checksum) != 0) >- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; >- } >- else { >- ret = _kdc_verify_checksum(context, >- crypto, >- KRB5_KU_OTHER_CKSUM, >- &datack, >- &self.cksum); >- } >- krb5_data_free(&datack); >- krb5_crypto_destroy(context, crypto); >- if (ret) { >- const char *msg = krb5_get_error_message(context, ret); >- free_PA_S4U2Self(&self); >- _kdc_audit_addreason((kdc_request_t)priv, >- "S4U2Self checksum failed"); >- kdc_log(context, config, 4, >- "krb5_verify_checksum failed for S4U2Self: %s", msg); >- krb5_free_error_message(context, msg); >- goto out; >- } >- >- ret = _krb5_principalname2krb5_principal(context, >- &tp, >- self.name, >- self.realm); >- free_PA_S4U2Self(&self); >- if (ret) >- goto out; >- >- ret = krb5_unparse_name(context, tp, &tpn); >- if (ret) >- goto out; >- >- /* >- * Note no HDB_F_SYNTHETIC_OK -- impersonating non-existent clients >- * is probably not desirable! >- */ >- ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | flags, >- NULL, &s4u2self_impersonated_clientdb, >- &s4u2self_impersonated_client); >- if (ret) { >- const char *msg; >- >- /* >- * If the client belongs to the same realm as our krbtgt, it >- * should exist in the local database. >- * >- */ >- >- if (ret == HDB_ERR_NOENTRY) >- ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; >- msg = krb5_get_error_message(context, ret); >- _kdc_audit_addreason((kdc_request_t)priv, >- "S4U2Self principal to impersonate not found"); >- kdc_log(context, config, 2, >- "S4U2Self principal to impersonate %s not found in database: %s", >- tpn, msg); >- krb5_free_error_message(context, msg); >- goto out; >- } >- >- /* Ignore require_pwchange and pw_end attributes (as Windows does), >- * since S4U2Self is not password authentication. */ >- s4u2self_impersonated_client->entry.flags.require_pwchange = FALSE; >- free(s4u2self_impersonated_client->entry.pw_end); >- s4u2self_impersonated_client->entry.pw_end = NULL; >- >- ret = kdc_check_flags(priv, FALSE, s4u2self_impersonated_client, priv->server); >- if (ret) >- goto out; /* kdc_check_flags() calls _kdc_audit_addreason() */ >- >- /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */ >- krb5_pac_free(context, priv->pac); >- priv->pac = NULL; >- >- ret = _kdc_pac_generate(context, >- s4u2self_impersonated_client, >- server, >- NULL, >- KRB5_PAC_WAS_GIVEN_IMPLICITLY, >- &priv->pac); >- if (ret) { >- kdc_log(context, config, 4, "PAC generation failed for -- %s", tpn); >- goto out; >- } >- >- /* >- * Check that service doing the impersonating is >- * requesting a ticket to it-self. >- */ >- ret = check_client_matches_target_service(context, >- config, >- clientdb, >- client, >- server, >- sp); >- if (ret) { >- kdc_log(context, config, 4, "S4U2Self: %s is not allowed " >- "to impersonate to service " >- "(tried for user %s to service %s)", >- cpn, tpn, spn); >- goto out; >- } >- >- /* >- * If the service isn't trusted for authentication to >- * delegation or if the impersonate client is disallowed >- * forwardable, remove the forwardable flag. >- */ >- >- if (client->entry.flags.trusted_for_delegation && >- s4u2self_impersonated_client->entry.flags.forwardable) { >- str = "[forwardable]"; >- } else { >- b->kdc_options.forwardable = 0; >- str = ""; >- } >- kdc_log(context, config, 4, "s4u2self %s impersonating %s to " >- "service %s %s", cpn, tpn, spn, str); >- } >- } >- > /* >- * Constrained delegation >+ * Services for User: protocol transition and constrained delegation > */ > >- if (client != NULL >- && b->additional_tickets != NULL >- && b->additional_tickets->len != 0 >- && b->kdc_options.cname_in_addl_tkt >- && b->kdc_options.enc_tkt_in_skey == 0) >- { >- hdb_entry_ex *adclient = NULL; >- krb5_boolean ad_kdc_issued = FALSE; >- Key *clientkey; >- Ticket *t; >- >- /* >- * We require that the service's krbtgt has a PAC. >- */ >- if (priv->pac == NULL) { >- ret = KRB5KDC_ERR_BADOPTION; >- _kdc_audit_addreason((kdc_request_t)priv, "Missing PAC"); >- kdc_log(context, config, 4, >- "Constrained delegation without PAC, %s/%s", >- cpn, spn); >- goto out; >- } >- >- krb5_pac_free(context, priv->pac); >- priv->pac = NULL; >- >- krb5_free_principal(context, priv->client_princ); >- priv->client_princ = NULL; >- >- t = &b->additional_tickets->val[0]; >- >- ret = hdb_enctype2key(context, &client->entry, >- hdb_kvno2keys(context, &client->entry, >- t->enc_part.kvno ? * t->enc_part.kvno : 0), >- t->enc_part.etype, &clientkey); >- if(ret){ >- ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ >- goto out; >- } >- >- ret = krb5_decrypt_ticket(context, t, &clientkey->key, &adtkt, 0); >- if (ret) { >- _kdc_audit_addreason((kdc_request_t)priv, >- "Failed to decrypt constrained delegation ticket"); >- kdc_log(context, config, 4, >- "failed to decrypt ticket for " >- "constrained delegation from %s to %s ", cpn, spn); >- goto out; >- } >- >- ret = _krb5_principalname2krb5_principal(context, >- &tp, >- adtkt.cname, >- adtkt.crealm); >- if (ret) >- goto out; >- >- ret = krb5_unparse_name(context, tp, &tpn); >- if (ret) >- goto out; >- >- _kdc_audit_addkv((kdc_request_t)priv, 0, "impersonatee", "%s", tpn); >- >- ret = _krb5_principalname2krb5_principal(context, >- &dp, >- t->sname, >- t->realm); >- if (ret) >- goto out; >- >- ret = krb5_unparse_name(context, dp, &dpn); >- if (ret) >- goto out; >- >- /* check that ticket is valid */ >- if (adtkt.flags.forwardable == 0) { >- _kdc_audit_addreason((kdc_request_t)priv, >- "Missing forwardable flag on ticket for constrained delegation"); >- kdc_log(context, config, 4, >- "Missing forwardable flag on ticket for " >- "constrained delegation from %s (%s) as %s to %s ", >- cpn, dpn, tpn, spn); >- ret = KRB5KDC_ERR_BADOPTION; >- goto out; >- } >- >- ret = check_constrained_delegation(context, config, clientdb, >- client, server, sp); >- if (ret) { >- _kdc_audit_addreason((kdc_request_t)priv, >- "Constrained delegation not allowed"); >- kdc_log(context, config, 4, >- "constrained delegation from %s (%s) as %s to %s not allowed", >- cpn, dpn, tpn, spn); >- goto out; >- } >- >- ret = _kdc_verify_flags(context, config, &adtkt, tpn); >- if (ret) { >- _kdc_audit_addreason((kdc_request_t)priv, >- "Constrained delegation ticket expired or invalid"); >- goto out; >- } >- >- /* Try lookup the delegated client in DB */ >- ret = _kdc_db_fetch_client(context, config, flags, tp, tpn, our_realm, >- NULL, &adclient); >- if (ret) >- goto out; >- >- if (adclient != NULL) { >- ret = kdc_check_flags(priv, FALSE, adclient, priv->server); >- if (ret) { >- _kdc_free_ent(context, adclient); >- goto out; >- } >- } >- >- /* >- * TODO: pass in t->sname and t->realm and build >- * a S4U_DELEGATION_INFO blob to the PAC. >- */ >- ret = _kdc_check_pac(context, config, tp, dp, adclient, server, krbtgt, client, >- &clientkey->key, &priv->ticket_key->key, &adtkt, >- &ad_kdc_issued, &priv->pac, &priv->client_princ, &priv->pac_attributes); >- if (adclient) >- _kdc_free_ent(context, adclient); >- if (ret) { >- const char *msg = krb5_get_error_message(context, ret); >- _kdc_audit_addreason((kdc_request_t)priv, >- "Constrained delegation ticket PAC check failed"); >- kdc_log(context, config, 4, >- "Verify delegated PAC failed to %s for client" >- "%s (%s) as %s from %s with %s", >- spn, cpn, dpn, tpn, from, msg); >- krb5_free_error_message(context, msg); >- goto out; >- } >- >- if (priv->pac == NULL || !ad_kdc_issued) { >- ret = KRB5KDC_ERR_BADOPTION; >- kdc_log(context, config, 4, >- "Ticket not signed with PAC; service %s failed for " >- "for delegation to %s for client %s (%s) from %s; (%s).", >- spn, tpn, dpn, cpn, from, priv->pac ? "Ticket unsigned" : "No PAC"); >- _kdc_audit_addreason((kdc_request_t)priv, >- "Constrained delegation ticket not signed"); >- goto out; >- } >- >- kdc_log(context, config, 4, "constrained delegation for %s " >- "from %s (%s) to %s", tpn, cpn, dpn, spn); >- } >+ ret = _kdc_validate_services_for_user(priv); >+ if (ret) >+ goto out; > > /* > * Check flags >@@ -2330,9 +1935,9 @@ server_lookup: > > if((b->kdc_options.validate || b->kdc_options.renew) && > !krb5_principal_compare(context, >- krbtgt->entry.principal, >- server->entry.principal)){ >- _kdc_audit_addreason((kdc_request_t)priv, "Inconsistent request"); >+ priv->krbtgt->principal, >+ priv->server->principal)){ >+ kdc_audit_addreason((kdc_request_t)priv, "Inconsistent request"); > kdc_log(context, config, 4, "Inconsistent request."); > ret = KRB5KDC_ERR_SERVER_NOMATCH; > goto out; >@@ -2342,12 +1947,12 @@ server_lookup: > if (!_kdc_check_addresses(priv, tgt->caddr, from_addr)) { > if (config->check_ticket_addresses) { > ret = KRB5KRB_AP_ERR_BADADDR; >- _kdc_audit_addkv((kdc_request_t)priv, 0, "wrongaddr", "yes"); >+ kdc_audit_setkv_bool((kdc_request_t)priv, "wrongaddr", TRUE); > kdc_log(context, config, 4, "Request from wrong address"); >- _kdc_audit_addreason((kdc_request_t)priv, "Request from wrong address"); >+ kdc_audit_addreason((kdc_request_t)priv, "Request from wrong address"); > goto out; > } else if (config->warn_ticket_addresses) { >- _kdc_audit_addkv((kdc_request_t)priv, 0, "wrongaddr", "yes"); >+ kdc_audit_setkv_bool((kdc_request_t)priv, "wrongaddr", TRUE); > } > } > >@@ -2377,7 +1982,7 @@ server_lookup: > NULL, s, &pa.padata_value); > krb5_crypto_destroy(context, crypto); > if (ret) { >- _kdc_audit_addreason((kdc_request_t)priv, "Referral build failed"); >+ kdc_audit_addreason((kdc_request_t)priv, "Referral build failed"); > kdc_log(context, config, 4, > "Failed building server referral"); > goto out; >@@ -2402,7 +2007,7 @@ server_lookup: > */ > > if (kdc_issued && >- !krb5_principal_is_krbtgt(context, server->entry.principal)) { >+ !krb5_principal_is_krbtgt(context, priv->server->principal)) { > > /* Validate armor TGT before potentially including device claims */ > if (priv->armor_ticket) { >@@ -2419,54 +2024,35 @@ server_lookup: > * read-only-dc identifier, we need to embed it in the PAC KDC signatures. > */ > >- rodc_id = krbtgt_out->entry.kvno >> 16; >+ rodc_id = krbtgt_out->kvno >> 16; > > /* > * > */ > > ret = tgs_make_reply(priv, >- tp, > tgt, > ekey, > &tkey_sign->key, > &sessionkey, > kvno, > *auth_data, >- server, >- rsp, >- client, >- cp, > tgt_realm, > rodc_id, > add_ticket_sig); > > out: > free(user2user_name); >- if (tpn != cpn) >- free(tpn); >- free(dpn); > free(krbtgt_out_n); > _krb5_free_capath(context, capath); > > krb5_free_keyblock_contents(context, &sessionkey); > if(krbtgt_out) >- _kdc_free_ent(context, krbtgt_out); >- if(server) >- _kdc_free_ent(context, server); >- if(client) >- _kdc_free_ent(context, client); >- if(s4u2self_impersonated_client) >- _kdc_free_ent(context, s4u2self_impersonated_client); >+ _kdc_free_ent(context, krbtgt_outdb, krbtgt_out); > if(user2user_krbtgt) >- _kdc_free_ent(context, user2user_krbtgt); >+ _kdc_free_ent(context, user2user_krbtgtdb, user2user_krbtgt); > > krb5_free_principal(context, user2user_princ); >- if (tp && tp != cp) >- krb5_free_principal(context, tp); >- krb5_free_principal(context, cp); >- krb5_free_principal(context, dp); >- krb5_free_principal(context, sp); > krb5_free_principal(context, krbtgt_out_principal); > free(ref_realm); > >@@ -2494,9 +2080,6 @@ _kdc_tgs_rep(astgs_request_t r) > krb5_error_code ret; > int i = 0; > const PA_DATA *tgs_req, *pa; >- >- hdb_entry_ex *krbtgt = NULL; >- krb5_ticket *ticket = NULL; > krb5_enctype krbtgt_etype = ETYPE_NULL; > > time_t *csec = NULL; >@@ -2529,9 +2112,7 @@ _kdc_tgs_rep(astgs_request_t r) > goto out; > } > ret = tgs_parse_request(r, tgs_req, >- &krbtgt, > &krbtgt_etype, >- &ticket, > from, from_addr, > &csec, &cusec, > &auth_data); >@@ -2557,9 +2138,7 @@ _kdc_tgs_rep(astgs_request_t r) > } > > ret = tgs_build_reply(r, >- krbtgt, > krbtgt_etype, >- ticket, > &auth_data, > from_addr); > if (ret) { >@@ -2576,6 +2155,9 @@ _kdc_tgs_rep(astgs_request_t r) > } > > out: >+ r->error_code = ret; >+ _kdc_audit_request(r); >+ > if(ret && ret != HDB_ERR_NOT_FOUND_HERE && data->data == NULL){ > METHOD_DATA error_method = { 0, NULL }; > >@@ -2584,9 +2166,9 @@ out: > &error_method, > r->armor_crypto, > &req->req_body, >- r->ret = ret, >- ticket != NULL ? ticket->client : NULL, >- ticket != NULL ? ticket->server : NULL, >+ r->error_code, >+ r->client_princ ? r->client_princ :(r->ticket != NULL ? r->ticket->client : NULL), >+ r->server_princ ? r->server_princ :(r->ticket != NULL ? r->ticket->server : NULL), > csec, cusec, > data); > free_METHOD_DATA(&error_method); >@@ -2609,9 +2191,9 @@ out: > } > free_EncryptionKey(&r->et.key); > >- if (r->client_princ) { >- krb5_free_principal(r->context, r->client_princ); >- r->client_princ = NULL; >+ if (r->canon_client_princ) { >+ krb5_free_principal(r->context, r->canon_client_princ); >+ r->canon_client_princ = NULL; > } > if (r->armor_crypto) { > krb5_crypto_destroy(r->context, r->armor_crypto); >@@ -2620,15 +2202,21 @@ out: > if (r->armor_ticket) > krb5_free_ticket(r->context, r->armor_ticket); > if (r->armor_server) >- _kdc_free_ent(r->context, r->armor_server); >+ _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server); > krb5_free_keyblock_contents(r->context, &r->reply_key); > krb5_free_keyblock_contents(r->context, &r->strengthen_key); > >- if (ticket) >- krb5_free_ticket(r->context, ticket); >- if(krbtgt) >- _kdc_free_ent(r->context, krbtgt); >- >+ if (r->ticket) >+ krb5_free_ticket(r->context, r->ticket); >+ if (r->krbtgt) >+ _kdc_free_ent(r->context, r->krbtgtdb, r->krbtgt); >+ >+ if (r->client) >+ _kdc_free_ent(r->context, r->clientdb, r->client); >+ krb5_free_principal(r->context, r->client_princ); >+ if (r->server) >+ _kdc_free_ent(r->context, r->serverdb, r->server); >+ krb5_free_principal(r->context, r->server_princ); > _kdc_free_fast_state(&r->fast); > krb5_pac_free(r->context, r->pac); > >diff --git a/third_party/heimdal/kdc/kstash.c b/third_party/heimdal/kdc/kstash.c >index bba2b11d0f0d..6ec1a548aca6 100644 >--- a/third_party/heimdal/kdc/kstash.c >+++ b/third_party/heimdal/kdc/kstash.c >@@ -131,6 +131,8 @@ main(int argc, char **argv) > krb5_string_to_key_salt(context, enctype, buf, salt, &key); > } > ret = hdb_add_master_key(context, &key, &mkey); >+ if (ret) >+ krb5_err(context, 1, ret, "hdb_add_master_key"); > > krb5_free_keyblock_contents(context, &key); > >diff --git a/third_party/heimdal/kdc/kx509.c b/third_party/heimdal/kdc/kx509.c >index bc3ca9deca6b..6efd94e3a12d 100644 >--- a/third_party/heimdal/kdc/kx509.c >+++ b/third_party/heimdal/kdc/kx509.c >@@ -157,9 +157,11 @@ verify_req_hash(krb5_context context, > } > > HMAC_CTX_init(&ctx); >- HMAC_Init_ex(&ctx, >- key->keyvalue.data, key->keyvalue.length, >- EVP_sha1(), NULL); >+ if (HMAC_Init_ex(&ctx, key->keyvalue.data, key->keyvalue.length, >+ EVP_sha1(), NULL) == 0) { >+ HMAC_CTX_cleanup(&ctx); >+ return krb5_enomem(context); >+ } > if (sizeof(digest) != HMAC_size(&ctx)) > krb5_abortx(context, "runtime error, hmac buffer wrong size in kx509"); > HMAC_Update(&ctx, version_2_0, sizeof(version_2_0)); >@@ -186,14 +188,17 @@ calculate_reply_hash(krb5_context context, > krb5_keyblock *key, > Kx509Response *rep) > { >- krb5_error_code ret; >+ krb5_error_code ret = 0; > HMAC_CTX ctx; > > HMAC_CTX_init(&ctx); > >- HMAC_Init_ex(&ctx, key->keyvalue.data, key->keyvalue.length, >- EVP_sha1(), NULL); >- ret = krb5_data_alloc(rep->hash, HMAC_size(&ctx)); >+ if (HMAC_Init_ex(&ctx, key->keyvalue.data, key->keyvalue.length, >+ EVP_sha1(), NULL) == 0) >+ ret = krb5_enomem(context); >+ >+ if (ret == 0) >+ ret = krb5_data_alloc(rep->hash, HMAC_size(&ctx)); > if (ret) { > HMAC_CTX_cleanup(&ctx); > return krb5_enomem(context); >@@ -248,7 +253,8 @@ is_local_realm(krb5_context context, > { > krb5_error_code ret; > krb5_principal tgs; >- hdb_entry_ex *ent = NULL; >+ HDB *db; >+ hdb_entry *ent = NULL; > > ret = krb5_make_principal(context, &tgs, realm, KRB5_TGS_NAME, realm, > NULL); >@@ -256,9 +262,9 @@ is_local_realm(krb5_context context, > return ret; > if (ret == 0) > ret = _kdc_db_fetch(context, reqctx->config, tgs, HDB_F_GET_KRBTGT, >- NULL, NULL, &ent); >+ NULL, &db, &ent); > if (ent) >- _kdc_free_ent(context, ent); >+ _kdc_free_ent(context, db, ent); > krb5_free_principal(context, tgs); > if (ret == HDB_ERR_NOENTRY || ret == HDB_ERR_NOT_FOUND_HERE) > return KRB5KRB_AP_ERR_NOT_US; >@@ -299,8 +305,8 @@ kdc_kx509_verify_service_principal(krb5_context context, > KRB5_TGS_NAME) == 0) { > const char *r = krb5_principal_get_comp_string(context, sprincipal, 1); > if ((ret = is_local_realm(context, reqctx, r))) >- _kdc_audit_addreason((kdc_request_t)reqctx, >- "Client used wrong krbtgt for kx509"); >+ kdc_audit_addreason((kdc_request_t)reqctx, >+ "Client used wrong krbtgt for kx509"); > goto out; > } > >@@ -309,8 +315,8 @@ kdc_kx509_verify_service_principal(krb5_context context, > if (ret != 0) { > ret = errno; > kdc_log(context, reqctx->config, 0, "Failed to get local hostname"); >- _kdc_audit_addreason((kdc_request_t)reqctx, >- "Failed to get local hostname"); >+ kdc_audit_addreason((kdc_request_t)reqctx, >+ "Failed to get local hostname"); > return ret; > } > localhost[sizeof(localhost) - 1] = '\0'; >@@ -329,8 +335,8 @@ err: > goto out; > > ret = KRB5KDC_ERR_SERVER_NOMATCH; >- _kdc_audit_addreason((kdc_request_t)reqctx, "Client used wrong kx509 " >- "service principal (expected %s)", expected); >+ kdc_audit_addreason((kdc_request_t)reqctx, "Client used wrong kx509 " >+ "service principal (expected %s)", expected); > > out: > krb5_xfree(expected); >@@ -394,7 +400,7 @@ mk_error_response(krb5_context context, > } > > va_start(ap, fmt); >- _kdc_audit_vaddreason((kdc_request_t)reqctx, fmt, ap); >+ kdc_audit_vaddreason((kdc_request_t)reqctx, fmt, ap); > va_end(ap); > } > >@@ -536,12 +542,13 @@ update_csr(krb5_context context, kx509_req_context reqctx, Extensions *exts) > } > } > if (ret) { >+ const char *emsg = krb5_get_error_message(context, ret); > kdc_log(context, reqctx->config, 1, >- "Error handling requested extensions: %s", >- krb5_get_error_message(context, ret)); >- _kdc_audit_addreason((kdc_request_t)reqctx, >- "Error handling requested extensions: %s", >- krb5_get_error_message(context, ret)); >+ "Error handling requested extensions: %s", emsg); >+ kdc_audit_addreason((kdc_request_t)reqctx, >+ "Error handling requested extensions: %s", >+ emsg); >+ krb5_free_error_message(context, emsg); > } > return ret; > } >@@ -574,7 +581,7 @@ get_csr(krb5_context context, kx509_req_context reqctx) > */ > if (ret == 0) > return update_csr(context, reqctx, reqctx->csr_plus.exts); >- _kdc_audit_addreason((kdc_request_t)reqctx, "Invalid CSR"); >+ kdc_audit_addreason((kdc_request_t)reqctx, "Invalid CSR"); > return ret; > } > reqctx->send_chain = 0; >@@ -582,8 +589,8 @@ get_csr(krb5_context context, kx509_req_context reqctx) > > /* Check if proof of possession is required by configuration */ > if (!get_bool_param(context, FALSE, reqctx->realm, "require_csr")) { >- _kdc_audit_addreason((kdc_request_t)reqctx, >- "CSRs required but client did not send one"); >+ kdc_audit_addreason((kdc_request_t)reqctx, >+ "CSRs required but client did not send one"); > krb5_set_error_message(context, KX509_STATUS_CLIENT_USE_CSR, > "CSRs required but kx509 client did not send " > "one"); >@@ -601,14 +608,14 @@ get_csr(krb5_context context, kx509_req_context reqctx) > /* Not an RSAPublicKey or garbage follows it */ > if (ret == 0) { > ret = KRB5KDC_ERR_NULL_KEY; >- _kdc_audit_addreason((kdc_request_t)reqctx, >- "Request has garbage after key"); >+ kdc_audit_addreason((kdc_request_t)reqctx, >+ "Request has garbage after key"); > krb5_set_error_message(context, ret, "Request has garbage after key"); > return ret; > } > >- _kdc_audit_addreason((kdc_request_t)reqctx, >- "Could not decode CSR or RSA subject public key"); >+ kdc_audit_addreason((kdc_request_t)reqctx, >+ "Could not decode CSR or RSA subject public key"); > krb5_set_error_message(context, ret, > "Could not decode CSR or RSA subject public key"); > return ret; >@@ -668,7 +675,7 @@ check_authz(krb5_context context, > ret = kdc_authorize_csr(context, reqctx->config->app, reqctx->csr, > cprincipal); > if (ret == 0) { >- _kdc_audit_addkv((kdc_request_t)reqctx, 0, "authorized", "true"); >+ kdc_audit_setkv_bool((kdc_request_t)reqctx, "authorized", TRUE); > > ret = hx509_request_get_san(reqctx->csr, 0, &san_type, &s); > if (ret == 0) { >@@ -685,20 +692,19 @@ check_authz(krb5_context context, > case HX509_SAN_TYPE_MS_UPN: san_type_s = "ms-UPN"; break; > default: san_type_s = "unknown"; break; > } >- _kdc_audit_addkv((kdc_request_t)reqctx, 0, "san0_type", "%s", >- san_type_s); >- _kdc_audit_addkv((kdc_request_t)reqctx, 0, "san0", "%s", s); >- free(s); >+ kdc_audit_addkv((kdc_request_t)reqctx, 0, "san0_type", "%s", >+ san_type_s); >+ kdc_audit_addkv((kdc_request_t)reqctx, 0, "san0", "%s", s); > } >+ frees(&s); > ret = hx509_request_get_eku(reqctx->csr, 0, &s); >- if (ret == 0) { >- _kdc_audit_addkv((kdc_request_t)reqctx, 0, "eku0", "%s", s); >- free(s); >- } >+ if (ret == 0) >+ kdc_audit_addkv((kdc_request_t)reqctx, 0, "eku0", "%s", s); >+ free(s); > return 0; > } > if (ret != KRB5_PLUGIN_NO_HANDLE) { >- _kdc_audit_addreason((kdc_request_t)reqctx, >+ kdc_audit_addreason((kdc_request_t)reqctx, > "Requested extensions rejected by plugin"); > return ret; > } >@@ -718,27 +724,27 @@ check_authz(krb5_context context, > if (ncomp != 2 || strcasecmp(comp1, s) != 0 || > strchr(s, '.') == NULL || > !check_authz_svc_ok(context, comp0)) { >- _kdc_audit_addreason((kdc_request_t)reqctx, >- "Requested extensions rejected by " >- "default policy (dNSName SAN " >- "does not match client)"); >+ kdc_audit_addreason((kdc_request_t)reqctx, >+ "Requested extensions rejected by " >+ "default policy (dNSName SAN " >+ "does not match client)"); > goto eacces; > } > break; > case HX509_SAN_TYPE_PKINIT: > if (strcmp(cprinc, s) != 0) { >- _kdc_audit_addreason((kdc_request_t)reqctx, >- "Requested extensions rejected by " >- "default policy (PKINIT SAN " >- "does not match client)"); >+ kdc_audit_addreason((kdc_request_t)reqctx, >+ "Requested extensions rejected by " >+ "default policy (PKINIT SAN " >+ "does not match client)"); > goto eacces; > } > break; > default: >- _kdc_audit_addreason((kdc_request_t)reqctx, >- "Requested extensions rejected by " >- "default policy (non-default SAN " >- "requested)"); >+ kdc_audit_addreason((kdc_request_t)reqctx, >+ "Requested extensions rejected by " >+ "default policy (non-default SAN " >+ "requested)"); > goto eacces; > } > } >@@ -766,8 +772,8 @@ check_authz(krb5_context context, > } > der_free_oid(&oid); > if (k == sizeof(eku_whitelist)/sizeof(eku_whitelist[0])) { >- _kdc_audit_addreason((kdc_request_t)reqctx, >- "Requested EKU rejected by default policy"); >+ kdc_audit_addreason((kdc_request_t)reqctx, >+ "Requested EKU rejected by default policy"); > goto eacces; > } > } >@@ -785,7 +791,8 @@ check_authz(krb5_context context, > if (KeyUsage2int(ku) != (KeyUsage2int(ku) & KeyUsage2int(ku_allowed))) > goto eacces; > >- _kdc_audit_addkv((kdc_request_t)reqctx, 0, "authorized", "true"); >+ kdc_audit_setkv_bool((kdc_request_t)reqctx, "authorized", TRUE); >+ free(cprinc); > return 0; > > eacces: >@@ -794,7 +801,7 @@ eacces: > > out: > /* XXX Display error code */ >- _kdc_audit_addreason((kdc_request_t)reqctx, >+ kdc_audit_addreason((kdc_request_t)reqctx, > "Error handling requested extensions"); > out2: > free(cprinc); >@@ -884,7 +891,7 @@ _kdc_do_kx509(kx509_req_context r) > * possibly change the error code and message. > */ > is_probe = 1; >- _kdc_audit_addkv((kdc_request_t)r, 0, "probe", "unauthenticated"); >+ kdc_audit_addkv((kdc_request_t)r, 0, "probe", "unauthenticated"); > ret = mk_error_response(r->context, r, 4, 0, > "kx509 service is available"); > goto out; >@@ -933,7 +940,8 @@ _kdc_do_kx509(kx509_req_context r) > goto out; > } > >- ret = krb5_unparse_name(r->context, cprincipal, &r->cname); >+ if (ret == 0) >+ ret = krb5_unparse_name(r->context, cprincipal, &r->cname); > > /* Check that the service name is a valid kx509 service name */ > if (ret == 0) >@@ -966,7 +974,7 @@ _kdc_do_kx509(kx509_req_context r) > * possibly change the error code and message. > */ > is_probe = 1; >- _kdc_audit_addkv((kdc_request_t)r, 0, "probe", "authenticated"); >+ kdc_audit_addkv((kdc_request_t)r, 0, "probe", "authenticated"); > ret = mk_error_response(r->context, r, 4, 0, > "kx509 authenticated probe request"); > goto out; >@@ -1041,14 +1049,14 @@ _kdc_do_kx509(kx509_req_context r) > ret = encode_reply(r->context, r, &rep); > if (ret) > /* Can't send an error message either in this case, surely */ >- _kdc_audit_addreason((kdc_request_t)r, "Could not encode response"); >+ kdc_audit_addreason((kdc_request_t)r, "Could not encode response"); > > out: > hx509_certs_free(&certs); > if (ret == 0 && !is_probe) >- _kdc_audit_addkv((kdc_request_t)r, 0, "cert_issued", "true"); >+ kdc_audit_setkv_bool((kdc_request_t)r, "cert_issued", TRUE); > else >- _kdc_audit_addkv((kdc_request_t)r, 0, "cert_issued", "false"); >+ kdc_audit_setkv_bool((kdc_request_t)r, "cert_issued", FALSE); > if (r->ac) > krb5_auth_con_free(r->context, r->ac); > if (ticket) >diff --git a/third_party/heimdal/kdc/libkdc-exports.def b/third_party/heimdal/kdc/libkdc-exports.def >index a4ed75bfb6a5..3cc929e6025b 100644 >--- a/third_party/heimdal/kdc/libkdc-exports.def >+++ b/third_party/heimdal/kdc/libkdc-exports.def >@@ -6,8 +6,9 @@ EXPORTS > kdc_log_msg > kdc_log_msg_va > kdc_openlog >+ kdc_check_flags > kdc_validate_token >- krb5_kdc_windc_init >+ krb5_kdc_plugin_init > krb5_kdc_get_config > krb5_kdc_pkinit_config > krb5_kdc_set_dbinfo >@@ -16,8 +17,80 @@ EXPORTS > krb5_kdc_save_request > krb5_kdc_update_time > krb5_kdc_pk_initialize >- _kdc_audit_addkv >- _kdc_audit_addreason >- _kdc_audit_vaddkv >- _kdc_audit_vaddreason >+ kdc_request_set_attribute >+ kdc_request_get_attribute >+ kdc_request_copy_attribute >+ kdc_request_delete_attribute >+ kdc_request_add_encrypted_padata >+ kdc_request_add_pac_buffer >+ kdc_request_add_reply_padata >+ kdc_request_get_addr >+ kdc_request_get_canon_client_princ >+ kdc_request_get_client >+ kdc_request_get_clientdb >+ kdc_request_get_client_princ >+ kdc_request_get_context >+ kdc_request_get_config >+ kdc_request_get_cname >+ kdc_request_get_error_code >+ kdc_request_get_from >+ kdc_request_get_krbtgt >+ kdc_request_get_krbtgtdb >+ kdc_request_get_krbtgt_princ >+ kdc_request_get_pac >+ kdc_request_get_pac_attributes >+ kdc_request_get_rep >+ kdc_request_get_reply_key >+ kdc_request_get_req >+ kdc_request_get_request >+ kdc_request_get_server >+ kdc_request_get_serverdb >+ kdc_request_get_server_princ >+ kdc_request_get_sname >+ kdc_request_get_ticket >+ kdc_request_get_tv_end >+ kdc_request_get_tv_start >+ kdc_request_set_canon_client_princ >+ kdc_request_set_client_princ >+ kdc_request_set_cname >+ kdc_request_set_error_code >+ kdc_request_set_krbtgt_princ >+ kdc_request_set_pac >+ kdc_request_set_pac_attributes >+ kdc_request_set_rep >+ kdc_request_set_reply_key >+ kdc_request_set_server_princ >+ kdc_request_set_sname >+ kdc_audit_addkv >+ kdc_audit_addkv_number >+ kdc_audit_addkv_object >+ kdc_audit_addkv_timediff >+ kdc_audit_addaddrs >+ kdc_audit_addreason >+ kdc_audit_getkv >+ kdc_audit_setkv_bool >+ kdc_audit_setkv_number >+ kdc_audit_setkv_object >+ kdc_audit_vaddkv >+ kdc_audit_vaddreason > _kdc_audit_trail >+ >+ kdc_object_alloc >+ kdc_object_retain >+ kdc_object_release >+ kdc_bool_create >+ kdc_bool_get_value >+ kdc_array_iterate >+ kdc_array_get_length >+ kdc_array_get_value >+ kdc_array_copy_value >+ kdc_string_create >+ kdc_string_get_utf8 >+ kdc_data_create >+ kdc_data_get_data >+ kdc_number_create >+ kdc_number_get_value >+ >+ ; needed for digest-service >+ _kdc_db_fetch >+ _kdc_free_ent >diff --git a/third_party/heimdal/kdc/log.c b/third_party/heimdal/kdc/log.c >index 895f1c9c6e4b..bfb0f54ff899 100644 >--- a/third_party/heimdal/kdc/log.c >+++ b/third_party/heimdal/kdc/log.c >@@ -35,7 +35,7 @@ > > #include "kdc_locl.h" > >-void >+KDC_LIB_FUNCTION void KDC_LIB_CALL > kdc_openlog(krb5_context context, > const char *service, > krb5_kdc_configuration *config) >@@ -63,7 +63,7 @@ kdc_openlog(krb5_context context, > #undef __attribute__ > #define __attribute__(X) > >-char* >+KDC_LIB_FUNCTION char * KDC_LIB_CALL > kdc_log_msg_va(krb5_context context, > krb5_kdc_configuration *config, > int level, const char *fmt, va_list ap) >@@ -74,7 +74,7 @@ kdc_log_msg_va(krb5_context context, > return msg; > } > >-char* >+KDC_LIB_FUNCTION char * KDC_LIB_CALL > kdc_log_msg(krb5_context context, > krb5_kdc_configuration *config, > int level, const char *fmt, ...) >@@ -88,7 +88,7 @@ kdc_log_msg(krb5_context context, > return s; > } > >-void >+KDC_LIB_FUNCTION void KDC_LIB_CALL > kdc_vlog(krb5_context context, > krb5_kdc_configuration *config, > int level, const char *fmt, va_list ap) >@@ -97,7 +97,7 @@ kdc_vlog(krb5_context context, > free(kdc_log_msg_va(context, config, level, fmt, ap)); > } > >-void >+KDC_LIB_FUNCTION void KDC_LIB_CALL > kdc_log(krb5_context context, > krb5_kdc_configuration *config, > int level, const char *fmt, ...) >diff --git a/third_party/heimdal/kdc/misc.c b/third_party/heimdal/kdc/misc.c >index e6a5c5c2340d..b48503d26a0e 100644 >--- a/third_party/heimdal/kdc/misc.c >+++ b/third_party/heimdal/kdc/misc.c >@@ -60,18 +60,18 @@ synthesize_hdb_close(krb5_context context, struct HDB *db) > } > > /* >- * Synthesize an HDB entry suitable for PKINIT and only PKINIT. >+ * Synthesize an HDB entry suitable for PKINIT and GSS preauth. > */ > static krb5_error_code > synthesize_client(krb5_context context, > krb5_kdc_configuration *config, > krb5_const_principal princ, > HDB **db, >- hdb_entry_ex **h) >+ hdb_entry **h) > { > static HDB null_db; > krb5_error_code ret; >- hdb_entry_ex *e; >+ hdb_entry *e; > > /* Hope this works! */ > null_db.hdb_destroy = synthesize_hdb_close; >@@ -81,57 +81,57 @@ synthesize_client(krb5_context context, > > ret = (e = calloc(1, sizeof(*e))) ? 0 : krb5_enomem(context); > if (ret == 0) { >- e->entry.flags.client = 1; >- e->entry.flags.immutable = 1; >- e->entry.flags.virtual = 1; >- e->entry.flags.synthetic = 1; >- e->entry.flags.do_not_store = 1; >- e->entry.kvno = 1; >- e->entry.keys.len = 0; >- e->entry.keys.val = NULL; >- e->entry.created_by.time = time(NULL); >- e->entry.modified_by = NULL; >- e->entry.valid_start = NULL; >- e->entry.valid_end = NULL; >- e->entry.pw_end = NULL; >- e->entry.etypes = NULL; >- e->entry.generation = NULL; >- e->entry.extensions = NULL; >+ e->flags.client = 1; >+ e->flags.immutable = 1; >+ e->flags.virtual = 1; >+ e->flags.synthetic = 1; >+ e->flags.do_not_store = 1; >+ e->kvno = 1; >+ e->keys.len = 0; >+ e->keys.val = NULL; >+ e->created_by.time = time(NULL); >+ e->modified_by = NULL; >+ e->valid_start = NULL; >+ e->valid_end = NULL; >+ e->pw_end = NULL; >+ e->etypes = NULL; >+ e->generation = NULL; >+ e->extensions = NULL; > } > if (ret == 0) >- ret = (e->entry.max_renew = calloc(1, sizeof(*e->entry.max_renew))) ? >+ ret = (e->max_renew = calloc(1, sizeof(*e->max_renew))) ? > 0 : krb5_enomem(context); > if (ret == 0) >- ret = (e->entry.max_life = calloc(1, sizeof(*e->entry.max_life))) ? >+ ret = (e->max_life = calloc(1, sizeof(*e->max_life))) ? > 0 : krb5_enomem(context); > if (ret == 0) >- ret = krb5_copy_principal(context, princ, &e->entry.principal); >+ ret = krb5_copy_principal(context, princ, &e->principal); > if (ret == 0) >- ret = krb5_copy_principal(context, princ, &e->entry.created_by.principal); >+ ret = krb5_copy_principal(context, princ, &e->created_by.principal); > if (ret == 0) { > /* > * We can't check OCSP in the TGS path, so we can't let tickets for > * synthetic principals live very long. > */ >- *(e->entry.max_renew) = config->synthetic_clients_max_renew; >- *(e->entry.max_life) = config->synthetic_clients_max_life; >+ *(e->max_renew) = config->synthetic_clients_max_renew; >+ *(e->max_life) = config->synthetic_clients_max_life; > *h = e; >- } else { >- hdb_free_entry(context, e); >+ } else if (e) { >+ hdb_free_entry(context, &null_db, e); > } > return ret; > } > >-krb5_error_code >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL > _kdc_db_fetch(krb5_context context, > krb5_kdc_configuration *config, > krb5_const_principal principal, > unsigned flags, > krb5uint32 *kvno_ptr, > HDB **db, >- hdb_entry_ex **h) >+ hdb_entry **h) > { >- hdb_entry_ex *ent = NULL; >+ hdb_entry *ent = NULL; > krb5_error_code ret = HDB_ERR_NOENTRY; > int i; > unsigned kvno = 0; >@@ -245,10 +245,10 @@ out: > return ret; > } > >-void >-_kdc_free_ent(krb5_context context, hdb_entry_ex *ent) >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+_kdc_free_ent(krb5_context context, HDB *db, hdb_entry *ent) > { >- hdb_free_entry (context, ent); >+ hdb_free_entry (context, db, ent); > free (ent); > } > >@@ -260,7 +260,7 @@ _kdc_free_ent(krb5_context context, hdb_entry_ex *ent) > krb5_error_code > _kdc_get_preferred_key(krb5_context context, > krb5_kdc_configuration *config, >- hdb_entry_ex *h, >+ hdb_entry *h, > const char *name, > krb5_enctype *enctype, > Key **key) >@@ -271,11 +271,11 @@ _kdc_get_preferred_key(krb5_context context, > if (config->use_strongest_server_key) { > const krb5_enctype *p = krb5_kerberos_enctypes(context); > >- for (i = 0; p[i] != (krb5_enctype)ETYPE_NULL; i++) { >+ for (i = 0; p[i] != ETYPE_NULL; i++) { > if (krb5_enctype_valid(context, p[i]) != 0 && >- !_kdc_is_weak_exception(h->entry.principal, p[i])) >+ !_kdc_is_weak_exception(h->principal, p[i])) > continue; >- ret = hdb_enctype2key(context, &h->entry, NULL, p[i], key); >+ ret = hdb_enctype2key(context, h, NULL, p[i], key); > if (ret != 0) > continue; > if (enctype != NULL) >@@ -285,12 +285,12 @@ _kdc_get_preferred_key(krb5_context context, > } else { > *key = NULL; > >- for (i = 0; i < h->entry.keys.len; i++) { >- if (krb5_enctype_valid(context, h->entry.keys.val[i].key.keytype) != 0 && >- !_kdc_is_weak_exception(h->entry.principal, h->entry.keys.val[i].key.keytype)) >+ for (i = 0; i < h->keys.len; i++) { >+ if (krb5_enctype_valid(context, h->keys.val[i].key.keytype) != 0 && >+ !_kdc_is_weak_exception(h->principal, h->keys.val[i].key.keytype)) > continue; >- ret = hdb_enctype2key(context, &h->entry, NULL, >- h->entry.keys.val[i].key.keytype, key); >+ ret = hdb_enctype2key(context, h, NULL, >+ h->keys.val[i].key.keytype, key); > if (ret != 0) > continue; > if (enctype != NULL) >@@ -336,3 +336,22 @@ _kdc_include_pac_p(astgs_request_t r) > { > return TRUE; > } >+ >+/* >+ * Notify the HDB backend and KDC plugin of the audited event. >+ */ >+ >+krb5_error_code >+_kdc_audit_request(astgs_request_t r) >+{ >+ krb5_error_code ret; >+ struct HDB *hdb; >+ >+ ret = _kdc_plugin_audit(r); >+ if (ret == 0 && >+ (hdb = r->clientdb ? r->clientdb : r->config->db[0]) && >+ hdb->hdb_audit) >+ ret = hdb->hdb_audit(r->context, hdb, r->client, (hdb_request_t)r); >+ >+ return ret; >+} >diff --git a/third_party/heimdal/kdc/mit_dump.c b/third_party/heimdal/kdc/mit_dump.c >index 3e4b47d7e1b9..32cf5dc65cea 100644 >--- a/third_party/heimdal/kdc/mit_dump.c >+++ b/third_party/heimdal/kdc/mit_dump.c >@@ -146,7 +146,7 @@ mit_prop_dump(void *arg, const char *file) > char *line = NULL; > int lineno = 0; > FILE *f; >- struct hdb_entry_ex ent; >+ hdb_entry ent; > struct prop_data *pd = arg; > krb5_storage *sp = NULL; > krb5_data kdb_ent; >@@ -202,14 +202,14 @@ mit_prop_dump(void *arg, const char *file) > } > ret = krb5_storage_to_data(sp, &kdb_ent); > if (ret) break; >- ret = _hdb_mdb_value2entry(pd->context, &kdb_ent, 0, &ent.entry); >+ ret = _hdb_mdb_value2entry(pd->context, &kdb_ent, 0, &ent); > krb5_data_free(&kdb_ent); > if (ret) { > warnx("line: %d: failed to store; ignoring", lineno); > continue; > } > ret = v5_prop(pd->context, NULL, &ent, arg); >- hdb_free_entry(pd->context, &ent); >+ hdb_free_entry(pd->context, NULL, &ent); /* XXX */ > if (ret) break; > } > >diff --git a/third_party/heimdal/kdc/mssfu.c b/third_party/heimdal/kdc/mssfu.c >new file mode 100644 >index 000000000000..9e67aad33193 >--- /dev/null >+++ b/third_party/heimdal/kdc/mssfu.c >@@ -0,0 +1,568 @@ >+/* >+ * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan >+ * (Royal Institute of Technology, Stockholm, Sweden). >+ * All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * 3. Neither the name of the Institute nor the names of its contributors >+ * may be used to endorse or promote products derived from this software >+ * without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND >+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE >+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >+ * SUCH DAMAGE. >+ */ >+ >+#include "kdc_locl.h" >+ >+/* >+ * [MS-SFU] Kerberos Protocol Extensions: >+ * Service for User (S4U2Self) and Constrained Delegation Protocol (S4U2Proxy) >+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/ >+ */ >+ >+/* >+ * Determine if constrained delegation is allowed from this client to this server >+ */ >+ >+static krb5_error_code >+check_constrained_delegation(krb5_context context, >+ krb5_kdc_configuration *config, >+ HDB *clientdb, >+ hdb_entry *client, >+ hdb_entry *server, >+ krb5_const_principal target) >+{ >+ const HDB_Ext_Constrained_delegation_acl *acl; >+ krb5_error_code ret; >+ size_t i; >+ >+ /* >+ * constrained delegation (S4U2Proxy) only works within >+ * the same realm. We use the already canonicalized version >+ * of the principals here, while "target" is the principal >+ * provided by the client. >+ */ >+ if (!krb5_realm_compare(context, client->principal, server->principal)) { >+ ret = KRB5KDC_ERR_BADOPTION; >+ kdc_log(context, config, 4, >+ "Bad request for constrained delegation"); >+ return ret; >+ } >+ >+ if (clientdb->hdb_check_constrained_delegation) { >+ ret = clientdb->hdb_check_constrained_delegation(context, clientdb, client, target); >+ if (ret == 0) >+ return 0; >+ } else { >+ /* if client delegates to itself, that ok */ >+ if (krb5_principal_compare(context, client->principal, server->principal) == TRUE) >+ return 0; >+ >+ ret = hdb_entry_get_ConstrainedDelegACL(client, &acl); >+ if (ret) { >+ krb5_clear_error_message(context); >+ return ret; >+ } >+ >+ if (acl) { >+ for (i = 0; i < acl->len; i++) { >+ if (krb5_principal_compare(context, target, &acl->val[i]) == TRUE) >+ return 0; >+ } >+ } >+ ret = KRB5KDC_ERR_BADOPTION; >+ } >+ kdc_log(context, config, 4, >+ "Bad request for constrained delegation"); >+ return ret; >+} >+ >+/* >+ * Validate a protocol transition (S4U2Self) request. If present and >+ * successfully validated then the client in the request structure >+ * will be replaced with the impersonated client. >+ */ >+ >+static krb5_error_code >+validate_protocol_transition(astgs_request_t r) >+{ >+ krb5_error_code ret; >+ KDC_REQ_BODY *b = &r->req.req_body; >+ EncTicketPart *ticket = &r->ticket->ticket; >+ hdb_entry *s4u_client = NULL; >+ HDB *s4u_clientdb; >+ int flags = HDB_F_FOR_TGS_REQ; >+ krb5_principal s4u_client_name = NULL, s4u_canon_client_name = NULL; >+ krb5_pac s4u_pac = NULL; >+ const PA_DATA *sdata; >+ char *s4ucname = NULL; >+ int i = 0; >+ krb5_crypto crypto; >+ krb5_data datack; >+ PA_S4U2Self self; >+ const char *str; >+ >+ if (r->client == NULL) >+ return 0; >+ >+ sdata = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FOR_USER); >+ if (sdata == NULL) >+ return 0; >+ >+ memset(&self, 0, sizeof(self)); >+ >+ if (b->kdc_options.canonicalize) >+ flags |= HDB_F_CANON; >+ >+ ret = decode_PA_S4U2Self(sdata->padata_value.data, >+ sdata->padata_value.length, >+ &self, NULL); >+ if (ret) { >+ kdc_audit_addreason((kdc_request_t)r, >+ "Failed to decode PA-S4U2Self"); >+ kdc_log(r->context, r->config, 4, "Failed to decode PA-S4U2Self"); >+ goto out; >+ } >+ >+ if (!krb5_checksum_is_keyed(r->context, self.cksum.cksumtype)) { >+ kdc_audit_addreason((kdc_request_t)r, >+ "PA-S4U2Self with unkeyed checksum"); >+ kdc_log(r->context, r->config, 4, "Reject PA-S4U2Self with unkeyed checksum"); >+ ret = KRB5KRB_AP_ERR_INAPP_CKSUM; >+ goto out; >+ } >+ >+ ret = _krb5_s4u2self_to_checksumdata(r->context, &self, &datack); >+ if (ret) >+ goto out; >+ >+ ret = krb5_crypto_init(r->context, &ticket->key, 0, &crypto); >+ if (ret) { >+ const char *msg = krb5_get_error_message(r->context, ret); >+ krb5_data_free(&datack); >+ kdc_log(r->context, r->config, 4, "krb5_crypto_init failed: %s", msg); >+ krb5_free_error_message(r->context, msg); >+ goto out; >+ } >+ >+ /* Allow HMAC_MD5 checksum with any key type */ >+ if (self.cksum.cksumtype == CKSUMTYPE_HMAC_MD5) { >+ struct krb5_crypto_iov iov; >+ unsigned char csdata[16]; >+ Checksum cs; >+ >+ cs.checksum.length = sizeof(csdata); >+ cs.checksum.data = &csdata; >+ >+ iov.data.data = datack.data; >+ iov.data.length = datack.length; >+ iov.flags = KRB5_CRYPTO_TYPE_DATA; >+ >+ ret = _krb5_HMAC_MD5_checksum(r->context, NULL, &crypto->key, >+ KRB5_KU_OTHER_CKSUM, &iov, 1, >+ &cs); >+ if (ret == 0 && >+ krb5_data_ct_cmp(&cs.checksum, &self.cksum.checksum) != 0) >+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; >+ } else { >+ ret = _kdc_verify_checksum(r->context, >+ crypto, >+ KRB5_KU_OTHER_CKSUM, >+ &datack, >+ &self.cksum); >+ } >+ krb5_data_free(&datack); >+ krb5_crypto_destroy(r->context, crypto); >+ if (ret) { >+ const char *msg = krb5_get_error_message(r->context, ret); >+ kdc_audit_addreason((kdc_request_t)r, >+ "S4U2Self checksum failed"); >+ kdc_log(r->context, r->config, 4, >+ "krb5_verify_checksum failed for S4U2Self: %s", msg); >+ krb5_free_error_message(r->context, msg); >+ goto out; >+ } >+ >+ ret = _krb5_principalname2krb5_principal(r->context, >+ &s4u_client_name, >+ self.name, >+ self.realm); >+ if (ret) >+ goto out; >+ >+ ret = krb5_unparse_name(r->context, s4u_client_name, &s4ucname); >+ if (ret) >+ goto out; >+ >+ /* >+ * Note no HDB_F_SYNTHETIC_OK -- impersonating non-existent clients >+ * is probably not desirable! >+ */ >+ ret = _kdc_db_fetch(r->context, r->config, s4u_client_name, >+ HDB_F_GET_CLIENT | flags, NULL, >+ &s4u_clientdb, &s4u_client); >+ if (ret) { >+ const char *msg; >+ >+ /* >+ * If the client belongs to the same realm as our krbtgt, it >+ * should exist in the local database. >+ * >+ */ >+ if (ret == HDB_ERR_NOENTRY) >+ ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; >+ msg = krb5_get_error_message(r->context, ret); >+ kdc_audit_addreason((kdc_request_t)r, >+ "S4U2Self principal to impersonate not found"); >+ kdc_log(r->context, r->config, 2, >+ "S4U2Self principal to impersonate %s not found in database: %s", >+ s4ucname, msg); >+ krb5_free_error_message(r->context, msg); >+ goto out; >+ } >+ >+ /* >+ * Ignore require_pwchange and pw_end attributes (as Windows does), >+ * since S4U2Self is not password authentication. >+ */ >+ s4u_client->flags.require_pwchange = FALSE; >+ free(s4u_client->pw_end); >+ s4u_client->pw_end = NULL; >+ >+ ret = kdc_check_flags(r, FALSE, s4u_client, r->server); >+ if (ret) >+ goto out; /* kdc_check_flags() calls kdc_audit_addreason() */ >+ >+ ret = _kdc_pac_generate(r->context, >+ r->config, >+ s4u_client, >+ r->server, >+ NULL, >+ KRB5_PAC_WAS_GIVEN_IMPLICITLY, >+ &s4u_pac); >+ if (ret) { >+ kdc_log(r->context, r->config, 4, "PAC generation failed for -- %s", s4ucname); >+ goto out; >+ } >+ >+ /* >+ * Check that service doing the impersonating is >+ * requesting a ticket to it-self. >+ */ >+ ret = _kdc_check_client_matches_target_service(r->context, >+ r->config, >+ r->clientdb, >+ r->client, >+ r->server, >+ r->server_princ); >+ if (ret) { >+ kdc_log(r->context, r->config, 4, "S4U2Self: %s is not allowed " >+ "to impersonate to service " >+ "(tried for user %s to service %s)", >+ r->cname, s4ucname, r->sname); >+ goto out; >+ } >+ >+ ret = krb5_copy_principal(r->context, s4u_client->principal, >+ &s4u_canon_client_name); >+ if (ret) >+ goto out; >+ >+ /* >+ * If the service isn't trusted for authentication to >+ * delegation or if the impersonate client is disallowed >+ * forwardable, remove the forwardable flag. >+ */ >+ if (r->client->flags.trusted_for_delegation && >+ s4u_client->flags.forwardable) { >+ str = "[forwardable]"; >+ } else { >+ b->kdc_options.forwardable = 0; >+ str = ""; >+ } >+ kdc_log(r->context, r->config, 4, "s4u2self %s impersonating %s to " >+ "service %s %s", r->cname, s4ucname, r->sname, str); >+ >+ /* >+ * Replace all client information in the request with the >+ * impersonated client. (The audit entry containing the original >+ * client name will have been created before this point.) >+ */ >+ _kdc_request_set_cname_nocopy((kdc_request_t)r, &s4ucname); >+ _kdc_request_set_client_princ_nocopy(r, &s4u_client_name); >+ >+ _kdc_free_ent(r->context, r->clientdb, r->client); >+ r->client = s4u_client; >+ s4u_client = NULL; >+ r->clientdb = s4u_clientdb; >+ s4u_clientdb = NULL; >+ >+ _kdc_request_set_canon_client_princ_nocopy(r, &s4u_canon_client_name); >+ _kdc_request_set_pac_nocopy(r, &s4u_pac); >+ >+out: >+ if (s4u_client) >+ _kdc_free_ent(r->context, s4u_clientdb, s4u_client); >+ krb5_free_principal(r->context, s4u_client_name); >+ krb5_xfree(s4ucname); >+ krb5_free_principal(r->context, s4u_canon_client_name); >+ krb5_pac_free(r->context, s4u_pac); >+ >+ free_PA_S4U2Self(&self); >+ >+ return ret; >+} >+ >+/* >+ * Validate a constrained delegation (S4U2Proxy) request. If present >+ * and successfully validated then the client in the request structure >+ * will be replaced with the client from the evidence ticket. >+ */ >+ >+static krb5_error_code >+validate_constrained_delegation(astgs_request_t r) >+{ >+ krb5_error_code ret; >+ KDC_REQ_BODY *b = &r->req.req_body; >+ int flags = HDB_F_FOR_TGS_REQ; >+ krb5_principal s4u_client_name = NULL, s4u_server_name = NULL; >+ krb5_principal s4u_canon_client_name = NULL; >+ krb5_pac s4u_pac = NULL; >+ uint64_t s4u_pac_attributes; >+ char *s4ucname = NULL, *s4usname = NULL; >+ EncTicketPart evidence_tkt; >+ HDB *s4u_clientdb; >+ hdb_entry *s4u_client = NULL; >+ krb5_boolean ad_kdc_issued = FALSE; >+ Key *clientkey; >+ Ticket *t; >+ krb5_const_realm local_realm; >+ >+ if (r->client == NULL >+ || b->additional_tickets == NULL >+ || b->additional_tickets->len == 0 >+ || b->kdc_options.cname_in_addl_tkt == 0 >+ || b->kdc_options.enc_tkt_in_skey) >+ return 0; >+ >+ memset(&evidence_tkt, 0, sizeof(evidence_tkt)); >+ local_realm = >+ krb5_principal_get_comp_string(r->context, r->krbtgt->principal, 1); >+ >+ /* >+ * We require that the service's TGT has a PAC; this will have been >+ * validated prior to this function being called. >+ */ >+ if (r->pac == NULL) { >+ ret = KRB5KDC_ERR_BADOPTION; >+ kdc_audit_addreason((kdc_request_t)r, "Missing PAC"); >+ kdc_log(r->context, r->config, 4, >+ "Constrained delegation without PAC, %s/%s", >+ r->cname, r->sname); >+ goto out; >+ } >+ >+ t = &b->additional_tickets->val[0]; >+ >+ ret = hdb_enctype2key(r->context, r->client, >+ hdb_kvno2keys(r->context, r->client, >+ t->enc_part.kvno ? * t->enc_part.kvno : 0), >+ t->enc_part.etype, &clientkey); >+ if (ret) { >+ ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ >+ goto out; >+ } >+ >+ ret = krb5_decrypt_ticket(r->context, t, &clientkey->key, &evidence_tkt, 0); >+ if (ret) { >+ kdc_audit_addreason((kdc_request_t)r, >+ "Failed to decrypt constrained delegation ticket"); >+ kdc_log(r->context, r->config, 4, >+ "failed to decrypt ticket for " >+ "constrained delegation from %s to %s ", r->cname, r->sname); >+ goto out; >+ } >+ >+ ret = _krb5_principalname2krb5_principal(r->context, >+ &s4u_client_name, >+ evidence_tkt.cname, >+ evidence_tkt.crealm); >+ if (ret) >+ goto out; >+ >+ ret = krb5_unparse_name(r->context, s4u_client_name, &s4ucname); >+ if (ret) >+ goto out; >+ >+ kdc_audit_addkv((kdc_request_t)r, 0, "impersonatee", "%s", s4ucname); >+ >+ ret = _krb5_principalname2krb5_principal(r->context, >+ &s4u_server_name, >+ t->sname, >+ t->realm); >+ if (ret) >+ goto out; >+ >+ ret = krb5_unparse_name(r->context, s4u_server_name, &s4usname); >+ if (ret) >+ goto out; >+ >+ /* check that ticket is valid */ >+ if (evidence_tkt.flags.forwardable == 0) { >+ kdc_audit_addreason((kdc_request_t)r, >+ "Missing forwardable flag on ticket for constrained delegation"); >+ kdc_log(r->context, r->config, 4, >+ "Missing forwardable flag on ticket for " >+ "constrained delegation from %s (%s) as %s to %s ", >+ r->cname, s4usname, s4ucname, r->sname); >+ ret = KRB5KDC_ERR_BADOPTION; >+ goto out; >+ } >+ >+ ret = check_constrained_delegation(r->context, r->config, r->clientdb, >+ r->client, r->server, r->server_princ); >+ if (ret) { >+ kdc_audit_addreason((kdc_request_t)r, >+ "Constrained delegation not allowed"); >+ kdc_log(r->context, r->config, 4, >+ "constrained delegation from %s (%s) as %s to %s not allowed", >+ r->cname, s4usname, s4ucname, r->sname); >+ goto out; >+ } >+ >+ ret = _kdc_verify_flags(r->context, r->config, &evidence_tkt, s4ucname); >+ if (ret) { >+ kdc_audit_addreason((kdc_request_t)r, >+ "Constrained delegation ticket expired or invalid"); >+ goto out; >+ } >+ >+ /* Try lookup the delegated client in DB */ >+ ret = _kdc_db_fetch_client(r->context, r->config, flags, >+ s4u_client_name, s4ucname, local_realm, >+ &s4u_clientdb, &s4u_client); >+ if (ret) >+ goto out; >+ >+ if (s4u_client != NULL) { >+ ret = kdc_check_flags(r, FALSE, s4u_client, r->server); >+ if (ret) >+ goto out; >+ } >+ >+ /* >+ * TODO: pass in t->sname and t->realm and build >+ * a S4U_DELEGATION_INFO blob to the PAC. >+ */ >+ ret = _kdc_check_pac(r->context, r->config, s4u_client_name, s4u_server_name, >+ s4u_client, r->server, r->krbtgt, r->client, >+ &clientkey->key, &r->ticket_key->key, &evidence_tkt, >+ &ad_kdc_issued, &s4u_pac, >+ &s4u_canon_client_name, &s4u_pac_attributes); >+ if (ret) { >+ const char *msg = krb5_get_error_message(r->context, ret); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Constrained delegation ticket PAC check failed"); >+ kdc_log(r->context, r->config, 4, >+ "Verify delegated PAC failed to %s for client" >+ "%s (%s) as %s from %s with %s", >+ r->sname, r->cname, s4usname, s4ucname, r->from, msg); >+ krb5_free_error_message(r->context, msg); >+ goto out; >+ } >+ >+ if (s4u_pac == NULL || !ad_kdc_issued) { >+ ret = KRB5KDC_ERR_BADOPTION; >+ kdc_log(r->context, r->config, 4, >+ "Ticket not signed with PAC; service %s failed for " >+ "for delegation to %s for client %s (%s) from %s; (%s).", >+ r->sname, s4ucname, s4usname, r->cname, r->from, >+ s4u_pac ? "Ticket unsigned" : "No PAC"); >+ kdc_audit_addreason((kdc_request_t)r, >+ "Constrained delegation ticket not signed"); >+ goto out; >+ } >+ >+ /* >+ * If the evidence ticket PAC didn't include PAC_UPN_DNS_INFO with >+ * the canonical client name, but the user is local to our KDC, we >+ * can insert the canonical client name ourselves. >+ */ >+ if (s4u_canon_client_name == NULL && s4u_client != NULL) { >+ ret = krb5_copy_principal(r->context, s4u_client->principal, >+ &s4u_canon_client_name); >+ if (ret) >+ goto out; >+ } >+ >+ kdc_log(r->context, r->config, 4, "constrained delegation for %s " >+ "from %s (%s) to %s", s4ucname, r->cname, s4usname, r->sname); >+ >+ /* >+ * Replace all client information in the request with the >+ * impersonated client. (The audit entry containing the original >+ * client name will have been created before this point.) >+ */ >+ _kdc_request_set_cname_nocopy((kdc_request_t)r, &s4ucname); >+ _kdc_request_set_client_princ_nocopy(r, &s4u_client_name); >+ >+ _kdc_free_ent(r->context, r->clientdb, r->client); >+ r->client = s4u_client; >+ s4u_client = NULL; >+ r->clientdb = s4u_clientdb; >+ s4u_clientdb = NULL; >+ >+ _kdc_request_set_canon_client_princ_nocopy(r, &s4u_canon_client_name); >+ _kdc_request_set_pac_nocopy(r, &s4u_pac); >+ >+ r->pac_attributes = s4u_pac_attributes; >+ >+out: >+ if (s4u_client) >+ _kdc_free_ent(r->context, s4u_clientdb, s4u_client); >+ krb5_free_principal(r->context, s4u_client_name); >+ krb5_xfree(s4ucname); >+ krb5_free_principal(r->context, s4u_server_name); >+ krb5_xfree(s4usname); >+ krb5_free_principal(r->context, s4u_canon_client_name); >+ krb5_pac_free(r->context, s4u_pac); >+ >+ free_EncTicketPart(&evidence_tkt); >+ >+ return ret; >+} >+ >+/* >+ * >+ */ >+ >+krb5_error_code >+_kdc_validate_services_for_user(astgs_request_t r) >+{ >+ krb5_error_code ret; >+ >+ ret = validate_protocol_transition(r); >+ if (ret == 0) >+ ret = validate_constrained_delegation(r); >+ >+ return ret; >+} >diff --git a/third_party/heimdal/kdc/negotiate_token_validator.c b/third_party/heimdal/kdc/negotiate_token_validator.c >index ad5db1e3ca46..20250c6dc897 100644 >--- a/third_party/heimdal/kdc/negotiate_token_validator.c >+++ b/third_party/heimdal/kdc/negotiate_token_validator.c >@@ -304,8 +304,6 @@ negotiate_get_instance(const char *libname) > { > if (strcmp(libname, "krb5") == 0) > return krb5_get_instance(libname); >- else if (strcmp(libname, "gssapi") == 0) >- return gss_get_instance(libname); > > return 0; > } >diff --git a/third_party/heimdal/kdc/pkinit.c b/third_party/heimdal/kdc/pkinit.c >index b355e4c8830b..f01178983f3c 100644 >--- a/third_party/heimdal/kdc/pkinit.c >+++ b/third_party/heimdal/kdc/pkinit.c >@@ -231,8 +231,6 @@ generate_dh_keyblock(krb5_context context, > memmove(dh_gen_key + size, dh_gen_key, dh_gen_keylen); > memset(dh_gen_key, 0, size); > } >- >- ret = 0; > } else if (client_params->keyex == USE_ECDH) { > if (client_params->u.ecdh.public_key == NULL) { > ret = KRB5KRB_ERR_GENERIC; >@@ -390,7 +388,7 @@ _kdc_pk_rd_padata(astgs_request_t priv, > krb5_context context = priv->context; > krb5_kdc_configuration *config = priv->config; > const KDC_REQ *req = &priv->req; >- hdb_entry_ex *client = priv->client; >+ hdb_entry *client = priv->client; > pk_client_params *cp; > krb5_error_code ret; > heim_oid eContentType = { 0, NULL }, contentInfoOid = { 0, NULL }; >@@ -433,7 +431,7 @@ _kdc_pk_rd_padata(astgs_request_t priv, > } > > /* Add any registered certificates for this client as trust anchors */ >- ret = hdb_entry_get_pkinit_cert(&client->entry, &pc); >+ ret = hdb_entry_get_pkinit_cert(client, &pc); > if (ret == 0 && pc != NULL) { > hx509_cert cert; > unsigned int i; >@@ -469,7 +467,7 @@ _kdc_pk_rd_padata(astgs_request_t priv, > > type = "PK-INIT-Win2k"; > >- if (_kdc_is_anonymous(context, client->entry.principal)) { >+ if (_kdc_is_anonymous(context, client->principal)) { > ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED; > krb5_set_error_message(context, ret, > "Anonymous client not supported in RSA mode"); >@@ -615,7 +613,7 @@ _kdc_pk_rd_padata(astgs_request_t priv, > hx509_certs signer_certs; > int flags = HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH; /* BTMM */ > >- if (_kdc_is_anonymous(context, client->entry.principal) >+ if (_kdc_is_anonymous(context, client->principal) > || (config->historical_anon_realm && _kdc_is_anon_request(req))) > flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER; > >@@ -701,7 +699,7 @@ _kdc_pk_rd_padata(astgs_request_t priv, > goto out; > } > >- if (_kdc_is_anonymous(context, client->entry.principal) && >+ if (_kdc_is_anonymous(context, client->principal) && > ap.clientPublicValue == NULL) { > free_AuthPack(&ap); > ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED; >@@ -1600,7 +1598,7 @@ match_ms_upn_san(krb5_context context, > hx509_context hx509ctx, > hx509_cert client_cert, > HDB *clientdb, >- hdb_entry_ex *client) >+ hdb_entry *client) > { > hx509_octet_string_list list; > krb5_principal principal = NULL; >@@ -1654,7 +1652,7 @@ match_ms_upn_san(krb5_context context, > */ > strupr(principal->realm); > >- if (krb5_principal_compare(context, principal, client->entry.principal) == FALSE) >+ if (krb5_principal_compare(context, principal, client->principal) == FALSE) > ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; > } > >@@ -1673,7 +1671,7 @@ _kdc_pk_check_client(astgs_request_t r, > { > krb5_kdc_configuration *config = r->config; > HDB *clientdb = r->clientdb; >- hdb_entry_ex *client = r->client; >+ hdb_entry *client = r->client; > const HDB_Ext_PKINIT_acl *acl; > const HDB_Ext_PKINIT_cert *pc; > krb5_error_code ret; >@@ -1681,7 +1679,7 @@ _kdc_pk_check_client(astgs_request_t r, > size_t i; > > if (cp->cert == NULL) { >- if (!_kdc_is_anonymous(r->context, client->entry.principal) >+ if (!_kdc_is_anonymous(r->context, client->principal) > && !config->historical_anon_realm) > return KRB5KDC_ERR_BADOPTION; > >@@ -1718,7 +1716,7 @@ _kdc_pk_check_client(astgs_request_t r, > "Trying to authorize PKINIT subject DN %s", > *subject_name); > >- ret = hdb_entry_get_pkinit_cert(&client->entry, &pc); >+ ret = hdb_entry_get_pkinit_cert(client, &pc); > if (ret == 0 && pc) { > hx509_cert cert; > size_t j; >@@ -1745,7 +1743,7 @@ _kdc_pk_check_client(astgs_request_t r, > ret = match_rfc_san(r->context, config, > r->context->hx509ctx, > cp->cert, >- client->entry.principal); >+ client->principal); > if (ret == 0) { > kdc_log(r->context, config, 5, > "Found matching PKINIT SAN in certificate"); >@@ -1763,7 +1761,7 @@ _kdc_pk_check_client(astgs_request_t r, > } > } > >- ret = hdb_entry_get_pkinit_acl(&client->entry, &acl); >+ ret = hdb_entry_get_pkinit_acl(client, &acl); > if (ret == 0 && acl != NULL) { > /* > * Cheat here and compare the generated name with the string >@@ -1789,7 +1787,7 @@ _kdc_pk_check_client(astgs_request_t r, > krb5_boolean b; > > b = krb5_principal_compare(r->context, >- client->entry.principal, >+ client->principal, > principal_mappings.val[i].principal); > if (b == FALSE) > continue; >@@ -1926,7 +1924,7 @@ load_mappings(krb5_context context, const char *fn) > * > */ > >-krb5_error_code >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL > krb5_kdc_pk_initialize(krb5_context context, > krb5_kdc_configuration *config, > const char *user_id, >diff --git a/third_party/heimdal/kdc/process.c b/third_party/heimdal/kdc/process.c >index 23a0fe0102d0..cf8ab060ec96 100644 >--- a/third_party/heimdal/kdc/process.c >+++ b/third_party/heimdal/kdc/process.c >@@ -42,15 +42,15 @@ > #undef __attribute__ > #define __attribute__(x) > >-void >-_kdc_audit_vaddreason(kdc_request_t r, const char *fmt, va_list ap) >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_audit_vaddreason(kdc_request_t r, const char *fmt, va_list ap) > __attribute__ ((__format__ (__printf__, 2, 0))) > { > heim_audit_vaddreason((heim_svc_req_desc)r, fmt, ap); > } > >-void >-_kdc_audit_addreason(kdc_request_t r, const char *fmt, ...) >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_audit_addreason(kdc_request_t r, const char *fmt, ...) > __attribute__ ((__format__ (__printf__, 2, 3))) > { > va_list ap; >@@ -66,16 +66,16 @@ _kdc_audit_addreason(kdc_request_t r, const char *fmt, ...) > * not a kv-pair. > */ > >-void >-_kdc_audit_vaddkv(kdc_request_t r, int flags, const char *k, >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_audit_vaddkv(kdc_request_t r, int flags, const char *k, > const char *fmt, va_list ap) > __attribute__ ((__format__ (__printf__, 4, 0))) > { > heim_audit_vaddkv((heim_svc_req_desc)r, flags, k, fmt, ap); > } > >-void >-_kdc_audit_addkv(kdc_request_t r, int flags, const char *k, >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_audit_addkv(kdc_request_t r, int flags, const char *k, > const char *fmt, ...) > __attribute__ ((__format__ (__printf__, 4, 5))) > { >@@ -86,20 +86,56 @@ _kdc_audit_addkv(kdc_request_t r, int flags, const char *k, > va_end(ap); > } > >-void >-_kdc_audit_addkv_timediff(kdc_request_t r, const char *k, >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_audit_addkv_timediff(kdc_request_t r, const char *k, > const struct timeval *start, > const struct timeval *end) > { > heim_audit_addkv_timediff((heim_svc_req_desc)r,k, start, end); > } > >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_audit_setkv_bool(kdc_request_t r, const char *k, krb5_boolean v) >+{ >+ heim_audit_setkv_bool((heim_svc_req_desc)r, k, (int)v); >+} >+ >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_audit_addkv_number(kdc_request_t r, const char *k, int64_t v) >+{ >+ heim_audit_addkv_number((heim_svc_req_desc)r, k, v); >+} >+ >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_audit_setkv_number(kdc_request_t r, const char *k, int64_t v) >+{ >+ heim_audit_setkv_number((heim_svc_req_desc)r, k, v); >+} >+ >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_audit_addkv_object(kdc_request_t r, const char *k, kdc_object_t obj) >+{ >+ heim_audit_addkv_object((heim_svc_req_desc)r, k, obj); >+} >+ >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_audit_setkv_object(kdc_request_t r, const char *k, kdc_object_t obj) >+{ >+ heim_audit_setkv_object((heim_svc_req_desc)r, k, obj); >+} >+ >+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL >+kdc_audit_getkv(kdc_request_t r, const char *k) >+{ >+ return heim_audit_getkv((heim_svc_req_desc)r, k); >+} >+ > /* > * Add up to 3 key value pairs to record HostAddresses from request body or > * PA-TGS ticket or whatever. > */ >-void >-_kdc_audit_addaddrs(kdc_request_t r, HostAddresses *a, const char *key) >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_audit_addaddrs(kdc_request_t r, HostAddresses *a, const char *key) > { > size_t i; > char buf[128]; >@@ -109,23 +145,23 @@ _kdc_audit_addaddrs(kdc_request_t r, HostAddresses *a, const char *key) > > if (snprintf(numkey, sizeof(numkey), "num%s", key) >= sizeof(numkey)) > numkey[31] = '\0'; >- _kdc_audit_addkv(r, 0, numkey, "%llu", (unsigned long long)a->len); >+ kdc_audit_addkv(r, 0, numkey, "%llu", (unsigned long long)a->len); > } > > for (i = 0; i < 3 && i < a->len; i++) { > if (krb5_print_address(&a->val[i], buf, sizeof(buf), NULL) == 0) >- _kdc_audit_addkv(r, 0, key, "%s", buf); >+ kdc_audit_addkv(r, 0, key, "%s", buf); > } > } > >-void >+KDC_LIB_FUNCTION void KDC_LIB_CALL > _kdc_audit_trail(kdc_request_t r, krb5_error_code ret) > { > const char *retname = NULL; > > /* Get a symbolic name for some error codes */ > #define CASE(x) case x : retname = #x; break >- switch (ret ? ret : r->ret) { >+ switch (ret ? ret : r->error_code) { > CASE(ENOMEM); > CASE(EACCES); > CASE(HDB_ERR_NOT_FOUND_HERE); >@@ -171,7 +207,7 @@ _kdc_audit_trail(kdc_request_t r, krb5_error_code ret) > heim_audit_trail((heim_svc_req_desc)r, ret, retname); > } > >-void >+KDC_LIB_FUNCTION void KDC_LIB_CALL > krb5_kdc_update_time(struct timeval *tv) > { > if (tv == NULL) >@@ -334,8 +370,11 @@ process_request(krb5_context context, > r->request.length = len; > r->datagram_reply = datagram_reply; > r->reply = reply; >- r->kv = heim_array_create(); >- if (!r->kv) { >+ r->kv = heim_dict_create(10); >+ r->attributes = heim_dict_create(1); >+ if (r->kv == NULL || r->attributes == NULL) { >+ heim_release(r->kv); >+ heim_release(r->attributes); > free(r); > return krb5_enomem(context); > } >@@ -361,6 +400,7 @@ process_request(krb5_context context, > > heim_release(r->reason); > heim_release(r->kv); >+ heim_release(r->attributes); > free(r); > return ret; > } >@@ -368,6 +408,7 @@ process_request(krb5_context context, > > heim_release(r->reason); > heim_release(r->kv); >+ heim_release(r->attributes); > free(r); > return -1; > } >@@ -377,7 +418,7 @@ process_request(krb5_context context, > * sending a reply in `reply'. > */ > >-int >+KDC_LIB_FUNCTION int KDC_LIB_CALL > krb5_kdc_process_request(krb5_context context, > krb5_kdc_configuration *config, > unsigned char *buf, >@@ -399,7 +440,7 @@ krb5_kdc_process_request(krb5_context context, > * This only processes krb5 requests > */ > >-int >+KDC_LIB_FUNCTION int KDC_LIB_CALL > krb5_kdc_process_krb5_request(krb5_context context, > krb5_kdc_configuration *config, > unsigned char *buf, >@@ -418,7 +459,7 @@ krb5_kdc_process_krb5_request(krb5_context context, > * > */ > >-int >+KDC_LIB_FUNCTION int KDC_LIB_CALL > krb5_kdc_save_request(krb5_context context, > const char *fn, > const unsigned char *buf, >@@ -428,56 +469,109 @@ krb5_kdc_save_request(krb5_context context, > { > krb5_storage *sp; > krb5_address a; >- int fd, ret; >+ int fd = -1; >+ int ret = 0; > uint32_t t; > krb5_data d; > > memset(&a, 0, sizeof(a)); > >- d.data = rk_UNCONST(buf); >+ d.data = rk_UNCONST(buf); /* do not free here */ > d.length = len; > t = _kdc_now.tv_sec; > >- fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600); >- if (fd < 0) { >- int saved_errno = errno; >- krb5_set_error_message(context, saved_errno, "Failed to open: %s", fn); >- return saved_errno; >- } >- >- sp = krb5_storage_from_fd(fd); >- close(fd); >- if (sp == NULL) { >- krb5_set_error_message(context, ENOMEM, "Storage failed to open fd"); >- return ENOMEM; >- } >- >- ret = krb5_sockaddr2address(context, sa, &a); >- if (ret) >- goto out; >- >- krb5_store_uint32(sp, 1); >- krb5_store_uint32(sp, t); >- krb5_store_address(sp, a); >- krb5_store_data(sp, d); >- { >+ sp = krb5_storage_emem(); >+ if (sp == NULL) >+ ret = krb5_enomem(context); >+ >+ if (ret == 0) >+ ret = krb5_sockaddr2address(context, sa, &a); >+ if (ret == 0) >+ ret = krb5_store_uint32(sp, 1); >+ if (ret == 0) >+ ret = krb5_store_uint32(sp, t); >+ if (ret == 0) >+ ret = krb5_store_address(sp, a); >+ if (ret == 0) >+ ret = krb5_store_data(sp, d); >+ d.length = 0; >+ d.data = NULL; >+ if (ret == 0) { > Der_class cl; > Der_type ty; > unsigned int tag; > ret = der_get_tag (reply->data, reply->length, > &cl, &ty, &tag, NULL); > if (ret) { >- krb5_store_uint32(sp, 0xffffffff); >- krb5_store_uint32(sp, 0xffffffff); >- } else { >- krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0)); >- krb5_store_uint32(sp, tag); >+ ret = krb5_store_uint32(sp, 0xffffffff); >+ if (ret == 0) >+ ret = krb5_store_uint32(sp, 0xffffffff); >+ } else { >+ ret = krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0)); >+ if (ret == 0) >+ ret = krb5_store_uint32(sp, tag); > } > } > >- krb5_free_address(context, &a); >-out: >+ if (ret == 0) >+ ret = krb5_storage_to_data(sp, &d); > krb5_storage_free(sp); >+ sp = NULL; >+ >+ /* >+ * We've got KDC concurrency, so we're going to try to do a single O_APPEND >+ * write(2). Hopefully we manage to write enough of the header that one >+ * can skip this request if it fails to write completely. >+ */ >+ if (ret == 0) >+ fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600); >+ if (fd < 0) >+ krb5_set_error_message(context, ret = errno, "Failed to open: %s", fn); >+ if (ret == 0) { >+ sp = krb5_storage_from_fd(fd); >+ if (sp == NULL) >+ krb5_set_error_message(context, ret = ENOMEM, >+ "Storage failed to open fd"); >+ } >+ (void) close(fd); >+ if (ret == 0) >+ ret = krb5_store_data(sp, d); >+ krb5_free_address(context, &a); >+ /* >+ * krb5_storage_free() currently always returns 0, but for FDs it sets >+ * errno to whatever close() set it to if it failed. >+ */ >+ errno = 0; >+ if (ret == 0) >+ ret = krb5_storage_free(sp); >+ else >+ (void) krb5_storage_free(sp); >+ if (ret == 0 && errno) >+ ret = errno; >+ >+ return ret; >+} > >- return 0; >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL >+kdc_request_set_attribute(kdc_request_t r, kdc_object_t key, kdc_object_t value) >+{ >+ return heim_dict_set_value(r->attributes, key, value); >+} >+ >+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL >+kdc_request_get_attribute(kdc_request_t r, kdc_object_t key) >+{ >+ return heim_dict_get_value(r->attributes, key); >+} >+ >+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL >+kdc_request_copy_attribute(kdc_request_t r, kdc_object_t key) >+{ >+ return heim_dict_copy_value(r->attributes, key); >+} >+ >+KDC_LIB_FUNCTION void KDC_LIB_CALL >+kdc_request_delete_attribute(kdc_request_t r, kdc_object_t key) >+{ >+ heim_dict_delete_key(r->attributes, key); > } >diff --git a/third_party/heimdal/kdc/set_dbinfo.c b/third_party/heimdal/kdc/set_dbinfo.c >index 93ded4ec2ae8..683eaaf7be4c 100644 >--- a/third_party/heimdal/kdc/set_dbinfo.c >+++ b/third_party/heimdal/kdc/set_dbinfo.c >@@ -64,7 +64,7 @@ add_db(krb5_context context, struct krb5_kdc_configuration *c, > return 0; > } > >-krb5_error_code >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL > krb5_kdc_set_dbinfo(krb5_context context, struct krb5_kdc_configuration *c) > { > struct hdb_dbinfo *info, *d; >diff --git a/third_party/heimdal/kdc/simple_csr_authorizer.c b/third_party/heimdal/kdc/simple_csr_authorizer.c >index 1ae9efd676cb..2300eb53299d 100644 >--- a/third_party/heimdal/kdc/simple_csr_authorizer.c >+++ b/third_party/heimdal/kdc/simple_csr_authorizer.c >@@ -157,6 +157,13 @@ string_encode(const char *in) > return s; > } > >+static void >+frees(char **s) >+{ >+ free(*s); >+ *s = NULL; >+} >+ > static KRB5_LIB_CALL krb5_error_code > authorize(void *ctx, > krb5_context context, >@@ -228,17 +235,19 @@ authorize(void *ctx, > > if ((san = string_encode(s)) == NULL || > asprintf(&p, "%s/%s/%s-%s", d, princ, prefix, san) == -1 || >- p == NULL) >+ p == NULL) { >+ free(san); > goto enomem; >+ } > ret = stat(p, &st) == -1 ? errno : 0; > free(san); > free(p); >- free(s); >- s = NULL; >+ frees(&s); > if (ret) > goto skip; > ret = hx509_request_authorize_san(csr, i); > } >+ frees(&s); > if (ret == HX509_NO_ITEM) > ret = 0; > if (ret) >@@ -251,14 +260,11 @@ authorize(void *ctx, > ret = hx509_request_get_eku(csr, i, &s); > if (ret) > break; >- if (asprintf(&p, "%s/%s/eku-%s", d, princ, s) == -1 || p == NULL) { >- free(princ); >- free(s); >- } >+ if (asprintf(&p, "%s/%s/eku-%s", d, princ, s) == -1 || p == NULL) >+ goto enomem; > ret = stat(p, &st) == -1 ? errno : 0; > free(p); >- free(s); >- s = NULL; >+ frees(&s); > if (ret) > goto skip; > ret = hx509_request_authorize_eku(csr, i); >diff --git a/third_party/heimdal/kdc/string2key.c b/third_party/heimdal/kdc/string2key.c >index 1b603dece58d..4b9c62e5a5d0 100644 >--- a/third_party/heimdal/kdc/string2key.c >+++ b/third_party/heimdal/kdc/string2key.c >@@ -128,9 +128,9 @@ main(int argc, char **argv) > if(ret) > krb5_err(context, 1, ret, "krb5_string_to_enctype"); > >- if((etype != (krb5_enctype)ETYPE_DES_CBC_CRC && >- etype != (krb5_enctype)ETYPE_DES_CBC_MD4 && >- etype != (krb5_enctype)ETYPE_DES_CBC_MD5) && >+ if((etype != ETYPE_DES_CBC_CRC && >+ etype != ETYPE_DES_CBC_MD4 && >+ etype != ETYPE_DES_CBC_MD5) && > (afs || version4)) { > if(!version5) { > etype = ETYPE_DES_CBC_CRC; >diff --git a/third_party/heimdal/kdc/test_kdc_ca.c b/third_party/heimdal/kdc/test_kdc_ca.c >index 12b873c039b7..4d80c96a034a 100644 >--- a/third_party/heimdal/kdc/test_kdc_ca.c >+++ b/third_party/heimdal/kdc/test_kdc_ca.c >@@ -137,8 +137,9 @@ main(int argc, char **argv) > if (ret == 0) > hx509_request_authorize_san(req, i); > } >- if (ret == HX509_NO_ITEM) >- ret = 0; >+ if (ret && ret != HX509_NO_ITEM) >+ krb5_err(context, 1, ret, >+ "Failed to mark requested extensions authorized"); > } else if ((ret = kdc_authorize_csr(context, app_string, req, p))) { > krb5_err(context, 1, ret, > "Requested certificate extensions rejected by policy"); >diff --git a/third_party/heimdal/kdc/token_validator.c b/third_party/heimdal/kdc/token_validator.c >index cdb50e47752c..858fdfa7b214 100644 >--- a/third_party/heimdal/kdc/token_validator.c >+++ b/third_party/heimdal/kdc/token_validator.c >@@ -78,7 +78,7 @@ static struct heim_plugin_data token_validator_data = { > * Invoke a plugin to validate a JWT/SAML/OIDC token and partially-evaluate > * access control. > */ >-krb5_error_code >+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL > kdc_validate_token(krb5_context context, > const char *realm, > const char *token_kind, >diff --git a/third_party/heimdal/kdc/version-script.map b/third_party/heimdal/kdc/version-script.map >index 4b27e6943ccc..9067bb6e43f4 100644 >--- a/third_party/heimdal/kdc/version-script.map >+++ b/third_party/heimdal/kdc/version-script.map >@@ -11,7 +11,7 @@ HEIMDAL_KDC_1.0 { > kdc_openlog; > kdc_check_flags; > kdc_validate_token; >- krb5_kdc_windc_init; >+ krb5_kdc_plugin_init; > krb5_kdc_get_config; > krb5_kdc_pkinit_config; > krb5_kdc_set_dbinfo; >@@ -20,12 +20,80 @@ HEIMDAL_KDC_1.0 { > krb5_kdc_save_request; > krb5_kdc_update_time; > krb5_kdc_pk_initialize; >- _kdc_audit_addkv; >- _kdc_audit_addreason; >- _kdc_audit_vaddkv; >- _kdc_audit_vaddreason; >+ kdc_request_set_attribute; >+ kdc_request_get_attribute; >+ kdc_request_copy_attribute; >+ kdc_request_delete_attribute; >+ kdc_request_add_encrypted_padata; >+ kdc_request_add_pac_buffer; >+ kdc_request_add_reply_padata; >+ kdc_request_get_addr; >+ kdc_request_get_canon_client_princ; >+ kdc_request_get_client; >+ kdc_request_get_clientdb; >+ kdc_request_get_client_princ; >+ kdc_request_get_context; >+ kdc_request_get_config; >+ kdc_request_get_cname; >+ kdc_request_get_error_code; >+ kdc_request_get_from; >+ kdc_request_get_krbtgt; >+ kdc_request_get_krbtgtdb; >+ kdc_request_get_krbtgt_princ; >+ kdc_request_get_pac; >+ kdc_request_get_pac_attributes; >+ kdc_request_get_rep; >+ kdc_request_get_reply_key; >+ kdc_request_get_req; >+ kdc_request_get_request; >+ kdc_request_get_server; >+ kdc_request_get_serverdb; >+ kdc_request_get_server_princ; >+ kdc_request_get_sname; >+ kdc_request_get_ticket; >+ kdc_request_get_tv_end; >+ kdc_request_get_tv_start; >+ kdc_request_set_canon_client_princ; >+ kdc_request_set_client_princ; >+ kdc_request_set_cname; >+ kdc_request_set_error_code; >+ kdc_request_set_krbtgt_princ; >+ kdc_request_set_pac; >+ kdc_request_set_pac_attributes; >+ kdc_request_set_rep; >+ kdc_request_set_reply_key; >+ kdc_request_set_server_princ; >+ kdc_request_set_sname; >+ kdc_audit_addkv; >+ kdc_audit_addkv_number; >+ kdc_audit_addkv_object; >+ kdc_audit_addkv_timediff; >+ kdc_audit_addaddrs; >+ kdc_audit_addreason; >+ kdc_audit_getkv; >+ kdc_audit_setkv_bool; >+ kdc_audit_setkv_number; >+ kdc_audit_setkv_object; >+ kdc_audit_vaddkv; >+ kdc_audit_vaddreason; > _kdc_audit_trail; > >+ kdc_object_alloc; >+ kdc_object_retain; >+ kdc_object_release; >+ kdc_bool_create; >+ kdc_bool_get_value; >+ kdc_array_iterate; >+ kdc_array_get_length; >+ kdc_array_get_value; >+ kdc_array_copy_value; >+ kdc_string_create; >+ kdc_string_get_utf8; >+ kdc_data_create; >+ kdc_data_get_data; >+ kdc_number_create; >+ kdc_number_get_value; >+ > # needed for digest-service > _kdc_db_fetch; > _kdc_free_ent; >diff --git a/third_party/heimdal/kdc/windc.c b/third_party/heimdal/kdc/windc.c >deleted file mode 100644 >index eb834cd6cfdd..000000000000 >--- a/third_party/heimdal/kdc/windc.c >+++ /dev/null >@@ -1,252 +0,0 @@ >-/* >- * Copyright (c) 2007 Kungliga Tekniska Högskolan >- * (Royal Institute of Technology, Stockholm, Sweden). >- * All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * 3. Neither the name of the Institute nor the names of its contributors >- * may be used to endorse or promote products derived from this software >- * without specific prior written permission. >- * >- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND >- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE >- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >- * SUCH DAMAGE. >- */ >- >-#include "kdc_locl.h" >- >-static int have_plugin = 0; >- >-/* >- * Pick the first WINDC module that we find. >- */ >- >-static const char *windc_plugin_deps[] = { >- "kdc", >- "krb5", >- "hdb", >- NULL >-}; >- >-static struct heim_plugin_data windc_plugin_data = { >- "krb5", >- "windc", >- KRB5_WINDC_PLUGIN_MINOR, >- windc_plugin_deps, >- kdc_get_instance >-}; >- >-static krb5_error_code KRB5_LIB_CALL >-load(krb5_context context, const void *plug, void *plugctx, void *userctx) >-{ >- have_plugin = 1; >- return KRB5_PLUGIN_NO_HANDLE; >-} >- >-krb5_error_code >-krb5_kdc_windc_init(krb5_context context) >-{ >- (void)_krb5_plugin_run_f(context, &windc_plugin_data, 0, NULL, load); >- >- return 0; >-} >- >-struct generate_uc { >- hdb_entry_ex *client; >- hdb_entry_ex *server; >- const krb5_keyblock *reply_key; >- uint64_t pac_attributes; >- krb5_pac *pac; >-}; >- >-static krb5_error_code KRB5_LIB_CALL >-generate(krb5_context context, const void *plug, void *plugctx, void *userctx) >-{ >- krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug; >- struct generate_uc *uc = (struct generate_uc *)userctx; >- >- if (ft->pac_generate == NULL) >- return KRB5_PLUGIN_NO_HANDLE; >- >- return ft->pac_generate((void *)plug, context, >- uc->client, >- uc->server, >- uc->reply_key, >- uc->pac_attributes, >- uc->pac); >-} >- >- >-krb5_error_code >-_kdc_pac_generate(krb5_context context, >- hdb_entry_ex *client, >- hdb_entry_ex *server, >- const krb5_keyblock *reply_key, >- uint64_t pac_attributes, >- krb5_pac *pac) >-{ >- krb5_error_code ret = 0; >- struct generate_uc uc; >- >- *pac = NULL; >- >- if (krb5_config_get_bool_default(context, NULL, FALSE, "realms", >- client->entry.principal->realm, >- "disable_pac", NULL)) >- return 0; >- >- if (have_plugin) { >- uc.client = client; >- uc.server = server; >- uc.reply_key = reply_key; >- uc.pac = pac; >- uc.pac_attributes = pac_attributes; >- >- ret = _krb5_plugin_run_f(context, &windc_plugin_data, >- 0, &uc, generate); >- if (ret != KRB5_PLUGIN_NO_HANDLE) >- return ret; >- ret = 0; >- } >- >- if (*pac == NULL) >- ret = krb5_pac_init(context, pac); >- >- return ret; >-} >- >-struct verify_uc { >- krb5_principal client_principal; >- krb5_principal delegated_proxy_principal; >- hdb_entry_ex *client; >- hdb_entry_ex *server; >- hdb_entry_ex *krbtgt; >- krb5_pac *pac; >-}; >- >-static krb5_error_code KRB5_LIB_CALL >-verify(krb5_context context, const void *plug, void *plugctx, void *userctx) >-{ >- krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug; >- struct verify_uc *uc = (struct verify_uc *)userctx; >- krb5_error_code ret; >- >- if (ft->pac_verify == NULL) >- return KRB5_PLUGIN_NO_HANDLE; >- >- ret = ft->pac_verify((void *)plug, context, >- uc->client_principal, >- uc->delegated_proxy_principal, >- uc->client, uc->server, uc->krbtgt, uc->pac); >- return ret; >-} >- >-krb5_error_code >-_kdc_pac_verify(krb5_context context, >- const krb5_principal client_principal, >- const krb5_principal delegated_proxy_principal, >- hdb_entry_ex *client, >- hdb_entry_ex *server, >- hdb_entry_ex *krbtgt, >- krb5_pac *pac) >-{ >- struct verify_uc uc; >- >- if (!have_plugin) >- return KRB5_PLUGIN_NO_HANDLE; >- >- uc.client_principal = client_principal; >- uc.delegated_proxy_principal = delegated_proxy_principal; >- uc.client = client; >- uc.server = server; >- uc.krbtgt = krbtgt; >- uc.pac = pac; >- >- return _krb5_plugin_run_f(context, &windc_plugin_data, >- 0, &uc, verify); >-} >- >-static krb5_error_code KRB5_LIB_CALL >-check(krb5_context context, const void *plug, void *plugctx, void *userctx) >-{ >- krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug; >- >- if (ft->client_access == NULL) >- return KRB5_PLUGIN_NO_HANDLE; >- return ft->client_access((void *)plug, userctx); >-} >- >-krb5_error_code >-_kdc_check_access(astgs_request_t r) >-{ >- krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE; >- >- if (have_plugin) { >- ret = _krb5_plugin_run_f(r->context, &windc_plugin_data, >- 0, r, check); >- } >- >- if (ret == KRB5_PLUGIN_NO_HANDLE) >- return kdc_check_flags(r, r->req.msg_type == krb_as_req, >- r->client, r->server); >- return ret; >-} >- >-static krb5_error_code KRB5_LIB_CALL >-finalize(krb5_context context, const void *plug, void *plugctx, void *userctx) >-{ >- krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug; >- >- if (ft->finalize_reply == NULL) >- return KRB5_PLUGIN_NO_HANDLE; >- return ft->finalize_reply((void *)plug, (astgs_request_t)userctx); >-} >- >-krb5_error_code >-_kdc_finalize_reply(astgs_request_t r) >-{ >- krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE; >- >- if (have_plugin) >- ret = _krb5_plugin_run_f(r->context, &windc_plugin_data, 0, r, finalize); >- >- if (ret == KRB5_PLUGIN_NO_HANDLE) >- ret = 0; >- >- return ret; >-} >- >-uintptr_t KRB5_CALLCONV >-kdc_get_instance(const char *libname) >-{ >- static const char *instance = "libkdc"; >- >- if (strcmp(libname, "kdc") == 0) >- return (uintptr_t)instance; >- else if (strcmp(libname, "hdb") == 0) >- return hdb_get_instance(libname); >- else if (strcmp(libname, "krb5") == 0) >- return krb5_get_instance(libname); >- else if (strcmp(libname, "gssapi") == 0) >- return gss_get_instance(libname); >- >- return 0; >-} >diff --git a/third_party/heimdal/kdc/windc_plugin.h b/third_party/heimdal/kdc/windc_plugin.h >deleted file mode 100644 >index ae0c6d181ea3..000000000000 >--- a/third_party/heimdal/kdc/windc_plugin.h >+++ /dev/null >@@ -1,92 +0,0 @@ >-/* >- * Copyright (c) 2006 Kungliga Tekniska Högskolan >- * (Royal Institute of Technology, Stockholm, Sweden). >- * All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * 3. Neither the name of the Institute nor the names of its contributors >- * may be used to endorse or promote products derived from this software >- * without specific prior written permission. >- * >- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND >- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE >- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >- * SUCH DAMAGE. >- */ >- >-/* $Id$ */ >- >-#ifndef HEIMDAL_KDC_WINDC_PLUGIN_H >-#define HEIMDAL_KDC_WINDC_PLUGIN_H 1 >- >-#include <krb5.h> >-#include <kdc.h> >- >-/* >- * The PAC generate function should allocate a krb5_pac using >- * krb5_pac_init and fill in the PAC structure for the principal using >- * krb5_pac_add_buffer. >- * >- * The PAC verify function should verify the PAC KDC signatures by fetching >- * the right KDC key and calling krb5_pac_verify() with that KDC key. >- * Optionally, update the PAC buffers upon success. >- * >- * Check client access function check if the client is authorized. >- */ >- >-struct hdb_entry_ex; >- >-typedef krb5_error_code >-(KRB5_CALLCONV *krb5plugin_windc_pac_generate)(void *, krb5_context, >- struct hdb_entry_ex *, /* client */ >- struct hdb_entry_ex *, /* server */ >- const krb5_keyblock *, /* pk_replykey */ >- uint64_t, /* pac_attributes */ >- krb5_pac *); >- >-typedef krb5_error_code >-(KRB5_CALLCONV *krb5plugin_windc_pac_verify)(void *, krb5_context, >- const krb5_principal, /* new ticket client */ >- const krb5_principal, /* delegation proxy */ >- struct hdb_entry_ex *,/* client */ >- struct hdb_entry_ex *,/* server */ >- struct hdb_entry_ex *,/* krbtgt */ >- krb5_pac *); >- >-typedef krb5_error_code >-(KRB5_CALLCONV *krb5plugin_windc_client_access)(void *, astgs_request_t); >- >-typedef krb5_error_code >-(KRB5_CALLCONV *krb5plugin_windc_finalize_reply)(void *, astgs_request_t r); >- >-#define KRB5_WINDC_PLUGIN_MINOR 8 >-#define KRB5_WINDC_PLUGING_MINOR KRB5_WINDC_PLUGIN_MINOR >- >-typedef struct krb5plugin_windc_ftable { >- int minor_version; >- krb5_error_code (KRB5_CALLCONV *init)(krb5_context, void **); >- void (KRB5_CALLCONV *fini)(void *); >- krb5plugin_windc_pac_generate pac_generate; >- krb5plugin_windc_pac_verify pac_verify; >- krb5plugin_windc_client_access client_access; >- krb5plugin_windc_finalize_reply finalize_reply; >-} krb5plugin_windc_ftable; >- >-#endif /* HEIMDAL_KDC_WINDC_PLUGIN_H */ >diff --git a/third_party/heimdal/kpasswd/kpasswdd.c b/third_party/heimdal/kpasswd/kpasswdd.c >index 344688e296e0..e04eebe46e1f 100644 >--- a/third_party/heimdal/kpasswd/kpasswdd.c >+++ b/third_party/heimdal/kpasswd/kpasswdd.c >@@ -406,6 +406,7 @@ change (krb5_auth_context auth_context, > krb5_warnx(context, > "%s didn't pass password quality check with error: %s", > client, str); >+ break; > default: > krb5_warnx(context, "kadm5_s_chpass_principal_cond: %s", str); > } >@@ -772,6 +773,7 @@ doit(krb5_keytab keytab, int port) > free(sockets); > > krb5_free_addresses(context, &addrs); >+ krb5_kt_close(context, keytab); > krb5_free_context(context); > return 0; > } >diff --git a/third_party/heimdal/kuser/generate-requests.c b/third_party/heimdal/kuser/generate-requests.c >index 1196c16dc679..2dd71bf7ab8a 100644 >--- a/third_party/heimdal/kuser/generate-requests.c >+++ b/third_party/heimdal/kuser/generate-requests.c >@@ -49,7 +49,7 @@ read_words (const char *filename, char ***ret_w) > buf[strcspn(buf, "\r\n")] = '\0'; > if (n >= alloc) { > alloc += 16; >- w = erealloc (w, alloc * sizeof(char **)); >+ w = erealloc (w, alloc * sizeof(*w)); > } > w[n++] = estrdup (buf); > } >diff --git a/third_party/heimdal/kuser/kgetcred.c b/third_party/heimdal/kuser/kgetcred.c >index 92eb770990c5..4982f8a796a8 100644 >--- a/third_party/heimdal/kuser/kgetcred.c >+++ b/third_party/heimdal/kuser/kgetcred.c >@@ -283,6 +283,9 @@ main(int argc, char **argv) > > ret = krb5_sname_to_principal(context, hname, sname, > KRB5_NT_SRV_HST, &server2); >+ if (ret) >+ krb5_err(context, 1, ret, "krb5_sname_to_principal %s %s", >+ sname, hname); > sname = krb5_principal_get_comp_string(context, server2, 0); > hname = krb5_principal_get_comp_string(context, server2, 1); > >diff --git a/third_party/heimdal/kuser/kimpersonate.c b/third_party/heimdal/kuser/kimpersonate.c >index 04a16fb6ade6..35b4295fb36d 100644 >--- a/third_party/heimdal/kuser/kimpersonate.c >+++ b/third_party/heimdal/kuser/kimpersonate.c >@@ -82,9 +82,7 @@ encode_ticket(krb5_context context, > et.flags = cred->flags.b; > et.key = cred->session; > et.crealm = cred->client->realm; >- ret = copy_PrincipalName(&cred->client->name, &et.cname); >- if (ret) >- krb5_err(context, 1, ret, "copy_PrincipalName"); >+ et.cname = cred->client->name; > { > krb5_data empty_string; > >@@ -129,16 +127,11 @@ encode_ticket(krb5_context context, > > ticket.tkt_vno = 5; > ticket.realm = cred->server->realm; >- ret = copy_PrincipalName(&cred->server->name, &ticket.sname); >- if (ret) >- krb5_err(context, 1, ret, "copy_PrincipalName"); >- >- ASN1_MALLOC_ENCODE(Ticket, buf, len, &ticket, &size, ret); >+ ticket.sname = cred->server->name; >+ ASN1_MALLOC_ENCODE(Ticket, cred->ticket.data, cred->ticket.length, &ticket, &size, ret); >+ free_EncryptedData(&ticket.enc_part); > if(ret) > krb5_err(context, 1, ret, "encode_Ticket"); >- >- krb5_data_copy(&cred->ticket, buf, len); >- free(buf); > } > > /* >@@ -173,12 +166,13 @@ create_krb5_tickets(krb5_context context, krb5_keytab kt) > > > ret = krb5_copy_principal(context, client_principal, &cred.client); >+ if (ret == 0) >+ ret = krb5_copy_principal(context, server_principal, &cred.server); > if (ret) > krb5_err(context, 1, ret, "krb5_copy_principal"); >- ret = krb5_copy_principal(context, server_principal, &cred.server); >+ ret = krb5_generate_random_keyblock(context, session_etype, &cred.session); > if (ret) >- krb5_err(context, 1, ret, "krb5_copy_principal"); >- krb5_generate_random_keyblock(context, session_etype, &cred.session); >+ krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); > > cred.times.authtime = time(NULL); > cred.times.starttime = time(NULL); >@@ -283,13 +277,13 @@ setup_env(krb5_context context, krb5_keytab *kt) > krb5_errx(context, 1, "missing client principal"); > ret = krb5_parse_name(context, client_principal_str, &client_principal); > if (ret) >- krb5_err(context, 1, ret, "resolvning client name"); >+ krb5_err(context, 1, ret, "resolving client name"); > > if (server_principal_str == NULL) > krb5_errx(context, 1, "missing server principal"); > ret = krb5_parse_name(context, server_principal_str, &server_principal); > if (ret) >- krb5_err(context, 1, ret, "resolvning server name"); >+ krb5_err(context, 1, ret, "resolving server name"); > > /* If no session-enc-type specified on command line and this is an afs */ > /* service ticket, change default of session_enc_type to DES. */ >@@ -395,6 +389,7 @@ main(int argc, char **argv) > create_krb5_tickets(context, kt); > > krb5_kt_close(context, kt); >+ krb5_free_context(context); > > return 0; > } >diff --git a/third_party/heimdal/kuser/kinit.c b/third_party/heimdal/kuser/kinit.c >index 0b22e7150950..6ac4b45426a9 100644 >--- a/third_party/heimdal/kuser/kinit.c >+++ b/third_party/heimdal/kuser/kinit.c >@@ -34,6 +34,8 @@ > */ > > #include "kuser_locl.h" >+#undef HC_DEPRECATED_CRYPTO >+#include <krb5_locl.h> > > #ifdef HAVE_FRAMEWORK_SECURITY > #include <Security/Security.h> >@@ -78,7 +80,7 @@ int pk_enterprise_flag = 0; > struct hx509_certs_data *ent_user_id = NULL; > char *pk_x509_anchors = NULL; > int pk_use_enckey = 0; >-int pk_anon_fast_armor = 0; >+int pk_anon_fast_armor = -1; > char *gss_preauth_mech = NULL; > char *gss_preauth_name = NULL; > char *kdc_hostname = NULL; >@@ -500,7 +502,7 @@ renew_validate(krb5_context context, > * no need to check the error here, it's only to be > * friendly to the user > */ >- krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out); >+ (void) krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out); > } > > flags.i = 0; >@@ -828,6 +830,8 @@ get_new_tickets(krb5_context context, > if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag) > krb5_get_init_creds_opt_set_win2k(context, opt, TRUE); > if (pk_user_id || ent_user_id || anonymous_pkinit) { >+ if (pk_anon_fast_armor == -1) >+ pk_anon_fast_armor = 0; > ret = krb5_get_init_creds_opt_set_pkinit(context, opt, > principal, > pk_user_id, >@@ -936,13 +940,22 @@ get_new_tickets(krb5_context context, > } > } > >+ if (anonymous_flag && pk_anon_fast_armor == -1) >+ pk_anon_fast_armor = 0; >+ if (!gss_preauth_mech && anonymous_flag && pk_anon_fast_armor) { >+ krb5_warnx(context, N_("Ignoring --pk-anon-fast-armor because " >+ "--anonymous given", "")); >+ pk_anon_fast_armor = 0; >+ } >+ > if (fast_armor_cache_string) { > krb5_ccache fastid = NULL; > >- if (pk_anon_fast_armor) >+ if (pk_anon_fast_armor > 0) > krb5_errx(context, 1, > N_("cannot specify FAST armor cache with FAST " > "anonymous PKINIT option", "")); >+ pk_anon_fast_armor = 0; > > ret = krb5_cc_resolve(context, fast_armor_cache_string, &fastid); > if (ret) { >@@ -955,6 +968,12 @@ get_new_tickets(krb5_context context, > krb5_warn(context, ret, "krb5_init_creds_set_fast_ccache"); > goto out; > } >+ } else if (pk_anon_fast_armor == -1) { >+ ret = _krb5_init_creds_set_fast_anon_pkinit_optimistic(context, ctx); >+ if (ret) { >+ krb5_warn(context, ret, "_krb5_init_creds_set_fast_anon_pkinit_optimistic"); >+ goto out; >+ } > } else if (pk_anon_fast_armor) { > ret = krb5_init_creds_set_fast_anon_pkinit(context, ctx); > if (ret) { >@@ -1659,6 +1678,10 @@ main(int argc, char **argv) > krb5_err(context, 1, ret, "krb5_pk_enterprise_certs"); > > pk_user_id = NULL; >+ if (pk_anon_fast_armor > 0) >+ krb5_warnx(context, N_("Ignoring --pk-anon-fast-armor " >+ "because --pk-user given", "")); >+ pk_anon_fast_armor = 0; > } else if (argc && argv[0][0] == '@' && > (gss_preauth_mech || anonymous_flag)) { > const char *instance; >@@ -1673,6 +1696,11 @@ main(int argc, char **argv) > ret = make_wellknown_name(context, &argv[0][1], instance, &principal); > if (ret) > krb5_err(context, 1, ret, "make_wellknown_name"); >+ if (!gss_preauth_mech && pk_anon_fast_armor > 1) { >+ krb5_warnx(context, N_("Ignoring --pk-anon-fast-armor " >+ "because --anonymous given", "")); >+ pk_anon_fast_armor = 0; >+ } > } else if (anonymous_flag && historical_anon_pkinit) { > char *realm = argc == 0 ? get_default_realm(context) : > argv[0][0] == '@' ? &argv[0][1] : argv[0]; >diff --git a/third_party/heimdal/kuser/klist.c b/third_party/heimdal/kuser/klist.c >index 5dbabcaad85e..b33c3c28a7aa 100644 >--- a/third_party/heimdal/kuser/klist.c >+++ b/third_party/heimdal/kuser/klist.c >@@ -362,7 +362,6 @@ print_tickets(krb5_context context, > if (ret) > krb5_err(context, 1, ret, "krb5_cc_end_seq_get"); > >- print_comma = 0; > if(!do_verbose) { > rtbl_format(ct, stdout); > rtbl_destroy(ct); >@@ -523,16 +522,16 @@ static int > list_caches(krb5_context context, struct klist_options *opt) > { > krb5_cccol_cursor cursor; >- const char *cdef_name; >+ const char *cdef_name = krb5_cc_default_name(context); > char *def_name; > krb5_error_code ret; > krb5_ccache id; > rtbl_t ct; > >- cdef_name = krb5_cc_default_name(context); >- if (cdef_name == NULL) >- krb5_errx(context, 1, "krb5_cc_default_name"); >- def_name = strdup(cdef_name); >+ if ((def_name = krb5_cccol_get_default_ccname(context)) == NULL) >+ cdef_name = krb5_cc_default_name(context); >+ if (!def_name && cdef_name && (def_name = strdup(cdef_name)) == NULL) >+ krb5_err(context, 1, ENOMEM, "Out of memory"); > > ret = krb5_cccol_cursor_new(context, &cursor); > if (ret == KRB5_CC_NOSUPP) { >@@ -554,7 +553,7 @@ list_caches(krb5_context context, struct klist_options *opt) > if (opt->json_flag) > rtbl_set_flags(ct, RTBL_JSON); > >- while (krb5_cccol_cursor_next(context, cursor, &id) == 0) { >+ while (krb5_cccol_cursor_next(context, cursor, &id) == 0 && id != NULL) { > int expired = 0; > char *name; > time_t t; >@@ -582,7 +581,7 @@ list_caches(krb5_context context, struct klist_options *opt) > rtbl_add_column_entry(ct, COL_CACHENAME, fname); > if (opt->json_flag) > ; >- else if (strcmp(fname, def_name) == 0) >+ else if (def_name && strcmp(fname, def_name) == 0) > rtbl_add_column_entry(ct, COL_DEFCACHE, "*"); > else > rtbl_add_column_entry(ct, COL_DEFCACHE, ""); >diff --git a/third_party/heimdal/kuser/kswitch.c b/third_party/heimdal/kuser/kswitch.c >index d897a8e74513..3bb3b700dbd1 100644 >--- a/third_party/heimdal/kuser/kswitch.c >+++ b/third_party/heimdal/kuser/kswitch.c >@@ -86,16 +86,17 @@ kswitch(struct kswitch_options *opt, int argc, char **argv) > krb5_err(heimtools_context, 1, ret, "krb5_cc_cache_get_first"); > > while (krb5_cc_cache_next(heimtools_context, cursor, &id) == 0) { >- krb5_principal p; >+ krb5_principal p = NULL; > char num[10]; > > ret = krb5_cc_get_principal(heimtools_context, id, &p); >+ if (ret == 0) >+ ret = krb5_unparse_name(heimtools_context, p, &name); > if (ret) { > krb5_cc_close(heimtools_context, id); > continue; > } > >- ret = krb5_unparse_name(heimtools_context, p, &name); > krb5_free_principal(heimtools_context, p); > > snprintf(num, sizeof(num), "%d", (int)(len + 1)); >diff --git a/third_party/heimdal/kuser/kuser_locl.h b/third_party/heimdal/kuser/kuser_locl.h >index 8218a6f096fd..b1a097a8d6f7 100644 >--- a/third_party/heimdal/kuser/kuser_locl.h >+++ b/third_party/heimdal/kuser/kuser_locl.h >@@ -97,11 +97,15 @@ > > #ifdef LIBINTL > #include <libintl.h> >+#undef N_ > #define N_(x,y) gettext(x) >+#undef NP_ > #define NP_(x,y) (x) > #define getarg_i18n gettext > #else >+#undef N_ > #define N_(x,y) (x) >+#undef NP_ > #define NP_(x,y) (x) > #define getarg_i18n NULL > #define bindtextdomain(package, localedir) >diff --git a/third_party/heimdal/lib/asn1/MANUAL.md b/third_party/heimdal/lib/asn1/MANUAL.md >new file mode 100644 >index 000000000000..89c452a031c0 >--- /dev/null >+++ b/third_party/heimdal/lib/asn1/MANUAL.md >@@ -0,0 +1,1287 @@ >+# Introduction >+ >+Heimdal is an implementation of PKIX and Kerberos. As such it must handle the >+use of [Abstract Syntax Notation One (ASN.1)](https://www.itu.int/rec/T-REC-X.680-X.693-202102-I/en) >+by those protocols. ASN.1 is a language for describing the schemata of network >+protocol messages. Associated with ASN.1 are the ASN.1 Encoding Rules (ERs) >+that specify how to encode such messages. >+ >+In short: >+ >+ - ASN.1 is just a _schema description language_ >+ >+ - ASN.1 Encoding Rules are specifications for encoding formats for values of >+ types described by ASN.1 schemas ("modules") >+ >+Similar languages include: >+ >+ - [DCE RPC's Interface Description Language (IDL)](https://pubs.opengroup.org/onlinepubs/9629399/chap4.htm#tagcjh_08) >+ - [Microsoft Interface Description Language (IDL)](https://docs.microsoft.com/en-us/windows/win32/midl/midl-start-page) >+ (MIDL is derived from the DCE RPC IDL) >+ - ONC RPC's eXternal Data Representation (XDR) [RFC4506](https://datatracker.ietf.org/doc/html/rfc4506) >+ - [XML Schema](https://en.wikipedia.org/wiki/XML_schema) >+ - Various JSON schema languages >+ - [Protocol Buffers](https://developers.google.com/protocol-buffers) >+ - and [many, many others](https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats)! >+ Many are not even listed there. >+ >+Similar encoding rules include: >+ >+ - DCE RPC's [NDR](https://pubs.opengroup.org/onlinepubs/9629399/chap14.htm) >+ - ONC RPC's [XDR](https://datatracker.ietf.org/doc/html/rfc4506) >+ - XML >+ - FastInfoSet >+ - JSON >+ - CBOR >+ - [Protocol Buffers](https://developers.google.com/protocol-buffers) >+ - [Flat Buffers](https://google.github.io/flatbuffers/) >+ - and [many, many others](https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats)! >+ Many are not even listed there. >+ >+Many such languages are quite old. ASN.1 itself dates to the early 1980s, with >+the first specification published in 1984. XDR was first published in 1987. >+IDL's lineage dates back to sometime during the 1980s, via the Apollo Domain >+operating system. >+ >+ASN.1 is standardized by the International Telecommunications Union (ITU-T), >+and has continued evolving over the years, with frequent updates. >+ >+The two most useful and transcending features of ASN.1 are: >+ >+ - the ability to formally express what some know as "open types", "typed >+ holes", or "references"; >+ >+ - the ability to add encoding rules over type, which for ASN.1 includes: >+ >+ - binary, tag-length-value (TLV) encoding rules >+ - binary, non-TLV encoding rules >+ - textual encoding rules using XML and JSON >+ - an ad-hoc generic text-based ER called GSER >+ >+ In principle ASN.1 can add encoding rules that would allow it to >+ interoperate with many others, such as: CBOR, protocol buffers, flat >+ buffers, NDR, and others. >+ >+ Readers may recognize that some alternatives to ASN.1 have followed a >+ similar arc. For example, Protocol Buffers was originally a syntax and >+ encoding, and has become a syntax and set of various encodings (e.g., Flat >+ Buffers was added later). And XML has FastInfoSet as a binary encoding >+ alternative to XML's textual encoding. >+ >+As well, ASN.1 has [high-quality, freely-available specifications](https://www.itu.int/rec/T-REC-X.680-X.693-202102-I/en). >+ >+## ASN.1 Example >+ >+For example, this is a `Certificate` as used in TLS and other protocols, taken >+from [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280): >+ >+ ```ASN.1 >+ Certificate ::= SEQUENCE { >+ tbsCertificate TBSCertificate, >+ signatureAlgorithm AlgorithmIdentifier, >+ signatureValue BIT STRING >+ } >+ >+ TBSCertificate ::= SEQUENCE { >+ version [0] EXPLICIT Version DEFAULT v1, >+ serialNumber CertificateSerialNumber, >+ signature AlgorithmIdentifier, >+ issuer Name, >+ validity Validity, >+ subject Name, >+ subjectPublicKeyInfo SubjectPublicKeyInfo, >+ issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, >+ subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, >+ extensions [3] EXPLICIT Extensions OPTIONAL >+ } >+ ``` >+ >+and the same `Certificate` taken from a more modern version -from >+[RFC5912](https://datatracker.ietf.org/doc/html/rfc5912)- using newer features >+of ASN.1: >+ >+ ```ASN.1 >+ Certificate ::= SIGNED{TBSCertificate} >+ >+ TBSCertificate ::= SEQUENCE { >+ version [0] Version DEFAULT v1, >+ serialNumber CertificateSerialNumber, >+ signature AlgorithmIdentifier{SIGNATURE-ALGORITHM, >+ {SignatureAlgorithms}}, >+ issuer Name, >+ validity Validity, >+ subject Name, >+ subjectPublicKeyInfo SubjectPublicKeyInfo, >+ ... , >+ [[2: >+ issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, >+ subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL >+ ]], >+ [[3: >+ extensions [3] Extensions{{CertExtensions}} OPTIONAL >+ ]], ... >+ } >+ ``` >+ >+As you can see, a `Certificate` is a structure containing a to-be-signed >+sub-structure, and a signature of that sub-structure, and the sub-structure >+has: a version number, a serial number, a signature algorithm, an issuer name, >+a validity period, a subject name, a public key for the subject name, "unique >+identifiers" for the issuer and subject entities, and "extensions". >+ >+To understand more we'd have to look at the types of those fields of >+`TBSCertificate`, but for now we won't do that. The point here is to show that >+ASN.1 allows us to describe "types" of data in a way that resembles >+"structures", "records", or "classes" in various programming languages. >+ >+To be sure, there are some "noisy" artifacts in the definition of >+`TBSCertificate` which mostly have to do with the original encoding rules for >+ASN.1. The original encoding rules for ASN.1 were tag-length-value (TLV) >+binary encodings, meaning that for every type, the encoding of a value of that >+type consisted of a _tag_, a _length_ of the value's encoding, and the _actual >+value's encoding_. Over time other encoding rules were added that do not >+require tags, such as the octet encoding rules (OER), but also JSON encoding >+rules (JER), XML encoding rules (XER), and others. There is almost no need for >+tagging directives like `[1] IMPLICIT` when using OER. But in existing >+protocols like PKIX and Kerberos that date back to the days when DER was king, >+tagging directives are unfortunately commonplace. >+ >+## ASN.1 Crash Course >+ >+This is not a specification. Readers should refer to the ITU-T's X.680 base >+specification for ASN.1's syntax. >+ >+A schema is called a "module". >+ >+A module looks like: >+ >+```ASN.1 >+-- This is a comment >+ >+-- Here's the name of the module, here given as an "object identifier" or >+-- OID: >+PKIXAlgs-2009 { iso(1) identified-organization(3) dod(6) >+ internet(1) security(5) mechanisms(5) pkix(7) id-mod(0) >+ id-mod-pkix1-algorithms2008-02(56) } >+ >+ >+-- `DEFINITIONS` is a required keyword >+-- `EXPLICIT TAGS` will be explained later >+DEFINITIONS EXPLICIT TAGS ::= >+BEGIN >+-- list exported types, or `ALL`: >+EXPORTS ALL; >+-- import some types: >+IMPORTS PUBLIC-KEY, SIGNATURE-ALGORITHM, ... FROM AlgorithmInformation-2009 >+ mda-sha224, mda-sha256, ... FROM PKIX1-PSS-OAEP-Algorithms-2009; >+ >+-- type definitions follow: >+... >+ >+END >+``` >+ >+Type names start with capital upper-case letters. Value names start with >+lower-case letters. >+ >+Type definitions are of the form `TypeName ::= TypeDefinition`. >+ >+Value (constant) definitions are of the form `valueName ::= TypeName <literal>`. >+ >+There are some "universal" primitive types (e.g., string types, numeric types), >+and several "constructed" types (arrays, structures. >+ >+Some useful primitive types include `BOOLEAN`, `INTEGER` and `UTF8String`. >+ >+Structures are either `SEQUENCE { ... }` or `SET { ... }`. The "fields" of >+these are known as "members". >+ >+Arrays are either `SEQUENCE OF SomeType` or `SET OF SomeType`. >+ >+A `SEQUENCE`'s elements or members are ordered, while a `SET`'s are not. In >+practice this means that for _canonical_ encoding rules a `SET OF` type's >+values must be sorted, while a `SET { ... }` type's members need not be sorted >+at run-time, but are sorted by _tag_ at compile-time. >+ >+Anonymous types are supported, such as `SET OF SET { a A, b B }` (which is a >+set of structures with an `a` field (member) of type `A` and a `b` member of >+type `B`). >+ >+The members of structures can be `OPTIONAL` or have a `DEFAULT` value. >+ >+There are also discriminated union types known as `CHOICE`s: `U ::= CHOICE { a >+A, b B, c C }` (in this case `U` is either an `A`, a `B`, or a `C`. >+ >+Extensibility is supported. "Extensibility" means: the ability to add new >+members to structures, new alternatives to discriminated unions, etc. For >+example, `A ::= SEQUENCE { a0 A0, a1 A1, ... }` means that type `A` is a >+structure that has two fields and which may have more fields added in future >+revisions, therefore decoders _must_ be able to receive and decode encodings of >+extended versions of `A`, even encoders produced prior to the extensions being >+specified! (Normally a decoder "skips" extensions it doesn't know about, and >+the encoding rules need only make it possible to do so.) >+ >+## TLV Encoding Rules >+ >+The TLV encoding rules for ASN.1 are: >+ >+ - Basic Encoding Rules (BER) >+ - Distinguished Encoding Rules (DER), a canonical subset of BER >+ - Canonical Encoding Rules (CER), another canonical subset of BER >+ >+"Canonical" encoding rules yield just one way to encode any value of any type, >+while non-canonical rules possibly yield many ways to encode values of certain >+types. For example, JSON is not a canonical data encoding. A canonical form >+of JSON would have to specify what interstitial whitespace is allowed, a >+canonical representation of strings (which Unicode codepoints must be escaped >+and in what way, and which must not), and a canonical representation of decimal >+numbers. >+ >+It is important to understand that originally ASN.1 came with TLV encoding >+rules, and some considerations around TLV encoding rules leaked into the >+language. For example, `A ::= SET { a0 [0] A0, a1 [1] A1 }` is a structure >+that has two members `a0` and `a1`, and when encoded those members will be >+tagged with a "context-specific" tags `0` and `1`, respectively. >+ >+Tags only have to be specified when needed to disambiguate encodings. >+Ambiguities arise only in `CHOICE` types and sometimes in `SEQUENCE`/`SET` >+types that have `OPTIONAL`/`DEFAULT`ed members. >+ >+In modern ASN.1 it is possible to specify that a module uses `AUTOMATIC` >+tagging so that one need never specify tags explicitly in order to fix >+ambiguities. >+ >+Also, there are two types of tags: `IMPLICIT` and `EXPLICIT`. Implicit tags >+replace the tags that the tagged type would have otherwise. Explicit tags >+treat the encoding of a type's value (including its tag and length) as the >+value of the tagged type, thus yielding a tag-length-tag-length-value encoding >+-- a TLTLV encoding! >+ >+Thus explicit tagging is more redundant and wasteful than implicit tagging. >+But implicit tagging loses metadata that is useful for tools that can decode >+TLV encodings without reference to the schema (module) corresponding to the >+types of values encoded. >+ >+TLV encodings were probably never justified except by lack of tooling and >+belief that codecs for TLV ERs can be hand-coded. But TLV RTs exist, and >+because they are widely used, cannot be removed. >+ >+## Other Encoding Rules >+ >+The Packed Encoding Rules (PER) and Octet Encoding Rules (OER) are rules that >+resemble XDR, but with a 1-byte word size instead of 4-byte word size, and also >+with a 1-byte alignment instead of 4-byte alignment, yielding space-efficient >+encodings. >+ >+Hand-coding XDR codecs is quite common and fairly easy. Hand-coding PER and >+OER is widely considered difficult because PER and OER try to be quite >+space-efficient. >+ >+Hand-coding TLV codecs used to be considered easy, but really, never was. >+ >+But no one should hand-code codecs for any encoding rules. >+ >+Instead, one should use a compiler. This is true for ASN.1, and for all schema >+languages. >+ >+## Encoding Rule Specific Syntactic Forms >+ >+Some encoding rules require specific syntactic forms for some aspects of them. >+ >+For example, the JER (JSON Encoding Rules) provide for syntax to select the use >+of JSON arrays vs. JSON objects for encoding structure types. >+ >+For example, the TLV encoding rules provide for syntax for specifying >+alternative tags for disambiguation. >+ >+## ASN.1 Syntax Specifications >+ >+ - The base specification is ITU-T >+ [X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en). >+ >+ - Additional syntax extensions include: >+ >+ - [X.681 ASN.1 Information object specification](https://www.itu.int/rec/T-REC-X.681/en) >+ - [X.682 ASN.1 Constraint specification](https://www.itu.int/rec/T-REC-X.682/en) >+ - [X.682 ASN.1 Parameterization of ASN.1 specifications](https://www.itu.int/rec/T-REC-X.683/en) >+ >+ Together these three specifications make the formal specification of open >+ types possible. >+ >+## ASN.1 Encoding Rules Specifications >+ >+ - The TLV Basic, Distinguished, and Canonical Encoding Rules (BER, DER, CER) >+ are described in ITU-T [X.690](https://www.itu.int/rec/T-REC-X.690/en). >+ >+ - The more flat-buffers/XDR-like Packed Encoding Rules (PER) are described in >+ ITU-T [X.691](https://www.itu.int/rec/T-REC-X.691/en), and its successor, >+ the Octet Encoding Rules (OER) are described in >+ [X.696](https://www.itu.int/rec/T-REC-X.692/en). >+ >+ - The XML Encoding Rules (XER) are described in ITU-T >+ [X.693](https://www.itu.int/rec/T-REC-X.693/en). >+ >+ Related is the [X.694 Mapping W3C XML schema definitions into ASN.1](https://www.itu.int/rec/T-REC-X.694/en) >+ >+ - The JSON Encoding Rules (JER) are described in ITU-T >+ [X.697](https://www.itu.int/rec/T-REC-X.697/en). >+ >+ - The Generic String Encoding Rules are specified by IETF RFCs >+ [RFC3641](https://datatracker.ietf.org/doc/html/rfc3641), >+ [RFC3642](https://datatracker.ietf.org/doc/html/rfc3642), >+ [RFC4792](https://datatracker.ietf.org/doc/html/rfc4792). >+ >+Additional ERs can be added. >+ >+For example, XDR can clearly encode a very large subset of ASN.1, and with a >+few additional conventions, all of ASN.1. >+ >+NDR too can clearly encode a very large subset of ASN.1, and with a few >+additional conventions, all of ASN. However, ASN.1 is not sufficiently rich a >+_syntax_ to express all of what NDR can express (think of NDR conformant and/or >+varying arrays), though with some extensions it could. >+ >+## Commentary >+ >+The text in this section is the personal opinion of the author(s). >+ >+ - ASN.1 gets a bad rap because BER/DER/CER are terrible encoding rules, as are >+ all TLV encoding rules. >+ >+ The BER family of encoding rules is a disaster, yes, but ASN.1 itself is >+ not. On the contrary, ASN.1 is quite rich in features and semantics -as >+ rich as any competitor- while also being very easy to write and understand >+ _as a syntax_. >+ >+ - ASN.1 also gets a bad rap because its full syntax is not context-free, and >+ so parsing it can be tricky. >+ >+ And yet the Heimdal ASN.1 compiler manages, using LALR(1) `yacc`/`bison`/`byacc` >+ parser-generators. For the subset of ASN.1 that this compiler handles, >+ there are no ambiguities. However, we understand that eventually we will >+ need run into ambiguities. >+ >+ For example, `ValueSet` and `ObjectSet` are ambiguous. X.680 says: >+ >+ ``` >+ ValueSet ::= "{" ElementSetSpecs "}" >+ ``` >+ >+ while X.681 says: >+ >+ ``` >+ ObjectSet ::= "{" ObjectSetSpec "}" >+ ``` >+ >+ and the set members can be just the symbolic names of members, in which case >+ there's no grammatical difference between those two productions. These then >+ cause a conflict in the `FieldSetting` production, which is used in the >+ `ObjectDefn` production, which is used in defining an object (which is to be >+ referenced from some `ObjectSet` or `FieldSetting`). >+ >+ This particular conflict can be resolved by one of: >+ >+ - limiting the power of object sets by disallowing recursion (object sets >+ containing objects that have field settings that are object sets ...), >+ >+ - or by introducing additional required and disambiguating syntactic >+ elements that preclude full compliance with ASN.1, >+ >+ - or by simply using the same production and type internally to handle >+ both, the `ValueSet` and `ObjectSet` productions and then internally >+ resolving the actual type as late as possible by either inspecting the >+ types of the set members or by inspecting the expected kind of field that >+ the `ValueSet`-or-`ObjectSet` is setting. >+ >+ Clearly, only the last of these is satisfying, but it is more work for the >+ compiler developer. >+ >+ - TLV encodings are bad because they yield unnecessary redundance in >+ encodings. This is space-inefficient, but also a source of bugs in >+ hand-coded codecs for TLV encodings. >+ >+ EXPLICIT tagging makes this worse by making the encoding a TLTLV encoding >+ (tag length tag length value). (The inner TLV is the V for the outer TL.) >+ >+ - TLV encodings are often described as "self-describing" because one can >+ usually write a `dumpasn1` style of tool that attempts to decode a TLV >+ encoding of a value without reference to the value's type definition. >+ >+ The use of `IMPLICIT` tagging with BER/DER/CER makes schema-less `dumpasn1` >+ style tools harder to use, as some type information is lost. E.g., a >+ primitive type implicitly tagged with a context tag results in a TLV >+ encoding where -without reference to the schema- the tag denotes no >+ information about the type of the value encoded. The user is left to figure >+ out what kind of data that is and to then decode it by hand. For >+ constructed types (arrays and structures), implicit tagging does not really >+ lose any metadata about the type that wasn't already lost by BER/DER/CER, so >+ there is no great loss there. >+ >+ However, Heimdal's ASN.1 compiler includes an `asn1_print(1)` utility that >+ can print DER-encoded values in much more detail than a schema-less >+ `dumpasn1` style of tool can. This is because `asn1_print(1)` includes >+ a number of compiled ASN.1 modules, and it can be extended to include more. >+ >+ - There is some merit to BER, however. Specifically, an appropriate use of >+ indeterminate length encoding with BER can yield on-line encoding. Think of >+ encoding streams of indeterminate size -- this cannot be done with DER or >+ Flat Buffers, or most encodings, though it can be done with some encodings, >+ such as BER and NDR (NDR has "pipes" for this). >+ >+ Some clues are needed in order to produce an codec that can handle such >+ on-line behavior. In IDL/NDR that clue comes from the "pipe" type. In >+ ASN.1 there is no such clue and it would have to be provided separately to >+ the ASN.1 compiler (e.g., as a command-line option). >+ >+ - Protocol Buffers is a TLV encoding. There was no need to make it a TLV >+ encoding. >+ >+ Public opinion seems to prefer Flat Buffers now, which is not a TLV encoding >+ and which is more comparable to XDR/NDR/PER/OER. >+ >+# Heimdal ASN.1 Compiler >+ >+The Heimdal ASN.1 compiler and library implement a very large subset of the >+ASN.1 syntax, meanign large parts of X.680, X.681, X.682, and X.683. >+ >+The compiler currently emits: >+ >+ - a JSON representation of ASN.1 modules >+ - C types corresponding to ASN.1 modules' types >+ - C functions for DER (and some BER) codecs for ASN.1 modules' types >+ >+We vaguely hope to eventually move to using the JSON representation of ASN.1 >+modules to do code generation in a programming language like `jq` rather than >+in C. The idea there is to make it much easier to target other programming >+languages than C, especially Rust, so that we can start moving Heimdal to Rust >+(first after this would be `lib/hx509`, then `lib/krb5`, then `lib/hdb`, then >+`lib/gssapi`, then `kdc/`). >+ >+The compiler has two "backends": >+ >+ - C code generation >+ - "template" (byte-code) generation and interpretation >+ >+## Features and Limitations >+ >+Supported encoding rules: >+ >+ - DER >+ - BER decoding (but not encoding) >+ >+As well, the Heimdal ASN.1 compiler can render values as JSON using an ad-hoc >+metaschema that is not quite JER-compliant. A sample rendering of a complex >+PKIX `Certificate` with all typed holes automatically decoded is shown in >+[README.md#features](README.md#features). >+ >+The Heimdal ASN.1 compiler supports open types via X.681/X.682/X.683 syntax. >+Specifically: (when using the template backend) the generated codecs can >+automatically and recursively decode and encode through "typed holes". >+ >+An "open type", also known as "typed holes" or "references", is a part of a >+structure that can contain the encoding of a value of some arbitrary data type, >+with a hint of that value's type expressed in some way such as: via an "object >+identifier", or an integer, or even a string (e.g., like a URN). >+ >+Open types are widely used as a form of extensibility. >+ >+Historically, open types were never documented formally, but with natural >+language (e.g., English) meant only for humans to understand. Documenting open >+types with formal syntax allows compilers to support them specially. >+ >+See the the [`asn1_compile(1)` manual page](#Manual-Page-for-asn1_compile) >+below and [README.md#features](README.md#features), for more details on >+limitations. Excerpt from the manual page: >+ >+``` >+The Information Object System support includes automatic codec support >+for encoding and decoding through âopen typesâ which are also known as >+âtyped holesâ. See RFC5912 for examples of how to use the ASN.1 Infor- >+mation Object System via X.681/X.682/X.683 annotations. See the com- >+piler's README files for more information on ASN.1 Information Object >+System support. >+ >+Extensions specific to Heimdal are generally not syntactic in nature but >+rather command-line options to this program. For example, one can use >+command-line options to: >+ ⢠enable decoding of BER-encoded values; >+ ⢠enable RFC1510-style handling of âBIT STRINGâ types; >+ ⢠enable saving of as-received encodings of specific types >+ for the purpose of signature validation; >+ ⢠generate add/remove utility functions for array types; >+ ⢠decorate generated âstructâ types with fields that are nei- >+ ther encoded nor decoded; >+etc. >+ >+ASN.1 x.680 features supported: >+ ⢠most primitive types (except BMPString and REAL); >+ ⢠all constructed types, including SET and SET OF; >+ ⢠explicit and implicit tagging. >+ >+Size and range constraints on the âINTEGERâ type cause the compiler to >+generate appropriate C types such as âintâ, âunsigned intâ, âint64_tâ, >+âuint64_tâ. Unconstrained âINTEGERâ is treated as âheim_integerâ, which >+represents an integer of arbitrary size. >+ >+Caveats and ASN.1 x.680 features not supported: >+ ⢠JSON encoding support is not quite X.697 (JER) compatible. >+ Its JSON schema is subject to change without notice. >+ ⢠Control over C types generated is very limited, mainly only >+ for integer types. >+ ⢠When using the template backend, `SET { .. }` types are >+ currently not sorted by tag as they should be, but if the >+ module author sorts them by hand then correct DER will be >+ produced. >+ ⢠âAUTOMATIC TAGSâ is not supported. >+ ⢠The REAL type is not supported. >+ ⢠The EmbeddedPDV type is not supported. >+ ⢠The BMPString type is not supported. >+ ⢠The IA5String is not properly supported, as it's essenâ >+ tially treated as a UTF8String with a different tag. >+ ⢠All supported non-octet strings are treated as like the >+ UTF8String type. >+ ⢠Only types can be imported into ASN.1 modules at this time. >+ ⢠Only simple value syntax is supported. Constructed value >+ syntax (i.e., values of SET, SEQUENCE, SET OF, and SEQUENCE >+ OF types), is not supported. Values of `CHOICE` types are >+ also not supported. >+``` >+ >+## Easy-to-Use C Types >+ >+The Heimdal ASN.1 compiler generates easy-to-use C types for ASN.1 types. >+ >+Unconstrained `INTEGER` becomes `heim_integer` -- a large integer type. >+ >+Constrained `INTEGER` types become `int`, `unsigned int`, `int64_t`, or >+`uint64_t`. >+ >+String types generally become `char *` (C strings, i.e., NUL-terminated) or >+`heim_octet_string` (a counted byte string type). >+ >+`SET` and `SEQUENCE` types become `struct` types. >+ >+`SET OF SomeType` and `SEQUENCE OF SomeType` types become `struct` types with a >+`size_t len` field counting the number of elements of the array, and a pointer >+to `len` consecutive elements of the `SomeType` type. >+ >+`CHOICE` types become a `struct` type with an `enum` discriminant and a >+`union`. >+ >+Type names have hyphens turned to underscores. >+ >+Every ASN.1 gets a `typedef`. >+ >+`OPTIONAL` members of `SET`s and `SEQUENCE`s become pointer types (`NULL` >+values mean "absent", while non-`NULL` values mean "present"). >+ >+Tags are of no consequence to the C types generated. >+ >+Types definitions to be topographically sorted because of the need to have >+forward declarations. >+ >+Forward `typedef` declarations are emmitted. >+ >+Circular type dependencies are allowed provided that `OPTIONAL` members are >+used for enough circular references so as to avoid creating types whose values >+have infinite size! (Circular type dependencies can be used to build linked >+lists, though that is a bit of a silly trick when one can use arrays instead, >+though in principle this could be used to do on-line encoding and decoding of >+arbitrarily large streams of objects. See the [commentary](#Commentary) >+section.) >+ >+Thus `Certificate` becomes: >+ >+```C >+typedef struct TBSCertificate { >+ heim_octet_string _save; /* see below! */ >+ Version *version; >+ CertificateSerialNumber serialNumber; >+ AlgorithmIdentifier signature; >+ Name issuer; >+ Validity validity; >+ Name subject; >+ SubjectPublicKeyInfo subjectPublicKeyInfo; >+ heim_bit_string *issuerUniqueID; >+ heim_bit_string *subjectUniqueID; >+ Extensions *extensions; >+} TBSCertificate; >+ >+typedef struct Certificate { >+ TBSCertificate tbsCertificate; >+ AlgorithmIdentifier signatureAlgorithm; >+ heim_bit_string signatureValue; >+} Certificate; >+``` >+ >+The `_save` field in `TBSCertificate` is generated when the compiler is invoked >+with `--preserve-binary=TBSCertificate`, and the decoder will place the >+original encoding of the value of a `TBSCertificate` in the decoded >+`TBSCertificate`'s `_save` field. This is very useful for signature >+validation: the application need not attempt to re-encode a `TBSCertificate` in >+order to validate its signature from the containing `Certificate`! >+ >+Let's compare to the `Certificate` as defined in ASN.1: >+ >+```ASN.1 >+ Certificate ::= SEQUENCE { >+ tbsCertificate TBSCertificate, >+ signatureAlgorithm AlgorithmIdentifier, >+ signatureValue BIT STRING >+ } >+ >+ TBSCertificate ::= SEQUENCE { >+ version [0] EXPLICIT Version DEFAULT v1, >+ serialNumber CertificateSerialNumber, >+ signature AlgorithmIdentifier, >+ issuer Name, >+ validity Validity, >+ subject Name, >+ subjectPublicKeyInfo SubjectPublicKeyInfo, >+ issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, >+ subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, >+ extensions [3] EXPLICIT Extensions OPTIONAL >+ } >+``` >+ >+The conversion from ASN.1 to C is quite mechanical and natural. That's what >+code-generators do, of course, so it's not surprising. But you can see that >+`Certificate` in ASN.1 and C differs only in: >+ >+ - in C `SEQUENCE { }` becomes `struct { }` >+ - in C the type name comes first >+ - in C we drop the tagging directives (e.g., `[0] EXPLICIT`) >+ - `DEFAULT` and `OPTIONAL` become pointers >+ - in C we use `typedef`s to make the type names usable without having to add >+ `struct` >+ >+## Circular Type Dependencies >+ >+As noted above, circular type dependencies are supported. >+ >+Here's a toy example from [XDR](https://datatracker.ietf.org/doc/html/rfc4506) >+-- a linked list: >+ >+```XDR >+struct stringentry { >+ string item<>; >+ stringentry *next; >+}; >+ >+typedef stringentry *stringlist; >+``` >+ >+Here is the same example in ASN.1: >+ >+```ASN.1 >+Stringentry ::= SEQUENCE { >+ item UTF8String, >+ next Stringentry OPTIONAL >+} >+``` >+ >+which compiles to: >+ >+```C >+typedef struct Stringentry Stringentry; >+struct Stringentry { >+ char *item; >+ Stringentry *next; >+}; >+``` >+ >+This illustrates that `OPTIONAL` members in ASN.1 are like pointers in XDR. >+ >+Making the `next` member not `OPTIONAL` would cause `Stringentry` to be >+infinitely large, and there is no way to declare the equivalent in C anyways >+(`struct foo { int a; struct foo b; };` will not compile in C). >+ >+Mutual circular references are allowed too. In the following example `A` >+refers to `B` and `B` refers to `A`, but as long as one (or both) of those >+references is `OPTIONAL`, then it will be allowed: >+ >+```ASN1 >+A ::= SEQUENCE { name UTF8String, b B } >+B ::= SEQUENCE { name UTF8String, a A OPTIONAL } >+``` >+ >+```ASN1 >+A ::= SEQUENCE { name UTF8String, b B OPTIONAL } >+B ::= SEQUENCE { name UTF8String, a A } >+``` >+ >+```ASN1 >+A ::= SEQUENCE { name UTF8String, b B OPTIONAL } >+B ::= SEQUENCE { name UTF8String, a A OPTIONAL } >+``` >+ >+In the above example values of types `A` and `B` together form a linked list. >+ >+Whereas this is broken and will not compile: >+ >+```ASN1 >+A ::= SEQUENCE { name UTF8String, b B } >+B ::= SEQUENCE { name UTF8String, a A } -- infinite size! >+``` >+ >+## Generated APIs For Any Given Type T >+ >+The C functions generated for ASN.1 types are all of the same form, for any >+type `T`: >+ >+```C >+int decode_T(const unsigned char *, size_t, TBSCertificate *, size_t *); >+int encode_T(unsigned char *, size_t, const TBSCertificate *, size_t *); >+size_t length_T(const TBSCertificate *); >+int copy_T(const TBSCertificate *, TBSCertificate *); >+void free_T(TBSCertificate *); >+char * print_T(const TBSCertificate *, int); >+``` >+ >+The `decode_T()` functions take a pointer to the encoded data, its length in >+bytes, a pointer to a C object of type `T` to decode into, and a pointer into >+which the number of bytes consumed will be written. >+ >+The `length_T()` functions take a pointer to a C object of type `T` and return >+the number of bytes its encoding would need. >+ >+The `encode_T()` functions take a pointer to enough bytes to encode the value, >+the number of bytes found there, a pointer to a C object of type `T` whose >+value to encode, and a pointer into which the number of bytes output will be >+written. >+ >+> NOTE WELL: The first argument to `encode_T()` functions must point to the >+> last byte in the buffer into which the encoder will encode the value. This >+> is because the encoder encodes from the end towards the beginning. >+ >+The `print_T()` functions encode the value of a C object of type `T` in JSON >+(though not in JER-compliant JSON). A sample printing of a complex PKIX >+`Certificate` can be seen in [README.md#features](README.md#features). >+ >+The `copy_T()` functions take a pointer to a source C object of type `T` whose >+value they then copy to the destination C object of the same type. The copy >+constructor is equivalent to encoding the source value and decoding it onto the >+destination. >+ >+The `free_T()` functions take a pointer to a C object of type `T` whose value's >+memory resources will be released. Note that the C object _itself_ is not >+freed, only its _content_. >+ >+See [sample usage](#Using-the-Generated-APIs). >+ >+These functions are all recursive. >+ >+> NOTE WELL: These functions use the standard C memory allocator. >+> When using the Windows statically-linked C run-time, you must link with >+> `LIBASN1.LIB` to avoid possibly freeing memory allocated by a different >+> allocator. >+ >+## Error Handling >+ >+All codec functions that return errors return them as `int`. >+ >+Error values are: >+ >+ - system error codes (use `strerror()` to display them) >+ >+or >+ >+ - `ASN1_BAD_TIMEFORMAT` >+ - `ASN1_MISSING_FIELD` >+ - `ASN1_MISPLACED_FIELD` >+ - `ASN1_TYPE_MISMATCH` >+ - `ASN1_OVERFLOW` >+ - `ASN1_OVERRUN` >+ - `ASN1_BAD_ID` >+ - `ASN1_BAD_LENGTH` >+ - `ASN1_BAD_FORMAT` >+ - `ASN1_PARSE_ERROR` >+ - `ASN1_EXTRA_DATA` >+ - `ASN1_BAD_CHARACTER` >+ - `ASN1_MIN_CONSTRAINT` >+ - `ASN1_MAX_CONSTRAINT` >+ - `ASN1_EXACT_CONSTRAINT` >+ - `ASN1_INDEF_OVERRUN` >+ - `ASN1_INDEF_UNDERRUN` >+ - `ASN1_GOT_BER` >+ - `ASN1_INDEF_EXTRA_DATA` >+ >+You can use the `com_err` library to display these errors as strings: >+ >+```C >+ struct et_list *etl = NULL; >+ initialize_asn1_error_table_r(&etl); >+ int ret; >+ >+ ... >+ >+ ret = decode_T(...); >+ if (ret) { >+ const char *error_message; >+ >+ if ((error_message = com_right(etl, ret)) == NULL) >+ error_message = strerror(ret); >+ >+ fprintf(stderr, "Failed to decode T: %s\n", >+ error_message ? error_message : "<unknown error>"); >+ } >+``` >+ >+## Using the Generated APIs >+ >+Value construction is as usual in C. Use the standard C allocator for >+allocating values of `OPTIONAL` fields. >+ >+Value destruction is done with the `free_T()` destructors. >+ >+Decoding is just: >+ >+```C >+ Certificate c; >+ size_t sz; >+ int ret; >+ >+ ret = decode_Certificate(pointer_to_encoded_bytes, >+ number_of_encoded_bytes, >+ &c, &sz); >+ if (ret == 0) { >+ if (sz != number_of_encoded_bytes) >+ warnx("Extra bytes after Certificate!"); >+ } else { >+ warnx("Failed to decode certificate!"); >+ return ret; >+ } >+ >+ /* Now do stuff with the Certificate */ >+ ... >+ >+ /* Now release the memory */ >+ free_Certificate(&c); >+``` >+ >+Encoding involves calling the `length_T()` function to compute the number of >+bytes needed for the encoding, then allocating that many bytes, then calling >+`encode_T()` to encode into that memory. A convenience macro, >+`ASN1_MALLOC_ENCODE()`, does all three operations: >+ >+```C >+ Certificate c; >+ size_t num_bytes, sz; >+ char *bytes = NULL; >+ int ret; >+ >+ /* Build a `Certificate` in `c` */ >+ ... >+ >+ /* Encode `c` */ >+ ASN1_MALLOC_ENCODE(Certificate, bytes, num_bytes, &c, sz, ret); >+ if (ret) >+ errx(1, "Out of memory encoding a Certificate"); >+ >+ /* This check isn't really needed -- it never fails */ >+ if (num_bytes != sz) >+ errx(1, "ASN.1 encoder internal error"); >+ >+ /* Send the `num_bytes` in `bytes` */ >+ ... >+ >+ /* Free the memory allocated by `ASN1_MALLOC_ENCODE()` */ >+ free(bytes); >+``` >+ >+or, the same code w/o the `ASN1_MALLOC_ENCODE()` macro: >+ >+```C >+ Certificate c; >+ size_t num_bytes, sz; >+ char *bytes = NULL; >+ int ret; >+ >+ /* Build a `Certificate` in `c` */ >+ ... >+ >+ /* Encode `c` */ >+ num_bytes = length_Certificate(&c); >+ bytes = malloc(num_bytes); >+ if (bytes == NULL) >+ errx(1, "Out of memory"); >+ >+ /* >+ * Note that the memory to encode into, passed to encode_Certificate() >+ * must be a pointer to the _last_ byte of that memory, not the first! >+ */ >+ ret = encode_Certificate(bytes + num_bytes - 1, num_bytes, >+ &c, &sz); >+ if (ret) >+ errx(1, "Out of memory encoding a Certificate"); >+ >+ /* This check isn't really needed -- it never fails */ >+ if (num_bytes != sz) >+ errx(1, "ASN.1 encoder internal error"); >+ >+ /* Send the `num_bytes` in `bytes` */ >+ ... >+ >+ /* Free the memory allocated by `ASN1_MALLOC_ENCODE()` */ >+ free(bytes); >+``` >+ >+## Open Types >+ >+The handling of X.681/X.682/X.683 syntax for open types is described at length >+in [README-X681.md](README-X681.md). >+ >+## Command-line Usage >+ >+The compiler takes an ASN.1 module file name and outputs a C header and C >+source files, as well as various other metadata files: >+ >+ - `<module>_asn1.h` >+ >+ This file defines all the exported types from the given ASN.1 module as C >+ types. >+ >+ - `<module>_asn1-priv.h` >+ >+ This file defines all the non-exported types from the given ASN.1 module as >+ C types. >+ >+ - `<module>_asn1_files` >+ >+ This file is needed because the default is to place the code for each type >+ in a separate C source file, which can help improve the performance of >+ builds by making it easier to parallelize the building of the ASN.1 module. >+ >+ - `asn1_<Type>.c` or `asn1_<module>_asn1.c` >+ >+ If `--one-code-file` is used, then the implementation of the module will be >+ in a file named `asn1_<module>_asn1.c`, otherwise the implementation of each >+ type in the module will be in `asn1_<Type>.c`. >+ >+ - `<module>_asn1.json` >+ >+ This file contains a JSON description of the module (the schema for this >+ file is ad-hoc and subject to change w/o notice). >+ >+ - `<module>_asn1_oids.c` >+ >+ This file is meant to be `#include`d, and contains just calls to a >+ `DEFINE_OID_WITH_NAME(sym)` macro that the user must define, where `sym` is >+ the suffix of the name of a variable of type `heim_oid`. The full name of >+ the variable is `asn1_oid_ ## sym`. >+ >+ - `<module>_asn1_syms.c` >+ >+ This file is meant to be `#include`d, and contains just calls to these >+ macros that the user must define: >+ >+ - `ASN1_SYM_INTVAL(name, genname, sym, num)` >+ - `ASN1_SYM_OID(name, genname, sym)` >+ - `ASN1_SYM_TYPE(name, genname, sym)` >+ >+ where `name` is the C string literal name of the value or type as it appears >+ in the ASN.1 module, `genname` is the C string literal name of the value or >+ type as generated (e.g., with hyphens replaced by underscores), `sym` is the >+ symbol or symbol suffix (see above0, and `num` is the numeric value of the >+ integer value. >+ >+Control over the C types used for ASN.1 `INTEGER` types is done by ASN.1 usage >+convention: >+ >+ - unconstrained `INTEGER` types, or `INTEGER` types where only the minimum, or >+ only the maximum value is specified generate `heim_integer` >+ >+ - constrained `INTEGER` types whose minimum and maximum fit in `unsigned`'s >+ range generate `unsigned` >+ >+ - constrained `INTEGER` types whose minimum and maximum fit in `int`'s >+ range generate `int` >+ >+ - constrained `INTEGER` types whose minimum and maximum fit in `uin64_t`'s >+ range generate `uin64_t` >+ >+ - constrained `INTEGER` types whose minimum and maximum fit in `in64_t`'s >+ range generate `in64_t` >+ >+ - `INTEGER` types with named members generate a C `struct` with `unsigned int` >+ bit-field members >+ >+ - all other `INTEGER` types generate `heim_integer` >+ >+Various code generation options are provided as command-line options or as >+ASN.1 usage conventions: >+ >+ - `--type-file=C-HEADER-FILE` -- generate an `#include` directive to include >+ that header for some useful base types (within Heimdal we use `krb5-types.h` >+ as that header) >+ >+ - `--template` -- use the "template" (byte-coded) backend >+ >+ - `--one-code-file` -- causes all the code generated to be placed in one C >+ source file (mutually exclusive with `--template`) >+ >+ - `--support-ber` -- accept non-DER BER when decoding >+ >+ - `--preserve-binary=TYPE` -- add a `_save` field to the C struct type for the >+ ASN.1 `TYPE` where the decoder will save the original encoding of the value >+ of `TYPE` it decodes (useful for cryptographic signature verification!) >+ >+ - `--sequence=TYPE` -- generate `add_TYPE()` and `remove_TYPE()` utility >+ functions (`TYPE` must be a `SET OF` or `SEQUENCE OF` type) >+ >+ - `--decorate=DECORATION` -- add fields to generated C struct types as >+ described in the `DECORATION` (see the >+ [manual page](#Manual-Page-for-asn1_compile) below) >+ >+ Decoration fields are never encoded or decoded. They are meant to be used >+ for, e.g., application state keeping. >+ >+ - `--no-parse-units` -- normally the compiler generates code to use the >+ Heimdal `libroken` "units" utility for displaying bit fields; this option >+ disables this >+ >+See the [manual page for `asn1_compile(1)`](#Manual-Page-for-asn1_compile) for >+a full listing of command-line options. >+ >+### Manual Page for `asn1_compile(1)` >+ >+``` >+ASN1_COMPILE(1) BSD General Commands Manual ASN1_COMPILE(1) >+ >+NAME >+ asn1_compile â compile ASN.1 modules >+ >+SYNOPSIS >+ asn1_compile [--template] [--prefix-enum] [--enum-prefix=PREFIX] >+ [--encode-rfc1510-bit-string] [--decode-dce-ber] >+ [--support-ber] [--preserve-binary=TYPE] [--sequence=TYPE] >+ [--decorate=DECORATION] [--one-code-file] [--gen-name=NAME] >+ [--option-file=FILE] [--original-order] [--no-parse-units] >+ [--type-file=C-HEADER-FILE] [--version] [--help] >+ [FILE.asn1 [NAME]] >+ >+DESCRIPTION >+ asn1_compile compiles an ASN.1 module into C source code and header >+ files. >+ >+ A fairly large subset of ASN.1 as specified in X.680, and the ASN.1 Inâ >+ formation Object System as specified in X.681, X.682, and X.683 is supâ >+ ported, with support for the Distinguished Encoding Rules (DER), partial >+ Basic Encoding Rules (BER) support, and experimental JSON support (encodâ >+ ing only at this time). >+ >+ See the compiler's README files for details about the C code and interâ >+ faces it generates. >+ >+ The Information Object System support includes automatic codec support >+ for encoding and decoding through âopen typesâ which are also known as >+ âtyped holesâ. See RFC 5912 for examples of how to use the ASN.1 Inforâ >+ mation Object System via X.681/X.682/X.683 annotations. See the comâ >+ piler's README files for more information on ASN.1 Information Object >+ System support. >+ >+ Extensions specific to Heimdal are generally not syntactic in nature but >+ rather command-line options to this program. For example, one can use >+ command-line options to: >+ ⢠enable decoding of BER-encoded values; >+ ⢠enable RFC1510-style handling of âBIT STRINGâ types; >+ ⢠enable saving of as-received encodings of specific types >+ for the purpose of signature validation; >+ ⢠generate add/remove utility functions for array types; >+ ⢠decorate generated âstructâ types with fields that are neiâ >+ ther encoded nor decoded; >+ etc. >+ >+ ASN.1 x.680 features supported: >+ ⢠most primitive types (except BMPString and REAL); >+ ⢠all constructed types, including SET and SET OF; >+ ⢠explicit and implicit tagging. >+ >+ Size and range constraints on the âINTEGERâ type cause the compiler to >+ generate appropriate C types such as âintâ, âunsigned intâ, âint64_tâ, >+ âuint64_tâ. Unconstrained âINTEGERâ is treated as âheim_integerâ, which >+ represents an integer of arbitrary size. >+ >+ Caveats and ASN.1 x.680 features not supported: >+ ⢠JSON encoding support is not quite X.697 (JER) compatible. >+ Its JSON schema is subject to change without notice. >+ ⢠Control over C types generated is very limited, mainly only >+ for integer types. >+ ⢠When using the template backend, `SET { .. }` types are >+ currently not sorted by tag as they should be, but if the >+ module author sorts them by hand then correct DER will be >+ produced. >+ ⢠âAUTOMATIC TAGSâ is not supported. >+ ⢠The REAL type is not supported. >+ ⢠The EmbeddedPDV type is not supported. >+ ⢠The BMPString type is not supported. >+ ⢠The IA5String is not properly supported, as it's essenâ >+ tially treated as a UTF8String with a different tag. >+ ⢠All supported non-octet strings are treated as like the >+ UTF8String type. >+ ⢠Only types can be imported into ASN.1 modules at this time. >+ ⢠Only simple value syntax is supported. Constructed value >+ syntax (i.e., values of SET, SEQUENCE, SET OF, and SEQUENCE >+ OF types), is not supported. Values of `CHOICE` types are >+ also not supported. >+ >+ Options supported: >+ >+ --template >+ Use the âtemplateâ backend instead of the âcodegenâ backend >+ (which is the default backend). >+ >+ The template backend generates âtemplatesâ which are akin to >+ bytecode, and which are interpreted at run-time. >+ >+ The codegen backend generates C code for all functions directly, >+ with no template interpretation. >+ >+ The template backend scales better than the codegen backend beâ >+ cause as we add support for more encoding rules and more operaâ >+ tions (we may add value comparators) the templates stay mostly >+ the same, thus scaling linearly with size of module. Whereas the >+ codegen backend scales linear with the product of module size and >+ number of encoding rules supported. >+ >+ --prefix-enum >+ This option should be removed because ENUMERATED types should alâ >+ ways have their labels prefixed. >+ >+ --enum-prefix=PREFIX >+ This option should be removed because ENUMERATED types should alâ >+ ways have their labels prefixed. >+ >+ --encode-rfc1510-bit-string >+ Use RFC1510, non-standard handling of âBIT STRINGâ types. >+ >+ --decode-dce-ber >+ >+ --support-ber >+ >+ --preserve-binary=TYPE >+ Generate a field named â_saveâ in the C struct generated for the >+ named TYPE. This field is used to preserve the original encoding >+ of the value of the TYPE. >+ >+ This is useful for cryptographic applications so that they can >+ check signatures of encoded values as-received without having to >+ re-encode those values. >+ >+ For example, the TBSCertificate type should have values preserved >+ so that Certificate validation can check the signatureValue over >+ the tbsCertificate's value as-received. >+ >+ The alternative of encoding a value to check a signature of it is >+ brittle. For types where non-canonical encodings (such as BER) >+ are allowed, this alternative is bound to fail. Thus the point >+ of this option. >+ >+ --sequence=TYPE >+ Generate add/remove functions for the named ASN.1 TYPE which must >+ be a âSET OFâ or âSEQUENCE OFâ type. >+ >+ --decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?] >+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE, >+ or CHOICE type named ASN1-TYPE a âhiddenâ field named fname of >+ the given ASN.1 type FIELD-ASN1-TYPE, but do not encode or decode >+ it. If the fname ends in a question mark, then treat the field >+ as OPTIONAL. >+ >+ This is useful for adding fields to existing types that can be >+ used for internal bookkeeping but which do not affect interoperâ >+ ability because they are neither encoded nor decoded. For examâ >+ ple, one might decorate a request type with state needed during >+ processing of the request. >+ >+ --decorate=ASN1-TYPE:void*:fname >+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE, >+ or CHOICE type named ASN1-TYPE a âhiddenâ field named fname of >+ type âvoid *â (but do not encode or decode it. >+ >+ The destructor and copy constructor functions generated by this >+ compiler for ASN1-TYPE will set this field to the âNULLâ pointer. >+ >+ --decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header >+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE, >+ or CHOICE type named ASN1-TYPE a âhiddenâ field named fname of >+ the given external C type FIELD-C-TYPE, declared in the given >+ header but do not encode or decode this field. If the fname ends >+ in a question mark, then treat the field as OPTIONAL. >+ >+ The header must include double quotes or angle brackets. The >+ copyfn must be the name of a copy constructor function that takes >+ a pointer to a source value of the type, and a pointer to a desâ >+ tination value of the type, in that order, and which returns zero >+ on success or else a system error code on failure. The freefn >+ must be the name of a destructor function that takes a pointer to >+ a value of the type and which releases resources referenced by >+ that value, but does not free the value itself (the run-time alâ >+ locates this value as needed from the C heap). The freefn should >+ also reset the value to a pristine state (such as all zeros). >+ >+ If the copyfn and freefn are empty strings, then the decoration >+ field will neither be copied nor freed by the functions generated >+ for the TYPE. >+ >+ --one-code-file >+ Generate a single source code file. Otherwise a separate code >+ file will be generated for every type. >+ >+ --gen-name=NAME >+ Use NAME to form the names of the files generated. >+ >+ --option-file=FILE >+ Take additional command-line options from FILE. >+ >+ --original-order >+ Attempt to preserve the original order of type definition in the >+ ASN.1 module. By default the compiler generates types in a topoâ >+ logical sort order. >+ >+ --no-parse-units >+ Do not generate to-int / from-int functions for enumeration >+ types. >+ >+ --type-file=C-HEADER-FILE >+ Generate an include of the named header file that might be needed >+ for common type defintions. >+ >+ --version >+ >+ --help >+ >+NOTES >+ Currently only the template backend supports automatic encoding and deâ >+ coding of open types via the ASN.1 Information Object System and >+ X.681/X.682/X.683 annotations. >+ >+HEIMDAL February 22, 2021 HEIMDAL >+``` >+ >+# Future Directions >+ >+The Heimdal ASN.1 compiler is focused on PKIX and Kerberos, and is almost >+feature-complete for dealing with those. It could use additional support for >+X.681/X.682/X.683 elements that would allow the compiler to understand >+`Certificate ::= SIGNED{TBSCertificate}`, particularly the ability to >+automatically validate cryptographic algorithm parameters. However, this is >+not that important. >+ >+Another feature that might be nice is the ability of callers to specify smaller >+information object sets when decoding values of types like `Certificate`, >+mainly to avoid spending CPU cycles and memory allocations on decoding types in >+typed holes that are not of interest to the application. >+ >+For testing purposes, a JSON reader to go with the JSON printer might be nice, >+and anyways, would make for a generally useful tool. >+ >+Another feature that would be nice would to automatically generate SQL and LDAP >+code for HDB based on `lib/hdb/hdb.asn1` (with certain usage conventions and/or >+compiler command-line options to make it possible to map schemas usefully). >+ >+For the `hxtool` command, it would be nice if the user could input arbitrary >+certificate extensions and `subjectAlternativeName` (SAN) values in JSON + an >+ASN.1 module and type reference that `hxtool` could then parse and encode using >+the ASN.1 compiler and library. Currently the `hx509` library and its `hxtool` >+command must be taught about every SAN type. >diff --git a/third_party/heimdal/lib/asn1/Makefile.am b/third_party/heimdal/lib/asn1/Makefile.am >index 94d24fc47eb6..eb0308ee13cc 100644 >--- a/third_party/heimdal/lib/asn1/Makefile.am >+++ b/third_party/heimdal/lib/asn1/Makefile.am >@@ -2,9 +2,11 @@ > > include $(top_srcdir)/Makefile.am.common > >-YFLAGS = -d -t >+WFLAGS += $(WFLAGS_ENUM_CONV) > >-AM_CPPFLAGS += $(ROKEN_RENAME) >+YFLAGS = -o asn1parse.c -t >+ >+AM_CPPFLAGS += $(ROKEN_RENAME) -I$(top_builddir)/include -I$(top_srcdir)/lib/base > > man_MANS = asn1_print.1 asn1_compile.1 > >@@ -30,64 +32,64 @@ libasn1template_la_LIBADD = \ > @LIB_com_err@ \ > $(LIBADD_roken) > >-BUILT_SOURCES = \ >- $(gen_files_rfc2459:.x=.c) \ >- $(gen_files_rfc4108:.x=.c) \ >- $(gen_files_cms:.x=.c) \ >- $(gen_files_krb5:.x=.c) \ >- $(gen_files_ocsp:.x=.c) \ >- $(gen_files_pkinit:.x=.c) \ >- $(gen_files_pkcs8:.x=.c) \ >- $(gen_files_pkcs9:.x=.c) \ >- $(gen_files_pkcs10:.x=.c) \ >- $(gen_files_pkcs12:.x=.c) \ >- $(gen_files_digest:.x=.c) \ >- $(gen_files_kx509:.x=.c) >- >-BUILT_TEMPLATE_SOURCES = \ >- $(gen_files_rfc2459_template:.x=.c) \ >- $(gen_files_rfc4108_template:.x=.c) \ >- $(gen_files_cms_template:.x=.c) \ >- $(gen_files_krb5_template:.x=.c) \ >- $(gen_files_ocsp_template:.x=.c) \ >- $(gen_files_pkinit_template:.x=.c) \ >- $(gen_files_pkcs8_template:.x=.c) \ >- $(gen_files_pkcs9_template:.x=.c) \ >- $(gen_files_pkcs10_template:.x=.c) \ >- $(gen_files_pkcs12_template:.x=.c) \ >- $(gen_files_digest_template:.x=.c) \ >- $(gen_files_kx509_template:.x=.c) >- >-gen_files_krb5 = asn1_krb5_asn1.x >-gen_files_krb5_template = asn1_krb5_template_asn1.x >-gen_files_cms = asn1_cms_asn1.x >-gen_files_cms_template = asn1_cms_template_asn1.x >-gen_files_crmf = asn1_crmf_asn1.x >-gen_files_crmf_template = asn1_crmf_template_asn1.x >-gen_files_rfc2459 = asn1_rfc2459_asn1.x >-gen_files_rfc2459_template = asn1_rfc2459_template_asn1.x >-gen_files_rfc4108 = asn1_rfc4108_asn1.x >-gen_files_rfc4108_template = asn1_rfc4108_template_asn1.x >-gen_files_ocsp = asn1_ocsp_asn1.x >-gen_files_ocsp_template = asn1_ocsp_template_asn1.x >-gen_files_pkinit = asn1_pkinit_asn1.x >-gen_files_pkinit_template = asn1_pkinit_template_asn1.x >-gen_files_pkcs10 = asn1_pkcs10_asn1.x >-gen_files_pkcs10_template = asn1_pkcs10_template_asn1.x >-gen_files_pkcs12 = asn1_pkcs12_asn1.x >-gen_files_pkcs12_template = asn1_pkcs12_template_asn1.x >-gen_files_pkcs8 = asn1_pkcs8_asn1.x >-gen_files_pkcs8_template = asn1_pkcs8_template_asn1.x >-gen_files_pkcs9 = asn1_pkcs9_asn1.x >-gen_files_pkcs9_template = asn1_pkcs9_template_asn1.x >-gen_files_test = asn1_test_asn1.x >-gen_files_test_template = asn1_test_template_asn1.x >-gen_files_digest = asn1_digest_asn1.x >-gen_files_digest_template = asn1_digest_template_asn1.x >-gen_files_kx509 = asn1_kx509_asn1.x >-gen_files_kx509_template = asn1_kx509_template_asn1.x >-gen_files_x690sample = asn1_x690sample_asn1.x >-gen_files_x690sample_template = asn1_x690sample_template_asn1.x >+BUILT_SOURCES = \ >+ $(gen_files_rfc2459) \ >+ $(gen_files_rfc4108) \ >+ $(gen_files_cms) \ >+ $(gen_files_krb5) \ >+ $(gen_files_ocsp) \ >+ $(gen_files_pkinit) \ >+ $(gen_files_pkcs8) \ >+ $(gen_files_pkcs9) \ >+ $(gen_files_pkcs10) \ >+ $(gen_files_pkcs12) \ >+ $(gen_files_digest) \ >+ $(gen_files_kx509) >+ >+BUILT_TEMPLATE_SOURCES = \ >+ $(gen_files_rfc2459_template) \ >+ $(gen_files_rfc4108_template) \ >+ $(gen_files_cms_template) \ >+ $(gen_files_krb5_template) \ >+ $(gen_files_ocsp_template) \ >+ $(gen_files_pkinit_template) \ >+ $(gen_files_pkcs8_template) \ >+ $(gen_files_pkcs9_template) \ >+ $(gen_files_pkcs10_template) \ >+ $(gen_files_pkcs12_template) \ >+ $(gen_files_digest_template) \ >+ $(gen_files_kx509_template) >+ >+gen_files_krb5 = asn1_krb5_asn1.c >+gen_files_krb5_template = asn1_krb5_template_asn1.c >+gen_files_cms = asn1_cms_asn1.c >+gen_files_cms_template = asn1_cms_template_asn1.c >+gen_files_crmf = asn1_crmf_asn1.c >+gen_files_crmf_template = asn1_crmf_template_asn1.c >+gen_files_rfc2459 = asn1_rfc2459_asn1.c >+gen_files_rfc2459_template = asn1_rfc2459_template_asn1.c >+gen_files_rfc4108 = asn1_rfc4108_asn1.c >+gen_files_rfc4108_template = asn1_rfc4108_template_asn1.c >+gen_files_ocsp = asn1_ocsp_asn1.c >+gen_files_ocsp_template = asn1_ocsp_template_asn1.c >+gen_files_pkinit = asn1_pkinit_asn1.c >+gen_files_pkinit_template = asn1_pkinit_template_asn1.c >+gen_files_pkcs10 = asn1_pkcs10_asn1.c >+gen_files_pkcs10_template = asn1_pkcs10_template_asn1.c >+gen_files_pkcs12 = asn1_pkcs12_asn1.c >+gen_files_pkcs12_template = asn1_pkcs12_template_asn1.c >+gen_files_pkcs8 = asn1_pkcs8_asn1.c >+gen_files_pkcs8_template = asn1_pkcs8_template_asn1.c >+gen_files_pkcs9 = asn1_pkcs9_asn1.c >+gen_files_pkcs9_template = asn1_pkcs9_template_asn1.c >+gen_files_test = asn1_test_asn1.c >+gen_files_test_template = asn1_test_template_asn1.c >+gen_files_digest = asn1_digest_asn1.c >+gen_files_digest_template = asn1_digest_template_asn1.c >+gen_files_kx509 = asn1_kx509_asn1.c >+gen_files_kx509_template = asn1_kx509_template_asn1.c >+gen_files_x690sample = asn1_x690sample_asn1.c >+gen_files_x690sample_template = asn1_x690sample_template_asn1.c > > oid_resolution.lo: $(BUILT_SOURCES) > >@@ -100,20 +102,20 @@ check_PROGRAMS = $(TESTS) > > asn1_gen_SOURCES = asn1_gen.c > asn1_print_SOURCES = asn1_print.c >-asn1_print_SOURCES += $(gen_files_x690sample_template:.x=.c) >+asn1_print_SOURCES += $(gen_files_x690sample_template) > asn1_print_CPPFLAGS = -DASN1_PRINT_SUPPORTED > check_der_SOURCES = check-der.c check-common.c check-common.h > > check_template_SOURCES = check-template.c check-common.c check-common.h >-nodist_check_template_SOURCES = $(gen_files_test_template:.x=.c) >+nodist_check_template_SOURCES = $(gen_files_test_template) > > check_gen_template_CPPFLAGS = -DASN1_IOS_SUPPORTED > dist_check_gen_template_SOURCES = check-gen.c check-common.c check-common.h >-nodist_check_gen_template_SOURCES = $(gen_files_test_template:.x=.c) \ >- $(gen_files_x690sample_template:.x=.c) >+nodist_check_gen_template_SOURCES = $(gen_files_test_template) \ >+ $(gen_files_x690sample_template) > > dist_check_gen_SOURCES = check-gen.c check-common.c check-common.h >-nodist_check_gen_SOURCES = $(gen_files_test:.x=.c) $(gen_files_x690sample:.x=.c) >+nodist_check_gen_SOURCES = $(gen_files_test) $(gen_files_x690sample) > > build_HEADERZ = asn1-template.h > >@@ -229,37 +231,37 @@ CLEANFILES = \ > $(nodist_check_gen_SOURCES) \ > asn1parse.c asn1parse.h lex.c \ > asn1_err.c asn1_err.h \ >- rfc2459_asn1_files rfc2459_asn1*.h* rfc2459_asn1*.x \ >- rfc2459_template_asn1_files rfc2459_template_asn1*.h* rfc2459_template_asn1*.x \ >- rfc4108_asn1_files rfc4108_asn1*.h* rfc4108_asn1*.x \ >- rfc4108_template_asn1_files rfc4108_template_asn1*.h* rfc4108_template_asn1*.x \ >- cms_asn1_files cms_asn1*.h* cms_asn1*.x \ >- cms_template_asn1_files cms_template_asn1*.h* cms_template_asn1*.x \ >- crmf_asn1_files crmf_asn1*.h* crmf_asn1*.x \ >- crmf_template_asn1_files crmf_template_asn1*.h* crmf_template_asn1*.x \ >- krb5_asn1_files krb5_asn1*.h* krb5_asn1*.x \ >- krb5_template_asn1_files krb5_template_asn1*.h* krb5_template_asn1*.x \ >- ocsp_asn1_files ocsp_asn1*.h* ocsp_asn1*.x \ >- ocsp_template_asn1_files ocsp_template_asn1*.h* ocsp_template_asn1*.x \ >- pkinit_asn1_files pkinit_asn1*.h* pkinit_asn1*.x \ >- pkinit_template_asn1_files pkinit_template_asn1*.h* pkinit_template_asn1*.x \ >- pkcs8_asn1_files pkcs8_asn1*.h* pkcs8_asn1*.x* \ >- pkcs8_template_asn1_files pkcs8_template_asn1*.h* pkcs8_template_asn1*.x* \ >- pkcs9_asn1_files pkcs9_asn1*.h* pkcs9_asn1*.x \ >- pkcs9_template_asn1_files pkcs9_template_asn1*.h* pkcs9_template_asn1*.x \ >- pkcs10_asn1_files pkcs10_asn1*.h* pkcs10_asn1*.x \ >- pkcs10_template_asn1_files pkcs10_template_asn1*.h* pkcs10_template_asn1*.x \ >- pkcs12_asn1_files pkcs12_asn1*.h* pkcs12_asn1*.x \ >- pkcs12_template_asn1_files pkcs12_template_asn1*.h* pkcs12_template_asn1*.x \ >- digest_asn1_files digest_asn1*.h* digest_asn1*.x \ >- digest_template_asn1_files digest_template_asn1*.h* digest_template_asn1*.x \ >- kx509_asn1_files kx509_asn1*.h* kx509_asn1*.x \ >- kx509_template_asn1_files kx509_template_asn1*.h* kx509_template_asn1*.x \ >- x690sample_asn1_files x690sample_asn1*.h* x690sample_asn1*.x \ >- x690sample_template_asn1_files x690sample_template_asn1*.h* x690sample_template_asn1*.x \ >- test_asn1_files test_asn1*.h* test_asn1*.x \ >- test_template_asn1_files test_template_asn1*.h* test_template_asn1*.x \ >- asn1_*.tmp.c asn1_*.x asn1_*.json >+ rfc2459_asn1_files rfc2459_asn1*.h \ >+ rfc2459_template_asn1_files rfc2459_template_asn1*.h \ >+ rfc4108_asn1_files rfc4108_asn1*.h \ >+ rfc4108_template_asn1_files rfc4108_template_asn1*.h \ >+ cms_asn1_files cms_asn1*.h \ >+ cms_template_asn1_files cms_template_asn1* \ >+ crmf_asn1_files crmf_asn1* \ >+ crmf_template_asn1_files crmf_template_asn1* \ >+ krb5_asn1_files krb5_asn1* \ >+ krb5_template_asn1_files krb5_template_asn1* \ >+ ocsp_asn1_files ocsp_asn1* \ >+ ocsp_template_asn1_files ocsp_template_asn1* \ >+ pkinit_asn1_files pkinit_asn1* \ >+ pkinit_template_asn1_files pkinit_template_asn1* \ >+ pkcs8_asn1_files pkcs8_asn1* \ >+ pkcs8_template_asn1_files pkcs8_template_asn1* \ >+ pkcs9_asn1_files pkcs9_asn1* \ >+ pkcs9_template_asn1_files pkcs9_template_asn1* \ >+ pkcs10_asn1_files pkcs10_asn1* \ >+ pkcs10_template_asn1_files pkcs10_template_asn1* \ >+ pkcs12_asn1_files pkcs12_asn1* \ >+ pkcs12_template_asn1_files pkcs12_template_asn1* \ >+ digest_asn1_files digest_asn1* \ >+ digest_template_asn1_files digest_template_asn1* \ >+ kx509_asn1_files kx509_asn1* \ >+ kx509_template_asn1_files kx509_template_asn1* \ >+ x690sample_asn1_files x690sample_asn1* \ >+ x690sample_template_asn1_files x690sample_template_asn1* \ >+ test_asn1_files test_asn1* \ >+ test_template_asn1_files test_template_asn1* \ >+ asn1_*_asn1.c *_asn1.json *_asn1_syms.c *_asn1_oids.c > > dist_include_HEADERS = der.h heim_asn1.h > dist_include_HEADERS += $(srcdir)/der-protos.h $(srcdir)/der-private.h >@@ -338,36 +340,36 @@ $(asn1_print_OBJECTS): $(nodist_include_HEADERS) $(priv_headers) > > asn1parse.h: asn1parse.c > >-$(gen_files_krb5) krb5_asn1.hx krb5_asn1-priv.hx: krb5_asn1_files >-$(gen_files_krb5_template) krb5_template_asn1.hx krb5_template_asn1-priv.hx: krb5_template_asn1_files >-$(gen_files_ocsp) ocsp_asn1.hx ocsp_asn1-priv.hx: ocsp_asn1_files >-$(gen_files_ocsp_template) ocsp_template_asn1.hx ocsp_template_asn1-priv.hx: ocsp_template_asn1_files >-$(gen_files_pkinit) pkinit_asn1.hx pkinit_asn1-priv.hx: pkinit_asn1_files >-$(gen_files_pkinit_template) pkinit_template_asn1.hx pkinit_template_asn1-priv.hx: pkinit_template_asn1_files >-$(gen_files_pkcs8) pkcs8_asn1.hx pkcs8_asn1-priv.hx: pkcs8_asn1_files >-$(gen_files_pkcs8_template) pkcs8_template_asn1.hx pkcs8_template_asn1-priv.hx: pkcs8_template_asn1_files >-$(gen_files_pkcs9) pkcs9_asn1.hx pkcs9_asn1-priv.hx: pkcs9_asn1_files >-$(gen_files_pkcs9_template) pkcs9_template_asn1.hx pkcs9_template_asn1-priv.hx: pkcs9_template_asn1_files >-$(gen_files_pkcs10) pkcs10_asn1.hx pkcs10_asn1-priv.hx: pkcs10_asn1_files >-$(gen_files_pkcs10_template) pkcs10_template_asn1.hx pkcs10_template_asn1-priv.hx: pkcs10_template_asn1_files >-$(gen_files_pkcs12) pkcs12_asn1.hx pkcs12_asn1-priv.hx: pkcs12_asn1_files >-$(gen_files_pkcs12_template) pkcs12_template_asn1.hx pkcs12_template_asn1-priv.hx: pkcs12_template_asn1_files >-$(gen_files_digest) digest_asn1.hx digest_asn1-priv.hx: digest_asn1_files >-$(gen_files_digest_template) digest_template_asn1.hx digest_template_asn1-priv.hx: digest_template_asn1_files >-$(gen_files_kx509) kx509_asn1.hx kx509_asn1-priv.hx: kx509_asn1_files >-$(gen_files_kx509_template) kx509_template_asn1.hx kx509_template_asn1-priv.hx: kx509_template_asn1_files >-$(gen_files_rfc2459) rfc2459_asn1.hx rfc2459_asn1-priv.hx: rfc2459_asn1_files >-$(gen_files_rfc2459_template) rfc2459_template_asn1.hx rfc2459_template_asn1-priv.hx: rfc2459_template_asn1_files >-$(gen_files_rfc4108) rfc4108_asn1.hx rfc4108_asn1-priv.hx: rfc4108_asn1_files >-$(gen_files_rfc4108_template) rfc4108_template_asn1.hx rfc4108_template_asn1-priv.hx: rfc4108_template_asn1_files >-$(gen_files_cms) cms_asn1.hx cms_asn1-priv.hx: cms_asn1_files >-$(gen_files_cms_template) cms_template_asn1.hx cms_template_asn1-priv.hx: cms_template_asn1_files >-$(gen_files_crmf) crmf_asn1.hx crmf_asn1-priv.hx: crmf_asn1_files >-$(gen_files_crmf_template) crmf_template_asn1.hx crmf_template_asn1-priv.hx: crmf_template_asn1_files >-$(gen_files_x690sample) x690sample_asn1.hx x690sample_asn1-priv.hx: x690sample_asn1_files >-$(gen_files_x690sample_template) x690sample_template_asn1.hx x690sample_template_asn1-priv.hx: x690sample_template_asn1_files >-$(gen_files_test) test_asn1.hx test_asn1-priv.hx: test_asn1_files >-$(gen_files_test_template) test_template_asn1.hx test_template_asn1-priv.hx: test_template_asn1_files >+$(gen_files_krb5) krb5_asn1.h krb5_asn1-priv.h: krb5_asn1_files >+$(gen_files_krb5_template) krb5_template_asn1.h krb5_template_asn1-priv.h: krb5_template_asn1_files >+$(gen_files_ocsp) ocsp_asn1.h ocsp_asn1-priv.h: ocsp_asn1_files >+$(gen_files_ocsp_template) ocsp_template_asn1.h ocsp_template_asn1-priv.h: ocsp_template_asn1_files >+$(gen_files_pkinit) pkinit_asn1.h pkinit_asn1-priv.h: pkinit_asn1_files >+$(gen_files_pkinit_template) pkinit_template_asn1.h pkinit_template_asn1-priv.h: pkinit_template_asn1_files >+$(gen_files_pkcs8) pkcs8_asn1.h pkcs8_asn1-priv.h: pkcs8_asn1_files >+$(gen_files_pkcs8_template) pkcs8_template_asn1.h pkcs8_template_asn1-priv.h: pkcs8_template_asn1_files >+$(gen_files_pkcs9) pkcs9_asn1.h pkcs9_asn1-priv.h: pkcs9_asn1_files >+$(gen_files_pkcs9_template) pkcs9_template_asn1.h pkcs9_template_asn1-priv.h: pkcs9_template_asn1_files >+$(gen_files_pkcs10) pkcs10_asn1.h pkcs10_asn1-priv.h: pkcs10_asn1_files >+$(gen_files_pkcs10_template) pkcs10_template_asn1.h pkcs10_template_asn1-priv.h: pkcs10_template_asn1_files >+$(gen_files_pkcs12) pkcs12_asn1.h pkcs12_asn1-priv.h: pkcs12_asn1_files >+$(gen_files_pkcs12_template) pkcs12_template_asn1.h pkcs12_template_asn1-priv.h: pkcs12_template_asn1_files >+$(gen_files_digest) digest_asn1.h digest_asn1-priv.h: digest_asn1_files >+$(gen_files_digest_template) digest_template_asn1.h digest_template_asn1-priv.h: digest_template_asn1_files >+$(gen_files_kx509) kx509_asn1.h kx509_asn1-priv.h: kx509_asn1_files >+$(gen_files_kx509_template) kx509_template_asn1.h kx509_template_asn1-priv.h: kx509_template_asn1_files >+$(gen_files_rfc2459) rfc2459_asn1.h rfc2459_asn1-priv.h: rfc2459_asn1_files >+$(gen_files_rfc2459_template) rfc2459_template_asn1.h rfc2459_template_asn1-priv.h: rfc2459_template_asn1_files >+$(gen_files_rfc4108) rfc4108_asn1.h rfc4108_asn1-priv.h: rfc4108_asn1_files >+$(gen_files_rfc4108_template) rfc4108_template_asn1.h rfc4108_template_asn1-priv.h: rfc4108_template_asn1_files >+$(gen_files_cms) cms_asn1.h cms_asn1-priv.h: cms_asn1_files >+$(gen_files_cms_template) cms_template_asn1.h cms_template_asn1-priv.h: cms_template_asn1_files >+$(gen_files_crmf) crmf_asn1.h crmf_asn1-priv.h: crmf_asn1_files >+$(gen_files_crmf_template) crmf_template_asn1.h crmf_template_asn1-priv.h: crmf_template_asn1_files >+$(gen_files_x690sample) x690sample_asn1.h x690sample_asn1-priv.h: x690sample_asn1_files >+$(gen_files_x690sample_template) x690sample_template_asn1.h x690sample_template_asn1-priv.h: x690sample_template_asn1_files >+$(gen_files_test) test_asn1.h test_asn1-priv.h: test_asn1_files >+$(gen_files_test_template) test_template_asn1.h test_template_asn1-priv.h: test_template_asn1_files > > if ASN1_TEMPLATING > TEMPLATE_OPTION=--template >@@ -379,136 +381,171 @@ endif > # templated anyways. > rfc2459_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc2459.asn1 > $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/rfc2459.opt $(srcdir)/rfc2459.asn1 rfc2459_template_asn1 || (rm -f rfc2459_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc2459_template_asn1.c > > rfc4108_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc4108.asn1 > $(ASN1_COMPILE) --one-code-file --template $(srcdir)/rfc4108.asn1 rfc4108_template_asn1 || (rm -f rfc4108_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc4108_template_asn1.c > > cms_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/cms.asn1 $(srcdir)/cms.opt > $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/cms.opt $(srcdir)/cms.asn1 cms_template_asn1 || (rm -f cms_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_cms_template_asn1.c > > crmf_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/crmf.asn1 $(srcdir)/crmf.opt > $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/crmf.opt $(srcdir)/crmf.asn1 crmf_template_asn1 || (rm -f crmf_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_crmf_template_asn1.c > > krb5_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/krb5.asn1 $(srcdir)/krb5.opt > $(ASN1_COMPILE) --one-code-file --template \ > --option-file=$(srcdir)/krb5.opt \ >- --decorate='Principal:PrincipalNameAttrs:nameattrs?' \ > $(srcdir)/krb5.asn1 krb5_template_asn1 || (rm -f krb5_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_krb5_template_asn1.c > > ocsp_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1 > $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_template_asn1 || (rm -f ocsp_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_ocsp_template_asn1.c > > pkinit_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1 > $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkinit.asn1 pkinit_template_asn1 || (rm -f pkinit_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkinit_template_asn1.c > > pkcs8_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs8.asn1 > $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkcs8.asn1 pkcs8_template_asn1 || (rm -f pkcs8_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs8_template_asn1.c > > pkcs9_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs9.asn1 > $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkcs9.asn1 pkcs9_template_asn1 || (rm -f pkcs9_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs9_template_asn1.c > > pkcs10_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs10.asn1 > $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/pkcs10.opt $(srcdir)/pkcs10.asn1 pkcs10_template_asn1 || (rm -f pkcs10_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs10_template_asn1.c > > pkcs12_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs12.asn1 > $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkcs12.asn1 pkcs12_template_asn1 || (rm -f pkcs12_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs12_template_asn1.c > > digest_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/digest.asn1 > $(ASN1_COMPILE) --one-code-file --template $(srcdir)/digest.asn1 digest_template_asn1 || (rm -f digest_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_digest_template_asn1.c > > kx509_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/kx509.asn1 > $(ASN1_COMPILE) --one-code-file --template $(srcdir)/kx509.asn1 kx509_template_asn1 || (rm -f kx509_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_kx509_template_asn1.c > > rfc2459_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc2459.asn1 > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/rfc2459.opt $(srcdir)/rfc2459.asn1 rfc2459_asn1 || (rm -f rfc2459_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc2459_asn1.c > > rfc4108_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc4108.asn1 > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/rfc4108.asn1 rfc4108_asn1 || (rm -f rfc4108_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc4108_asn1.c > > cms_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/cms.asn1 $(srcdir)/cms.opt > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/cms.opt $(srcdir)/cms.asn1 cms_asn1 || (rm -f cms_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_cms_asn1.c > > crmf_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/crmf.asn1 $(srcdir)/crmf.opt > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/crmf.opt $(srcdir)/crmf.asn1 crmf_asn1 || (rm -f crmf_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_crmf_asn1.c > > krb5_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/krb5.asn1 $(srcdir)/krb5.opt > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) \ > --option-file=$(srcdir)/krb5.opt \ >- --decorate='Principal:PrincipalNameAttrs:nameattrs?' \ > $(srcdir)/krb5.asn1 krb5_asn1 || (rm -f krb5_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_krb5_asn1.c > > ocsp_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1 > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_asn1 || (rm -f ocsp_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_ocsp_asn1.c > > pkinit_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1 > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkinit.asn1 pkinit_asn1 || (rm -f pkinit_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkinit_asn1.c > > pkcs8_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs8.asn1 > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkcs8.asn1 pkcs8_asn1 || (rm -f pkcs8_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs8_asn1.c > > pkcs9_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs9.asn1 > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkcs9.asn1 pkcs9_asn1 || (rm -f pkcs9_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs9_asn1.c > > pkcs10_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs10.asn1 > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/pkcs10.opt $(srcdir)/pkcs10.asn1 pkcs10_asn1 || (rm -f pkcs10_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs10_asn1.c > > pkcs12_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs12.asn1 > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkcs12.asn1 pkcs12_asn1 || (rm -f pkcs12_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs12_asn1.c > > digest_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/digest.asn1 > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/digest.asn1 digest_asn1 || (rm -f digest_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_digest_asn1.c > > kx509_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/kx509.asn1 > $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/kx509.asn1 kx509_asn1 || (rm -f kx509_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_kx509_asn1.c > > x690sample_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/x690sample.asn1 > $(ASN1_COMPILE) --one-code-file --template $(srcdir)/x690sample.asn1 x690sample_template_asn1 || (rm -f x690sample_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_x690sample_template_asn1.c > > x690sample_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/x690sample.asn1 > $(ASN1_COMPILE) --one-code-file $(srcdir)/x690sample.asn1 x690sample_asn1 || (rm -f x690sample_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_x690sample_asn1.c > > test_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1 > $(ASN1_COMPILE) --one-code-file \ > --template \ >- --sequence=TESTSeqOf \ >- --decorate='TESTDecorated:TESTuint32:version2?' \ >+ --option-file=$(srcdir)/test.opt \ > $(srcdir)/test.asn1 test_template_asn1 || (rm -f test_template_asn1_files ; exit 1) >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_test_template_asn1.c > > test_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1 > $(ASN1_COMPILE) --one-code-file \ >- --decorate='TESTDecorated:TESTuint32:version2?' \ >- --sequence=TESTSeqOf \ >+ --option-file=$(srcdir)/test.opt \ > $(srcdir)/test.asn1 test_asn1 || (rm -f test_asn1_files ; exit 1) >- >- >-EXTRA_DIST = \ >- NTMakefile \ >- README.template \ >- asn1_compile-version.rc \ >- libasn1-exports.def \ >- cms.asn1 \ >- cms.opt \ >- crmf.asn1 \ >- crmf.opt \ >- asn1_err.et \ >- canthandle.asn1 \ >- digest.asn1 \ >- krb5.asn1 \ >- krb5.opt \ >- kx509.asn1 \ >- ocsp.asn1 \ >- pkcs12.asn1 \ >- pkcs8.asn1 \ >- pkcs9.asn1 \ >- pkcs10.asn1 \ >- pkinit.asn1 \ >- rfc2459.asn1 \ >- rfc4108.asn1 \ >- tcg.asn1 \ >- setchgpw2.asn1 \ >- x690sample.asn1 \ >- test.asn1 \ >- test.gen \ >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_test_asn1.c >+ >+ >+EXTRA_DIST = \ >+ NTMakefile \ >+ README-template.md \ >+ asn1_compile-version.rc \ >+ libasn1-exports.def \ >+ canthandle.asn1 \ >+ cms.asn1 \ >+ cms.opt \ >+ crmf.asn1 \ >+ crmf.opt \ >+ digest.asn1 \ >+ krb5.asn1 \ >+ krb5.opt \ >+ kx509.asn1 \ >+ ocsp.asn1 \ >+ ocsp.opt \ >+ pkcs10.asn1 \ >+ pkcs10.opt \ >+ pkcs12.asn1 \ >+ pkcs8.asn1 \ >+ pkcs9.asn1 \ >+ pkinit.asn1 \ >+ pku2u.asn1 \ >+ rfc2459.asn1 \ >+ rfc2459.opt \ >+ rfc4108.asn1 \ >+ setchgpw2.asn1 \ >+ tcg.asn1 \ >+ test.asn1 \ >+ test.opt \ >+ x690sample.asn1 \ >+ test.gen \ >+ asn1_err.et \ >+ asn1_err.c \ >+ asn1_err.h \ >+ asn1_print.1 \ >+ asn1_compile.1 \ > version-script.map > > DER_PROTOS = $(srcdir)/der-protos.h $(srcdir)/der-private.h >diff --git a/third_party/heimdal/lib/asn1/NTMakefile b/third_party/heimdal/lib/asn1/NTMakefile >index eca92bd3853c..19255c6cf710 100644 >--- a/third_party/heimdal/lib/asn1/NTMakefile >+++ b/third_party/heimdal/lib/asn1/NTMakefile >@@ -1,6 +1,6 @@ > ######################################################################## > # >-# Copyright (c) 2009, Secure Endpoints Inc. >+# Copyright (c) 2009-2022, Secure Endpoints Inc. > # All rights reserved. > # > # Redistribution and use in source and binary forms, with or without >@@ -31,42 +31,10 @@ > > RELDIR=lib\asn1 > >-intcflags=-I$(SRCDIR) -I$(OBJ) -DROKEN_RENAME -DASN1_IOS_SUPPORTED >+intcflags=-I$(SRCDIR) -I$(OBJ) -DROKEN_RENAME -DASN1_IOS_SUPPORTED -DASN1_LIB > > !include ../../windows/NTMakefile.w32 > >-gen_files_krb5 = $(OBJ)\asn1_krb5_asn1.x >- >-gen_files_cms = $(OBJ)\asn1_cms_asn1.x >- >-gen_files_crmf = $(OBJ)\asn1_crmf_asn1.x >- >-gen_files_rfc2459 = $(OBJ)\asn1_rfc2459_asn1.x >- >-gen_files_rfc4108 = $(OBJ)\asn1_rfc4108_asn1.x >- >-gen_files_ocsp = $(OBJ)\asn1_ocsp_asn1.x >- >-gen_files_pkinit = $(OBJ)\asn1_pkinit_asn1.x >- >-gen_files_pkcs12 = $(OBJ)\asn1_pkcs12_asn1.x >- >-gen_files_pkcs8 = $(OBJ)\asn1_pkcs8_asn1.x >- >-gen_files_pkcs9 = $(OBJ)\asn1_pkcs9_asn1.x >- >-gen_files_pkcs10 = $(OBJ)\asn1_pkcs10_asn1.x >- >-gen_files_test = $(OBJ)\asn1_test_asn1.x >- >-gen_files_test_template = $(OBJ)\asn1_test_template_asn1.x >- >-gen_files_digest = $(OBJ)\asn1_digest_asn1.x >- >-gen_files_kx509 = $(OBJ)\asn1_kx509_asn1.x >- >-gen_files_x690sample = $(OBJ)\asn1_x690sample_asn1.x >- > ASN1_BINARIES = \ > $(LIBEXECDIR)\asn1_compile.exe > >@@ -112,6 +80,21 @@ $(BINDIR)\asn1_gen.exe: $(OBJ)\asn1_gen.obj $(LIBHEIMDAL) > $(EXECONLINK) $(LIBVERS) $(LIBROKEN) > $(EXEPREP) > >+LIBASN1_X= \ >+ $(OBJ)\asn1_rfc2459_asn1.c \ >+ $(OBJ)\asn1_rfc4108_asn1.c \ >+ $(OBJ)\asn1_cms_asn1.c \ >+ $(OBJ)\asn1_krb5_asn1.c \ >+ $(OBJ)\asn1_ocsp_asn1.c \ >+ $(OBJ)\asn1_pkinit_asn1.c \ >+ $(OBJ)\asn1_pkcs8_asn1.c \ >+ $(OBJ)\asn1_pkcs9_asn1.c \ >+ $(OBJ)\asn1_pkcs10_asn1.c \ >+ $(OBJ)\asn1_pkcs12_asn1.c \ >+ $(OBJ)\asn1_digest_asn1.c \ >+ $(OBJ)\asn1_kx509_asn1.c \ >+ $(OBJ)\asn1_x690sample_asn1.c >+ > LIBASN1_OBJS= \ > $(OBJ)\der.obj \ > $(OBJ)\der_get.obj \ >@@ -124,27 +107,26 @@ LIBASN1_OBJS= \ > $(OBJ)\der_format.obj \ > $(OBJ)\template.obj \ > $(OBJ)\extra.obj \ >+ $(OBJ)\oid_resolution.obj \ > $(OBJ)\timegm.obj \ >- $(gen_files_rfc2459:.x=.obj) \ >- $(gen_files_rfc4108:.x=.obj) \ >- $(gen_files_cms:.x=.obj) \ >- $(gen_files_krb5:.x=.obj) \ >- $(gen_files_ocsp:.x=.obj) \ >- $(gen_files_pkinit:.x=.obj) \ >- $(gen_files_pkcs8:.x=.obj) \ >- $(gen_files_pkcs9:.x=.obj) \ >- $(gen_files_pkcs10:.x=.obj) \ >- $(gen_files_pkcs12:.x=.obj) \ >- $(gen_files_digest:.x=.obj) \ >- $(gen_files_kx509:.x=.obj) \ >- $(gen_files_x690sample:.x=.obj) \ >+ $(OBJ)\asn1_rfc2459_asn1.obj \ >+ $(OBJ)\asn1_rfc4108_asn1.obj \ >+ $(OBJ)\asn1_cms_asn1.obj \ >+ $(OBJ)\asn1_krb5_asn1.obj \ >+ $(OBJ)\asn1_ocsp_asn1.obj \ >+ $(OBJ)\asn1_pkinit_asn1.obj \ >+ $(OBJ)\asn1_pkcs8_asn1.obj \ >+ $(OBJ)\asn1_pkcs9_asn1.obj \ >+ $(OBJ)\asn1_pkcs10_asn1.obj \ >+ $(OBJ)\asn1_pkcs12_asn1.obj \ >+ $(OBJ)\asn1_digest_asn1.obj \ >+ $(OBJ)\asn1_kx509_asn1.obj \ >+ $(OBJ)\asn1_x690sample_asn1.obj \ > $(OBJ)\asn1_err.obj > >-$(OBJ)\oid_resolution.obj: $(LIBASN1_OBJS) >- >-LIBASN1_OBJS2= $(LIBASN1_OBJS) $(OBJ)\oid_resolution.obj >+$(OBJ)\oid_resolution.obj: $(LIBASN1_X) > >-$(LIBASN1): $(LIBASN1_OBJS2) >+$(LIBASN1): $(LIBASN1_OBJS) > $(LIBCON_C) -out:$@ @<< > $(**: = > ) >@@ -154,61 +136,159 @@ clean:: > -$(RM) $(LIBASN1) > > # >-# Generate list of exports >-# >-# This target is only used during development to generate a list of >-# symbols that are exported from all the object files in LIBASN1_OBJS. >-# >-exports-list.txt: $(LIBASN1_OBJS) >- $(PERL) ..\..\cf\w32-list-externs-from-objs.pl -q -u @<< > $@ >-$(**: = >-) >-<< >+# The static runtime version LIBASN1_S is for use by thirdparty >+# components. It is not used in the construction of the Heimdal >+# DLLs. >+ >+LIBASN1_S_OBJS= \ >+ $(OBJ)\der.s.obj \ >+ $(OBJ)\der_get.s.obj \ >+ $(OBJ)\der_put.s.obj \ >+ $(OBJ)\der_free.s.obj \ >+ $(OBJ)\der_print.s.obj \ >+ $(OBJ)\der_length.s.obj \ >+ $(OBJ)\der_copy.s.obj \ >+ $(OBJ)\der_cmp.s.obj \ >+ $(OBJ)\der_format.s.obj \ >+ $(OBJ)\template.s.obj \ >+ $(OBJ)\extra.s.obj \ >+ $(OBJ)\oid_resolution.s.obj \ >+ $(OBJ)\timegm.s.obj \ >+ $(OBJ)\asn1_rfc2459_asn1.s.obj \ >+ $(OBJ)\asn1_rfc4108_asn1.s.obj \ >+ $(OBJ)\asn1_cms_asn1.s.obj \ >+ $(OBJ)\asn1_krb5_asn1.s.obj \ >+ $(OBJ)\asn1_ocsp_asn1.s.obj \ >+ $(OBJ)\asn1_pkinit_asn1.s.obj \ >+ $(OBJ)\asn1_pkcs8_asn1.s.obj \ >+ $(OBJ)\asn1_pkcs9_asn1.s.obj \ >+ $(OBJ)\asn1_pkcs10_asn1.s.obj \ >+ $(OBJ)\asn1_pkcs12_asn1.s.obj \ >+ $(OBJ)\asn1_digest_asn1.s.obj \ >+ $(OBJ)\asn1_kx509_asn1.s.obj \ >+ $(OBJ)\asn1_x690sample_asn1.s.obj \ >+ $(OBJ)\asn1_err.s.obj >+ >+$(OBJ)\oid_resolution.s.obj: oid_resolution.c $(LIBASN1_X) >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ oid_resolution.c >+ >+$(OBJ)\der.s.obj: der.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** >+ >+$(OBJ)\der_get.s.obj: der_get.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_krb5:.x=.c) : $$(@R).x >+$(OBJ)\der_put.s.obj: der_put.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_ocsp:.x=.c) : $$(@R).x >+$(OBJ)\der_free.s.obj: der_free.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_pkinit:.x=.c) : $$(@R).x >+$(OBJ)\der_print.s.obj: der_print.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_pkcs8:.x=.c) : $$(@R).x >+$(OBJ)\der_length.s.obj: der_length.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_pkcs9:.x=.c) : $$(@R).x >+$(OBJ)\der_copy.s.obj: der_copy.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_pkcs10:.x=.c) : $$(@R).x >+$(OBJ)\der_cmp.s.obj: der_cmp.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_pkcs12:.x=.c) : $$(@R).x >+$(OBJ)\der_format.s.obj: der_format.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_digest:.x=.c) : $$(@R).x >+$(OBJ)\template.s.obj: template.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_kx509:.x=.c) : $$(@R).x >+$(OBJ)\extra.s.obj: extra.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_rfc2459:.x=.c) : $$(@R).x >+$(OBJ)\timegm.s.obj: timegm.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_rfc4108:.x=.c) : $$(@R).x >+$(OBJ)\asn1_rfc2459_asn1.s.obj: $(OBJ)\asn1_rfc2459_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_cms:.x=.c) : $$(@R).x >+$(OBJ)\asn1_rfc4108_asn1.s.obj: $(OBJ)\asn1_rfc4108_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_crmf:.x=.c) : $$(@R).x >+$(OBJ)\asn1_cms_asn1.s.obj: $(OBJ)\asn1_cms_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_x690sample:.x=.c) : $$(@R).x >+$(OBJ)\asn1_krb5_asn1.s.obj: $(OBJ)\asn1_krb5_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_test:.x=.c) : $$(@R).x >+$(OBJ)\asn1_ocsp_asn1.s.obj: $(OBJ)\asn1_ocsp_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_test_template:.x=.c) : $$(@R).x >+$(OBJ)\asn1_pkinit_asn1.s.obj: $(OBJ)\asn1_pkinit_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** > >-$(gen_files_krb5) $(OBJ)\krb5_asn1.hx: $(BINDIR)\asn1_compile.exe krb5.asn1 krb5.opt >+$(OBJ)\asn1_pkcs8_asn1.s.obj: $(OBJ)\asn1_pkcs8_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** >+ >+$(OBJ)\asn1_pkcs9_asn1.s.obj: $(OBJ)\asn1_pkcs9_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** >+ >+$(OBJ)\asn1_pkcs10_asn1.s.obj: $(OBJ)\asn1_pkcs10_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** >+ >+$(OBJ)\asn1_pkcs12_asn1.s.obj: $(OBJ)\asn1_pkcs12_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** >+ >+$(OBJ)\asn1_digest_asn1.s.obj: $(OBJ)\asn1_digest_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** >+ >+$(OBJ)\asn1_kx509_asn1.s.obj: $(OBJ)\asn1_kx509_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** >+ >+$(OBJ)\asn1_x690sample_asn1.s.obj: $(OBJ)\asn1_x690sample_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** >+ >+$(OBJ)\asn1_test_asn1.s.obj: $(OBJ)\asn1_test_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** >+ >+$(OBJ)\asn1_test_template_asn1.s.obj: $(OBJ)\asn1_test_template_asn1.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** >+ >+$(OBJ)\asn1_err.s.obj: $(OBJ)\asn1_err.c >+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $** >+ >+$(LIBASN1_S): $(LIBASN1_S_OBJS) >+ $(LIBCON_C) -out:$@ @<< >+$(**: = >+) >+<< >+ >+clean:: >+ -$(RM) $(LIBASN1_S) >+ >+ >+# >+# Generate list of exports >+# >+# This target is only used during development to generate a list of >+# symbols that are exported from all the object files in LIBASN1_OBJS. >+# >+exports-list.txt: $(LIBASN1_OBJS) >+ $(PERL) ..\..\cf\w32-list-externs-from-objs.pl -q -u @<< > $@ >+$(**: = >+) >+<< >+ >+$(OBJ)\asn1_krb5_asn1.c $(OBJ)\krb5_asn1.h: $(BINDIR)\asn1_compile.exe krb5.asn1 krb5.opt > cd $(OBJ) > $(BINDIR)\asn1_compile.exe \ > --template \ > --one-code-file \ >- --decorate="Principal:PrincipalNameAttrs:nameattrs?" \ > --option-file=$(SRCDIR)\krb5.opt \ > $(SRCDIR)\krb5.asn1 krb5_asn1 \ > || ($(RM) $(OBJ)\krb5_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_ocsp) $(OBJ)\ocsp_asn1.hx: $(BINDIR)\asn1_compile.exe ocsp.asn1 >+$(OBJ)\asn1_ocsp_asn1.c $(OBJ)\ocsp_asn1.h: $(BINDIR)\asn1_compile.exe ocsp.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe \ > --template \ >@@ -219,25 +299,25 @@ $(gen_files_ocsp) $(OBJ)\ocsp_asn1.hx: $(BINDIR)\asn1_compile.exe ocsp.asn1 > || ($(RM) $(OBJ)\ocsp_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_pkinit) $(OBJ)\pkinit_asn1.hx: $(BINDIR)\asn1_compile.exe pkinit.asn1 >+$(OBJ)\asn1_pkinit_asn1.c $(OBJ)\pkinit_asn1.h: $(BINDIR)\asn1_compile.exe pkinit.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkinit.asn1 pkinit_asn1 \ > || ($(RM) $(OBJ)\pkinit_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_pkcs8) $(OBJ)\pkcs8_asn1.hx: $(BINDIR)\asn1_compile.exe pkcs8.asn1 >+$(OBJ)\asn1_pkcs8_asn1.c $(OBJ)\pkcs8_asn1.h: $(BINDIR)\asn1_compile.exe pkcs8.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkcs8.asn1 pkcs8_asn1 \ > || ($(RM) $(OBJ)\pkcs8_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_pkcs9) $(OBJ)\pkcs9_asn1.hx: $(BINDIR)\asn1_compile.exe pkcs9.asn1 >+$(OBJ)\asn1_pkcs9_asn1.c $(OBJ)\pkcs9_asn1.h: $(BINDIR)\asn1_compile.exe pkcs9.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkcs9.asn1 pkcs9_asn1 \ > || ($(RM) $(OBJ)\pkcs9_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_pkcs10) $(OBJ)\pkcs10_asn1.hx: $(BINDIR)\asn1_compile.exe pkcs10.asn1 >+$(OBJ)\asn1_pkcs10_asn1.c $(OBJ)\pkcs10_asn1.h: $(BINDIR)\asn1_compile.exe pkcs10.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe \ > --template \ >@@ -248,25 +328,25 @@ $(gen_files_pkcs10) $(OBJ)\pkcs10_asn1.hx: $(BINDIR)\asn1_compile.exe pkcs10.asn > || ($(RM) $(OBJ)\pkcs10_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_pkcs12) $(OBJ)\pkcs12_asn1.hx: $(BINDIR)\asn1_compile.exe pkcs12.asn1 >+$(OBJ)\asn1_pkcs12_asn1.c $(OBJ)\pkcs12_asn1.h: $(BINDIR)\asn1_compile.exe pkcs12.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkcs12.asn1 pkcs12_asn1 \ > || ($(RM) $(OBJ)\pkcs12_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_digest) $(OBJ)\digest_asn1.hx: $(BINDIR)\asn1_compile.exe digest.asn1 >+$(OBJ)\asn1_digest_asn1.c $(OBJ)\digest_asn1.h: $(BINDIR)\asn1_compile.exe digest.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\digest.asn1 digest_asn1 \ > || ($(RM) $(OBJ)\digest_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_kx509) $(OBJ)\kx509_asn1.hx: $(BINDIR)\asn1_compile.exe kx509.asn1 >+$(OBJ)\asn1_kx509_asn1.c $(OBJ)\kx509_asn1.h: $(BINDIR)\asn1_compile.exe kx509.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\kx509.asn1 kx509_asn1 \ > || ($(RM) $(OBJ)\kx509_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_rfc2459) $(OBJ)\rfc2459_asn1.hx: $(BINDIR)\asn1_compile.exe rfc2459.asn1 >+$(OBJ)\asn1_rfc2459_asn1.c $(OBJ)\rfc2459_asn1.h: $(BINDIR)\asn1_compile.exe rfc2459.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe \ > --template \ >@@ -276,7 +356,7 @@ $(gen_files_rfc2459) $(OBJ)\rfc2459_asn1.hx: $(BINDIR)\asn1_compile.exe rfc2459. > || ($(RM) $(OBJ)\rfc2459_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_rfc4108) $(OBJ)\rfc4108_asn1.hx: $(BINDIR)\asn1_compile.exe rfc4108.asn1 >+$(OBJ)\asn1_rfc4108_asn1.c $(OBJ)\rfc4108_asn1.h: $(BINDIR)\asn1_compile.exe rfc4108.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe \ > --template \ >@@ -285,7 +365,7 @@ $(gen_files_rfc4108) $(OBJ)\rfc4108_asn1.hx: $(BINDIR)\asn1_compile.exe rfc4108. > || ($(RM) $(OBJ)\rfc4108_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_cms) $(OBJ)\cms_asn1.hx: $(BINDIR)\asn1_compile.exe cms.asn1 cms.opt >+$(OBJ)\asn1_cms_asn1.c $(OBJ)\cms_asn1.h: $(BINDIR)\asn1_compile.exe cms.asn1 cms.opt > cd $(OBJ) > $(BINDIR)\asn1_compile.exe \ > --template \ >@@ -294,7 +374,7 @@ $(gen_files_cms) $(OBJ)\cms_asn1.hx: $(BINDIR)\asn1_compile.exe cms.asn1 cms.opt > || ($(RM) $(OBJ)\cms_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_crmf) $(OBJ)\crmf_asn1.hx: $(BINDIR)\asn1_compile.exe crmf.asn1 crmf.opt >+$(gen_files_crmf) $(OBJ)\crmf_asn1.h: $(BINDIR)\asn1_compile.exe crmf.asn1 crmf.opt > cd $(OBJ) > $(BINDIR)\asn1_compile.exe \ > --template \ >@@ -303,7 +383,7 @@ $(gen_files_crmf) $(OBJ)\crmf_asn1.hx: $(BINDIR)\asn1_compile.exe crmf.asn1 crmf > || ($(RM) $(OBJ)\crmf_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_x690sample) $(OBJ)\x690sample_asn1.hx: $(BINDIR)\asn1_compile.exe x690sample.asn1 >+$(OBJ)\asn1_x690sample_asn1.c $(OBJ)\x690sample_asn1.h: $(BINDIR)\asn1_compile.exe x690sample.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe \ > --template \ >@@ -312,23 +392,22 @@ $(gen_files_x690sample) $(OBJ)\x690sample_asn1.hx: $(BINDIR)\asn1_compile.exe x6 > || ($(RM) $(OBJ)\x690sample_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_test) $(OBJ)\test_asn1.hx: $(BINDIR)\asn1_compile.exe test.asn1 >+$(OBJ)\asn1_test_asn1.c $(OBJ)\test_asn1.h: $(BINDIR)\asn1_compile.exe test.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe \ > --template \ >- --decorate="TESTDecorated:TESTuint32:version2?" \ >- --one-code-file --sequence=TESTSeqOf \ >+ --option-file=$(SRCDIR)/test.opt \ >+ --one-code-file \ > $(SRCDIR)\test.asn1 test_asn1 \ > || ($(RM) $(OBJ)\test_asn1.h ; exit /b 1) > cd $(SRCDIR) > >-$(gen_files_test_template) $(OBJ)\test_template_asn1.hx: $(BINDIR)\asn1_compile.exe test.asn1 >+$(OBJ)\asn1_test_template_asn1.c $(OBJ)\test_template_asn1.h: $(BINDIR)\asn1_compile.exe test.asn1 > cd $(OBJ) > $(BINDIR)\asn1_compile.exe \ > --template \ >- --decorate="TESTDecorated:TESTuint32:version2?" \ >+ --option-file=$(SRCDIR)/test.opt \ > --one-code-file \ >- --sequence=TESTSeqOf \ > $(SRCDIR)\test.asn1 test_template_asn1 \ > || ($(RM) $(OBJ)\test_template_asn1.h ; exit /b 1) > cd $(SRCDIR) >@@ -408,7 +487,7 @@ $(OBJ)\der-private.h: $(libasn1_SOURCES) > clean:: > -$(RM) $(INCDIR)\der-protos.h > >-all:: $(INCFILES) $(GENINCFILES) $(ASN1_BINARIES) $(LIBASN1) >+all:: $(INCFILES) $(GENINCFILES) $(ASN1_BINARIES) $(LIBASN1) $(LIBASN1_S) > > all-tools:: $(LIBEXECDIR)\asn1_print.exe $(BINDIR)\asn1_gen.exe > >@@ -454,7 +533,7 @@ $(OBJ)\check-der.exe: $(OBJ)\check-der.obj $(OBJ)\check-common.obj \ > $(EXEPREP_NODIST) > > $(OBJ)\check-gen-template.exe: $(OBJ)\check-gen.obj $(OBJ)\check-common.obj \ >- $(LIBHEIMDAL) $(LIBROKEN) $(gen_files_test_template:.x=.obj) >+ $(LIBHEIMDAL) $(LIBROKEN) $(OBJ)\asn1_test_template_asn1.obj > $(EXECONLINK) > $(EXEPREP_NODIST) > >@@ -464,6 +543,6 @@ $(OBJ)\check-timegm.exe: $(OBJ)\check-timegm.obj \ > $(EXEPREP_NODIST) > > $(OBJ)\check-template.exe: $(OBJ)\check-template.obj $(OBJ)\check-common.obj \ >- $(LIBHEIMDAL) $(LIBROKEN) $(gen_files_test:.x=.obj) >+ $(LIBHEIMDAL) $(LIBROKEN) $(OBJ)\asn1_test_asn1.obj > $(EXECONLINK) > $(EXEPREP_NODIST) >diff --git a/third_party/heimdal/lib/asn1/README.md b/third_party/heimdal/lib/asn1/README.md >index a00dde72227f..9c4e6979569c 100644 >--- a/third_party/heimdal/lib/asn1/README.md >+++ b/third_party/heimdal/lib/asn1/README.md >@@ -14,7 +14,7 @@ annotations](/lib/asn1/README-X681.md). > 5. [Limitations](#Limitations) > 6. [Compiler Usage](#Compiler-usage) > 7. [APIs Generated by the Compiler](#APIs-generated-by-the-compiler) >- 8. [asn1_print Usage](#asn1_print-usage) >+ 8. [`asn1_print` Usage](#asn1_print-usage) > 9. [Implementation](#implementation) > 10. [Moving From C](#moving-from-c) > >@@ -166,11 +166,14 @@ In recent times the following features have been added: > - Automatic open type traversal, using a subset of X.681/X.682/X.683 for > expressing the requisite metadata. > >+ - Decoration of ASN.1 types with "hidden" fields (ones that don't get encoded >+ or decoded) of ASN.1 or C types. >+ > ## Futures > > - JER support? > >- - XDR/OER support? >+ - XDR/NDR/OER support? > > - Generate comparators? (lib/hx509 has a half-baked Certificate comparator) > >@@ -181,6 +184,43 @@ In recent times the following features have been added: > - Most of X.690 is supported for decoding, with only DER supported for > encoding. > >+ - For cryptographic applications there is a `--preserve-binary=TYPE` compiler >+ option that causes the `TYPE`'s C `struct` to gain a `_save` field where the >+ original encoding of the `TYPE` is preserved by the decoder. This allows >+ cryptographic applications to validate signatures, MACs, authenticated >+ decryption tags, checksums, etc., without having to re-encode the `TYPE` >+ (which wouldn't even work if the encoding received were BER and BER were >+ permitted for that `TYPE`). >+ >+ - Unconstrained integer types have a large integer representation in C that is >+ not terribly useful in common cases. Range and member constraints on >+ integer types cause the compiler to use `int`, `int64_t`, `unsigned int`, >+ and/or `uint64_t` as appropriate. >+ >+ - The Heimdal ASN.1 compiler currently handles a large subset of X.680, and >+ (in a branch) a small subset of X.681, X.682, and X.683, which manifests as >+ automatic handling of all open types contained in `SET`/`SEQUENCE` types >+ that are parameterized with information object sets. This allows all open >+ types in PKIX certificates, for example, to get decoded automatically no >+ matter how deeply nested. We use a TCG EK certificate that has eight >+ certificate extensions, including subject alternative names and subject >+ directory attributes where the attribute values are not string types, and >+ all of these things get decoded automatically. >+ >+ - The template backend dedups templates to save space. This is an O(N^2) kind >+ of feature that we need to make optional, but it works. (When we implement >+ JER this will have the side-effect of printing the wrong type names in some >+ cases because two or more types have the same templates and get deduped.) >+ >+ - There is an _experimental_ ASN.1 module -> JSON feature in the compiler. It >+ currently dumps type and value definitions, but not class, or object set >+ definitions. Even for types, it is not complete, and the JSON schema used >+ is subject to change *WITHOUT NOTICE*. >+ >+ Perhaps eventually we can re-write the compiler as a C-coded ASN.1 -> JSON >+ stage followed by a jq-coded code and template generator state, which would >+ make it much easier to extend the compiler. >+ > - We have an `asn1_print` program that can decode DER from any exported types > from any ASN.1 modules committed in Heimdal: > >@@ -780,40 +820,12 @@ In recent times the following features have been added: > slightly different names in the ASN.1 modules in Heimdal's source tree. > We'll fix this eventually.) > >- - Unconstrained integer types have a large integer representation in C that is >- not terribly useful in common cases. Range constraints on integer types >- cause the compiler to use `int32_t`, `int64_t`, `uint32_t`, and/or >- `uint64_t`. >- >- - The Heimdal ASN.1 compiler currently handles a large subset of X.680, and >- (in a branch) a small subset of X.681, X.682, and X.683, which manifests as >- automatic handling of all open types contained in `SET`/`SEQUENCE` types >- that are parameterized with information object sets. This allows all open >- types in PKIX certificates, for example, to get decoded automatically no >- matter how deeply nested. We use a TCG EK certificate that has eight >- certificate extensions, including subject alternative names and subject >- directory attributes where the attribute values are not string types, and >- all of these things get decoded automatically. >- >- - The template backend dedups templates to save space. This is an O(N^2) kind >- of feature that we need to make optional, but it works. (When we implement >- JER this will have the side-effect of printing the wrong type names in some >- cases because two or more types have the same templates and get deduped.) >- >- - There is an _experimental_ ASN.1 -> JSON feature in the compiler. It >- currently dumps type and value definitions, but not class, or object set >- definitions. Even for types, it is not complete, and the JSON schema used >- is subject to change *WITHOUT NOTICE*. >- >- Perhaps eventually we can re-write the compiler as a C-coded ASN.1 -> JSON >- stage followed by a jq-coded code and template generator state, which would >- make it much easier to extend the compiler. >- > ... > > ## Limitations > >- - `asn1_print`'s JSON support is not X.697 (JER) compatible. >+ - `libasn1`'s and, therefore, `asn1_print`'s JSON support is not X.697 (JER) >+ compatible. > > - Control over C types generated is very limited, mainly only for integer > types. >@@ -839,6 +851,12 @@ In recent times the following features have been added: > values of `SET`, `SEQUENCE`, `SET OF`, and `SEQUENCE OF`), is not supported. > Values of `CHOICE` types are also not supported. > >+ - There is no way to substitute object sets at run-time. This means that >+ automatic decoding through open types will spend more CPU cycles than the >+ application might want, by decoding more types than the application might >+ care about. The ability to substitute object sets at run-time would require >+ a change to the APIs generated. >+ > - ... > > ## Compiler Usage >@@ -861,104 +879,218 @@ functions for adding or removing items from the named type when it is a > > See the manual page `asn1_compile.1`: > >-``` >-ASN1_COMPILE(1) HEIMDAL General Commands Manual ASN1_COMPILE(1) >+```text >+ASN1_COMPILE(1) BSD General Commands Manual ASN1_COMPILE(1) > > NAME > asn1_compile â compile ASN.1 modules > > SYNOPSIS > asn1_compile [--template] [--prefix-enum] [--enum-prefix=PREFIX] >- [--encode-rfc1510-bit-string] [--decode-dce-ber] >- [--support-ber] [--preserve-binary=TYPE-NAME] >- [--sequence=TYPE-NAME] [--one-code-file] [--gen-name=NAME] >- [--decorate=TYPE-NAME:FIELD-TYPE:field-name[?]] >- [--option-file=FILE] [--original-order] [--no-parse-units] >- [--type-file=C-HEADER-FILE] [--version] [--help] >- [FILE.asn1 [NAME]] >+ [--encode-rfc1510-bit-string] [--decode-dce-ber] >+ [--support-ber] [--preserve-binary=TYPE] [--sequence=TYPE] >+ [--decorate=DECORATION] [--one-code-file] [--gen-name=NAME] >+ [--option-file=FILE] [--original-order] [--no-parse-units] >+ [--type-file=C-HEADER-FILE] [--version] [--help] >+ [FILE.asn1 [NAME]] > > DESCRIPTION >- asn1_compile Compiles an ASN.1 module into C source code and header >+ asn1_compile compiles an ASN.1 module into C source code and header > files. > >+ A fairly large subset of ASN.1 as specified in X.680, and the ASN.1 Inâ >+ formation Object System as specified in X.681, X.682, and X.683 is supâ >+ ported, with support for the Distinguished Encoding Rules (DER), partial >+ Basic Encoding Rules (BER) support, and experimental JSON support (encodâ >+ ing only at this time). >+ >+ See the compiler's README files for details about the C code and interâ >+ faces it generates. >+ >+ The Information Object System support includes automatic codec support >+ for encoding and decoding through âopen typesâ which are also known as >+ âtyped holesâ. See RFC 5912 for examples of how to use the ASN.1 Inforâ >+ mation Object System via X.681/X.682/X.683 annotations. See the comâ >+ piler's README files for more information on ASN.1 Information Object >+ System support. >+ >+ Extensions specific to Heimdal are generally not syntactic in nature but >+ rather command-line options to this program. For example, one can use >+ command-line options to: >+ ⢠enable decoding of BER-encoded values; >+ ⢠enable RFC1510-style handling of âBIT STRINGâ types; >+ ⢠enable saving of as-received encodings of specific types >+ for the purpose of signature validation; >+ ⢠generate add/remove utility functions for array types; >+ ⢠decorate generated âstructâ types with fields that are neiâ >+ ther encoded nor decoded; >+ etc. >+ >+ ASN.1 x.680 features supported: >+ ⢠most primitive types (except BMPString and REAL); >+ ⢠all constructed types, including SET and SET OF; >+ ⢠explicit and implicit tagging. >+ >+ Size and range constraints on the âINTEGERâ type cause the compiler to >+ generate appropriate C types such as âintâ, âunsigned intâ, âint64_tâ, >+ âuint64_tâ. Unconstrained âINTEGERâ is treated as âheim_integerâ, which >+ represents an integer of arbitrary size. >+ >+ Caveats and ASN.1 x.680 features not supported: >+ ⢠JSON encoding support is not quite X.697 (JER) compatible. >+ Its JSON schema is subject to change without notice. >+ ⢠Control over C types generated is very limited, mainly only >+ for integer types. >+ ⢠When using the template backend, `SET { .. }` types are >+ currently not sorted by tag as they should be, but if the >+ module author sorts them by hand then correct DER will be >+ produced. >+ ⢠âAUTOMATIC TAGSâ is not supported. >+ ⢠The REAL type is not supported. >+ ⢠The EmbeddedPDV type is not supported. >+ ⢠The BMPString type is not supported. >+ ⢠The IA5String is not properly supported, as it's essenâ >+ tially treated as a UTF8String with a different tag. >+ ⢠All supported non-octet strings are treated as like the >+ UTF8String type. >+ ⢠Only types can be imported into ASN.1 modules at this time. >+ ⢠Only simple value syntax is supported. Constructed value >+ syntax (i.e., values of SET, SEQUENCE, SET OF, and SEQUENCE >+ OF types), is not supported. Values of `CHOICE` types are >+ also not supported. >+ > Options supported: > > --template >- Use the âtemplateâ backend instead of the âcodegenâ backend >- (which is the default backend). The template backend generates >- âtemplatesâ which are akin to bytecode, and which are interpreted >- at run-time. The codegen backend generates C code for all func- >- tions directly, with no template interpretation. The template >- backend scales better than the codegen backend because as we add >- support for more encoding rules the templates stay mostly the >- same, thus scaling linearly with size of module. Whereas the >- codegen backend scales linear with the product of module size and >- number of encoding rules supported. More importantly, currently >- only the template backend supports automatic decoding of open >- types via X.681/X.682/X.683 annotations. >+ Use the âtemplateâ backend instead of the âcodegenâ backend >+ (which is the default backend). >+ >+ The template backend generates âtemplatesâ which are akin to >+ bytecode, and which are interpreted at run-time. >+ >+ The codegen backend generates C code for all functions directly, >+ with no template interpretation. >+ >+ The template backend scales better than the codegen backend beâ >+ cause as we add support for more encoding rules and more operaâ >+ tions (we may add value comparators) the templates stay mostly >+ the same, thus scaling linearly with size of module. Whereas the >+ codegen backend scales linear with the product of module size and >+ number of encoding rules supported. > > --prefix-enum >- This option should be removed because ENUMERATED types should >- always have their labels prefixed. >+ This option should be removed because ENUMERATED types should alâ >+ ways have their labels prefixed. > > --enum-prefix=PREFIX >- This option should be removed because ENUMERATED types should >- always have their labels prefixed. >+ This option should be removed because ENUMERATED types should alâ >+ ways have their labels prefixed. > > --encode-rfc1510-bit-string >- Use RFC1510, non-standard handling of âBIT STRINGâ types. >+ Use RFC1510, non-standard handling of âBIT STRINGâ types. > > --decode-dce-ber >+ > --support-ber > >- --preserve-binary=TYPE-NAME >- Generate â_saveâ fields in structs to preserve the original >- encoding of some sub-value. This is useful for cryptographic >- applications to avoid having to re-encode values to check signa- >- tures, etc. >- >- --sequence=TYPE-NAME >- Generate add/remove functions for âSET OFâ and âSEQUENCE OFâ >- types. >- >- --decorate=TYPE-NAME:FIELD-TYPE:field-name[?] >- Add to the TYPE-NAME SET or SEQUENCE type a field of the given >- FIELD-TYPE and field-name, but do not encode or decode this >- field. If the field-name ends in a question mark, then treat the >- field as OPTIONAL for the purposes of copy/free function stubs. >- This is useful for adding fields to existing types that can be >- used for internal bookkeeping but which do not affect interoper- >- ability because they are not encoded. >+ --preserve-binary=TYPE >+ Generate a field named â_saveâ in the C struct generated for the >+ named TYPE. This field is used to preserve the original encoding >+ of the value of the TYPE. >+ >+ This is useful for cryptographic applications so that they can >+ check signatures of encoded values as-received without having to >+ re-encode those values. >+ >+ For example, the TBSCertificate type should have values preserved >+ so that Certificate validation can check the signatureValue over >+ the tbsCertificate's value as-received. >+ >+ The alternative of encoding a value to check a signature of it is >+ brittle. For types where non-canonical encodings (such as BER) >+ are allowed, this alternative is bound to fail. Thus the point >+ of this option. >+ >+ --sequence=TYPE >+ Generate add/remove functions for the named ASN.1 TYPE which must >+ be a âSET OFâ or âSEQUENCE OFâ type. >+ >+ --decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?] >+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE, >+ or CHOICE type named ASN1-TYPE a âhiddenâ field named fname of >+ the given ASN.1 type FIELD-ASN1-TYPE, but do not encode or decode >+ it. If the fname ends in a question mark, then treat the field >+ as OPTIONAL. >+ >+ This is useful for adding fields to existing types that can be >+ used for internal bookkeeping but which do not affect interoperâ >+ ability because they are neither encoded nor decoded. For examâ >+ ple, one might decorate a request type with state needed during >+ processing of the request. >+ >+ --decorate=ASN1-TYPE:void*:fname >+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE, >+ or CHOICE type named ASN1-TYPE a âhiddenâ field named fname of >+ type âvoid *â (but do not encode or decode it. >+ >+ The destructor and copy constructor functions generated by this >+ compiler for ASN1-TYPE will set this field to the âNULLâ pointer. >+ >+ --decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header >+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE, >+ or CHOICE type named ASN1-TYPE a âhiddenâ field named fname of >+ the given external C type FIELD-C-TYPE, declared in the given >+ header but do not encode or decode this field. If the fname ends >+ in a question mark, then treat the field as OPTIONAL. >+ >+ The header must include double quotes or angle brackets. The >+ copyfn must be the name of a copy constructor function that takes >+ a pointer to a source value of the type, and a pointer to a desâ >+ tination value of the type, in that order, and which returns zero >+ on success or else a system error code on failure. The freefn >+ must be the name of a destructor function that takes a pointer to >+ a value of the type and which releases resources referenced by >+ that value, but does not free the value itself (the run-time alâ >+ locates this value as needed from the C heap). The freefn should >+ also reset the value to a pristine state (such as all zeros). >+ >+ If the copyfn and freefn are empty strings, then the decoration >+ field will neither be copied nor freed by the functions generated >+ for the TYPE. > > --one-code-file >- Generate a single source code file. Otherwise a separate code >- file will be generated for every type. >+ Generate a single source code file. Otherwise a separate code >+ file will be generated for every type. > > --gen-name=NAME >- Use NAME to form the names of the files generated. >+ Use NAME to form the names of the files generated. > > --option-file=FILE >- Take additional command-line options from FILE. >+ Take additional command-line options from FILE. > > --original-order >- Attempt to preserve the original order of type definition in the >- ASN.1 module. By default the compiler generates types in a topo- >- logical sort order. >+ Attempt to preserve the original order of type definition in the >+ ASN.1 module. By default the compiler generates types in a topoâ >+ logical sort order. > > --no-parse-units >- Do not generate to-int / from-int functions for enumeration >- types. >+ Do not generate to-int / from-int functions for enumeration >+ types. > > --type-file=C-HEADER-FILE >- Generate an include of the named header file that might be needed >- for common type defintions. >+ Generate an include of the named header file that might be needed >+ for common type defintions. > > --version > > --help > >-HEIMDAL February 22, 2021 HEIMDAL >+NOTES >+ Currently only the template backend supports automatic encoding and deâ >+ coding of open types via the ASN.1 Information Object System and >+ X.681/X.682/X.683 annotations. > >+HEIMDAL February 22, 2021 HEIMDAL > ``` > > ## APIs Generated by the Compiler >@@ -1076,9 +1208,9 @@ absence and non-NULL indicating presence. > > And so on. > >-## asn1_print Usage >+## `asn1_print` Usage > >-``` >+```text > ASN1_PRINT(1) BSD General Commands Manual ASN1_PRINT(1) > > NAME >@@ -1170,13 +1302,19 @@ See: > > - Add JER support so we can convert between JER and DER? > >- - Add XDR support? >+ - Add XDR support? There are no ASN.1 Encoding Rules based on XDR, but it is >+ trivial to construct such for at least that subset of ASN.1 for which the >+ XDR syntax has equivalent semantics. > > - Add OER support? > >- - Add NDR support? >+ - Add NDR support? There are no ASN.1 Encoding Rules based on NDR, but it is >+ trivial to construct such for at least that subset of ASN.1 for which the >+ IDL syntax has equivalent semantics. > >- - Perhaps third parties will contribute more control over generate types? >+ - Perhaps third parties will contribute more control over generated types? >+ This may require separate publication of the Heimdal ASN.1 compiler from the >+ rest of Heimdal. > > ## Moving From C > >diff --git a/third_party/heimdal/lib/asn1/asn1-template.h b/third_party/heimdal/lib/asn1/asn1-template.h >index e75734ea26ce..07c4461e3e9a 100644 >--- a/third_party/heimdal/lib/asn1/asn1-template.h >+++ b/third_party/heimdal/lib/asn1/asn1-template.h >@@ -42,43 +42,16 @@ > * TBD: > * > * - For OER also encode number of optional/default/extension elements into >- * header entry's ptr field, not just the number of entries that follow it >+ * header entry's ptr field, not just the number of entries that follow it. > * >- * - For JER/GSER/whatver, and probably for not-C-coded template interpreters, >- * we'll need to have an entry type for the names of structures and their >- * fields. >+ * - For JER we'll need to encode encoding options (encode as array, encode as >+ * object, etc.) > * >- * - For auto open types we need a new opcode, let's call it >- * A1_OP_OPENTYPE_OBJSET, and we need to encode into its entry: >- * a) the index of the template entry for the type ID field, and >- * b) the index of the template entry for the open type field, >- * c) 1 bit to indicate whether the object set is sorted by type ID value, >- * d) a pointer to the object set's template. >- * With that we can then find the struct offsets of those, and also their >- * types (since we can find their template entries). >- * The object set entries should be encoded into two template entries each: >- * one pointing to the value of the type ID field for that object (unless >- * the value is an integer, in which case the ptr should be the integer >- * value directly), and the other pointing to the template for the type >- * identified by the type ID. These will need an opcode each... >- * A1_OP_OPENTYPE_ID and A1_OP_OPENTYPE. >- * We should also end the object set with an A1_OP_OPENTYPE_OBJSET entry so >- * that iterating backwards can be fast. Unless... unless we don't inline >- * the object set and its objects but point to the object set's template. >- * Also, for extensible object sets we can point to the object set's name, >- * and we can then have a function to get an object set template by name, >- * one to release that, and one to add an object to the object set (there's >- * no need to remove objects from object sets, which helps with thread- >- * safety). And then we don't need (c) either. >- * The decoder will then not see these entries until after decoding the type >- * ID and open type field (as its outer type, so OCTET STRING, BIT STRING, >- * or HEIM_ANY) and so it will be able to find those values in the struct at >- * their respective offsets. >- * The encoder and decoder both need to identify the relevant object in the >- * object set, either by linear search or binary search if they are sorted >- * by type ID value, then interpret the template for the identified type. >- * The encoder needs to place the encoding into the normal location for it >- * in the struct, then it can execute the normal template entry for it. >+ * - For open types we'll need to be able to indicate what encoding rules the >+ * type uses. >+ * >+ * - We have too many bits for tags (20) and probably not enough for ops (4 >+ * bits, and we've used all but one). > */ > > /* header: >@@ -155,21 +128,23 @@ > * 28..31 op > */ > >-#define A1_OP_MASK (0xf0000000) >-#define A1_OP_TYPE (0x10000000) >-#define A1_OP_TYPE_EXTERN (0x20000000) >-#define A1_OP_TAG (0x30000000) >-#define A1_OP_PARSE (0x40000000) >-#define A1_OP_SEQOF (0x50000000) >-#define A1_OP_SETOF (0x60000000) >-#define A1_OP_BMEMBER (0x70000000) >-#define A1_OP_CHOICE (0x80000000) >-#define A1_OP_DEFVAL (0x90000000) >-#define A1_OP_OPENTYPE_OBJSET (0xa0000000) >-#define A1_OP_OPENTYPE_ID (0xb0000000) >-#define A1_OP_OPENTYPE (0xc0000000) >-#define A1_OP_NAME (0xd0000000) >-#define A1_OP_TYPE_DECORATE (0xe0000000) >+#define A1_OP_MASK (0xf0000000) >+#define A1_OP_TYPE (0x10000000) /* templated type */ >+#define A1_OP_TYPE_EXTERN (0x20000000) /* templated type (imported) */ >+#define A1_OP_TAG (0x30000000) /* a tag */ >+#define A1_OP_PARSE (0x40000000) /* primitive type */ >+#define A1_OP_SEQOF (0x50000000) /* sequence of */ >+#define A1_OP_SETOF (0x60000000) /* set of */ >+#define A1_OP_BMEMBER (0x70000000) /* BIT STRING member */ >+#define A1_OP_CHOICE (0x80000000) /* CHOICE */ >+#define A1_OP_DEFVAL (0x90000000) /* def. value */ >+#define A1_OP_OPENTYPE_OBJSET (0xa0000000) /* object set for open type */ >+#define A1_OP_OPENTYPE_ID (0xb0000000) /* open type id field */ >+#define A1_OP_OPENTYPE (0xc0000000) /* open type field */ >+#define A1_OP_NAME (0xd0000000) /* symbol */ >+#define A1_OP_TYPE_DECORATE (0xe0000000) /* decoration w/ templated type */ >+#define A1_OP_TYPE_DECORATE_EXTERN (0xf0000000) /* decoration w/ some C type */ >+ /* 0x00.. is still free */ > > #define A1_FLAG_MASK (0x0f000000) > #define A1_FLAG_OPTIONAL (0x01000000) >diff --git a/third_party/heimdal/lib/asn1/asn1_compile.1 b/third_party/heimdal/lib/asn1/asn1_compile.1 >index 74cf314f16e4..a7953df5fa17 100644 >--- a/third_party/heimdal/lib/asn1/asn1_compile.1 >+++ b/third_party/heimdal/lib/asn1/asn1_compile.1 >@@ -46,9 +46,9 @@ > .Op Fl Fl encode-rfc1510-bit-string > .Op Fl Fl decode-dce-ber > .Op Fl Fl support-ber >-.Op Fl Fl preserve-binary=TYPE-NAME >-.Op Fl Fl sequence=TYPE-NAME >-.Op Fl Fl decorate=TYPE-NAME:FIELD-TYPE:field-name[?] >+.Op Fl Fl preserve-binary=TYPE >+.Op Fl Fl sequence=TYPE >+.Op Fl Fl decorate=DECORATION > .Op Fl Fl one-code-file > .Op Fl Fl gen-name=NAME > .Op Fl Fl option-file=FILE >@@ -61,7 +61,117 @@ > .Ek > .Sh DESCRIPTION > .Nm >-Compiles an ASN.1 module into C source code and header files. >+compiles an ASN.1 module into C source code and header files. >+.Pp >+A fairly large subset of ASN.1 as specified in X.680, and the >+ASN.1 Information Object System as specified in X.681, X.682, and >+X.683 is supported, with support for the Distinguished Encoding >+Rules (DER), partial Basic Encoding Rules (BER) support, and >+experimental JSON support (encoding only at this time). >+.Pp >+See the compiler's README files for details about the C code and >+interfaces it generates. >+.Pp >+The Information Object System support includes automatic codec >+support for encoding and decoding through >+.Dq open types >+which are also known as >+.Dq typed holes . >+See RFC 5912 for examples of how to use the ASN.1 >+Information Object System via X.681/X.682/X.683 annotations. See >+the compiler's README files for more information on ASN.1 >+Information Object System support. >+.Pp >+Extensions specific to Heimdal are generally not syntactic in >+nature but rather command-line options to this program. >+For example, one can use command-line options to: >+.Bl -bullet -compact -width Ds -offset indent >+.It >+enable decoding of BER-encoded values; >+.It >+enable RFC1510-style handling of >+.Sq BIT STRING >+types; >+.It >+enable saving of as-received encodings of specific types for the >+purpose of signature validation; >+.It >+generate add/remove utility functions for array types; >+.It >+decorate generated >+.Sq struct >+types with fields that are neither encoded nor decoded; >+.El >+etc. >+.Pp >+ASN.1 x.680 features supported: >+.Bl -bullet -compact -width Ds -offset indent >+.It >+most primitive types (except BMPString and REAL); >+.It >+all constructed types, including SET and SET OF; >+.It >+explicit and implicit tagging. >+.El >+.Pp >+Size and range constraints on the >+.Sq INTEGER >+type cause the compiler to generate appropriate C types such as >+.Sq int , >+.Sq unsigned int , >+.Sq int64_t , >+.Sq uint64_t . >+Unconstrained >+.Sq INTEGER >+is treated as >+.Sq heim_integer , >+which represents an integer of arbitrary size. >+.Pp >+Caveats and ASN.1 x.680 features not supported: >+.Bl -bullet -compact -width Ds -offset indent >+.It >+JSON encoding support is not quite X.697 (JER) compatible. >+Its JSON schema is subject to change without notice. >+.It >+Control over C types generated is very limited, mainly only for >+integer types. >+.It >+When using the template backend, `SET { .. }` types are currently >+not sorted by tag as they should be, but if the module author >+sorts them by hand then correct DER will be produced. >+.It >+.Sq AUTOMATIC TAGS >+is not supported. >+.It >+The >+.Va REAL >+type is not supported. >+.It >+The >+.Va EmbeddedPDV >+type is not supported. >+.It >+The >+.Va BMPString >+type is not supported. >+.It >+The >+.Va IA5String >+is not properly supported, as it's essentially treated as a >+.Va UTF8String >+with a different tag. >+.It >+All supported non-octet strings are treated as like the >+.Va UTF8String >+type. >+.It >+Only types can be imported into ASN.1 modules at this time. >+.It >+Only simple value syntax is supported. >+Constructed value syntax (i.e., values of SET, SEQUENCE, SET OF, >+and SEQUENCE OF types), is not supported. >+Values of `CHOICE` types are also not supported. >+.El > .Pp > Options supported: > .Bl -tag -width Ds >@@ -71,20 +181,21 @@ Use the > backend instead of the > .Dq codegen > backend (which is the default backend). >+.Pp > The template backend generates > .Dq templates > which are akin to bytecode, and which are interpreted at > run-time. >+.Pp > The codegen backend generates C code for all functions directly, > with no template interpretation. >+.Pp > The template backend scales better than the codegen backend >-because as we add support for more encoding rules the templates >-stay mostly the same, thus scaling linearly with size of module. >+because as we add support for more encoding rules and more >+operations (we may add value comparators) the templates stay >+mostly the same, thus scaling linearly with size of module. > Whereas the codegen backend scales linear with the product of > module size and number of encoding rules supported. >-More importantly, currently only the template backend supports >-automatic decoding of open types via X.681/X.682/X.683 >-annotations. > .It Fl Fl prefix-enum > This option should be removed because ENUMERATED types should > always have their labels prefixed. >@@ -97,34 +208,118 @@ Use RFC1510, non-standard handling of > types. > .It Fl Fl decode-dce-ber > .It Fl Fl support-ber >-.It Fl Fl preserve-binary=TYPE-NAME >-Generate >+.It Fl Fl preserve-binary=TYPE >+Generate a field named > .Sq _save >-fields in structs to preserve the original encoding of some >-sub-value. >-This is useful for cryptographic applications to avoid having to >-re-encode values to check signatures, etc. >-.It Fl Fl sequence=TYPE-NAME >-Generate add/remove functions for >+in the C struct generated for the named >+.Ar TYPE . >+This field is used to preserve the original encoding of the value >+of the >+.Ar TYPE . >+.Pp >+This is useful for cryptographic applications so that they can >+check signatures of encoded values as-received without having to >+re-encode those values. >+.Pp >+For example, the TBSCertificate type should have values preserved >+so that Certificate validation can check the signatureValue over >+the tbsCertificate's value as-received. >+.Pp >+The alternative of encoding a value to check a signature of it is >+brittle. >+For types where non-canonical encodings (such as BER) are >+allowed, this alternative is bound to fail. >+Thus the point of this option. >+.It Fl Fl sequence=TYPE >+Generate add/remove functions for the named ASN.1 >+.Ar TYPE >+which must be a > .Sq SET OF >-and >+or > .Sq SEQUENCE OF >-types. >-.It Fl Fl decorate=TYPE-NAME:FIELD-TYPE:field-name[?] >-Add to the >-.Va TYPE-NAME >-SET or SEQUENCE type a field of the given >-.Va FIELD-TYPE >-and >-.Va field-name , >+type. >+.It Fl Fl decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?] >+Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or >+CHOICE type named >+.Ar ASN1-TYPE >+a >+.Dq hidden >+field named >+.Ar fname >+of the given ASN.1 type >+.Ar FIELD-ASN1-TYPE , >+but do not encode or decode it. >+If the >+.Ar fname >+ends in a question mark, then treat the field as OPTIONAL. >+.Pp >+This is useful for adding fields to existing types that can be >+used for internal bookkeeping but which do not affect >+interoperability because they are neither encoded nor decoded. >+For example, one might decorate a request type with state needed >+during processing of the request. >+.It Fl Fl decorate=ASN1-TYPE:void*:fname >+Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or >+CHOICE type named >+.Ar ASN1-TYPE >+a >+.Dq hidden >+field named >+.Ar fname >+of type >+.Sq void * >+(but do not encode or decode it. >+.Pp >+The destructor and copy constructor functions generated by this >+compiler for >+.Ar ASN1-TYPE >+will set this field to the >+.Sq NULL >+pointer. >+.It Fl Fl decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header >+Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or >+CHOICE type named >+.Ar ASN1-TYPE >+a >+.Dq hidden >+field named >+.Ar fname >+of the given external C type >+.Ar FIELD-C-TYPE , >+declared in the given >+.Ar header > but do not encode or decode this field. > If the >-.Va field-name >-ends in a question mark, then treat the field as OPTIONAL for >-the purposes of copy/free function stubs. >-This is useful for adding fields to existing types that can be used >-for internal bookkeeping but which do not affect interoperability >-because they are not encoded. >+.Ar fname >+ends in a question mark, then treat the field as OPTIONAL. >+.Pp >+The >+.Ar header >+must include double quotes or angle brackets. >+The >+.Ar copyfn >+must be the name of a copy constructor function that takes a >+pointer to a source value of the type, and a pointer to a >+destination value of the type, in that order, and which returns >+zero on success or else a system error code on failure. >+The >+.Ar freefn >+must be the name of a destructor function that takes a pointer to >+a value of the type and which releases resources referenced by >+that value, but does not free the value itself (the run-time >+allocates this value as needed from the C heap). >+The >+.Ar freefn >+should also reset the value to a pristine state (such as all >+zeros). >+.Pp >+If the >+.Ar copyfn >+and >+.Ar freefn >+are empty strings, then the decoration field will neither be >+copied nor freed by the functions generated for the >+.Ar TYPE . > .It Fl Fl one-code-file > Generate a single source code file. > Otherwise a separate code file will be generated for every type. >@@ -149,3 +344,7 @@ for common type defintions. > .It Fl Fl version > .It Fl Fl help > .El >+.Sh NOTES >+Currently only the template backend supports automatic encoding >+and decoding of open types via the ASN.1 Information Object >+System and X.681/X.682/X.683 annotations. >diff --git a/third_party/heimdal/lib/asn1/asn1_print.c b/third_party/heimdal/lib/asn1/asn1_print.c >index 39c43341aa62..40c37fbbb946 100644 >--- a/third_party/heimdal/lib/asn1/asn1_print.c >+++ b/third_party/heimdal/lib/asn1/asn1_print.c >@@ -114,22 +114,22 @@ const struct types { > (releaser)free_ ## gns, \ > }, > #endif >-#include "cms_asn1_syms.x" >-#include "digest_asn1_syms.x" >-#include "krb5_asn1_syms.x" >-#include "kx509_asn1_syms.x" >-#include "ocsp_asn1_syms.x" >-#include "pkcs10_asn1_syms.x" >-#include "pkcs12_asn1_syms.x" >-#include "pkcs8_asn1_syms.x" >-#include "pkcs9_asn1_syms.x" >-#include "pkinit_asn1_syms.x" >-#include "rfc2459_asn1_syms.x" >-#include "rfc4108_asn1_syms.x" >+#include "cms_asn1_syms.c" >+#include "digest_asn1_syms.c" >+#include "krb5_asn1_syms.c" >+#include "kx509_asn1_syms.c" >+#include "ocsp_asn1_syms.c" >+#include "pkcs10_asn1_syms.c" >+#include "pkcs12_asn1_syms.c" >+#include "pkcs8_asn1_syms.c" >+#include "pkcs9_asn1_syms.c" >+#include "pkinit_asn1_syms.c" >+#include "rfc2459_asn1_syms.c" >+#include "rfc4108_asn1_syms.c" > #ifdef ASN1_PRINT_SUPPORTED >-#include "x690sample_template_asn1_syms.x" >+#include "x690sample_template_asn1_syms.c" > #else >-#include "x690sample_asn1_syms.x" >+#include "x690sample_asn1_syms.c" > #endif > }; > >@@ -453,10 +453,8 @@ dotype(unsigned char *buf, size_t len, char **argv, size_t *size) > char *s; > > s = sorted_types[i].print(v, indent_flag ? ASN1_PRINT_INDENT : 0); >- if (!s) { >- ret = errno; >+ if (!s) > err(1, "Could not print %s\n", typename); >- } > if (!quiet_flag) > printf("%s\n", s); > free(s); >diff --git a/third_party/heimdal/lib/asn1/asn1parse.y b/third_party/heimdal/lib/asn1/asn1parse.y >index 290cb86310ed..f6f6ec0e5c46 100644 >--- a/third_party/heimdal/lib/asn1/asn1parse.y >+++ b/third_party/heimdal/lib/asn1/asn1parse.y >@@ -242,6 +242,7 @@ static unsigned long idcounter; > %type <type> BooleanType > %type <type> ChoiceType > %type <type> ConstrainedType >+%type <type> UnconstrainedType > %type <type> EnumeratedType > %type <type> IntegerType > %type <type> NullType >@@ -288,6 +289,7 @@ static unsigned long idcounter; > > %type <constraint_spec> Constraint > %type <constraint_spec> ConstraintSpec >+%type <constraint_spec> SubtypeConstraint > %type <constraint_spec> GeneralConstraint > %type <constraint_spec> ContentsConstraint > %type <constraint_spec> UserDefinedConstraint >@@ -295,7 +297,6 @@ static unsigned long idcounter; > %type <constraint_spec> ComponentRelationConstraint > > >- > %start ModuleDefinition > > %% >@@ -304,6 +305,9 @@ static unsigned long idcounter; > * We have sinned by allowing types to have names that start with lower-case, > * and values that have names that start with upper-case. > * >+ * UPDATE: We sin no more. However, parts of this block comment are still >+ * relevant. >+ * > * That worked when we only supported basic X.680 because the rules for > * TypeAssignment and ValueAssignment are clearly unambiguous in spite of the > * case issue. >@@ -312,35 +316,41 @@ static unsigned long idcounter; > * have to help us distinguish certain rules is the form of an identifier: the > * case of its first letter. > * >- * We have begun to undo our sin by not allowing wrong-case identifiers in >- * certain situations. >+ * We have cleansed our sin by not allowing wrong-case identifiers any more. > * > * Some historical instances of this sin in-tree: > * >- * - DOMAIN-X500-COMPRESS (value (enum) but name starts with upper-case) >- * - krb5int32 (type but name starts with lower-case) >- * - krb5uint32 (type but name starts with lower-case) >- * - hdb_keyset (type but name starts with lower-case) >- * - hdb_entry (type but name starts with lower-case) >- * - hdb_entry_alias (type but name starts with lower-case) >+ * - DOMAIN-X500-COMPRESS (value (enum) but name starts with upper-case) >+ * - krb5int32 (type but name starts with lower-case) >+ * - krb5uint32 (type but name starts with lower-case) >+ * - hdb_keyset (type but name starts with lower-case) >+ * - hdb_entry (type but name starts with lower-case) >+ * - hdb_entry_alias (type but name starts with lower-case) >+ * - HDB_DB_FORMAT INTEGER (value (int) but name starts with upper-case) > * >- * We have fixed most of these, in some cases leaving behind aliases in header >- * files as needed. >+ * We have fixed all of these and others, in some cases leaving behind aliases >+ * in header files as needed. > * >- * This issue is probably also the source of remaining shift/reduce conflicts. >+ * We have one shift/reduce conflict (shift ObjectClassAssignment, reduce >+ * TypeAssignment) and one reduce/reduce conflict (ObjectAssignment vs >+ * ValueAssignment) that we avoid by requiring CLASS names to start with an >+ * underscore. > * >- * In the FieldSetting rule in particular, we get a reduce/reduce conflict if >- * we use `Identifier' instead of `TYPE_IDENTIFIER' for type field settings and >+ * In the FieldSetting rule, also, we get a reduce/reduce conflict if we use >+ * `Identifier' instead of `TYPE_IDENTIFIER' for type field settings and > * `VALUE_IDENTIFIER' for value field settings, and then we can't make > * progress. > * > * Looking forward, we may not (will not) be able to distinguish ValueSet and >- * ObjectSet field settings from each other either even without committing this >- * leading-identifier-character-case sin, and we may not (will not) be able >- * distinguish Object and Value field settings from each other as well. To >- * deal with those we will have to run-time type-tag/pun the C structures for >- * valueset/objectset and value/object, and have one rule for each of those >- * that inspects the type of the item to decide what kind of setting it is. >+ * ObjectSet field settings from each other either, and we may not (will not) >+ * be able distinguish Object and Value field settings from each other as well. >+ * To deal with those we will have to run-time type-tag and type-pun the C >+ * structures for valueset/objectset and value/object, and have one rule for >+ * each of those that inspects the type of the item to decide what kind of >+ * setting it is. >+ * >+ * Sadly, the extended syntax for ASN.1 (x.680 + x.681/2/3) appears to have >+ * ambiguities that cannot be resolved with bison/yacc. > */ > Identifier : TYPE_IDENTIFIER { $$ = $1; } > | VALUE_IDENTIFIER { $$ = $1; }; >@@ -364,8 +374,6 @@ ModuleDefinition: Identifier objid_opt kw_DEFINITIONS TagDefault ExtensionDefaul > fprintf(jsonfile, "]}\n"); > free(o); > } >- | CLASS_IDENTIFIER objid_opt kw_DEFINITIONS TagDefault ExtensionDefault >- EEQUAL kw_BEGIN ModuleBody kw_END > ; > > TagDefault : kw_EXPLICIT kw_TAGS >@@ -914,10 +922,20 @@ ParamGovernor : DefinedObjectClass > /* | Type */ > ; > >-Type : BuiltinType >- | ReferencedType >- | ConstrainedType >- ; >+UnconstrainedType : BitStringType >+ | BooleanType >+ | CharacterStringType >+ | ChoiceType >+ | EnumeratedType >+ | IntegerType >+ | NullType >+ | ObjectIdentifierType >+ | OctetStringType >+ | SequenceType >+ | SetType >+ | ObjectClassFieldType; /* X.681 */ >+ >+Type : BuiltinType | ReferencedType | ConstrainedType ; > > BuiltinType : BitStringType > | BooleanType >@@ -948,39 +966,49 @@ BooleanType : kw_BOOLEAN > } > ; > >-range : '(' Value RANGE Value ')' >+ /* >+ * The spec says the values in a ValueRange are Values, but a) all >+ * the various value ranges do not involve OBJECT IDENTIFIER, b) >+ * we only support integer value ranges at this time (as opposed >+ * to, e.g., time ranges, and we don't even support time values at >+ * this time), c) allowing OBJECT IDENTIFIER here causes a >+ * shift-reduce conflict, so we limit ourselves to integer values >+ * in ranges. We could always define IntegerValueRange, >+ * TimeValueRange, etc. when we add support for more value types. >+ */ >+range : IntegerValue RANGE IntegerValue > { >- if($2->type != integervalue) >+ if($1->type != integervalue) > lex_error_message("Non-integer used in first part of range"); >- if($2->type != integervalue) >+ if($1->type != integervalue) > lex_error_message("Non-integer in second part of range"); > $$ = ecalloc(1, sizeof(*$$)); >- $$->min = $2->u.integervalue; >- $$->max = $4->u.integervalue; >+ $$->min = $1->u.integervalue; >+ $$->max = $3->u.integervalue; > } >- | '(' Value RANGE kw_MAX ')' >+ | IntegerValue RANGE kw_MAX > { >- if($2->type != integervalue) >+ if($1->type != integervalue) > lex_error_message("Non-integer in first part of range"); > $$ = ecalloc(1, sizeof(*$$)); >- $$->min = $2->u.integervalue; >+ $$->min = $1->u.integervalue; > $$->max = INT_MAX; > } >- | '(' kw_MIN RANGE Value ')' >+ | kw_MIN RANGE IntegerValue > { >- if($4->type != integervalue) >+ if($3->type != integervalue) > lex_error_message("Non-integer in second part of range"); > $$ = ecalloc(1, sizeof(*$$)); > $$->min = INT_MIN; >- $$->max = $4->u.integervalue; >+ $$->max = $3->u.integervalue; > } >- | '(' Value ')' >+ | IntegerValue > { >- if($2->type != integervalue) >+ if($1->type != integervalue) > lex_error_message("Non-integer used in limit"); > $$ = ecalloc(1, sizeof(*$$)); >- $$->min = $2->u.integervalue; >- $$->max = $2->u.integervalue; >+ $$->min = $1->u.integervalue; >+ $$->max = $1->u.integervalue; > } > ; > >@@ -990,12 +1018,6 @@ IntegerType : kw_INTEGER > $$ = new_tag(ASN1_C_UNIV, UT_Integer, > TE_EXPLICIT, new_type(TInteger)); > } >- | kw_INTEGER range >- { >- $$ = new_type(TInteger); >- $$->range = $2; >- $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$); >- } > | kw_INTEGER '{' NamedNumberList '}' > { > $$ = new_type(TInteger); >@@ -1101,8 +1123,8 @@ NullType : kw_NULL > > size : > { $$ = NULL; } >- | kw_SIZE range >- { $$ = $2; } >+ | kw_SIZE '(' range ')' >+ { $$ = $3; } > ; > > >@@ -1250,10 +1272,17 @@ UsefulType : kw_GeneralizedTime > } > ; > >-ConstrainedType : Type Constraint >+ConstrainedType : UnconstrainedType Constraint > { > $$ = $1; >- $$->constraint = $2; >+ if ($2->ctype == CT_RANGE) { >+ if ($1->type != TTag || $1->subtype->type != TInteger) >+ lex_error_message("RANGE constraints apply only to INTEGER types"); >+ $$->subtype->range = $2->u.range; >+ free($2); >+ } else { >+ $$->constraint = $2; >+ } > /* if (Constraint.type == contentConstraint) { > assert(Constraint.u.constraint.type == octetstring|bitstring-w/o-NamedBitList); // remember to check type reference too > if (Constraint.u.constraint.type) { >@@ -1274,9 +1303,15 @@ Constraint : '(' ConstraintSpec ')' > } > ; > >-ConstraintSpec : GeneralConstraint >+ConstraintSpec : SubtypeConstraint | GeneralConstraint > ; > >+SubtypeConstraint: range >+ { >+ $$ = new_constraint_spec(CT_RANGE); >+ $$->u.range = $1; >+ } >+ > GeneralConstraint: ContentsConstraint > | UserDefinedConstraint > | TableConstraint >@@ -1452,7 +1487,7 @@ tagenv : /* */ > ; > > >-ValueAssignment : Identifier Type EEQUAL Value >+ValueAssignment : VALUE_IDENTIFIER Type EEQUAL Value > { > Symbol *s; > s = addsym ($1); >diff --git a/third_party/heimdal/lib/asn1/check-common.h b/third_party/heimdal/lib/asn1/check-common.h >index 97d118997397..6ea1f812651e 100644 >--- a/third_party/heimdal/lib/asn1/check-common.h >+++ b/third_party/heimdal/lib/asn1/check-common.h >@@ -34,7 +34,8 @@ > */ > > #define IF_OPT_COMPARE(ac,bc,e) \ >- if (((ac)->e == NULL && (bc)->e != NULL) || (((ac)->e != NULL && (bc)->e == NULL))) return 1; if ((ac)->e) >+ if (((ac)->e == NULL && (bc)->e != NULL) || (((ac)->e != NULL && (bc)->e == NULL))) return 1; \ >+ if ((ac)->e) > #define COMPARE_OPT_STRING(ac,bc,e) \ > do { if (strcmp(*(ac)->e, *(bc)->e) != 0) return 1; } while(0) > #define COMPARE_OPT_OCTET_STRING(ac,bc,e) \ >diff --git a/third_party/heimdal/lib/asn1/check-der.c b/third_party/heimdal/lib/asn1/check-der.c >index 15fd2bcff920..a8956a74bd26 100644 >--- a/third_party/heimdal/lib/asn1/check-der.c >+++ b/third_party/heimdal/lib/asn1/check-der.c >@@ -900,6 +900,8 @@ test_heim_oid_format_same(const char *str, const heim_oid *oid) > ret = der_heim_oid_cmp(&o2, oid); > der_free_oid(&o2); > >+ if (ret != 0) >+ return 1; > return 0; > } > >diff --git a/third_party/heimdal/lib/asn1/check-gen.c b/third_party/heimdal/lib/asn1/check-gen.c >index f49f5e8edf92..6b5c71c39f57 100644 >--- a/third_party/heimdal/lib/asn1/check-gen.c >+++ b/third_party/heimdal/lib/asn1/check-gen.c >@@ -51,6 +51,24 @@ > > #include "check-common.h" > >+static int my_copy_vers_called; >+static int my_free_vers_called; >+ >+int >+my_copy_vers(const my_vers *from, my_vers *to) >+{ >+ my_copy_vers_called++; >+ *to = *from; >+ return 0; >+} >+ >+void >+my_free_vers(my_vers *v) >+{ >+ my_free_vers_called++; >+ v->v = -1; >+} >+ > static char *lha_principal[] = { "lha" }; > static char *lharoot_princ[] = { "lha", "root" }; > static char *datan_princ[] = { "host", "nutcracker.e.kth.se" }; >@@ -1021,7 +1039,7 @@ static int > test_decorated(void) > { > TESTNotDecorated tnd; >- TESTDecorated td; >+ TESTDecorated td, td_copy; > size_t len, size; > void *ptr; > int ret; >@@ -1029,7 +1047,12 @@ test_decorated(void) > memset(&td, 0, sizeof(td)); > memset(&tnd, 0, sizeof(tnd)); > >+ my_copy_vers_called = 0; >+ my_free_vers_called = 0; >+ > td.version = 3; >+ td.version3.v = 5; >+ td.privthing = &td; > if ((td.version2 = malloc(sizeof(*td.version2))) == NULL) > errx(1, "out of memory"); > *td.version2 = 5; >@@ -1043,6 +1066,7 @@ test_decorated(void) > warnx("could not decode a TESTDecorated struct as TESTNotDecorated"); > return 1; > } >+ free(ptr); > if (size != len) { > warnx("TESTDecorated encoded size mismatch"); > return 1; >@@ -1051,9 +1075,122 @@ test_decorated(void) > warnx("TESTDecorated did not decode as a TESTNotDecorated correctly"); > return 1; > } >+ if (copy_TESTDecorated(&td, &td_copy)) { >+ warnx("copy_TESTDecorated() failed"); >+ return 1; >+ } >+ if (td.version != td_copy.version) { >+ warnx("copy_TESTDecorated() did not work correctly (1)"); >+ return 1; >+ } >+ if (td_copy.version2 == NULL || *td.version2 != *td_copy.version2) { >+ warnx("copy_TESTDecorated() did not work correctly (2)"); >+ return 1; >+ } >+ if (td.version3.v != td_copy.version3.v || >+ my_copy_vers_called != 1) { >+ warnx("copy_TESTDecorated() did not work correctly (3)"); >+ return 1; >+ } >+ if (td_copy.privthing != 0) { >+ warnx("copy_TESTDecorated() did not work correctly (4)"); >+ return 1; >+ } >+ >+ free_TESTDecorated(&td_copy); > free_TESTDecorated(&td); > if (td.version2) { >- warnx("free_TESTDecorated() did not work correctly"); >+ warnx("free_TESTDecorated() did not work correctly (1)"); >+ return 1; >+ } >+ if (td.version3.v != 0 || my_free_vers_called != 2) { >+ warnx("free_TESTDecorated() did not work correctly (2)"); >+ return 1; >+ } >+ if (td.privthing != 0) { >+ warnx("free_TESTDecorated() did not work correctly (3)"); >+ return 1; >+ } >+ return 0; >+} >+ >+static int >+test_decorated_choice(void) >+{ >+ TESTNotDecoratedChoice tndc; >+ TESTDecoratedChoice tdc, tdc_copy; >+ size_t len, size; >+ void *ptr; >+ int ret; >+ >+ memset(&tdc, 0, sizeof(tdc)); >+ memset(&tndc, 0, sizeof(tndc)); >+ >+ my_copy_vers_called = 0; >+ my_free_vers_called = 0; >+ >+ tdc.element = choice_TESTDecoratedChoice_version; >+ tdc.u.version = 3; >+ tdc.version3.v = 5; >+ tdc.privthing = &tdc; >+ if ((tdc.version2 = malloc(sizeof(*tdc.version2))) == NULL) >+ errx(1, "out of memory"); >+ *tdc.version2 = 5; >+ ASN1_MALLOC_ENCODE(TESTDecoratedChoice, ptr, len, &tdc, &size, ret); >+ if (ret) { >+ warnx("could not encode a TESTDecoratedChoice struct"); >+ return 1; >+ } >+ ret = decode_TESTNotDecoratedChoice(ptr, len, &tndc, &size); >+ if (ret) { >+ warnx("could not decode a TESTDecoratedChoice struct as TESTNotDecoratedChoice"); >+ return 1; >+ } >+ free(ptr); >+ if (size != len) { >+ warnx("TESTDecoratedChoice encoded size mismatch"); >+ return 1; >+ } >+ if ((int)tdc.element != (int)tndc.element || >+ tdc.u.version != tndc.u.version) { >+ warnx("TESTDecoratedChoice did not decode as a TESTNotDecoratedChoice correctly"); >+ return 1; >+ } >+ if (copy_TESTDecoratedChoice(&tdc, &tdc_copy)) { >+ warnx("copy_TESTDecoratedChoice() failed"); >+ return 1; >+ } >+ if ((int)tdc.element != (int)tdc_copy.element || >+ tdc.u.version != tdc_copy.u.version) { >+ warnx("copy_TESTDecoratedChoice() did not work correctly (1)"); >+ return 1; >+ } >+ if (tdc_copy.version2 == NULL || *tdc.version2 != *tdc_copy.version2) { >+ warnx("copy_TESTDecoratedChoice() did not work correctly (2)"); >+ return 1; >+ } >+ if (tdc.version3.v != tdc_copy.version3.v || >+ my_copy_vers_called != 1) { >+ warnx("copy_TESTDecoratedChoice() did not work correctly (3)"); >+ return 1; >+ } >+ if (tdc_copy.privthing != 0) { >+ warnx("copy_TESTDecoratedChoice() did not work correctly (4)"); >+ return 1; >+ } >+ >+ free_TESTDecoratedChoice(&tdc_copy); >+ free_TESTDecoratedChoice(&tdc); >+ if (tdc.version2) { >+ warnx("free_TESTDecoratedChoice() did not work correctly (1)"); >+ return 1; >+ } >+ if (tdc.version3.v != 0 || my_free_vers_called != 2) { >+ warnx("free_TESTDecoratedChoice() did not work correctly (2)"); >+ return 1; >+ } >+ if (tdc.privthing != 0) { >+ warnx("free_TESTDecoratedChoice() did not work correctly (3)"); > return 1; > } > return 0; >@@ -1521,7 +1658,7 @@ static int > check_seq(void) > { > TESTSeqOf seq; >- TESTInteger i; >+ TESTInteger i = 0; > int ret; > > seq.val = NULL; >@@ -2537,6 +2674,7 @@ main(int argc, char **argv) > > DO_ONE(test_default); > >+ DO_ONE(test_decorated_choice); > DO_ONE(test_decorated); > > #if ASN1_IOS_SUPPORTED >diff --git a/third_party/heimdal/lib/asn1/check-gen.h b/third_party/heimdal/lib/asn1/check-gen.h >new file mode 100644 >index 000000000000..df8c4747b6b8 >--- /dev/null >+++ b/third_party/heimdal/lib/asn1/check-gen.h >@@ -0,0 +1,9 @@ >+#ifndef _CHECK_GEN_H >+#define _CHECK_GEN_H >+typedef struct my_vers_s { >+ int v; >+} my_vers; >+ >+int my_copy_vers(const my_vers *, my_vers *); >+void my_free_vers(my_vers *); >+#endif /* _CHECK_GEN_H */ >diff --git a/third_party/heimdal/lib/asn1/check-template.c b/third_party/heimdal/lib/asn1/check-template.c >index 21132c8d1a4d..ef5bd6990ded 100644 >--- a/third_party/heimdal/lib/asn1/check-template.c >+++ b/third_party/heimdal/lib/asn1/check-template.c >@@ -48,6 +48,19 @@ > #include "check-common.h" > #include "der_locl.h" > >+int >+my_copy_vers(const my_vers *from, my_vers *to) >+{ >+ *to = *from; >+ return 0; >+} >+ >+void >+my_free_vers(my_vers *v) >+{ >+ v->v = -1; >+} >+ > static int > cmp_dummy (void *a, void *b) > { >diff --git a/third_party/heimdal/lib/asn1/der_copy.c b/third_party/heimdal/lib/asn1/der_copy.c >index 854131e2ab47..2084cef5f088 100644 >--- a/third_party/heimdal/lib/asn1/der_copy.c >+++ b/third_party/heimdal/lib/asn1/der_copy.c >@@ -99,11 +99,14 @@ int ASN1CALL > der_copy_printable_string (const heim_printable_string *from, > heim_printable_string *to) > { >- to->length = from->length; >- to->data = malloc(to->length + 1); >- if(to->data == NULL) >+ assert(from->length == 0 || (from->length > 0 && from->data != NULL)); >+ to->data = malloc(from->length + 1); >+ if (to->data == NULL) { >+ to->length = 0; > return ENOMEM; >- if (from->data != NULL) >+ } >+ to->length = from->length; >+ if (to->length > 0) > memcpy(to->data, from->data, to->length); > ((char *)to->data)[to->length] = '\0'; > return 0; >@@ -119,11 +122,17 @@ der_copy_ia5_string (const heim_ia5_string *from, > int ASN1CALL > der_copy_bmp_string (const heim_bmp_string *from, heim_bmp_string *to) > { >- to->length = from->length; >- to->data = malloc(to->length * sizeof(to->data[0])); >- if(to->length != 0 && to->data == NULL) >+ assert(from->length == 0 || (from->length > 0 && from->data != NULL)); >+ if (from->length == 0) >+ to->data = calloc(1, sizeof(from->data[0])); >+ else >+ to->data = malloc(from->length * sizeof(from->data[0])); >+ if (to->data == NULL) { >+ to->length = 0; > return ENOMEM; >- if (to->data != NULL && from->data != NULL) >+ } >+ to->length = from->length; >+ if (to->length > 0) > memcpy(to->data, from->data, to->length * sizeof(to->data[0])); > return 0; > } >@@ -132,11 +141,17 @@ int ASN1CALL > der_copy_universal_string (const heim_universal_string *from, > heim_universal_string *to) > { >- to->length = from->length; >- to->data = malloc(to->length * sizeof(to->data[0])); >- if(to->length != 0 && to->data == NULL) >+ assert(from->length == 0 || (from->length > 0 && from->data != NULL)); >+ if (from->length == 0) >+ to->data = calloc(1, sizeof(from->data[0])); >+ else >+ to->data = malloc(from->length * sizeof(from->data[0])); >+ if (to->data == NULL) { >+ to->length = 0; > return ENOMEM; >- if (to->data != NULL && from->data != NULL) >+ } >+ to->length = from->length; >+ if (to->length > 0) > memcpy(to->data, from->data, to->length * sizeof(to->data[0])); > return 0; > } >@@ -151,11 +166,17 @@ der_copy_visible_string (const heim_visible_string *from, > int ASN1CALL > der_copy_octet_string (const heim_octet_string *from, heim_octet_string *to) > { >- to->length = from->length; >- to->data = malloc(to->length); >- if(to->length != 0 && to->data == NULL) >+ assert(from->length == 0 || (from->length > 0 && from->data != NULL)); >+ if (from->length == 0) >+ to->data = calloc(1, 1); >+ else >+ to->data = malloc(from->length); >+ if (to->data == NULL) { >+ to->length = 0; > return ENOMEM; >- if (to->data != NULL && from->data != NULL) >+ } >+ to->length = from->length; >+ if (to->length > 0) > memcpy(to->data, from->data, to->length); > return 0; > } >@@ -163,11 +184,17 @@ der_copy_octet_string (const heim_octet_string *from, heim_octet_string *to) > int ASN1CALL > der_copy_heim_integer (const heim_integer *from, heim_integer *to) > { >- to->length = from->length; >- to->data = malloc(to->length); >- if(to->length != 0 && to->data == NULL) >+ assert(from->length == 0 || (from->length > 0 && from->data != NULL)); >+ if (from->length == 0) >+ to->data = calloc(1, 1); >+ else >+ to->data = malloc(from->length); >+ if (to->data == NULL) { >+ to->length = 0; > return ENOMEM; >- if (to->data != NULL && from->data != NULL) >+ } >+ to->length = from->length; >+ if (to->length > 0) > memcpy(to->data, from->data, to->length); > to->negative = from->negative; > return 0; >@@ -176,13 +203,22 @@ der_copy_heim_integer (const heim_integer *from, heim_integer *to) > int ASN1CALL > der_copy_oid (const heim_oid *from, heim_oid *to) > { >- to->length = from->length; >- to->components = malloc(to->length * sizeof(*to->components)); >- if (to->length != 0 && to->components == NULL) >+ if (from->length == 0) { >+ to->length = 0; >+ to->components = calloc(1, sizeof(*from->components)); >+ if (to->components == NULL) >+ return ENOMEM; >+ return 0; >+ } >+ assert(from->components != NULL); >+ to->components = malloc(from->length * sizeof(*from->components)); >+ if (to->components == NULL) { >+ to->length = 0; > return ENOMEM; >- if (to->components != NULL && from->components != NULL) >- memcpy(to->components, from->components, >- to->length * sizeof(*to->components)); >+ } >+ to->length = from->length; >+ memcpy(to->components, from->components, >+ to->length * sizeof(*to->components)); > return 0; > } > >@@ -191,12 +227,19 @@ der_copy_bit_string (const heim_bit_string *from, heim_bit_string *to) > { > size_t len; > >+ assert(from->length == 0 || (from->length > 0 && from->data != NULL)); >+ > len = (from->length + 7) / 8; >- to->length = from->length; >- to->data = malloc(len); >- if(len != 0 && to->data == NULL) >+ if (len == 0) >+ to->data = calloc(1, 1); >+ else >+ to->data = malloc(len); >+ if (to->data == NULL) { >+ to->length = 0; > return ENOMEM; >- if (to->data != NULL && from->data != NULL) >+ } >+ to->length = from->length; >+ if (len > 0) > memcpy(to->data, from->data, len); > return 0; > } >diff --git a/third_party/heimdal/lib/asn1/der_get.c b/third_party/heimdal/lib/asn1/der_get.c >index 55ba62623595..c12f81700251 100644 >--- a/third_party/heimdal/lib/asn1/der_get.c >+++ b/third_party/heimdal/lib/asn1/der_get.c >@@ -174,6 +174,11 @@ der_get_general_string (const unsigned char *p, size_t len, > const unsigned char *p1; > char *s; > >+ assert(p != NULL); >+ >+ if (size) >+ *size = 0; >+ > p1 = memchr(p, 0, len); > if (p1 != NULL) { > /* >@@ -217,6 +222,11 @@ int ASN1CALL > der_get_printable_string(const unsigned char *p, size_t len, > heim_printable_string *str, size_t *size) > { >+ assert(p != NULL); >+ >+ if (size) >+ *size = 0; >+ > if (len == SIZE_MAX) { > gen_data_zero(str); > return ASN1_BAD_LENGTH; >@@ -227,6 +237,7 @@ der_get_printable_string(const unsigned char *p, size_t len, > gen_data_zero(str); > return ENOMEM; > } >+ > memcpy(str->data, p, len); > ((char *)str->data)[len] = '\0'; > if(size) *size = len; >@@ -246,6 +257,11 @@ der_get_bmp_string (const unsigned char *p, size_t len, > { > size_t i; > >+ assert(p != NULL); >+ >+ if (size) >+ *size = 0; >+ > if (len & 1) { > gen_data_zero(data); > return ASN1_BAD_FORMAT; >@@ -282,6 +298,11 @@ der_get_universal_string (const unsigned char *p, size_t len, > { > size_t i; > >+ assert(p != NULL); >+ >+ if (size) >+ *size = 0; >+ > if (len & 3) { > gen_data_zero(data); > return ASN1_BAD_FORMAT; >@@ -322,13 +343,23 @@ int ASN1CALL > der_get_octet_string (const unsigned char *p, size_t len, > heim_octet_string *data, size_t *size) > { >- data->length = len; >- data->data = malloc(len); >- if (data->data == NULL && data->length != 0) >+ assert(p != NULL); >+ >+ if (size) >+ *size = 0; >+ >+ if (len == 0) >+ data->data = malloc(1); >+ else >+ data->data = malloc(len); >+ if (data->data == NULL) { >+ data->length = 0; > return ENOMEM; >- if (data->data != NULL) >- memcpy (data->data, p, len); >- if(size) *size = len; >+ } >+ data->length = len; >+ memcpy (data->data, p, len); >+ if (size) >+ *size = len; > return 0; > } > >@@ -342,6 +373,11 @@ der_get_octet_string_ber (const unsigned char *p, size_t len, > unsigned int tag, depth = 0; > size_t l, datalen, oldlen = len; > >+ assert(p != NULL); >+ >+ if (size) >+ *size = 0; >+ > data->length = 0; > data->data = NULL; > >@@ -409,11 +445,14 @@ der_get_heim_integer (const unsigned char *p, size_t len, > data->negative = 0; > data->data = NULL; > >- if (len == 0) { >- if (size) >- *size = 0; >+ if (size) >+ *size = 0; >+ >+ if (len == 0) > return 0; >- } >+ >+ assert(p != NULL); >+ > if (p[0] & 0x80) { > unsigned char *q; > int carry = 1; >@@ -494,6 +533,11 @@ der_get_time (const unsigned char *p, size_t len, > char *times; > int e; > >+ assert(p != NULL); >+ >+ if (size) >+ *size = 0; >+ > if (len == SIZE_MAX || len == 0) > return ASN1_BAD_LENGTH; > >@@ -529,6 +573,11 @@ der_get_oid (const unsigned char *p, size_t len, > size_t n; > size_t oldlen = len; > >+ assert(p != NULL); >+ >+ if (size) >+ *size = 0; >+ > if (len < 1) > return ASN1_OVERRUN; > >@@ -539,8 +588,10 @@ der_get_oid (const unsigned char *p, size_t len, > return ERANGE; > > data->components = malloc((len + 1) * sizeof(data->components[0])); >- if (data->components == NULL) >+ if (data->components == NULL) { >+ data->length = 0; > return ENOMEM; >+ } > data->components[0] = (*p) / 40; > data->components[1] = (*p) % 40; > --len; >@@ -576,8 +627,15 @@ der_get_tag (const unsigned char *p, size_t len, > unsigned int *tag, size_t *size) > { > size_t ret = 0; >+ >+ if (size) >+ *size = 0; >+ > if (len < 1) > return ASN1_MISSING_FIELD; >+ >+ assert(p != NULL); >+ > *cls = (Der_class)(((*p) >> 6) & 0x03); > *type = (Der_type)(((*p) >> 5) & 0x01); > *tag = (*p) & 0x1f; >@@ -626,6 +684,9 @@ der_match_tag2 (const unsigned char *p, size_t len, > unsigned int thistag; > int e; > >+ if (size) >+ *size = 0; >+ > e = der_get_tag(p, len, &thisclass, type, &thistag, &l); > if (e) return e; > /* >@@ -701,6 +762,11 @@ int ASN1CALL > der_get_bit_string (const unsigned char *p, size_t len, > heim_bit_string *data, size_t *size) > { >+ assert(p != NULL); >+ >+ if (size) >+ *size = 0; >+ > if (len < 1) > return ASN1_OVERRUN; > if (p[0] > 7) >@@ -717,8 +783,10 @@ der_get_bit_string (const unsigned char *p, size_t len, > if (len - 1 > 0) { > data->length = (len - 1) * 8; > data->data = malloc(len - 1); >- if (data->data == NULL) >+ if (data->data == NULL) { >+ data->length = 0; > return ENOMEM; >+ } > memcpy (data->data, p + 1, len - 1); > data->length -= p[0]; > } else { >diff --git a/third_party/heimdal/lib/asn1/der_put.c b/third_party/heimdal/lib/asn1/der_put.c >index 5f40fba16152..8fbd6f3da1c0 100644 >--- a/third_party/heimdal/lib/asn1/der_put.c >+++ b/third_party/heimdal/lib/asn1/der_put.c >@@ -49,6 +49,8 @@ der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size) > unsigned char *base = p; > unsigned val = *v; > >+ *size = 0; >+ > if (val) { > while (len > 0 && val) { > *p-- = val % 256; >@@ -81,6 +83,8 @@ der_put_unsigned64 (unsigned char *p, size_t len, const uint64_t *v, size_t *siz > unsigned char *base = p; > uint64_t val = *v; > >+ *size = 0; >+ > if (val) { > while (len > 0 && val) { > *p-- = val % 256; >@@ -113,6 +117,8 @@ der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size) > unsigned char *base = p; > int val = *v; > >+ *size = 0; >+ > if(val >= 0) { > do { > if(len < 1) >@@ -153,6 +159,8 @@ der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size) > unsigned char *base = p; > int64_t val = *v; > >+ *size = 0; >+ > if(val >= 0) { > do { > if(len < 1) >@@ -191,12 +199,16 @@ der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size) > int ASN1CALL > der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) > { >+ if (size) >+ *size = 0; >+ > if (len < 1) > return ASN1_OVERFLOW; > > if (val < 128) { > *p = val; >- *size = 1; >+ if (size) >+ *size = 1; > } else { > size_t l = 0; > >@@ -218,6 +230,8 @@ der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) > int ASN1CALL > der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size) > { >+ *size = 0; >+ > if(len < 1) > return ASN1_OVERFLOW; > if(*data != 0) >@@ -232,13 +246,15 @@ int ASN1CALL > der_put_general_string (unsigned char *p, size_t len, > const heim_general_string *str, size_t *size) > { >- size_t slen = strlen(*str); >+ size_t slen; > >+ assert(p != NULL && str != NULL && *str != NULL && size != NULL); >+ *size = 0; >+ slen = strlen(*str); > if (len < slen) > return ASN1_OVERFLOW; > p -= slen; >- if (*str != NULL) >- memcpy (p+1, *str, slen); >+ memcpy (p+1, *str, slen); > *size = slen; > return 0; > } >@@ -269,6 +285,12 @@ der_put_bmp_string (unsigned char *p, size_t len, > const heim_bmp_string *data, size_t *size) > { > size_t i; >+ >+ assert(p != NULL && data != NULL); >+ >+ if (size) >+ *size = 0; >+ > if (len / 2 < data->length) > return ASN1_OVERFLOW; > p -= data->length * 2; >@@ -286,6 +308,10 @@ der_put_universal_string (unsigned char *p, size_t len, > const heim_universal_string *data, size_t *size) > { > size_t i; >+ >+ if (size) >+ *size = 0; >+ > if (len / 4 < data->length) > return ASN1_OVERFLOW; > p -= data->length * 4; >@@ -311,11 +337,13 @@ int ASN1CALL > der_put_octet_string (unsigned char *p, size_t len, > const heim_octet_string *data, size_t *size) > { >+ assert(p != NULL && data != NULL && size != NULL); >+ >+ *size = 0; > if (len < data->length) > return ASN1_OVERFLOW; > p -= data->length; >- if (data->data) >- memcpy (p+1, data->data, data->length); >+ memcpy (p+1, data->data, data->length); > *size = data->length; > return 0; > } >@@ -324,9 +352,14 @@ int ASN1CALL > der_put_heim_integer (unsigned char *p, size_t len, > const heim_integer *data, size_t *size) > { >- unsigned char *buf = data->data; >+ unsigned char *buf; > int hibitset = 0; > >+ assert(p != NULL); >+ >+ if (size) >+ *size = 0; >+ > if (data->length == 0) { > if (len < 1) > return ASN1_OVERFLOW; >@@ -338,6 +371,8 @@ der_put_heim_integer (unsigned char *p, size_t len, > if (len < data->length) > return ASN1_OVERFLOW; > >+ assert(data->data != NULL); >+ buf = data->data; > len -= data->length; > > if (data->negative) { >@@ -461,6 +496,8 @@ der_replace_tag(const unsigned char *p, size_t len, > size_t payload_len, l, tag_len, len_len; > int e; > >+ assert(p != NULL && out != NULL && outlen != NULL); >+ > e = der_get_tag(p, len, &found_class, &found_type, &found_tag, &l); > if (e) > return e; >@@ -506,6 +543,8 @@ der_encode_implicit(unsigned char *p, size_t len, > unsigned char *p2; > int e; > >+ assert(p != NULL && size != NULL); >+ > /* Attempt to encode in place */ > e = encoder(p, len, obj, size); > if (e == 0) { >@@ -630,13 +669,17 @@ int ASN1CALL > der_put_bit_string (unsigned char *p, size_t len, > const heim_bit_string *data, size_t *size) > { >- size_t data_size = (data->length + 7) / 8; >+ size_t data_size; >+ >+ assert(p != NULL && data != NULL && size != NULL); >+ >+ *size = 0; >+ data_size = (data->length + 7) / 8; > if (len < data_size + 1) > return ASN1_OVERFLOW; > p -= data_size + 1; > >- if (data->data != NULL) >- memcpy (p+2, data->data, data_size); >+ memcpy (p+2, data->data, data_size); > if (data->length && (data->length % 8) != 0) > p[1] = 8 - (data->length % 8); > else >@@ -648,9 +691,12 @@ der_put_bit_string (unsigned char *p, size_t len, > int > _heim_der_set_sort(const void *a1, const void *a2) > { >- const heim_octet_string *s1 = a1, *s2 = a2; >+ const heim_octet_string *s1, *s2; > int ret; > >+ assert(a1 != NULL && a2 != NULL); >+ s1 = a1; >+ s2 = a2; > ret = memcmp(s1->data, s2->data, > s1->length < s2->length ? s1->length : s2->length); > if (ret != 0) >diff --git a/third_party/heimdal/lib/asn1/extra.c b/third_party/heimdal/lib/asn1/extra.c >index 5a494d23acaf..253ac5aca6f3 100644 >--- a/third_party/heimdal/lib/asn1/extra.c >+++ b/third_party/heimdal/lib/asn1/extra.c >@@ -105,7 +105,7 @@ print_heim_any(const heim_any *data, int flags) > free(s); > s = NULL; > if (r > -1) >- r = asprintf(&s, "\"%s\"", s2); >+ (void) asprintf(&s, "\"%s\"", s2); > free(s2); > return s; > } >@@ -155,7 +155,7 @@ print_HEIM_ANY(const heim_any *data, int flags) > free(s); > s = NULL; > if (r > -1) >- r = asprintf(&s, "\"%s\"", s2); >+ (void) asprintf(&s, "\"%s\"", s2); > free(s2); > return s; > } >@@ -205,7 +205,7 @@ print_heim_any_set(const heim_any_set *data, int flags) > free(s); > s = NULL; > if (r > -1) >- r = asprintf(&s, "\"%s\"", s2); >+ (void) asprintf(&s, "\"%s\"", s2); > free(s2); > return s; > } >@@ -261,7 +261,7 @@ print_HEIM_ANY_SET(const heim_any_set *data, int flags) > free(s); > s = NULL; > if (r > -1) >- r = asprintf(&s, "\"%s\"", s2); >+ (void) asprintf(&s, "\"%s\"", s2); > free(s2); > return s; > } >diff --git a/third_party/heimdal/lib/asn1/gen.c b/third_party/heimdal/lib/asn1/gen.c >index 8e323188fff9..10153c60379e 100644 >--- a/third_party/heimdal/lib/asn1/gen.c >+++ b/third_party/heimdal/lib/asn1/gen.c >@@ -159,7 +159,7 @@ init_generate (const char *filename, const char *base) > /* public header file */ > if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL) > errx(1, "malloc"); >- if (asprintf(&fn, "%s.hx", headerbase) < 0 || fn == NULL) >+ if (asprintf(&fn, "%s.h", headerbase) < 0 || fn == NULL) > errx(1, "malloc"); > headerfile = fopen (fn, "w"); > if (headerfile == NULL) >@@ -170,7 +170,7 @@ init_generate (const char *filename, const char *base) > /* private header file */ > if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL) > errx(1, "malloc"); >- if (asprintf(&fn, "%s-priv.hx", headerbase) < 0 || fn == NULL) >+ if (asprintf(&fn, "%s-priv.h", headerbase) < 0 || fn == NULL) > errx(1, "malloc"); > privheaderfile = fopen (fn, "w"); > if (privheaderfile == NULL) >@@ -179,7 +179,7 @@ init_generate (const char *filename, const char *base) > fn = NULL; > > /* template file */ >- if (asprintf(&template, "%s-template.x", headerbase) < 0 || template == NULL) >+ if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL) > errx(1, "malloc"); > fprintf (headerfile, > "/* Generated from %s */\n" >@@ -258,7 +258,7 @@ init_generate (const char *filename, const char *base) > fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n" > " do { \\\n" > " (BL) = length_##T((S)); \\\n" >- " (B) = malloc((BL)); \\\n" >+ " (B) = calloc(1, (BL)); \\\n" > " if((B) == NULL) { \\\n" > " *(L) = 0; \\\n" > " (R) = ENOMEM; \\\n" >@@ -300,12 +300,12 @@ init_generate (const char *filename, const char *base) > free(fn); > fn = NULL; > >- if (asprintf(&fn, "%s_oids.x", base) < 0 || fn == NULL) >+ if (asprintf(&fn, "%s_oids.c", base) < 0 || fn == NULL) > errx(1, "malloc"); > oidsfile = fopen(fn, "w"); > if (oidsfile == NULL) > err (1, "open %s", fn); >- if (asprintf(&fn, "%s_syms.x", base) < 0 || fn == NULL) >+ if (asprintf(&fn, "%s_syms.c", base) < 0 || fn == NULL) > errx(1, "malloc"); > symsfile = fopen(fn, "w"); > if (symsfile == NULL) >@@ -356,11 +356,19 @@ close_generate (void) > err(1, "writes to private header file failed"); > if (templatefile && fclose(templatefile) == EOF) > err(1, "writes to template file failed"); >- if (logfile) { >- fprintf(logfile, "\n"); >- if (fclose(logfile) == EOF) >- err(1, "writes to log file failed"); >- } >+ if (!jsonfile) abort(); >+ if (fclose(jsonfile) == EOF) >+ err(1, "writes to JSON file failed"); >+ if (!oidsfile) abort(); >+ if (fclose(oidsfile) == EOF) >+ err(1, "writes to OIDs file failed"); >+ if (!symsfile) abort(); >+ if (fclose(symsfile) == EOF) >+ err(1, "writes to symbols file failed"); >+ if (!logfile) abort(); >+ fprintf(logfile, "\n"); >+ if (fclose(logfile) == EOF) >+ err(1, "writes to log file failed"); > } > > void >@@ -415,7 +423,7 @@ generate_header_of_codefile(const char *name) > if (codefile != NULL) > abort(); > >- if (asprintf (&filename, "%s_%s.x", STEM, name) < 0 || filename == NULL) >+ if (asprintf (&filename, "%s_%s.c", STEM, name) < 0 || filename == NULL) > errx(1, "malloc"); > codefile = fopen (filename, "w"); > if (codefile == NULL) >@@ -427,7 +435,9 @@ generate_header_of_codefile(const char *name) > fprintf (codefile, > "/* Generated from %s */\n" > "/* Do not edit */\n\n" >- "#define ASN1_LIB\n\n" >+ "#if defined(_WIN32) && !defined(ASN1_LIB)\n" >+ "# error \"ASN1_LIB must be defined\"\n" >+ "#endif\n" > "#include <stdio.h>\n" > "#include <stdlib.h>\n" > "#include <time.h>\n" >@@ -757,8 +767,10 @@ define_asn1 (int level, Type *t) > fprintf(headerfile, "%s.&%s", > t->typeref.iosclass->symbol->name, > t->typeref.field->name); >- } else >+ } else if (t->symbol) > fprintf(headerfile, "%s", t->symbol->name); >+ else >+ abort(); > break; > case TInteger: > if(t->members == NULL) { >@@ -772,8 +784,8 @@ define_asn1 (int level, Type *t) > fprintf (headerfile, "INTEGER {\n"); > HEIM_TAILQ_FOREACH(m, t->members, members) { > space (level + 1); >- fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val, >- last_member_p(m)); >+ fprintf(headerfile, "%s(%lld)%s\n", m->gen_name, >+ (long long)m->val, last_member_p(m)); > } > space(level); > fprintf (headerfile, "}"); >@@ -796,8 +808,8 @@ define_asn1 (int level, Type *t) > fprintf (headerfile, "ENUMERATED {\n"); > HEIM_TAILQ_FOREACH(m, t->members, members) { > space(level + 1); >- fprintf (headerfile, "%s(%d)%s\n", m->name, m->val, >- last_member_p(m)); >+ fprintf(headerfile, "%s(%lld)%s\n", m->name, >+ (long long)m->val, last_member_p(m)); > } > space(level); > fprintf (headerfile, "}"); >@@ -1022,6 +1034,10 @@ get_open_type_defn_fields(const Type *t, > subtype->constraint->u.content.type->constraint && > subtype->constraint->u.content.type->constraint->ctype == CT_TABLE_CONSTRAINT) { > /* Type like OCTET STRING or BIT STRING CONTAINING open type */ >+ if (*opentypemember) >+ errx(1, "Multiple open type members %s and %s for the same " >+ "field %s?", (*opentypemember)->name, m->name, >+ (*opentypefield)->name); > *opentypemember = m; > *opentypefield = subtype->constraint->u.content.type->typeref.field; > *is_array_of = sOfType != NULL; >@@ -1029,6 +1045,10 @@ get_open_type_defn_fields(const Type *t, > break; > } else if (subtype->symbol && strcmp(subtype->symbol->name, "HEIM_ANY") == 0) { > /* Open type, but NOT embedded in OCTET STRING or BIT STRING */ >+ if (*opentypemember) >+ errx(1, "Multiple open type members %s and %s for the same " >+ "field %s?", (*opentypemember)->name, m->name, >+ (*opentypefield)->name); > *opentypemember = m; > *opentypefield = subtype->typeref.field; > *is_array_of = sOfType != NULL; >@@ -1036,6 +1056,10 @@ get_open_type_defn_fields(const Type *t, > break; > } > } >+ >+ if (!idmembername) >+ errx(1, "Missing open type id member in %s", >+ t->symbol ? t->symbol->name : "<unknown type>"); > /* Look for the type ID member identified in the previous loop */ > HEIM_TAILQ_FOREACH(m, t->members, members) { > if (!m->type->subtype || strcmp(m->name, idmembername) != 0) >@@ -1169,11 +1193,12 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t > define_open_type(level, newbasename, name, basename, t, t); > } else if (!t->symbol && pt->actual_parameter) { > define_open_type(level, newbasename, name, basename, pt, t); >- } else { >+ } else if (t->symbol) { > fprintf(headerfile, "%s %s;\n", t->symbol->gen_name, name); > fprintf(jsonfile, "\"ttype\":\"%s\"," > "\"alias\":true\n", t->symbol->gen_name); >- } >+ } else >+ abort(); > break; > case TInteger: > if (t->symbol && t->symbol->emitted_definition) >@@ -1190,12 +1215,12 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t > "\"members\":[\n"); > HEIM_TAILQ_FOREACH(m, t->members, members) { > space (level + 1); >- fprintf(headerfile, "%s%s%s = %d%s\n", >+ fprintf(headerfile, "%s%s%s = %lld%s\n", > label_prefix, label_prefix_sep, >- m->gen_name, m->val, last_member_p(m)); >- fprintf(jsonfile, "{\"%s%s%s\":%d}%s\n", >+ m->gen_name, (long long)m->val, last_member_p(m)); >+ fprintf(jsonfile, "{\"%s%s%s\":%lld}%s\n", > label_prefix, label_prefix_sep, >- m->gen_name, m->val, last_member_p(m)); >+ m->gen_name, (long long)m->val, last_member_p(m)); > } > fprintf(headerfile, "} %s;\n", name); > fprintf(jsonfile, "]"); >@@ -1268,7 +1293,7 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t > fprintf (headerfile, "heim_bit_string %s;\n", name); > fprintf(jsonfile, "\"ctype\":\"heim_bit_string\""); > } else { >- int pos = 0; >+ int64_t pos = 0; > getnewbasename(&newbasename, typedefp || level == 0, basename, name); > > fprintf (headerfile, "struct %s {\n", newbasename); >@@ -1281,7 +1306,8 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t > * forces the compiler to give us an obvious layout) > */ > while (pos < m->val) { >- if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) >+ if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 || >+ n == NULL) > err(1, "malloc"); > define_type(level + 1, n, newbasename, NULL, &i, FALSE, FALSE); > fprintf(jsonfile, ","); >@@ -1308,7 +1334,8 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t > fprintf(jsonfile, ","); > while (pos < bitset_size) { > char *n = NULL; >- if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) >+ if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 || >+ n == NULL) > errx(1, "malloc"); > define_type(level + 1, n, newbasename, NULL, &i, FALSE, FALSE); > fprintf(jsonfile, "%s", (pos + 1) < bitset_size ? "," : ""); >@@ -1339,12 +1366,12 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t > if (m->ellipsis) { > fprintf (headerfile, "/* ... */\n"); > } else { >- fprintf(headerfile, "%s%s%s = %d%s\n", >+ fprintf(headerfile, "%s%s%s = %lld%s\n", > label_prefix, label_prefix_sep, >- m->gen_name, m->val, last_member_p(m)); >- fprintf(jsonfile, "{\"%s%s%s\":%d%s}\n", >+ m->gen_name, (long long)m->val, last_member_p(m)); >+ fprintf(jsonfile, "{\"%s%s%s\":%lld%s}\n", > label_prefix, label_prefix_sep, >- m->gen_name, m->val, last_member_p(m)); >+ m->gen_name, (long long)m->val, last_member_p(m)); > } > } > space(level); >@@ -1355,12 +1382,14 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t > case TSet: > case TSequence: { > Member *m; >- char *ft, *fn; >- int deco_opt; >+ struct decoration deco; >+ ssize_t more_deco = -1; >+ int decorated = 0; > > getnewbasename(&newbasename, typedefp || level == 0, basename, name); > > space(level); >+ > fprintf (headerfile, "struct %s {\n", newbasename); > fprintf(jsonfile, "\"ttype\":\"%s\",\"extensible\":%s," > "\"ctype\":\"struct %s\"", >@@ -1397,15 +1426,37 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t > fprintf(jsonfile, ",\"opentype\":"); > define_open_type(level, newbasename, name, basename, t, t); > } >- if (decorate_type(newbasename, &ft, &fn, &deco_opt)) { >+ while (decorate_type(newbasename, &deco, &more_deco)) { >+ decorated++; > space(level + 1); >- fprintf(headerfile, "%s %s%s;\n", ft, deco_opt ? "*" : "", fn); >- fprintf(jsonfile, ",\"decorate\":{\"type\":\"%s\",\"name\":\"%s\", \"optional\":%s}", ft, fn, deco_opt ? "true" : "false"); >- free(ft); >- free(fn); >+ fprintf(headerfile, "%s %s%s;\n", deco.field_type, >+ deco.opt ? "*" : "", deco.field_name); >+ if (deco.first) >+ fprintf(jsonfile, ",\"decorate\":["); >+ fprintf(jsonfile, "%s{" >+ "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s," >+ "\"external\":%s,\"pointer\":%s,\"void_star\":%s," >+ "\"struct_star\":%s," >+ "\"copy_function\":\"%s\"," >+ "\"free_function\":\"%s\",\"header_name\":%s%s%s" >+ "}", >+ deco.first ? "" : ",", >+ deco.field_type, deco.field_name, >+ deco.opt ? "true" : "false", deco.ext ? "true" : "false", >+ deco.ptr ? "true" : "false", deco.void_star ? "true" : "false", >+ deco.struct_star ? "true" : "false", >+ deco.copy_function_name ? deco.copy_function_name : "", >+ deco.free_function_name ? deco.free_function_name : "", >+ deco.header_name && deco.header_name[0] == '"' ? "" : "\"", >+ deco.header_name ? deco.header_name : "", >+ deco.header_name && deco.header_name[0] == '"' ? "" : "\"" >+ ); > } >+ if (decorated) >+ fprintf(jsonfile, "]"); > space(level); > fprintf (headerfile, "} %s;\n", name); >+ free(deco.field_type); > break; > } > case TSetOf: >@@ -1454,6 +1505,9 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t > define_type(level, name, basename, t, t->subtype, typedefp, preservep); > break; > case TChoice: { >+ struct decoration deco; >+ ssize_t more_deco = -1; >+ int decorated = 0; > int first = 1; > Member *m; > >@@ -1512,9 +1566,39 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t > } > space(level + 1); > fprintf (headerfile, "} u;\n"); >+ fprintf(jsonfile, "]"); >+ >+ while (decorate_type(newbasename, &deco, &more_deco)) { >+ decorated++; >+ space(level + 1); >+ fprintf(headerfile, "%s %s%s;\n", deco.field_type, >+ deco.opt ? "*" : "", deco.field_name); >+ if (deco.first) >+ fprintf(jsonfile, ",\"decorate\":["); >+ fprintf(jsonfile, "%s{" >+ "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s," >+ "\"external\":%s,\"pointer\":%s,\"void_star\":%s," >+ "\"struct_star\":%s," >+ "\"copy_function\":\"%s\"," >+ "\"free_function\":\"%s\",\"header_name\":%s%s%s" >+ "}", >+ deco.first ? "" : ",", >+ deco.field_type, deco.field_name, >+ deco.opt ? "true" : "false", deco.ext ? "true" : "false", >+ deco.ptr ? "true" : "false", deco.void_star ? "true" : "false", >+ deco.struct_star ? "true" : "false", >+ deco.copy_function_name ? deco.copy_function_name : "", >+ deco.free_function_name ? deco.free_function_name : "", >+ deco.header_name && deco.header_name[0] == '"' ? "" : "\"", >+ deco.header_name ? deco.header_name : "", >+ deco.header_name && deco.header_name[0] == '"' ? "" : "\"" >+ ); >+ } >+ if (decorated) >+ fprintf(jsonfile, "]"); >+ > space(level); > fprintf (headerfile, "} %s;\n", name); >- fprintf(jsonfile, "]"); > break; > } > case TUTCTime: >@@ -1617,19 +1701,37 @@ declare_type(const Symbol *s, Type *t, int typedefp) > > switch (t->type) { > case TSet: >- case TSequence: >+ case TSequence: { >+ struct decoration deco; >+ ssize_t more_deco = -1; >+ > getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name); > fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name); >+ while (decorate_type(newbasename, &deco, &more_deco)) { >+ if (deco.header_name) >+ fprintf(headerfile, "#include %s\n", deco.header_name); >+ free(deco.field_type); >+ } > break; >+ } > case TSetOf: > case TSequenceOf: > getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name); > fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name); > break; >- case TChoice: >+ case TChoice: { >+ struct decoration deco; >+ ssize_t more_deco = -1; >+ > getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name); > fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name); >+ while (decorate_type(newbasename, &deco, &more_deco)) { >+ if (deco.header_name) >+ fprintf(headerfile, "#include %s\n", deco.header_name); >+ free(deco.field_type); >+ } > break; >+ } > default: > abort (); > } >@@ -1755,6 +1857,7 @@ static void > generate_type_header (const Symbol *s) > { > Type *t = s->type; >+ > if (!s->type) > return; > >@@ -1823,6 +1926,7 @@ generate_type_header (const Symbol *s) > if (is_export(s->name)) > fprintf(symsfile, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n", > s->name, s->gen_name, s->gen_name); >+ > fprintf(headerfile, "typedef "); > define_type(0, s->gen_name, s->gen_name, NULL, s->type, TRUE, > preserve_type(s->name) ? TRUE : FALSE); >diff --git a/third_party/heimdal/lib/asn1/gen_copy.c b/third_party/heimdal/lib/asn1/gen_copy.c >index 243aa2b0ccae..bec6f8b059f5 100644 >--- a/third_party/heimdal/lib/asn1/gen_copy.c >+++ b/third_party/heimdal/lib/asn1/gen_copy.c >@@ -62,7 +62,7 @@ copy_type (const char *from, const char *to, const Type *t, int preserve) > copy_primitive ("heim_integer", from, to); > break; > } >- /* FALLTHROUGH */ >+ fallthrough; > case TBoolean: > case TEnumerated : > fprintf(codefile, "*(%s) = *(%s);\n", to, from); >@@ -125,7 +125,7 @@ copy_type (const char *from, const char *to, const Type *t, int preserve) > errx(1, "malloc"); > if(m->optional){ > fprintf(codefile, "if(%s) {\n", fs); >- fprintf(codefile, "%s = malloc(sizeof(*%s));\n", ts, ts); >+ fprintf(codefile, "%s = calloc(1, sizeof(*%s));\n", ts, ts); > fprintf(codefile, "if(%s == NULL) goto fail;\n", ts); > used_fail++; > } >@@ -161,7 +161,7 @@ copy_type (const char *from, const char *to, const Type *t, int preserve) > char *f = NULL, *T = NULL; > > fprintf (codefile, "if(((%s)->val = " >- "malloc((%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n", >+ "calloc(1, (%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n", > to, from, to, from); > fprintf (codefile, "goto fail;\n"); > used_fail++; >@@ -228,10 +228,10 @@ copy_type (const char *from, const char *to, const Type *t, int preserve) > void > generate_type_copy (const Symbol *s) > { >+ struct decoration deco; >+ ssize_t more_deco = -1; > int preserve = preserve_type(s->name) ? TRUE : FALSE; > int save_used_fail = used_fail; >- int deco_opt; >- char *ft, *fn; > > used_fail = 0; > >@@ -241,18 +241,39 @@ generate_type_copy (const Symbol *s) > "memset(to, 0, sizeof(*to));\n", > s->gen_name, s->gen_name, s->gen_name); > copy_type ("from", "to", s->type, preserve); >- if (decorate_type(s->gen_name, &ft, &fn, &deco_opt)) { >- if (deco_opt) { >- fprintf(codefile, "if (from->%s) {\n", fn); >- fprintf(codefile, "(to)->%s = malloc(sizeof(*(to)->%s));\n", fn, fn); >- fprintf(codefile, "if (copy_%s((from)->%s, (to)->%s)) goto fail;\n", ft, fn, fn); >+ while (decorate_type(s->gen_name, &deco, &more_deco)) { >+ if (deco.ext && deco.copy_function_name == NULL) { >+ /* Decorated with field of external type but no copy function */ >+ if (deco.ptr) >+ fprintf(codefile, "(to)->%s = 0;\n", deco.field_name); >+ else >+ fprintf(codefile, "memset(&(to)->%s, 0, sizeof((to)->%s));\n", >+ deco.field_name, deco.field_name); >+ } else if (deco.ext) { >+ /* Decorated with field of external type w/ copy function */ >+ if (deco.ptr) { >+ fprintf(codefile, "if (from->%s) {\n", deco.field_name); >+ fprintf(codefile, "(to)->%s = calloc(1, sizeof(*(to)->%s));\n", >+ deco.field_name, deco.field_name); >+ fprintf(codefile, "if (%s((from)->%s, (to)->%s)) goto fail;\n", >+ deco.copy_function_name, deco.field_name, deco.field_name); >+ fprintf(codefile, "}\n"); >+ } else { >+ fprintf(codefile, "if (%s(&(from)->%s, &(to)->%s)) goto fail;\n", >+ deco.copy_function_name, deco.field_name, deco.field_name); >+ } >+ } else if (deco.opt) { >+ /* Decorated with optional field of ASN.1 type */ >+ fprintf(codefile, "if (from->%s) {\n", deco.field_name); >+ fprintf(codefile, "(to)->%s = calloc(1, sizeof(*(to)->%s));\n", deco.field_name, deco.field_name); >+ fprintf(codefile, "if (copy_%s((from)->%s, (to)->%s)) goto fail;\n", deco.field_type, deco.field_name, deco.field_name); > fprintf(codefile, "}\n"); > } else { >- fprintf(codefile, "if (copy_%s(&(from)->%s, &(to)->%s)) goto fail;\n", ft, fn, fn); >+ /* Decorated with required field of ASN.1 type */ >+ fprintf(codefile, "if (copy_%s(&(from)->%s, &(to)->%s)) goto fail;\n", deco.field_type, deco.field_name, deco.field_name); > } > used_fail++; >- free(ft); >- free(fn); >+ free(deco.field_type); > } > fprintf (codefile, "return 0;\n"); > >diff --git a/third_party/heimdal/lib/asn1/gen_decode.c b/third_party/heimdal/lib/asn1/gen_decode.c >index 739f9d85f70a..93d412f63356 100644 >--- a/third_party/heimdal/lib/asn1/gen_decode.c >+++ b/third_party/heimdal/lib/asn1/gen_decode.c >@@ -328,9 +328,9 @@ decode_type(const char *name, const Type *t, int optional, struct value *defval, > "if (len < 1) break;\n"); > pos += 8; > } >- fprintf (codefile, >- "(%s)->%s = (*p >> %d) & 1;\n", >- name, m->gen_name, 7 - m->val % 8); >+ fprintf(codefile, >+ "(%s)->%s = (*p >> %d) & 1;\n", >+ name, m->gen_name, (int)(7 - m->val % 8)); > } > fprintf(codefile, > "} while(0);\n"); >diff --git a/third_party/heimdal/lib/asn1/gen_encode.c b/third_party/heimdal/lib/asn1/gen_encode.c >index b0123a8be176..d61dc2e6d502 100644 >--- a/third_party/heimdal/lib/asn1/gen_encode.c >+++ b/third_party/heimdal/lib/asn1/gen_encode.c >@@ -226,7 +226,7 @@ encode_type (const char *name, const Type *t, const char *tmpstr) > fprintf (codefile, > "if((%s)->%s) {\n" > "c |= 1<<%d;\n", >- name, m->gen_name, 7 - m->val % 8); >+ name, m->gen_name, (int)(7 - m->val % 8)); > fprintf (codefile, > "}\n"); > } >@@ -313,7 +313,7 @@ encode_type (const char *name, const Type *t, const char *tmpstr) > name); > > fprintf(codefile, >- "val = malloc(sizeof(val[0]) * (%s)->len);\n" >+ "val = calloc(1, sizeof(val[0]) * (%s)->len);\n" > "if (val == NULL && (%s)->len != 0) return ENOMEM;\n", > name, name); > >@@ -461,23 +461,24 @@ encode_type (const char *name, const Type *t, const char *tmpstr) > > if (replace_tag) > fprintf(codefile, >- "{ unsigned char *psave_%s = p;\n" >+ "{ unsigned char *psave_%s = p, *pfree_%s = NULL;\n" > "size_t l2_%s, lensave_%s = len;\n" > "len = length_%s(%s);\n" > /* Allocate a temp buffer for the encoder */ >- "if ((p = malloc(len)) == NULL) return ENOMEM;\n" >+ "if ((p = pfree_%s = calloc(1, len)) == NULL) return ENOMEM;\n" > /* Make p point to the last byte of the allocated buf */ > "p += len - 1;\n", >- tmpstr, tmpstr, tmpstr, >- t->subtype->symbol->gen_name, name); >+ tmpstr, tmpstr, tmpstr, tmpstr, >+ t->subtype->symbol->gen_name, name, tmpstr); > >+ /* XXX Currently we generate code that leaks `pfree_%s` here. */ > c = encode_type (name, t->subtype, tname); > /* Explicit non-UNIVERSAL tags are always constructed */ > if (!c && t->tag.tagclass != ASN1_C_UNIV && t->tag.tagenv == TE_EXPLICIT) > c = 1; > if (replace_tag) > fprintf(codefile, >- "if (len) abort();\n" >+ "if (len) { free(pfree_%s); return EINVAL; }\n" > /* > * Here we have `p' pointing to one byte before the buffer > * we allocated above. >@@ -552,16 +553,16 @@ encode_type (const char *name, const Type *t, const char *tmpstr) > * +-- psave_<fieldName> > */ > "e = der_put_tag(psave_%s, %lu, %s, %s, %d, &l2_%s);\n" >- "if (e) return e;\n" >+ "if (e) { free(pfree_%s); return e; }\n" > /* Restore `len' and adjust it (see `p' below) */ >- "len = lensave_%s - (l + %lu - asn1_tag_length_%s);\n" >+ "len = lensave_%s - (l + %zu - asn1_tag_length_%s);\n" > /* > * Adjust `ret' to account for the difference in size > * between the length of the right and wrong tags. > */ >- "ret += %lu - asn1_tag_length_%s;\n" >+ "ret += %zu - asn1_tag_length_%s;\n" > /* Free the buffer and restore `p' */ >- "free(p + 1);\n" >+ "free(pfree_%s);\n" > /* > * Make `p' point into the original buffer again, to one > * byte before the bytes we wrote: >@@ -573,7 +574,7 @@ encode_type (const char *name, const Type *t, const char *tmpstr) > * +-- p > */ > "p = psave_%s - (1 + %lu - asn1_tag_length_%s); }\n", >- tmpstr, tmpstr, t->subtype->symbol->name, >+ tmpstr, tmpstr, tmpstr, t->subtype->symbol->name, > tmpstr, t->subtype->symbol->name, t->subtype->symbol->name, > tmpstr, length_tag(t->tag.tagvalue), > classname(t->tag.tagclass), >@@ -581,9 +582,9 @@ encode_type (const char *name, const Type *t, const char *tmpstr) > t->tag.tagvalue, > tmpstr, > >- tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name, >+ tmpstr, tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name, > length_tag(t->tag.tagvalue), t->subtype->symbol->name, >- tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name); >+ tmpstr, tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name); > else > fprintf(codefile, > "e = der_put_length_and_tag (p, len, ret, %s, %s, %s, &l);\n" >diff --git a/third_party/heimdal/lib/asn1/gen_free.c b/third_party/heimdal/lib/asn1/gen_free.c >index 6c9424cbf351..0507d5421803 100644 >--- a/third_party/heimdal/lib/asn1/gen_free.c >+++ b/third_party/heimdal/lib/asn1/gen_free.c >@@ -56,6 +56,7 @@ free_type (const char *name, const Type *t, int preserve) > free_primitive ("heim_integer", name); > break; > } >+ /* fallthrough; */ > case TBoolean: > case TEnumerated : > case TNull: >@@ -126,14 +127,14 @@ free_type (const char *name, const Type *t, int preserve) > case TSequenceOf: { > char *n; > >- fprintf (codefile, "while((%s)->len){\n", name); >+ fprintf (codefile, "if ((%s)->val)\nwhile((%s)->len){\n", name, name); > if (asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name) < 0 || n == NULL) > errx(1, "malloc"); > free_type(n, t->subtype, FALSE); > fprintf(codefile, > "(%s)->len--;\n" >- "}\n", >- name); >+ "} else (%s)->len = 0;\n", >+ name, name); > fprintf(codefile, > "free((%s)->val);\n" > "(%s)->val = NULL;\n", name, name); >@@ -178,9 +179,9 @@ free_type (const char *name, const Type *t, int preserve) > void > generate_type_free (const Symbol *s) > { >+ struct decoration deco; >+ ssize_t more_deco = -1; > int preserve = preserve_type(s->name) ? TRUE : FALSE; >- int deco_opt; >- char *ft, *fn; > > fprintf (codefile, "void ASN1CALL\n" > "free_%s(%s *data)\n" >@@ -188,18 +189,44 @@ generate_type_free (const Symbol *s) > s->gen_name, s->gen_name); > > free_type ("data", s->type, preserve); >- if (decorate_type(s->gen_name, &ft, &fn, &deco_opt)) { >- if (deco_opt) { >- fprintf(codefile, "if ((data)->%s) {\n", fn); >- fprintf(codefile, "free_%s((data)->%s);\n", ft, fn); >- fprintf(codefile, "free((data)->%s);\n", fn); >- fprintf(codefile, "(data)->%s = NULL;\n", fn); >+ while (decorate_type(s->gen_name, &deco, &more_deco)) { >+ if (deco.ext && deco.free_function_name == NULL) { >+ /* Decorated with field of external type but no free function */ >+ if (deco.ptr) >+ fprintf(codefile, "(data)->%s = 0;\n", deco.field_name); >+ else >+ fprintf(codefile, >+ "memset(&(data)->%s, 0, sizeof((data)->%s));\n", >+ deco.field_name, deco.field_name); >+ } else if (deco.ext) { >+ /* Decorated with field of external type w/ free function */ >+ if (deco.ptr) { >+ fprintf(codefile, "if ((data)->%s) {\n", deco.field_name); >+ fprintf(codefile, "%s((data)->%s);\n", >+ deco.free_function_name, deco.field_name); >+ fprintf(codefile, "(data)->%s = 0;\n", deco.field_name); >+ fprintf(codefile, "}\n"); >+ } else { >+ fprintf(codefile, "%s(&(data)->%s);\n", >+ deco.free_function_name, deco.field_name); >+ fprintf(codefile, >+ "memset(&(data)->%s, 0, sizeof((data)->%s));\n", >+ deco.field_name, deco.field_name); >+ } >+ } else if (deco.opt) { >+ /* Decorated with optional field of ASN.1 type */ >+ fprintf(codefile, "if ((data)->%s) {\n", deco.field_name); >+ fprintf(codefile, "free_%s((data)->%s);\n", >+ deco.field_type, deco.field_name); >+ fprintf(codefile, "free((data)->%s);\n", deco.field_name); >+ fprintf(codefile, "(data)->%s = NULL;\n", deco.field_name); > fprintf(codefile, "}\n"); > } else { >- fprintf(codefile, "free_%s(&(data)->%s);\n", ft, fn); >+ /* Decorated with required field of ASN.1 type */ >+ fprintf(codefile, "free_%s(&(data)->%s);\n", >+ deco.field_type, deco.field_name); > } >- free(ft); >- free(fn); >+ free(deco.field_type); > } > fprintf (codefile, "}\n\n"); > } >diff --git a/third_party/heimdal/lib/asn1/gen_glue.c b/third_party/heimdal/lib/asn1/gen_glue.c >index 24f16528c630..424e5de5d5eb 100644 >--- a/third_party/heimdal/lib/asn1/gen_glue.c >+++ b/third_party/heimdal/lib/asn1/gen_glue.c >@@ -62,7 +62,7 @@ generate_2int (const Type *t, const char *gen_name) > > HEIM_TAILQ_FOREACH(m, t->members, members) { > fprintf (get_code_file(), "if(f.%s) r |= (1ULL << %d);\n", >- m->gen_name, m->val); >+ m->gen_name, (int)m->val); > } > fprintf (get_code_file(), "return r;\n" > "}\n\n"); >@@ -87,7 +87,7 @@ generate_int2 (const Type *t, const char *gen_name) > if(t->members) { > HEIM_TAILQ_FOREACH(m, t->members, members) { > fprintf (get_code_file(), "\tflags.%s = (n >> %d) & 1;\n", >- m->gen_name, m->val); >+ m->gen_name, (int)m->val); > } > } > fprintf (get_code_file(), "\treturn flags;\n" >@@ -114,7 +114,7 @@ generate_units (const Type *t, const char *gen_name) > if(t->members) { > HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) { > fprintf (get_code_file(), >- "\t{\"%s\",\t1ULL << %d},\n", m->name, m->val); >+ "\t{\"%s\",\t1ULL << %d},\n", m->name, (int)m->val); > } > } > >@@ -144,8 +144,11 @@ generate_glue (const Type *t, const char *gen_name) > if (HEIM_TAILQ_EMPTY(t->members)) > break; > HEIM_TAILQ_FOREACH(m, t->members, members) { >- if (m->val > 63) >+ if (m->val > 63) { >+ warnx("Not generating 2int, int2, or units for %s due to " >+ "having a member valued more than 63", gen_name); > return; >+ } > } > generate_2int (t, gen_name); > generate_int2 (t, gen_name); >diff --git a/third_party/heimdal/lib/asn1/gen_locl.h b/third_party/heimdal/lib/asn1/gen_locl.h >index ccef2acd2319..f37f1490320b 100644 >--- a/third_party/heimdal/lib/asn1/gen_locl.h >+++ b/third_party/heimdal/lib/asn1/gen_locl.h >@@ -144,7 +144,22 @@ int is_tagged_type(const Type *); > > int preserve_type(const char *); > int seq_type(const char *); >-int decorate_type(const char *, char **, char **, int *); >+ >+struct decoration { >+ char *field_type; /* C type name */ >+ char *field_name; /* C struct field name */ >+ char *copy_function_name; /* copy constructor function name */ >+ char *free_function_name; /* destructor function name */ >+ char *header_name; /* header name */ >+ unsigned int decorated:1; >+ unsigned int first:1; /* optional */ >+ unsigned int opt:1; /* optional */ >+ unsigned int ext:1; /* external */ >+ unsigned int ptr:1; /* external, pointer */ >+ unsigned int void_star:1; /* external, void * */ >+ unsigned int struct_star:1; /* external, struct foo * */ >+}; >+int decorate_type(const char *, struct decoration *, ssize_t *); > > void generate_header_of_codefile(const char *); > void close_codefile(void); >diff --git a/third_party/heimdal/lib/asn1/gen_template.c b/third_party/heimdal/lib/asn1/gen_template.c >index af1e44ee68b3..883eab4b6714 100644 >--- a/third_party/heimdal/lib/asn1/gen_template.c >+++ b/third_party/heimdal/lib/asn1/gen_template.c >@@ -449,14 +449,17 @@ add_line_pointer(struct templatehead *t, > errx(1, "malloc"); > va_end(ap); > >- q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr); >+ if (ptr[0] == '&') >+ q = add_line(t, "{ %s, %s, %s }", tt, offset, ptr); >+ else >+ q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr); > q->tt = tt; > q->offset = strdup(offset); > q->ptr = strdup(ptr); > } > > /* >- * Add an entry to a template where the pointer firled is a string literal. >+ * Add an entry to a template where the pointer field is a string literal. > */ > static void > add_line_string(struct templatehead *t, >@@ -549,11 +552,11 @@ defval(struct templatehead *temp, Member *m) > { > switch (m->defval->type) { > case booleanvalue: >- add_line(temp, "{ A1_OP_DEFVAL|A1_DV_BOOLEAN, ~0, (void *)%u }", >+ add_line(temp, "{ A1_OP_DEFVAL|A1_DV_BOOLEAN, ~0, (void *)(uintptr_t)%u }", > m->defval->u.booleanvalue); > break; > case nullvalue: >- add_line(temp, "{ A1_OP_DEFVAL|A1_DV_NULL, ~0, (void *)0 }"); >+ add_line(temp, "{ A1_OP_DEFVAL|A1_DV_NULL, ~0, (void *)(uintptr_t)0 }"); > break; > case integervalue: { > const char *dv = "A1_DV_INTEGER"; >@@ -576,16 +579,16 @@ defval(struct templatehead *temp, Member *m) > > if (t->members) > dv = "A1_DV_INTEGER32"; /* XXX Enum size assumptions! No good! */ >- else if (t->range->min < 0 && >+ else if (t->range && t->range->min < 0 && > (t->range->min < INT_MIN || t->range->max > INT_MAX)) > dv = "A1_DV_INTEGER64"; >- else if (t->range->min < 0) >+ else if (t->range && t->range->min < 0) > dv = "A1_DV_INTEGER32"; >- else if (t->range->max > UINT_MAX) >+ else if (t->range && t->range->max > UINT_MAX) > dv = "A1_DV_INTEGER64"; > else > dv = "A1_DV_INTEGER32"; >- add_line(temp, "{ A1_OP_DEFVAL|%s, ~0, (void *)%llu }", >+ add_line(temp, "{ A1_OP_DEFVAL|%s, ~0, (void *)(uintptr_t)%llu }", > dv, (long long)m->defval->u.integervalue); > break; > } >@@ -595,7 +598,7 @@ defval(struct templatehead *temp, Member *m) > if (rk_strasvis("ed, m->defval->u.stringvalue, > VIS_CSTYLE | VIS_NL, "\"") < 0) > err(1, "Could not quote a string"); >- add_line(temp, "{ A1_OP_DEFVAL|A1_DV_UTF8STRING, ~0, (void *)\"%s\" }", >+ add_line(temp, "{ A1_OP_DEFVAL|A1_DV_UTF8STRING, ~0, (void *)(uintptr_t)\"%s\" }", > quoted); > free(quoted); > break; >@@ -624,11 +627,13 @@ defval(struct templatehead *temp, Member *m) > sz -= len; > p += len; > } >- len = snprintf(p, sz, " }"); >+ if ((len = snprintf(p, sz, " }")) >= sz) >+ abort(); > sz -= len; >- p += len; >+ if (sz != 0) >+ abort(); > >- add_line(temp, "{ A1_OP_DEFVAL|A1_DV_INTEGER, ~0, (void *)\"%s\" }", s); >+ add_line(temp, "{ A1_OP_DEFVAL|A1_DV_INTEGER, ~0, (void *)(uintptr_t)\"%s\" }", s); > free(s); > break; > } >@@ -711,6 +716,8 @@ sort_object_set(IOSObjectSet *os, /* Object set to sort fields of */ > IOSObject *o; > size_t i, nobjs = 0; > >+ *objectsp = NULL; >+ > HEIM_TAILQ_FOREACH(o, os->objects, objects) { > ObjectField *typeidobjf = NULL; > ObjectField *of; >@@ -730,6 +737,9 @@ sort_object_set(IOSObjectSet *os, /* Object set to sort fields of */ > } > *nobjsp = nobjs; > >+ if (nobjs == 0) >+ return; >+ > if ((objects = calloc(nobjs, sizeof(*objects))) == NULL) > err(1, "Out of memory"); > *objectsp = objects; >@@ -752,7 +762,7 @@ sort_object_set(IOSObjectSet *os, /* Object set to sort fields of */ > static void > template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield) > { >- IOSObject **objects; >+ IOSObject **objects = NULL; > IOSObject *o; > struct tlist *tl; > size_t nobjs, i; >@@ -794,7 +804,7 @@ template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield) > switch (typeidobjf->value->type) { > case integervalue: > add_line(&tl->template, >- "{ A1_OP_OPENTYPE_ID | A1_OTI_IS_INTEGER, 0, (void *)%lld }", >+ "{ A1_OP_OPENTYPE_ID | A1_OTI_IS_INTEGER, 0, (void *)(uintptr_t)%lld }", > (long long)typeidobjf->value->u.integervalue); > break; > case objectidentifiervalue: >@@ -820,7 +830,7 @@ template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield) > } > free(objects); > >- tlist_header(tl, "{ 0, 0, ((void *)%lu) }", nobjs); >+ tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%lu) }", nobjs); > tlist_print(tl); > tlist_add(tl); > os->symbol->emitted_template = 1; >@@ -952,12 +962,15 @@ template_members(struct templatehead *temp, > */ > HEIM_TAILQ_FOREACH(m, t->members, members) { > if (m->val > UINT32_MAX) >- continue; /* Wouldn't fit in the offset field */ >+ errx(1, "Cannot handle %s type %s with named bit %s " >+ "larger than 63", >+ t->type == TEnumerated ? "ENUMERATED" : "INTEGER", >+ name, m->gen_name); > add_line(&tl->template, >- "{ A1_OP_NAME, %d, \"%s\" }", m->val, m->name); >+ "{ A1_OP_NAME, %d, \"%s\" }", (int)m->val, m->name); > nmemb++; > } >- tlist_header(tl, "{ 0, 0, ((void *)%lu) }", nmemb); >+ tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%lu) }", nmemb); > /* XXX Accidentally O(N^2)? */ > if (!tlist_find_dup(tl)) { > tlist_print(tl); >@@ -1031,7 +1044,10 @@ template_members(struct templatehead *temp, > output_name(bname); > > HEIM_TAILQ_FOREACH(m, t->members, members) { >- add_line(&template, "{ 0, %d, \"%s\" }", m->val, m->gen_name); >+ if (m->val > UINT32_MAX) >+ errx(1, "Cannot handle BIT STRING type %s with named bit %s " >+ "larger than 63", name, m->gen_name); >+ add_line(&template, "{ 0, %d, \"%s\" }", (int)m->val, m->gen_name); > } > > HEIM_TAILQ_FOREACH(q, &template, members) { >@@ -1039,7 +1055,7 @@ template_members(struct templatehead *temp, > } > > fprintf(f, "static const struct asn1_template asn1_%s_%s[] = {\n", basetype, bname); >- fprintf(f, "/* 0 */ { 0%s, sizeof(%s), ((void *)%lu) },\n", >+ fprintf(f, "/* 0 */ { 0%s, sizeof(%s), ((void *)(uintptr_t)%lu) },\n", > rfc1510_bitstring ? "|A1_HBF_RFC1510" : "", > basetype, (unsigned long)count); > i = 1; >@@ -1061,10 +1077,10 @@ template_members(struct templatehead *temp, > Field *opentypefield = NULL; > Field *typeidfield = NULL; > Member *m; >+ struct decoration deco; >+ ssize_t more_deco = -1; > size_t i = 0, typeididx = 0, opentypeidx = 0; > int is_array_of_open_type = 0; >- int deco_opt; >- char *ft, *fn; > > if (isstruct && t->actual_parameter) > get_open_type_defn_fields(t, &typeidmember, &opentypemember, >@@ -1104,15 +1120,29 @@ template_members(struct templatehead *temp, > typeidfield, opentypefield, opentypemember, > is_array_of_open_type); > >- if (decorate_type(basetype, &ft, &fn, &deco_opt)) { >+ while (decorate_type(basetype, &deco, &more_deco)) { > char *poffset2; > >- poffset2 = partial_offset(basetype, fn, 1, isstruct); >- add_line_pointer(temp, ft, poffset2, "A1_OP_TYPE_DECORATE %s", >- deco_opt ? "|A1_FLAG_OPTIONAL" : ""); >+ poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct); >+ >+ if (deco.ext) { >+ char *ptr = NULL; >+ >+ /* Decorated with external C type */ >+ if (asprintf(&ptr, "&asn1_extern_%s_%s", >+ basetype, deco.field_name) == -1 || ptr == NULL) >+ err(1, "out of memory"); >+ add_line_pointer(temp, ptr, poffset2, >+ "A1_OP_TYPE_DECORATE_EXTERN %s", >+ deco.opt ? "|A1_FLAG_OPTIONAL" : ""); >+ free(ptr); >+ } else >+ /* Decorated with a templated ASN.1 type */ >+ add_line_pointer(temp, deco.field_type, poffset2, >+ "A1_OP_TYPE_DECORATE %s", >+ deco.opt ? "|A1_FLAG_OPTIONAL" : ""); > free(poffset2); >- free(ft); >- free(fn); >+ free(deco.field_type); > } > > if (isstruct) >@@ -1125,10 +1155,10 @@ template_members(struct templatehead *temp, > Field *opentypefield = NULL; > Field *typeidfield = NULL; > Member *m; >+ struct decoration deco; >+ ssize_t more_deco = -1; > size_t i = 0, typeididx = 0, opentypeidx = 0; > int is_array_of_open_type = 0; >- int deco_opt; >- char *ft, *fn; > > if (isstruct && t->actual_parameter) > get_open_type_defn_fields(t, &typeidmember, &opentypemember, >@@ -1168,15 +1198,29 @@ template_members(struct templatehead *temp, > typeidfield, opentypefield, opentypemember, > is_array_of_open_type); > >- if (decorate_type(basetype, &ft, &fn, &deco_opt)) { >+ while (decorate_type(basetype, &deco, &more_deco)) { > char *poffset2; > >- poffset2 = partial_offset(basetype, fn, 1, isstruct); >- add_line_pointer(temp, ft, poffset2, "A1_OP_TYPE_DECORATE %s", >- deco_opt ? "|A1_FLAG_OPTIONAL" : ""); >+ poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct); >+ >+ if (deco.ext) { >+ char *ptr = NULL; >+ >+ /* Decorated with external C type */ >+ if (asprintf(&ptr, "&asn1_extern_%s_%s", >+ basetype, deco.field_name) == -1 || ptr == NULL) >+ err(1, "out of memory"); >+ add_line_pointer(temp, ptr, poffset2, >+ "A1_OP_TYPE_DECORATE_EXTERN %s", >+ deco.opt ? "|A1_FLAG_OPTIONAL" : ""); >+ free(ptr); >+ } else >+ /* Decorated with a templated ASN.1 type */ >+ add_line_pointer(temp, deco.field_type, poffset2, >+ "A1_OP_TYPE_DECORATE %s", >+ deco.opt ? "|A1_FLAG_OPTIONAL" : ""); > free(poffset2); >- free(ft); >- free(fn); >+ free(deco.field_type); > } > > if (isstruct) >@@ -1273,6 +1317,8 @@ template_members(struct templatehead *temp, > break; > } > case TChoice: { >+ struct decoration deco; >+ ssize_t more_deco = -1; > struct templatehead template; > struct template *q; > size_t count = 0, i; >@@ -1343,7 +1389,7 @@ template_members(struct templatehead *temp, > } > > fprintf(f, "static const struct asn1_template %s[] = {\n", tname); >- fprintf(f, "/* 0 */ { %s, offsetof(%s%s, element), ((void *)%lu) },\n", >+ fprintf(f, "/* 0 */ { %s, offsetof(%s%s, element), ((void *)(uintptr_t)%lu) },\n", > e ? e : "0", isstruct ? "struct " : "", basetype, (unsigned long)count); > i = 1; > HEIM_TAILQ_FOREACH(q, &template, members) { >@@ -1354,6 +1400,31 @@ template_members(struct templatehead *temp, > > add_line(temp, "{ A1_OP_CHOICE, %s, %s }", poffset, tname); > >+ while (decorate_type(basetype, &deco, &more_deco)) { >+ char *poffset2; >+ >+ poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct); >+ >+ if (deco.ext) { >+ char *ptr = NULL; >+ >+ /* Decorated with external C type */ >+ if (asprintf(&ptr, "&asn1_extern_%s_%s", >+ basetype, deco.field_name) == -1 || ptr == NULL) >+ err(1, "out of memory"); >+ add_line_pointer(temp, ptr, poffset2, >+ "A1_OP_TYPE_DECORATE_EXTERN %s", >+ deco.opt ? "|A1_FLAG_OPTIONAL" : ""); >+ free(ptr); >+ } else >+ /* Decorated with a templated ASN.1 type */ >+ add_line_pointer(temp, deco.field_type, poffset2, >+ "A1_OP_TYPE_DECORATE %s", >+ deco.opt ? "|A1_FLAG_OPTIONAL" : ""); >+ free(poffset2); >+ free(deco.field_type); >+ } >+ > free(e); > free(tname); > break; >@@ -1464,7 +1535,7 @@ generate_template_type(const char *varname, > > fprintf(get_code_file(), "/* generate_template_type: %s */\n", tl->name); > >- tlist_header(tl, "{ 0%s%s, sizeof(%s), ((void *)%lu) }", >+ tlist_header(tl, "{ 0%s%s, sizeof(%s), ((void *)(uintptr_t)%lu) }", > (symname && preserve_type(symname)) ? "|A1_HF_PRESERVE" : "", > have_ellipsis ? "|A1_HF_ELLIPSIS" : "", szt, tlist_count(tl)); > >@@ -1491,12 +1562,37 @@ generate_template(const Symbol *s) > { > FILE *f = get_code_file(); > const char *dupname; >+ struct decoration deco; >+ ssize_t more_deco = -1; > > if (use_extern(s)) { > gen_extern_stubs(f, s->gen_name); > return; > } > >+ while (decorate_type(s->gen_name, &deco, &more_deco)) { >+ if (!deco.ext) >+ continue; >+ if (deco.void_star && deco.header_name) >+ fprintf(f, "#include %s\n", deco.header_name); >+ fprintf(f, >+ "static const struct asn1_type_func asn1_extern_%s_%s = {\n" >+ "\t(asn1_type_encode)0,\n" >+ "\t(asn1_type_decode)0,\n" >+ "\t(asn1_type_length)0,\n" >+ "\t(asn1_type_copy)%s,\n" >+ "\t(asn1_type_release)%s,\n" >+ "\t(asn1_type_print)0,\n" >+ "\tsizeof(%s)\n" >+ "};\n", s->gen_name, deco.field_name, >+ deco.copy_function_name && deco.copy_function_name[0] ? >+ deco.copy_function_name : "0", >+ deco.free_function_name && deco.free_function_name[0] ? >+ deco.free_function_name : "0", >+ deco.void_star ? "void *" : deco.field_type); >+ free(deco.field_type); >+ } >+ > generate_template_type(s->gen_name, &dupname, s->name, s->gen_name, NULL, s->type, 0, 0, 1); > > fprintf(f, >diff --git a/third_party/heimdal/lib/asn1/krb5.asn1 b/third_party/heimdal/lib/asn1/krb5.asn1 >index baaec52f5f83..639ec5af2d25 100644 >--- a/third_party/heimdal/lib/asn1/krb5.asn1 >+++ b/third_party/heimdal/lib/asn1/krb5.asn1 >@@ -18,6 +18,7 @@ EXPORTS > CKSUMTYPE, > ChangePasswdDataMS, > Checksum, >+ CompositePrincipal, > ENCTYPE, > ETYPE-INFO, > ETYPE-INFO-ENTRY, >@@ -440,9 +441,9 @@ Checksum ::= SEQUENCE { > -- > -- Attributes have three possible sources in Heimdal Kerberos at this time: > -- >--- - the EncKDCRepPart >--- - the EncTicketPart >--- - the Authenticator's AuthorizationData (if any) >+-- - the EncKDCRepPart (for the client's attributes on the client side) >+-- - the EncTicketPart (for the client's attributes on the server side) >+-- - the Authenticator's AuthorizationData (if any; server-side) > -- > -- In principle there can be more: > -- >@@ -461,18 +462,47 @@ PrincipalNameAttrSrc ::= CHOICE { > enc-ticket-part [1] EncTicketPart -- minus session key > } > PrincipalNameAttrs ::= SEQUENCE { >+ -- True if this name was authenticated via an AP-REQ or a KDC-REP > authenticated [0] BOOLEAN, >- -- These are compiled from the Ticket and Authenticator: >+ -- These are compiled from the Ticket, KDC-REP, and/or Authenticator > source [1] PrincipalNameAttrSrc OPTIONAL, >- authenticator-ad [2] AuthorizationData OPTIONAL >+ authenticator-ad [2] AuthorizationData OPTIONAL, >+ -- For the server on the client side we should keep track of the >+ -- transit path taken to reach it (if absent -> unknown). >+ -- >+ -- We don't learn much more about the server from the KDC. >+ peer-realm [3] Realm OPTIONAL, >+ transited [4] TransitedEncoding OPTIONAL, >+ -- True if the PAC was verified >+ pac-verified [5] BOOLEAN, >+ -- True if any AD-KDC-ISSUEDs in the Ticket were validated >+ kdc-issued-verified [6] BOOLEAN, >+ -- TODO: Add requested attributes, for gss_set_name_attribute(), which >+ -- should cause corresponding authz-data elements to be added to >+ -- any TGS-REQ or to the AP-REQ's Authenticator as appropriate. >+ want-ad [7] AuthorizationData OPTIONAL >+} >+-- This is our type for exported composite name tokens for GSS [RFC6680]. >+-- It's the same as Principal (below) as decorated with (see krb5.opt file and >+-- asn1_compile usage), except it's not decorated, so the name attributes are >+-- encoded/decoded. >+CompositePrincipal ::= [APPLICATION 48] SEQUENCE { >+ name[0] PrincipalName, >+ realm[1] Realm, >+ nameattrs[2] PrincipalNameAttrs OPTIONAL > } > >--- this is not part of RFC1510 >+-- This is not part of RFC1510/RFC4120. We use this internally as our >+-- krb5_principal (which is a typedef of *Principal), and in HDB entries. > Principal ::= SEQUENCE { > name[0] PrincipalName, > realm[1] Realm >- -- This will be decorated with a name-attrs field of >- -- PrincipalNameAttrs type that doesn't get encoded >+ -- This will be decorated with an optional nameattrs field of >+ -- PrincipalNameAttrs type that doesn't get encoded. Same as >+ -- CompositePrincipal above, except that CompositePrincipal's >+ -- nameattrs field does get encoded, while Principal's does not: >+ -- >+ -- nameattrs[2] PrincipalNameAttrs OPTIONAL > } > > Principals ::= SEQUENCE OF Principal >diff --git a/third_party/heimdal/lib/asn1/krb5.opt b/third_party/heimdal/lib/asn1/krb5.opt >index 5acc596d39ce..a8bd85c522fb 100644 >--- a/third_party/heimdal/lib/asn1/krb5.opt >+++ b/third_party/heimdal/lib/asn1/krb5.opt >@@ -5,3 +5,5 @@ > --sequence=ETYPE-INFO > --sequence=ETYPE-INFO2 > --preserve-binary=KDC-REQ-BODY >+--decorate=PrincipalNameAttrs:void *:pac >+--decorate=Principal:PrincipalNameAttrs:nameattrs? >diff --git a/third_party/heimdal/lib/asn1/libasn1-exports.def b/third_party/heimdal/lib/asn1/libasn1-exports.def >index ade5e2d0bfd0..15d3a37bebaf 100644 >--- a/third_party/heimdal/lib/asn1/libasn1-exports.def >+++ b/third_party/heimdal/lib/asn1/libasn1-exports.def >@@ -335,6 +335,7 @@ EXPORTS > copy_CommonCriteriaMeasures > copy_CommunityIdentifier > copy_CommunityIdentifiers >+ copy_CompositePrincipal > copy_ContentEncryptionAlgorithmIdentifier > copy_ContentInfo > copy_ContentType >@@ -691,6 +692,7 @@ EXPORTS > decode_CommonCriteriaMeasures > decode_CommunityIdentifier > decode_CommunityIdentifiers >+ decode_CompositePrincipal > decode_ContentEncryptionAlgorithmIdentifier > decode_ContentInfo > decode_ContentType >@@ -1196,6 +1198,7 @@ EXPORTS > encode_CommonCriteriaMeasures > encode_CommunityIdentifier > encode_CommunityIdentifiers >+ encode_CompositePrincipal > encode_ContentEncryptionAlgorithmIdentifier > encode_ContentInfo > encode_ContentType >@@ -1556,6 +1559,7 @@ EXPORTS > free_CommonCriteriaMeasures > free_CommunityIdentifier > free_CommunityIdentifiers >+ free_CompositePrincipal > free_ContentEncryptionAlgorithmIdentifier > free_ContentInfo > free_ContentType >@@ -1938,6 +1942,7 @@ EXPORTS > length_CommonCriteriaMeasures > length_CommunityIdentifier > length_CommunityIdentifiers >+ length_CompositePrincipal > length_ContentEncryptionAlgorithmIdentifier > length_ContentInfo > length_ContentType >@@ -2294,6 +2299,7 @@ EXPORTS > print_CommonCriteriaMeasures > print_CommunityIdentifier > print_CommunityIdentifiers >+ print_CompositePrincipal > print_ContentEncryptionAlgorithmIdentifier > print_ContentInfo > print_ContentType >diff --git a/third_party/heimdal/lib/asn1/main.c b/third_party/heimdal/lib/asn1/main.c >index 64db63ab2ecb..bcfdad62e2e7 100644 >--- a/third_party/heimdal/lib/asn1/main.c >+++ b/third_party/heimdal/lib/asn1/main.c >@@ -41,60 +41,195 @@ static getarg_strings preserve; > static getarg_strings seq; > static getarg_strings decorate; > >+static int >+strcmp4mergesort_r(const void *ap, const void *bp, void *d) >+{ >+ const char *a = *(const char **)ap; >+ const char *b = *(const char **)bp; >+ char sep = *(const char *)d; >+ int cmp; >+ >+ if (sep) { >+ const char *sepa = strchr(a, sep); >+ const char *sepb = strchr(b, sep); >+ size_t alen, blen; >+ >+ if (sepa == NULL) sepa = a + strlen(a); >+ if (sepb == NULL) sepb = b + strlen(b); >+ alen = sepa - a; >+ blen = sepb - b; >+ cmp = strncmp(a, b, alen > blen ? alen : blen); >+ if (cmp == 0) >+ cmp = alen - blen; >+ } else >+ cmp = strcmp(a, b); >+ if (cmp == 0) >+ return (uintptr_t)ap - (uintptr_t)bp; /* stable sort */ >+ return cmp; >+} >+ >+static int >+prefix_check(const char *s, const char *p, size_t plen, char sep, int *cmp) >+{ >+ if ((*cmp = strncmp(p, s, plen)) == 0 && s[plen] == sep) >+ return 1; >+ if (*cmp == 0) >+ *cmp = 1; >+ return 0; >+} >+ >+static ssize_t >+bsearch_strings(struct getarg_strings *strs, const char *p, >+ char sep, ssize_t *more) >+{ >+ ssize_t right = (ssize_t)strs->num_strings - 1; >+ ssize_t left = 0; >+ ssize_t plen = 0; >+ int cmp; >+ >+ if (sep) >+ plen = strlen(p); >+ >+ if (strs->num_strings == 0) >+ return -1; >+ >+ if (sep && more && *more > -1) { >+ /* If *more > -1 we're continuing an iteration */ >+ if (*more > right) >+ return -1; >+ if (prefix_check(strs->strings[*more], p, plen, sep, &cmp)) >+ return (*more)++; >+ (*more)++; >+ return -1; >+ } >+ >+ while (left <= right) { >+ ssize_t mid = left + (right - left) / 2; >+ >+ if (sep) { >+ int cmp2; >+ >+ while (prefix_check(strs->strings[mid], p, plen, sep, &cmp) && >+ mid > 0 && >+ prefix_check(strs->strings[mid - 1], p, plen, sep, &cmp2)) >+ mid--; >+ } else >+ cmp = strcmp(p, strs->strings[mid]); >+ if (cmp == 0) { >+ if (more) >+ *more = mid + 1; >+ return mid; >+ } >+ if (cmp < 0) >+ right = mid - 1; /* -1 if `p' is smaller than smallest in strs */ >+ else >+ left = mid + 1; >+ } >+ return -1; >+} >+ > int > preserve_type(const char *p) > { >- int i; >- for (i = 0; i < preserve.num_strings; i++) >- if (strcmp(preserve.strings[i], p) == 0) >- return 1; >- return 0; >+ return bsearch_strings(&preserve, p, '\0', 0) > -1; > } > > int > seq_type(const char *p) > { >- size_t i; >- >- for (i = 0; i < seq.num_strings; i++) >- if (strcmp(seq.strings[i], p) == 0) >- return 1; >- return 0; >+ return bsearch_strings(&seq, p, '\0', 0) > -1; > } > >-int >-decorate_type(const char *p, char **field_type, char **field_name, int *opt) >+/* >+ * Split `s' on `sep' and fill fs[] with pointers to the substrings. >+ * >+ * Only the first substring is to be freed -- the rest share the same >+ * allocation. >+ * >+ * The last element may contain `sep' chars if there are more fields in `s' >+ * than output locations in `fs[]'. >+ */ >+static void >+split_str(const char *s, char sep, char ***fs) > { >- size_t plen = strlen(p); > size_t i; > >- *field_type = NULL; >- *field_name = NULL; >- *opt = 0; >- >- for (i = 0; i < decorate.num_strings; i++) { >- const char *r; >+ fs[0][0] = estrdup(s); >+ for (i = 1; fs[i]; i++) { > char *q; > >- if (strncmp(decorate.strings[i], p, plen) != 0) >- continue; >- if (decorate.strings[i][plen] != ':') >- errx(1, "--decorate argument missing field type"); >- >- p = &decorate.strings[i][plen + 1]; >- if ((r = strchr(p, ':')) == NULL) >- errx(1, "--decorate argument missing field name"); >- r++; >- *field_type = estrdup(p); >- *(strchr(*field_type, ':')) = '\0'; >- *field_name = estrdup(r); >- if ((q = strchr(*field_name, '?'))) { >- *q = '\0'; >- *opt = 1; >- } >- return 1; >+ if ((q = strchr(fs[i-1][0], sep)) == NULL) >+ break; >+ *(q++) = '\0'; >+ fs[i][0] = q; > } >- return 0; >+ for (; fs[i]; i++) >+ fs[i][0] = NULL; >+} >+ >+/* >+ * If `p' is "decorated" with a not-to-be-encoded-or-decoded field, >+ * output the field's typename and fieldname, whether it's optional, whether >+ * it's an ASN.1 type or an "external" type, and if external the names of >+ * functions to copy and free values of that type. >+ */ >+int >+decorate_type(const char *p, struct decoration *deco, ssize_t *more) >+{ >+ ssize_t i; >+ char **s[7]; >+ char *junk = NULL; >+ char *cp; >+ >+ deco->first = *more == -1; >+ deco->decorated = 0; >+ deco->field_type = NULL; >+ if ((i = bsearch_strings(&decorate, p, ':', more)) == -1) >+ return 0; >+ >+ deco->decorated = 1; >+ deco->opt = deco->ext = deco->ptr = 0; >+ deco->void_star = deco->struct_star = 0; >+ deco->field_name = deco->copy_function_name = deco->free_function_name = >+ deco->header_name = NULL; >+ >+ s[0] = &deco->field_type; >+ s[1] = &deco->field_name; >+ s[2] = &deco->copy_function_name; >+ s[3] = &deco->free_function_name; >+ s[4] = &deco->header_name; >+ s[5] = &junk; >+ s[6] = NULL; >+ split_str(decorate.strings[i] + strlen(p) + 1, ':', s); >+ >+ if (junk || deco->field_type[0] == '\0' || !deco->field_name || >+ deco->field_name[0] == '\0' || deco->field_name[0] == '?') { >+ errx(1, "Invalidate type decoration specification: --decorate=\"%s\"", >+ decorate.strings[i]); >+ } >+ if ((cp = strchr(deco->field_name, '?'))) { >+ deco->opt = 1; >+ *cp = '\0'; >+ } >+ if (strcmp(deco->field_type, "void*") == 0 || >+ strcmp(deco->field_type, "void *") == 0) { >+ deco->ext = deco->ptr = deco->void_star = 1; >+ deco->opt = 1; >+ deco->header_name = NULL; >+ } else if (strncmp(deco->field_type, "struct ", sizeof("struct ") - 1) == 0 && >+ deco->field_type[strlen(deco->field_type) - 1] == '*') >+ deco->ptr = deco->struct_star = 1; >+ if (deco->ptr || deco->copy_function_name) >+ deco->ext = 1; >+ if (deco->ext && deco->copy_function_name && !deco->copy_function_name[0]) >+ deco->copy_function_name = NULL; >+ if (deco->ext && deco->free_function_name && !deco->free_function_name[0]) >+ deco->free_function_name = NULL; >+ if (deco->header_name && !deco->header_name[0]) >+ deco->header_name = NULL; >+ if (deco->ptr) >+ deco->opt = 0; >+ return 1; > } > > static const char * >@@ -147,11 +282,11 @@ struct getargs args[] = { > { "preserve-binary", 0, arg_strings, &preserve, > "Names of types for which to generate _save fields, saving original " > "encoding, in containing structures (useful for signature " >- "verification)", "TYPE-NAME" }, >+ "verification)", "TYPE" }, > { "sequence", 0, arg_strings, &seq, >- "Generate add/remove functions for SEQUENCE OF types", "TYPE-NAME" }, >+ "Generate add/remove functions for SEQUENCE OF types", "TYPE" }, > { "decorate", 0, arg_strings, &decorate, >- "Generate private field for SEQUENCE/SET type", "TYPE-NAME:FIELD_TYPE:field_name[?]" }, >+ "Generate private field for SEQUENCE/SET type", "DECORATION" }, > { "one-code-file", 0, arg_flag, &one_code_file, NULL, NULL }, > { "gen-name", 0, arg_string, &name, > "Name of generated module", "NAME" }, >@@ -166,7 +301,7 @@ struct getargs args[] = { > "Do not generate roken-style units", NULL }, > { "type-file", 0, arg_string, &type_file_string, > "Name of a C header file to generate includes of for base types", >- "C-HEADER-FILE" }, >+ "FILE" }, > { "version", 0, arg_flag, &version_flag, NULL, NULL }, > { "help", 0, arg_flag, &help_flag, NULL, NULL } > }; >@@ -175,7 +310,17 @@ int num_args = sizeof(args) / sizeof(args[0]); > static void > usage(int code) > { >+ if (code) >+ dup2(STDERR_FILENO, STDOUT_FILENO); >+ else >+ dup2(STDOUT_FILENO, STDERR_FILENO); > arg_printusage(args, num_args, NULL, "[asn1-file [name]]"); >+ fprintf(stderr, >+ "\nA DECORATION is one of:\n\n" >+ "\tTYPE:FTYPE:fname[?]\n" >+ "\tTYPE:FTYPE:fname[?]:[copy_function]:[free_function]:header\n" >+ "\tTYPE:void:fname:::\n" >+ "\nSee the manual page.\n"); > exit(code); > } > >@@ -304,6 +449,15 @@ main(int argc, char **argv) > #endif > } > >+ if (preserve.num_strings) >+ mergesort_r(preserve.strings, preserve.num_strings, >+ sizeof(preserve.strings[0]), strcmp4mergesort_r, ""); >+ if (seq.num_strings) >+ mergesort_r(seq.strings, seq.num_strings, sizeof(seq.strings[0]), >+ strcmp4mergesort_r, ""); >+ if (decorate.num_strings) >+ mergesort_r(decorate.strings, decorate.num_strings, >+ sizeof(decorate.strings[0]), strcmp4mergesort_r, ":"); > > init_generate(file, name); > >@@ -316,12 +470,12 @@ main(int argc, char **argv) > exit(1); > if (!original_order) > generate_types(); >- close_generate (); > if (argc != optidx) > fclose(yyin); > > if (one_code_file) > close_codefile(); >+ close_generate(); > > if (arg) { > for (i = 1; i < len; i++) >diff --git a/third_party/heimdal/lib/asn1/oid_resolution.c b/third_party/heimdal/lib/asn1/oid_resolution.c >index 63155efbd073..db11b114282e 100644 >--- a/third_party/heimdal/lib/asn1/oid_resolution.c >+++ b/third_party/heimdal/lib/asn1/oid_resolution.c >@@ -59,19 +59,19 @@ struct sym_oid { > { #sym, &asn1_oid_ ## sym }, > > static const struct sym_oid sym_oids[] = { >-#include "cms_asn1_oids.x" >-#include "crmf_asn1_oids.x" >-#include "digest_asn1_oids.x" >-#include "krb5_asn1_oids.x" >-#include "kx509_asn1_oids.x" >-#include "ocsp_asn1_oids.x" >-#include "pkcs10_asn1_oids.x" >-#include "pkcs12_asn1_oids.x" >-#include "pkcs8_asn1_oids.x" >-#include "pkcs9_asn1_oids.x" >-#include "pkinit_asn1_oids.x" >-#include "rfc2459_asn1_oids.x" >-#include "rfc4108_asn1_oids.x" >+#include "cms_asn1_oids.c" >+#include "crmf_asn1_oids.c" >+#include "digest_asn1_oids.c" >+#include "krb5_asn1_oids.c" >+#include "kx509_asn1_oids.c" >+#include "ocsp_asn1_oids.c" >+#include "pkcs10_asn1_oids.c" >+#include "pkcs12_asn1_oids.c" >+#include "pkcs8_asn1_oids.c" >+#include "pkcs9_asn1_oids.c" >+#include "pkinit_asn1_oids.c" >+#include "rfc2459_asn1_oids.c" >+#include "rfc4108_asn1_oids.c" > }; > > static size_t num_sym_oids = sizeof(sym_oids) / sizeof(sym_oids[0]); >@@ -95,18 +95,18 @@ static size_t > count_sym_oids(void) > { > size_t c = 0; >-#include "cms_asn1_oids.x" >-#include "crmf_asn1_oids.x" >-#include "digest_asn1_oids.x" >-#include "krb5_asn1_oids.x" >-#include "kx509_asn1_oids.x" >-#include "ocsp_asn1_oids.x" >-#include "pkcs10_asn1_oids.x" >-#include "pkcs12_asn1_oids.x" >-#include "pkcs8_asn1_oids.x" >-#include "pkcs9_asn1_oids.x" >-#include "pkinit_asn1_oids.x" >-#include "rfc2459_asn1_oids.x" >+#include "cms_asn1_oids.c" >+#include "crmf_asn1_oids.c" >+#include "digest_asn1_oids.c" >+#include "krb5_asn1_oids.c" >+#include "kx509_asn1_oids.c" >+#include "ocsp_asn1_oids.c" >+#include "pkcs10_asn1_oids.c" >+#include "pkcs12_asn1_oids.c" >+#include "pkcs8_asn1_oids.c" >+#include "pkcs9_asn1_oids.c" >+#include "pkinit_asn1_oids.c" >+#include "rfc2459_asn1_oids.c" > return c; > } > #undef DEFINE_OID_WITH_NAME >@@ -125,18 +125,18 @@ init_sym_oids(void) > if (!sym_oids && > (c = count_sym_oids()) && > (tmp = calloc(c, sizeof(tmp[0])))) { >-#include "cms_asn1_oids.x" >-#include "crmf_asn1_oids.x" >-#include "digest_asn1_oids.x" >-#include "krb5_asn1_oids.x" >-#include "kx509_asn1_oids.x" >-#include "ocsp_asn1_oids.x" >-#include "pkcs10_asn1_oids.x" >-#include "pkcs12_asn1_oids.x" >-#include "pkcs8_asn1_oids.x" >-#include "pkcs9_asn1_oids.x" >-#include "pkinit_asn1_oids.x" >-#include "rfc2459_asn1_oids.x" >+#include "cms_asn1_oids.c" >+#include "crmf_asn1_oids.c" >+#include "digest_asn1_oids.c" >+#include "krb5_asn1_oids.c" >+#include "kx509_asn1_oids.c" >+#include "ocsp_asn1_oids.c" >+#include "pkcs10_asn1_oids.c" >+#include "pkcs12_asn1_oids.c" >+#include "pkcs8_asn1_oids.c" >+#include "pkcs9_asn1_oids.c" >+#include "pkinit_asn1_oids.c" >+#include "rfc2459_asn1_oids.c" > num_sym_oids = c; > sym_oids = tmp; > } >@@ -331,7 +331,6 @@ der_print_heim_oid_sym(const heim_oid *oid, char delim, char **strp) > *strp = s1; > return 0; > } >- p = s2 + strlen(s1) + 1; > for (p = s2 + strlen(s1) + 1; *p; p++) { > if (*p == '_') > *p = '-'; >diff --git a/third_party/heimdal/lib/asn1/symbol.h b/third_party/heimdal/lib/asn1/symbol.h >index b88386223b30..8a24e2515657 100644 >--- a/third_party/heimdal/lib/asn1/symbol.h >+++ b/third_party/heimdal/lib/asn1/symbol.h >@@ -91,7 +91,7 @@ struct member { > char *name; > char *gen_name; > char *label; >- int val; >+ int64_t val; > int optional; > int ellipsis; > struct type *type; >@@ -120,7 +120,7 @@ struct range { > int64_t max; > }; > >-enum ctype { CT_CONTENTS, CT_USER, CT_TABLE_CONSTRAINT } ; >+enum ctype { CT_CONTENTS, CT_USER, CT_TABLE_CONSTRAINT, CT_RANGE } ; > > struct constraint_spec; > >@@ -217,6 +217,7 @@ struct constraint_spec { > struct value *encoding; > struct component_relation_constraint crel; > } content; >+ struct range *range; > } u; > }; > >diff --git a/third_party/heimdal/lib/asn1/template.c b/third_party/heimdal/lib/asn1/template.c >index 7f5670f3456f..7a19e7477e3d 100644 >--- a/third_party/heimdal/lib/asn1/template.c >+++ b/third_party/heimdal/lib/asn1/template.c >@@ -37,6 +37,7 @@ > #include <com_err.h> > #include <vis.h> > #include <vis-extras.h> >+#include <heimbase.h> > > #ifndef ENOTSUP > /* Very old MSVC CRTs don't have ENOTSUP */ >@@ -774,6 +775,7 @@ _asn1_decode(const struct asn1_template *t, unsigned flags, > return ret; > break; > } >+ case A1_OP_TYPE_DECORATE_EXTERN: break; > case A1_OP_TYPE_DECORATE: break; > case A1_OP_NAME: break; > case A1_OP_DEFVAL: >@@ -829,6 +831,8 @@ _asn1_decode(const struct asn1_template *t, unsigned flags, > if (ret) { > if (t->tt & A1_FLAG_OPTIONAL) { > } else if (t->tt & A1_FLAG_DEFAULT) { >+ if (!tdefval) >+ return ASN1_PARSE_ERROR; /* Can't happen */ > /* > * Defaulted field not present in encoding, presumably, > * though we should really look more carefully at `ret'. >@@ -895,6 +899,8 @@ _asn1_decode(const struct asn1_template *t, unsigned flags, > data = olddata; > break; > } else if (t->tt & A1_FLAG_DEFAULT) { >+ if (!tdefval) >+ return ASN1_PARSE_ERROR; /* Can't happen */ > /* > * Defaulted field not present in encoding, presumably, > * though we should really look more carefully at `ret'. >@@ -1418,6 +1424,7 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const > } > case A1_OP_NAME: break; > case A1_OP_DEFVAL: break; >+ case A1_OP_TYPE_DECORATE_EXTERN: break; > case A1_OP_TYPE_DECORATE: break; > case A1_OP_TYPE: > case A1_OP_TYPE_EXTERN: { >@@ -1583,10 +1590,9 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const > } > if (ret == 0) { > /* Copy the encoding where it belongs */ >- len -= l; p -= l; > psave -= (datalen + l - oldtaglen); > lensave -= (datalen + l - oldtaglen); >- memcpy(psave + 1, p + 1, datalen + l - oldtaglen); >+ memcpy(psave + 1, p + 1 - l, datalen + l - oldtaglen); > p = psave; > len = lensave; > } >@@ -1828,7 +1834,7 @@ _asn1_length_open_type_id(const struct asn1_template *t, > const void *data) > { > struct asn1_template pretend[2] = { >- { 0, 0, ((void*)1) }, >+ { 0, 0, ((void*)(uintptr_t)1) }, > }; > pretend[1] = *t; > while ((t->tt & A1_OP_MASK) == A1_OP_TAG) >@@ -1895,8 +1901,6 @@ _asn1_length_open_type(const struct asn1_template *tbase, > break; > default: return 0; > } >- if (!typeid_is_int && !typeid_is_oid) >- return 0; > if (!(t->tt & A1_OS_OT_IS_ARRAY)) { > struct heim_base_data *os = DPO(data, topentype->offset); > >@@ -1994,6 +1998,7 @@ _asn1_length(const struct asn1_template *t, const void *data) > } > case A1_OP_NAME: break; > case A1_OP_DEFVAL: break; >+ case A1_OP_TYPE_DECORATE_EXTERN: break; > case A1_OP_TYPE_DECORATE: break; > case A1_OP_TYPE: > case A1_OP_TYPE_EXTERN: { >@@ -2256,6 +2261,7 @@ _asn1_free(const struct asn1_template *t, void *data) > } > case A1_OP_NAME: break; > case A1_OP_DEFVAL: break; >+ case A1_OP_TYPE_DECORATE_EXTERN: > case A1_OP_TYPE_DECORATE: > case A1_OP_TYPE: > case A1_OP_TYPE_EXTERN: { >@@ -2270,9 +2276,17 @@ _asn1_free(const struct asn1_template *t, void *data) > > if ((t->tt & A1_OP_MASK) == A1_OP_TYPE || (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) { > _asn1_free(t->ptr, el); >- } else { >+ } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) { > const struct asn1_type_func *f = t->ptr; > (f->release)(el); >+ } else { >+ /* A1_OP_TYPE_DECORATE_EXTERN */ >+ const struct asn1_type_func *f = t->ptr; >+ >+ if (f && f->release) >+ (f->release)(el); >+ else if (f) >+ memset(el, 0, f->size); > } > if (t->tt & A1_FLAG_OPTIONAL) { > free(el); >@@ -2432,9 +2446,9 @@ _asn1_print_open_type(const struct asn1_template *t, /* object set template */ > if (s) > r = rk_strpoolprintf(r, ",%s\"_%s\":%s", > indents ? indents : "", opentype_name, s); >- free(indents); > free(s); > } >+ free(indents); > return r; > } > >@@ -2450,8 +2464,7 @@ _asn1_print_open_type(const struct asn1_template *t, /* object set template */ > opentype_name); > free(indents); > indents = getindent(flags, indent + 1); >- if (indents) >- r = rk_strpoolprintf(r, "%s", indents ? indents : ""); >+ r = rk_strpoolprintf(r, "%s", indents ? indents : ""); > for (i = 0; r && i < len; i++) { > struct rk_strpool *r2 = NULL; > char *s = NULL;; >@@ -2545,6 +2558,7 @@ _asn1_print(const struct asn1_template *t, > break; > case A1_OP_NAME: break; > case A1_OP_DEFVAL: break; >+ case A1_OP_TYPE_DECORATE_EXTERN: break; > case A1_OP_TYPE_DECORATE: break; /* We could probably print this though */ > case A1_OP_TYPE: > case A1_OP_TYPE_EXTERN: { >@@ -2816,7 +2830,7 @@ _asn1_copy_open_type(const struct asn1_template *t, /* object set template */ > *dtop = NULL; > if ((valto = calloc(len, sizeof(valto[0]))) == NULL) > ret = ENOMEM; >- for (i = 0, len = *lenfromp; ret == 0 && i < len; (*lentop)++, i++) { >+ for (i = 0, len = *lenfromp; ret == 0 && i < len; i++) { > if (valfrom[i] == NULL) { > valto[i] = NULL; > continue; >@@ -2825,17 +2839,19 @@ _asn1_copy_open_type(const struct asn1_template *t, /* object set template */ > ret = ENOMEM; > else > ret = _asn1_copy(tactual_type->ptr, valfrom[i], valto[i]); >+ (*lentop)++; > } > >- for (i = 0; ret && i < len; i++) { >+ for (i = 0; ret && i < (*lentop); i++) { > if (valto[i]) { > _asn1_free(tactual_type->ptr, valto[i]); > free(valto[i]); > } > } >- if (ret) >+ if (ret) { > free(valto); >- else >+ *lentop = 0; >+ } else > *dtop = valto; > return ret; > } >@@ -2863,6 +2879,7 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to) > } > case A1_OP_NAME: break; > case A1_OP_DEFVAL: break; >+ case A1_OP_TYPE_DECORATE_EXTERN: > case A1_OP_TYPE_DECORATE: > case A1_OP_TYPE: > case A1_OP_TYPE_EXTERN: { >@@ -2871,7 +2888,8 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to) > void **ptel = (void **)tel; > size_t size; > >- if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { >+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE || >+ (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) { > size = _asn1_sizeofType(t->ptr); > } else { > const struct asn1_type_func *f = t->ptr; >@@ -2892,9 +2910,17 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to) > if ((t->tt & A1_OP_MASK) == A1_OP_TYPE || > (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) { > ret = _asn1_copy(t->ptr, fel, tel); >+ } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) { >+ const struct asn1_type_func *f = t->ptr; >+ ret = (f->copy)(fel, tel); > } else { > const struct asn1_type_func *f = t->ptr; >- ret = (f->copy)(fel, tel); >+ >+ /* A1_OP_TYPE_DECORATE_EXTERN */ >+ if (f && f->copy) >+ ret = (f->copy)(fel, tel); >+ else if (f) >+ memset(tel, 0, f->size); > } > > if (ret) { >diff --git a/third_party/heimdal/lib/asn1/test.asn1 b/third_party/heimdal/lib/asn1/test.asn1 >index a76152712d9e..08c7dcd93ee1 100644 >--- a/third_party/heimdal/lib/asn1/test.asn1 >+++ b/third_party/heimdal/lib/asn1/test.asn1 >@@ -288,7 +288,7 @@ TESTExtensible ::= SEQUENCE { > > TESTDecorated ::= SEQUENCE { > version TESTuint32 >- -- gets decorated >+ -- gets decorated with varius fields (see test.opt) > } > > TESTNotDecorated ::= SEQUENCE { >@@ -296,4 +296,14 @@ TESTNotDecorated ::= SEQUENCE { > -- should have the same encoding as TESTDecorated > } > >+TESTDecoratedChoice ::= CHOICE { >+ version TESTuint32 >+ -- gets decorated with varius fields (see test.opt) >+} >+ >+TESTNotDecoratedChoice ::= CHOICE { >+ version TESTuint32 >+ -- should have the same encoding as TESTDecoratedChoice >+} >+ > END >diff --git a/third_party/heimdal/lib/asn1/test.opt b/third_party/heimdal/lib/asn1/test.opt >index 500ee4ec8111..755eba01bfb9 100644 >--- a/third_party/heimdal/lib/asn1/test.opt >+++ b/third_party/heimdal/lib/asn1/test.opt >@@ -1 +1,7 @@ > --sequence=TESTSeqOf >+--decorate=TESTDecorated:TESTuint32:version2? >+--decorate=TESTDecorated:my_vers:version3:my_copy_vers:my_free_vers:"check-gen.h" >+--decorate=TESTDecorated:void *:privthing >+--decorate=TESTDecoratedChoice:TESTuint32:version2? >+--decorate=TESTDecoratedChoice:my_vers:version3:my_copy_vers:my_free_vers:"check-gen.h" >+--decorate=TESTDecoratedChoice:void *:privthing >diff --git a/third_party/heimdal/lib/base/array.c b/third_party/heimdal/lib/base/array.c >index b34f9de48800..994fa7d38e4c 100644 >--- a/third_party/heimdal/lib/base/array.c >+++ b/third_party/heimdal/lib/base/array.c >@@ -46,7 +46,7 @@ struct heim_array_data { > heim_object_t *allocated; > }; > >-static void >+static void HEIM_CALLCONV > array_dealloc(heim_object_t ptr) > { > heim_array_t array = ptr; >@@ -58,7 +58,7 @@ array_dealloc(heim_object_t ptr) > > struct heim_type_data array_object = { > HEIM_TID_ARRAY, >- "dict-object", >+ "array-object", > NULL, > array_dealloc, > NULL, >diff --git a/third_party/heimdal/lib/base/bsearch.c b/third_party/heimdal/lib/base/bsearch.c >index 278962172683..268cc018df6f 100644 >--- a/third_party/heimdal/lib/base/bsearch.c >+++ b/third_party/heimdal/lib/base/bsearch.c >@@ -275,11 +275,12 @@ bsearch_common(const char *buf, size_t sz, const char *key, > ret = 0; > if (val_len && value) { > /* Avoid strndup() so we don't need libroken here yet */ >- *value = malloc(val_len + 1); >- if (!*value) >- ret = errno; >- (void) memcpy(*value, &buf[val_start], val_len); >- (*value)[val_len] = '\0'; >+ if ((*value = malloc(val_len + 1))) { >+ (void) memcpy(*value, &buf[val_start], val_len); >+ (*value)[val_len] = '\0'; >+ } else { >+ ret = errno; >+ } > } > break; > } >@@ -708,6 +709,10 @@ _bsearch_file(bsearch_file_handle bfh, const char *key, > > if (reads) > *reads = 0; >+ if (value) >+ *value = NULL; >+ if (loops) >+ *loops = 0; > > /* If whole file is in memory then search that and we're done */ > if (bfh->file_sz == bfh->cache_sz) >@@ -715,11 +720,6 @@ _bsearch_file(bsearch_file_handle bfh, const char *key, > > /* Else block-wise binary search */ > >- if (value) >- *value = NULL; >- if (loops) >- *loops = 0; >- > l = 0; > r = (bfh->file_sz / bfh->page_sz) + 1; > for (level = 0, page = r >> 1; page >= l && page < r ; level++) { >@@ -851,7 +851,7 @@ stdb_copy_value(void *db, heim_string_t table, heim_data_t key, > { > bsearch_file_handle bfh = db; > const char *k; >- char *v; >+ char *v = NULL; > heim_data_t value; > int ret; > >@@ -869,6 +869,8 @@ stdb_copy_value(void *db, heim_string_t table, heim_data_t key, > else > k = (const char *)heim_data_get_ptr(key); > ret = _bsearch_file(bfh, k, &v, NULL, NULL, NULL); >+ if (ret == 0 && v == NULL) >+ ret = -1; /* Quiet lint */ > if (ret != 0) { > if (ret > 0 && error) > *error = heim_error_create(ret, "%s", strerror(ret)); >diff --git a/third_party/heimdal/lib/base/data.c b/third_party/heimdal/lib/base/data.c >index 4aa6efc66774..cefdde0c1bbe 100644 >--- a/third_party/heimdal/lib/base/data.c >+++ b/third_party/heimdal/lib/base/data.c >@@ -34,7 +34,7 @@ > #include "baselocl.h" > #include <string.h> > >-static void >+static void HEIM_CALLCONV > data_dealloc(void *ptr) > { > heim_data_t d = ptr; >@@ -61,7 +61,7 @@ data_cmp(void *a, void *b) > return memcmp(osa->data, osb->data, osa->length); > } > >-static unsigned long >+static uintptr_t > data_hash(void *ptr) > { > heim_octet_string *os = ptr; >@@ -69,8 +69,9 @@ data_hash(void *ptr) > > if (os->length < 4) > return os->length; >- return s[0] | (s[1] << 8) | >- (s[os->length - 2] << 16) | (s[os->length - 1] << 24); >+ >+ return ((unsigned long)s[os->length - 1] << 24) >+ | (s[os->length - 2] << 16) | (s[1] << 8) | s[0]; > } > > struct heim_type_data _heim_data_object = { >diff --git a/third_party/heimdal/lib/base/db.c b/third_party/heimdal/lib/base/db.c >index cd750386accf..b206ff6d766b 100644 >--- a/third_party/heimdal/lib/base/db.c >+++ b/third_party/heimdal/lib/base/db.c >@@ -84,7 +84,7 @@ static int open_file(const char *, int , int, int *, heim_error_t *); > static int read_json(const char *, heim_object_t *, heim_error_t *); > static struct heim_db_type json_dbt; > >-static void db_dealloc(void *ptr); >+static void HEIM_CALLCONV db_dealloc(void *ptr); > > struct heim_type_data db_object = { > HEIM_TID_DB, >@@ -150,7 +150,7 @@ db_init_plugins_once(void *arg) > db_plugins = heim_retain(arg); > } > >-static void >+static void HEIM_CALLCONV > plugin_dealloc(void *arg) > { > db_plugin plug = arg; >@@ -242,7 +242,7 @@ heim_db_register(const char *dbtype, > return ret; > } > >-static void >+static void HEIM_CALLCONV > db_dealloc(void *arg) > { > heim_db_t db = arg; >@@ -577,7 +577,7 @@ heim_db_commit(heim_db_t db, heim_error_t *error) > goto done; > } > >- if (db->options == NULL) >+ if (db->options) > journal_fname = heim_dict_get_value(db->options, HSTR("journal-filename")); > > if (journal_fname != NULL) { >@@ -1144,21 +1144,15 @@ enomem: > static > heim_data_t from_base64(heim_string_t s, heim_error_t *error) > { >+ ssize_t len = -1; > void *buf; >- size_t len; > heim_data_t d; > > buf = malloc(strlen(heim_string_get_utf8(s))); >- if (buf == NULL) >- goto enomem; >- >- len = rk_base64_decode(heim_string_get_utf8(s), buf); >- d = heim_data_ref_create(buf, len, free); >- if (d == NULL) >- goto enomem; >- return d; >- >-enomem: >+ if (buf) >+ len = rk_base64_decode(heim_string_get_utf8(s), buf); >+ if (len > -1 && (d = heim_data_ref_create(buf, len, free))) >+ return d; > free(buf); > if (error) > *error = heim_error_create_enomem(); >diff --git a/third_party/heimdal/lib/base/dict.c b/third_party/heimdal/lib/base/dict.c >index 8d73846b2bbb..86be109ffc5e 100644 >--- a/third_party/heimdal/lib/base/dict.c >+++ b/third_party/heimdal/lib/base/dict.c >@@ -47,7 +47,7 @@ struct heim_dict_data { > struct hashentry **tab; > }; > >-static void >+static void HEIM_CALLCONV > dict_dealloc(void *ptr) > { > heim_dict_t dict = ptr; >@@ -115,6 +115,8 @@ heim_dict_create(size_t size) > heim_dict_t dict; > > dict = _heim_alloc_object(&dict_object, sizeof(*dict)); >+ if (dict == NULL) >+ return NULL; > > dict->size = findprime(size); > if (dict->size == 0) { >@@ -149,7 +151,7 @@ heim_dict_get_type_id(void) > static struct hashentry * > _search(heim_dict_t dict, heim_object_t ptr) > { >- unsigned long v = heim_get_hash(ptr); >+ uintptr_t v = heim_get_hash(ptr); > struct hashentry *p; > > for (p = dict->tab[v % dict->size]; p != NULL; p = p->next) >@@ -219,7 +221,7 @@ heim_dict_set_value(heim_dict_t dict, heim_object_t key, heim_object_t value) > heim_release(h->value); > h->value = heim_retain(value); > } else { >- unsigned long v; >+ uintptr_t v; > > h = malloc(sizeof(*h)); > if (h == NULL) >diff --git a/third_party/heimdal/lib/base/dll.c b/third_party/heimdal/lib/base/dll.c >index 31017a01191b..59c39137b727 100644 >--- a/third_party/heimdal/lib/base/dll.c >+++ b/third_party/heimdal/lib/base/dll.c >@@ -83,7 +83,8 @@ struct tls_values { > > static HEIMDAL_THREAD_LOCAL struct tls_values values; > >-#define DEAD_KEY ((void *)8) >+static char dead_key; >+#define DEAD_KEY ((void *)&dead_key) > > void > heim_w32_service_thread_detach(void *unused) >diff --git a/third_party/heimdal/lib/base/error.c b/third_party/heimdal/lib/base/error.c >index 8ae65de4981e..6ba3bea412db 100644 >--- a/third_party/heimdal/lib/base/error.c >+++ b/third_party/heimdal/lib/base/error.c >@@ -41,7 +41,7 @@ struct heim_error { > struct heim_error *next; > }; > >-static void >+static void HEIM_CALLCONV > error_dealloc(void *ptr) > { > struct heim_error *p = ptr; >@@ -58,7 +58,7 @@ error_cmp(void *a, void *b) > return heim_cmp(ap->msg, bp->msg); > } > >-static unsigned long >+static uintptr_t > error_hash(void *ptr) > { > struct heim_error *p = ptr; >diff --git a/third_party/heimdal/lib/base/error_string.c b/third_party/heimdal/lib/base/error_string.c >index 5c787ba2ce51..a562833a91a0 100644 >--- a/third_party/heimdal/lib/base/error_string.c >+++ b/third_party/heimdal/lib/base/error_string.c >@@ -39,6 +39,8 @@ > void > heim_clear_error_message(heim_context context) > { >+ if (!context) >+ return; > if (context->error_string) > free(context->error_string); > context->error_code = 0; >@@ -53,7 +55,8 @@ heim_set_error_message(heim_context context, heim_error_code ret, > va_list ap; > > va_start(ap, fmt); >- heim_vset_error_message(context, ret, fmt, ap); >+ if (context) >+ heim_vset_error_message(context, ret, fmt, ap); > va_end(ap); > } > >@@ -164,7 +167,7 @@ heim_get_error_string(heim_context context) > int > heim_have_error_string(heim_context context) > { >- return context->error_string != NULL; >+ return context && context->error_string != NULL; > } > > void >diff --git a/third_party/heimdal/lib/base/expand_path.c b/third_party/heimdal/lib/base/expand_path.c >index df382b99887d..cf249917e8fe 100644 >--- a/third_party/heimdal/lib/base/expand_path.c >+++ b/third_party/heimdal/lib/base/expand_path.c >@@ -59,10 +59,9 @@ expand_temp_folder(heim_context context, PTYPE param, const char *postfix, > size_t len; > > if (!GetTempPath(sizeof(tpath)/sizeof(tpath[0]), tpath)) { >- if (context) >- heim_set_error_message(context, EINVAL, >- "Failed to get temporary path (GLE=%d)", >- GetLastError()); >+ heim_set_error_message(context, EINVAL, >+ "Failed to get temporary path (GLE=%d)", >+ GetLastError()); > return EINVAL; > } > >@@ -170,55 +169,52 @@ expand_userid(heim_context context, PTYPE param, const char *postfix, > } > > if (le != 0) { >- if (context) >- heim_set_error_message(context, rv, >- "Can't open thread token (GLE=%d)", le); >+ heim_set_error_message(context, rv, >+ "Can't open thread token (GLE=%d)", le); > goto _exit; > } > } > > if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &len)) { > if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { >- if (context) >- heim_set_error_message(context, rv, >- "Unexpected error reading token information (GLE=%d)", >- GetLastError()); >+ heim_set_error_message(context, rv, >+ "Unexpected error reading token information (GLE=%d)", >+ GetLastError()); > goto _exit; > } > > if (len == 0) { >- if (context) >- heim_set_error_message(context, rv, >- "GetTokenInformation() returned truncated buffer"); >+ heim_set_error_message(context, rv, >+ "GetTokenInformation() returned truncated buffer"); > goto _exit; > } > > pOwner = malloc(len); > if (pOwner == NULL) { >- if (context) >- heim_set_error_message(context, rv, "Out of memory"); >+ heim_set_error_message(context, rv, "Out of memory"); > goto _exit; > } > } else { >- if (context) >- heim_set_error_message(context, rv, "GetTokenInformation() returned truncated buffer"); >+ heim_set_error_message(context, rv, "GetTokenInformation() returned truncated buffer"); > goto _exit; > } > > if (!GetTokenInformation(hToken, TokenOwner, pOwner, len, &len)) { >- if (context) >- heim_set_error_message(context, rv, "GetTokenInformation() failed. GLE=%d", GetLastError()); >+ heim_set_error_message(context, rv, >+ "GetTokenInformation() failed. GLE=%d", >+ GetLastError()); > goto _exit; > } > > if (!ConvertSidToStringSid(pOwner->Owner, &strSid)) { >- if (context) >- heim_set_error_message(context, rv, "Can't convert SID to string. GLE=%d", GetLastError()); >+ heim_set_error_message(context, rv, >+ "Can't convert SID to string. GLE=%d", >+ GetLastError()); > goto _exit; > } > > *ret = strdup(strSid); >- if (*ret == NULL && context) >+ if (*ret == NULL) > heim_set_error_message(context, rv, "Out of memory"); > > rv = 0; >@@ -248,8 +244,7 @@ expand_csidl(heim_context context, PTYPE folder, const char *postfix, > size_t len; > > if (SHGetFolderPath(NULL, folder, NULL, SHGFP_TYPE_CURRENT, path) != S_OK) { >- if (context) >- heim_set_error_message(context, EINVAL, "Unable to determine folder path"); >+ heim_set_error_message(context, EINVAL, "Unable to determine folder path"); > return EINVAL; > } > >@@ -387,7 +382,7 @@ expand_strftime(heim_context context, PTYPE param, const char *postfix, > t = time(NULL); > len = strftime(buf, sizeof(buf), arg, localtime(&t)); > if (len == 0 || len >= sizeof(buf)) >- return ENOMEM; >+ return heim_enomem(context); > *ret = strdup(buf); > return 0; > } >@@ -488,8 +483,7 @@ expand_token(heim_context context, > > if (token[0] != '%' || token[1] != '{' || token_end[0] != '}' || > token_end - token <= 2) { >- if (context) >- heim_set_error_message(context, EINVAL,"Invalid token."); >+ heim_set_error_message(context, EINVAL,"Invalid token."); > return EINVAL; > } > >@@ -521,8 +515,7 @@ expand_token(heim_context context, > return errcode; > } > >- if (context) >- heim_set_error_message(context, EINVAL, "Invalid token."); >+ heim_set_error_message(context, EINVAL, "Invalid token."); > return EINVAL; > } > >@@ -630,7 +623,6 @@ heim_expand_path_tokensv(heim_context context, > break; > extra_tokens[i] = strdup(s); > if (extra_tokens[i++] == NULL) { >- va_end(ap); > free_extra_tokens(extra_tokens); > return heim_enomem(context); > } >@@ -639,7 +631,6 @@ heim_expand_path_tokensv(heim_context context, > s = ""; > extra_tokens[i] = strdup(s); > if (extra_tokens[i] == NULL) { >- va_end(ap); > free_extra_tokens(extra_tokens); > return heim_enomem(context); > } >@@ -667,8 +658,7 @@ heim_expand_path_tokensv(heim_context context, > if (*ppath_out) > free(*ppath_out); > *ppath_out = NULL; >- if (context) >- heim_set_error_message(context, EINVAL, "variable missing }"); >+ heim_set_error_message(context, EINVAL, "variable missing }"); > return EINVAL; > } > >diff --git a/third_party/heimdal/lib/base/heimbase-svc.h b/third_party/heimdal/lib/base/heimbase-svc.h >index 1f0abd622e50..083917fb806a 100644 >--- a/third_party/heimdal/lib/base/heimbase-svc.h >+++ b/third_party/heimdal/lib/base/heimbase-svc.h >@@ -36,6 +36,8 @@ > #ifndef HEIMBASE_SVC_H > #define HEIMBASE_SVC_H 1 > >+#include <heimbase.h> >+ > /* > * This file is meant to be included in services, which can > * >@@ -68,7 +70,9 @@ > const char *e_text; \ > char *e_text_buf; \ > heim_string_t reason; \ >- heim_array_t kv; \ >- int32_t ret >+ /* auditing key/value store */ \ >+ heim_dict_t kv; \ >+ heim_dict_t attributes; \ >+ int32_t error_code > > #endif /* HEIMBASE_SVC_H */ >diff --git a/third_party/heimdal/lib/base/heimbase.c b/third_party/heimdal/lib/base/heimbase.c >index 8aacdb9187d2..1e6805a25e7f 100644 >--- a/third_party/heimdal/lib/base/heimbase.c >+++ b/third_party/heimdal/lib/base/heimbase.c >@@ -53,7 +53,7 @@ struct heim_base_mem { > HEIM_TAILQ_ENTRY(heim_base) autorel; > heim_auto_release_t autorelpool; > const char *name; >- void (*dealloc)(void *); >+ void (HEIM_CALLCONV *dealloc)(void *); > uintptr_t isaextra[1]; > }; > >@@ -83,10 +83,10 @@ struct heim_auto_release { > * @return the same object as passed in > */ > >-void * >-heim_retain(void *ptr) >+heim_object_t >+heim_retain(heim_object_t ptr) > { >- struct heim_base *p = NULL; >+ struct heim_base *p; > > if (ptr == NULL || heim_base_is_tagged(ptr)) > return ptr; >@@ -111,7 +111,7 @@ void > heim_release(void *ptr) > { > heim_base_atomic_integer_type old; >- struct heim_base *p = NULL; >+ struct heim_base *p; > > if (ptr == NULL || heim_base_is_tagged(ptr)) > return; >@@ -214,13 +214,13 @@ heim_get_tid(heim_object_t ptr) > * @return a hash value > */ > >-unsigned long >+uintptr_t > heim_get_hash(heim_object_t ptr) > { > heim_type_t isa = _heim_get_isa(ptr); > if (isa->hash) > return isa->hash(ptr); >- return (unsigned long)ptr; >+ return (uintptr_t)ptr; > } > > /** >@@ -257,7 +257,7 @@ heim_cmp(heim_object_t a, heim_object_t b) > * Private - allocates an memory object > */ > >-static void >+static void HEIM_CALLCONV > memory_dealloc(void *ptr) > { > struct heim_base_mem *p = (struct heim_base_mem *)PTR2BASE(ptr); >@@ -346,7 +346,7 @@ _heim_alloc_object(heim_type_t type, size_t size) > void * > _heim_get_isaextra(heim_object_t ptr, size_t idx) > { >- struct heim_base *p = NULL; >+ struct heim_base *p; > > heim_assert(ptr != NULL, "internal error"); > p = (struct heim_base *)PTR2BASE(ptr); >@@ -585,7 +585,7 @@ autorel_tls(void) > > } > >-static void >+static void HEIM_CALLCONV > autorel_dealloc(void *ptr) > { > heim_auto_release_t ar = ptr; >@@ -614,10 +614,10 @@ autorel_cmp(void *a, void *b) > return (a == b); > } > >-static unsigned long >+static uintptr_t > autorel_hash(void *ptr) > { >- return (unsigned long)ptr; >+ return (uintptr_t)ptr; > } > > >@@ -671,7 +671,7 @@ heim_auto_release_create(void) > heim_object_t > heim_auto_release(heim_object_t ptr) > { >- struct heim_base *p = NULL; >+ struct heim_base *p; > struct ar_tls *tls = autorel_tls(); > heim_auto_release_t ar; > >@@ -763,9 +763,10 @@ heim_path_vget2(heim_object_t ptr, heim_object_t *parent, heim_object_t *key, > next_node = heim_dict_get_value(node, path_element); > } else if (node_type == HEIM_TID_DB) { > next_node = _heim_db_get_value(node, NULL, path_element, NULL); >- } else if (node_type == HEIM_TID_ARRAY) { >+ } else { > int idx = -1; > >+ /* node_type == HEIM_TID_ARRAY */ > if (heim_get_tid(path_element) == HEIM_TID_NUMBER) > idx = heim_number_get_int(path_element); > if (idx < 0) { >@@ -777,12 +778,6 @@ heim_path_vget2(heim_object_t ptr, heim_object_t *parent, heim_object_t *key, > return NULL; > } > next_node = heim_array_get_value(node, idx); >- } else { >- if (error) >- *error = heim_error_create(EINVAL, >- "heim_path_get() node in path " >- "not a container type"); >- return NULL; > } > node = next_node; > } >diff --git a/third_party/heimdal/lib/base/heimbase.h b/third_party/heimdal/lib/base/heimbase.h >index c0c94e2649b2..3706fc8710d2 100644 >--- a/third_party/heimdal/lib/base/heimbase.h >+++ b/third_party/heimdal/lib/base/heimbase.h >@@ -168,12 +168,12 @@ typedef long heim_base_once_t; /* XXX arch dependant */ > #endif > > >-void * heim_retain(heim_object_t); >+heim_object_t heim_retain(heim_object_t); > void heim_release(heim_object_t); > > void heim_show(heim_object_t); > >-typedef void (*heim_type_dealloc)(void *); >+typedef void (HEIM_CALLCONV *heim_type_dealloc)(void *); > > void * > heim_alloc(size_t size, const char *name, heim_type_dealloc dealloc); >@@ -184,7 +184,7 @@ heim_get_tid(heim_object_t object); > int > heim_cmp(heim_object_t a, heim_object_t b); > >-unsigned long >+uintptr_t > heim_get_hash(heim_object_t ptr); > > void >@@ -436,9 +436,10 @@ void heim_db_iterate(heim_db_t, heim_string_t, > > typedef struct heim_number_data *heim_number_t; > >-heim_number_t heim_number_create(int); >+heim_number_t heim_number_create(int64_t); > heim_tid_t heim_number_get_type_id(void); > int heim_number_get_int(heim_number_t); >+int64_t heim_number_get_long(heim_number_t); > > /* > * >diff --git a/third_party/heimdal/lib/base/heimbasepriv.h b/third_party/heimdal/lib/base/heimbasepriv.h >index 8f8fad0fc8c3..b9f63e56b6a1 100644 >--- a/third_party/heimdal/lib/base/heimbasepriv.h >+++ b/third_party/heimdal/lib/base/heimbasepriv.h >@@ -42,7 +42,7 @@ > typedef void (*heim_type_init)(void *); > typedef heim_object_t (*heim_type_copy)(void *); > typedef int (*heim_type_cmp)(void *, void *); >-typedef unsigned long (*heim_type_hash)(void *); >+typedef uintptr_t (*heim_type_hash)(void *); > typedef heim_string_t (*heim_type_description)(void *); > > typedef struct heim_type_data *heim_type_t; >@@ -65,6 +65,7 @@ enum { > HEIM_TID_DATA = 134, > HEIM_TID_DB = 135, > HEIM_TID_PA_AUTH_MECH = 136, >+ HEIM_TID_PAC = 137, > HEIM_TID_USER = 255 > > }; >diff --git a/third_party/heimdal/lib/base/log.c b/third_party/heimdal/lib/base/log.c >index 904d0c3ba124..818ac8398d53 100644 >--- a/third_party/heimdal/lib/base/log.c >+++ b/third_party/heimdal/lib/base/log.c >@@ -40,6 +40,7 @@ > #include <assert.h> > #include <stdarg.h> > #include <vis.h> >+#include <base64.h> > > struct heim_log_facility_internal { > int min; >@@ -204,10 +205,13 @@ open_syslog(heim_context context, > heim_log_facility *facility, int min, int max, > const char *sev, const char *fac) > { >- struct _heimdal_syslog_data *sd = malloc(sizeof(*sd)); >+ struct _heimdal_syslog_data *sd; >+ heim_error_code ret; > int i; > >- if (sd == NULL) >+ if (facility == NULL) >+ return EINVAL; >+ if ((sd = calloc(1, sizeof(*sd))) == NULL) > return heim_enomem(context); > i = find_value(sev, syslogvals); > if (i == -1) >@@ -218,8 +222,11 @@ open_syslog(heim_context context, > i = LOG_AUTH; > sd->priority |= i; > roken_openlog(facility->program, LOG_PID | LOG_NDELAY, i); >- return heim_addlog_func(context, facility, min, max, >- log_syslog, close_syslog, sd); >+ ret = heim_addlog_func(context, facility, min, max, log_syslog, >+ close_syslog, sd); >+ if (ret) >+ free(sd); >+ return ret; > } > > struct file_data { >@@ -247,7 +254,7 @@ log_file(heim_context context, const char *timestr, const char *msg, void *data) > size_t i = 0; > size_t j; > >- if (logf == NULL || (f->disp & FILEDISP_REOPEN)) { >+ if (f->filename && (logf == NULL || (f->disp & FILEDISP_REOPEN))) { > int flags = O_WRONLY|O_APPEND; > int fd; > >@@ -338,9 +345,9 @@ open_file(heim_context context, heim_log_facility *fac, int min, int max, > if (ret) { > free(fd->filename); > free(fd); >- } >- if (disp & FILEDISP_KEEPOPEN) >+ } else if (disp & FILEDISP_KEEPOPEN) { > log_file(context, NULL, NULL, fd); >+ } > return ret; > } > >@@ -384,7 +391,7 @@ heim_addlog_dest(heim_context context, heim_log_facility *f, const char *orig) > p++; > } > if (strcmp(p, "STDERR") == 0) { >- ret = open_file(context, f, min, max, NULL, NULL, stderr, >+ ret = open_file(context, f, min, max, NULL, "a", stderr, > FILEDISP_KEEPOPEN, 0); > } else if (strcmp(p, "CONSOLE") == 0) { > /* XXX WIN32 */ >@@ -608,10 +615,7 @@ __attribute__ ((__format__ (__printf__, 3, 0))) > heim_error_code > heim_have_debug(heim_context context, int level) > { >- heim_log_facility *fac; >- >- return (context != NULL && >- (fac = heim_get_debug_dest(context)) != NULL); >+ return (context != NULL && heim_get_debug_dest(context) != NULL); > } > > heim_error_code >@@ -655,32 +659,34 @@ heim_add_debug_dest(heim_context context, const char *program, > return 0; > } > >-static heim_string_t >+struct heim_audit_kv_tuple { >+ heim_string_t key; >+ heim_object_t value; >+}; >+ >+static struct heim_audit_kv_tuple zero_tuple; >+ >+static struct heim_audit_kv_tuple > fmtkv(int flags, const char *k, const char *fmt, va_list ap) > __attribute__ ((__format__ (__printf__, 3, 0))) > { >- heim_string_t str; > size_t i; > ssize_t j; >- char *buf1; >- char *buf2; >- char *buf3; >- int ret = vasprintf(&buf1, fmt, ap); >- if (ret < 0 || !buf1) >- return NULL;; >- >- j = asprintf(&buf2, "%s=%s", k, buf1); >- free(buf1); >- if (j < 0 || !buf2) >- return NULL;; >+ struct heim_audit_kv_tuple kv; >+ char *value; >+ char *value_vis; >+ >+ j = vasprintf(&value, fmt, ap); >+ if (j < 0 || value == NULL) >+ return zero_tuple; > > /* We optionally eat the whitespace. */ > > if (flags & HEIM_SVC_AUDIT_EATWHITE) { >- for (i=0, j=0; buf2[i]; i++) >- if (buf2[i] != ' ' && buf2[i] != '\t') >- buf2[j++] = buf2[i]; >- buf2[j] = '\0'; >+ for (i=0, j=0; value[i]; i++) >+ if (value[i] != ' ' && value[i] != '\t') >+ value[j++] = value[i]; >+ value[j] = '\0'; > } > > if (flags & (HEIM_SVC_AUDIT_VIS | HEIM_SVC_AUDIT_VISLAST)) { >@@ -688,48 +694,52 @@ fmtkv(int flags, const char *k, const char *fmt, va_list ap) > > if (flags & HEIM_SVC_AUDIT_VIS) > vis_flags |= VIS_WHITE; >- buf3 = malloc((j + 1) * 4 + 1); >- if (buf3) >- strvisx(buf3, buf2, j, vis_flags); >- free(buf2); >- if (buf3 == NULL) >- return NULL; >+ value_vis = malloc((j + 1) * 4 + 1); >+ if (value_vis) >+ strvisx(value_vis, value, j, vis_flags); >+ free(value); >+ if (value_vis == NULL) >+ return zero_tuple; > } else >- buf3 = buf2; >+ value_vis = value; > >- str = heim_string_create(buf3); >- free(buf3); >- return str; >+ if (k) >+ kv.key = heim_string_create(k); >+ else >+ kv.key = NULL; >+ kv.value = heim_string_ref_create(value_vis, free); >+ >+ return kv; > } > > void > heim_audit_vaddreason(heim_svc_req_desc r, const char *fmt, va_list ap) > __attribute__ ((__format__ (__printf__, 2, 0))) > { >- heim_string_t str; >+ struct heim_audit_kv_tuple kv; > >- str = fmtkv(HEIM_SVC_AUDIT_VISLAST, "reason", fmt, ap); >- if (!str) { >+ kv = fmtkv(HEIM_SVC_AUDIT_VISLAST, NULL, fmt, ap); >+ if (kv.value == NULL) { > heim_log(r->hcontext, r->logf, 1, "heim_audit_vaddreason: " > "failed to add reason (out of memory)"); > return; > } > > heim_log(r->hcontext, r->logf, 7, "heim_audit_vaddreason(): " >- "adding reason %s", heim_string_get_utf8(str)); >+ "adding reason %s", heim_string_get_utf8(kv.value)); > if (r->reason) { > heim_string_t str2; > > str2 = heim_string_create_with_format("%s: %s", >- heim_string_get_utf8(str), >+ heim_string_get_utf8(kv.value), > heim_string_get_utf8(r->reason)); > if (str2) { >- heim_release(str); >- str = str2; >+ heim_release(kv.value); >+ kv.value = str2; > } > } > heim_release(r->reason); >- r->reason = str; >+ r->reason = kv.value; > } > > void >@@ -743,10 +753,37 @@ heim_audit_addreason(heim_svc_req_desc r, const char *fmt, ...) > va_end(ap); > } > >+size_t >+addkv(heim_svc_req_desc r, heim_object_t key, heim_object_t value) >+{ >+ size_t index; >+ heim_object_t obj; >+ >+ obj = heim_dict_get_value(r->kv, key); >+ if (obj) { >+ if (heim_get_tid(obj) == HEIM_TID_ARRAY) { >+ index = heim_array_get_length(obj); >+ heim_array_append_value(obj, value); >+ } else { >+ heim_array_t array = heim_array_create(); >+ >+ index = 1; >+ heim_array_append_value(array, obj); >+ heim_array_append_value(array, value); >+ heim_dict_set_value(r->kv, key, array); >+ heim_release(array); /* retained by r->kv */ >+ } >+ } else { >+ index = 0; >+ heim_dict_set_value(r->kv, key, value); >+ } >+ >+ return index; >+} >+ > /* >- * append_token adds a token which is optionally a kv-pair and it >- * also optionally eats the whitespace. If k == NULL, then it's >- * not a kv-pair. >+ * add a key-value token. if the key already exists, the value is >+ * promoted to an array of values. > */ > > void >@@ -754,19 +791,26 @@ heim_audit_vaddkv(heim_svc_req_desc r, int flags, const char *k, > const char *fmt, va_list ap) > __attribute__ ((__format__ (__printf__, 4, 0))) > { >- heim_string_t str; >+ struct heim_audit_kv_tuple kv; >+ size_t index; > >- str = fmtkv(flags, k, fmt, ap); >- if (!str) { >+ kv = fmtkv(flags, k, fmt, ap); >+ if (kv.key == NULL || kv.value == NULL) { > heim_log(r->hcontext, r->logf, 1, "heim_audit_vaddkv: " > "failed to add kv pair (out of memory)"); >+ heim_release(kv.key); >+ heim_release(kv.value); > return; > } > >+ index = addkv(r, kv.key, kv.value); >+ > heim_log(r->hcontext, r->logf, 7, "heim_audit_vaddkv(): " >- "adding kv pair %s", heim_string_get_utf8(str)); >- heim_array_append_value(r->kv, str); >- heim_release(str); >+ "kv pair[%zu] %s=%s", index, >+ heim_string_get_utf8(kv.key), heim_string_get_utf8(kv.value)); >+ >+ heim_release(kv.key); >+ heim_release(kv.value); > } > > void >@@ -808,19 +852,197 @@ heim_audit_addkv_timediff(heim_svc_req_desc r, const char *k, > heim_audit_addkv(r, 0, k, "%s%ld.%06d", sign, sec, usec); > } > >+void >+heim_audit_setkv_bool(heim_svc_req_desc r, const char *k, int v) >+{ >+ heim_string_t key = heim_string_create(k); >+ heim_number_t value; >+ >+ if (key == NULL) >+ return; >+ >+ heim_log(r->hcontext, r->logf, 7, "heim_audit_setkv_bool(): " >+ "setting kv pair %s=%s", k, v ? "true" : "false"); >+ >+ value = heim_bool_create(v); >+ heim_dict_set_value(r->kv, key, value); >+ heim_release(key); >+ heim_release(value); >+} >+ >+void >+heim_audit_addkv_number(heim_svc_req_desc r, const char *k, int64_t v) >+{ >+ heim_string_t key = heim_string_create(k); >+ heim_number_t value; >+ >+ if (key == NULL) >+ return; >+ >+ heim_log(r->hcontext, r->logf, 7, "heim_audit_addkv_number(): " >+ "adding kv pair %s=%lld", k, (long long)v); >+ >+ value = heim_number_create(v); >+ addkv(r, key, value); >+ heim_release(key); >+ heim_release(value); >+} >+ >+void >+heim_audit_setkv_number(heim_svc_req_desc r, const char *k, int64_t v) >+{ >+ heim_string_t key = heim_string_create(k); >+ heim_number_t value; >+ >+ if (key == NULL) >+ return; >+ >+ heim_log(r->hcontext, r->logf, 7, "heim_audit_setkv_number(): " >+ "setting kv pair %s=%lld", k, (long long)v); >+ >+ value = heim_number_create(v); >+ heim_dict_set_value(r->kv, key, value); >+ heim_release(key); >+ heim_release(value); >+} >+ >+void >+heim_audit_addkv_object(heim_svc_req_desc r, const char *k, heim_object_t value) >+{ >+ heim_string_t key = heim_string_create(k); >+ heim_string_t descr; >+ >+ if (key == NULL) >+ return; >+ >+ descr = heim_json_copy_serialize(value, HEIM_JSON_F_NO_DATA_DICT, NULL); >+ heim_log(r->hcontext, r->logf, 7, "heim_audit_addkv_object(): " >+ "adding kv pair %s=%s", >+ k, descr ? heim_string_get_utf8(descr) : "<unprintable>"); >+ addkv(r, key, value); >+ heim_release(key); >+ heim_release(descr); >+} >+ >+void >+heim_audit_setkv_object(heim_svc_req_desc r, const char *k, heim_object_t value) >+{ >+ heim_string_t key = heim_string_create(k); >+ heim_string_t descr; >+ >+ if (key == NULL) >+ return; >+ >+ descr = heim_json_copy_serialize(value, HEIM_JSON_F_NO_DATA_DICT, NULL); >+ heim_log(r->hcontext, r->logf, 7, "heim_audit_setkv_object(): " >+ "setting kv pair %s=%s", >+ k, descr ? heim_string_get_utf8(descr) : "<unprintable>"); >+ heim_dict_set_value(r->kv, key, value); >+ heim_release(key); >+ heim_release(descr); >+} >+ >+heim_object_t >+heim_audit_getkv(heim_svc_req_desc r, const char *k) >+{ >+ heim_string_t key; >+ heim_object_t value; >+ >+ key = heim_string_create(k); >+ if (key == NULL) >+ return NULL; >+ >+ value = heim_dict_get_value(r->kv, key); >+ heim_release(key); >+ return value; >+} >+ >+struct heim_audit_kv_buf { >+ char buf[1024]; >+ size_t pos; >+ heim_object_t iter; >+}; >+ >+static void >+audit_trail_iterator(heim_object_t key, heim_object_t value, void *arg); >+ >+static void >+audit_trail_iterator_array(heim_object_t value, void *arg, int *stop) >+{ >+ struct heim_audit_kv_buf *kvb = arg; >+ >+ audit_trail_iterator(kvb->iter, value, kvb); >+} >+ >+static void >+audit_trail_iterator(heim_object_t key, heim_object_t value, void *arg) >+{ >+ struct heim_audit_kv_buf *kvb = arg; >+ char num[32]; >+ const char *k = heim_string_get_utf8(key), *v = NULL; >+ char *b64 = NULL; >+ >+ if (k == NULL || *k == '#') /* # keys are hidden */ >+ return; >+ >+ switch (heim_get_tid(value)) { >+ case HEIM_TID_STRING: >+ v = heim_string_get_utf8(value); >+ break; >+ case HEIM_TID_NUMBER: >+ snprintf(num, sizeof(num), "%lld", (long long)heim_number_get_long(value)); >+ v = num; >+ break; >+ case HEIM_TID_NULL: >+ v = "null"; >+ break; >+ case HEIM_TID_BOOL: >+ v = heim_bool_val(value) ? "true" : "false"; >+ break; >+ case HEIM_TID_ARRAY: >+ if (kvb->iter) >+ break; /* arrays cannot be nested */ >+ >+ kvb->iter = key; >+ heim_array_iterate_f(value, kvb, audit_trail_iterator_array); >+ kvb->iter = NULL; >+ break; >+ case HEIM_TID_DATA: { >+ const heim_octet_string *data = heim_data_get_data(value); >+ if (rk_base64_encode(data->data, data->length, &b64) >= 0) >+ v = b64; >+ break; >+ } >+ default: >+ break; >+ } >+ >+ if (v == NULL) >+ return; >+ >+ if (kvb->pos < sizeof(kvb->buf) - 1) >+ kvb->buf[kvb->pos++] = ' '; >+ for (; *k && kvb->pos < sizeof(kvb->buf) - 1; kvb->pos++) >+ kvb->buf[kvb->pos] = *k++; >+ if (kvb->pos < sizeof(kvb->buf) - 1) >+ kvb->buf[kvb->pos++] = '='; >+ for (; *v && kvb->pos < sizeof(kvb->buf) - 1; kvb->pos++) >+ kvb->buf[kvb->pos] = *v++; >+ >+ free(b64); >+} >+ > void > heim_audit_trail(heim_svc_req_desc r, heim_error_code ret, const char *retname) > { > const char *retval; >- char kvbuf[1024]; >+ struct heim_audit_kv_buf kvb; > char retvalbuf[30]; /* Enough for UNKNOWN-%d */ >- size_t nelem; >- size_t i, j; > > #define CASE(x) case x : retval = #x; break > if (retname) { > retval = retname; >- } else switch (ret ? ret : r->ret) { >+ } else switch (ret ? ret : r->error_code) { > CASE(ENOMEM); > CASE(ENOENT); > CASE(EACCES); >@@ -838,26 +1060,15 @@ heim_audit_trail(heim_svc_req_desc r, heim_error_code ret, const char *retname) > if (r->e_text && r->kv) > heim_audit_addkv(r, HEIM_SVC_AUDIT_VIS, "e-text", "%s", r->e_text); > >- nelem = r->kv ? heim_array_get_length(r->kv) : 0; >- for (i=0, j=0; i < nelem; i++) { >- heim_string_t s; >- const char *kvpair; >- >- /* We know these are strings... */ >- s = heim_array_get_value(r->kv, i); >- kvpair = heim_string_get_utf8(s); >- >- if (j < sizeof(kvbuf) - 1) >- kvbuf[j++] = ' '; >- for (; *kvpair && j < sizeof(kvbuf) - 1; j++) >- kvbuf[j] = *kvpair++; >- } >- kvbuf[j] = '\0'; >+ memset(&kvb, 0, sizeof(kvb)); >+ if (r->kv) >+ heim_dict_iterate_f(r->kv, &kvb, audit_trail_iterator); >+ kvb.buf[kvb.pos] = '\0'; > > heim_log(r->hcontext, r->logf, 3, "%s %s %s %s %s%s%s%s", > r->reqtype, retval, r->from, > r->cname ? r->cname : "<unknown>", > r->sname ? r->sname : "<unknown>", >- kvbuf, r->reason ? " " : "", >+ kvb.buf, r->reason ? " reason=" : "", > r->reason ? heim_string_get_utf8(r->reason) : ""); > } >diff --git a/third_party/heimdal/lib/base/number.c b/third_party/heimdal/lib/base/number.c >index c259f69971d0..8833c8b15233 100644 >--- a/third_party/heimdal/lib/base/number.c >+++ b/third_party/heimdal/lib/base/number.c >@@ -35,7 +35,7 @@ > > #include "baselocl.h" > >-static void >+static void HEIM_CALLCONV > number_dealloc(void *ptr) > { > } >@@ -58,12 +58,12 @@ number_cmp(void *a, void *b) > return na - nb; > } > >-static unsigned long >+static uintptr_t > number_hash(void *ptr) > { > if (heim_base_is_tagged_object(ptr)) > return heim_base_tagged_object_value(ptr); >- return (unsigned long)*(int *)ptr; >+ return (uintptr_t)*(int64_t *)ptr; > } > > struct heim_type_data _heim_number_object = { >@@ -86,16 +86,16 @@ struct heim_type_data _heim_number_object = { > */ > > heim_number_t >-heim_number_create(int number) >+heim_number_create(int64_t number) > { > heim_number_t n; > > if (number < 0xffffff && number >= 0) > return heim_base_make_tagged_object(number, HEIM_TID_NUMBER); > >- n = _heim_alloc_object(&_heim_number_object, sizeof(int)); >+ n = _heim_alloc_object(&_heim_number_object, sizeof(int64_t)); > if (n) >- *((int *)n) = number; >+ *((int64_t *)n) = number; > return n; > } > >@@ -124,5 +124,13 @@ heim_number_get_int(heim_number_t number) > { > if (heim_base_is_tagged_object(number)) > return heim_base_tagged_object_value(number); >- return *(int *)number; >+ return (int)(*(int64_t *)number); >+} >+ >+int64_t >+heim_number_get_long(heim_number_t number) >+{ >+ if (heim_base_is_tagged_object(number)) >+ return heim_base_tagged_object_value(number); >+ return *(int64_t *)number; > } >diff --git a/third_party/heimdal/lib/base/plugin.c b/third_party/heimdal/lib/base/plugin.c >index df225a939c25..631a3386c831 100644 >--- a/third_party/heimdal/lib/base/plugin.c >+++ b/third_party/heimdal/lib/base/plugin.c >@@ -112,7 +112,7 @@ struct heim_dso { > void *dsohandle; > }; > >-static void >+static void HEIM_CALLCONV > dso_dealloc(void *ptr) > { > struct heim_dso *p = ptr; >@@ -156,7 +156,7 @@ struct heim_plugin { > void *ctx; > }; > >-static void >+static void HEIM_CALLCONV > plugin_free(void *ptr) > { > struct heim_plugin *pl = ptr; >@@ -590,34 +590,37 @@ add_dso_plugins_load_fn(heim_context context, > heim_error_code ret; > heim_array_t plugins; > heim_plugin_load_t load_fn; >- char *sym; >+ char *sym = NULL; > size_t i; > heim_get_instance_func_t get_instance; > size_t n_ftables; > heim_plugin_common_ftable_cp *ftables; > >- if (asprintf(&sym, "%s_plugin_load", caller->name) == -1) >+ if (asprintf(&sym, "%s_plugin_load", caller->name) == -1 || sym == NULL) > return NULL; > > /* suppress error here because we may be looking for a different plugin type */ > load_fn = (heim_plugin_load_t)dlsym(dsohandle, sym); >- free(sym); > if (load_fn == NULL) { > heim_debug(context, 15, "Symbol %s not found in %s", sym, dsopath); >+ free(sym); > return NULL; > } > > ret = load_fn(pcontext, &get_instance, &n_ftables, &ftables); > if (ret) { > heim_warn(context, ret, "plugin %s failed to load", dsopath); >+ free(sym); > > /* fallback to loading structure directly */ > return add_dso_plugin_struct(context, pcontext, dsopath, > dsohandle, caller->name); > } > >- if (!validate_plugin_deps(context, caller, dsopath, get_instance)) >+ if (!validate_plugin_deps(context, caller, dsopath, get_instance)) { >+ free(sym); > return NULL; >+ } > > plugins = heim_array_create(); > >@@ -639,6 +642,7 @@ add_dso_plugins_load_fn(heim_context context, > } > > heim_debug(context, 15, "DSO %s loaded (%s)", dsopath, sym); >+ free(sym); > return plugins; > } > #endif /* HAVE_DLOPEN */ >diff --git a/third_party/heimdal/lib/base/string.c b/third_party/heimdal/lib/base/string.c >index 5384998080a5..f942447163db 100644 >--- a/third_party/heimdal/lib/base/string.c >+++ b/third_party/heimdal/lib/base/string.c >@@ -36,7 +36,7 @@ > #include "baselocl.h" > #include <string.h> > >-static void >+static void HEIM_CALLCONV > string_dealloc(void *ptr) > { > heim_string_t s = ptr; >@@ -73,11 +73,11 @@ string_cmp(void *a, void *b) > return strcmp(a, b); > } > >-static unsigned long >+static uintptr_t > string_hash(void *ptr) > { > const char *s = ptr; >- unsigned long n; >+ uintptr_t n; > > for (n = 0; *s; ++s) > n += *s; >diff --git a/third_party/heimdal/lib/base/test_base.c b/third_party/heimdal/lib/base/test_base.c >index fba675cf488e..be6c860e26b9 100644 >--- a/third_party/heimdal/lib/base/test_base.c >+++ b/third_party/heimdal/lib/base/test_base.c >@@ -64,7 +64,7 @@ > > #include "baselocl.h" > >-static void >+static void HEIM_CALLCONV > memory_free(heim_object_t obj) > { > } >@@ -238,8 +238,8 @@ test_json(void) > "{ \"k1\" : \"s1\", \"k2\" : \"s2\" }", > "{ \"k1\" : [\"s1\", \"s2\", \"s3\"], \"k2\" : \"s3\" }", > "{ \"k1\" : {\"k2\":\"s1\",\"k3\":\"s2\",\"k4\":\"s3\"}, \"k5\" : \"s4\" }", >- "[ \"v1\", \"v2\", [\"v3\",\"v4\",[\"v 5\",\" v 7 \"]], -123456789, " >- "null, true, false, 123456789, \"\"]", >+ ("[ \"v1\", \"v2\", [\"v3\",\"v4\",[\"v 5\",\" v 7 \"]], -123456789, " >+ "null, true, false, 123456789, \"\"]"), > " -1" > }; > char *s; >diff --git a/third_party/heimdal/lib/base/version-script.map b/third_party/heimdal/lib/base/version-script.map >index 0cd0c8444cb7..928e86199955 100644 >--- a/third_party/heimdal/lib/base/version-script.map >+++ b/third_party/heimdal/lib/base/version-script.map >@@ -29,8 +29,14 @@ HEIMDAL_BASE_1.0 { > heim_array_iterate_reverse_f; > heim_array_set_value; > heim_audit_addkv; >+ heim_audit_addkv_number; >+ heim_audit_addkv_object; > heim_audit_addkv_timediff; >+ heim_audit_setkv_bool; >+ heim_audit_setkv_number; >+ heim_audit_setkv_object; > heim_audit_addreason; >+ heim_audit_getkv; > heim_audit_trail; > heim_audit_vaddkv; > heim_audit_vaddreason; >@@ -147,6 +153,7 @@ HEIMDAL_BASE_1.0 { > heim_null_create; > heim_number_create; > heim_number_get_int; >+ heim_number_get_long; > heim_number_get_type_id; > heim_openlog; > heim_path_copy; >diff --git a/third_party/heimdal/lib/com_err/Makefile.am b/third_party/heimdal/lib/com_err/Makefile.am >index 8c027c74da9f..14e8e66fcdc6 100644 >--- a/third_party/heimdal/lib/com_err/Makefile.am >+++ b/third_party/heimdal/lib/com_err/Makefile.am >@@ -2,7 +2,7 @@ > > include $(top_srcdir)/Makefile.am.common > >-YFLAGS = -d >+YFLAGS = -d -o parse.c > LFLAGS = @FLEXNOUNPUTARGS@ > > lib_LTLIBRARIES = libcom_err.la >diff --git a/third_party/heimdal/lib/gss_preauth/pa_client.c b/third_party/heimdal/lib/gss_preauth/pa_client.c >index 1159e63c2a46..de2d7b5cbe6d 100644 >--- a/third_party/heimdal/lib/gss_preauth/pa_client.c >+++ b/third_party/heimdal/lib/gss_preauth/pa_client.c >@@ -95,9 +95,10 @@ pa_gss_step(krb5_context context, > gss_name_t target_name = GSS_C_NO_NAME; > OM_uint32 req_flags = GSS_C_MUTUAL_FLAG; > OM_uint32 ret_flags; >- struct gss_channel_bindings_struct cb = { 0 }; >+ struct gss_channel_bindings_struct cb; > gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER; > >+ memset(&cb, 0, sizeof(cb)); > krb5_data_zero(out); > > if (flags.request_anonymous) >diff --git a/third_party/heimdal/lib/gss_preauth/pa_common.c b/third_party/heimdal/lib/gss_preauth/pa_common.c >index c2287ca707a7..00efde72d662 100644 >--- a/third_party/heimdal/lib/gss_preauth/pa_common.c >+++ b/third_party/heimdal/lib/gss_preauth/pa_common.c >@@ -64,11 +64,6 @@ _krb5_gss_map_error(OM_uint32 major, OM_uint32 minor) > ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; > break; > case GSS_S_FAILURE: >- if (minor == (OM_uint32)KRB5KRB_AP_ERR_BAD_INTEGRITY || >- minor == (OM_uint32)HNTLM_ERR_AUTH) { >- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; >- break; >- } > default: > ret = KRB5KDC_ERR_PREAUTH_FAILED; > break; >diff --git a/third_party/heimdal/lib/gssapi/Makefile.am b/third_party/heimdal/lib/gssapi/Makefile.am >index 744232e2e35b..a69ebffb04ec 100644 >--- a/third_party/heimdal/lib/gssapi/Makefile.am >+++ b/third_party/heimdal/lib/gssapi/Makefile.am >@@ -2,9 +2,12 @@ > > include $(top_srcdir)/Makefile.am.common > >+WFLAGS += $(WFLAGS_ENUM_CONV) >+ > AUTOMAKE_OPTIONS = subdir-objects > > AM_CPPFLAGS += \ >+ -I$(top_srcdir)/lib \ > -I$(srcdir)/../krb5 \ > -I$(srcdir) \ > -I$(srcdir)/gssapi \ >@@ -59,6 +62,7 @@ krb5src = \ > krb5/inquire_mechs_for_name.c \ > krb5/inquire_names_for_mech.c \ > krb5/inquire_sec_context_by_oid.c \ >+ krb5/name_attrs.c \ > krb5/pname_to_uid.c \ > krb5/process_context_token.c \ > krb5/prf.c \ >@@ -249,6 +253,7 @@ sanonsrc = \ > sanon/process_context_token.c \ > sanon/release_cred.c \ > sanon/release_name.c \ >+ sanon/sanon_locl.h \ > sanon/sanon-private.h > > dist_libgssapi_la_SOURCES = \ >@@ -302,19 +307,20 @@ nobase_include_HEADERS = \ > gssapidir = $(includedir)/gssapi > nodist_gssapi_HEADERS = gkrb5_err.h negoex_err.h > >-gssapi_files = asn1_GSSAPIContextToken.x >+gssapi_files = \ >+ asn1_GSSAPIContextToken.c > > spnego_files = \ >- asn1_ContextFlags.x \ >- asn1_MechType.x \ >- asn1_MechTypeList.x \ >- asn1_NegotiationToken.x \ >- asn1_NegotiationToken2.x \ >- asn1_NegHints.x \ >- asn1_NegTokenInit.x \ >- asn1_NegTokenInit2.x \ >- asn1_NegTokenResp.x \ >- asn1_NegStateEnum.x >+ asn1_ContextFlags.c \ >+ asn1_MechType.c \ >+ asn1_MechTypeList.c \ >+ asn1_NegHints.c \ >+ asn1_NegStateEnum.c \ >+ asn1_NegTokenInit.c \ >+ asn1_NegTokenInit2.c \ >+ asn1_NegTokenResp.c \ >+ asn1_NegotiationToken.c \ >+ asn1_NegotiationToken2.c > > BUILTHEADERS = \ > $(srcdir)/krb5/gsskrb5-private.h \ >@@ -327,7 +333,7 @@ $(test_context_OBJECTS): $(BUILTHEADERS) > > $(libgssapi_la_OBJECTS): $(srcdir)/version-script.map > >-BUILT_SOURCES = $(spnego_files:.x=.c) $(gssapi_files:.x=.c) >+BUILT_SOURCES = $(spnego_files) $(gssapi_files) > > $(libgssapi_la_OBJECTS): gkrb5_err.h negoex_err.h > gkrb5_err.h: $(srcdir)/krb5/gkrb5_err.et >@@ -337,16 +343,27 @@ CLEANFILES = $(BUILT_SOURCES) \ > gkrb5_err.[ch] negoex_err.[ch] \ > $(spnego_files) spnego_asn1*.h* spnego_asn1_files spnego_asn1-template.[cx] \ > $(gssapi_files) gssapi_asn1*.h* gssapi_asn1_files gssapi_asn1-template.[cx] \ >- gss-commands.h gss-commands.c >+ gss-commands.h gss-commands.c \ >+ gssapi_asn1.json gssapi_asn1_oids.c gssapi_asn1_syms.c \ >+ spnego_asn1.json spnego_asn1_oids.c spnego_asn1_syms.c >+ >+$(spnego_files) spnego_asn1.h spnego_asn1-priv.h: spnego_asn1_files >+ for genfile in '$(spnego_files)'; do \ >+ $(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $${genfile}; \ >+ done > >-$(spnego_files) spnego_asn1.hx spnego_asn1-priv.hx: spnego_asn1_files >-$(gssapi_files) gssapi_asn1.hx gssapi_asn1-priv.hx: gssapi_asn1_files >+$(gssapi_files) gssapi_asn1.h gssapi_asn1-priv.h: gssapi_asn1_files >+ for genfile in '$(gssapi_files)'; do \ >+ $(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $${genfile}; \ >+ done > > spnego_asn1_files: $(ASN1_COMPILE_DEP) $(srcdir)/spnego/spnego.asn1 $(srcdir)/spnego/spnego.opt > $(ASN1_COMPILE) --option-file=$(srcdir)/spnego/spnego.opt $(srcdir)/spnego/spnego.asn1 spnego_asn1 >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $$(cat spnego_asn1_files) > > gssapi_asn1_files: $(ASN1_COMPILE_DEP) $(srcdir)/mech/gssapi.asn1 > $(ASN1_COMPILE) $(srcdir)/mech/gssapi.asn1 gssapi_asn1 >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $$(cat gssapi_asn1_files) > > $(srcdir)/krb5/gsskrb5-private.h: > cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p krb5/gsskrb5-private.h $(krb5src) || rm -f krb5/gsskrb5-private.h >@@ -358,7 +375,7 @@ $(srcdir)/sanon/sanon-private.h: > cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p sanon/sanon-private.h $(sanonsrc) || rm -f sanon/sanon-private.h > > TESTS = test_oid test_names test_cfx >-# test_sequence >+# test_sequence > > test_cfx_SOURCES = krb5/test_cfx.c > >@@ -381,6 +398,9 @@ LDADD = libgssapi.la \ > $(top_builddir)/lib/krb5/libkrb5.la \ > $(LIB_roken) > >+test_names_LDADD = $(LDADD) $(top_builddir)/lib/asn1/libasn1.la >+test_context_LDADD = $(LDADD) $(top_builddir)/lib/asn1/libasn1.la $(top_builddir)/lib/wind/libwind.la >+ > # gss > > dist_gsstool_SOURCES = gsstool.c >@@ -441,9 +461,8 @@ $(srcdir)/gssapi/gssapi_oid.h $(srcdir)/mech/gss_oid.c: > # NegoEx test mechanism, uses decode_GSSAPIContextToken > # > >-test_negoex_mech_la_SOURCES = test_negoex_mech.c $(gssapi_files:.x=.c) >+test_negoex_mech_la_SOURCES = test_negoex_mech.c $(gssapi_files) > test_negoex_mech_la_LDFLAGS = -module > test_negoex_mech_la_LIBADD = \ > $(top_builddir)/lib/asn1/libasn1.la \ > libgssapi.la >- >diff --git a/third_party/heimdal/lib/gssapi/NTMakefile b/third_party/heimdal/lib/gssapi/NTMakefile >index 8d5784f17f11..ffba9d52be05 100644 >--- a/third_party/heimdal/lib/gssapi/NTMakefile >+++ b/third_party/heimdal/lib/gssapi/NTMakefile >@@ -33,6 +33,8 @@ > > RELDIR=lib\gssapi > >+intcflags=-DASN1_LIB >+ > !include ../../windows/NTMakefile.w32 > > krb5src = \ >@@ -77,6 +79,7 @@ krb5src = \ > krb5/inquire_mechs_for_name.c \ > krb5/inquire_names_for_mech.c \ > krb5/inquire_sec_context_by_oid.c \ >+ krb5/name_attrs.c \ > krb5/pname_to_uid.c \ > krb5/process_context_token.c \ > krb5/prf.c \ >@@ -274,22 +277,14 @@ $(OBJ)\spnego\spnego-private.h: $(spnegosrc) > $(OBJ)\sanon\sanon-private.h: $(sanonsrc) > $(PERL) ../../cf/make-proto.pl -q -P remove -p $@ $(sanonsrc) > >-gssapi_files = $(OBJ)\gssapi\asn1_gssapi_asn1.x >- >-spnego_files = $(OBJ)\spnego\asn1_spnego_asn1.x >- >-$(gssapi_files:.x=.c): $$(@R).x >- >-$(spnego_files:.x=.c): $$(@R).x >- >-$(gssapi_files) $(OBJ)\gssapi\gssapi_asn1.hx $(OBJ)\gssapi\gssapi_asn1-priv.hx: \ >+$(OBJ)\gssapi\asn1_gssapi_asn1.c $(OBJ)\gssapi\gssapi_asn1.h $(OBJ)\gssapi\gssapi_asn1-priv.h: \ > $(BINDIR)\asn1_compile.exe mech\gssapi.asn1 > cd $(OBJ)\gssapi > $(BINDIR)\asn1_compile.exe --one-code-file $(SRCDIR)\mech\gssapi.asn1 gssapi_asn1 \ > || ( $(RM) $(OBJ)\gssapi\gssapi_asn1.h ; exit /b 1 ) > cd $(SRCDIR) > >-$(spnego_files) $(OBJ)\spnego\spnego_asn1.hx $(OBJ)\spnego\spnego_asn1-priv.hx: \ >+$(OBJ)\spnego\asn1_spnego_asn1.c $(OBJ)\spnego\spnego_asn1.h $(OBJ)\spnego\spnego_asn1-priv.h: \ > $(BINDIR)\asn1_compile.exe spnego\spnego.asn1 > cd $(OBJ)\spnego > $(BINDIR)\asn1_compile --one-code-file --sequence=MechTypeList \ >@@ -368,6 +363,7 @@ libgssapi_OBJs = \ > $(OBJ)\krb5/inquire_mechs_for_name.obj \ > $(OBJ)\krb5/inquire_names_for_mech.obj \ > $(OBJ)\krb5/inquire_sec_context_by_oid.obj \ >+ $(OBJ)\krb5/name_attrs.obj \ > $(OBJ)\krb5/pname_to_uid.obj \ > $(OBJ)\krb5/process_context_token.obj \ > $(OBJ)\krb5/prf.obj \ >@@ -537,8 +533,8 @@ libgssapi_OBJs = \ > $(OBJ)\sanon/release_name.obj \ > $(OBJ)\gkrb5_err.obj \ > $(OBJ)\negoex_err.obj \ >- $(spnego_files:.x=.obj) \ >- $(gssapi_files:.x=.obj) >+ $(OBJ)\spnego\asn1_spnego_asn1.obj \ >+ $(OBJ)\gssapi\asn1_gssapi_asn1.obj > > GCOPTS=-I$(SRCDIR) -I$(OBJ) -Igssapi -DBUILD_GSSAPI_LIB > >@@ -578,24 +574,12 @@ GCOPTS=-I$(SRCDIR) -I$(OBJ) -Igssapi -DBUILD_GSSAPI_LIB > {$(OBJ)}.c{$(OBJ)}.obj:: > $(C2OBJ_P) $(GCOPTS) > >-{$(OBJ)\spnego}.x{$(OBJ)\spnego}.c: >- $(CP) $** $@ >- >-{$(OBJ)\gssapi}.x{$(OBJ)\gssapi}.c: >- $(CP) $** $@ >- > {gssapi}.h{$(INCDIR)\gssapi}.h: > $(CP) $** $@ > > {$(OBJ)}.h{$(INCDIR)\gssapi}.h: > $(CP) $** $@ > >-{$(OBJ)\gssapi}.hx{$(OBJ)\gssapi}.h: >- $(CP) $** $@ >- >-{$(OBJ)\spnego}.hx{$(OBJ)\spnego}.h: >- $(CP) $** $@ >- > LIBGSSAPI_LIBS=\ > $(LIBHEIMBASE) \ > $(LIBROKEN) \ >@@ -690,8 +674,8 @@ $(OBJ)\gss-commands.c $(OBJ)\gss-commands.h: gss-commands.in > (generate-obj-macro "libgssapi_OBJs" > (concat "\t$(OBJ)\\gkrb5_err.obj \\\n" > "\t$(OBJ)\\negoex_err.obj \\\n" >- "\t$(spnego_files:.x=.obj) \\\n" >- "\t$(gssapi_files:.x=.obj)") >+ "\t$(OBJ)\\spnego\\asn1_spnego_asn1.obj \\\n" >+ "\t$(OBJ)\\gssapi\\asn1_gssapi_asn1.obj") > "krb5src" "mechsrc" "spnegosrc" "ntlmsrc") > !endif > >@@ -715,7 +699,7 @@ $(OBJ)\test_oid.exe: $(OBJ)\test_oid.obj $(LIBGSSAPI) $(LIBROKEN) > $(EXECONLINK) > $(EXEPREP_NODIST) > >-$(OBJ)\test_names.exe: $(OBJ)\test_names.obj $(LIBGSSAPI) $(LIBROKEN) $(LIBVERS) >+$(OBJ)\test_names.exe: $(OBJ)\test_names.obj $(LIBGSSAPI) $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS) > $(EXECONLINK) > $(EXEPREP_NODIST) > >diff --git a/third_party/heimdal/lib/gssapi/gss-token.c b/third_party/heimdal/lib/gssapi/gss-token.c >index 1ead3e15b32f..844fa4d38206 100644 >--- a/third_party/heimdal/lib/gssapi/gss-token.c >+++ b/third_party/heimdal/lib/gssapi/gss-token.c >@@ -250,7 +250,7 @@ write_and_free_token(gss_buffer_t out, int negotiate) > > bail: > gss_release_buffer(&min, out); >- return 0; >+ return ret; > } > > static int >@@ -402,7 +402,7 @@ static int > initiate_many(gss_name_t service, int delegate, int negotiate, int memcache, > size_t count) > { >- krb5_error_code kret; >+ krb5_error_code kret = 0; > krb5_context kctx = NULL; > krb5_ccache def_cache = NULL; > krb5_ccache mem_cache = NULL; >@@ -443,7 +443,8 @@ accept_one(gss_name_t service, const char *ccname, int negotiate) > gss_OID mech_oid; > gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; > gss_buffer_desc in = GSS_C_EMPTY_BUFFER; >- gss_buffer_desc out, dname; >+ gss_buffer_desc out; >+ gss_buffer_desc dname = GSS_C_EMPTY_BUFFER; > krb5_context kctx = NULL; > krb5_ccache ccache = NULL; > krb5_error_code kret; >@@ -488,6 +489,8 @@ accept_one(gss_name_t service, const char *ccname, int negotiate) > if (!nflag) > printf("Authenticated: %.*s\n", (int)dname.length, > (char *)dname.value); >+ (void) gss_release_buffer(&min, &dname); >+ (void) gss_release_name(&min, &client); > > if (ccname) { > #ifdef HAVE_GSS_STORE_CRED_INTO >@@ -565,7 +568,7 @@ print_all_mechs(void) > for (i=0; i < mech_set->count; i++) > printf("%s\n", gss_oid_to_name(&mech_set->elements[i])); > >- maj = gss_release_oid_set(&min, &mech_set); >+ (void) gss_release_oid_set(&min, &mech_set); > > bail: > exit(ret); >diff --git a/third_party/heimdal/lib/gssapi/gssapi/gssapi.h b/third_party/heimdal/lib/gssapi/gssapi/gssapi.h >index 4214acc0e5f7..726543f5a382 100644 >--- a/third_party/heimdal/lib/gssapi/gssapi/gssapi.h >+++ b/third_party/heimdal/lib/gssapi/gssapi/gssapi.h >@@ -233,6 +233,7 @@ typedef OM_uint32 gss_qop_t; > #define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0) > #define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0) > #define GSS_C_EMPTY_BUFFER {0, NULL} >+#define GSS_C_EMPTY_BUFFER_SET {0, NULL} > #define GSS_C_NO_IOV_BUFFER ((gss_iov_buffer_t)0) > #define GSS_C_NO_CRED_STORE ((gss_key_value_set_t)0) > >@@ -393,6 +394,18 @@ extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_anonymous_oid_desc; > extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_export_name_oid_desc; > #define GSS_C_NT_EXPORT_NAME (&__gss_c_nt_export_name_oid_desc) > >+/* >+ * The implementation must reserve static storage for a >+ * gss_OID_desc object containing the value >+ * {6, (void *)"\x2b\x06\x01\x05\x06\x06"}, corresponding to an >+ * object-identifier value of {iso(1) identified-organization(3) dod(6) >+ * internet(1) security(5) nametypes(6) gss-composite-export(6)}. >+ * The constant GSS_C_NT_COMPOSITE_EXPORT [RFC6680] should be initialized to >+ * point to that gss_OID_desc. >+ */ >+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_composite_export_oid_desc; >+#define GSS_C_NT_COMPOSITE_EXPORT (&__gss_c_nt_composite_export_oid_desc) >+ > /* Major status codes */ > > #define GSS_S_COMPLETE 0 >@@ -1240,9 +1253,6 @@ GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL > gss_destroy_cred(OM_uint32 *minor_status, > gss_cred_id_t *cred_handle); > >-GSSAPI_LIB_FUNCTION uintptr_t GSSAPI_CALLCONV >-gss_get_instance(const char *libname); >- > /* > * S4UProxy and S4USelf extensions. > */ >diff --git a/third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h b/third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h >index 74d5109aa19c..818042fa7739 100644 >--- a/third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h >+++ b/third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h >@@ -218,6 +218,8 @@ gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, > OM_uint32 num_enctypes, > int32_t *enctypes); > >+#define GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "urn:ietf:kerberos:nameattr-" >+ > GSSAPI_CPP_END > > #endif /* GSSAPI_SPNEGO_H_ */ >diff --git a/third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c >index f125573c1372..3f8e2740e212 100644 >--- a/third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c >+++ b/third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c >@@ -157,39 +157,31 @@ gsskrb5_accept_delegated_token(OM_uint32 *minor_status, > krb5_ccache ccache = NULL; > krb5_error_code kret; > int32_t ac_flags, ret = GSS_S_COMPLETE; >+ gsskrb5_cred handle; > > *minor_status = 0; > > /* XXX Create a new delegated_cred_handle? */ >- if (delegated_cred_handle == NULL) { >- ret = GSS_S_COMPLETE; >- goto out; >- } >+ if (delegated_cred_handle == NULL) >+ return GSS_S_COMPLETE; > > *delegated_cred_handle = NULL; > kret = krb5_cc_resolve(context, "MEMORY:anonymous", &ccache); >- if (kret) { >- ctx->flags &= ~GSS_C_DELEG_FLAG; >- goto out; >+ if (kret == 0) >+ kret = krb5_cc_initialize(context, ccache, ctx->source); >+ if (kret == 0) { >+ (void) krb5_auth_con_removeflags(context, >+ ctx->auth_context, >+ KRB5_AUTH_CONTEXT_DO_TIME, >+ &ac_flags); >+ kret = krb5_rd_cred2(context, >+ ctx->auth_context, >+ ccache, >+ &ctx->fwd_data); >+ (void) krb5_auth_con_setflags(context, >+ ctx->auth_context, >+ ac_flags); > } >- >- kret = krb5_cc_initialize(context, ccache, ctx->source); >- if (kret) { >- ctx->flags &= ~GSS_C_DELEG_FLAG; >- goto out; >- } >- >- krb5_auth_con_removeflags(context, >- ctx->auth_context, >- KRB5_AUTH_CONTEXT_DO_TIME, >- &ac_flags); >- kret = krb5_rd_cred2(context, >- ctx->auth_context, >- ccache, >- &ctx->fwd_data); >- krb5_auth_con_setflags(context, >- ctx->auth_context, >- ac_flags); > if (kret) { > ctx->flags &= ~GSS_C_DELEG_FLAG; > ret = GSS_S_FAILURE; >@@ -197,62 +189,54 @@ gsskrb5_accept_delegated_token(OM_uint32 *minor_status, > goto out; > } > >- if (delegated_cred_handle) { >- gsskrb5_cred handle; >+ ret = _gsskrb5_krb5_import_cred(minor_status, >+ &ccache, >+ NULL, >+ NULL, >+ delegated_cred_handle); >+ if (ret != GSS_S_COMPLETE) >+ goto out; > >- ret = _gsskrb5_krb5_import_cred(minor_status, >- &ccache, >- NULL, >- NULL, >- delegated_cred_handle); >- if (ret != GSS_S_COMPLETE) >- goto out; >- >- handle = (gsskrb5_cred) *delegated_cred_handle; >- handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; >- >- /* >- * A root TGT is one of the form krbtgt/REALM@SAME-REALM. >- * >- * A destination TGT is a root TGT for the same realm as the acceptor >- * service's realm. >- * >- * Normally clients delegate a root TGT for the client's realm. >- * >- * In some deployments clients may want to delegate destination TGTs as >- * a form of constrained delegation: so that the destination service >- * cannot use the delegated credential to impersonate the client >- * principal to services in its home realm (due to KDC lineage/transit >- * checks). In those deployments there may not even be a route back to >- * the KDCs of the client's realm, and attempting to use a >- * non-destination TGT might even lead to timeouts. >- * >- * We could simply pretend not to have obtained a credential, except >- * that a) we don't (yet) have an app name here for the appdefault we >- * need to check, b) the application really wants to be able to log a >- * message about the delegated credential being no good. >- * >- * Thus we leave it to _gsskrb5_store_cred_into2() to decide what to do >- * with non-destination TGTs. To do that, it needs the realm of the >- * acceptor service, which we record here. >- */ >- handle->destination_realm = >- strdup(krb5_principal_get_realm(context, ctx->target)); >- if (handle->destination_realm == NULL) { >- _gsskrb5_release_cred(minor_status, delegated_cred_handle); >- *minor_status = krb5_enomem(context); >- ret = GSS_S_FAILURE; >- goto out; >- } >+ handle = (gsskrb5_cred) *delegated_cred_handle; >+ handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; >+ >+ /* >+ * A root TGT is one of the form krbtgt/REALM@SAME-REALM. >+ * >+ * A destination TGT is a root TGT for the same realm as the acceptor >+ * service's realm. >+ * >+ * Normally clients delegate a root TGT for the client's realm. >+ * >+ * In some deployments clients may want to delegate destination TGTs as >+ * a form of constrained delegation: so that the destination service >+ * cannot use the delegated credential to impersonate the client >+ * principal to services in its home realm (due to KDC lineage/transit >+ * checks). In those deployments there may not even be a route back to >+ * the KDCs of the client's realm, and attempting to use a >+ * non-destination TGT might even lead to timeouts. >+ * >+ * We could simply pretend not to have obtained a credential, except >+ * that a) we don't (yet) have an app name here for the appdefault we >+ * need to check, b) the application really wants to be able to log a >+ * message about the delegated credential being no good. >+ * >+ * Thus we leave it to _gsskrb5_store_cred_into2() to decide what to do >+ * with non-destination TGTs. To do that, it needs the realm of the >+ * acceptor service, which we record here. >+ */ >+ handle->destination_realm = >+ strdup(krb5_principal_get_realm(context, ctx->target)); >+ if (handle->destination_realm == NULL) { >+ _gsskrb5_release_cred(minor_status, delegated_cred_handle); >+ *minor_status = krb5_enomem(context); >+ ret = GSS_S_FAILURE; >+ goto out; > } > > out: > if (ccache) { >- /* Don't destroy the default cred cache */ >- if (delegated_cred_handle == NULL) >- krb5_cc_close(context, ccache); >- else >- krb5_cc_destroy(context, ccache); >+ krb5_cc_close(context, ccache); > } > return ret; > } >@@ -478,6 +462,10 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status, > * lets only send the error token on clock skew, that > * limit when send error token for non-MUTUAL. > */ >+ krb5_auth_con_free(context, ctx->auth_context); >+ krb5_auth_con_free(context, ctx->deleg_auth_context); >+ ctx->deleg_auth_context = NULL; >+ ctx->auth_context = NULL; > return send_error_token(minor_status, context, kret, > server, &indata, output_token); > } else if (kret) { >diff --git a/third_party/heimdal/lib/gssapi/krb5/acquire_cred.c b/third_party/heimdal/lib/gssapi/krb5/acquire_cred.c >index 6b625160668a..211dcaa7f753 100644 >--- a/third_party/heimdal/lib/gssapi/krb5/acquire_cred.c >+++ b/third_party/heimdal/lib/gssapi/krb5/acquire_cred.c >@@ -203,7 +203,8 @@ acquire_cred_with_password(OM_uint32 *minor_status, > { > OM_uint32 ret = GSS_S_FAILURE; > krb5_creds cred; >- krb5_get_init_creds_opt *opt; >+ krb5_init_creds_context ctx = NULL; >+ krb5_get_init_creds_opt *opt = NULL; > krb5_ccache ccache = NULL; > krb5_error_code kret; > time_t now; >@@ -236,13 +237,19 @@ acquire_cred_with_password(OM_uint32 *minor_status, > if (kret) > goto end; > } >- kret = krb5_get_init_creds_opt_alloc(context, &opt); >- if (kret) >- goto end; >- > realm = krb5_principal_get_realm(context, handle->principal); > >- krb5_get_init_creds_opt_set_default_flags(context, "gss_krb5", realm, opt); >+ kret = krb5_get_init_creds_opt_alloc(context, &opt); >+ if (kret == 0) { >+ krb5_get_init_creds_opt_set_default_flags(context, "gss_krb5", realm, >+ opt); >+ kret = krb5_init_creds_init(context, handle->principal, NULL, NULL, 0, >+ opt, &ctx); >+ } >+ if (kret == 0) >+ kret = _krb5_init_creds_set_fast_anon_pkinit_optimistic(context, ctx); >+ if (kret == 0) >+ kret = krb5_init_creds_set_password(context, ctx, password); > > /* > * Get the current time before the AS exchange so we don't >@@ -256,21 +263,18 @@ acquire_cred_with_password(OM_uint32 *minor_status, > */ > krb5_timeofday(context, &now); > >- kret = krb5_get_init_creds_password(context, &cred, handle->principal, >- password, NULL, NULL, 0, NULL, opt); >- krb5_get_init_creds_opt_free(context, opt); >- if (kret) >- goto end; >- >- kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); >- if (kret) >- goto end; >- >- kret = krb5_cc_initialize(context, ccache, cred.client); >- if (kret) >- goto end; >- >- kret = krb5_cc_store_cred(context, ccache, &cred); >+ if (kret == 0) >+ kret = krb5_init_creds_get(context, ctx); >+ if (kret == 0) >+ kret = krb5_init_creds_get_creds(context, ctx, &cred); >+ if (kret == 0) >+ kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); >+ if (kret == 0) >+ kret = krb5_cc_initialize(context, ccache, cred.client); >+ if (kret == 0) >+ kret = krb5_init_creds_store(context, ctx, ccache); >+ if (kret == 0) >+ kret = krb5_cc_store_cred(context, ccache, &cred); > if (kret) > goto end; > >@@ -284,14 +288,16 @@ acquire_cred_with_password(OM_uint32 *minor_status, > handle->ccache = ccache; > ccache = NULL; > ret = GSS_S_COMPLETE; >- kret = 0; > > end: >+ krb5_get_init_creds_opt_free(context, opt); >+ if (ctx) >+ krb5_init_creds_free(context, ctx); > if (ccache != NULL) > krb5_cc_destroy(context, ccache); > if (cred.client != NULL) > krb5_free_cred_contents(context, &cred); >- if (ret != GSS_S_COMPLETE && kret != 0) >+ if (ret != GSS_S_COMPLETE) > *minor_status = kret; > return (ret); > } >diff --git a/third_party/heimdal/lib/gssapi/krb5/arcfour.c b/third_party/heimdal/lib/gssapi/krb5/arcfour.c >index 9093b7a1d36a..8931b32e1c99 100644 >--- a/third_party/heimdal/lib/gssapi/krb5/arcfour.c >+++ b/third_party/heimdal/lib/gssapi/krb5/arcfour.c >@@ -167,18 +167,20 @@ arcfour_mic_cksum_iov(krb5_context context, > continue; > } > >- if (iov[i].buffer.value != NULL) >+ if (iov[i].buffer.length > 0) { >+ assert(iov[i].buffer.value != NULL); > memcpy(ptr + ofs, > iov[i].buffer.value, > iov[i].buffer.length); >- ofs += iov[i].buffer.length; >+ ofs += iov[i].buffer.length; >+ } > } > > if (padding) { > memcpy(ptr + ofs, > padding->buffer.value, > padding->buffer.length); >- ofs += padding->buffer.length; >+ /* ofs += padding->buffer.length; */ > } > > ret = krb5_crypto_init(context, key, 0, &crypto); >@@ -881,6 +883,11 @@ _gssapi_wrap_iov_length_arcfour(OM_uint32 *minor_status, > } > } > >+ if (header == NULL) { >+ *minor_status = EINVAL; >+ return GSS_S_FAILURE; >+ } >+ > major_status = _gk_verify_buffers(minor_status, ctx, header, > padding, trailer, FALSE); > if (major_status != GSS_S_COMPLETE) { >diff --git a/third_party/heimdal/lib/gssapi/krb5/copy_ccache.c b/third_party/heimdal/lib/gssapi/krb5/copy_ccache.c >index 182421581a8c..fc0b9b128723 100644 >--- a/third_party/heimdal/lib/gssapi/krb5/copy_ccache.c >+++ b/third_party/heimdal/lib/gssapi/krb5/copy_ccache.c >@@ -82,6 +82,7 @@ _gsskrb5_krb5_import_cred(OM_uint32 *minor_status, > krb5_error_code kret; > gsskrb5_cred handle; > OM_uint32 ret; >+ int id_given = (*id != NULL); > > *cred = NULL; > >@@ -142,8 +143,6 @@ _gsskrb5_krb5_import_cred(OM_uint32 *minor_status, > > handle->ccache = *id; > *id = NULL; >- if (kret) >- goto out; > } > > >@@ -171,7 +170,7 @@ _gsskrb5_krb5_import_cred(OM_uint32 *minor_status, > } > > >- if (id || keytab) { >+ if (id_given || keytab) { > ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); > if (ret == GSS_S_COMPLETE) > ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, >diff --git a/third_party/heimdal/lib/gssapi/krb5/export_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/export_sec_context.c >index 981baed6edd6..c29841537526 100644 >--- a/third_party/heimdal/lib/gssapi/krb5/export_sec_context.c >+++ b/third_party/heimdal/lib/gssapi/krb5/export_sec_context.c >@@ -195,7 +195,7 @@ _gsskrb5_export_sec_context( > } > > if (ctx->target) { >- kret = krb5_store_principal(sp, ctx->source); >+ kret = krb5_store_principal(sp, ctx->target); > if (kret) { > *minor_status = kret; > goto failure; >diff --git a/third_party/heimdal/lib/gssapi/krb5/external.c b/third_party/heimdal/lib/gssapi/krb5/external.c >index 91947025cc7f..e58df18c5f0a 100644 >--- a/third_party/heimdal/lib/gssapi/krb5/external.c >+++ b/third_party/heimdal/lib/gssapi/krb5/external.c >@@ -152,6 +152,13 @@ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_export_name_oid_desc = > gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_nt_principal_name_oid_desc = > {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01") }; > >+/* >+ * GSS_C_NT_COMPOSITE_EXPORT [RFC6680], OID {iso(1) identified-organization(3) >+ * dod(6) internet(1) security(5) nametypes(6) gss-composite-export(6)}. >+ */ >+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_composite_export_oid_desc = >+ {6, rk_UNCONST("\x2b\x06\x01\x05\x06\x06")}; >+ > /* > * draft-ietf-cat-iakerb-09, IAKERB: > * The mechanism ID for IAKERB proxy GSS-API Kerberos, in accordance >@@ -383,12 +390,12 @@ static gssapi_mech_interface_desc krb5_mech = { > sizeof(krb5_mo) / sizeof(krb5_mo[0]), > _gsskrb5_localname, > _gsskrb5_authorize_localname, >- NULL, /* gm_display_name_ext */ >- NULL, /* gm_inquire_name */ >- NULL, /* gm_get_name_attribute */ >- NULL, /* gm_set_name_attribute */ >- NULL, /* gm_delete_name_attribute */ >- NULL, /* gm_export_name_composite */ >+ _gsskrb5_display_name_ext, >+ _gsskrb5_inquire_name, >+ _gsskrb5_get_name_attribute, >+ _gsskrb5_set_name_attribute, >+ _gsskrb5_delete_name_attribute, >+ _gsskrb5_export_name_composite, > _gsskrb5_duplicate_cred, > _gsskrb5_add_cred_from, > _gsskrb5_store_cred_into, >diff --git a/third_party/heimdal/lib/gssapi/krb5/import_name.c b/third_party/heimdal/lib/gssapi/krb5/import_name.c >index 77449612d05c..f4ee2313c16f 100644 >--- a/third_party/heimdal/lib/gssapi/krb5/import_name.c >+++ b/third_party/heimdal/lib/gssapi/krb5/import_name.c >@@ -183,9 +183,12 @@ import_export_name (OM_uint32 *minor_status, > const gss_buffer_t input_name_buffer, > gss_name_t *output_name) > { >+ CompositePrincipal *composite; > unsigned char *p; > uint32_t length; >+ size_t sz; > OM_uint32 ret; >+ int is_composite; > char *name; > > if (input_name_buffer->length < 10 + GSS_KRB5_MECHANISM->length) >@@ -195,7 +198,9 @@ import_export_name (OM_uint32 *minor_status, > > p = input_name_buffer->value; > >- if (memcmp(&p[0], "\x04\x01\x00", 3) != 0 || >+ if (p[0] != 0x04 || >+ (p[1] != 0x01 && p[1] != 0x02) || >+ p[2] != 0x00 || > p[3] != GSS_KRB5_MECHANISM->length + 2 || > p[4] != 0x06 || > p[5] != GSS_KRB5_MECHANISM->length || >@@ -203,6 +208,8 @@ import_export_name (OM_uint32 *minor_status, > GSS_KRB5_MECHANISM->length) != 0) > return GSS_S_BAD_NAME; > >+ is_composite = p[1] == 0x02; >+ > p += 6 + GSS_KRB5_MECHANISM->length; > > length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; >@@ -211,6 +218,28 @@ import_export_name (OM_uint32 *minor_status, > if (length > input_name_buffer->length - 10 - GSS_KRB5_MECHANISM->length) > return GSS_S_BAD_NAME; > >+ if (is_composite) { >+ if ((composite = calloc(1, sizeof(*composite))) == NULL) { >+ *minor_status = ENOMEM; >+ return GSS_S_FAILURE; >+ } >+ >+ ret = decode_CompositePrincipal(p, length, composite, &sz); >+ if (ret) { >+ *minor_status = ret; >+ return GSS_S_FAILURE; >+ } >+ if (sz != length) { >+ free_CompositePrincipal(composite); >+ free(composite); >+ *minor_status = EINVAL; >+ return GSS_S_FAILURE; >+ } >+ >+ *output_name = (void *)composite; >+ return GSS_S_COMPLETE; >+ } >+ > name = malloc(length + 1); > if (name == NULL) { > *minor_status = ENOMEM; >@@ -221,7 +250,6 @@ import_export_name (OM_uint32 *minor_status, > > ret = parse_krb5_name(minor_status, context, name, output_name); > free(name); >- > return ret; > } > >@@ -253,7 +281,8 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_import_name > context, > input_name_buffer, > output_name); >- else if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) { >+ else if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME) || >+ gss_oid_equal(input_name_type, GSS_C_NT_COMPOSITE_EXPORT)) { > return import_export_name(minor_status, > context, > input_name_buffer, >diff --git a/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c >index c7dfdc85166c..62b26ed7eb91 100644 >--- a/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c >+++ b/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c >@@ -33,6 +33,12 @@ > > #include "gsskrb5_locl.h" > >+static OM_uint32 >+gsskrb5_set_authorization_data(OM_uint32 *, >+ krb5_context, >+ krb5_auth_context, >+ gss_const_name_t); >+ > /* > * copy the addresses from `input_chan_bindings' (if any) to > * the auth context `ac' >@@ -418,6 +424,11 @@ init_auth > if (ret) > goto failure; > >+ ret = gsskrb5_set_authorization_data(minor_status, context, >+ ctx->auth_context, name); >+ if (ret) >+ goto failure; >+ > ctx->endtime = ctx->kcred->times.endtime; > > ret = _gss_DES3_get_mic_compat(minor_status, ctx, context); >@@ -921,7 +932,7 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_init_sec_context > time_rec); > if (ret != GSS_S_COMPLETE) > break; >- /* FALLTHROUGH */ >+ fallthrough; > case INITIATOR_RESTART: > ret = init_auth_restart(minor_status, > cred, >@@ -980,3 +991,31 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_init_sec_context > return ret; > > } >+ >+static OM_uint32 >+gsskrb5_set_authorization_data(OM_uint32 *minor_status, >+ krb5_context context, >+ krb5_auth_context auth_context, >+ gss_const_name_t gn) >+{ >+ const CompositePrincipal *name = (const void *)gn; >+ AuthorizationData *ad; >+ krb5_error_code kret = 0; >+ size_t i; >+ >+ if (name->nameattrs == NULL || name->nameattrs->want_ad == NULL) >+ return GSS_S_COMPLETE; >+ >+ ad = name->nameattrs->want_ad; >+ for (i = 0; kret == 0 && i < ad->len; i++) { >+ kret = krb5_auth_con_add_AuthorizationData(context, auth_context, >+ ad->val[0].ad_type, >+ &ad->val[0].ad_data); >+ } >+ >+ if (kret) { >+ *minor_status = kret; >+ return GSS_S_FAILURE; >+ } >+ return GSS_S_COMPLETE; >+} >diff --git a/third_party/heimdal/lib/gssapi/krb5/name_attrs.c b/third_party/heimdal/lib/gssapi/krb5/name_attrs.c >new file mode 100644 >index 000000000000..11fc2ef969fb >--- /dev/null >+++ b/third_party/heimdal/lib/gssapi/krb5/name_attrs.c >@@ -0,0 +1,1171 @@ >+/* >+ * Copyright (c) 2021 Kungliga Tekniska Högskolan >+ * (Royal Institute of Technology, Stockholm, Sweden). >+ * All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * 3. Neither the name of the Institute nor the names of its contributors >+ * may be used to endorse or promote products derived from this software >+ * without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND >+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE >+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >+ * SUCH DAMAGE. >+ */ >+ >+#include "gsskrb5_locl.h" >+ >+/* >+ * (Not-yet-)Standard name attributes for Kerberos MNs, >+ * GSS_KRB5_NAME_ATTRIBUTE_BASE_URN + "...". >+ * >+ * I.e., "urn:ietf:kerberos:nameattr-...". (XXX Register this URN namespace >+ * with IANA.) >+ * >+ * Note that we do use URN fragments. >+ * >+ * Specific attributes below the base URN: >+ * >+ * - name access attributes: >+ * - "realm" -> realm of name >+ * - "name-ncomp" -> count of name components >+ * - "name-ncomp#<digit>" -> name component N (0 <= N <= 9) >+ * >+ * Ticket and Authenticator access attributes: >+ * >+ * - "transit-path" -> encoding of the transited path >+ * - "authenticator-authz-data" -> encoding of all of the authz-data from >+ * the AP-REQ's Authenticator >+ * - "ticket-authz-data" -> encoding of all of the authz-data from >+ * the AP-REQ's Ticket >+ * - "ticket-authz-data#pac" -> the PAC >+ * - "authz-data#<N>" -> encoding of all of a specific auth-data >+ * element type N (e.g., 2, meaning >+ * AD-INTENDED-FOR-SERVER) >+ * >+ * Misc. attributes: >+ * >+ * - "peer-realm" -> name of peer's realm (if this is an MN >+ * resulting for establishing a security >+ * context) >+ * - "canonical-name" -> exported name token and RFC1964 display >+ * syntax of the name's canonical name >+ * >+ * Compatibility with MIT: >+ * >+ * - "urn:mspac:" -> the PAC and its individual info buffers >+ * >+ * TODO: >+ * >+ * - Add some sort of display syntax for transit path >+ * - Add support for URN q-components or attribute prefixes to specify >+ * alternative raw and/or display value encodings (JSON?) >+ * - Add support for attributes for accessing other parts of the Ticket / KDC >+ * reply enc-parts, like auth times >+ * - Add support for getting PAC logon fields, including SIDs (one at a time) >+ * - Add support for CAMMAC? >+ */ >+ >+static int >+attr_eq(gss_const_buffer_t attr, const char *aname, size_t aname_len, \ >+ int prefix_check) >+{ >+ if (attr->length < aname_len) >+ return 0; >+ >+ if (strncmp((char *)attr->value, aname, aname_len) != 0) >+ return 0; >+ >+ return prefix_check || attr->length == aname_len; >+} >+ >+#define ATTR_EQ(a, an) (attr_eq(a, an, sizeof(an) - 1, FALSE)) >+#define ATTR_EQ_PREFIX(a, an) (attr_eq(a, an, sizeof(an) - 1, TRUE)) >+ >+/* Split attribute into prefix, suffix, and fragment. See RFC6680. */ >+static void >+split_attr(gss_const_buffer_t orig, >+ gss_buffer_t prefix, >+ gss_buffer_t attr, >+ gss_buffer_t frag, >+ int *is_urn) >+{ >+ char *last = NULL; >+ char *p = orig->value; >+ >+ *attr = *orig; >+ prefix->value = orig->value; >+ prefix->length = 0; >+ frag->length = 0; >+ frag->value = NULL; >+ >+ /* FIXME We don't have a memrchr() in lib/roken */ >+ for (p = memchr(p, ' ', orig->length); >+ p; >+ p = memchr(p + 1, ' ', orig->length)) { >+ last = p; >+ prefix->length = last - (const char *)orig->value; >+ attr->value = last + 1; >+ attr->length = orig->length - (prefix->length + 1); >+ } >+ if (prefix->length == 0) >+ prefix->value = NULL; >+ >+ if ((*is_urn = (strncmp(attr->value, "urn:", sizeof("urn:") - 1) == 0)) && >+ (p = memchr((char *)attr->value + 1, '#', attr->length - 1))) { >+ frag->value = ++p; >+ frag->length = attr->length - (p - (const char *)attr->value); >+ attr->length = --p - (const char *)attr->value; >+ } >+} >+ >+typedef OM_uint32 get_name_attr_f(OM_uint32 *, >+ const CompositePrincipal *, >+ gss_const_buffer_t, >+ gss_const_buffer_t, >+ gss_const_buffer_t, >+ int *, >+ int *, >+ gss_buffer_t, >+ gss_buffer_t, >+ int *); >+ >+typedef OM_uint32 set_name_attr_f(OM_uint32 *, >+ CompositePrincipal *, >+ gss_const_buffer_t, >+ gss_const_buffer_t, >+ gss_const_buffer_t, >+ int, >+ gss_buffer_t); >+ >+typedef OM_uint32 del_name_attr_f(OM_uint32 *, >+ CompositePrincipal *, >+ gss_const_buffer_t, >+ gss_const_buffer_t, >+ gss_const_buffer_t); >+typedef get_name_attr_f *get_name_attr_fp; >+typedef set_name_attr_f *set_name_attr_fp; >+typedef del_name_attr_f *del_name_attr_fp; >+ >+static get_name_attr_f get_realm; >+static get_name_attr_f get_ncomps; >+static get_name_attr_f get_peer_realm; >+static get_name_attr_f get_pac; >+static get_name_attr_f get_pac_buffer; >+static get_name_attr_f get_authz_data; >+static get_name_attr_f get_ticket_authz_data; >+static get_name_attr_f get_authenticator_authz_data; >+static set_name_attr_f set_authenticator_authz_data; >+static get_name_attr_f get_transited; >+static get_name_attr_f get_canonical_name; >+ >+#define NB(n) \ >+ GSS_KRB5_NAME_ATTRIBUTE_BASE_URN n, n, \ >+ sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN n) - 1, \ >+ sizeof(n) - 1 >+#define NM(n) \ >+ "urn:mspac:" n, n, sizeof("urn:mspac:" n) - 1, sizeof(n) - 1 >+ >+static struct krb5_name_attrs { >+ const char *fullname; >+ const char *name; >+ size_t fullnamelen; >+ size_t namelen; >+ get_name_attr_fp getter; >+ set_name_attr_fp setter; >+ del_name_attr_fp deleter; >+ unsigned int indicate:1; >+ unsigned int is_krb5_name_attr_urn:1; >+} name_attrs[] = { >+ /* XXX We should sort these so we can binary search them */ >+ { NB("realm"), get_realm, NULL, NULL, 1, 1 }, >+ { NB("name-ncomp"), get_ncomps, NULL, NULL, 1, 1 }, >+ { NB("name-ncomp#0"), get_ncomps, NULL, NULL, 1, 1 }, >+ { NB("name-ncomp#1"), get_ncomps, NULL, NULL, 1, 1 }, >+ { NB("name-ncomp#2"), get_ncomps, NULL, NULL, 1, 1 }, >+ { NB("name-ncomp#3"), get_ncomps, NULL, NULL, 1, 1 }, >+ { NB("name-ncomp#4"), get_ncomps, NULL, NULL, 1, 1 }, >+ { NB("name-ncomp#5"), get_ncomps, NULL, NULL, 1, 1 }, >+ { NB("name-ncomp#6"), get_ncomps, NULL, NULL, 1, 1 }, >+ { NB("name-ncomp#7"), get_ncomps, NULL, NULL, 1, 1 }, >+ { NB("name-ncomp#8"), get_ncomps, NULL, NULL, 1, 1 }, >+ { NB("name-ncomp#9"), get_ncomps, NULL, NULL, 1, 1 }, >+ { NB("peer-realm"), get_peer_realm, NULL, NULL, 1, 1 }, >+ { NB("ticket-authz-data#pac"), get_pac, NULL, NULL, 1, 1 }, >+ { NM(""), get_pac, NULL, NULL, 1, 0 }, >+ { NM("logon-info"), get_pac_buffer, NULL, NULL, 1, 0 }, >+ { NM("credentials-info"), get_pac_buffer, NULL, NULL, 1, 0 }, >+ { NM("server-checksum"), get_pac_buffer, NULL, NULL, 1, 0 }, >+ { NM("privsvr-checksum"), get_pac_buffer, NULL, NULL, 1, 0 }, >+ { NM("client-info"), get_pac_buffer, NULL, NULL, 1, 0 }, >+ { NM("delegation-info"), get_pac_buffer, NULL, NULL, 1, 0 }, >+ { NM("upn-dns-info"), get_pac_buffer, NULL, NULL, 1, 0 }, >+ { NM("ticket-checksum"), get_pac_buffer, NULL, NULL, 1, 0 }, >+ { NM("attributes-info"), get_pac_buffer, NULL, NULL, 1, 0 }, >+ { NM("requestor-sid"), get_pac_buffer, NULL, NULL, 1, 0 }, >+ { NB("ticket-authz-data#kdc-issued"), >+ get_ticket_authz_data, NULL, NULL, 1, 1 }, >+ { NB("ticket-authz-data"), >+ get_ticket_authz_data, NULL, NULL, 1, 1 }, >+ { NB("authenticator-authz-data"), >+ get_authenticator_authz_data, >+ set_authenticator_authz_data, NULL, 1, 1 }, >+ { NB("authz-data"), get_authz_data, NULL, NULL, 1, 1 }, >+ { NB("transit-path"), get_transited, NULL, NULL, 1, 1 }, >+ { NB("canonical-name"), get_canonical_name, NULL, NULL, 1, 1 }, >+}; >+ >+OM_uint32 GSSAPI_CALLCONV >+_gsskrb5_get_name_attribute(OM_uint32 *minor_status, >+ gss_name_t name, >+ gss_buffer_t original_attr, >+ int *authenticated, >+ int *complete, >+ gss_buffer_t value, >+ gss_buffer_t display_value, >+ int *more) >+{ >+ gss_buffer_desc prefix, attr, suffix, frag; >+ size_t i; >+ int is_krb5_name_attr_urn = 0; >+ int is_urn = 0; >+ >+ *minor_status = 0; >+ if (authenticated) >+ *authenticated = 0; >+ if (complete) >+ *complete = 0; >+ if (more) >+ *more = 0; >+ if (value) { >+ value->length = 0; >+ value->value = NULL; >+ } >+ if (display_value) { >+ display_value->length = 0; >+ display_value->value = NULL; >+ } >+ >+ suffix.value = NULL; >+ suffix.length = 0; >+ >+ split_attr(original_attr, &prefix, &attr, &frag, &is_urn); >+ >+ if (prefix.length || !is_urn) >+ return GSS_S_UNAVAILABLE; >+ >+ is_krb5_name_attr_urn = >+ ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN); >+ if (is_krb5_name_attr_urn) { >+ suffix.value = >+ (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1; >+ suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1); >+ } >+ >+ for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) { >+ if (!name_attrs[i].getter) >+ continue; >+ if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) { >+ if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0)) >+ continue; >+ } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) { >+ if (!attr_eq(&attr, name_attrs[i].fullname, name_attrs[i].fullnamelen, 0)) >+ continue; >+ } else >+ continue; >+ >+ return name_attrs[i].getter(minor_status, >+ (const CompositePrincipal *)name, >+ &prefix, &attr, &frag, authenticated, >+ complete, value, display_value, more); >+ } >+ return GSS_S_UNAVAILABLE; >+} >+ >+OM_uint32 GSSAPI_CALLCONV >+_gsskrb5_set_name_attribute(OM_uint32 *minor_status, >+ gss_name_t name, >+ int complete, >+ gss_buffer_t original_attr, >+ gss_buffer_t value) >+{ >+ gss_buffer_desc prefix, attr, suffix, frag; >+ size_t i; >+ int is_krb5_name_attr_urn = 0; >+ int is_urn = 0; >+ >+ *minor_status = 0; >+ >+ suffix.value = NULL; >+ suffix.length = 0; >+ >+ split_attr(original_attr, &prefix, &attr, &frag, &is_urn); >+ >+ if (prefix.length || !is_urn) >+ return GSS_S_UNAVAILABLE; >+ >+ is_krb5_name_attr_urn = >+ ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN); >+ if (is_krb5_name_attr_urn) { >+ suffix.value = >+ (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1; >+ suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1); >+ } >+ >+ for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) { >+ if (!name_attrs[i].setter) >+ continue; >+ if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) { >+ if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0)) >+ continue; >+ } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) { >+ if (!attr_eq(&attr, name_attrs[i].name, name_attrs[i].namelen, 0)) >+ continue; >+ } else >+ continue; >+ >+ return name_attrs[i].setter(minor_status, (CompositePrincipal *)name, >+ &prefix, &attr, &frag, complete, value); >+ } >+ return GSS_S_UNAVAILABLE; >+} >+ >+OM_uint32 GSSAPI_CALLCONV >+_gsskrb5_delete_name_attribute(OM_uint32 *minor_status, >+ gss_name_t name, >+ gss_buffer_t original_attr) >+{ >+ gss_buffer_desc prefix, attr, suffix, frag; >+ size_t i; >+ int is_krb5_name_attr_urn = 0; >+ int is_urn = 0; >+ >+ *minor_status = 0; >+ >+ suffix.value = NULL; >+ suffix.length = 0; >+ >+ split_attr(original_attr, &prefix, &attr, &frag, &is_urn); >+ >+ if (prefix.length || !is_urn) >+ return GSS_S_UNAVAILABLE; >+ >+ is_krb5_name_attr_urn = >+ ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN); >+ if (is_krb5_name_attr_urn) { >+ suffix.value = >+ (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1; >+ suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1); >+ } >+ >+ for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) { >+ if (!name_attrs[i].deleter) >+ continue; >+ if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) { >+ if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0)) >+ continue; >+ } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) { >+ if (!attr_eq(&attr, name_attrs[i].fullname, name_attrs[i].fullnamelen, 0)) >+ continue; >+ } else >+ continue; >+ >+ return name_attrs[i].deleter(minor_status, (CompositePrincipal *)name, >+ &prefix, &attr, &frag); >+ } >+ return GSS_S_UNAVAILABLE; >+} >+ >+OM_uint32 GSSAPI_CALLCONV >+_gsskrb5_inquire_name(OM_uint32 *minor_status, >+ gss_name_t name, >+ int *name_is_MN, >+ gss_OID *MN_mech, >+ gss_buffer_set_t *attrs) >+{ >+ gss_buffer_desc prefix, attr, frag, a; >+ OM_uint32 major = GSS_S_UNAVAILABLE; >+ size_t i; >+ int authenticated, is_urn; >+ >+ *minor_status = 0; >+ if (name_is_MN) >+ *name_is_MN = 1; >+ if (MN_mech) >+ *MN_mech = GSS_KRB5_MECHANISM; >+ if (name == GSS_C_NO_NAME) >+ return GSS_S_CALL_INACCESSIBLE_READ; >+ if (attrs == NULL) >+ return GSS_S_CALL_INACCESSIBLE_WRITE; >+ >+ for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) { >+ if (!name_attrs[i].indicate) >+ continue; >+ a.value = (void *)(uintptr_t)name_attrs[i].fullname; >+ a.length = name_attrs[i].fullnamelen; >+ split_attr(&a, &prefix, &attr, &frag, &is_urn); >+ major = name_attrs[i].getter(minor_status, >+ (const CompositePrincipal *)name, >+ &prefix, &attr, &frag, &authenticated, >+ NULL, NULL, NULL, NULL); >+ if (major == GSS_S_UNAVAILABLE) >+ continue; >+ if (major != GSS_S_COMPLETE) >+ break; >+ major = gss_add_buffer_set_member(minor_status, &a, attrs); >+ } >+ if (major == GSS_S_UNAVAILABLE) >+ major = GSS_S_COMPLETE; >+ return major; >+} >+ >+OM_uint32 GSSAPI_CALLCONV >+_gsskrb5_display_name_ext(OM_uint32 *minor_status, >+ gss_name_t name, >+ gss_OID display_as_name_type, >+ gss_buffer_t display_name) >+{ >+ krb5_const_principal p = (void *)name; >+ char *s = NULL; >+ >+ *minor_status = 0; >+ if (display_name == NULL) >+ return GSS_S_CALL_INACCESSIBLE_WRITE; >+ display_name->length = 0; >+ display_name->value = NULL; >+ >+ if (gss_oid_equal(display_as_name_type, GSS_C_NT_USER_NAME)) { >+ if (p->name.name_string.len != 1) >+ return GSS_S_UNAVAILABLE; >+ return _gsskrb5_localname(minor_status, name, GSS_KRB5_MECHANISM, >+ display_name); >+ } >+ if (!gss_oid_equal(display_as_name_type, GSS_C_NT_HOSTBASED_SERVICE) || >+ p->name.name_string.len != 2 || >+ strchr(p->name.name_string.val[0], '@') || >+ strchr(p->name.name_string.val[1], '.') == NULL) >+ return GSS_S_UNAVAILABLE; >+ if (asprintf(&s, "%s@%s", p->name.name_string.val[0], >+ p->name.name_string.val[1]) == -1 || s == NULL) { >+ *minor_status = ENOMEM; >+ return GSS_S_FAILURE; >+ } >+ display_name->length = strlen(s); >+ display_name->value = s; >+ return GSS_S_COMPLETE; >+} >+ >+OM_uint32 GSSAPI_CALLCONV >+_gsskrb5_export_name_composite(OM_uint32 *minor_status, >+ gss_name_t name, >+ gss_buffer_t exported_name) >+{ >+ krb5_error_code kret; >+ gss_buffer_desc inner = GSS_C_EMPTY_BUFFER; >+ unsigned char *buf; >+ size_t sz; >+ >+ if (name == NULL) >+ return GSS_S_CALL_INACCESSIBLE_READ; >+ if (exported_name == NULL) >+ return GSS_S_CALL_INACCESSIBLE_WRITE; >+ >+ ASN1_MALLOC_ENCODE(CompositePrincipal, inner.value, inner.length, >+ (void *)name, &sz, kret); >+ if (kret != 0) { >+ *minor_status = kret; >+ return GSS_S_FAILURE; >+ } >+ >+ exported_name->length = 10 + inner.length + GSS_KRB5_MECHANISM->length; >+ exported_name->value = malloc(exported_name->length); >+ if (exported_name->value == NULL) { >+ free(inner.value); >+ *minor_status = ENOMEM; >+ return GSS_S_FAILURE; >+ } >+ >+ /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ >+ >+ buf = exported_name->value; >+ buf[0] = 0x04; >+ buf[1] = 0x02; >+ buf[2] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff; >+ buf[3] = (GSS_KRB5_MECHANISM->length + 2) & 0xff; >+ buf[4] = 0x06; >+ buf[5] = (GSS_KRB5_MECHANISM->length) & 0xFF; >+ >+ memcpy(buf + 6, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); >+ buf += 6 + GSS_KRB5_MECHANISM->length; >+ >+ buf[0] = (inner.length >> 24) & 0xff; >+ buf[1] = (inner.length >> 16) & 0xff; >+ buf[2] = (inner.length >> 8) & 0xff; >+ buf[3] = (inner.length) & 0xff; >+ buf += 4; >+ >+ memcpy(buf, inner.value, inner.length); >+ free(inner.value); >+ >+ *minor_status = 0; >+ return GSS_S_COMPLETE; >+} >+ >+#define CHECK_ENOMEM(v, dv) \ >+ do { \ >+ if (((v) && !(v)->value) || ((dv) && !(dv)->value)) { \ >+ if ((v) && (v)->value) { \ >+ free((v)->value); \ >+ (v)->length = 0; \ >+ (v)->value = NULL; \ >+ } \ >+ *minor_status = ENOMEM; \ >+ return GSS_S_FAILURE; \ >+ } \ >+ } while (0) >+ >+static OM_uint32 >+get_realm(OM_uint32 *minor_status, >+ const CompositePrincipal *name, >+ gss_const_buffer_t prefix, >+ gss_const_buffer_t attr, >+ gss_const_buffer_t frag, >+ int *authenticated, >+ int *complete, >+ gss_buffer_t value, >+ gss_buffer_t display_value, >+ int *more) >+{ >+ PrincipalNameAttrs *nameattrs = name->nameattrs; >+ >+ if (prefix->length || frag->length || !name->realm) >+ return GSS_S_UNAVAILABLE; >+ if (authenticated && nameattrs && nameattrs->authenticated) >+ *authenticated = 1; >+ if (complete) >+ *complete = 1; >+ if (value && (value->value = strdup(name->realm))) >+ value->length = strlen(name->realm); >+ if (display_value && (display_value->value = strdup(name->realm))) >+ display_value->length = strlen(name->realm); >+ CHECK_ENOMEM(value, display_value); >+ return GSS_S_COMPLETE; >+} >+ >+static OM_uint32 >+get_ncomps(OM_uint32 *minor_status, >+ const CompositePrincipal *name, >+ gss_const_buffer_t prefix, >+ gss_const_buffer_t attr, >+ gss_const_buffer_t frag, >+ int *authenticated, >+ int *complete, >+ gss_buffer_t value, >+ gss_buffer_t display_value, >+ int *more) >+{ >+ PrincipalNameAttrs *nameattrs = name->nameattrs; >+ int n = -1; >+ >+ if (authenticated && nameattrs && nameattrs->authenticated) >+ *authenticated = 1; >+ if (complete) >+ *complete = 1; >+ >+ if (frag->length == 1 && >+ ((const char *)frag->value)[0] >= '0' && >+ ((const char *)frag->value)[0] <= '9') { >+ n = ((const char *)frag->value)[0] - '0'; >+ } else if (frag->length == sizeof("all") - 1 && >+ strncmp(frag->value, "all", sizeof("all") - 1) == 0) { >+ if (!more || *more < -1 || *more == 0 || *more > CHAR_MAX || >+ *more > (int)name->name.name_string.len) { >+ *minor_status = EINVAL; >+ return GSS_S_UNAVAILABLE; >+ } >+ if (*more == -1) { >+ *more = name->name.name_string.len - 1; >+ n = 0; >+ } else { >+ n = name->name.name_string.len - *more; >+ (*more)--; >+ } >+ } >+ >+ if (frag->length == 0) { >+ char *s = NULL; >+ >+ /* Outut count of components */ >+ if (value && (value->value = malloc(sizeof(size_t)))) { >+ *((size_t *)value->value) = name->name.name_string.len; >+ value->length = sizeof(size_t); >+ } >+ if (display_value && >+ asprintf(&s, "%u", (unsigned int)name->name.name_string.len) > 0) { >+ display_value->value = s; >+ display_value->length = strlen(display_value->value); >+ } >+ } else { >+ /* >+ * Output a component. The value and the display value are the same in >+ * this case. >+ */ >+ if (n < 0 || n >= name->name.name_string.len) { >+ *minor_status = EINVAL; >+ return GSS_S_UNAVAILABLE; >+ } >+ if (value && (value->value = strdup(name->name.name_string.val[n]))) >+ value->length = strlen(name->name.name_string.val[n]); >+ if (display_value && >+ (display_value->value = strdup(name->name.name_string.val[n]))) >+ display_value->length = strlen(name->name.name_string.val[n]); >+ } >+ >+ CHECK_ENOMEM(value, display_value); >+ return GSS_S_COMPLETE; >+} >+ >+static OM_uint32 >+get_peer_realm(OM_uint32 *minor_status, >+ const CompositePrincipal *name, >+ gss_const_buffer_t prefix, >+ gss_const_buffer_t attr, >+ gss_const_buffer_t frag, >+ int *authenticated, >+ int *complete, >+ gss_buffer_t value, >+ gss_buffer_t display_value, >+ int *more) >+{ >+ PrincipalNameAttrs *nameattrs = name->nameattrs; >+ >+ if (prefix->length || frag->length || !nameattrs || !nameattrs->peer_realm) >+ return GSS_S_UNAVAILABLE; >+ if (authenticated) >+ *authenticated = 1; >+ if (complete) >+ *complete = 1; >+ if (value && (value->value = strdup(nameattrs->peer_realm[0]))) >+ value->length = strlen(value->value); >+ if (display_value && >+ (display_value->value = strdup(nameattrs->peer_realm[0]))) >+ display_value->length = strlen(display_value->value); >+ >+ CHECK_ENOMEM(value, display_value); >+ return GSS_S_COMPLETE; >+} >+ >+static OM_uint32 >+get_pac(OM_uint32 *minor_status, >+ const CompositePrincipal *name, >+ gss_const_buffer_t prefix, >+ gss_const_buffer_t attr, >+ gss_const_buffer_t frag, >+ int *authenticated, >+ int *complete, >+ gss_buffer_t value, >+ gss_buffer_t display_value, >+ int *more) >+{ >+ krb5_error_code kret; >+ krb5_context context; >+ krb5_data data; >+ PrincipalNameAttrs *nameattrs = name->nameattrs; >+ PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL; >+ EncTicketPart *ticket = NULL; >+ >+ krb5_data_zero(&data); >+ >+ if (src == NULL || >+ src->element != choice_PrincipalNameAttrSrc_enc_ticket_part) >+ return GSS_S_UNAVAILABLE; >+ >+ ticket = &src->u.enc_ticket_part; >+ >+ if (prefix->length || !authenticated || !ticket) >+ return GSS_S_UNAVAILABLE; >+ >+ GSSAPI_KRB5_INIT(&context); >+ >+ *authenticated = nameattrs->pac_verified; >+ if (complete) >+ *complete = 1; >+ >+ kret = _krb5_get_ad(context, ticket->authorization_data, >+ NULL, KRB5_AUTHDATA_WIN2K_PAC, >+ value ? &data : NULL); >+ >+ if (value) { >+ value->length = data.length; >+ value->value = data.data; >+ } >+ >+ *minor_status = kret; >+ if (kret == ENOENT) >+ return GSS_S_UNAVAILABLE; >+ return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; >+} >+ >+static OM_uint32 >+get_pac_buffer(OM_uint32 *minor_status, >+ const CompositePrincipal *name, >+ gss_const_buffer_t prefix, >+ gss_const_buffer_t attr, >+ gss_const_buffer_t frag, >+ int *authenticated, >+ int *complete, >+ gss_buffer_t value, >+ gss_buffer_t display_value, >+ int *more) >+{ >+ krb5_error_code kret; >+ krb5_context context; >+ krb5_data data; >+ PrincipalNameAttrs *nameattrs = name->nameattrs; >+ krb5_data suffix; >+ >+ krb5_data_zero(&data); >+ >+ if (prefix->length || !authenticated || >+ !nameattrs || !nameattrs->pac) >+ return GSS_S_UNAVAILABLE; >+ >+ GSSAPI_KRB5_INIT(&context); >+ >+ if (ATTR_EQ_PREFIX(attr, "urn:mspac:")) { >+ suffix.length = attr->length - (sizeof("urn:mspac:") - 1); >+ suffix.data = (char *)attr->value + sizeof("urn:mspac:") - 1; >+ } else if (ATTR_EQ_PREFIX(frag, "pac-")) { >+ suffix.length = frag->length - sizeof("pac-") - 1; >+ suffix.data = (char *)frag->value + sizeof("pac-") - 1; >+ } else >+ return GSS_S_UNAVAILABLE; /* should not be reached */ >+ >+ *authenticated = nameattrs->pac_verified; >+ if (complete) >+ *complete = 1; >+ >+ kret = _krb5_pac_get_buffer_by_name(context, nameattrs->pac, &suffix, >+ value ? &data : NULL); >+ >+ if (value) { >+ value->length = data.length; >+ value->value = data.data; >+ } >+ >+ *minor_status = kret; >+ if (kret == ENOENT) >+ return GSS_S_UNAVAILABLE; >+ return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; >+} >+ >+static OM_uint32 >+get_authz_data(OM_uint32 *minor_status, >+ const CompositePrincipal *name, >+ gss_const_buffer_t prefix, >+ gss_const_buffer_t attr, >+ gss_const_buffer_t frag, >+ int *authenticated, >+ int *complete, >+ gss_buffer_t value, >+ gss_buffer_t display_value, >+ int *more) >+{ >+ krb5_error_code kret = 0; >+ PrincipalNameAttrs *nameattrs = name->nameattrs; >+ PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL; >+ EncTicketPart *ticket = NULL; >+ krb5_context context; >+ krb5_data data; >+ char s[22]; >+ char *end; >+ int64_t n; >+ >+ if (src) switch (src->element) { >+ case choice_PrincipalNameAttrSrc_enc_ticket_part: >+ ticket = &src->u.enc_ticket_part; >+ break; >+ case choice_PrincipalNameAttrSrc_enc_kdc_rep_part: >+ default: >+ return GSS_S_UNAVAILABLE; >+ } >+ >+ if (!nameattrs || !frag->length || frag->length > sizeof(s) - 1) >+ return GSS_S_UNAVAILABLE; >+ >+ /* Output a specific AD element from the ticket or authenticator */ >+ krb5_data_zero(&data); >+ memcpy(s, frag->value, frag->length); >+ s[frag->length] = '\0'; >+ errno = 0; >+ n = strtoll(s, &end, 10); >+ if (end[0] == '\0' && (errno || n > INT_MAX || n < INT_MIN)) { >+ *minor_status = ERANGE; >+ return GSS_S_UNAVAILABLE; >+ } >+ if (end[0] != '\0') { >+ *minor_status = EINVAL; >+ return GSS_S_UNAVAILABLE; >+ } >+ >+ if (authenticated) >+ *authenticated = 0; >+ if (complete) >+ *complete = 1; >+ >+ GSSAPI_KRB5_INIT(&context); >+ >+ kret = ENOENT; >+ if (ticket && ticket->authorization_data) { >+ kret = _krb5_get_ad(context, ticket->authorization_data, >+ NULL, n, value ? &data : NULL); >+ >+ /* If it's from the ticket, it _may_ be authenticated: */ >+ if (kret == 0 && authenticated) { >+ if (n == KRB5_AUTHDATA_KDC_ISSUED) >+ *authenticated = nameattrs->kdc_issued_verified; >+ else if (n == KRB5_AUTHDATA_WIN2K_PAC) >+ *authenticated = nameattrs->pac_verified; >+ } >+ } >+ if (kret == ENOENT && nameattrs->authenticator_ad && >+ n != KRB5_AUTHDATA_KDC_ISSUED && >+ n != KRB5_AUTHDATA_WIN2K_PAC) { >+ kret = _krb5_get_ad(context, nameattrs->authenticator_ad, >+ NULL, n, value ? &data : NULL); >+ } >+ >+ if (value) { >+ value->length = data.length; >+ value->value = data.data; >+ } >+ *minor_status = kret; >+ if (kret == ENOENT) >+ return GSS_S_UNAVAILABLE; >+ return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; >+} >+ >+static OM_uint32 >+get_ticket_authz_data(OM_uint32 *minor_status, >+ const CompositePrincipal *name, >+ gss_const_buffer_t prefix, >+ gss_const_buffer_t attr, >+ gss_const_buffer_t frag, >+ int *authenticated, >+ int *complete, >+ gss_buffer_t value, >+ gss_buffer_t display_value, >+ int *more) >+{ >+ krb5_error_code kret = 0; >+ PrincipalNameAttrs *nameattrs = name->nameattrs; >+ PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL; >+ EncTicketPart *ticket = NULL; >+ size_t sz; >+ >+ if (src) switch (src->element) { >+ case choice_PrincipalNameAttrSrc_enc_ticket_part: >+ ticket = &src->u.enc_ticket_part; >+ break; >+ case choice_PrincipalNameAttrSrc_enc_kdc_rep_part: >+ default: >+ return GSS_S_UNAVAILABLE; >+ } >+ >+ if (!ticket) >+ return GSS_S_UNAVAILABLE; >+ >+ if (complete) >+ *complete = 1; >+ >+ if (frag->length == sizeof("kdc-issued") - 1 && >+ strncmp(frag->value, "kdc-issued", sizeof("kdc-issued") - 1) == 0) { >+ krb5_context context; >+ krb5_data data; >+ >+ GSSAPI_KRB5_INIT(&context); >+ if (authenticated) >+ *authenticated = nameattrs->kdc_issued_verified; >+ >+ kret = _krb5_get_ad(context, ticket->authorization_data, >+ NULL, KRB5_AUTHDATA_KDC_ISSUED, >+ value ? &data : NULL); >+ if (value) { >+ value->length = data.length; >+ value->value = data.data; >+ } >+ if (kret == ENOENT) >+ return GSS_S_UNAVAILABLE; >+ *minor_status = kret; >+ return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; >+ } else if (frag->length) { >+ return GSS_S_UNAVAILABLE; >+ } >+ >+ /* Just because it's in the Ticket doesn't make it authenticated */ >+ if (authenticated) >+ *authenticated = 0; >+ >+ if (value) { >+ ASN1_MALLOC_ENCODE(AuthorizationData, value->value, value->length, >+ ticket->authorization_data, &sz, kret); >+ *minor_status = kret; >+ } >+ return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; >+} >+ >+static OM_uint32 >+get_authenticator_authz_data(OM_uint32 *minor_status, >+ const CompositePrincipal *name, >+ gss_const_buffer_t prefix, >+ gss_const_buffer_t attr, >+ gss_const_buffer_t frag, >+ int *authenticated, >+ int *complete, >+ gss_buffer_t value, >+ gss_buffer_t display_value, >+ int *more) >+{ >+ krb5_error_code kret = 0; >+ PrincipalNameAttrs *nameattrs = name->nameattrs; >+ size_t sz; >+ >+ if (!nameattrs || !nameattrs->authenticator_ad) >+ return GSS_S_UNAVAILABLE; >+ if (authenticated) >+ *authenticated = 0; >+ if (complete) >+ *complete = 1; >+ >+ if (value) { >+ ASN1_MALLOC_ENCODE(AuthorizationData, value->value, value->length, >+ nameattrs->authenticator_ad, &sz, kret); >+ *minor_status = kret; >+ } >+ return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; >+} >+ >+static OM_uint32 >+set_authenticator_authz_data(OM_uint32 *minor_status, >+ CompositePrincipal *name, >+ gss_const_buffer_t prefix, >+ gss_const_buffer_t attr, >+ gss_const_buffer_t frag, >+ int complete, >+ gss_buffer_t value) >+{ >+ AuthorizationDataElement e; >+ krb5_error_code kret; >+ size_t sz; >+ >+ if (!value) >+ return GSS_S_CALL_INACCESSIBLE_READ; >+ if (frag->length && >+ !ATTR_EQ(frag, "if-relevant")) >+ return GSS_S_UNAVAILABLE; >+ >+ if ((name->nameattrs == NULL && >+ (name->nameattrs = calloc(1, sizeof(*name->nameattrs))) == NULL) || >+ (name->nameattrs->want_ad == NULL && >+ (name->nameattrs->want_ad = >+ calloc(1, sizeof(*name->nameattrs->want_ad))) == NULL)) { >+ *minor_status = ENOMEM; >+ return GSS_S_FAILURE; >+ } >+ >+ memset(&e, 0, sizeof(e)); >+ kret = decode_AuthorizationDataElement(value->value, value->length, &e, >+ &sz); >+ if (kret == 0) { >+ if (frag->length) { >+ AuthorizationData ir; >+ >+ ir.len = 0; >+ ir.val = NULL; >+ kret = add_AuthorizationData(&ir, &e); >+ free_AuthorizationDataElement(&e); >+ if (kret == 0) { >+ e.ad_type = KRB5_AUTHDATA_IF_RELEVANT; >+ ASN1_MALLOC_ENCODE(AuthorizationData, e.ad_data.data, >+ e.ad_data.length, &ir, &sz, kret); >+ kret = add_AuthorizationData(name->nameattrs->want_ad, &e); >+ } >+ free_AuthorizationData(&ir); >+ } else { >+ kret = add_AuthorizationData(name->nameattrs->want_ad, &e); >+ free_AuthorizationDataElement(&e); >+ } >+ } >+ >+ *minor_status = kret; >+ return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; >+} >+ >+static OM_uint32 >+get_transited(OM_uint32 *minor_status, >+ const CompositePrincipal *name, >+ gss_const_buffer_t prefix, >+ gss_const_buffer_t attr, >+ gss_const_buffer_t frag, >+ int *authenticated, >+ int *complete, >+ gss_buffer_t value, >+ gss_buffer_t display_value, >+ int *more) >+{ >+ krb5_error_code kret = 0; >+ PrincipalNameAttrs *nameattrs = name->nameattrs; >+ PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL; >+ EncTicketPart *ticket = NULL; >+ size_t sz; >+ >+ if (src) switch (src->element) { >+ case choice_PrincipalNameAttrSrc_enc_kdc_rep_part: >+ break; >+ case choice_PrincipalNameAttrSrc_enc_ticket_part: >+ ticket = &src->u.enc_ticket_part; >+ break; >+ default: >+ return GSS_S_UNAVAILABLE; >+ } >+ >+ if (!nameattrs && !ticket) >+ return GSS_S_UNAVAILABLE; >+ if (nameattrs && !nameattrs->transited && !ticket) >+ return GSS_S_UNAVAILABLE; >+ >+ if (authenticated) >+ *authenticated = 1; >+ if (complete) >+ *complete = 1; >+ >+ if (value && ticket) >+ ASN1_MALLOC_ENCODE(TransitedEncoding, value->value, value->length, >+ &ticket->transited, &sz, kret); >+ else if (value && nameattrs->transited) >+ ASN1_MALLOC_ENCODE(TransitedEncoding, value->value, value->length, >+ nameattrs->transited, &sz, kret); >+ *minor_status = kret; >+ return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; >+} >+ >+static OM_uint32 >+get_canonical_name(OM_uint32 *minor_status, >+ const CompositePrincipal *name, >+ gss_const_buffer_t prefix, >+ gss_const_buffer_t attr, >+ gss_const_buffer_t frag, >+ int *authenticated, >+ int *complete, >+ gss_buffer_t value, >+ gss_buffer_t display_value, >+ int *more) >+{ >+ krb5_error_code kret = 0; >+ PrincipalNameAttrs *nameattrs = name->nameattrs; >+ PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL; >+ krb5_principal p = NULL; >+ krb5_context context; >+ EncTicketPart *ticket = NULL; >+ EncKDCRepPart *kdcrep = NULL; >+ >+ if (src) switch (src->element) { >+ case choice_PrincipalNameAttrSrc_enc_kdc_rep_part: >+ kdcrep = &src->u.enc_kdc_rep_part; >+ break; >+ case choice_PrincipalNameAttrSrc_enc_ticket_part: >+ ticket = &src->u.enc_ticket_part; >+ break; >+ default: >+ return GSS_S_UNAVAILABLE; >+ } >+ >+ GSSAPI_KRB5_INIT(&context); >+ >+ if (authenticated) >+ *authenticated = 1; >+ if (complete) >+ *complete = 1; >+ >+ if (kdcrep) { >+ kret = _krb5_principalname2krb5_principal(context, &p, >+ kdcrep->sname, >+ kdcrep->srealm); >+ } else if (nameattrs && nameattrs->pac && >+ (_krb5_pac_get_canon_principal(context, nameattrs->pac, &p)) == 0) { >+ if (authenticated) >+ *authenticated = nameattrs->pac_verified; >+ } else if (ticket) { >+ krb5_data data; >+ krb5_pac pac = NULL; >+ >+ krb5_data_zero(&data); >+ >+ /* Use canonical name from PAC if available */ >+ kret = _krb5_get_ad(context, ticket->authorization_data, >+ NULL, KRB5_AUTHDATA_WIN2K_PAC, &data); >+ if (kret == 0) >+ kret = krb5_pac_parse(context, data.data, data.length, &pac); >+ if (kret == 0) >+ kret = _krb5_pac_get_canon_principal(context, pac, &p); >+ if (kret == 0 && authenticated) >+ *authenticated = nameattrs->pac_verified; >+ else if (kret == ENOENT) >+ kret = _krb5_principalname2krb5_principal(context, &p, >+ ticket->cname, >+ ticket->crealm); >+ >+ krb5_data_free(&data); >+ krb5_pac_free(context, pac); >+ } else >+ return GSS_S_UNAVAILABLE; >+ if (kret == 0 && value) { >+ OM_uint32 major; >+ /* >+ * Value is exported name token (exported composite name token >+ * should also work). >+ */ >+ major = _gsskrb5_export_name(minor_status, (gss_name_t)p, value); >+ if (major != GSS_S_COMPLETE) { >+ krb5_free_principal(context, p); >+ return major; >+ } >+ } >+ if (kret == 0 && display_value) { >+ /* Display value is principal name display form */ >+ kret = krb5_unparse_name(context, p, >+ (char **)&display_value->value); >+ if (kret == 0) >+ display_value->length = strlen(display_value->value); >+ } >+ >+ krb5_free_principal(context, p); >+ if (kret) { >+ if (value) { >+ free(value->value); >+ value->length = 0; >+ value->value = NULL; >+ } >+ *minor_status = kret; >+ return GSS_S_UNAVAILABLE; >+ } >+ return GSS_S_COMPLETE; >+} >diff --git a/third_party/heimdal/lib/gssapi/krb5/store_cred.c b/third_party/heimdal/lib/gssapi/krb5/store_cred.c >index 311686dc13a8..6d727b4e289e 100644 >--- a/third_party/heimdal/lib/gssapi/krb5/store_cred.c >+++ b/third_party/heimdal/lib/gssapi/krb5/store_cred.c >@@ -185,7 +185,8 @@ _gsskrb5_store_cred_into2(OM_uint32 *minor_status, > const char *cs_user_name = NULL; > const char *cs_app_name = NULL; > char *ccache_name = NULL; >- OM_uint32 major_status, junk; >+ OM_uint32 major_status = GSS_S_FAILURE; >+ OM_uint32 junk; > OM_uint32 overwrite_cred = store_cred_flags & GSS_C_STORE_CRED_OVERWRITE; > int default_for = 0; > >@@ -346,7 +347,7 @@ _gsskrb5_store_cred_into2(OM_uint32 *minor_status, > (void) gss_release_buffer_set(&junk, &env); > free(ccache_name); > *minor_status = ret; >- return ret ? GSS_S_FAILURE : GSS_S_COMPLETE; >+ return ret ? major_status : GSS_S_COMPLETE; > } > > OM_uint32 GSSAPI_CALLCONV >diff --git a/third_party/heimdal/lib/gssapi/krb5/test_kcred.c b/third_party/heimdal/lib/gssapi/krb5/test_kcred.c >index 3cbba243f0b8..c90a1443bc60 100644 >--- a/third_party/heimdal/lib/gssapi/krb5/test_kcred.c >+++ b/third_party/heimdal/lib/gssapi/krb5/test_kcred.c >@@ -90,9 +90,11 @@ copy_import(void) > if (!equal) > errx(1, "names not equal"); > >- /* FIXME: This check is racy! */ >- if (lifetime1 != lifetime2) >+ /* This check is racy! */ >+ if (getenv("TESTS_ENVIRONMENT") == NULL) && lifetime1 != lifetime2) > errx(1, "lifetime not equal"); >+ if (lifetime1 != lifetime2) >+ warnx("lifetime not equal"); > > if (usage1 != usage1) > errx(1, "usage not equal"); >diff --git a/third_party/heimdal/lib/gssapi/libgssapi-exports.def b/third_party/heimdal/lib/gssapi/libgssapi-exports.def >index b8f9e75c4bcc..6077c8e26f4f 100644 >--- a/third_party/heimdal/lib/gssapi/libgssapi-exports.def >+++ b/third_party/heimdal/lib/gssapi/libgssapi-exports.def >@@ -1,5 +1,6 @@ > EXPORTS > __gss_c_nt_anonymous_oid_desc DATA >+ __gss_c_nt_composite_export_oid_desc DATA > __gss_c_nt_export_name_oid_desc DATA > __gss_c_nt_hostbased_service_oid_desc DATA > __gss_c_nt_hostbased_service_x_oid_desc DATA >@@ -41,7 +42,6 @@ EXPORTS > gss_export_name > gss_export_name_composite > gss_export_sec_context >- gss_get_instance > gss_get_mic > gss_get_neg_mechs > gss_get_name_attribute >diff --git a/third_party/heimdal/lib/gssapi/mech/gss_compare_name.c b/third_party/heimdal/lib/gssapi/mech/gss_compare_name.c >index fd2523fd8e3e..97ef57898da1 100644 >--- a/third_party/heimdal/lib/gssapi/mech/gss_compare_name.c >+++ b/third_party/heimdal/lib/gssapi/mech/gss_compare_name.c >@@ -44,7 +44,15 @@ gss_compare_name(OM_uint32 *minor_status, > * names have one. Otherwise, try to find common mechanism > * names and compare them. > */ >- if (name1->gn_value.value && name2->gn_value.value) { >+ if (name1->gn_value.value && name2->gn_value.value && >+ name1->gn_type == GSS_C_NO_OID && name2->gn_type == GSS_C_NO_OID) { >+ *name_equal = >+ name1->gn_value.length == name2->gn_value.length && >+ memcmp(name1->gn_value.value, name2->gn_value.value, >+ name1->gn_value.length) == 0; >+ } else if (name1->gn_value.value && name2->gn_value.value && >+ name1->gn_type != GSS_C_NO_OID && >+ name2->gn_type != GSS_C_NO_OID) { > *name_equal = 1; > /* RFC 2743: anonymous names always compare false */ > if (gss_oid_equal(name1->gn_type, GSS_C_NT_ANONYMOUS) || >diff --git a/third_party/heimdal/lib/gssapi/mech/gss_cred.c b/third_party/heimdal/lib/gssapi/mech/gss_cred.c >index 3ba2dd84621e..00561ce928e9 100644 >--- a/third_party/heimdal/lib/gssapi/mech/gss_cred.c >+++ b/third_party/heimdal/lib/gssapi/mech/gss_cred.c >@@ -262,8 +262,7 @@ gss_import_cred(OM_uint32 * minor_status, > goto out; > } > >- if (m->gm_import_cred == NULL && >- !gss_oid_equal(&m->gm_mech_oid, GSS_SPNEGO_MECHANISM)) { >+ if (m->gm_import_cred == NULL) { > *minor_status = 0; > major = GSS_S_BAD_MECH; > goto out; >@@ -287,8 +286,7 @@ gss_import_cred(OM_uint32 * minor_status, > continue; > } > >- major = m->gm_import_cred(minor_status, >- &buffer, &mcred); >+ major = m->gm_import_cred(minor_status, &buffer, &mcred); > gss_release_buffer(&junk, &buffer); > if (major != GSS_S_COMPLETE) > goto out; >diff --git a/third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c b/third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c >index 05a05f508dea..c0309809f745 100644 >--- a/third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c >+++ b/third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c >@@ -72,6 +72,10 @@ gss_export_sec_context(OM_uint32 *minor_status, > verflags |= EXPORT_CONTEXT_FLAG_MECH_CTX; > > kret = krb5_store_uint8(sp, verflags); >+ if (kret) { >+ *minor_status = kret; >+ goto failure; >+ } > > if (ctx->gc_target_len) { > _gss_mg_log(10, "gss-esc: exporting partial token %zu/%zu", >diff --git a/third_party/heimdal/lib/gssapi/mech/gss_import_name.c b/third_party/heimdal/lib/gssapi/mech/gss_import_name.c >index d7559981dc53..54930bf46452 100644 >--- a/third_party/heimdal/lib/gssapi/mech/gss_import_name.c >+++ b/third_party/heimdal/lib/gssapi/mech/gss_import_name.c >@@ -31,6 +31,7 @@ > static OM_uint32 > _gss_import_export_name(OM_uint32 *minor_status, > const gss_buffer_t input_name_buffer, >+ const gss_OID name_type, > gss_name_t *output_name) > { > OM_uint32 major_status; >@@ -65,6 +66,24 @@ _gss_import_export_name(OM_uint32 *minor_status, > p += 2; > len -= 2; > >+ /* >+ * If the name token is a composite token (TOK_ID 0x04 0x02) then per >+ * RFC6680 everything after that is implementation-specific. This >+ * mech-glue is pluggable however, so we need the format of the rest of >+ * the header to be stable, otherwise we couldn't reliably determine >+ * what mechanism the token is for and we'd have to try all of them. >+ * >+ * So... we keep the same format for the exported composite name token >+ * as for normal exported name tokens (see RFC2743, section 3.2), with >+ * the TOK_ID 0x04 0x02, but only up to the mechanism OID. We don't >+ * enforce that there be a NAME_LEN in the exported composite name >+ * token, or that it match the length of the remainder of the token. >+ * >+ * FYI, at least one out-of-tree mechanism implements exported >+ * composite name tokens as the same as exported name tokens with >+ * attributes appended and the NAME_LEN not modified to match. >+ */ >+ > /* > * Get the mech length and the name length and sanity > * check the size of of the buffer. >@@ -107,17 +126,19 @@ _gss_import_export_name(OM_uint32 *minor_status, > > mech_oid.elements = p; > >- if (len < t + 4) >- return (GSS_S_BAD_NAME); >- p += t; >- len -= t; >+ if (!composite) { >+ if (len < t + 4) >+ return (GSS_S_BAD_NAME); >+ p += t; >+ len -= t; > >- t = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; >- p += 4; >- len -= 4; >+ t = ((unsigned long)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; >+ /* p += 4; // we're done using `p' now */ >+ len -= 4; > >- if (!composite && len != t) >- return (GSS_S_BAD_NAME); >+ if (len != t) >+ return (GSS_S_BAD_NAME); >+ } > > m = __gss_get_mechanism(&mech_oid); > if (!m || !m->gm_import_name) >@@ -127,7 +148,7 @@ _gss_import_export_name(OM_uint32 *minor_status, > * Ask the mechanism to import the name. > */ > major_status = m->gm_import_name(minor_status, >- input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name); >+ input_name_buffer, name_type, &new_canonical_name); > if (major_status != GSS_S_COMPLETE) { > _gss_mg_error(m, *minor_status); > return major_status; >@@ -156,6 +177,7 @@ _gss_import_export_name(OM_uint32 *minor_status, > * - GSS_C_NT_USER_NAME > * - GSS_C_NT_HOSTBASED_SERVICE > * - GSS_C_NT_EXPORT_NAME >+ * - GSS_C_NT_COMPOSITE_EXPORT > * - GSS_C_NT_ANONYMOUS > * - GSS_KRB5_NT_PRINCIPAL_NAME > * >@@ -197,20 +219,15 @@ gss_import_name(OM_uint32 *minor_status, > > _gss_load_mech(); > >- /* >- * Use GSS_NT_USER_NAME as default name type. >- */ >- if (name_type == GSS_C_NO_OID) >- name_type = GSS_C_NT_USER_NAME; >- > /* > * If this is an exported name, we need to parse it to find > * the mechanism and then import it as an MN. See RFC 2743 > * section 3.2 for a description of the format. > */ >- if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) { >- return _gss_import_export_name(minor_status, >- input_name_buffer, output_name); >+ if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME) || >+ gss_oid_equal(name_type, GSS_C_NT_COMPOSITE_EXPORT)) { >+ return _gss_import_export_name(minor_status, input_name_buffer, >+ name_type, output_name); > } > > >@@ -221,13 +238,16 @@ gss_import_name(OM_uint32 *minor_status, > return (GSS_S_FAILURE); > } > >- major_status = _gss_intern_oid(minor_status, >- name_type, &name->gn_type); >- if (major_status) { >- rname = (gss_name_t)name; >- gss_release_name(&ms, (gss_name_t *)&rname); >- return (GSS_S_FAILURE); >- } >+ if (name_type != GSS_C_NO_OID) { >+ major_status = _gss_intern_oid(minor_status, >+ name_type, &name->gn_type); >+ if (major_status) { >+ rname = (gss_name_t)name; >+ gss_release_name(&ms, (gss_name_t *)&rname); >+ return (GSS_S_FAILURE); >+ } >+ } else >+ name->gn_type = GSS_C_NO_OID; > > major_status = _gss_copy_buffer(minor_status, > input_name_buffer, &name->gn_value); >@@ -245,11 +265,13 @@ gss_import_name(OM_uint32 *minor_status, > if ((m->gm_mech.gm_flags & GM_USE_MG_NAME)) > continue; > >- major_status = gss_test_oid_set_member(minor_status, >- name_type, m->gm_name_types, &present); >+ if (name_type != GSS_C_NO_OID) { >+ major_status = gss_test_oid_set_member(minor_status, >+ name_type, m->gm_name_types, &present); > >- if (major_status || present == 0) >- continue; >+ if (GSS_ERROR(major_status) || present == 0) >+ continue; >+ } > > mn = malloc(sizeof(struct _gss_mechanism_name)); > if (!mn) { >diff --git a/third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c b/third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c >index 0acae8533242..39b717e3dc2f 100644 >--- a/third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c >+++ b/third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c >@@ -42,9 +42,9 @@ gss_import_sec_context(OM_uint32 *minor_status, > > _gss_mg_log(10, "gss-isc called"); > >- if (!minor_status || !context_handle) { >+ if (!context_handle) { > *minor_status = EFAULT; >- return GSS_S_FAILURE; >+ return GSS_S_CALL_INACCESSIBLE_WRITE; > } > > *minor_status = 0; >@@ -87,7 +87,7 @@ gss_import_sec_context(OM_uint32 *minor_status, > if (ret != GSS_S_COMPLETE) > goto failure; > >- ctx->gc_input.value = calloc(target_len, 1); >+ ctx->gc_free_this = ctx->gc_input.value = calloc(target_len, 1); > if (ctx->gc_input.value == NULL) > goto failure; > >diff --git a/third_party/heimdal/lib/gssapi/mech/gss_krb5.c b/third_party/heimdal/lib/gssapi/mech/gss_krb5.c >index 0f6d14209af2..78c305689f00 100644 >--- a/third_party/heimdal/lib/gssapi/mech/gss_krb5.c >+++ b/third_party/heimdal/lib/gssapi/mech/gss_krb5.c >@@ -520,7 +520,8 @@ gss_krb5_ccache_name(OM_uint32 *minor_status, > } > } > >- *out_name = args.out_name; >+ if (out_name) >+ *out_name = args.out_name; > > return major_status; > } >@@ -571,7 +572,7 @@ gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status, > > { > unsigned char *buf = data_set->elements[0].value; >- *authtime = (buf[3] <<24) | (buf[2] << 16) | >+ *authtime = ((unsigned long)buf[3] <<24) | (buf[2] << 16) | > (buf[1] << 8) | (buf[0] << 0); > } > >@@ -729,7 +730,7 @@ gsskrb5_extract_key(OM_uint32 *minor_status, > } > > *keyblock = calloc(1, sizeof(**keyblock)); >- if (keyblock == NULL) { >+ if (*keyblock == NULL) { > ret = ENOMEM; > goto out; > } >diff --git a/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c b/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c >index 60fe376a914e..372e72dd5da8 100644 >--- a/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c >+++ b/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c >@@ -137,6 +137,8 @@ _gss_string_to_oid(const char* s, gss_OID *oidp) > } > } > } >+ if (byte_count == 0) >+ return EINVAL; > if (!res) { > res = malloc(byte_count); > if (!res) >@@ -228,8 +230,12 @@ add_builtin(gssapi_mech_interface mech) > free(m); > return minor_status; > } >- gss_add_oid_set_member(&minor_status, >- &m->gm_mech.gm_mech_oid, &_gss_mech_oids); >+ >+ if (gss_add_oid_set_member(&minor_status, &m->gm_mech.gm_mech_oid, >+ &_gss_mech_oids) != GSS_S_COMPLETE) { >+ free(m); >+ return ENOMEM; >+ } > > /* pick up the oid sets of names */ > >@@ -237,8 +243,12 @@ add_builtin(gssapi_mech_interface mech) > (*m->gm_mech.gm_inquire_names_for_mech)(&minor_status, > &m->gm_mech.gm_mech_oid, &m->gm_name_types); > >- if (m->gm_name_types == NULL) >- gss_create_empty_oid_set(&minor_status, &m->gm_name_types); >+ if (m->gm_name_types == NULL && >+ gss_create_empty_oid_set(&minor_status, >+ &m->gm_name_types) != GSS_S_COMPLETE) { >+ free(m); >+ return ENOMEM; >+ } > > HEIM_TAILQ_INSERT_TAIL(&_gss_mechs, m, gm_link); > return 0; >@@ -288,9 +298,15 @@ _gss_load_mech(void) > return; > } > >- add_builtin(__gss_krb5_initialize()); >- add_builtin(__gss_spnego_initialize()); >- add_builtin(__gss_ntlm_initialize()); >+ if (add_builtin(__gss_krb5_initialize())) >+ _gss_mg_log(1, "Out of memory while adding builtin Kerberos GSS " >+ "mechanism to the GSS mechanism switch"); >+ if (add_builtin(__gss_spnego_initialize())) >+ _gss_mg_log(1, "Out of memory while adding builtin SPNEGO " >+ "mechanism to the GSS mechanism switch"); >+ if (add_builtin(__gss_ntlm_initialize())) >+ _gss_mg_log(1, "Out of memory while adding builtin NTLM " >+ "mechanism to the GSS mechanism switch"); > > #ifdef HAVE_DLOPEN > fp = fopen(conf ? conf : _PATH_GSS_MECH, "r"); >@@ -461,7 +477,9 @@ _gss_load_mech(void) > out: > > #endif >- add_builtin(__gss_sanon_initialize()); >+ if (add_builtin(__gss_sanon_initialize())) >+ _gss_mg_log(1, "Out of memory while adding builtin SANON " >+ "mechanism to the GSS mechanism switch"); > HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); > } > >@@ -565,16 +583,3 @@ gss_oid_to_name(gss_const_OID oid) > > return NULL; > } >- >-GSSAPI_LIB_FUNCTION uintptr_t GSSAPI_CALLCONV >-gss_get_instance(const char *libname) >-{ >- static const char *instance = "libgssapi"; >- >- if (strcmp(libname, "gssapi") == 0) >- return (uintptr_t)instance; >- else if (strcmp(libname, "krb5") == 0) >- return krb5_get_instance(libname); >- >- return 0; >-} >diff --git a/third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c b/third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c >index 72fd9de46245..5046faed0267 100644 >--- a/third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c >+++ b/third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c >@@ -158,6 +158,10 @@ gss_pname_to_uid(OM_uint32 *minor_status, > major = gss_localname(minor_status, pname, mech_type, &localname); > if (GSS_ERROR(major)) > return major; >+ if (localname.length == 0) { >+ *minor_status = KRB5_NO_LOCALNAME; >+ return GSS_S_FAILURE; >+ } > > szLocalname = malloc(localname.length + 1); > if (szLocalname == NULL) { >diff --git a/third_party/heimdal/lib/gssapi/mech/mech_locl.h b/third_party/heimdal/lib/gssapi/mech/mech_locl.h >index 0d74091e054c..d451b87c4a71 100644 >--- a/third_party/heimdal/lib/gssapi/mech/mech_locl.h >+++ b/third_party/heimdal/lib/gssapi/mech/mech_locl.h >@@ -35,24 +35,17 @@ > > #include <config.h> > >-#include <krb5-types.h> >+#include <roken.h> > >-#include <sys/types.h> >+#include <krb5-types.h> > >-#include <stdio.h> >-#include <stdlib.h> >-#include <string.h> > #include <ctype.h> >-#include <dlfcn.h> >-#include <errno.h> > > #include <heimbase.h> > > #include <gssapi_asn1.h> > #include <der.h> > >-#include <roken.h> >- > #include <gssapi.h> > #include <gssapi_mech.h> > #include <gssapi_krb5.h> >diff --git a/third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c b/third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c >index d6300006b210..6a3e8899ee76 100644 >--- a/third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c >+++ b/third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c >@@ -171,12 +171,14 @@ _gss_ntlm_accept_sec_context > output_token->value = malloc(out.length); > if (output_token->value == NULL && out.length != 0) { > OM_uint32 gunk; >+ heim_ntlm_free_buf(&out); > _gss_ntlm_delete_sec_context(&gunk, context_handle, NULL); > *minor_status = ENOMEM; > return GSS_S_FAILURE; > } > memcpy(output_token->value, out.data, out.length); > output_token->length = out.length; >+ heim_ntlm_free_buf(&out); > > ctx->flags = retflags; > >diff --git a/third_party/heimdal/lib/gssapi/ntlm/creds.c b/third_party/heimdal/lib/gssapi/ntlm/creds.c >index 84a710c69e60..57940156cb59 100644 >--- a/third_party/heimdal/lib/gssapi/ntlm/creds.c >+++ b/third_party/heimdal/lib/gssapi/ntlm/creds.c >@@ -76,10 +76,6 @@ _gss_ntlm_inquire_cred > *cred_usage = 0; > if (mechanisms) > *mechanisms = GSS_C_NO_OID_SET; >- >- if (cred_handle == GSS_C_NO_CREDENTIAL) >- return GSS_S_NO_CRED; >- > if (mechanisms) { > ret = gss_create_empty_oid_set(minor_status, mechanisms); > if (ret) >diff --git a/third_party/heimdal/lib/gssapi/ntlm/crypto.c b/third_party/heimdal/lib/gssapi/ntlm/crypto.c >index a8c670c50b28..efa71d911dcb 100644 >--- a/third_party/heimdal/lib/gssapi/ntlm/crypto.c >+++ b/third_party/heimdal/lib/gssapi/ntlm/crypto.c >@@ -194,7 +194,10 @@ v2_sign_message(gss_buffer_t in, > HMAC_CTX c; > > HMAC_CTX_init(&c); >- HMAC_Init_ex(&c, signkey, 16, EVP_md5(), NULL); >+ if (HMAC_Init_ex(&c, signkey, 16, EVP_md5(), NULL) == 0) { >+ HMAC_CTX_cleanup(&c); >+ return GSS_S_FAILURE; >+ } > > encode_le_uint32(seq, hmac); > HMAC_Update(&c, hmac, 4); >diff --git a/third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c b/third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c >index 41c30b76f1a8..57587a020db3 100644 >--- a/third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c >+++ b/third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c >@@ -39,6 +39,8 @@ OM_uint32 GSSAPI_CALLCONV _gss_ntlm_delete_sec_context > gss_buffer_t output_token > ) > { >+ OM_uint32 min; >+ > if (context_handle) { > ntlm_ctx ctx = (ntlm_ctx)*context_handle; > gss_cred_id_t cred = (gss_cred_id_t)ctx->client; >@@ -49,6 +51,10 @@ OM_uint32 GSSAPI_CALLCONV _gss_ntlm_delete_sec_context > (*ctx->server->nsi_destroy)(minor_status, ctx->ictx); > > _gss_ntlm_release_cred(NULL, &cred); >+ memset_s(ctx->sessionkey.data, ctx->sessionkey.length, 0, >+ ctx->sessionkey.length); >+ krb5_data_free(&ctx->sessionkey); >+ gss_release_buffer(&min, &ctx->pac); > > memset(ctx, 0, sizeof(*ctx)); > free(ctx); >diff --git a/third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c b/third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c >index 1063db19b0f1..be9c987c4ca0 100644 >--- a/third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c >+++ b/third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c >@@ -56,20 +56,25 @@ from_file(const char *fn, const char *target_domain, > d = strtok_r(buf, ":", &str); > free(*domainp); > *domainp = NULL; >+ if (!d) >+ continue; > if (d && target_domain != NULL && strcasecmp(target_domain, d) != 0) > continue; > *domainp = strdup(d); >- if (*domainp == NULL) >+ if (*domainp == NULL) { >+ fclose(f); > return ENOMEM; >+ } > u = strtok_r(NULL, ":", &str); > p = strtok_r(NULL, ":", &str); > if (u == NULL || p == NULL) > continue; > > *usernamep = strdup(u); >- if (*usernamep == NULL) >+ if (*usernamep == NULL) { >+ fclose(f); > return ENOMEM; >- >+ } > heim_ntlm_nt_key(p, key); > > memset_s(buf, sizeof(buf), 0, sizeof(buf)); >@@ -376,6 +381,7 @@ _gss_ntlm_init_sec_context > if (RAND_bytes(nonce, sizeof(nonce)) != 1) { > _gss_ntlm_delete_sec_context(minor_status, > context_handle, NULL); >+ heim_ntlm_free_type2(&type2); > *minor_status = EINVAL; > return GSS_S_FAILURE; > } >@@ -394,6 +400,7 @@ _gss_ntlm_init_sec_context > } > if (ret) { > _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); >+ heim_ntlm_free_type2(&type2); > *minor_status = ret; > return GSS_S_FAILURE; > } >@@ -408,6 +415,7 @@ _gss_ntlm_init_sec_context > if (type3.ntlm.data) > free(type3.ntlm.data); > _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); >+ heim_ntlm_free_type2(&type2); > *minor_status = ret; > return GSS_S_FAILURE; > } >@@ -421,6 +429,7 @@ _gss_ntlm_init_sec_context > if (type3.ntlm.data) > free(type3.ntlm.data); > _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); >+ heim_ntlm_free_type2(&type2); > *minor_status = ret; > return GSS_S_FAILURE; > } >@@ -437,6 +446,7 @@ _gss_ntlm_init_sec_context > if(ret) { > _gss_ntlm_delete_sec_context(minor_status, > context_handle, NULL); >+ heim_ntlm_free_type2(&type2); > *minor_status = ret; > return GSS_S_DEFECTIVE_TOKEN; > } >@@ -444,6 +454,7 @@ _gss_ntlm_init_sec_context > if (ti.domainname && strcmp(ti.domainname, name->domain) != 0) { > _gss_ntlm_delete_sec_context(minor_status, > context_handle, NULL); >+ heim_ntlm_free_type2(&type2); > *minor_status = EINVAL; > return GSS_S_FAILURE; > } >@@ -459,6 +470,7 @@ _gss_ntlm_init_sec_context > if (ret) { > _gss_ntlm_delete_sec_context(minor_status, > context_handle, NULL); >+ heim_ntlm_free_type2(&type2); > *minor_status = ret; > return GSS_S_FAILURE; > } >@@ -470,6 +482,7 @@ _gss_ntlm_init_sec_context > if (ret) { > _gss_ntlm_delete_sec_context(minor_status, > context_handle, NULL); >+ heim_ntlm_free_type2(&type2); > *minor_status = ret; > return GSS_S_FAILURE; > } >@@ -482,6 +495,7 @@ _gss_ntlm_init_sec_context > if (ret) { > _gss_ntlm_delete_sec_context(minor_status, > context_handle, NULL); >+ heim_ntlm_free_type2(&type2); > *minor_status = ret; > return GSS_S_FAILURE; > } >@@ -499,6 +513,7 @@ _gss_ntlm_init_sec_context > free(type3.ntlm.data); > if (ret) { > _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); >+ heim_ntlm_free_type2(&type2); > *minor_status = ret; > return GSS_S_FAILURE; > } >@@ -515,6 +530,7 @@ _gss_ntlm_init_sec_context > > ctx->status |= STATUS_OPEN; > >+ heim_ntlm_free_type2(&type2); > return GSS_S_COMPLETE; > } > } >diff --git a/third_party/heimdal/lib/gssapi/ntlm/kdc.c b/third_party/heimdal/lib/gssapi/ntlm/kdc.c >index e5c25596aa6d..1bce00fc5d6f 100644 >--- a/third_party/heimdal/lib/gssapi/ntlm/kdc.c >+++ b/third_party/heimdal/lib/gssapi/ntlm/kdc.c >@@ -252,6 +252,7 @@ kdc_type2(OM_uint32 *minor_status, > krb5_data ti; > > memset(&type2, 0, sizeof(type2)); >+ memset(out, 0, sizeof(*out)); > > /* > * Request data for type 2 packet from the KDC. >diff --git a/third_party/heimdal/lib/gssapi/sanon/import_name.c b/third_party/heimdal/lib/gssapi/sanon/import_name.c >index 189308d96ea0..1a228b69e1a9 100644 >--- a/third_party/heimdal/lib/gssapi/sanon/import_name.c >+++ b/third_party/heimdal/lib/gssapi/sanon/import_name.c >@@ -36,7 +36,8 @@ is_anonymous_identity_p(gss_buffer_t name_string, gss_OID name_type) > { > if (gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS)) > return TRUE; >- else if ((gss_oid_equal(name_type, GSS_C_NT_USER_NAME) || >+ else if ((name_type == GSS_C_NO_OID || >+ gss_oid_equal(name_type, GSS_C_NT_USER_NAME) || > gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) && > buffer_equal_p(name_string, _gss_sanon_wellknown_user_name)) > return TRUE; >@@ -58,17 +59,15 @@ storage_ret_der_oid(krb5_storage *sp, gss_OID_desc *oid) > oid->elements = NULL; > > ret = krb5_ret_uint16(sp, &der_oid_len); >- if (ret != 0) >+ if (ret == 0) >+ ret = krb5_ret_uint8(sp, &tag); >+ if (ret == 0) >+ ret = krb5_ret_uint8(sp, &oid_len); >+ if (ret) > return ret; >- >- ret = krb5_ret_uint8(sp, &tag); > if (tag != 0x06) > return EINVAL; > >- ret = krb5_ret_uint8(sp, &oid_len); >- if (ret != 0) >- return ret; >- > if (der_oid_len != 2 + oid_len) > return EINVAL; > >@@ -125,10 +124,11 @@ import_export_name(OM_uint32 *minor, > } > if (ret == 0) > ret = krb5_ret_uint32(sp, &name_len); >- if (name_len != 1) >- ret = EINVAL; >- ret = krb5_ret_uint8(sp, &is_anonymous); >+ if (ret == 0) >+ ret = krb5_ret_uint8(sp, &is_anonymous); > if (ret == 0) { >+ if (name_len != 1) >+ ret = EINVAL; > if (is_anonymous == 1) { > *output_name = _gss_sanon_anonymous_identity; > major = GSS_S_COMPLETE; >@@ -151,9 +151,6 @@ _gss_sanon_import_name(OM_uint32 *minor, > const gss_OID input_name_type, > gss_name_t *output_name) > { >- heim_assert(input_name_type != GSS_C_NO_OID, >- "Mechglue passed null OID to _gss_sanon_import_name"); >- > if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) > return import_export_name(minor, input_name_buffer, output_name); > >diff --git a/third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c b/third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c >index 8cb4211da266..c4ac7455cf6e 100644 >--- a/third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c >+++ b/third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c >@@ -743,6 +743,7 @@ acceptor_start > } > } else { > *minor_status = 0; >+ gss_release_oid_set(&junk, &supported_mechs); > HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); > return gss_mg_set_error_string(GSS_C_NO_OID, GSS_S_NO_CONTEXT, > *minor_status, >diff --git a/third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c b/third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c >index 13e28bb59fdd..3f8aa5c3e7b1 100644 >--- a/third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c >+++ b/third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c >@@ -904,12 +904,14 @@ cleanup: > > if (GSS_ERROR(major)) { > if (!mech_error) { >- krb5_context context = _gss_mg_krb5_context(); >- >- gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, >- major, *minor, >- "NegoEx failed to initialize security context: %s", >- krb5_get_error_message(context, *minor)); >+ krb5_context context = _gss_mg_krb5_context(); >+ const char *emsg = krb5_get_error_message(context, *minor); >+ >+ gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, >+ major, *minor, >+ "NegoEx failed to initialize security context: %s", >+ emsg); >+ krb5_free_error_message(context, emsg); > } > > _gss_negoex_release_context(ctx); >@@ -1022,12 +1024,14 @@ cleanup: > > if (GSS_ERROR(major)) { > if (!mech_error) { >- krb5_context context = _gss_mg_krb5_context(); >- >- gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, >- major, *minor, >- "NegoEx failed to accept security context: %s", >- krb5_get_error_message(context, *minor)); >+ krb5_context context = _gss_mg_krb5_context(); >+ const char *emsg = krb5_get_error_message(context, *minor); >+ >+ gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, >+ major, *minor, >+ "NegoEx failed to accept security context: %s", >+ emsg); >+ krb5_free_error_message(context, emsg); > } > > _gss_negoex_release_context(ctx); >diff --git a/third_party/heimdal/lib/gssapi/test_context.c b/third_party/heimdal/lib/gssapi/test_context.c >index 30fb5cb231f7..7446d15e0df1 100644 >--- a/third_party/heimdal/lib/gssapi/test_context.c >+++ b/third_party/heimdal/lib/gssapi/test_context.c >@@ -56,6 +56,7 @@ static char *localname_string; > static char *client_name; > static char *client_password; > static char *localname_string; >+static char *on_behalf_of_string; > static int dns_canon_flag = -1; > static int mutual_auth_flag = 0; > static int dce_style_flag = 0; >@@ -134,6 +135,112 @@ string_to_oids(gss_OID_set *oidsetp, char *names) > } > } > >+static void >+show_pac_client_info(gss_name_t n) >+{ >+ gss_buffer_desc dv = GSS_C_EMPTY_BUFFER; >+ gss_buffer_desc v = GSS_C_EMPTY_BUFFER; >+ gss_buffer_desc a; >+ OM_uint32 maj, min; >+ int authenticated, complete, more, name_is_MN, found; >+ gss_OID MN_mech; >+ gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET; >+ size_t i; >+ >+ krb5_error_code ret; >+ krb5_storage *sp = NULL; >+ uint16_t len = 0, *s; >+ uint64_t tmp; >+ char *logon_string = NULL; >+ >+ maj = gss_inquire_name(&min, n, &name_is_MN, &MN_mech, &attrs); >+ if (maj != GSS_S_COMPLETE) >+ errx(1, "gss_inquire_name: %s", >+ gssapi_err(maj, min, GSS_KRB5_MECHANISM)); >+ >+ a.value = "urn:mspac:client-info"; >+ a.length = sizeof("urn:mspac:client-info") - 1; >+ >+ for (found = 0, i = 0; i < attrs->count; i++) { >+ gss_buffer_t attr = &attrs->elements[i]; >+ >+ if (attr->length == a.length && >+ memcmp(attr->value, a.value, a.length) == 0) { >+ found++; >+ break; >+ } >+ } >+ >+ gss_release_buffer_set(&min, &attrs); >+ >+ if (!found) >+ errx(1, "gss_inquire_name: attribute %.*s not enumerated", >+ (int)a.length, (char *)a.value); >+ >+ more = 0; >+ maj = gss_get_name_attribute(&min, n, &a, &authenticated, &complete, &v, >+ &dv, &more); >+ if (maj != GSS_S_COMPLETE) >+ errx(1, "gss_get_name_attribute: %s", >+ gssapi_err(maj, min, GSS_KRB5_MECHANISM)); >+ >+ >+ sp = krb5_storage_from_readonly_mem(v.value, v.length); >+ if (sp == NULL) >+ errx(1, "show_pac_client_info: out of memory"); >+ >+ krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); >+ >+ ret = krb5_ret_uint64(sp, &tmp); /* skip over time */ >+ if (ret == 0) >+ ret = krb5_ret_uint16(sp, &len); >+ if (ret || len == 0) >+ errx(1, "show_pac_client_info: invalid PAC logon info length"); >+ >+ s = malloc(len); >+ ret = krb5_storage_read(sp, s, len); >+ if (ret != len) >+ errx(1, "show_pac_client_info:, failed to read PAC logon name"); >+ >+ krb5_storage_free(sp); >+ >+ { >+ size_t ucs2len = len / 2; >+ uint16_t *ucs2; >+ size_t u8len; >+ unsigned int flags = WIND_RW_LE; >+ >+ ucs2 = malloc(sizeof(ucs2[0]) * ucs2len); >+ if (ucs2 == NULL) >+ errx(1, "show_pac_client_info: out of memory"); >+ >+ ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len); >+ free(s); >+ if (ret) >+ errx(1, "failed to convert string to UCS-2"); >+ >+ ret = wind_ucs2utf8_length(ucs2, ucs2len, &u8len); >+ if (ret) >+ errx(1, "failed to count length of UCS-2 string"); >+ >+ u8len += 1; /* Add space for NUL */ >+ logon_string = malloc(u8len); >+ if (logon_string == NULL) >+ errx(1, "show_pac_client_info: out of memory"); >+ >+ ret = wind_ucs2utf8(ucs2, ucs2len, logon_string, &u8len); >+ free(ucs2); >+ if (ret) >+ errx(1, "failed to convert to UTF-8"); >+ } >+ >+ printf("logon name: %s\n", logon_string); >+ free(logon_string); >+ >+ gss_release_buffer(&min, &dv); >+ gss_release_buffer(&min, &v); >+} >+ > static void > loop(gss_OID mechoid, > gss_OID nameoid, const char *target, >@@ -155,12 +262,15 @@ loop(gss_OID mechoid, > OM_uint32 flags = 0, ret_cflags = 0, ret_sflags = 0; > gss_OID actual_mech_client = GSS_C_NO_OID; > gss_OID actual_mech_server = GSS_C_NO_OID; >- struct gss_channel_bindings_struct i_channel_bindings_data = {0}; >- struct gss_channel_bindings_struct a_channel_bindings_data = {0}; >+ struct gss_channel_bindings_struct i_channel_bindings_data; >+ struct gss_channel_bindings_struct a_channel_bindings_data; > gss_channel_bindings_t i_channel_bindings_p = GSS_C_NO_CHANNEL_BINDINGS; > gss_channel_bindings_t a_channel_bindings_p = GSS_C_NO_CHANNEL_BINDINGS; > size_t offset = 0; > >+ memset(&i_channel_bindings_data, 0, sizeof(i_channel_bindings_data)); >+ memset(&a_channel_bindings_data, 0, sizeof(a_channel_bindings_data)); >+ > *actual_mech = GSS_C_NO_OID; > > flags |= GSS_C_REPLAY_FLAG; >@@ -188,6 +298,32 @@ loop(gss_OID mechoid, > if (GSS_ERROR(maj_stat)) > err(1, "import name creds failed with: %d", maj_stat); > >+ if (on_behalf_of_string) { >+ AuthorizationDataElement e; >+ gss_buffer_desc attr, value; >+ int32_t kret; >+ size_t sz; >+ >+ memset(&e, 0, sizeof(e)); >+ e.ad_type = KRB5_AUTHDATA_ON_BEHALF_OF; >+ e.ad_data.length = strlen(on_behalf_of_string); >+ e.ad_data.data = on_behalf_of_string; >+ ASN1_MALLOC_ENCODE(AuthorizationDataElement, value.value, value.length, >+ &e, &sz, kret); >+ if (kret) >+ errx(1, "Could not encode AD-ON-BEHALF-OF AuthorizationDataElement"); >+ attr.value = >+ GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authenticator-authz-data"; >+ attr.length = >+ sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authenticator-authz-data") - 1; >+ maj_stat = gss_set_name_attribute(&min_stat, gss_target_name, 1, &attr, >+ &value); >+ if (maj_stat != GSS_S_COMPLETE) >+ errx(1, "gss_set_name_attribute() failed with: %s", >+ gssapi_err(maj_stat, min_stat, GSS_KRB5_MECHANISM)); >+ free(value.value); >+ } >+ > input_token.length = 0; > input_token.value = NULL; > >@@ -351,6 +487,25 @@ loop(gss_OID mechoid, > errx(1, "mech mismatch"); > *actual_mech = actual_mech_server; > >+ if (on_behalf_of_string) { >+ gss_buffer_desc attr, value; >+ >+ attr.value = >+ GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authz-data#580"; >+ attr.length = >+ sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authz-data#580") - 1; >+ maj_stat = gss_get_name_attribute(&min_stat, src_name, &attr, NULL, >+ NULL, &value, NULL, NULL); >+ if (maj_stat != GSS_S_COMPLETE) >+ errx(1, "gss_get_name_attribute(authz-data#580) failed with %s", >+ gssapi_err(maj_stat, min_stat, GSS_KRB5_MECHANISM)); >+ >+ if (value.length != strlen(on_behalf_of_string) || >+ strncmp(value.value, on_behalf_of_string, >+ strlen(on_behalf_of_string)) != 0) >+ errx(1, "AD-ON-BEHALF-OF did not match"); >+ (void) gss_release_buffer(&min_stat, &value); >+ } > if (localname_string) { > gss_buffer_desc lname; > >@@ -393,6 +548,9 @@ loop(gss_OID mechoid, > } else > warnx("display_name: %s", > gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); >+ if (!anon_flag && >+ gss_oid_equal(actual_mech_server, GSS_KRB5_MECHANISM)) >+ show_pac_client_info(src_name); > } > gss_release_name(&min_stat, &src_name); > >@@ -756,6 +914,8 @@ static struct getargs args[] = { > {"server-time-offset", 0, arg_integer, &server_time_offset, "time", NULL }, > {"max-loops", 0, arg_integer, &max_loops, "time", NULL }, > {"token-split", 0, arg_integer, &token_split, "bytes", NULL }, >+ {"on-behalf-of", 0, arg_string, &on_behalf_of_string, "principal", >+ "send authenticator authz-data AD-ON-BEHALF-OF" }, > {"version", 0, arg_flag, &version_flag, "print version", NULL }, > {"verbose", 'v', arg_flag, &verbose_flag, "verbose", NULL }, > {"help", 0, arg_flag, &help_flag, NULL, NULL } >@@ -1102,7 +1262,7 @@ main(int argc, char **argv) > > if (maj_stat != GSS_S_COMPLETE) > keyblock2 = NULL; >- else if (limit_enctype && keyblock->keytype != limit_enctype) >+ else if (limit_enctype && keyblock && keyblock->keytype != limit_enctype) > errx(1, "gsskrb5_get_subkey wrong enctype"); > > if (keyblock || keyblock2) { >@@ -1130,7 +1290,7 @@ main(int argc, char **argv) > if (ret) > krb5_err(context, 1, ret, "krb5_string_to_enctype"); > >- if (enctype != keyblock->keytype) >+ if (keyblock && enctype != keyblock->keytype) > errx(1, "keytype is not the expected %d != %d", > (int)enctype, (int)keyblock2->keytype); > } >diff --git a/third_party/heimdal/lib/gssapi/test_kcred.c b/third_party/heimdal/lib/gssapi/test_kcred.c >index 866ee78ecf1f..abfe390449d9 100644 >--- a/third_party/heimdal/lib/gssapi/test_kcred.c >+++ b/third_party/heimdal/lib/gssapi/test_kcred.c >@@ -102,10 +102,17 @@ copy_import(void) > if (!equal) > errx(1, "names not equal"); > >- /* FIXME: This check is racy! */ >- if (lifetime1 != lifetime2) >+ /* >+ * This check is racy! It tends to fail when run with valgrind. >+ * >+ * make check-valgrind sets TESTS_ENVIRONMENT in the environment... >+ */ >+ if (getenv("TESTS_ENVIRONMENT") == NULL && lifetime1 != lifetime2) > errx(1, "lifetime not equal %lu != %lu", > (unsigned long)lifetime1, (unsigned long)lifetime2); >+ if (lifetime1 != lifetime2) >+ warnx("lifetime not equal %lu != %lu", >+ (unsigned long)lifetime1, (unsigned long)lifetime2); > > if (usage1 != usage2) { > /* as long any of them is both are everything it ok */ >@@ -127,10 +134,13 @@ copy_import(void) > if (!equal) > errx(1, "names not equal"); > >- /* FIXME: This check is racy! */ >- if (lifetime1 != lifetime2) >+ /* This check is racy! */ >+ if (getenv("TESTS_ENVIRONMENT") == NULL && lifetime1 != lifetime2) > errx(1, "lifetime not equal %lu != %lu", > (unsigned long)lifetime1, (unsigned long)lifetime2); >+ if (lifetime1 != lifetime2) >+ warnx("lifetime not equal %lu != %lu", >+ (unsigned long)lifetime1, (unsigned long)lifetime2); > > gss_release_cred(&min_stat, &cred1); > gss_release_cred(&min_stat, &cred2); >diff --git a/third_party/heimdal/lib/gssapi/test_names.c b/third_party/heimdal/lib/gssapi/test_names.c >index e195313505c4..933635e78c01 100644 >--- a/third_party/heimdal/lib/gssapi/test_names.c >+++ b/third_party/heimdal/lib/gssapi/test_names.c >@@ -43,42 +43,286 @@ > #include <gssapi.h> > #include <gssapi_krb5.h> > #include <gssapi_spnego.h> >+#include <krb5_asn1.h> > #include <err.h> > #include <getarg.h> > >+static void make_composite_name(CompositePrincipal *, gss_name_t *); >+static void assert_attr(gss_name_t, const char *, OM_uint32, gss_buffer_t, >+ const char *, int, int, int); >+static void assert_attr_unavail(gss_name_t, const char *); >+static void assert_attr_set(gss_name_t, gss_buffer_set_t); >+ > static void >-gss_print_errors (int min_stat) >+gss_print_errors(OM_uint32 stat, gss_OID mech) > { >- OM_uint32 new_stat; >- OM_uint32 msg_ctx = 0; >- gss_buffer_desc status_string; >+ OM_uint32 junk; >+ OM_uint32 more = 0; >+ gss_buffer_desc buf = GSS_C_EMPTY_BUFFER; > OM_uint32 ret; > >+ if (mech) { >+ junk = gss_oid_to_str(&junk, mech, &buf); >+ if (junk == GSS_S_COMPLETE) >+ fprintf(stderr, "mech = %.*s\n", (int)buf.length, (char *)buf.value); >+ gss_release_buffer(&junk, &buf); >+ } > do { >- ret = gss_display_status (&new_stat, >- min_stat, >- GSS_C_MECH_CODE, >- GSS_C_NO_OID, >- &msg_ctx, >- &status_string); >- if (!GSS_ERROR(ret)) { >- fprintf (stderr, "%.*s\n", (int)status_string.length, >- (char *)status_string.value); >- gss_release_buffer (&new_stat, &status_string); >- } >- } while (!GSS_ERROR(ret) && msg_ctx != 0); >+ ret = gss_display_status(&junk, >+ stat, >+ mech ? GSS_C_MECH_CODE : GSS_C_GSS_CODE, >+ mech, >+ &more, >+ &buf); >+ if (ret != GSS_S_COMPLETE) >+ errx(1, "gss_display_status() failed"); >+ fprintf(stderr, "%.*s\n", (int)buf.length, (char *)buf.value); >+ gss_release_buffer(&junk, &buf); >+ } while (more); > } > > static void >-gss_err(int exitval, int status, const char *fmt, ...) >+ __attribute__ ((__format__ (__printf__, 5, 6))) >+gss_err(int exitval, >+ OM_uint32 maj, >+ OM_uint32 min, >+ gss_OID mech, >+ const char *fmt, ...) > { > va_list args; > > va_start(args, fmt); >- vwarnx (fmt, args); >- gss_print_errors (status); >+ vwarnx(fmt, args); > va_end(args); >- exit (exitval); >+ gss_print_errors(maj, GSS_C_NO_OID); >+ if (mech) >+ gss_print_errors(min, mech); >+ exit(exitval); >+} >+ >+#define MAKE_URN(tail) \ >+ { sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN tail) - 1, \ >+ GSS_KRB5_NAME_ATTRIBUTE_BASE_URN tail } >+ >+/* >+ * Test RFC6680 name attributes for Kerberos. >+ */ >+static void >+check_name_attrs(void) >+{ >+ CompositePrincipal p; >+ EncTicketPart *t; >+ gss_buffer_desc v = GSS_C_EMPTY_BUFFER; >+ gss_name_t n; >+ OM_uint32 maj, min; >+ int32_t ret; >+ gss_buffer_desc attrs[] = { >+ MAKE_URN("realm"), >+ MAKE_URN("name-ncomp"), >+ MAKE_URN("name-ncomp#0"), >+ MAKE_URN("peer-realm"), >+ MAKE_URN("ticket-authz-data"), >+ MAKE_URN("transit-path"), >+ MAKE_URN("canonical-name"), >+ }; /* Set of attributes we expect to see indicated */ >+ gss_buffer_set_desc attr_set; >+ size_t i, sz; >+ >+ memset(&p, 0, sizeof(p)); >+ attr_set.elements = attrs; >+ /* >+ * attr_set.count is set in each of the following sections to ever more >+ * items. >+ */ >+ >+ /* >+ * Testing name attributes is pretty tricky. >+ * >+ * Our approach is to construct a composite name, construct an exported >+ * composite name token for it, import it, then test the gss_inquire_name() >+ * and gss_get_name_attribute() accessors, and then gss_display_name_ext(). >+ * >+ * Ideally we'd test the accessors on names imported from query forms with >+ * gss_import_name(), and on names from established contexts. However, >+ * that belongs in the test_context program. >+ * >+ * TODO: Implement and test gss_set_name_attribute() and >+ * gss_delete_name_attribute(). >+ */ >+ >+ /* First construct and test an unauthenticated name */ >+ p.realm = estrdup("TEST.H5L.SE"); >+ p.name.name_type = KRB5_NT_PRINCIPAL; >+ p.name.name_string.val = ecalloc(1, sizeof(p.name.name_string.val[0])); >+ p.name.name_string.len = 1; >+ p.name.name_string.val[0] = estrdup("someuser"); >+ p.nameattrs = NULL; >+ make_composite_name(&p, &n); >+ >+ /* Test the attributes we expect it to have */ >+ v.length = sizeof("TEST.H5L.SE") - 1; >+ v.value = "TEST.H5L.SE"; >+ assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "realm", GSS_S_COMPLETE, >+ &v, "TEST.H5L.SE", 0, 1, 0); >+ >+ i = 1; >+ v.length = sizeof(size_t); >+ v.value = &i; >+ assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp", >+ GSS_S_COMPLETE, &v, "1", 0, 1, 0); >+ >+ v.length = sizeof("someuser") - 1; >+ v.value = "someuser"; >+ assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#0", >+ GSS_S_COMPLETE, &v, "someuser", 0, 1, 0); >+ >+ attr_set.count = 3; >+ assert_attr_set(n, &attr_set); >+ >+ /* Check that it does not have prefixed attributes */ >+ assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN >+ "realm"); >+ assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN >+ "name-ncomp"); >+ assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN >+ "name-ncomp#0"); >+ assert_attr_unavail(n, "what ever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN >+ "name-ncomp#0"); >+ >+ /* Check that it does not have various other supported attributes */ >+ assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "peer-realm"); >+ assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#1"); >+ assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "canonical-name"); >+ assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN >+ "ticket-authz-data#pac"); >+ assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN >+ "ticket-authz-data"); >+ assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "transit-path"); >+ >+ /* Exercise URN parser */ >+ assert_attr_unavail(n, "urn:whatever"); >+ assert_attr_unavail(n, "urn:whatever#"); >+ assert_attr_unavail(n, "urn:what#ever"); >+ assert_attr_unavail(n, "#"); >+ assert_attr_unavail(n, "#whatever"); >+ assert_attr_unavail(n, "whatever"); >+ assert_attr_unavail(n, "what ever"); >+ assert_attr_unavail(n, "what ever#"); >+ >+ /* Now test an authenticated name */ >+ gss_release_name(&min, &n); >+ p.nameattrs = ecalloc(1, sizeof(p.nameattrs[0])); >+ p.nameattrs->authenticated = 1; >+ make_composite_name(&p, &n); >+ >+ v.length = sizeof("TEST.H5L.SE") - 1; >+ v.value = "TEST.H5L.SE"; >+ assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "realm", GSS_S_COMPLETE, >+ &v, "TEST.H5L.SE", 1, 1, 0); >+ >+ i = 1; >+ v.length = sizeof(size_t); >+ v.value = &i; >+ assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp", >+ GSS_S_COMPLETE, &v, "1", 1, 1, 0); >+ >+ v.length = sizeof("someuser") - 1; >+ v.value = "someuser"; >+ assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#0", >+ GSS_S_COMPLETE, &v, "someuser", 1, 1, 0); >+ >+ assert_attr_set(n, &attr_set); >+ >+ /* Now add a peer realm */ >+ gss_release_name(&min, &n); >+ p.nameattrs->peer_realm = ecalloc(1, sizeof(p.nameattrs->peer_realm[0])); >+ p.nameattrs->peer_realm[0] = estrdup("FOO.TEST.H5L.SE"); >+ make_composite_name(&p, &n); >+ >+ v.length = sizeof("FOO.TEST.H5L.SE") - 1; >+ v.value = "FOO.TEST.H5L.SE"; >+ assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "peer-realm", >+ GSS_S_COMPLETE, &v, "FOO.TEST.H5L.SE", 1, 1, 0); >+ attr_set.count = 4; >+ assert_attr_set(n, &attr_set); >+ >+ /* Now add canonical name and an authz-data element */ >+ gss_release_name(&min, &n); >+ p.nameattrs->source = ecalloc(1, sizeof(p.nameattrs->source[0])); >+ p.nameattrs->source->element = choice_PrincipalNameAttrSrc_enc_ticket_part; >+ >+ t = &p.nameattrs->source->u.enc_ticket_part; >+ t->cname.name_type = KRB5_NT_PRINCIPAL; >+ t->cname.name_string.val = ecalloc(1, sizeof(t->cname.name_string.val[0])); >+ t->crealm = estrdup("TEST.H5L.SE"); >+ t->cname.name_string.len = 1; >+ t->cname.name_string.val[0] = estrdup("realusername"); >+ t->authorization_data = ecalloc(1, sizeof(t->authorization_data[0])); >+ t->authorization_data->val = >+ ecalloc(1, sizeof(t->authorization_data->val[0])); >+ t->authorization_data->len = 1; >+ t->authorization_data->val[0].ad_type = >+ KRB5_AUTHDATA_ON_BEHALF_OF; /* whatever */ >+ t->authorization_data->val[0].ad_data.data = >+ estrdup("foobar@TEST.H5L.SE"); >+ t->authorization_data->val[0].ad_data.length = >+ sizeof("foobar@TEST.H5L.SE") - 1; >+ make_composite_name(&p, &n); >+ >+ assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "canonical-name", >+ GSS_S_COMPLETE, GSS_C_NO_BUFFER, "realusername@TEST.H5L.SE", 1, >+ 1, 0); >+ >+ ASN1_MALLOC_ENCODE(AuthorizationData, v.value, v.length, >+ t->authorization_data, &sz, ret); >+ if (ret) >+ errx(1, "Failed to encode AuthorizationData"); >+ >+ assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "ticket-authz-data", >+ GSS_S_COMPLETE, &v, NULL, 0, 1, 0); >+ free(v.value); >+ >+ attr_set.count = 7; >+ assert_attr_set(n, &attr_set); >+ >+ gss_release_name(&min, &n); >+ free_CompositePrincipal(&p); >+ >+ /* >+ * Test gss_display_name_ext() with a host-based service principal >+ * "host/somehost.test.h5l.se@TEST.H5L.SE". >+ * >+ * Where gss_display_name() would display this as a Kerberos principal >+ * name, gss_display_name_ext() with GSS_C_NT_HOSTBASED_SERVICE should >+ * display it as "host@somehost.test.h5l.se". >+ */ >+ p.realm = estrdup("TEST.H5L.SE"); >+ p.name.name_type = KRB5_NT_SRV_HST; >+ p.name.name_string.val = ecalloc(2, sizeof(p.name.name_string.val[0])); >+ p.name.name_string.len = 2; >+ p.name.name_string.val[0] = estrdup("host"); >+ p.name.name_string.val[1] = estrdup("somehost.test.h5l.se"); >+ p.nameattrs = NULL; >+ make_composite_name(&p, &n); >+ >+ maj = gss_display_name_ext(&min, n, GSS_C_NT_HOSTBASED_SERVICE, &v); >+ if (maj) >+ gss_err(1, maj, min, GSS_KRB5_MECHANISM, "display name ext"); >+ if (v.length != sizeof("host@somehost.test.h5l.se") - 1 || >+ strncmp(v.value, "host@somehost.test.h5l.se", v.length) != 0) >+ errx(1, "display name ext"); >+ gss_release_buffer(&min, &v); >+ gss_release_name(&min, &n); >+ free_CompositePrincipal(&p); >+ >+ /* >+ * TODO: >+ * >+ * - test URN fragments for access to specific authorization data element >+ * types >+ * - test GSS_C_ATTR_LOCAL_LOGIN_USER support (requires configuration or >+ * that we register a plugin here) >+ */ > } > > static int version_flag = 0; >@@ -145,7 +389,7 @@ main(int argc, char **argv) > GSS_C_NT_HOSTBASED_SERVICE, > &name); > if (maj_stat != GSS_S_COMPLETE) >- gss_err(1, min_stat, "import name error"); >+ gss_err(1, maj_stat, min_stat, GSS_C_NO_OID, "import name error"); > free(str); > > if (anon_flag) >@@ -158,13 +402,13 @@ main(int argc, char **argv) > mech_oid, > &MNname); > if (maj_stat != GSS_S_COMPLETE) >- gss_err(1, min_stat, "canonicalize name error"); >+ gss_err(1, maj_stat, min_stat, mech_oid, "canonicalize name error"); > > maj_stat = gss_export_name(&min_stat, > MNname, > &name_buffer); > if (maj_stat != GSS_S_COMPLETE) >- gss_err(1, min_stat, "export name error (KRB5)"); >+ gss_err(1, maj_stat, min_stat, mech_oid, "export name error"); > > /* > * Import the exported name and compare >@@ -174,13 +418,13 @@ main(int argc, char **argv) > GSS_C_NT_EXPORT_NAME, > &MNname2); > if (maj_stat != GSS_S_COMPLETE) >- gss_err(1, min_stat, "import name error (exported KRB5 name)"); >+ gss_err(1, maj_stat, min_stat, mech_oid, "export name error"); > > > maj_stat = gss_compare_name(&min_stat, MNname, MNname2, &equal); > if (maj_stat != GSS_S_COMPLETE) >- errx(1, "gss_compare_name"); >- if (equal == anon_flag) >+ gss_err(1, maj_stat, min_stat, mech_oid, "compare name error"); >+ if (equal && anon_flag) > errx(1, "names %s equal", anon_flag ? "incorrectly" : "not"); > > gss_release_name(&min_stat, &MNname2); >@@ -205,13 +449,13 @@ main(int argc, char **argv) > GSS_C_NO_OID, > &name); > if (maj_stat != GSS_S_COMPLETE) >- gss_err(1, min_stat, "import (no oid) name error"); >+ gss_err(1, maj_stat, min_stat, NULL, "import (no oid) name error"); > > maj_stat = gss_import_name(&min_stat, &name_buffer, > GSS_KRB5_NT_USER_NAME, > &MNname); > if (maj_stat != GSS_S_COMPLETE) >- gss_err(1, min_stat, "import (krb5 mn) name error"); >+ gss_err(1, maj_stat, min_stat, NULL, "import (krb5 mn) name error"); > > free(str); > >@@ -230,14 +474,16 @@ main(int argc, char **argv) > GSS_SPNEGO_MECHANISM, > &MNname); > if (maj_stat != GSS_S_COMPLETE) >- gss_err(1, min_stat, "canonicalize name error"); >+ gss_err(1, maj_stat, min_stat, GSS_SPNEGO_MECHANISM, >+ "canonicalize name error"); > > > maj_stat = gss_export_name(&maj_stat, > MNname, > &name_buffer); > if (maj_stat != GSS_S_COMPLETE) >- gss_err(1, min_stat, "export name error (SPNEGO)"); >+ gss_err(1, maj_stat, min_stat, GSS_SPNEGO_MECHANISM, >+ "export name error (SPNEGO)"); > > gss_release_name(&min_stat, &MNname); > gss_release_buffer(&min_stat, &name_buffer); >@@ -253,29 +499,177 @@ main(int argc, char **argv) > maj_stat = gss_import_name(&min_stat, &name_buffer, > GSS_C_NT_ANONYMOUS, &name); > if (maj_stat != GSS_S_COMPLETE) >- gss_err(1, min_stat, "import (anon) name error"); >+ gss_err(1, maj_stat, min_stat, GSS_C_NO_OID, >+ "import (anon) name error"); > > maj_stat = gss_canonicalize_name(&min_stat, name, > GSS_SANON_X25519_MECHANISM, > &MNname); > if (maj_stat != GSS_S_COMPLETE) >- gss_err(1, min_stat, "canonicalize (anon) name error"); >+ gss_err(1, maj_stat, min_stat, GSS_SANON_X25519_MECHANISM, >+ "canonicalize (anon) name error"); > > maj_stat = gss_display_name(&min_stat, MNname, > &name_buffer, &name_type); > if (maj_stat != GSS_S_COMPLETE) >- gss_err(1, min_stat, "display_name (anon) name error"); >+ gss_err(1, maj_stat, min_stat, GSS_SANON_X25519_MECHANISM, >+ "display_name (anon) name error"); > > if (!gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS)) >- gss_err(1, 0, "display name type not anonymous"); >+ errx(1, "display name type not anonymous"); > if (memcmp(name_buffer.value, "WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS", > sizeof("WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS") - 1) != 0) >- gss_err(1, 0, "display name string not well known anonymous name"); >+ errx(1, "display name string not well known anonymous name"); > > gss_release_name(&min_stat, &MNname); > gss_release_name(&min_stat, &name); > gss_release_buffer(&min_stat, &name_buffer); > } > >+ check_name_attrs(); > return 0; > } >+ >+/* Copied from _gsskrb5_export_name_composite() */ >+static void >+export_name_composite(CompositePrincipal *name, gss_buffer_t exported_name) >+{ >+ gss_buffer_desc inner = GSS_C_EMPTY_BUFFER; >+ unsigned char *buf; >+ int32_t ret; >+ size_t sz; >+ >+ ASN1_MALLOC_ENCODE(CompositePrincipal, inner.value, inner.length, >+ (void *)name, &sz, ret); >+ if (ret) >+ errx(1, "Failed to encode exported composite name token"); >+ >+ exported_name->length = 10 + inner.length + GSS_KRB5_MECHANISM->length; >+ exported_name->value = malloc(exported_name->length); >+ if (exported_name->value == NULL) >+ errx(1, "Failed to allocate exported composite name token"); >+ >+ /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ >+ >+ buf = exported_name->value; >+ buf[0] = 0x04; >+ buf[1] = 0x02; >+ buf[2] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff; >+ buf[3] = (GSS_KRB5_MECHANISM->length + 2) & 0xff; >+ buf[4] = 0x06; >+ buf[5] = (GSS_KRB5_MECHANISM->length) & 0xFF; >+ >+ memcpy(buf + 6, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); >+ buf += 6 + GSS_KRB5_MECHANISM->length; >+ >+ buf[0] = (inner.length >> 24) & 0xff; >+ buf[1] = (inner.length >> 16) & 0xff; >+ buf[2] = (inner.length >> 8) & 0xff; >+ buf[3] = (inner.length) & 0xff; >+ buf += 4; >+ >+ memcpy(buf, inner.value, inner.length); >+ free(inner.value); >+} >+ >+static void >+make_composite_name(CompositePrincipal *princ, gss_name_t *n) >+{ >+ gss_buffer_desc token, exported; >+ OM_uint32 maj, min; >+ >+ export_name_composite(princ, &token); >+ maj = gss_import_name(&min, &token, GSS_C_NT_COMPOSITE_EXPORT, n); >+ if (maj) >+ gss_err(1, maj, min, GSS_KRB5_MECHANISM, "import composite name"); >+ maj = gss_export_name_composite(&min, *n, &exported); >+ if (maj) >+ gss_err(1, maj, min, GSS_KRB5_MECHANISM, "export composite name"); >+ if (token.length != exported.length || >+ memcmp(token.value, exported.value, token.length) != 0) >+ errx(1, "import/export composite token disagreement"); >+ gss_release_buffer(&min, &exported); >+ free(token.value); /* Use free because we allocated this one */ >+} >+ >+static void >+assert_attr(gss_name_t n, >+ const char *aname, >+ OM_uint32 exp_maj, >+ gss_buffer_t exp_v, >+ const char *exp_dv, >+ int exp_authenticated, >+ int exp_complete, >+ int exp_multivalued) >+{ >+ gss_buffer_desc dv = GSS_C_EMPTY_BUFFER; >+ gss_buffer_desc v = GSS_C_EMPTY_BUFFER; >+ gss_buffer_desc a; >+ OM_uint32 maj, min; >+ int authenticated, complete, more; >+ >+ a.value = (void*)(uintptr_t)aname; >+ a.length = strlen(aname); >+ more = 0; >+ maj = gss_get_name_attribute(&min, n, &a, &authenticated, &complete, &v, >+ &dv, &more); >+ if (maj != GSS_S_COMPLETE && maj != exp_maj) >+ gss_err(1, maj, min, GSS_KRB5_MECHANISM, >+ "import composite name error"); >+ if (maj == GSS_S_COMPLETE && maj != exp_maj) >+ errx(1, "unexpected name attribute %s", aname); >+ if (maj == GSS_S_COMPLETE) { >+ if (exp_v && >+ (v.length != exp_v->length || >+ memcmp(v.value, exp_v->value, exp_v->length) != 0)) >+ errx(1, "import composite name: wrong %s value", aname); >+ if (exp_dv && >+ (dv.length != strlen(exp_dv) || >+ strncmp(dv.value, exp_dv, dv.length) != 0)) >+ errx(1, "import composite name: wrong %s display value " >+ "(wanted %s, got %.*s)", aname, exp_dv, >+ (int)dv.length, (char *)dv.value); >+ if (authenticated != exp_authenticated) >+ errx(1, "import composite name: %s incorrectly marked " >+ "%sauthenticated", aname, authenticated ? "" : "un"); >+ if (complete != exp_complete) >+ errx(1, "import composite name: %s incorrectly marked " >+ "%scomplete", aname, complete ? "" : "in"); >+ if (more != exp_multivalued) >+ errx(1, "import composite name: %s incorrectly marked " >+ "%s-valued", aname, more ? "multi" : "single"); >+ } >+ gss_release_buffer(&min, &dv); >+ gss_release_buffer(&min, &v); >+} >+ >+static void >+assert_attr_unavail(gss_name_t n, const char *aname) >+{ >+ assert_attr(n, aname, GSS_S_UNAVAILABLE, GSS_C_NO_BUFFER, NULL, 0, 0, 0); >+} >+ >+static void >+assert_attr_set(gss_name_t n, gss_buffer_set_t exp_as) >+{ >+ OM_uint32 maj, min; >+ gss_buffer_set_t as = NULL; >+ gss_OID MN_mech = GSS_C_NO_OID; >+ size_t i; >+ int name_is_MN = 0; >+ >+ maj = gss_inquire_name(&min, n, &name_is_MN, &MN_mech, &as); >+ if (maj) >+ gss_err(1, maj, min, MN_mech, "inquire name"); >+ for (i = 0; i < as->count && i < exp_as->count; i++) { >+ if (as->elements[i].length != exp_as->elements[i].length || >+ memcmp(as->elements[i].value, exp_as->elements[i].value, >+ as->elements[i].length) != 0) >+ errx(1, "attribute sets differ"); >+ } >+ if (i < as->count) >+ errx(1, "more attributes indicated than expected"); >+ if (i < exp_as->count) >+ errx(1, "fewer attributes indicated than expected"); >+ gss_release_buffer_set(&min, &as); >+} >diff --git a/third_party/heimdal/lib/gssapi/version-script.map b/third_party/heimdal/lib/gssapi/version-script.map >index be266da773c4..7f482b536240 100644 >--- a/third_party/heimdal/lib/gssapi/version-script.map >+++ b/third_party/heimdal/lib/gssapi/version-script.map >@@ -4,6 +4,7 @@ HEIMDAL_GSS_2.0 { > global: > # __gss_c_nt_anonymous; > __gss_c_nt_anonymous_oid_desc; >+ __gss_c_nt_composite_export_oid_desc; > __gss_c_nt_export_name_oid_desc; > __gss_c_nt_hostbased_service_oid_desc; > __gss_c_nt_hostbased_service_x_oid_desc; >@@ -44,7 +45,6 @@ HEIMDAL_GSS_2.0 { > gss_export_name; > gss_export_name_composite; > gss_export_sec_context; >- gss_get_instance; > gss_get_mic; > gss_get_neg_mechs; > gss_get_name_attribute; >diff --git a/third_party/heimdal/lib/hcrypto/Makefile.am b/third_party/heimdal/lib/hcrypto/Makefile.am >index 1c610829feb3..bb36f7451907 100644 >--- a/third_party/heimdal/lib/hcrypto/Makefile.am >+++ b/third_party/heimdal/lib/hcrypto/Makefile.am >@@ -16,6 +16,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/lib/hx509 \ > WFLAGS += $(WFLAGS_LITE) -Wno-error=unused-function > # XXX: Make these not necessary: > WFLAGS += -Wno-error=unused-result -Wno-error=deprecated-declarations >+WFLAGS += $(WFLAGS_UNUSED_BUT_SET_VAR) > > lib_LTLIBRARIES = libhcrypto.la > check_LTLIBRARIES = libhctest.la >@@ -60,8 +61,7 @@ hcryptoinclude_HEADERS = \ > rsa.h \ > sha.h \ > ui.h \ >- undef.h \ >- x25519_ref10.h >+ undef.h > > install-build-headers:: $(hcryptoinclude_HEADERS) $(x25519include_HEADERS) > @foo='$(hcryptoinclude_HEADERS)'; \ >@@ -103,6 +103,22 @@ SCRIPT_TESTS = \ > > noinst_PROGRAMS = test_rand > >+noinst_HEADERS = \ >+ x25519/ed25519_ref10_fe_51.h \ >+ x25519/ed25519_ref10_fe_25_5.h \ >+ x25519/ed25519_ref10.h \ >+ x25519/fe_25_5/base.h \ >+ x25519/fe_25_5/base2.h \ >+ x25519/fe_25_5/constants.h \ >+ x25519/fe_25_5/fe.h \ >+ x25519/fe_51/base.h \ >+ x25519/fe_51/base2.h \ >+ x25519/fe_51/constants.h \ >+ x25519/fe_51/fe.h \ >+ x25519/align.h \ >+ x25519_ref10.h >+ >+ > check_PROGRAMS = $(PROGRAM_TESTS) test_rsa test_dh example_evp_cipher > check_SCRIPTS = $(SCRIPT_TESTS) > >@@ -335,7 +351,12 @@ ltmsources = \ > libtommath/bn_s_mp_sqr_fast.c \ > libtommath/bn_s_mp_sub.c \ > libtommath/bn_s_mp_toom_mul.c \ >- libtommath/bn_s_mp_toom_sqr.c >+ libtommath/bn_s_mp_toom_sqr.c \ >+ libtommath/tommath_private.h \ >+ libtommath/tommath_cutoffs.h \ >+ libtommath/tommath_superclass.h \ >+ libtommath/tommath_class.h \ >+ libtommath/tommath.h > > x25519sources = \ > x25519/ed25519_ref10.c \ >diff --git a/third_party/heimdal/lib/hcrypto/bn.c b/third_party/heimdal/lib/hcrypto/bn.c >index 15bf78738adf..62297b145f10 100644 >--- a/third_party/heimdal/lib/hcrypto/bn.c >+++ b/third_party/heimdal/lib/hcrypto/bn.c >@@ -142,7 +142,8 @@ BN_bin2bn(const void *s, int len, BIGNUM *bn) > return NULL; > } > hi->length = len; >- memcpy(hi->data, s, len); >+ if (len) >+ memcpy(hi->data, s, len); > return (BIGNUM *)hi; > } > >@@ -250,7 +251,7 @@ BN_set_bit(BIGNUM *bn, int bit) > unsigned char *p; > > if ((bit / 8) > hi->length || hi->length == 0) { >- size_t len = (bit + 7) / 8; >+ size_t len = bit == 0 ? 1 : (bit + 7) / 8; > void *d = realloc(hi->data, len); > if (d == NULL) > return 0; >@@ -286,6 +287,9 @@ BN_set_word(BIGNUM *bn, unsigned long num) > unsigned long num2; > int i, len; > >+ if (bn == NULL) >+ return 0; >+ > for (num2 = num, i = 0; num2 > 0; i++) > num2 = num2 >> 8; > >diff --git a/third_party/heimdal/lib/hcrypto/des.c b/third_party/heimdal/lib/hcrypto/des.c >index 9f5c648ec945..ac174180fb92 100644 >--- a/third_party/heimdal/lib/hcrypto/des.c >+++ b/third_party/heimdal/lib/hcrypto/des.c >@@ -728,6 +728,7 @@ DES_cfb64_encrypt(const void *in, void *out, > int i = *num; > unsigned char c; > >+ memset(tmp, 0, DES_CBLOCK_LEN); > while (length > 0) { > if (i == 0) { > DES_encrypt(uiv, ks, 1); >diff --git a/third_party/heimdal/lib/hcrypto/dh-ltm.c b/third_party/heimdal/lib/hcrypto/dh-ltm.c >index 774f0e1176ab..720662199f99 100644 >--- a/third_party/heimdal/lib/hcrypto/dh-ltm.c >+++ b/third_party/heimdal/lib/hcrypto/dh-ltm.c >@@ -40,7 +40,7 @@ > > #include "tommath.h" > >-static void >+static int > BN2mpz(mp_int *s, const BIGNUM *bn) > { > size_t len; >@@ -49,8 +49,12 @@ BN2mpz(mp_int *s, const BIGNUM *bn) > len = BN_num_bytes(bn); > p = malloc(len); > BN_bn2bin(bn, p); >- mp_read_unsigned_bin(s, p, len); >+ if (mp_from_ubin(s, p, len) != MP_OKAY) { >+ free(p); >+ return -1; >+ } > free(p); >+ return 0; > } > > >@@ -61,11 +65,14 @@ mpz2BN(mp_int *s) > BIGNUM *bn; > void *p; > >- size = mp_unsigned_bin_size(s); >+ size = mp_ubin_size(s); > p = malloc(size); >- if (p == NULL && size != 0) >+ if (p == NULL) >+ return NULL; >+ if (mp_to_ubin(s, p, SIZE_MAX, NULL) != MP_OKAY) { >+ free(p); > return NULL; >- mp_to_unsigned_bin(s, p); >+ }; > > bn = BN_bin2bn(p, size, NULL); > free(p); >@@ -110,11 +117,17 @@ ltm_dh_generate_key(DH *dh) > dh->pub_key = NULL; > } > >- mp_init_multi(&pub, &priv_key, &g, &p, NULL); >+ if (mp_init_multi(&pub, &priv_key, &g, &p, NULL) != MP_OKAY) >+ continue; > >- BN2mpz(&priv_key, dh->priv_key); >- BN2mpz(&g, dh->g); >- BN2mpz(&p, dh->p); >+ if (BN2mpz(&priv_key, dh->priv_key) != 0) >+ continue; >+ >+ if (BN2mpz(&g, dh->g) != 0) >+ continue; >+ >+ if (BN2mpz(&p, dh->p) != 0) >+ continue; > > res = mp_exptmod(&g, &priv_key, &p, &pub); > >@@ -157,9 +170,18 @@ ltm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh) > if (dh->pub_key == NULL || dh->g == NULL || dh->priv_key == NULL) > return -1; > >- mp_init_multi(&s, &priv_key, &p, &peer_pub, NULL); >- BN2mpz(&p, dh->p); >- BN2mpz(&peer_pub, pub); >+ if (mp_init_multi(&s, &priv_key, &p, &peer_pub, NULL) != MP_OKAY) >+ return -1; >+ >+ if (BN2mpz(&p, dh->p) != 0) { >+ ret = -1; >+ goto out; >+ } >+ >+ if (BN2mpz(&peer_pub, pub) != 0) { >+ ret = 1; >+ goto out; >+ } > > /* check if peers pubkey is reasonable */ > if (mp_isneg(&peer_pub) >@@ -170,17 +192,20 @@ ltm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh) > goto out; > } > >- BN2mpz(&priv_key, dh->priv_key); >+ if (BN2mpz(&priv_key, dh->priv_key) != 0) { >+ ret = -1; >+ goto out; >+ } > > ret = mp_exptmod(&peer_pub, &priv_key, &p, &s); >- > if (ret != 0) { > ret = -1; > goto out; > } > >- ret = mp_unsigned_bin_size(&s); >- mp_to_unsigned_bin(&s, shared); >+ ret = mp_ubin_size(&s); >+ if (mp_to_ubin(&s, shared, SIZE_MAX, NULL) != MP_OKAY) >+ ret = -1; > > out: > mp_clear_multi(&s, &priv_key, &p, &peer_pub, NULL); >diff --git a/third_party/heimdal/lib/hcrypto/dh.c b/third_party/heimdal/lib/hcrypto/dh.c >index 0447c4f48384..5d2d214f7526 100644 >--- a/third_party/heimdal/lib/hcrypto/dh.c >+++ b/third_party/heimdal/lib/hcrypto/dh.c >@@ -98,7 +98,7 @@ DH_new_method(ENGINE *engine) > if (dh->engine) { > dh->meth = ENGINE_get_DH(dh->engine); > if (dh->meth == NULL) { >- ENGINE_finish(engine); >+ ENGINE_finish(dh->engine); > free(dh); > return 0; > } >diff --git a/third_party/heimdal/lib/hcrypto/engine.c b/third_party/heimdal/lib/hcrypto/engine.c >index 9cea24821767..3dae960fd0c8 100644 >--- a/third_party/heimdal/lib/hcrypto/engine.c >+++ b/third_party/heimdal/lib/hcrypto/engine.c >@@ -44,15 +44,22 @@ struct hc_engine { > const RSA_METHOD *rsa; > const DH_METHOD *dh; > const RAND_METHOD *rand; >+ void *dso_handle; > }; > >-ENGINE * >+ENGINE * > ENGINE_new(void) > { > ENGINE *engine; > > engine = calloc(1, sizeof(*engine)); >+ if (engine == NULL) >+ return NULL; > engine->references = 1; >+ engine->destroy = 0; >+ engine->dh = 0; >+ engine->rand = 0; >+ engine->dso_handle = 0; > > return engine; > } >@@ -77,6 +84,8 @@ ENGINE_finish(ENGINE *engine) > free(engine->id); > if(engine->destroy) > (*engine->destroy)(engine); >+ if (engine->dso_handle) >+ dlclose(engine->dso_handle); > > memset(engine, 0, sizeof(*engine)); > engine->references = -1; >@@ -299,15 +308,17 @@ ENGINE_by_dso(const char *path, const char *id) > { > #ifdef HAVE_DLOPEN > ENGINE *engine; >- void *handle; > int ret; > > engine = calloc(1, sizeof(*engine)); > if (engine == NULL) > return NULL; >- >- handle = dlopen(path, RTLD_NOW | RTLD_LOCAL | RTLD_GROUP); >- if (handle == NULL) { >+ engine->references = 0; /* ref will be added below */ >+ engine->destroy = 0; >+ engine->dh = 0; >+ engine->rand = 0; >+ engine->dso_handle = dlopen(path, RTLD_NOW | RTLD_LOCAL | RTLD_GROUP); >+ if (engine->dso_handle == NULL) { > /* printf("error: %s\n", dlerror()); */ > free(engine); > return NULL; >@@ -317,16 +328,16 @@ ENGINE_by_dso(const char *path, const char *id) > unsigned long version; > openssl_v_check v_check; > >- v_check = (openssl_v_check)dlsym(handle, "v_check"); >+ v_check = (openssl_v_check)dlsym(engine->dso_handle, "v_check"); > if (v_check == NULL) { >- dlclose(handle); >+ dlclose(engine->dso_handle); > free(engine); > return NULL; > } > > version = (*v_check)(OPENSSL_DYNAMIC_VERSION); > if (version == 0) { >- dlclose(handle); >+ dlclose(engine->dso_handle); > free(engine); > return NULL; > } >@@ -335,16 +346,17 @@ ENGINE_by_dso(const char *path, const char *id) > { > openssl_bind_engine bind_engine; > >- bind_engine = (openssl_bind_engine)dlsym(handle, "bind_engine"); >+ bind_engine = >+ (openssl_bind_engine)dlsym(engine->dso_handle, "bind_engine"); > if (bind_engine == NULL) { >- dlclose(handle); >+ dlclose(engine->dso_handle); > free(engine); > return NULL; > } > > ret = (*bind_engine)(engine, id, NULL); /* XXX fix third arg */ > if (ret != 1) { >- dlclose(handle); >+ dlclose(engine->dso_handle); > free(engine); > return NULL; > } >@@ -354,7 +366,6 @@ ENGINE_by_dso(const char *path, const char *id) > > ret = add_engine(engine); > if (ret != 1) { >- dlclose(handle); > ENGINE_finish(engine); > return NULL; > } >diff --git a/third_party/heimdal/lib/hcrypto/evp.c b/third_party/heimdal/lib/hcrypto/evp.c >index 23838709c8e9..9cced4c536ce 100644 >--- a/third_party/heimdal/lib/hcrypto/evp.c >+++ b/third_party/heimdal/lib/hcrypto/evp.c >@@ -485,17 +485,20 @@ EVP_md2(void) HC_DEPRECATED_CRYPTO > * > */ > >-static void >+static int > null_Init (void *m) > { >+ return 1; > } >-static void >+static int > null_Update (void *m, const void * data, size_t size) > { >+ return 1; > } >-static void >+static int > null_Final(void *res, void *m) > { >+ return 1; > } > > /** >diff --git a/third_party/heimdal/lib/hcrypto/hmac.c b/third_party/heimdal/lib/hcrypto/hmac.c >index 6cdf4e97a4e9..6b387ae90dc7 100644 >--- a/third_party/heimdal/lib/hcrypto/hmac.c >+++ b/third_party/heimdal/lib/hcrypto/hmac.c >@@ -85,7 +85,7 @@ HMAC_size(const HMAC_CTX *ctx) > return EVP_MD_size(ctx->md); > } > >-void >+int > HMAC_Init_ex(HMAC_CTX *ctx, > const void *key, > size_t keylen, >@@ -103,17 +103,26 @@ HMAC_Init_ex(HMAC_CTX *ctx, > > ctx->md = md; > ctx->key_length = EVP_MD_size(ctx->md); >+ ctx->opad = NULL; >+ ctx->ipad = NULL; >+ ctx->ctx = NULL; > ctx->buf = malloc(ctx->key_length); >- ctx->opad = malloc(blockSize); >- ctx->ipad = malloc(blockSize); >- ctx->ctx = EVP_MD_CTX_create(); >+ if (ctx->buf) >+ ctx->opad = malloc(blockSize); >+ if (ctx->opad) >+ ctx->ipad = malloc(blockSize); >+ if (ctx->ipad) >+ ctx->ctx = EVP_MD_CTX_create(); >+ if (!ctx->buf || !ctx->opad || !ctx->ipad || !ctx->ctx) >+ return 0; > } > #if 0 > ctx->engine = engine; > #endif > > if (keylen > blockSize) { >- EVP_Digest(key, keylen, ctx->buf, NULL, ctx->md, engine); >+ if (EVP_Digest(key, keylen, ctx->buf, NULL, ctx->md, engine) == 0) >+ return 0; > key = ctx->buf; > keylen = EVP_MD_size(ctx->md); > } >@@ -126,8 +135,10 @@ HMAC_Init_ex(HMAC_CTX *ctx, > for (i = 0, p = ctx->opad; i < keylen; i++) > p[i] ^= ((const unsigned char *)key)[i]; > >- EVP_DigestInit_ex(ctx->ctx, ctx->md, ctx->engine); >+ if (EVP_DigestInit_ex(ctx->ctx, ctx->md, ctx->engine) == 0) >+ return 0; > EVP_DigestUpdate(ctx->ctx, ctx->ipad, EVP_MD_block_size(ctx->md)); >+ return 1; > } > > void >@@ -156,7 +167,10 @@ HMAC(const EVP_MD *md, > HMAC_CTX ctx; > > HMAC_CTX_init(&ctx); >- HMAC_Init_ex(&ctx, key, key_size, md, NULL); >+ if (HMAC_Init_ex(&ctx, key, key_size, md, NULL) == 0) { >+ HMAC_CTX_cleanup(&ctx); >+ return NULL; >+ } > HMAC_Update(&ctx, data, data_size); > HMAC_Final(&ctx, hash, hash_len); > HMAC_CTX_cleanup(&ctx); >diff --git a/third_party/heimdal/lib/hcrypto/hmac.h b/third_party/heimdal/lib/hcrypto/hmac.h >index 2c7d9b8803a9..cc99c879fb91 100644 >--- a/third_party/heimdal/lib/hcrypto/hmac.h >+++ b/third_party/heimdal/lib/hcrypto/hmac.h >@@ -75,7 +75,7 @@ void HMAC_CTX_free(HMAC_CTX *ctx); > > size_t HMAC_size(const HMAC_CTX *ctx); > >-void HMAC_Init_ex(HMAC_CTX *, const void *, size_t, >+int HMAC_Init_ex(HMAC_CTX *, const void *, size_t, > const EVP_MD *, ENGINE *); > void HMAC_Update(HMAC_CTX *ctx, const void *data, size_t len); > void HMAC_Final(HMAC_CTX *ctx, void *md, unsigned int *len); >diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_set_double.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_set_double.c >index a42fc70d9086..6f91b64f5034 100644 >--- a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_set_double.c >+++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_set_double.c >@@ -3,7 +3,7 @@ > /* LibTomMath, multiple-precision integer library -- Tom St Denis */ > /* SPDX-License-Identifier: Unlicense */ > >-#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) >+#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) || defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(_M_X86) || defined(__aarch64__) || defined(__arm__) > mp_err mp_set_double(mp_int *a, double b) > { > uint64_t frac; >diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c >index 55c69390eef7..79879c35039a 100644 >--- a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c >+++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c >@@ -96,7 +96,7 @@ static mp_err s_read_urandom(void *p, size_t n) > if (fd == -1) return MP_ERR; > > while (n > 0u) { >- ssize_t ret = read(fd, p, n); >+ ssize_t ret = read(fd, q, n); > if (ret < 0) { > if (errno == EINTR) { > continue; >diff --git a/third_party/heimdal/lib/hcrypto/libtommath/demo/test.c b/third_party/heimdal/lib/hcrypto/libtommath/demo/test.c >index 7b29a4ce9489..9049fa81f91a 100644 >--- a/third_party/heimdal/lib/hcrypto/libtommath/demo/test.c >+++ b/third_party/heimdal/lib/hcrypto/libtommath/demo/test.c >@@ -625,7 +625,7 @@ LBL_ERR: > > } > >-#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) >+#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) || defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(_M_X86) || defined(__aarch64__) || defined(__arm__) > static int test_mp_set_double(void) > { > int i; >diff --git a/third_party/heimdal/lib/hcrypto/libtommath/etc/tune.c b/third_party/heimdal/lib/hcrypto/libtommath/etc/tune.c >index bc2cdfe6e03e..e7b99fce2895 100644 >--- a/third_party/heimdal/lib/hcrypto/libtommath/etc/tune.c >+++ b/third_party/heimdal/lib/hcrypto/libtommath/etc/tune.c >@@ -424,7 +424,7 @@ int main(int argc, char **argv) > break; > case 'h': > s_exit_code = EXIT_SUCCESS; >- /* FALLTHROUGH */ >+ /* FALLTHROUGH */ > default: > s_usage(argv[0]); > } >diff --git a/third_party/heimdal/lib/hcrypto/rsa-ltm.c b/third_party/heimdal/lib/hcrypto/rsa-ltm.c >index 2852bd4d6b8a..1d5b73e60e5a 100644 >--- a/third_party/heimdal/lib/hcrypto/rsa-ltm.c >+++ b/third_party/heimdal/lib/hcrypto/rsa-ltm.c >@@ -456,8 +456,11 @@ mpz2BN(mp_int *s) > void *p; > > size = mp_ubin_size(s); >+ if (size == 0) >+ return NULL; >+ > p = malloc(size); >- if (p == NULL && size != 0) >+ if (p == NULL) > return NULL; > > ret = mp_to_ubin(s, p, SIZE_MAX, NULL); >@@ -534,8 +537,6 @@ ltm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) > > bitsp = (bits + 1) / 2; > >- ret = -1; >- > FIRST(mp_init_multi(&el, &p, &q, &n, &d, > &dmp1, &dmq1, &iqmp, > &t1, &t2, &t3, NULL)); >diff --git a/third_party/heimdal/lib/hcrypto/rsa.c b/third_party/heimdal/lib/hcrypto/rsa.c >index c99b2b6cbe95..6172b25413f1 100644 >--- a/third_party/heimdal/lib/hcrypto/rsa.c >+++ b/third_party/heimdal/lib/hcrypto/rsa.c >@@ -114,7 +114,7 @@ RSA_new_method(ENGINE *engine) > if (rsa->engine) { > rsa->meth = ENGINE_get_RSA(rsa->engine); > if (rsa->meth == NULL) { >- ENGINE_finish(engine); >+ ENGINE_finish(rsa->engine); > free(rsa); > return 0; > } >@@ -272,7 +272,10 @@ RSA_check_key(const RSA *key) > * and then decrypt/verify. > */ > >- if ((rsa->d == NULL || rsa->n == NULL) && >+ if (rsa->n == NULL) >+ return 0; >+ >+ if (rsa->d == NULL && > (rsa->p == NULL || rsa->q || rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL)) > return 0; > >diff --git a/third_party/heimdal/lib/hcrypto/test_hmac.c b/third_party/heimdal/lib/hcrypto/test_hmac.c >index 063a461cc161..36a5626a7086 100644 >--- a/third_party/heimdal/lib/hcrypto/test_hmac.c >+++ b/third_party/heimdal/lib/hcrypto/test_hmac.c >@@ -51,7 +51,11 @@ main(int argc, char **argv) > "\x6f\xd1\x52\x4d\x54\x58\x73\x0f\xf3\x24"; > > HMAC_CTX_init(&c); >- HMAC_Init_ex(&c, hmackey, hmackey_size, EVP_sha1(), NULL); >+ if (HMAC_Init_ex(&c, hmackey, hmackey_size, EVP_sha1(), NULL) == 0) { >+ HMAC_CTX_cleanup(&c); >+ printf("out of memory\n"); >+ return 1; >+ } > HMAC_Update(&c, buf, sizeof(buf)); > HMAC_Final(&c, hmac, &hmaclen); > HMAC_CTX_cleanup(&c); >diff --git a/third_party/heimdal/lib/hcrypto/validate.c b/third_party/heimdal/lib/hcrypto/validate.c >index 562e5aa4dd02..4b655f262c87 100644 >--- a/third_party/heimdal/lib/hcrypto/validate.c >+++ b/third_party/heimdal/lib/hcrypto/validate.c >@@ -276,7 +276,8 @@ check_hmac(void) > "\x6f\xd1\x52\x4d\x54\x58\x73\x0f\xf3\x24"; > > HMAC_CTX_init(&c); >- HMAC_Init_ex(&c, hmackey, hmackey_size, EVP_sha1(), NULL); >+ if (HMAC_Init_ex(&c, hmackey, hmackey_size, EVP_sha1(), NULL) == 0) >+ errx(1, "HMAC_Init_ex() out of memory"); > HMAC_Update(&c, buf, sizeof(buf)); > HMAC_Final(&c, hmac, &hmaclen); > HMAC_CTX_cleanup(&c); >diff --git a/third_party/heimdal/lib/hdb/Makefile.am b/third_party/heimdal/lib/hdb/Makefile.am >index 342aaffbe960..89ab15d9d3e5 100644 >--- a/third_party/heimdal/lib/hdb/Makefile.am >+++ b/third_party/heimdal/lib/hdb/Makefile.am >@@ -2,6 +2,8 @@ > > include $(top_srcdir)/Makefile.am.common > >+WFLAGS += $(WFLAGS_ENUM_CONV) >+ > AM_CPPFLAGS += -I../asn1 -I$(srcdir)/../asn1 > AM_CPPFLAGS += $(INCLUDE_openldap) -DHDB_DB_DIR=\"$(DIR_hdbdir)\" > AM_CPPFLAGS += -I$(srcdir)/../krb5 >@@ -13,38 +15,40 @@ AM_CPPFLAGS += -I$(DBHEADER) > endif > > BUILT_SOURCES = \ >- $(gen_files_hdb:.x=.c) \ >+ $(gen_files_hdb) \ > hdb_err.c \ > hdb_err.h > > gen_files_hdb = \ >- asn1_Salt.x \ >- asn1_Key.x \ >- asn1_Event.x \ >- asn1_HDBFlags.x \ >- asn1_GENERATION.x \ >- asn1_HDB_Ext_PKINIT_acl.x \ >- asn1_HDB_Ext_PKINIT_cert.x \ >- asn1_HDB_Ext_PKINIT_hash.x \ >- asn1_HDB_Ext_Constrained_delegation_acl.x \ >- asn1_HDB_Ext_KeyRotation.x \ >- asn1_HDB_Ext_Lan_Manager_OWF.x \ >- asn1_HDB_Ext_Password.x \ >- asn1_HDB_Ext_Aliases.x \ >- asn1_HDB_Ext_KeySet.x \ >- asn1_HDB_extension.x \ >- asn1_HDB_extensions.x \ >- asn1_HDB_EncTypeList.x \ >- asn1_HDB_EntryOrAlias.x \ >- asn1_KeyRotation.x \ >- asn1_KeyRotationFlags.x \ >- asn1_HDB_entry.x \ >- asn1_HDB_entry_alias.x \ >- asn1_HDB_keyset.x \ >- asn1_Keys.x >+ asn1_Event.c \ >+ asn1_GENERATION.c \ >+ asn1_HDB_EncTypeList.c \ >+ asn1_HDB_Ext_Aliases.c \ >+ asn1_HDB_Ext_Constrained_delegation_acl.c \ >+ asn1_HDB_Ext_KeyRotation.c \ >+ asn1_HDB_Ext_KeySet.c \ >+ asn1_HDB_Ext_Lan_Manager_OWF.c \ >+ asn1_HDB_Ext_Password.c \ >+ asn1_HDB_Ext_PKINIT_acl.c \ >+ asn1_HDB_Ext_PKINIT_cert.c \ >+ asn1_HDB_Ext_PKINIT_hash.c \ >+ asn1_HDB_EntryOrAlias.c \ >+ asn1_HDB_entry_alias.c \ >+ asn1_HDB_entry.c \ >+ asn1_HDB_extension.c \ >+ asn1_HDB_extensions.c \ >+ asn1_HDB_keyset.c \ >+ asn1_HDBFlags.c \ >+ asn1_Key.c \ >+ asn1_KeyRotation.c \ >+ asn1_KeyRotationFlags.c \ >+ asn1_Keys.c \ >+ asn1_Salt.c > > CLEANFILES = $(BUILT_SOURCES) $(gen_files_hdb) \ >- hdb_asn1{,-priv}.h* hdb_asn1_files hdb_asn1-template.[cx] >+ hdb_asn1{,-priv}.h hdb_asn1_files hdb_asn1-template.c \ >+ hdb_asn1_syms.c hdb_asn1_oids.c hdb_asn1.json \ >+ testhdb-* > > LDADD = libhdb.la \ > ../krb5/libkrb5.la \ >@@ -139,13 +143,14 @@ $(srcdir)/hdb-protos.h: $(dist_libhdb_la_SOURCES) > $(srcdir)/hdb-private.h: $(dist_libhdb_la_SOURCES) > cd $(srcdir); perl ../../cf/make-proto.pl -q -P comment -p hdb-private.h $(dist_libhdb_la_SOURCES) || rm -f hdb-private.h > >-$(gen_files_hdb) hdb_asn1.hx hdb_asn1-priv.hx: hdb_asn1_files >+$(gen_files_hdb) hdb_asn1.h hdb_asn1-priv.h: hdb_asn1_files >+ for genfile in '$(gen_files_hdb)'; do \ >+ $(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $${genfile}; \ >+ done > > hdb_asn1_files: $(ASN1_COMPILE_DEP) $(srcdir)/hdb.asn1 >- $(ASN1_COMPILE) --sequence=HDB-extensions \ >- --sequence=HDB-Ext-KeyRotation \ >- --sequence=HDB-Ext-KeySet \ >- --sequence=Keys $(srcdir)/hdb.asn1 hdb_asn1 >+ $(ASN1_COMPILE) --option-file=$(srcdir)/hdb.opt $(srcdir)/hdb.asn1 hdb_asn1 >+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $$(cat hdb_asn1_files) > > # to help stupid solaris make > >diff --git a/third_party/heimdal/lib/hdb/NTMakefile b/third_party/heimdal/lib/hdb/NTMakefile >index 5ad9d9c57424..f4801f7c54e9 100644 >--- a/third_party/heimdal/lib/hdb/NTMakefile >+++ b/third_party/heimdal/lib/hdb/NTMakefile >@@ -31,17 +31,15 @@ > > RELDIR=lib\hdb > >-!include ../../windows/NTMakefile.w32 >+intcflags=-DASN1_LIB > >-gen_files_hdb = $(OBJ)\asn1_hdb_asn1.x >+!include ../../windows/NTMakefile.w32 > >-$(gen_files_hdb) $(OBJ)\hdb_asn1.hx $(OBJ)\hdb_asn1-priv.hx: $(BINDIR)\asn1_compile.exe hdb.asn1 >+$(OBJ)\asn1_hdb_asn1.c $(OBJ)\hdb_asn1.h $(OBJ)\hdb_asn1-priv.h: $(BINDIR)\asn1_compile.exe hdb.asn1 > cd $(OBJ) >- $(BINDIR)\asn1_compile.exe --sequence=HDB-extensions --sequence=HDB-Ext-KeyRotation --sequence=HDB-Ext-KeySet --sequence=Keys --one-code-file $(SRCDIR)\hdb.asn1 hdb_asn1 >+ $(BINDIR)\asn1_compile.exe --one-code-file --option-file=$(SRCDIR)\hdb.opt $(SRCDIR)\hdb.asn1 hdb_asn1 > cd $(SRCDIR) > >-$(gen_files_hdb:.x=.c): $$(@R).x >- > !ifdef OPENLDAP_MODULE > > ldap_dll = $(BINDIR)\hdb_ldap.dll >@@ -98,7 +96,7 @@ libhdb_OBJs = \ > $(OBJ)\mkey.obj \ > $(OBJ)\ndbm.obj \ > $(OBJ)\print.obj \ >- $(gen_files_hdb:.x=.obj) \ >+ $(OBJ)\asn1_hdb_asn1.obj \ > $(OBJ)\hdb_err.obj > > $(OBJ)\hdb_err.c $(OBJ)\hdb_err.h: hdb_err.et >diff --git a/third_party/heimdal/lib/hdb/common.c b/third_party/heimdal/lib/hdb/common.c >index 251eb9b77148..a92cc1372db5 100644 >--- a/third_party/heimdal/lib/hdb/common.c >+++ b/third_party/heimdal/lib/hdb/common.c >@@ -148,7 +148,7 @@ fetch_entry_or_alias(krb5_context context, > HDB *db, > krb5_const_principal principal, > unsigned flags, >- hdb_entry_ex *entry) >+ hdb_entry *entry) > { > HDB_EntryOrAlias eoa; > krb5_principal enterprise_principal = NULL; >@@ -180,7 +180,7 @@ fetch_entry_or_alias(krb5_context context, > if (ret == 0) > ret = decode_HDB_EntryOrAlias(value.data, value.length, &eoa, NULL); > if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_entry) { >- entry->entry = eoa.u.entry; >+ *entry = eoa.u.entry; > } else if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_alias) { > krb5_data_free(&key); > ret = hdb_principal2key(context, eoa.u.alias.principal, &key); >@@ -190,7 +190,7 @@ fetch_entry_or_alias(krb5_context context, > } > if (ret == 0) > /* No alias chaining */ >- ret = hdb_value2entry(context, &value, &entry->entry); >+ ret = hdb_value2entry(context, &value, entry); > krb5_free_principal(context, eoa.u.alias.principal); > } else if (ret == 0) > ret = ENOTSUP; >@@ -200,7 +200,7 @@ fetch_entry_or_alias(krb5_context context, > * the canonicalize flag is unset, the original specification in > * draft-ietf-krb-wg-kerberos-referrals-03.txt says we should. > */ >- entry->entry.flags.force_canonicalize = 1; >+ entry->flags.force_canonicalize = 1; > } > > /* HDB_F_GET_ANY indicates request originated from KDC (not kadmin) */ >@@ -208,7 +208,7 @@ fetch_entry_or_alias(krb5_context context, > (flags & (HDB_F_CANON|HDB_F_GET_ANY)) == 0) { > > /* `principal' was alias but canon not req'd */ >- free_HDB_entry(&entry->entry); >+ free_HDB_entry(entry); > ret = HDB_ERR_NOENTRY; > } > >@@ -221,7 +221,7 @@ fetch_entry_or_alias(krb5_context context, > > krb5_error_code > _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, >- unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry) >+ unsigned flags, krb5_kvno kvno, hdb_entry *entry) > { > krb5_error_code ret; > >@@ -231,23 +231,23 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, > > if ((flags & HDB_F_DECRYPT) && (flags & HDB_F_ALL_KVNOS)) { > /* Decrypt the current keys */ >- ret = hdb_unseal_keys(context, db, &entry->entry); >+ ret = hdb_unseal_keys(context, db, entry); > if (ret) { >- hdb_free_entry(context, entry); >+ hdb_free_entry(context, db, entry); > return ret; > } > /* Decrypt the key history too */ >- ret = hdb_unseal_keys_kvno(context, db, 0, flags, &entry->entry); >+ ret = hdb_unseal_keys_kvno(context, db, 0, flags, entry); > if (ret) { >- hdb_free_entry(context, entry); >+ hdb_free_entry(context, db, entry); > return ret; > } > } else if ((flags & HDB_F_DECRYPT)) { >- if ((flags & HDB_F_KVNO_SPECIFIED) == 0 || kvno == entry->entry.kvno) { >+ if ((flags & HDB_F_KVNO_SPECIFIED) == 0 || kvno == entry->kvno) { > /* Decrypt the current keys */ >- ret = hdb_unseal_keys(context, db, &entry->entry); >+ ret = hdb_unseal_keys(context, db, entry); > if (ret) { >- hdb_free_entry(context, entry); >+ hdb_free_entry(context, db, entry); > return ret; > } > } else { >@@ -257,9 +257,9 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, > * Find and decrypt the keys from the history that we want, > * and swap them with the current keys > */ >- ret = hdb_unseal_keys_kvno(context, db, kvno, flags, &entry->entry); >+ ret = hdb_unseal_keys_kvno(context, db, kvno, flags, entry); > if (ret) { >- hdb_free_entry(context, entry); >+ hdb_free_entry(context, db, entry); > return ret; > } > } >@@ -271,9 +271,9 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, > * key was generated, but given the salt will be ignored by a keytab > * client it doesn't hurt to include the default salt. > */ >- ret = add_default_salts(context, db, &entry->entry); >+ ret = add_default_salts(context, db, entry); > if (ret) { >- hdb_free_entry(context, entry); >+ hdb_free_entry(context, db, entry); > return ret; > } > } >@@ -325,20 +325,20 @@ hdb_remove_aliases(krb5_context context, HDB *db, krb5_data *key) > > static krb5_error_code > hdb_add_aliases(krb5_context context, HDB *db, >- unsigned flags, hdb_entry_ex *entry) >+ unsigned flags, hdb_entry *entry) > { > const HDB_Ext_Aliases *aliases; > krb5_error_code code; > krb5_data key, value; > size_t i; > >- code = hdb_entry_get_aliases(&entry->entry, &aliases); >+ code = hdb_entry_get_aliases(entry, &aliases); > if (code || aliases == NULL) > return code; > > for (i = 0; i < aliases->aliases.len; i++) { > hdb_entry_alias entryalias; >- entryalias.principal = entry->entry.principal; >+ entryalias.principal = entry->principal; > > code = hdb_entry_alias2value(context, &entryalias, &value); > if (code) >@@ -358,7 +358,7 @@ hdb_add_aliases(krb5_context context, HDB *db, > > /* Check if new aliases are already used for other entries */ > static krb5_error_code >-hdb_check_aliases(krb5_context context, HDB *db, hdb_entry_ex *entry) >+hdb_check_aliases(krb5_context context, HDB *db, hdb_entry *entry) > { > const HDB_Ext_Aliases *aliases = NULL; > HDB_EntryOrAlias eoa; >@@ -370,7 +370,7 @@ hdb_check_aliases(krb5_context context, HDB *db, hdb_entry_ex *entry) > krb5_data_zero(&value); > akey = value; > >- ret = hdb_entry_get_aliases(&entry->entry, &aliases); >+ ret = hdb_entry_get_aliases(entry, &aliases); > for (i = 0; ret == 0 && aliases && i < aliases->aliases.len; i++) { > ret = hdb_principal2key(context, &aliases->aliases.val[i], &akey); > if (ret == 0) >@@ -385,7 +385,7 @@ hdb_check_aliases(krb5_context context, HDB *db, hdb_entry_ex *entry) > ret = HDB_ERR_EXISTS; > if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_alias && > !krb5_principal_compare(context, eoa.u.alias.principal, >- entry->entry.principal)) >+ entry->principal)) > /* New alias names an existing alias of a different entry */ > ret = HDB_ERR_EXISTS; > if (ret == HDB_ERR_NOENTRY) /* from db->hdb__get */ >@@ -433,14 +433,8 @@ hdb_derive_etypes(krb5_context context, hdb_entry *e, HDB_Ext_KeySet *base_keys) > free(e->etypes->val); > e->etypes->len = 0; > e->etypes->val = 0; >- } >- >- if (e->etypes == NULL && >- (e->etypes = malloc(sizeof(e->etypes[0]))) == NULL) >+ } else if ((e->etypes = calloc(1, sizeof(e->etypes[0]))) == NULL) { > ret = krb5_enomem(context); >- if (ret == 0) { >- e->etypes->len = 0; >- e->etypes->val = 0; > } > if (ret == 0 && > (e->etypes->val = calloc(netypes, sizeof(e->etypes->val[0]))) == NULL) >@@ -465,13 +459,13 @@ hdb_derive_etypes(krb5_context context, hdb_entry *e, HDB_Ext_KeySet *base_keys) > } > > krb5_error_code >-_hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+_hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > krb5_data key, value; > int code; > >- if (entry->entry.flags.do_not_store || >- entry->entry.flags.force_canonicalize) >+ if (entry->flags.do_not_store || >+ entry->flags.force_canonicalize) > return HDB_ERR_MISUSE; > /* check if new aliases already is used */ > code = hdb_check_aliases(context, db, entry); >@@ -482,7 +476,7 @@ _hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) > return 0; > > if ((flags & HDB_F_PRECHECK)) { >- code = hdb_principal2key(context, entry->entry.principal, &key); >+ code = hdb_principal2key(context, entry->principal, &key); > if (code) > return code; > code = db->hdb__get(context, db, key, &value); >@@ -494,29 +488,31 @@ _hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) > return code ? code : HDB_ERR_EXISTS; > } > >- if ((entry->entry.etypes == NULL || entry->entry.etypes->len == 0) && >- (code = hdb_derive_etypes(context, &entry->entry, NULL))) >+ if ((entry->etypes == NULL || entry->etypes->len == 0) && >+ (code = hdb_derive_etypes(context, entry, NULL))) > return code; > >- if (entry->entry.generation == NULL) { >+ if (entry->generation == NULL) { > struct timeval t; >- entry->entry.generation = malloc(sizeof(*entry->entry.generation)); >- if(entry->entry.generation == NULL) { >+ entry->generation = malloc(sizeof(*entry->generation)); >+ if(entry->generation == NULL) { > krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); > return ENOMEM; > } > gettimeofday(&t, NULL); >- entry->entry.generation->time = t.tv_sec; >- entry->entry.generation->usec = t.tv_usec; >- entry->entry.generation->gen = 0; >+ entry->generation->time = t.tv_sec; >+ entry->generation->usec = t.tv_usec; >+ entry->generation->gen = 0; > } else >- entry->entry.generation->gen++; >+ entry->generation->gen++; > >- code = hdb_seal_keys(context, db, &entry->entry); >+ code = hdb_seal_keys(context, db, entry); > if (code) > return code; > >- hdb_principal2key(context, entry->entry.principal, &key); >+ code = hdb_principal2key(context, entry->principal, &key); >+ if (code) >+ return code; > > /* remove aliases */ > code = hdb_remove_aliases(context, db, &key); >@@ -524,8 +520,9 @@ _hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) > krb5_data_free(&key); > return code; > } >- hdb_entry2value(context, &entry->entry, &value); >- code = db->hdb__put(context, db, flags & HDB_F_REPLACE, key, value); >+ code = hdb_entry2value(context, entry, &value); >+ if (code == 0) >+ code = db->hdb__put(context, db, flags & HDB_F_REPLACE, key, value); > krb5_data_free(&value); > krb5_data_free(&key); > if (code) >@@ -554,8 +551,9 @@ _hdb_remove(krb5_context context, HDB *db, > * HDB_entry_alias instead and assume it's an entry if decoding fails... > */ > >- hdb_principal2key(context, principal, &key); >- code = db->hdb__get(context, db, key, &value); >+ code = hdb_principal2key(context, principal, &key); >+ if (code == 0) >+ code = db->hdb__get(context, db, key, &value); > if (code == 0) { > code = decode_HDB_EntryOrAlias(value.data, value.length, &eoa, NULL); > krb5_data_free(&value); >@@ -573,7 +571,8 @@ _hdb_remove(krb5_context context, HDB *db, > return code; > } > >- code = hdb_remove_aliases(context, db, &key); >+ if (code == 0) >+ code = hdb_remove_aliases(context, db, &key); > if (code == 0) > code = db->hdb__del(context, db, key); > krb5_data_free(&key); >@@ -714,7 +713,7 @@ derive_keyset(krb5_context context, > { > dks->kvno = kvno; > dks->keys.val = 0; >- dks->set_time = malloc(sizeof(*dks->set_time)); >+ dks->set_time = malloc(sizeof(*(dks->set_time))); > if (dks->set_time == NULL) > return krb5_enomem(context); > *dks->set_time = set_time; >@@ -724,7 +723,7 @@ derive_keyset(krb5_context context, > /* Possibly derive and install in `h' a keyset identified by `t' */ > static krb5_error_code > derive_keys_for_kr(krb5_context context, >- hdb_entry_ex *h, >+ hdb_entry *h, > HDB_Ext_KeySet *base_keys, > int is_current_keyset, > int rotation_period_offset, >@@ -798,7 +797,7 @@ derive_keys_for_kr(krb5_context context, > ret = derive_keyset(context, &base_keys->val[i].keys, princ, etype, kvno, > set_time, &dks); > if (ret == 0) >- ret = hdb_install_keyset(context, &h->entry, is_current_keyset, &dks); >+ ret = hdb_install_keyset(context, h, is_current_keyset, &dks); > > free_HDB_keyset(&dks); > return ret; >@@ -807,7 +806,7 @@ derive_keys_for_kr(krb5_context context, > /* Derive and install current keys, and possibly preceding or next keys */ > static krb5_error_code > derive_keys_for_current_kr(krb5_context context, >- hdb_entry_ex *h, >+ hdb_entry *h, > HDB_Ext_KeySet *base_keys, > const char *princ, > unsigned int flags, >@@ -873,12 +872,12 @@ derive_keys_for_current_kr(krb5_context context, > * Arguments: > * > * - `flags' is the flags passed to `hdb_fetch_kvno()' >- * - `princ' is the name of the principal we'll end up with in `h->entry' >+ * - `princ' is the name of the principal we'll end up with in `entry' > * - `h_is_namespace' indicates whether `h' is for a namespace or a concrete > * principal (that might nonetheless have virtual/derived keys) > * - `t' is the time such that the derived keys are for kvnos needed at `t' > * - `etype' indicates what enctype to derive keys for (0 for all enctypes in >- * `h->entry.etypes') >+ * `entry->etypes') > * - `kvno' requests a particular kvno, or all if zero > * > * The caller doesn't know if the principal needs key derivation -- we make >@@ -970,7 +969,7 @@ derive_keys(krb5_context context, > krb5_timestamp t, > krb5int32 etype, > krb5uint32 kvno, >- hdb_entry_ex *h) >+ hdb_entry *h) > { > HDB_Ext_KeyRotation kr; > HDB_Ext_KeySet base_keys; >@@ -979,14 +978,9 @@ derive_keys(krb5_context context, > char *p = NULL; > int valid = 1; > >- if (!h_is_namespace && !h->entry.flags.virtual_keys) >+ if (!h_is_namespace && !h->flags.virtual_keys) > return 0; >- h->entry.flags.virtual = 1; >- if (h_is_namespace) { >- /* Set the entry's principal name */ >- free_Principal(h->entry.principal); >- ret = copy_Principal(princ, h->entry.principal); >- } >+ h->flags.virtual = 1; > > kr.len = 0; > kr.val = 0; >@@ -994,7 +988,7 @@ derive_keys(krb5_context context, > const HDB_Ext_KeyRotation *ckr; > > /* Installing keys invalidates `ckr', so we copy it */ >- ret = hdb_entry_get_key_rotation(context, &h->entry, &ckr); >+ ret = hdb_entry_get_key_rotation(context, h, &ckr); > if (!ckr) > return ret; > if (ret == 0) >@@ -1005,11 +999,11 @@ derive_keys(krb5_context context, > base_keys.val = 0; > base_keys.len = 0; > if (ret == 0) >- ret = hdb_remove_base_keys(context, &h->entry, &base_keys); >+ ret = _hdb_remove_base_keys(context, h, &base_keys, &kr); > >- /* Make sure we have h->entry.etypes */ >- if (ret == 0 && !h->entry.etypes) >- ret = hdb_derive_etypes(context, &h->entry, &base_keys); >+ /* Make sure we have h->etypes */ >+ if (ret == 0 && !h->etypes) >+ ret = hdb_derive_etypes(context, h, &base_keys); > > /* Keys not desired? Don't derive them! */ > if (ret || !(flags & HDB_F_DECRYPT)) { >@@ -1019,7 +1013,7 @@ derive_keys(krb5_context context, > } > > /* The principal name will be used in key derivation and error messages */ >- if (ret == 0 && h_is_namespace) >+ if (ret == 0) > ret = krb5_unparse_name(context, princ, &p); > > /* Sanity check key rotations, determine current & last kr */ >@@ -1101,10 +1095,10 @@ derive_keys(krb5_context context, > /* > * Derive and set in `h' its current kvno and current keys. > * >- * This will set h->entry.kvno as well. >+ * This will set h->kvno as well. > * > * This may set up to TWO keysets for the current key rotation period: >- * - current keys (h->entry.keys and h->entry.kvno) >+ * - current keys (h->keys and h->kvno) > * - possibly one future > * OR > * possibly one past keyset in hist_keys for the current_kr >@@ -1137,14 +1131,14 @@ derive_keys(krb5_context context, > kr.val[current_kr].epoch - 1, &kr.val[past_kr]); > > /* >- * Impose a bound on h->entry.max_life so that [when the KDC is the caller] >+ * Impose a bound on h->max_life so that [when the KDC is the caller] > * the KDC won't issue tickets longer lived than this. > */ >- if (ret == 0 && !h->entry.max_life && >- (h->entry.max_life = malloc(sizeof(h->entry.max_life[0]))) == NULL) >+ if (ret == 0 && !h->max_life && >+ (h->max_life = calloc(1, sizeof(h->max_life[0]))) == NULL) > ret = krb5_enomem(context); >- if (ret == 0 && *h->entry.max_life > kr.val[current_kr].period >> 1) >- *h->entry.max_life = kr.val[current_kr].period >> 1; >+ if (ret == 0 && *h->max_life > kr.val[current_kr].period >> 1) >+ *h->max_life = kr.val[current_kr].period >> 1; > > free_HDB_Ext_KeyRotation(&kr); > free_HDB_Ext_KeySet(&base_keys); >@@ -1153,6 +1147,10 @@ derive_keys(krb5_context context, > } > > /* >+ * Pick a best kvno for the given principal at the given time. >+ * >+ * Implements the [hdb] new_service_key_delay configuration parameter. >+ * > * In order for disparate keytab provisioning systems such as OSKT and our own > * kadmin ext_keytab and httpkadmind's get-keys to coexist, we need to be able > * to force keys set by the former to not become current keys until users of >@@ -1163,9 +1161,9 @@ derive_keys(krb5_context context, > * The context is that OSKT's krb5_keytab is very happy to change keys in a way > * that requires all members of a cluster to rekey together. If one also > * wishes to have cluster members that opt out of this and just fetch current, >- * past, and future keys periodically, then the keys set by OSKT need to not >- * come into effect until all the opt-out members have had a chance to fetch >- * the new keys. >+ * past, and future keys periodically, then the keys set by OSKT must not come >+ * into effect until all the opt-out members have had a chance to fetch the new >+ * keys. > * > * The assumption is that services will fetch new keys periodically, say, every > * four hours. Then one can set `[hdb] new_service_key_delay = 8h' in the >@@ -1175,12 +1173,12 @@ derive_keys(krb5_context context, > * Naturally, this applies only to concrete principals with concrete keys. > */ > static krb5_error_code >-fix_keys(krb5_context context, >- HDB *db, >- unsigned flags, >- krb5_timestamp now, >- krb5uint32 kvno, >- hdb_entry_ex *h) >+pick_kvno(krb5_context context, >+ HDB *db, >+ unsigned flags, >+ krb5_timestamp now, >+ krb5uint32 kvno, >+ hdb_entry *h) > { > HDB_extension *ext; > HDB_Ext_KeySet keys; >@@ -1193,25 +1191,25 @@ fix_keys(krb5_context context, > * delayed, or if there's no new-key delay configured, or we're not > * fetching for use as a service principal, then we're out. > */ >- if (!(flags & HDB_F_DELAY_NEW_KEYS) || kvno || h->entry.flags.virtual || >- h->entry.flags.virtual_keys || db->new_service_key_delay <= 0) >+ if (!(flags & HDB_F_DELAY_NEW_KEYS) || kvno || h->flags.virtual || >+ h->flags.virtual_keys || db->new_service_key_delay <= 0) > return 0; > > /* No history -> current keyset is the only one and therefore the best */ >- ext = hdb_find_extension(&h->entry, choice_HDB_extension_data_hist_keys); >+ ext = hdb_find_extension(h, choice_HDB_extension_data_hist_keys); > if (!ext) > return 0; > > /* Assume the current keyset is the best to start with */ >- (void) hdb_entry_get_pw_change_time(&h->entry, ¤t); >- if (current == 0 && h->entry.modified_by) >- current = h->entry.modified_by->time; >+ (void) hdb_entry_get_pw_change_time(h, ¤t); >+ if (current == 0 && h->modified_by) >+ current = h->modified_by->time; > if (current == 0) >- current = h->entry.created_by.time; >+ current = h->created_by.time; > > /* Current keyset starts out as best */ > best = current; >- kvno = h->entry.kvno; >+ kvno = h->kvno; > > /* Look for a better keyset in the history */ > keys = ext->data.u.hist_keys; >@@ -1251,7 +1249,7 @@ fix_keys(krb5_context context, > best = keys.val[i].set_time[0]; > kvno = keys.val[i].kvno; > } >- return hdb_change_kvno(context, kvno, &h->entry); >+ return hdb_change_kvno(context, kvno, h); > } > > /* >@@ -1296,7 +1294,7 @@ make_namespace_princ(krb5_context context, > > /* First go around, need a namespace princ. Make it! */ > ret = krb5_build_principal(context, namespace, strlen(realm), >- realm, "WELLKNOWN", >+ realm, KRB5_WELLKNOWN_NAME, > HDB_WK_NAMESPACE, comp0, NULL); > if (ret == 0) > ret = krb5_principal_set_comp_string(context, *namespace, 3, comp1); >@@ -1307,6 +1305,138 @@ make_namespace_princ(krb5_context context, > return ret; > } > >+static int >+is_namespace_princ_p(krb5_context context, >+ krb5_const_principal princ) >+{ >+ return >+ krb5_principal_get_num_comp(context, princ) >= 4 >+ && strcmp(krb5_principal_get_comp_string(context, princ, 0), >+ KRB5_WELLKNOWN_NAME) == 0 >+ && strcmp(krb5_principal_get_comp_string(context, princ, 1), >+ HDB_WK_NAMESPACE) == 0; >+} >+ >+/* See call site */ >+static krb5_error_code >+rewrite_hostname(krb5_context context, >+ krb5_const_principal wanted_princ, >+ krb5_const_principal ns_princ, >+ krb5_const_principal found_ns_princ, >+ char **s) >+{ >+ const char *ns_host_part, *wanted_host_part, *found_host_part; >+ const char *p, *r; >+ size_t ns_host_part_len, wanted_host_part_len; >+ >+ wanted_host_part = krb5_principal_get_comp_string(context, wanted_princ, 1); >+ wanted_host_part_len = strlen(wanted_host_part); >+ if (wanted_host_part_len > 256) { >+ krb5_set_error_message(context, HDB_ERR_NOENTRY, >+ "Aliases of host-based principals longer than " >+ "256 bytes not supported"); >+ return HDB_ERR_NOENTRY; >+ } >+ >+ ns_host_part = krb5_principal_get_comp_string(context, ns_princ, 3); >+ ns_host_part_len = strlen(ns_host_part); >+ >+ /* Find `ns_host_part' as the tail of `wanted_host_part' */ >+ for (r = p = strstr(wanted_host_part, ns_host_part); >+ r && strnlen(r, ns_host_part_len + 1) > ns_host_part_len; >+ p = (r = strstr(r, ns_host_part)) ? r : p) >+ ; >+ if (!p || strnlen(p, ns_host_part_len + 1) != ns_host_part_len) >+ return HDB_ERR_NOENTRY; /* Can't happen */ >+ if (p == wanted_host_part || p[-1] != '.') >+ return HDB_ERR_NOENTRY; >+ >+ found_host_part = >+ krb5_principal_get_comp_string(context, found_ns_princ, 3); >+ return >+ asprintf(s, "%.*s%s", (int)(p - wanted_host_part), wanted_host_part, >+ found_host_part) < 0 || >+ *s == NULL ? krb5_enomem(context) : 0; >+} >+ >+/* >+ * Fix `h->principal' to match the desired `princ' in the namespace >+ * `nsprinc' (which is either the same as `h->principal' or an alias >+ * of it). >+ */ >+static krb5_error_code >+fix_princ_name(krb5_context context, >+ krb5_const_principal princ, >+ krb5_const_principal nsprinc, >+ hdb_entry *h) >+{ >+ krb5_error_code ret = 0; >+ char *s = NULL; >+ >+ if (!nsprinc) >+ return 0; >+ if (krb5_principal_get_num_comp(context, princ) < 2) >+ return HDB_ERR_NOENTRY; >+ >+ /* `nsprinc' must be a namespace principal */ >+ >+ if (krb5_principal_compare(context, nsprinc, h->principal)) { >+ /* >+ * `h' is the HDB entry for `nsprinc', and `nsprinc' is its canonical >+ * name. >+ * >+ * Set the entry's principal name to the desired name. The keys will >+ * be fixed next (upstairs, but don't forget to!). >+ */ >+ free_Principal(h->principal); >+ return copy_Principal(princ, h->principal); >+ } >+ >+ if (!is_namespace_princ_p(context, h->principal)) { >+ /* >+ * The alias is a namespace, but the canonical name is not. WAT. >+ * >+ * Well, the KDC will just issue a referral anyways, so we can leave >+ * `h->principal' as is... >+ * >+ * Remove all of `h's keys just in case, and leave >+ * `h->principal' as-is. >+ */ >+ free_Keys(&h->keys); >+ (void) hdb_entry_clear_password(context, h); >+ return hdb_clear_extension(context, h, >+ choice_HDB_extension_data_hist_keys); >+ } >+ >+ /* >+ * A namespace alias of a namespace entry. >+ * >+ * We'll want to rewrite the original principal accordingly. >+ * >+ * E.g., if the caller wanted host/foo.ns.test.h5l.se and we >+ * found WELLKNOWN/HOSTBASED-NAMESPACE/ns.test.h5l.se is an >+ * alias of WELLKNOWN/HOSTBASED-NAMESPACE/ns.example.org, then >+ * we'll want to treat host/foo.ns.test.h5l.se as an alias of >+ * host/foo.ns.example.org. >+ */ >+ if (krb5_principal_get_num_comp(context, h->principal) != >+ 2 + krb5_principal_get_num_comp(context, princ)) >+ ret = HDB_ERR_NOENTRY; /* Only host-based services for now */ >+ if (ret == 0) >+ ret = rewrite_hostname(context, princ, nsprinc, h->principal, &s); >+ if (ret == 0) { >+ krb5_free_principal(context, h->principal); >+ h->principal = NULL; >+ ret = krb5_make_principal(context, &h->principal, >+ krb5_principal_get_realm(context, princ), >+ krb5_principal_get_comp_string(context, >+ princ, 0), >+ s, >+ NULL); >+ } >+ return ret; >+} >+ > /* Wrapper around db->hdb_fetch_kvno() that implements virtual princs/keys */ > static krb5_error_code > fetch_it(krb5_context context, >@@ -1316,10 +1446,10 @@ fetch_it(krb5_context context, > krb5_timestamp t, > krb5int32 etype, > krb5uint32 kvno, >- hdb_entry_ex *ent) >+ hdb_entry *ent) > { > krb5_const_principal tmpprinc = princ; >- krb5_principal baseprinc = NULL; >+ krb5_principal nsprinc = NULL; > krb5_error_code ret = 0; > const char *comp0 = krb5_principal_get_comp_string(context, princ, 0); > const char *comp1 = krb5_principal_get_comp_string(context, princ, 1); >@@ -1330,8 +1460,10 @@ fetch_it(krb5_context context, > char *host = NULL; > int do_search = 0; > >+ if (!db->enable_virtual_hostbased_princs) >+ maxdots = mindots = 0; > if (db->enable_virtual_hostbased_princs && comp1 && >- strcmp("krbtgt", comp0) != 0 && strcmp("WELLKNOWN", comp0) != 0) { >+ strcmp("krbtgt", comp0) != 0 && strcmp(KRB5_WELLKNOWN_NAME, comp0) != 0) { > char *htmp; > > if ((host = strdup(comp1)) == NULL) >@@ -1358,7 +1490,7 @@ fetch_it(krb5_context context, > } > > tmp = host ? host : comp1; >- for (ret = HDB_ERR_NOENTRY; ret == HDB_ERR_NOENTRY; tmpprinc = baseprinc) { >+ for (ret = HDB_ERR_NOENTRY; ret == HDB_ERR_NOENTRY; tmpprinc = nsprinc) { > krb5_error_code ret2 = 0; > > /* >@@ -1376,7 +1508,7 @@ fetch_it(krb5_context context, > ret = db->hdb_fetch_kvno(context, db, tmpprinc, flags, kvno, ent); > if (ret != HDB_ERR_NOENTRY || hdots == 0 || hdots < mindots || !tmp || > !do_search) >- break; >+ break; > > /* > * Breadcrumb: >@@ -1398,17 +1530,22 @@ fetch_it(krb5_context context, > */ > while (maxdots && hdots > maxdots && tmp) { > tmp = strchr(tmp, '.'); >- /* tmp != NULL because maxdots > 0 */ >+ /* tmp != NULL because maxdots > 0; we check to quiet linters */ >+ if (tmp == NULL) { >+ ret = HDB_ERR_NOENTRY; >+ goto out; >+ } > tmp++; > hdots--; > } > >- if (baseprinc == NULL) >+ if (nsprinc == NULL) > /* First go around, need a namespace princ. Make it! */ >- ret2 = make_namespace_princ(context, db, tmpprinc, &baseprinc); >- /* Update the hostname component */ >+ ret2 = make_namespace_princ(context, db, tmpprinc, &nsprinc); >+ >+ /* Update the hostname component of the namespace principal */ > if (ret2 == 0) >- ret2 = krb5_principal_set_comp_string(context, baseprinc, 3, tmp); >+ ret2 = krb5_principal_set_comp_string(context, nsprinc, 3, tmp); > if (ret2) > ret = ret2; > >@@ -1425,14 +1562,22 @@ fetch_it(krb5_context context, > * key derivation to do, but that's decided in derive_keys(). > */ > if (ret == 0) { >- ret = derive_keys(context, flags, princ, !!baseprinc, t, etype, kvno, >- ent); >+ /* Fix the principal name if namespaced */ >+ ret = fix_princ_name(context, princ, nsprinc, ent); >+ >+ /* Derive keys if namespaced or virtual */ > if (ret == 0) >- ret = fix_keys(context, db, flags, t, kvno, ent); >- if (ret) >- hdb_free_entry(context, ent); >+ ret = derive_keys(context, flags, princ, !!nsprinc, t, etype, kvno, >+ ent); >+ /* Pick the best kvno for this principal at the given time */ >+ if (ret == 0) >+ ret = pick_kvno(context, db, flags, t, kvno, ent); > } >- krb5_free_principal(context, baseprinc); >+ >+out: >+ if (ret != 0 && ret != HDB_ERR_WRONG_REALM) >+ hdb_free_entry(context, db, ent); >+ krb5_free_principal(context, nsprinc); > free(host); > return ret; > } >@@ -1468,7 +1613,7 @@ hdb_fetch_kvno(krb5_context context, > krb5_timestamp t, > krb5int32 etype, > krb5uint32 kvno, >- hdb_entry_ex *h) >+ hdb_entry *h) > { > krb5_error_code ret = HDB_ERR_NOENTRY; > >@@ -1485,8 +1630,8 @@ hdb_fetch_kvno(krb5_context context, > * independently of principal aliases (used by Samba). > */ > if (ret == 0 && !(flags & HDB_F_ADMIN_DATA) && >- !h->entry.flags.force_canonicalize && >- !krb5_realm_compare(context, principal, h->entry.principal)) >+ !h->flags.force_canonicalize && >+ !krb5_realm_compare(context, principal, h->principal)) > ret = HDB_ERR_WRONG_REALM; > return ret; > } >diff --git a/third_party/heimdal/lib/hdb/db.c b/third_party/heimdal/lib/hdb/db.c >index 6e415b95f169..5fcce7b8e8b3 100644 >--- a/third_party/heimdal/lib/hdb/db.c >+++ b/third_party/heimdal/lib/hdb/db.c >@@ -114,7 +114,7 @@ DB_unlock(krb5_context context, HDB *db) > > static krb5_error_code > DB_seq(krb5_context context, HDB *db, >- unsigned flags, hdb_entry_ex *entry, int flag) >+ unsigned flags, hdb_entry *entry, int flag) > { > DB *d = (DB*)db->hdb_db; > DBT key, value; >@@ -138,21 +138,21 @@ DB_seq(krb5_context context, HDB *db, > data.data = value.data; > data.length = value.size; > memset(entry, 0, sizeof(*entry)); >- if (hdb_value2entry(context, &data, &entry->entry)) >+ if (hdb_value2entry(context, &data, entry)) > return DB_seq(context, db, flags, entry, R_NEXT); > if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { >- code = hdb_unseal_keys (context, db, &entry->entry); >+ code = hdb_unseal_keys (context, db, entry); > if (code) >- hdb_free_entry (context, entry); >+ hdb_free_entry (context, db, entry); > } >- if (code == 0 && entry->entry.principal == NULL) { >- entry->entry.principal = malloc(sizeof(*entry->entry.principal)); >- if (entry->entry.principal == NULL) { >+ if (code == 0 && entry->principal == NULL) { >+ entry->principal = malloc(sizeof(*entry->principal)); >+ if (entry->principal == NULL) { > code = ENOMEM; > krb5_set_error_message(context, code, "malloc: out of memory"); >- hdb_free_entry (context, entry); >+ hdb_free_entry (context, db, entry); > } else { >- hdb_key2principal(context, &key_data, entry->entry.principal); >+ hdb_key2principal(context, &key_data, entry->principal); > } > } > return code; >@@ -160,14 +160,14 @@ DB_seq(krb5_context context, HDB *db, > > > static krb5_error_code >-DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > return DB_seq(context, db, flags, entry, R_FIRST); > } > > > static krb5_error_code >-DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > return DB_seq(context, db, flags, entry, R_NEXT); > } >diff --git a/third_party/heimdal/lib/hdb/db3.c b/third_party/heimdal/lib/hdb/db3.c >index 0daa25bbec46..9d0c0a97d9ab 100644 >--- a/third_party/heimdal/lib/hdb/db3.c >+++ b/third_party/heimdal/lib/hdb/db3.c >@@ -136,7 +136,7 @@ DB_unlock(krb5_context context, HDB *db) > > static krb5_error_code > DB_seq(krb5_context context, HDB *db, >- unsigned flags, hdb_entry_ex *entry, int flag) >+ unsigned flags, hdb_entry *entry, int flag) > { > DBT key, value; > DBC *dbcp = db->hdb_dbc; >@@ -156,21 +156,21 @@ DB_seq(krb5_context context, HDB *db, > data.data = value.data; > data.length = value.size; > memset(entry, 0, sizeof(*entry)); >- if (hdb_value2entry(context, &data, &entry->entry)) >+ if (hdb_value2entry(context, &data, entry)) > return DB_seq(context, db, flags, entry, DB_NEXT); > if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { >- code = hdb_unseal_keys (context, db, &entry->entry); >+ code = hdb_unseal_keys (context, db, entry); > if (code) >- hdb_free_entry (context, entry); >+ hdb_free_entry (context, db, entry); > } >- if (entry->entry.principal == NULL) { >- entry->entry.principal = malloc(sizeof(*entry->entry.principal)); >- if (entry->entry.principal == NULL) { >- hdb_free_entry (context, entry); >+ if (entry->principal == NULL) { >+ entry->principal = malloc(sizeof(*entry->principal)); >+ if (entry->principal == NULL) { >+ hdb_free_entry (context, db, entry); > krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); > return ENOMEM; > } else { >- hdb_key2principal(context, &key_data, entry->entry.principal); >+ hdb_key2principal(context, &key_data, entry->principal); > } > } > return 0; >@@ -178,14 +178,14 @@ DB_seq(krb5_context context, HDB *db, > > > static krb5_error_code >-DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > return DB_seq(context, db, flags, entry, DB_FIRST); > } > > > static krb5_error_code >-DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > return DB_seq(context, db, flags, entry, DB_NEXT); > } >diff --git a/third_party/heimdal/lib/hdb/ext.c b/third_party/heimdal/lib/hdb/ext.c >index ec52d35dcba7..48683ef1607f 100644 >--- a/third_party/heimdal/lib/hdb/ext.c >+++ b/third_party/heimdal/lib/hdb/ext.c >@@ -712,7 +712,7 @@ hdb_entry_add_key_rotation(krb5_context context, > { > krb5_error_code ret; > HDB_extension new_ext; >- HDB_extension *ext = 0; >+ HDB_extension *ext = &new_ext; > KeyRotation tmp; > size_t i, sz; > >@@ -734,8 +734,6 @@ hdb_entry_add_key_rotation(krb5_context context, > ext = hdb_find_extension(entry, choice_HDB_extension_data_key_rotation); > if (!ext) > ext = &new_ext; >- else >- krs = &ext->data.u.key_rotation; > } else { > const KeyRotation *prev_kr = &krs->val[0]; > unsigned int last_kvno = 0; >diff --git a/third_party/heimdal/lib/hdb/hdb-keytab.c b/third_party/heimdal/lib/hdb/hdb-keytab.c >index f3cb8fbe61da..c9b469cb1a85 100644 >--- a/third_party/heimdal/lib/hdb/hdb-keytab.c >+++ b/third_party/heimdal/lib/hdb/hdb-keytab.c >@@ -90,14 +90,14 @@ hkt_unlock(krb5_context context, HDB *db) > > static krb5_error_code > hkt_firstkey(krb5_context context, HDB *db, >- unsigned flags, hdb_entry_ex *entry) >+ unsigned flags, hdb_entry *entry) > { > return HDB_ERR_DB_INUSE; > } > > static krb5_error_code > hkt_nextkey(krb5_context context, HDB * db, unsigned flags, >- hdb_entry_ex * entry) >+ hdb_entry * entry) > { > return HDB_ERR_DB_INUSE; > } >@@ -119,7 +119,7 @@ hkt_open(krb5_context context, HDB * db, int flags, mode_t mode) > > static krb5_error_code > hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal, >- unsigned flags, krb5_kvno kvno, hdb_entry_ex * entry) >+ unsigned flags, krb5_kvno kvno, hdb_entry * entry) > { > hdb_keytab k = (hdb_keytab)db->hdb_db; > krb5_error_code ret; >@@ -132,13 +132,13 @@ hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal, > > memset(&ktentry, 0, sizeof(ktentry)); > >- entry->entry.flags.server = 1; >- entry->entry.flags.forwardable = 1; >- entry->entry.flags.renewable = 1; >+ entry->flags.server = 1; >+ entry->flags.forwardable = 1; >+ entry->flags.renewable = 1; > > /* Not recorded in the OD backend, make something up */ > ret = krb5_parse_name(context, "hdb/keytab@WELL-KNOWN:KEYTAB-BACKEND", >- &entry->entry.created_by.principal); >+ &entry->created_by.principal); > if (ret) > goto out; > >@@ -155,7 +155,7 @@ hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal, > goto out; > } > >- ret = krb5_copy_principal(context, principal, &entry->entry.principal); >+ ret = krb5_copy_principal(context, principal, &entry->principal); > if (ret) > goto out; > >@@ -163,8 +163,8 @@ hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal, > > out: > if (ret) { >- free_HDB_entry(&entry->entry); >- memset(&entry->entry, 0, sizeof(entry->entry)); >+ free_HDB_entry(entry); >+ memset(entry, 0, sizeof(*entry)); > } > krb5_kt_free_entry(context, &ktentry); > >@@ -173,7 +173,7 @@ hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal, > > static krb5_error_code > hkt_store(krb5_context context, HDB * db, unsigned flags, >- hdb_entry_ex * entry) >+ hdb_entry * entry) > { > return HDB_ERR_DB_INUSE; > } >diff --git a/third_party/heimdal/lib/hdb/hdb-ldap.c b/third_party/heimdal/lib/hdb/hdb-ldap.c >index 1dbb00d3e5f7..6a2876c51d71 100644 >--- a/third_party/heimdal/lib/hdb/hdb-ldap.c >+++ b/third_party/heimdal/lib/hdb/hdb-ldap.c >@@ -47,7 +47,7 @@ static krb5_error_code LDAP_close(krb5_context context, HDB *); > > static krb5_error_code > LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, >- int flags, hdb_entry_ex * ent); >+ int flags, hdb_entry * ent); > > static const char *default_structural_object = "account"; > static char *structural_object; >@@ -388,14 +388,14 @@ bervalstrcmp(struct berval *v, const char *str) > > > static krb5_error_code >-LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, >+LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry * ent, > LDAPMessage * msg, LDAPMod *** pmods, krb5_boolean *pis_new_entry) > { > krb5_error_code ret; > krb5_boolean is_new_entry = FALSE; > char *tmp = NULL; > LDAPMod **mods = NULL; >- hdb_entry_ex orig; >+ hdb_entry orig; > unsigned long oflags, nflags; > int i; > >@@ -477,12 +477,12 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > } > > if (is_new_entry || >- krb5_principal_compare(context, ent->entry.principal, orig.entry.principal) >+ krb5_principal_compare(context, ent->principal, orig.principal) > == FALSE) > { > if (is_heimdal_principal || is_heimdal_entry) { > >- ret = krb5_unparse_name(context, ent->entry.principal, &tmp); >+ ret = krb5_unparse_name(context, ent->principal, &tmp); > if (ret) > goto out; > >@@ -496,7 +496,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > } > > if (is_account || is_samba_account) { >- ret = krb5_unparse_name_short(context, ent->entry.principal, &tmp); >+ ret = krb5_unparse_name_short(context, ent->principal, &tmp); > if (ret) > goto out; > ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "uid", tmp); >@@ -508,15 +508,15 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > } > } > >- if (is_heimdal_entry && (ent->entry.kvno != orig.entry.kvno || is_new_entry)) { >+ if (is_heimdal_entry && (ent->kvno != orig.kvno || is_new_entry)) { > ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, > "krb5KeyVersionNumber", >- ent->entry.kvno); >+ ent->kvno); > if (ret) > goto out; > } > >- if (is_heimdal_entry && ent->entry.extensions) { >+ if (is_heimdal_entry && ent->extensions) { > if (!is_new_entry) { > vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5ExtendedAttributes"); > if (vals) { >@@ -527,11 +527,11 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > } > } > >- for (i = 0; i < ent->entry.extensions->len; i++) { >+ for (i = 0; i < ent->extensions->len; i++) { > unsigned char *buf; > size_t size, sz = 0; > >- ASN1_MALLOC_ENCODE(HDB_extension, buf, size, &ent->entry.extensions->val[i], &sz, ret); >+ ASN1_MALLOC_ENCODE(HDB_extension, buf, size, &ent->extensions->val[i], &sz, ret); > if (ret) > goto out; > if (size != sz) >@@ -543,42 +543,42 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > } > } > >- if (is_heimdal_entry && ent->entry.valid_start) { >- if (orig.entry.valid_end == NULL >- || (*(ent->entry.valid_start) != *(orig.entry.valid_start))) { >+ if (is_heimdal_entry && ent->valid_start) { >+ if (orig.valid_end == NULL >+ || (*(ent->valid_start) != *(orig.valid_start))) { > ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, > "krb5ValidStart", >- ent->entry.valid_start); >+ ent->valid_start); > if (ret) > goto out; > } > } > >- if (ent->entry.valid_end) { >- if (orig.entry.valid_end == NULL || (*(ent->entry.valid_end) != *(orig.entry.valid_end))) { >+ if (ent->valid_end) { >+ if (orig.valid_end == NULL || (*(ent->valid_end) != *(orig.valid_end))) { > if (is_heimdal_entry) { > ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, > "krb5ValidEnd", >- ent->entry.valid_end); >+ ent->valid_end); > if (ret) > goto out; > } > if (is_samba_account) { > ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, > "sambaKickoffTime", >- *(ent->entry.valid_end)); >+ *(ent->valid_end)); > if (ret) > goto out; > } > } > } > >- if (ent->entry.pw_end) { >- if (orig.entry.pw_end == NULL || (*(ent->entry.pw_end) != *(orig.entry.pw_end))) { >+ if (ent->pw_end) { >+ if (orig.pw_end == NULL || (*(ent->pw_end) != *(orig.pw_end))) { > if (is_heimdal_entry) { > ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, > "krb5PasswordEnd", >- ent->entry.pw_end); >+ ent->pw_end); > if (ret) > goto out; > } >@@ -586,7 +586,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > if (is_samba_account) { > ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, > "sambaPwdMustChange", >- *(ent->entry.pw_end)); >+ *(ent->pw_end)); > if (ret) > goto out; > } >@@ -595,43 +595,43 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > > > #if 0 /* we we have last_pw_change */ >- if (is_samba_account && ent->entry.last_pw_change) { >- if (orig.entry.last_pw_change == NULL || (*(ent->entry.last_pw_change) != *(orig.entry.last_pw_change))) { >+ if (is_samba_account && ent->last_pw_change) { >+ if (orig.last_pw_change == NULL || (*(ent->last_pw_change) != *(orig.last_pw_change))) { > ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, > "sambaPwdLastSet", >- *(ent->entry.last_pw_change)); >+ *(ent->last_pw_change)); > if (ret) > goto out; > } > } > #endif > >- if (is_heimdal_entry && ent->entry.max_life) { >- if (orig.entry.max_life == NULL >- || (*(ent->entry.max_life) != *(orig.entry.max_life))) { >+ if (is_heimdal_entry && ent->max_life) { >+ if (orig.max_life == NULL >+ || (*(ent->max_life) != *(orig.max_life))) { > > ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, > "krb5MaxLife", >- *(ent->entry.max_life)); >+ *(ent->max_life)); > if (ret) > goto out; > } > } > >- if (is_heimdal_entry && ent->entry.max_renew) { >- if (orig.entry.max_renew == NULL >- || (*(ent->entry.max_renew) != *(orig.entry.max_renew))) { >+ if (is_heimdal_entry && ent->max_renew) { >+ if (orig.max_renew == NULL >+ || (*(ent->max_renew) != *(orig.max_renew))) { > > ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, > "krb5MaxRenew", >- *(ent->entry.max_renew)); >+ *(ent->max_renew)); > if (ret) > goto out; > } > } > >- oflags = HDBFlags2int(orig.entry.flags); >- nflags = HDBFlags2int(ent->entry.flags); >+ oflags = HDBFlags2int(orig.flags); >+ nflags = HDBFlags2int(ent->flags); > > if (is_heimdal_entry && oflags != nflags) { > >@@ -643,7 +643,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > } > > /* Remove keys if they exists, and then replace keys. */ >- if (!is_new_entry && orig.entry.keys.len > 0) { >+ if (!is_new_entry && orig.keys.len > 0) { > vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key"); > if (vals) { > ldap_value_free_len(vals); >@@ -654,21 +654,21 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > } > } > >- for (i = 0; i < ent->entry.keys.len; i++) { >+ for (i = 0; i < ent->keys.len; i++) { > > if (is_samba_account >- && ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { >+ && ent->keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { > char *ntHexPassword; > char *nt; > time_t now = time(NULL); > > /* the key might have been 'sealed', but samba passwords > are clear in the directory */ >- ret = hdb_unseal_key(context, db, &ent->entry.keys.val[i]); >+ ret = hdb_unseal_key(context, db, &ent->keys.val[i]); > if (ret) > goto out; > >- nt = ent->entry.keys.val[i].key.keyvalue.data; >+ nt = ent->keys.val[i].key.keyvalue.data; > /* store in ntPassword, not krb5key */ > ret = hex_encode(nt, 16, &ntHexPassword); > if (ret < 0) { >@@ -701,7 +701,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > unsigned char *buf; > size_t len, buf_size; > >- ASN1_MALLOC_ENCODE(Key, buf, buf_size, &ent->entry.keys.val[i], &len, ret); >+ ASN1_MALLOC_ENCODE(Key, buf, buf_size, &ent->keys.val[i], &len, ret); > if (ret) > goto out; > if(buf_size != len) >@@ -714,7 +714,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > } > } > >- if (ent->entry.etypes) { >+ if (ent->etypes) { > int add_krb5EncryptionType = 0; > > /* >@@ -736,15 +736,15 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > add_krb5EncryptionType = 1; > > if (add_krb5EncryptionType) { >- for (i = 0; i < ent->entry.etypes->len; i++) { >+ for (i = 0; i < ent->etypes->len; i++) { > if (is_samba_account && >- ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) >+ ent->keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) > { > ; > } else if (is_heimdal_entry) { > ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_ADD, > "krb5EncryptionType", >- ent->entry.etypes->val[i]); >+ ent->etypes->val[i]); > if (ret) > goto out; > } >@@ -767,7 +767,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, > } > > if (msg) >- hdb_free_entry(context, &orig); >+ hdb_free_entry(context, db, &orig); > > return ret; > } >@@ -1005,7 +1005,7 @@ LDAP_principal2message(krb5_context context, HDB * db, > */ > static krb5_error_code > LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, >- int flags, hdb_entry_ex * ent) >+ int flags, hdb_entry * ent) > { > char *unparsed_name = NULL, *dn = NULL, *ntPasswordIN = NULL; > char *samba_acct_flags = NULL; >@@ -1015,18 +1015,18 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, > int tmp, tmp_time, i, ret, have_arcfour = 0; > > memset(ent, 0, sizeof(*ent)); >- ent->entry.flags = int2HDBFlags(0); >+ ent->flags = int2HDBFlags(0); > > ret = LDAP_get_string_value(db, msg, "krb5PrincipalName", &unparsed_name); > if (ret == 0) { >- ret = krb5_parse_name(context, unparsed_name, &ent->entry.principal); >+ ret = krb5_parse_name(context, unparsed_name, &ent->principal); > if (ret) > goto out; > } else { > ret = LDAP_get_string_value(db, msg, "uid", > &unparsed_name); > if (ret == 0) { >- ret = krb5_parse_name(context, unparsed_name, &ent->entry.principal); >+ ret = krb5_parse_name(context, unparsed_name, &ent->principal); > if (ret) > goto out; > } else { >@@ -1042,25 +1042,25 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, > ret = LDAP_get_integer_value(db, msg, "krb5KeyVersionNumber", > &integer); > if (ret) >- ent->entry.kvno = 0; >+ ent->kvno = 0; > else >- ent->entry.kvno = integer; >+ ent->kvno = integer; > } > > keys = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key"); > if (keys != NULL) { > size_t l; > >- ent->entry.keys.len = ldap_count_values_len(keys); >- ent->entry.keys.val = (Key *) calloc(ent->entry.keys.len, sizeof(Key)); >- if (ent->entry.keys.val == NULL) { >+ ent->keys.len = ldap_count_values_len(keys); >+ ent->keys.val = (Key *) calloc(ent->keys.len, sizeof(Key)); >+ if (ent->keys.val == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "calloc: out of memory"); > goto out; > } >- for (i = 0; i < ent->entry.keys.len; i++) { >+ for (i = 0; i < ent->keys.len; i++) { > decode_Key((unsigned char *) keys[i]->bv_val, >- (size_t) keys[i]->bv_len, &ent->entry.keys.val[i], &l); >+ (size_t) keys[i]->bv_len, &ent->keys.val[i], &l); > } > ber_bvecfree(keys); > } else { >@@ -1070,8 +1070,8 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, > * be related to a general directory entry without creating > * the keys. Hopefully it's OK. > */ >- ent->entry.keys.len = 0; >- ent->entry.keys.val = NULL; >+ ent->keys.len = 0; >+ ent->keys.val = NULL; > #else > ret = HDB_ERR_NOENTRY; > goto out; >@@ -1082,47 +1082,47 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, > if (extensions != NULL) { > size_t l; > >- ent->entry.extensions = calloc(1, sizeof(*(ent->entry.extensions))); >- if (ent->entry.extensions == NULL) { >+ ent->extensions = calloc(1, sizeof(*(ent->extensions))); >+ if (ent->extensions == NULL) { > ret = krb5_enomem(context); > goto out; > } >- ent->entry.extensions->len = ldap_count_values_len(extensions); >- ent->entry.extensions->val = (HDB_extension *) calloc(ent->entry.extensions->len, sizeof(HDB_extension)); >- if (ent->entry.extensions->val == NULL) { >- ent->entry.extensions->len = 0; >+ ent->extensions->len = ldap_count_values_len(extensions); >+ ent->extensions->val = (HDB_extension *) calloc(ent->extensions->len, sizeof(HDB_extension)); >+ if (ent->extensions->val == NULL) { >+ ent->extensions->len = 0; > ret = krb5_enomem(context); > goto out; > } >- for (i = 0; i < ent->entry.extensions->len; i++) { >+ for (i = 0; i < ent->extensions->len; i++) { > ret = decode_HDB_extension((unsigned char *) extensions[i]->bv_val, >- (size_t) extensions[i]->bv_len, &ent->entry.extensions->val[i], &l); >+ (size_t) extensions[i]->bv_len, &ent->extensions->val[i], &l); > if (ret) > krb5_set_error_message(context, ret, "decode_HDB_extension failed"); > } > ber_bvecfree(extensions); > } else { >- ent->entry.extensions = NULL; >+ ent->extensions = NULL; > } > > vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5EncryptionType"); > if (vals != NULL) { >- ent->entry.etypes = malloc(sizeof(*(ent->entry.etypes))); >- if (ent->entry.etypes == NULL) { >+ ent->etypes = malloc(sizeof(*(ent->etypes))); >+ if (ent->etypes == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret,"malloc: out of memory"); > goto out; > } >- ent->entry.etypes->len = ldap_count_values_len(vals); >- ent->entry.etypes->val = calloc(ent->entry.etypes->len, >- sizeof(ent->entry.etypes->val[0])); >- if (ent->entry.etypes->val == NULL) { >+ ent->etypes->len = ldap_count_values_len(vals); >+ ent->etypes->val = calloc(ent->etypes->len, >+ sizeof(ent->etypes->val[0])); >+ if (ent->etypes->val == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); >- ent->entry.etypes->len = 0; >+ ent->etypes->len = 0; > goto out; > } >- for (i = 0; i < ent->entry.etypes->len; i++) { >+ for (i = 0; i < ent->etypes->len; i++) { > char *buf; > > buf = malloc(vals[i]->bv_len + 1); >@@ -1133,14 +1133,14 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, > } > memcpy(buf, vals[i]->bv_val, vals[i]->bv_len); > buf[vals[i]->bv_len] = '\0'; >- ent->entry.etypes->val[i] = atoi(buf); >+ ent->etypes->val[i] = atoi(buf); > free(buf); > } > ldap_value_free_len(vals); > } > >- for (i = 0; i < ent->entry.keys.len; i++) { >- if (ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { >+ for (i = 0; i < ent->keys.len; i++) { >+ if (ent->keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { > have_arcfour = 1; > break; > } >@@ -1152,146 +1152,151 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, > unsigned *etypes; > Key *ks; > >- ks = realloc(ent->entry.keys.val, >- (ent->entry.keys.len + 1) * >- sizeof(ent->entry.keys.val[0])); >+ ks = realloc(ent->keys.val, >+ (ent->keys.len + 1) * >+ sizeof(ent->keys.val[0])); > if (ks == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } >- ent->entry.keys.val = ks; >- memset(&ent->entry.keys.val[ent->entry.keys.len], 0, sizeof(Key)); >- ent->entry.keys.val[ent->entry.keys.len].key.keytype = ETYPE_ARCFOUR_HMAC_MD5; >- ret = krb5_data_alloc (&ent->entry.keys.val[ent->entry.keys.len].key.keyvalue, 16); >+ ent->keys.val = ks; >+ memset(&ent->keys.val[ent->keys.len], 0, sizeof(Key)); >+ ent->keys.val[ent->keys.len].key.keytype = ETYPE_ARCFOUR_HMAC_MD5; >+ ret = krb5_data_alloc (&ent->keys.val[ent->keys.len].key.keyvalue, 16); > if (ret) { > krb5_set_error_message(context, ret, "malloc: out of memory"); > ret = ENOMEM; > goto out; > } > ret = hex_decode(ntPasswordIN, >- ent->entry.keys.val[ent->entry.keys.len].key.keyvalue.data, 16); >- ent->entry.keys.len++; >- >- if (ent->entry.etypes == NULL) { >- ent->entry.etypes = malloc(sizeof(*(ent->entry.etypes))); >- if (ent->entry.etypes == NULL) { >+ ent->keys.val[ent->keys.len].key.keyvalue.data, 16); >+ ent->keys.len++; >+ if (ret == -1) { >+ krb5_set_error_message(context, ret = EINVAL, >+ "invalid hex encoding of password"); >+ goto out; >+ } >+ >+ if (ent->etypes == NULL) { >+ ent->etypes = malloc(sizeof(*(ent->etypes))); >+ if (ent->etypes == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } >- ent->entry.etypes->val = NULL; >- ent->entry.etypes->len = 0; >+ ent->etypes->val = NULL; >+ ent->etypes->len = 0; > } > >- for (i = 0; i < ent->entry.etypes->len; i++) >- if (ent->entry.etypes->val[i] == ETYPE_ARCFOUR_HMAC_MD5) >+ for (i = 0; i < ent->etypes->len; i++) >+ if (ent->etypes->val[i] == ETYPE_ARCFOUR_HMAC_MD5) > break; > /* If there is no ARCFOUR enctype, add one */ >- if (i == ent->entry.etypes->len) { >- etypes = realloc(ent->entry.etypes->val, >- (ent->entry.etypes->len + 1) * >- sizeof(ent->entry.etypes->val[0])); >+ if (i == ent->etypes->len) { >+ etypes = realloc(ent->etypes->val, >+ (ent->etypes->len + 1) * >+ sizeof(ent->etypes->val[0])); > if (etypes == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } >- ent->entry.etypes->val = etypes; >- ent->entry.etypes->val[ent->entry.etypes->len] = >+ ent->etypes->val = etypes; >+ ent->etypes->val[ent->etypes->len] = > ETYPE_ARCFOUR_HMAC_MD5; >- ent->entry.etypes->len++; >+ ent->etypes->len++; > } > } > > ret = LDAP_get_generalized_time_value(db, msg, "createTimestamp", >- &ent->entry.created_by.time); >+ &ent->created_by.time); > if (ret) >- ent->entry.created_by.time = time(NULL); >+ ent->created_by.time = time(NULL); > >- ent->entry.created_by.principal = NULL; >+ ent->created_by.principal = NULL; > > if (flags & HDB_F_ADMIN_DATA) { > ret = LDAP_get_string_value(db, msg, "creatorsName", &dn); > if (ret == 0) { >- LDAP_dn2principal(context, db, dn, &ent->entry.created_by.principal); >+ LDAP_dn2principal(context, db, dn, &ent->created_by.principal); > free(dn); > } > >- ent->entry.modified_by = calloc(1, sizeof(*ent->entry.modified_by)); >- if (ent->entry.modified_by == NULL) { >+ ent->modified_by = calloc(1, sizeof(*ent->modified_by)); >+ if (ent->modified_by == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } > > ret = LDAP_get_generalized_time_value(db, msg, "modifyTimestamp", >- &ent->entry.modified_by->time); >+ &ent->modified_by->time); > if (ret == 0) { > ret = LDAP_get_string_value(db, msg, "modifiersName", &dn); > if (ret == 0) { >- LDAP_dn2principal(context, db, dn, &ent->entry.modified_by->principal); >+ LDAP_dn2principal(context, db, dn, &ent->modified_by->principal); > free(dn); > } else { >- free(ent->entry.modified_by); >- ent->entry.modified_by = NULL; >+ free(ent->modified_by); >+ ent->modified_by = NULL; > } > } > } > >- ent->entry.valid_start = malloc(sizeof(*ent->entry.valid_start)); >- if (ent->entry.valid_start == NULL) { >+ ent->valid_start = malloc(sizeof(*ent->valid_start)); >+ if (ent->valid_start == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } > ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidStart", >- ent->entry.valid_start); >+ ent->valid_start); > if (ret) { > /* OPTIONAL */ >- free(ent->entry.valid_start); >- ent->entry.valid_start = NULL; >+ free(ent->valid_start); >+ ent->valid_start = NULL; > } > >- ent->entry.valid_end = malloc(sizeof(*ent->entry.valid_end)); >- if (ent->entry.valid_end == NULL) { >+ ent->valid_end = malloc(sizeof(*ent->valid_end)); >+ if (ent->valid_end == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } > ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidEnd", >- ent->entry.valid_end); >+ ent->valid_end); > if (ret) { > /* OPTIONAL */ >- free(ent->entry.valid_end); >- ent->entry.valid_end = NULL; >+ free(ent->valid_end); >+ ent->valid_end = NULL; > } > > ret = LDAP_get_integer_value(db, msg, "sambaKickoffTime", &tmp_time); > if (ret == 0) { >- if (ent->entry.valid_end == NULL) { >- ent->entry.valid_end = malloc(sizeof(*ent->entry.valid_end)); >- if (ent->entry.valid_end == NULL) { >+ if (ent->valid_end == NULL) { >+ ent->valid_end = malloc(sizeof(*ent->valid_end)); >+ if (ent->valid_end == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } > } >- *ent->entry.valid_end = tmp_time; >+ *ent->valid_end = tmp_time; > } > >- ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end)); >- if (ent->entry.pw_end == NULL) { >+ ent->pw_end = malloc(sizeof(*ent->pw_end)); >+ if (ent->pw_end == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } > ret = LDAP_get_generalized_time_value(db, msg, "krb5PasswordEnd", >- ent->entry.pw_end); >+ ent->pw_end); > if (ret) { > /* OPTIONAL */ >- free(ent->entry.pw_end); >- ent->entry.pw_end = NULL; >+ free(ent->pw_end); >+ ent->pw_end = NULL; > } > > ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet", &tmp_time); >@@ -1305,76 +1310,76 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, > NULL); > > if (delta) { >- if (ent->entry.pw_end == NULL) { >- ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end)); >- if (ent->entry.pw_end == NULL) { >+ if (ent->pw_end == NULL) { >+ ent->pw_end = malloc(sizeof(*ent->pw_end)); >+ if (ent->pw_end == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } > } > >- *ent->entry.pw_end = tmp_time + delta; >+ *ent->pw_end = tmp_time + delta; > } > } > > ret = LDAP_get_integer_value(db, msg, "sambaPwdMustChange", &tmp_time); > if (ret == 0) { >- if (ent->entry.pw_end == NULL) { >- ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end)); >- if (ent->entry.pw_end == NULL) { >+ if (ent->pw_end == NULL) { >+ ent->pw_end = malloc(sizeof(*ent->pw_end)); >+ if (ent->pw_end == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } > } >- *ent->entry.pw_end = tmp_time; >+ *ent->pw_end = tmp_time; > } > > /* OPTIONAL */ > ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet", &tmp_time); > if (ret == 0) >- hdb_entry_set_pw_change_time(context, &ent->entry, tmp_time); >+ hdb_entry_set_pw_change_time(context, ent, tmp_time); > > { > int max_life; > >- ent->entry.max_life = malloc(sizeof(*ent->entry.max_life)); >- if (ent->entry.max_life == NULL) { >+ ent->max_life = malloc(sizeof(*ent->max_life)); >+ if (ent->max_life == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } > ret = LDAP_get_integer_value(db, msg, "krb5MaxLife", &max_life); > if (ret) { >- free(ent->entry.max_life); >- ent->entry.max_life = NULL; >+ free(ent->max_life); >+ ent->max_life = NULL; > } else >- *ent->entry.max_life = max_life; >+ *ent->max_life = max_life; > } > > { > int max_renew; > >- ent->entry.max_renew = malloc(sizeof(*ent->entry.max_renew)); >- if (ent->entry.max_renew == NULL) { >+ ent->max_renew = malloc(sizeof(*ent->max_renew)); >+ if (ent->max_renew == NULL) { > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > goto out; > } > ret = LDAP_get_integer_value(db, msg, "krb5MaxRenew", &max_renew); > if (ret) { >- free(ent->entry.max_renew); >- ent->entry.max_renew = NULL; >+ free(ent->max_renew); >+ ent->max_renew = NULL; > } else >- *ent->entry.max_renew = max_renew; >+ *ent->max_renew = max_renew; > } > > ret = LDAP_get_integer_value(db, msg, "krb5KDCFlags", &tmp); > if (ret) > tmp = 0; > >- ent->entry.flags = int2HDBFlags(tmp); >+ ent->flags = int2HDBFlags(tmp); > > /* Try and find Samba flags to put into the mix */ > ret = LDAP_get_string_value(db, msg, "sambaAcctFlags", &samba_acct_flags); >@@ -1406,7 +1411,7 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, > > /* Allow forwarding */ > if (samba_forwardable) >- ent->entry.flags.forwardable = TRUE; >+ ent->flags.forwardable = TRUE; > > for (i=0; i < flags_len; i++) { > switch (samba_acct_flags[i]) { >@@ -1418,36 +1423,36 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, > /* how to handle no password in kerberos? */ > break; > case 'D': >- ent->entry.flags.invalid = TRUE; >+ ent->flags.invalid = TRUE; > break; > case 'H': > break; > case 'T': > /* temp duplicate */ >- ent->entry.flags.invalid = TRUE; >+ ent->flags.invalid = TRUE; > break; > case 'U': >- ent->entry.flags.client = TRUE; >+ ent->flags.client = TRUE; > break; > case 'M': > break; > case 'W': > case 'S': >- ent->entry.flags.server = TRUE; >- ent->entry.flags.client = TRUE; >+ ent->flags.server = TRUE; >+ ent->flags.client = TRUE; > break; > case 'L': >- ent->entry.flags.invalid = TRUE; >+ ent->flags.invalid = TRUE; > break; > case 'X': >- if (ent->entry.pw_end) { >- free(ent->entry.pw_end); >- ent->entry.pw_end = NULL; >+ if (ent->pw_end) { >+ free(ent->pw_end); >+ ent->pw_end = NULL; > } > break; > case 'I': >- ent->entry.flags.server = TRUE; >- ent->entry.flags.client = TRUE; >+ ent->flags.server = TRUE; >+ ent->flags.client = TRUE; > break; > } > } >@@ -1462,7 +1467,7 @@ out: > free(ntPasswordIN); > > if (ret) >- hdb_free_entry(context, ent); >+ hdb_free_entry(context, db, ent); > > return ret; > } >@@ -1491,7 +1496,7 @@ LDAP_unlock(krb5_context context, HDB * db) > } > > static krb5_error_code >-LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry_ex * entry) >+LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry * entry) > { > int msgid, rc, parserc; > krb5_error_code ret; >@@ -1545,9 +1550,9 @@ LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry_ex * entry) > > if (ret == 0) { > if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { >- ret = hdb_unseal_keys(context, db, &entry->entry); >+ ret = hdb_unseal_keys(context, db, entry); > if (ret) >- hdb_free_entry(context, entry); >+ hdb_free_entry(context, db, entry); > } > } > >@@ -1556,7 +1561,7 @@ LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry_ex * entry) > > static krb5_error_code > LDAP_firstkey(krb5_context context, HDB *db, unsigned flags, >- hdb_entry_ex *entry) >+ hdb_entry *entry) > { > krb5_error_code ret; > int msgid; >@@ -1584,7 +1589,7 @@ LDAP_firstkey(krb5_context context, HDB *db, unsigned flags, > > static krb5_error_code > LDAP_nextkey(krb5_context context, HDB * db, unsigned flags, >- hdb_entry_ex * entry) >+ hdb_entry * entry) > { > return LDAP_seq(context, db, flags, entry); > } >@@ -1687,7 +1692,7 @@ LDAP_open(krb5_context context, HDB * db, int flags, mode_t mode) > > static krb5_error_code > LDAP_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal, >- unsigned flags, krb5_kvno kvno, hdb_entry_ex * entry) >+ unsigned flags, krb5_kvno kvno, hdb_entry * entry) > { > LDAPMessage *msg, *e; > krb5_error_code ret; >@@ -1705,9 +1710,9 @@ LDAP_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal, > ret = LDAP_message2entry(context, db, e, flags, entry); > if (ret == 0) { > if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { >- ret = hdb_unseal_keys(context, db, &entry->entry); >+ ret = hdb_unseal_keys(context, db, entry); > if (ret) >- hdb_free_entry(context, entry); >+ hdb_free_entry(context, db, entry); > } > } > >@@ -1720,7 +1725,7 @@ LDAP_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal, > #if 0 > static krb5_error_code > LDAP_fetch(krb5_context context, HDB * db, krb5_const_principal principal, >- unsigned flags, hdb_entry_ex * entry) >+ unsigned flags, hdb_entry * entry) > { > return LDAP_fetch_kvno(context, db, principal, > flags & (~HDB_F_KVNO_SPECIFIED), 0, entry); >@@ -1729,7 +1734,7 @@ LDAP_fetch(krb5_context context, HDB * db, krb5_const_principal principal, > > static krb5_error_code > LDAP_store(krb5_context context, HDB * db, unsigned flags, >- hdb_entry_ex * entry) >+ hdb_entry * entry) > { > LDAPMod **mods = NULL; > krb5_error_code ret; >@@ -1742,17 +1747,17 @@ LDAP_store(krb5_context context, HDB * db, unsigned flags, > if ((flags & HDB_F_PRECHECK)) > return 0; /* we can't guarantee whether we'll be able to perform it */ > >- ret = LDAP_principal2message(context, db, entry->entry.principal, &msg); >+ ret = LDAP_principal2message(context, db, entry->principal, &msg); > if (ret == 0) > e = ldap_first_entry(HDB2LDAP(db), msg); > >- ret = krb5_unparse_name(context, entry->entry.principal, &name); >+ ret = krb5_unparse_name(context, entry->principal, &name); > if (ret) { > free(name); > return ret; > } > >- ret = hdb_seal_keys(context, db, &entry->entry); >+ ret = hdb_seal_keys(context, db, entry); > if (ret) > goto out; > >diff --git a/third_party/heimdal/lib/hdb/hdb-mdb.c b/third_party/heimdal/lib/hdb/hdb-mdb.c >index cabda277f4ee..6aa5201eb8a5 100644 >--- a/third_party/heimdal/lib/hdb/hdb-mdb.c >+++ b/third_party/heimdal/lib/hdb/hdb-mdb.c >@@ -383,7 +383,7 @@ DB_unlock(krb5_context context, HDB *db) > > static krb5_error_code > DB_seq(krb5_context context, HDB *db, >- unsigned flags, hdb_entry_ex *entry, int flag) >+ unsigned flags, hdb_entry *entry, int flag) > { > mdb_info *mi = db->hdb_db; > MDB_val key, value; >@@ -406,21 +406,21 @@ DB_seq(krb5_context context, HDB *db, > data.data = value.mv_data; > data.length = value.mv_size; > memset(entry, 0, sizeof(*entry)); >- if (hdb_value2entry(context, &data, &entry->entry)) >+ if (hdb_value2entry(context, &data, entry)) > return DB_seq(context, db, flags, entry, MDB_NEXT); > if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { >- code = hdb_unseal_keys (context, db, &entry->entry); >+ code = hdb_unseal_keys (context, db, entry); > if (code) >- hdb_free_entry (context, entry); >+ hdb_free_entry (context, db, entry); > } >- if (entry->entry.principal == NULL) { >- entry->entry.principal = malloc(sizeof(*entry->entry.principal)); >- if (entry->entry.principal == NULL) { >- hdb_free_entry (context, entry); >+ if (entry->principal == NULL) { >+ entry->principal = malloc(sizeof(*entry->principal)); >+ if (entry->principal == NULL) { >+ hdb_free_entry (context, db, entry); > krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); > return ENOMEM; > } else { >- hdb_key2principal(context, &key_data, entry->entry.principal); >+ hdb_key2principal(context, &key_data, entry->principal); > } > } > return 0; >@@ -428,7 +428,7 @@ DB_seq(krb5_context context, HDB *db, > > > static krb5_error_code >-DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > krb5_error_code ret = 0; > mdb_info *mi = db->hdb_db; >@@ -462,7 +462,7 @@ DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) > > > static krb5_error_code >-DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > return DB_seq(context, db, flags, entry, MDB_NEXT); > } >diff --git a/third_party/heimdal/lib/hdb/hdb-mitdb.c b/third_party/heimdal/lib/hdb/hdb-mitdb.c >index 1ae013157c2b..7436f39edbbe 100644 >--- a/third_party/heimdal/lib/hdb/hdb-mitdb.c >+++ b/third_party/heimdal/lib/hdb/hdb-mitdb.c >@@ -555,7 +555,7 @@ _hdb_mdb_value2entry(krb5_context context, krb5_data *data, > goto out; > } > CHECK(ret = krb5_parse_name(context, p, &modby)); >- ret = hdb_set_last_modified_by(context, entry, modby, u32); >+ CHECK(ret = hdb_set_last_modified_by(context, entry, modby, u32)); > krb5_free_principal(context, modby); > free(p); > break; >@@ -765,7 +765,7 @@ mdb_unlock(krb5_context context, HDB *db) > > static krb5_error_code > mdb_seq(krb5_context context, HDB *db, >- unsigned flags, hdb_entry_ex *entry, int flag) >+ unsigned flags, hdb_entry *entry, int flag) > { > DB *d = (DB*)db->hdb_db; > DBT key, value; >@@ -796,13 +796,13 @@ mdb_seq(krb5_context context, HDB *db, > data.length = value.size; > memset(entry, 0, sizeof(*entry)); > >- if (_hdb_mdb_value2entry(context, &data, 0, &entry->entry)) >+ if (_hdb_mdb_value2entry(context, &data, 0, entry)) > return mdb_seq(context, db, flags, entry, R_NEXT); > > if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { >- code = hdb_unseal_keys (context, db, &entry->entry); >+ code = hdb_unseal_keys (context, db, entry); > if (code) >- hdb_free_entry (context, entry); >+ hdb_free_entry (context, db, entry); > } > > return code; >@@ -810,14 +810,14 @@ mdb_seq(krb5_context context, HDB *db, > > > static krb5_error_code >-mdb_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+mdb_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > return mdb_seq(context, db, flags, entry, R_FIRST); > } > > > static krb5_error_code >-mdb_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+mdb_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > return mdb_seq(context, db, flags, entry, R_NEXT); > } >@@ -941,7 +941,7 @@ mdb__del(krb5_context context, HDB *db, krb5_data key) > > static krb5_error_code > mdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, >- unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry) >+ unsigned flags, krb5_kvno kvno, hdb_entry *entry) > { > krb5_data key, value; > krb5_error_code ret; >@@ -953,15 +953,15 @@ mdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, > krb5_data_free(&key); > if(ret) > return ret; >- ret = _hdb_mdb_value2entry(context, &value, kvno, &entry->entry); >+ ret = _hdb_mdb_value2entry(context, &value, kvno, entry); > krb5_data_free(&value); > if (ret) > return ret; > > if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { >- ret = hdb_unseal_keys (context, db, &entry->entry); >+ ret = hdb_unseal_keys (context, db, entry); > if (ret) { >- hdb_free_entry(context, entry); >+ hdb_free_entry(context, db, entry); > return ret; > } > } >@@ -970,7 +970,7 @@ mdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, > } > > static krb5_error_code >-mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > krb5_error_code ret; > krb5_storage *sp = NULL; >@@ -985,7 +985,7 @@ mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) > return 0; > > if ((flags & HDB_F_PRECHECK)) { >- ret = mdb_principal2key(context, entry->entry.principal, &key); >+ ret = mdb_principal2key(context, entry->principal, &key); > if (ret) return ret; > ret = db->hdb__get(context, db, key, &value); > krb5_data_free(&key); >@@ -999,9 +999,9 @@ mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) > sp = krb5_storage_emem(); > if (!sp) return ENOMEM; > ret = _hdb_set_master_key_usage(context, db, 0); /* MIT KDB uses KU 0 */ >- ret = hdb_seal_keys(context, db, &entry->entry); >+ ret = hdb_seal_keys(context, db, entry); > if (ret) return ret; >- ret = entry2mit_string_int(context, sp, &entry->entry); >+ ret = entry2mit_string_int(context, sp, entry); > if (ret) goto out; > sz = krb5_storage_write(sp, "\n", 2); /* NUL-terminate */ > ret = ENOMEM; >@@ -1016,7 +1016,7 @@ mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) > if (ret) goto out; > ret = krb5_storage_to_data(spent, &kdb_ent); > if (ret) goto out; >- ret = mdb_principal2key(context, entry->entry.principal, &key); >+ ret = mdb_principal2key(context, entry->principal, &key); > if (ret) goto out; > ret = mdb__put(context, db, 1, key, kdb_ent); > >@@ -1253,17 +1253,16 @@ getdata(char **p, unsigned char *buf, size_t len, const char *what) > } > > static int >-getint(char **p, const char *what) >+getint(char **p, const char *what, int *val) > { >- int val; > char *q = nexttoken(p, 0, what); > if (!q) { > warnx("Failed to find a signed integer (%s) in dump", what); >- return -1; >+ return 1; > } >- if (sscanf(q, "%d", &val) != 1) >- return -1; >- return val; >+ if (sscanf(q, "%d", val) != 1) >+ return 1; >+ return 0; > } > > static unsigned int >@@ -1327,7 +1326,7 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp) > "'policy', nor 'princ'"); > return -1; > } >- if (getint(&p, "constant '38'") != 38) { >+ if (getint(&p, "constant '38'", &tmp) || tmp != 38) { > warnx("Dump entry does not start with '38<TAB>'"); > return EINVAL; > } >@@ -1343,7 +1342,7 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp) > } > num_tl_data = getuint(&p, "number of TL data"); > num_key_data = getuint(&p, "number of key data"); >- getint(&p, "5th field, length of 'extra data'"); >+ (void) getint(&p, "5th field, length of 'extra data'", &tmp); > princ = nexttoken(&p, (int)princ_len, "principal name"); > if (princ == NULL) { > warnx("Failed to read principal name (expected length %llu)", >@@ -1355,38 +1354,31 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp) > ret = krb5_store_uint32(sp, attributes); > if (ret) return ret; > >- tmp = getint(&p, "max life"); >- CHECK_UINT(tmp); >+ if (getint(&p, "max life", &tmp)) return EINVAL; > ret = krb5_store_uint32(sp, tmp); > if (ret) return ret; > >- tmp = getint(&p, "max renewable life"); >- CHECK_UINT(tmp); >+ if (getint(&p, "max renewable life", &tmp)) return EINVAL; > ret = krb5_store_uint32(sp, tmp); > if (ret) return ret; > >- tmp = getint(&p, "expiration"); >- CHECK_UINT(tmp); >+ if (getint(&p, "expiration", &tmp)) return EINVAL; > ret = krb5_store_uint32(sp, tmp); > if (ret) return ret; > >- tmp = getint(&p, "pw expiration"); >- CHECK_UINT(tmp); >+ if (getint(&p, "pw expiration", &tmp)) return EINVAL; > ret = krb5_store_uint32(sp, tmp); > if (ret) return ret; > >- tmp = getint(&p, "last auth"); >- CHECK_UINT(tmp); >+ if (getint(&p, "last auth", &tmp)) return EINVAL; > ret = krb5_store_uint32(sp, tmp); > if (ret) return ret; > >- tmp = getint(&p, "last failed auth"); >- CHECK_UINT(tmp); >+ if (getint(&p, "last failed auth", &tmp)) return EINVAL; > ret = krb5_store_uint32(sp, tmp); > if (ret) return ret; > >- tmp = getint(&p,"fail auth count"); >- CHECK_UINT(tmp); >+ if (getint(&p,"fail auth count", &tmp)) return EINVAL; > ret = krb5_store_uint32(sp, tmp); > if (ret) return ret; > >@@ -1414,8 +1406,9 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp) > int tl_type, tl_length; > unsigned char *buf; > >- tl_type = getint(&p, "TL data type"); >- tl_length = getint(&p, "data length"); >+ if (getint(&p, "TL data type", &tl_type) || >+ getint(&p, "data length", &tl_length)) >+ return EINVAL; > > if (asprintf(&reading_what, "TL data type %d (length %d)", > tl_type, tl_length) < 0) >@@ -1435,8 +1428,10 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp) > if (tl_length) { > buf = malloc(tl_length); > if (!buf) return ENOMEM; >- if (getdata(&p, buf, tl_length, reading_what) != tl_length) >+ if (getdata(&p, buf, tl_length, reading_what) != tl_length) { >+ free(buf); > return EINVAL; >+ } > sz = krb5_storage_write(sp, buf, tl_length); > free(buf); > if (sz != tl_length) return ENOMEM; >@@ -1454,23 +1449,23 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp) > int keylen; > size_t k; > >- key_versions = getint(&p, "key data 'version'"); >+ if (getint(&p, "key data 'version'", &key_versions)) return EINVAL; > CHECK_UINT16(key_versions); > ret = krb5_store_int16(sp, key_versions); > if (ret) return ret; > >- kvno = getint(&p, "kvno"); >+ if (getint(&p, "kvno", &kvno)) return EINVAL; > CHECK_UINT16(kvno); > ret = krb5_store_int16(sp, kvno); > if (ret) return ret; > > for (k = 0; k < key_versions; k++) { >- keytype = getint(&p, "enctype"); >+ if (getint(&p, "enctype", &keytype)) return EINVAL; > CHECK_UINT16(keytype); > ret = krb5_store_int16(sp, keytype); > if (ret) return ret; > >- keylen = getint(&p, "encrypted key length"); >+ if (getint(&p, "encrypted key length", &keylen)) return EINVAL; > CHECK_UINT16(keylen); > ret = krb5_store_int16(sp, keylen); > if (ret) return ret; >@@ -1478,8 +1473,10 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp) > if (keylen) { > buf = malloc(keylen); > if (!buf) return ENOMEM; >- if (getdata(&p, buf, keylen, "key (or salt) data") != keylen) >+ if (getdata(&p, buf, keylen, "key (or salt) data") != keylen) { >+ free(buf); > return EINVAL; >+ } > sz = krb5_storage_write(sp, buf, keylen); > free(buf); > if (sz != keylen) return ENOMEM; >diff --git a/third_party/heimdal/lib/hdb/hdb-sqlite.c b/third_party/heimdal/lib/hdb/hdb-sqlite.c >index 3cab9178965e..4bb2f8e8553c 100644 >--- a/third_party/heimdal/lib/hdb/hdb-sqlite.c >+++ b/third_party/heimdal/lib/hdb/hdb-sqlite.c >@@ -495,7 +495,7 @@ hdb_sqlite_make_database(krb5_context context, HDB *db, const char *filename) > */ > static krb5_error_code > hdb_sqlite_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, >- unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry) >+ unsigned flags, krb5_kvno kvno, hdb_entry *entry) > { > int sqlite_error; > krb5_error_code ret; >@@ -541,14 +541,14 @@ hdb_sqlite_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal princi > value.length = sqlite3_column_bytes(fetch, 0); > value.data = (void *) sqlite3_column_blob(fetch, 0); > >- ret = hdb_value2entry(context, &value, &entry->entry); >+ ret = hdb_value2entry(context, &value, entry); > if(ret) > goto out; > > if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { >- ret = hdb_unseal_keys(context, db, &entry->entry); >+ ret = hdb_unseal_keys(context, db, entry); > if(ret) { >- hdb_free_entry(context, entry); >+ hdb_free_entry(context, db, entry); > goto out; > } > } >@@ -600,7 +600,7 @@ hdb_sqlite_step_once(krb5_context context, HDB *db, sqlite3_stmt *statement) > */ > static krb5_error_code > hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags, >- hdb_entry_ex *entry) >+ hdb_entry *entry) > { > int ret; > int i; >@@ -624,17 +624,17 @@ hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags, > goto rollback; > } > >- ret = hdb_seal_keys(context, db, &entry->entry); >+ ret = hdb_seal_keys(context, db, entry); > if(ret) { > goto rollback; > } > >- ret = hdb_entry2value(context, &entry->entry, &value); >+ ret = hdb_entry2value(context, entry, &value); > if(ret) { > goto rollback; > } > >- ret = bind_principal(context, entry->entry.principal, get_ids, 1); >+ ret = bind_principal(context, entry->principal, get_ids, 1); > if (ret) > goto rollback; > >@@ -656,7 +656,7 @@ hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags, > goto rollback; > } > >- ret = bind_principal(context, entry->entry.principal, hsdb->add_principal, 1); >+ ret = bind_principal(context, entry->principal, hsdb->add_principal, 1); > if (ret) > goto rollback; > >@@ -684,8 +684,10 @@ hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags, > > } else if(ret == SQLITE_ROW) { /* Found a principal */ > >- if(! (flags & HDB_F_REPLACE)) /* Not allowed to replace it */ >+ if(!(flags & HDB_F_REPLACE)) { >+ ret = HDB_ERR_EXISTS; > goto rollback; >+ } > > entry_id = sqlite3_column_int64(get_ids, 1); > >@@ -711,7 +713,7 @@ hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags, > goto rollback; > } > >- ret = hdb_entry_get_aliases(&entry->entry, &aliases); >+ ret = hdb_entry_get_aliases(entry, &aliases); > if(ret || aliases == NULL) > goto commit; > >@@ -862,7 +864,7 @@ hdb_sqlite_unlock(krb5_context context, HDB *db) > */ > static krb5_error_code > hdb_sqlite_nextkey(krb5_context context, HDB *db, unsigned flags, >- hdb_entry_ex *entry) >+ hdb_entry *entry) > { > krb5_error_code ret = 0; > int sqlite_error; >@@ -876,7 +878,7 @@ hdb_sqlite_nextkey(krb5_context context, HDB *db, unsigned flags, > value.length = sqlite3_column_bytes(hsdb->get_all_entries, 0); > value.data = (void *) sqlite3_column_blob(hsdb->get_all_entries, 0); > memset(entry, 0, sizeof(*entry)); >- ret = hdb_value2entry(context, &value, &entry->entry); >+ ret = hdb_value2entry(context, &value, entry); > } > else if(sqlite_error == SQLITE_DONE) { > /* No more entries */ >@@ -900,7 +902,7 @@ hdb_sqlite_nextkey(krb5_context context, HDB *db, unsigned flags, > */ > static krb5_error_code > hdb_sqlite_firstkey(krb5_context context, HDB *db, unsigned flags, >- hdb_entry_ex *entry) >+ hdb_entry *entry) > { > hdb_sqlite_db *hsdb = (hdb_sqlite_db *) db->hdb_db; > krb5_error_code ret; >@@ -950,11 +952,12 @@ hdb_sqlite_remove(krb5_context context, HDB *db, > sqlite3_stmt *get_ids = hsdb->get_ids; > sqlite3_stmt *rm = hsdb->remove; > >- bind_principal(context, principal, rm, 1); >+ ret = bind_principal(context, principal, rm, 1); > >- ret = hdb_sqlite_exec_stmt(context, hsdb, >- "BEGIN IMMEDIATE TRANSACTION", >- HDB_ERR_UK_SERROR); >+ if (ret == 0) >+ ret = hdb_sqlite_exec_stmt(context, hsdb, >+ "BEGIN IMMEDIATE TRANSACTION", >+ HDB_ERR_UK_SERROR); > if (ret != SQLITE_OK) { > ret = HDB_ERR_UK_SERROR; > (void) hdb_sqlite_exec_stmt(context, hsdb, "ROLLBACK", 0); >diff --git a/third_party/heimdal/lib/hdb/hdb.asn1 b/third_party/heimdal/lib/hdb/hdb.asn1 >index f6490783a6cd..9eb96be73d06 100644 >--- a/third_party/heimdal/lib/hdb/hdb.asn1 >+++ b/third_party/heimdal/lib/hdb/hdb.asn1 >@@ -4,7 +4,7 @@ BEGIN > > IMPORTS EncryptionKey, KerberosTime, Principal FROM krb5; > >-HDB_DB_FORMAT INTEGER ::= 2 -- format of database, >+hdb_db_format INTEGER ::= 2 -- format of database, > -- update when making changes > > -- these must have the same value as the pa-* counterparts >diff --git a/third_party/heimdal/lib/hdb/hdb.c b/third_party/heimdal/lib/hdb/hdb.c >index 3978048ad17f..56c403842e60 100644 >--- a/third_party/heimdal/lib/hdb/hdb.c >+++ b/third_party/heimdal/lib/hdb/hdb.c >@@ -232,38 +232,25 @@ hdb_remove_keys(krb5_context context, > * @param context Context > * @param e The HDB entry > * @param ks A pointer to a variable of type HDB_Ext_KeySet >+ * @param ckr A pointer to stable (copied) HDB_Ext_KeyRotation > * > * @return Zero on success, an error code otherwise. > */ > krb5_error_code >-hdb_remove_base_keys(krb5_context context, >- hdb_entry *e, >- HDB_Ext_KeySet *base_keys) >+_hdb_remove_base_keys(krb5_context context, >+ hdb_entry *e, >+ HDB_Ext_KeySet *base_keys, >+ const HDB_Ext_KeyRotation *ckr) > { >- krb5_error_code ret; >- const HDB_Ext_KeyRotation *ckr; >- HDB_Ext_KeyRotation kr; >+ krb5_error_code ret = 0; > size_t i, k; > >- ret = hdb_entry_get_key_rotation(context, e, &ckr); >- if (!ckr) >- return 0; >- >- if (ret == 0) { >- /* >- * Changing the entry's extensions invalidates extensions obtained >- * before the change. >- */ >- ret = copy_HDB_Ext_KeyRotation(ckr, &kr); >- ckr = NULL; >- } > base_keys->len = 0; >- if (ret == 0 && >- (base_keys->val = calloc(kr.len, sizeof(base_keys->val[0]))) == NULL) >+ if ((base_keys->val = calloc(ckr->len, sizeof(base_keys->val[0]))) == NULL) > ret = krb5_enomem(context); > >- for (k = i = 0; ret == 0 && i < kr.len; i++) { >- const KeyRotation *krp = &kr.val[i]; >+ for (k = i = 0; ret == 0 && i < ckr->len; i++) { >+ const KeyRotation *krp = &ckr->val[i]; > > /* > * WARNING: O(N * M) where M is number of keysets and N is the number >@@ -284,7 +271,6 @@ hdb_remove_base_keys(krb5_context context, > base_keys->len = k; > else > free_HDB_Ext_KeySet(base_keys); >- free_HDB_Ext_KeyRotation(&kr); > return 0; > } > >@@ -312,12 +298,12 @@ hdb_install_keyset(krb5_context context, > (ret = hdb_add_current_keys_to_history(context, e))) > return ret; > free_Keys(&e->keys); >+ e->kvno = ks->kvno; > if (ret == 0) > ret = copy_Keys(&ks->keys, &e->keys); >- e->kvno = ks->kvno; >- if (ks->set_time) >- return hdb_entry_set_pw_change_time(context, e, *ks->set_time); >- return 0; >+ if (ret == 0 && ks->set_time) >+ ret = hdb_entry_set_pw_change_time(context, e, *ks->set_time); >+ return ret; > } > return hdb_add_history_keyset(context, e, ks); > } >@@ -359,9 +345,10 @@ hdb_enctype2key(krb5_context context, > void > hdb_free_key(Key *key) > { >- memset(key->key.keyvalue.data, >- 0, >- key->key.keyvalue.length); >+ memset_s(key->key.keyvalue.data, >+ key->key.keyvalue.length, >+ 0, >+ key->key.keyvalue.length); > free_Key(key); > free(key); > } >@@ -396,20 +383,23 @@ hdb_unlock(int fd) > } > > void >-hdb_free_entry(krb5_context context, hdb_entry_ex *ent) >+hdb_free_entry(krb5_context context, HDB *db, hdb_entry *ent) > { > Key *k; > size_t i; > >- if (ent->free_entry) >- (*ent->free_entry)(context, ent); >+ if (db && db->hdb_free_entry_context) >+ db->hdb_free_entry_context(context, db, ent); > >- for(i = 0; i < ent->entry.keys.len; i++) { >- k = &ent->entry.keys.val[i]; >+ for(i = 0; i < ent->keys.len; i++) { >+ k = &ent->keys.val[i]; > >- memset (k->key.keyvalue.data, 0, k->key.keyvalue.length); >+ memset_s(k->key.keyvalue.data, >+ k->key.keyvalue.length, >+ 0, >+ k->key.keyvalue.length); > } >- free_HDB_entry(&ent->entry); >+ free_HDB_entry(ent); > } > > krb5_error_code >@@ -420,13 +410,13 @@ hdb_foreach(krb5_context context, > void *data) > { > krb5_error_code ret; >- hdb_entry_ex entry; >+ hdb_entry entry; > ret = db->hdb_firstkey(context, db, flags, &entry); > if (ret == 0) > krb5_clear_error_message(context); > while(ret == 0){ > ret = (*func)(context, db, &entry, data); >- hdb_free_entry(context, &entry); >+ hdb_free_entry(context, db, &entry); > if(ret == 0) > ret = db->hdb_nextkey(context, db, flags, &entry); > } >@@ -661,22 +651,22 @@ hdb_list_builtin(krb5_context context, char **list) > krb5_error_code > _hdb_keytab2hdb_entry(krb5_context context, > const krb5_keytab_entry *ktentry, >- hdb_entry_ex *entry) >+ hdb_entry *entry) > { >- entry->entry.kvno = ktentry->vno; >- entry->entry.created_by.time = ktentry->timestamp; >+ entry->kvno = ktentry->vno; >+ entry->created_by.time = ktentry->timestamp; > >- entry->entry.keys.val = calloc(1, sizeof(entry->entry.keys.val[0])); >- if (entry->entry.keys.val == NULL) >+ entry->keys.val = calloc(1, sizeof(entry->keys.val[0])); >+ if (entry->keys.val == NULL) > return ENOMEM; >- entry->entry.keys.len = 1; >+ entry->keys.len = 1; > >- entry->entry.keys.val[0].mkvno = NULL; >- entry->entry.keys.val[0].salt = NULL; >+ entry->keys.val[0].mkvno = NULL; >+ entry->keys.val[0].salt = NULL; > > return krb5_copy_keyblock_contents(context, > &ktentry->keyblock, >- &entry->entry.keys.val[0].key); >+ &entry->keys.val[0].key); > } > > static krb5_error_code >@@ -789,7 +779,7 @@ hdb_create(krb5_context context, HDB **db, const char *filename) > return ret; > } > for (cb_ctx.h = methods; cb_ctx.h->prefix != NULL; cb_ctx.h++) { >- if (cb_ctx.h->is_file_based && !pathish) >+ if (cb_ctx.h->is_file_based) > continue; > if (!cb_ctx.h->can_taste) > continue; >@@ -805,9 +795,11 @@ hdb_create(krb5_context context, HDB **db, const char *filename) > (*db)->hdb_destroy(context, *db); > *db = NULL; > } >+ if (cb_ctx.h->prefix == NULL) >+ cb_ctx.h = NULL; > } > #ifdef HDB_DEFAULT_DB_TYPE >- if (cb_ctx.h == NULL || cb_ctx.h->prefix == NULL) { >+ if (cb_ctx.h == NULL) { > /* > * If still we've not picked a backend, use a build configuration time > * default. >@@ -815,12 +807,14 @@ hdb_create(krb5_context context, HDB **db, const char *filename) > for (cb_ctx.h = methods; cb_ctx.h->prefix != NULL; cb_ctx.h++) > if (strcmp(cb_ctx.h->prefix, HDB_DEFAULT_DB_TYPE) == 0) > break; >+ if (cb_ctx.h->prefix == NULL) >+ cb_ctx.h = NULL; > } > #endif >- if (cb_ctx.h == NULL || cb_ctx.h->prefix == NULL) >+ if (cb_ctx.h == NULL) > /* Last resort default */ > cb_ctx.h = &default_dbmethod; >- if (cb_ctx.h == NULL || cb_ctx.h->prefix == NULL) { >+ if (cb_ctx.h->prefix == NULL) { > krb5_set_error_message(context, ENOTSUP, > "Could not determine default DB backend for %s", > filename); >diff --git a/third_party/heimdal/lib/hdb/hdb.h b/third_party/heimdal/lib/hdb/hdb.h >index 97ca70c0a7e8..0f2c92151e5f 100644 >--- a/third_party/heimdal/lib/hdb/hdb.h >+++ b/third_party/heimdal/lib/hdb/hdb.h >@@ -42,8 +42,12 @@ > > #include <hdb_err.h> > >+#include <heimbase-svc.h> > #include <heim_asn1.h> > #include <hdb_asn1.h> >+ >+#define HDB_DB_FORMAT hdb_db_format >+ > typedef HDB_keyset hdb_keyset; > typedef HDB_entry hdb_entry; > typedef HDB_entry_alias hdb_entry_alias; >@@ -53,25 +57,26 @@ struct hdb_dbinfo; > enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK }; > > /* flags for various functions */ >-#define HDB_F_DECRYPT 1 /* decrypt keys */ >-#define HDB_F_REPLACE 2 /* replace entry */ >-#define HDB_F_GET_CLIENT 4 /* fetch client */ >-#define HDB_F_GET_SERVER 8 /* fetch server */ >-#define HDB_F_GET_KRBTGT 16 /* fetch krbtgt */ >-#define HDB_F_GET_ANY 28 /* fetch any of client,server,krbtgt */ >-#define HDB_F_CANON 32 /* want canonicalition */ >-#define HDB_F_ADMIN_DATA 64 /* want data that kdc don't use */ >-#define HDB_F_KVNO_SPECIFIED 128 /* we want a particular KVNO */ >-#define HDB_F_CURRENT_KVNO 256 /* we want the current KVNO */ >-#define HDB_F_LIVE_CLNT_KVNOS 512 /* we want all live keys for pre-auth */ >-#define HDB_F_LIVE_SVC_KVNOS 1024 /* we want all live keys for tix */ >-#define HDB_F_ALL_KVNOS 2048 /* we want all the keys, live or not */ >-#define HDB_F_FOR_AS_REQ 4096 /* fetch is for a AS REQ */ >-#define HDB_F_FOR_TGS_REQ 8192 /* fetch is for a TGS REQ */ >-#define HDB_F_PRECHECK 16384 /* check that the operation would succeed */ >-#define HDB_F_DELAY_NEW_KEYS 32768 /* apply [hdb] new_service_key_delay */ >-#define HDB_F_SYNTHETIC_OK 65536 /* synthetic principal for PKINIT or GSS preauth OK */ >-#define HDB_F_GET_FAST_COOKIE 131072 /* fetch the FX-COOKIE key (not a normal principal) */ >+#define HDB_F_DECRYPT 0x00001 /* decrypt keys */ >+#define HDB_F_REPLACE 0x00002 /* replace entry */ >+#define HDB_F_GET_CLIENT 0x00004 /* fetch client */ >+#define HDB_F_GET_SERVER 0x00008 /* fetch server */ >+#define HDB_F_GET_KRBTGT 0x00010 /* fetch krbtgt */ >+#define HDB_F_GET_ANY ( HDB_F_GET_CLIENT | \ >+ HDB_F_GET_SERVER | \ >+ HDB_F_GET_KRBTGT ) /* fetch any of client,server,krbtgt */ >+#define HDB_F_CANON 0x00020 /* want canonicalition */ >+#define HDB_F_ADMIN_DATA 0x00040 /* want data that kdc don't use */ >+#define HDB_F_KVNO_SPECIFIED 0x00080 /* we want a particular KVNO */ >+#define HDB_F_LIVE_CLNT_KVNOS 0x00200 /* we want all live keys for pre-auth */ >+#define HDB_F_LIVE_SVC_KVNOS 0x00400 /* we want all live keys for tix */ >+#define HDB_F_ALL_KVNOS 0x00800 /* we want all the keys, live or not */ >+#define HDB_F_FOR_AS_REQ 0x01000 /* fetch is for a AS REQ */ >+#define HDB_F_FOR_TGS_REQ 0x02000 /* fetch is for a TGS REQ */ >+#define HDB_F_PRECHECK 0x04000 /* check that the operation would succeed */ >+#define HDB_F_DELAY_NEW_KEYS 0x08000 /* apply [hdb] new_service_key_delay */ >+#define HDB_F_SYNTHETIC_OK 0x10000 /* synthetic principal for PKINIT or GSS preauth OK */ >+#define HDB_F_GET_FAST_COOKIE 0x20000 /* fetch the FX-COOKIE key (not a normal principal) */ > > /* hdb_capability_flags */ > #define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1 >@@ -79,78 +84,15 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK }; > #define HDB_CAP_F_PASSWORD_UPDATE_KEYS 4 > #define HDB_CAP_F_SHARED_DIRECTORY 8 > >-/* auth status values */ >- >-/* >- * Un-initialised value, not permitted, used to indicate that a value >- * wasn't set for the benifit of logic in the caller, must not be >- * passed to hdb_auth_status() >- */ >- >-#define HDB_AUTHSTATUS_INVALID 0 >+#define heim_pcontext krb5_context >+#define heim_pconfig void * > >-/* >- * A ticket was issued after authorization was successfully completed >- * (eg flags on the entry and expiry times were checked) >- */ >-#define HDB_AUTHSTATUS_AUTHORIZATION_SUCCESS 1 >+typedef struct hdb_request_desc { >+ HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS; >+} *hdb_request_t; > >-/* >- * The user supplied the wrong password to a password-based >- * authentication mechanism (eg ENC-TS, ENC-CHAL) >- * >- * The HDB backend might increment a bad password count. >- */ >-#define HDB_AUTHSTATUS_WRONG_PASSWORD 2 >- >-/* >- * The user supplied a correct password to a password-based >- * authentication mechanism (eg ENC-TS, ENC-CHAL) >- * >- * The HDB backend might reset a bad password count. >- */ >-#define HDB_AUTHSTATUS_CORRECT_PASSWORD 3 >- >-/* >- * Attempted authenticaton with an unknown user >- */ >-#define HDB_AUTHSTATUS_CLIENT_UNKNOWN 4 >- >-/* >- * Attempted authenticaton with an known user that is already locked >- * out. >- */ >-#define HDB_AUTHSTATUS_CLIENT_LOCKED_OUT 5 >- >-/* >- * Successful authentication with a pre-authentication mechanism >- */ >-#define HDB_AUTHSTATUS_GENERIC_SUCCESS 6 >- >-/* >- * Failed authentication with a pre-authentication mechanism >- */ >-#define HDB_AUTHSTATUS_GENERIC_FAILURE 7 >- >-/* >- * Successful pre-authentication with PKINIT (smart card login etc) >- */ >-#define HDB_AUTHSTATUS_PKINIT_SUCCESS 8 >- >-/* >- * Failed pre-authentication with PKINIT (smart card login etc) >- */ >-#define HDB_AUTHSTATUS_PKINIT_FAILURE 9 >- >-/* >- * Successful pre-authentication with GSS pre-authentication >- */ >-#define HDB_AUTHSTATUS_GSS_SUCCESS 10 >- >-/* >- * Failed pre-authentication with GSS pre-authentication >- */ >-#define HDB_AUTHSTATUS_GSS_FAILURE 11 >+#undef heim_pcontext >+#undef heim_pconfig > > /* key usage for master key */ > #define HDB_KU_MKEY 0x484442 >@@ -163,20 +105,6 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK }; > > typedef struct hdb_master_key_data *hdb_master_key; > >-/** >- * hdb_entry_ex is a wrapper structure around the hdb_entry structure >- * that allows backends to keep a pointer to the backing store, ie in >- * ->hdb_fetch_kvno(), so that we the kadmin/kpasswd backend gets around to >- * ->hdb_store(), the backend doesn't need to lookup the entry again. >- */ >- >-typedef struct hdb_entry_ex { >- void *ctx; >- hdb_entry entry; >- void (*free_entry)(krb5_context, struct hdb_entry_ex *); >-} hdb_entry_ex; >- >- > /** > * HDB backend function pointer structure > * >@@ -226,9 +154,9 @@ typedef struct HDB { > */ > krb5_error_code (*hdb_close)(krb5_context, struct HDB*); > /** >- * Free an entry after use. >+ * Free backend-specific entry context. > */ >- void (*hdb_free)(krb5_context, struct HDB*, hdb_entry_ex*); >+ void (*hdb_free_entry_context)(krb5_context, struct HDB*, hdb_entry*); > /** > * Fetch an entry from the backend > * >@@ -238,12 +166,12 @@ typedef struct HDB { > */ > krb5_error_code (*hdb_fetch_kvno)(krb5_context, struct HDB*, > krb5_const_principal, unsigned, krb5_kvno, >- hdb_entry_ex*); >+ hdb_entry*); > /** > * Store an entry to database > */ > krb5_error_code (*hdb_store)(krb5_context, struct HDB*, >- unsigned, hdb_entry_ex*); >+ unsigned, hdb_entry*); > /** > * Remove an entry from the database. > */ >@@ -253,12 +181,12 @@ typedef struct HDB { > * As part of iteration, fetch one entry > */ > krb5_error_code (*hdb_firstkey)(krb5_context, struct HDB*, >- unsigned, hdb_entry_ex*); >+ unsigned, hdb_entry*); > /** > * As part of iteration, fetch next entry > */ > krb5_error_code (*hdb_nextkey)(krb5_context, struct HDB*, >- unsigned, hdb_entry_ex*); >+ unsigned, hdb_entry*); > /** > * Lock database > * >@@ -337,40 +265,35 @@ typedef struct HDB { > * The backend needs to call _kadm5_set_keys() and perform password > * quality checks. > */ >- krb5_error_code (*hdb_password)(krb5_context, struct HDB*, hdb_entry_ex*, const char *, int); >+ krb5_error_code (*hdb_password)(krb5_context, struct HDB*, hdb_entry*, const char *, int); > > /** >- * Auth feedback >+ * Authentication auditing. Note that this function is called by >+ * both the AS and TGS, but currently only the AS sets the auth >+ * event type. This may change in a future version. > * >- * This is a feedback call that allows backends that provides >- * lockout functionality to register failure and/or successes. >+ * Event details are available by querying the request using >+ * heim_audit_getkv(HDB_REQUEST_KV_...). > * > * In case the entry is locked out, the backend should set the > * hdb_entry.flags.locked-out flag. > */ >- krb5_error_code (*hdb_auth_status)(krb5_context, >- struct HDB *, >- hdb_entry_ex *, >- const struct timeval *start_time, >- const struct sockaddr *from_addr, >- const char *original_client_name, >- int auth_type, >- const char *auth_details, >- const char *pa_type); >+ krb5_error_code (*hdb_audit)(krb5_context, struct HDB *, hdb_entry *, hdb_request_t); >+ > /** > * Check if delegation is allowed. > */ >- krb5_error_code (*hdb_check_constrained_delegation)(krb5_context, struct HDB *, hdb_entry_ex *, krb5_const_principal); >+ krb5_error_code (*hdb_check_constrained_delegation)(krb5_context, struct HDB *, hdb_entry *, krb5_const_principal); > > /** > * Check if this name is an alias for the supplied client for PKINIT userPrinicpalName logins > */ >- krb5_error_code (*hdb_check_pkinit_ms_upn_match)(krb5_context, struct HDB *, hdb_entry_ex *, krb5_const_principal); >+ krb5_error_code (*hdb_check_pkinit_ms_upn_match)(krb5_context, struct HDB *, hdb_entry *, krb5_const_principal); > > /** > * Check if s4u2self is allowed from this client to this server or the SPN is a valid SPN of this client (for user2user) > */ >- krb5_error_code (*hdb_check_client_matches_target_service)(krb5_context, struct HDB *, hdb_entry_ex *, hdb_entry_ex *); >+ krb5_error_code (*hdb_check_client_matches_target_service)(krb5_context, struct HDB *, hdb_entry *, hdb_entry *); > > /** > * Enable/disable synchronous updates >@@ -405,7 +328,7 @@ struct hdb_print_entry_arg { > }; > > typedef krb5_error_code (*hdb_foreach_func_t)(krb5_context, HDB*, >- hdb_entry_ex*, void*); >+ hdb_entry*, void*); > extern krb5_kt_ops hdb_kt_ops; > extern krb5_kt_ops hdb_get_kt_ops; > >diff --git a/third_party/heimdal/lib/hdb/hdb.opt b/third_party/heimdal/lib/hdb/hdb.opt >new file mode 100644 >index 000000000000..626f8c7b07ab >--- /dev/null >+++ b/third_party/heimdal/lib/hdb/hdb.opt >@@ -0,0 +1,5 @@ >+--sequence=HDB-extensions >+--sequence=HDB-Ext-KeyRotation >+--sequence=HDB-Ext-KeySet >+--sequence=Keys >+--decorate=HDB_entry:void:context?::: >diff --git a/third_party/heimdal/lib/hdb/keys.c b/third_party/heimdal/lib/hdb/keys.c >index ae0b067f79ba..457e5daf7a7b 100644 >--- a/third_party/heimdal/lib/hdb/keys.c >+++ b/third_party/heimdal/lib/hdb/keys.c >@@ -305,7 +305,7 @@ hdb_add_history_keyset(krb5_context context, > HDB_Ext_KeySet *hist_keys; > HDB_extension ext; > HDB_extension *extp; >- krb5_error_code ret; >+ krb5_error_code ret = 0; > > memset(&ext, 0, sizeof (ext)); > >diff --git a/third_party/heimdal/lib/hdb/keytab.c b/third_party/heimdal/lib/hdb/keytab.c >index 83cc851d91f5..b1aa0207c978 100644 >--- a/third_party/heimdal/lib/hdb/keytab.c >+++ b/third_party/heimdal/lib/hdb/keytab.c >@@ -42,7 +42,7 @@ struct hdb_data { > > struct hdb_cursor { > HDB *db; >- hdb_entry_ex hdb_entry; >+ hdb_entry hdb_entry; > int first, next; > int key_idx; > }; >@@ -160,8 +160,11 @@ find_db (krb5_context context, > } > hdb_free_dbinfo(context, &head); > if (*dbname == NULL && >- (*dbname = strdup(hdb_default_db(context))) == NULL) >+ (*dbname = strdup(hdb_default_db(context))) == NULL) { >+ free(*mkey); >+ *mkey = NULL; > return krb5_enomem(context); >+ } > return 0; > } > >@@ -178,7 +181,7 @@ hdb_get_entry(krb5_context context, > krb5_enctype enctype, > krb5_keytab_entry *entry) > { >- hdb_entry_ex ent; >+ hdb_entry ent; > krb5_error_code ret; > struct hdb_data *d = id->data; > const char *dbname = d->dbname; >@@ -187,6 +190,9 @@ hdb_get_entry(krb5_context context, > HDB *db; > size_t i; > >+ if (!principal) >+ return KRB5_KT_NOTFOUND; >+ > memset(&ent, 0, sizeof(ent)); > > if (dbname == NULL) { >@@ -223,27 +229,27 @@ hdb_get_entry(krb5_context context, > }else if(ret) > goto out; > >- if(kvno && (krb5_kvno)ent.entry.kvno != kvno) { >- hdb_free_entry(context, &ent); >+ if(kvno && (krb5_kvno)ent.kvno != kvno) { >+ hdb_free_entry(context, db, &ent); > ret = KRB5_KT_NOTFOUND; > goto out; > } > if(enctype == 0) >- if(ent.entry.keys.len > 0) >- enctype = ent.entry.keys.val[0].key.keytype; >+ if(ent.keys.len > 0) >+ enctype = ent.keys.val[0].key.keytype; > ret = KRB5_KT_NOTFOUND; >- for(i = 0; i < ent.entry.keys.len; i++) { >- if(ent.entry.keys.val[i].key.keytype == enctype) { >+ for(i = 0; i < ent.keys.len; i++) { >+ if(ent.keys.val[i].key.keytype == enctype) { > krb5_copy_principal(context, principal, &entry->principal); >- entry->vno = ent.entry.kvno; >+ entry->vno = ent.kvno; > krb5_copy_keyblock_contents(context, >- &ent.entry.keys.val[i].key, >+ &ent.keys.val[i].key, > &entry->keyblock); > ret = 0; > break; > } > } >- hdb_free_entry(context, &ent); >+ hdb_free_entry(context, db, &ent); > out: > (*db->hdb_close)(context, db); > (*db->hdb_destroy)(context, db); >@@ -333,8 +339,8 @@ hdb_next_entry(krb5_context context, > else if (ret) > return ret; > >- if (c->hdb_entry.entry.keys.len == 0) >- hdb_free_entry(context, &c->hdb_entry); >+ if (c->hdb_entry.keys.len == 0) >+ hdb_free_entry(context, c->db, &c->hdb_entry); > else > c->next = FALSE; > } >@@ -350,8 +356,8 @@ hdb_next_entry(krb5_context context, > return ret; > > /* If no keys on this entry, try again */ >- if (c->hdb_entry.entry.keys.len == 0) >- hdb_free_entry(context, &c->hdb_entry); >+ if (c->hdb_entry.keys.len == 0) >+ hdb_free_entry(context, c->db, &c->hdb_entry); > else > c->next = FALSE; > } >@@ -362,14 +368,14 @@ hdb_next_entry(krb5_context context, > */ > > ret = krb5_copy_principal(context, >- c->hdb_entry.entry.principal, >+ c->hdb_entry.principal, > &entry->principal); > if (ret) > return ret; > >- entry->vno = c->hdb_entry.entry.kvno; >+ entry->vno = c->hdb_entry.kvno; > ret = krb5_copy_keyblock_contents(context, >- &c->hdb_entry.entry.keys.val[c->key_idx].key, >+ &c->hdb_entry.keys.val[c->key_idx].key, > &entry->keyblock); > if (ret) { > krb5_free_principal(context, entry->principal); >@@ -383,8 +389,8 @@ hdb_next_entry(krb5_context context, > * next entry > */ > >- if ((size_t)c->key_idx == c->hdb_entry.entry.keys.len) { >- hdb_free_entry(context, &c->hdb_entry); >+ if ((size_t)c->key_idx == c->hdb_entry.keys.len) { >+ hdb_free_entry(context, c->db, &c->hdb_entry); > c->next = TRUE; > c->key_idx = 0; > } >@@ -401,7 +407,7 @@ hdb_end_seq_get(krb5_context context, > struct hdb_cursor *c = cursor->data; > > if (!c->next) >- hdb_free_entry(context, &c->hdb_entry); >+ hdb_free_entry(context, c->db, &c->hdb_entry); > > (c->db->hdb_close)(context, c->db); > (c->db->hdb_destroy)(context, c->db); >diff --git a/third_party/heimdal/lib/hdb/libhdb-exports.def b/third_party/heimdal/lib/hdb/libhdb-exports.def >index a124f93f6456..72a7fb7aaad7 100644 >--- a/third_party/heimdal/lib/hdb/libhdb-exports.def >+++ b/third_party/heimdal/lib/hdb/libhdb-exports.def >@@ -69,7 +69,6 @@ EXPORTS > hdb_prune_keys > hdb_prune_keys_kvno > hdb_read_master_key >- hdb_remove_base_keys > hdb_remove_keys > hdb_replace_extension > hdb_seal_key >diff --git a/third_party/heimdal/lib/hdb/ndbm.c b/third_party/heimdal/lib/hdb/ndbm.c >index 4e3a340fe555..52c52c890dc0 100644 >--- a/third_party/heimdal/lib/hdb/ndbm.c >+++ b/third_party/heimdal/lib/hdb/ndbm.c >@@ -76,7 +76,7 @@ NDBM_unlock(krb5_context context, HDB *db) > > static krb5_error_code > NDBM_seq(krb5_context context, HDB *db, >- unsigned flags, hdb_entry_ex *entry, int first) >+ unsigned flags, hdb_entry *entry, int first) > > { > struct ndbm_db *d = (struct ndbm_db *)db->hdb_db; >@@ -99,21 +99,21 @@ NDBM_seq(krb5_context context, HDB *db, > data.data = value.dptr; > data.length = value.dsize; > memset(entry, 0, sizeof(*entry)); >- if(hdb_value2entry(context, &data, &entry->entry)) >+ if(hdb_value2entry(context, &data, entry)) > return NDBM_seq(context, db, flags, entry, 0); > if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { >- ret = hdb_unseal_keys (context, db, &entry->entry); >+ ret = hdb_unseal_keys (context, db, entry); > if (ret) >- hdb_free_entry (context, entry); >+ hdb_free_entry (context, db, entry); > } >- if (ret == 0 && entry->entry.principal == NULL) { >- entry->entry.principal = malloc (sizeof(*entry->entry.principal)); >- if (entry->entry.principal == NULL) { >- hdb_free_entry (context, entry); >+ if (ret == 0 && entry->principal == NULL) { >+ entry->principal = malloc (sizeof(*entry->principal)); >+ if (entry->principal == NULL) { >+ hdb_free_entry (context, db, entry); > ret = ENOMEM; > krb5_set_error_message(context, ret, "malloc: out of memory"); > } else { >- hdb_key2principal (context, &key_data, entry->entry.principal); >+ hdb_key2principal (context, &key_data, entry->principal); > } > } > return ret; >@@ -121,14 +121,14 @@ NDBM_seq(krb5_context context, HDB *db, > > > static krb5_error_code >-NDBM_firstkey(krb5_context context, HDB *db,unsigned flags,hdb_entry_ex *entry) >+NDBM_firstkey(krb5_context context, HDB *db,unsigned flags,hdb_entry *entry) > { > return NDBM_seq(context, db, flags, entry, 1); > } > > > static krb5_error_code >-NDBM_nextkey(krb5_context context, HDB *db, unsigned flags,hdb_entry_ex *entry) >+NDBM_nextkey(krb5_context context, HDB *db, unsigned flags,hdb_entry *entry) > { > return NDBM_seq(context, db, flags, entry, 0); > } >@@ -140,8 +140,7 @@ open_lock_file(krb5_context context, const char *db_name, int *fd) > int ret = 0; > > /* lock old and new databases */ >- asprintf(&lock_file, "%s.lock", db_name); >- if(lock_file == NULL) { >+ if (asprintf(&lock_file, "%s.lock", db_name) == -1) { > krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); > return ENOMEM; > } >@@ -161,7 +160,8 @@ static krb5_error_code > NDBM_rename(krb5_context context, HDB *db, const char *new_name) > { > int ret; >- char *old_dir, *old_pag, *new_dir, *new_pag; >+ char *old_dir = NULL, *old_pag = NULL; >+ char *new_dir = NULL, *new_pag = NULL; > int old_lock_fd, new_lock_fd; > > /* lock old and new databases */ >@@ -190,10 +190,26 @@ NDBM_rename(krb5_context context, HDB *db, const char *new_name) > return ret; > } > >- asprintf(&old_dir, "%s.dir", db->hdb_name); >- asprintf(&old_pag, "%s.pag", db->hdb_name); >- asprintf(&new_dir, "%s.dir", new_name); >- asprintf(&new_pag, "%s.pag", new_name); >+ if (asprintf(&old_dir, "%s.dir", db->hdb_name) == -1) { >+ old_dir = NULL; >+ ret = ENOMEM; >+ goto out; >+ } >+ if (asprintf(&old_pag, "%s.pag", db->hdb_name) == -1) { >+ old_pag = NULL; >+ ret = ENOMEM; >+ goto out; >+ } >+ if (asprintf(&new_dir, "%s.dir", new_name) == -1) { >+ new_dir = NULL; >+ ret = ENOMEM; >+ goto out; >+ } >+ if (asprintf(&new_pag, "%s.pag", new_name) == -1) { >+ new_pag = NULL; >+ ret = ENOMEM; >+ goto out; >+ } > > ret = rename(old_dir, new_dir) || rename(old_pag, new_pag); > if (ret) { >@@ -203,6 +219,7 @@ NDBM_rename(krb5_context context, HDB *db, const char *new_name) > krb5_set_error_message(context, ret, "rename: %s", strerror(ret)); > } > >+ out: > free(old_dir); > free(old_pag); > free(new_dir); >diff --git a/third_party/heimdal/lib/hdb/print.c b/third_party/heimdal/lib/hdb/print.c >index 0d1e2855217d..7f2535881892 100644 >--- a/third_party/heimdal/lib/hdb/print.c >+++ b/third_party/heimdal/lib/hdb/print.c >@@ -453,7 +453,8 @@ entry2mit_string_int(krb5_context context, krb5_storage *sp, hdb_entry *ent) > unsigned char *ptr; > > ptr = (unsigned char *)&last_pw_chg; >- val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); >+ val = ((unsigned long)ptr[3] << 24) | (ptr[2] << 16) >+ | (ptr[1] << 8) | ptr[0]; > d.data = &val; > d.length = sizeof (last_pw_chg); > sz = append_string(context, sp, "\t%u\t%u\t", >@@ -474,12 +475,16 @@ entry2mit_string_int(krb5_context context, krb5_storage *sp, hdb_entry *ent) > d.data = &val; > d.length = sizeof (ent->modified_by->time); > ret = krb5_unparse_name(context, ent->modified_by->principal, &modby_p); >- if (ret) return ret; >+ if (ret) >+ return ret; > plen = strlen(modby_p); > sz = append_string(context, sp, "\t%u\t%u\t", > mit_KRB5_TL_MOD_PRINC, > d.length + plen + 1 /* NULL counted */); >- if (sz == -1) return ENOMEM; >+ if (sz == -1) { >+ free(modby_p); >+ return ENOMEM; >+ } > sz = append_hex(context, sp, 1, 1, &d); > if (sz == -1) { > free(modby_p); >@@ -489,7 +494,8 @@ entry2mit_string_int(krb5_context context, krb5_storage *sp, hdb_entry *ent) > d.length = plen + 1; > sz = append_hex(context, sp, 1, 1, &d); > free(modby_p); >- if (sz == -1) return ENOMEM; >+ if (sz == -1) >+ return ENOMEM; > } > /* > * Dump keys (remembering to not include any with kvno higher than >@@ -556,7 +562,7 @@ hdb_entry2string(krb5_context context, hdb_entry *ent, char **str) > /* print a hdb_entry to (FILE*)data; suitable for hdb_foreach */ > > krb5_error_code >-hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry, >+hdb_print_entry(krb5_context context, HDB *db, hdb_entry *entry, > void *data) > { > struct hdb_print_entry_arg *parg = data; >@@ -572,10 +578,10 @@ hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry, > > switch (parg->fmt) { > case HDB_DUMP_HEIMDAL: >- ret = entry2string_int(context, sp, &entry->entry); >+ ret = entry2string_int(context, sp, entry); > break; > case HDB_DUMP_MIT: >- ret = entry2mit_string_int(context, sp, &entry->entry); >+ ret = entry2mit_string_int(context, sp, entry); > break; > default: > heim_abort("Only two dump formats supported: Heimdal and MIT"); >diff --git a/third_party/heimdal/lib/hdb/test_concurrency.c b/third_party/heimdal/lib/hdb/test_concurrency.c >index 9c95e6390f40..35c01f59f594 100644 >--- a/third_party/heimdal/lib/hdb/test_concurrency.c >+++ b/third_party/heimdal/lib/hdb/test_concurrency.c >@@ -70,7 +70,7 @@ threaded_reader(void *d) > krb5_error_code ret; > krb5_context context; > struct tsync *s = d; >- hdb_entry_ex entr; >+ hdb_entry entr; > HDB *dbr = NULL; > > printf("Reader thread opening HDB\n"); >@@ -101,7 +101,7 @@ threaded_reader(void *d) > //(void) unlink(s->fname); > krb5_err(context, 1, ret, "Could not iterate HDB %s", s->hdb_name); > } >- free_HDB_entry(&entr.entry); >+ free_HDB_entry(&entr); > > /* Tell the writer to go ahead and write */ > printf("Reader thread iterated one entry; telling writer to write more\n"); >@@ -124,7 +124,7 @@ threaded_reader(void *d) > "Could not iterate while writing to HDB %s", s->hdb_name); > } > printf("Reader thread iterated another entry\n"); >- free_HDB_entry(&entr.entry); >+ free_HDB_entry(&entr); > if ((ret = dbr->hdb_nextkey(context, dbr, 0, &entr)) == 0) { > //(void) unlink(s->fname); > krb5_warn(context, ret, >@@ -154,7 +154,7 @@ forked_reader(struct tsync *s) > { > krb5_error_code ret; > krb5_context context; >- hdb_entry_ex entr; >+ hdb_entry entr; > ssize_t bytes; > char b[1]; > HDB *dbr = NULL; >@@ -172,6 +172,8 @@ forked_reader(struct tsync *s) > while ((bytes = read(s->reader_go_pipe[0], b, sizeof(b))) == -1 && > errno == EINTR) > ; >+ if (bytes == -1) >+ err(1, "Could not read from reader-go pipe (error)"); > > /* Open a new HDB handle to read */ > if ((ret = hdb_create(context, &dbr, s->hdb_name))) { >@@ -188,13 +190,15 @@ forked_reader(struct tsync *s) > krb5_err(context, 1, ret, "Could not iterate HDB %s", s->hdb_name); > } > printf("Reader process iterated one entry\n"); >- free_HDB_entry(&entr.entry); >+ free_HDB_entry(&entr); > > /* Tell the writer to go ahead and write */ > printf("Reader process iterated one entry; telling writer to write more\n"); > while ((bytes = write(s->writer_go_pipe[1], "", sizeof(""))) == -1 && > errno == EINTR) > ; >+ if (bytes == -1) >+ err(1, "Could not write to writer-go pipe (error)"); > > > /* Wait for the writer to have written one more entry to the HDB */ >@@ -213,13 +217,13 @@ forked_reader(struct tsync *s) > krb5_err(context, 1, ret, > "Could not iterate while writing to HDB %s", s->hdb_name); > } >- free_HDB_entry(&entr.entry); >+ free_HDB_entry(&entr); > printf("Reader process iterated another entry\n"); > if ((ret = dbr->hdb_nextkey(context, dbr, 0, &entr)) == 0) { > //(void) unlink(s->fname); > krb5_warn(context, ret, > "HDB %s sees writes committed since starting iteration (%s)", >- s->hdb_name, entr.entry.principal->name.name_string.val[0]); >+ s->hdb_name, entr.principal->name.name_string.val[0]); > } else if (ret != HDB_ERR_NOENTRY) { > //(void) unlink(s->fname); > krb5_err(context, 1, ret, >@@ -231,6 +235,8 @@ forked_reader(struct tsync *s) > while ((bytes = write(s->writer_go_pipe[1], "", sizeof(""))) == -1 && > errno == EINTR) > ; >+ if (bytes == -1) >+ err(1, "Could not write to writer-go pipe (error)"); > > dbr->hdb_close(context, dbr); > dbr->hdb_destroy(context, dbr); >@@ -242,27 +248,27 @@ forked_reader(struct tsync *s) > } > > static krb5_error_code >-make_entry(krb5_context context, hdb_entry_ex *entry, const char *name) >+make_entry(krb5_context context, hdb_entry *entry, const char *name) > { > krb5_error_code ret; > > memset(entry, 0, sizeof(*entry)); >- entry->entry.kvno = 2; >- entry->entry.keys.len = 0; >- entry->entry.keys.val = NULL; >- entry->entry.created_by.time = time(NULL); >- entry->entry.modified_by = NULL; >- entry->entry.valid_start = NULL; >- entry->entry.valid_end = NULL; >- entry->entry.max_life = NULL; >- entry->entry.max_renew = NULL; >- entry->entry.etypes = NULL; >- entry->entry.generation = NULL; >- entry->entry.extensions = NULL; >- if ((ret = krb5_make_principal(context, &entry->entry.principal, >+ entry->kvno = 2; >+ entry->keys.len = 0; >+ entry->keys.val = NULL; >+ entry->created_by.time = time(NULL); >+ entry->modified_by = NULL; >+ entry->valid_start = NULL; >+ entry->valid_end = NULL; >+ entry->max_life = NULL; >+ entry->max_renew = NULL; >+ entry->etypes = NULL; >+ entry->generation = NULL; >+ entry->extensions = NULL; >+ if ((ret = krb5_make_principal(context, &entry->principal, > "TEST.H5L.SE", name, NULL))) > return ret; >- if ((ret = krb5_make_principal(context, &entry->entry.created_by.principal, >+ if ((ret = krb5_make_principal(context, &entry->created_by.principal, > "TEST.H5L.SE", "tester", NULL))) > return ret; > return 0; >@@ -320,7 +326,7 @@ test_hdb_concurrency(char *name, const char *ext, int threaded) > char *fname_ext = NULL; > pthread_t reader_thread; > struct tsync ts; >- hdb_entry_ex entw; >+ hdb_entry entw; > pid_t child = getpid(); > HDB *dbw = NULL; > int status; >@@ -387,14 +393,14 @@ test_hdb_concurrency(char *name, const char *ext, int threaded) > krb5_err(context, 1, ret, > "Could not store entry for \"foo\" in HDB %s", name); > } >- free_HDB_entry(&entw.entry); >+ free_HDB_entry(&entw); > if ((ret = make_entry(context, &entw, "bar")) || > (ret = dbw->hdb_store(context, dbw, 0, &entw))) { > (void) unlink(fname_ext); > krb5_err(context, 1, ret, > "Could not store entry for \"foo\" in HDB %s", name); > } >- free_HDB_entry(&entw.entry); >+ free_HDB_entry(&entw); > > /* Tell the reader to start reading */ > readers_turn(&ts, child, threaded); >@@ -407,7 +413,7 @@ test_hdb_concurrency(char *name, const char *ext, int threaded) > "Could not store entry for \"foobar\" in HDB %s " > "while iterating it", name); > } >- free_HDB_entry(&entw.entry); >+ free_HDB_entry(&entw); > > /* Tell the reader to go again */ > readers_turn(&ts, child, threaded); >diff --git a/third_party/heimdal/lib/hdb/test_namespace.c b/third_party/heimdal/lib/hdb/test_namespace.c >index 6aaecc083ec7..a4c44ba190e5 100644 >--- a/third_party/heimdal/lib/hdb/test_namespace.c >+++ b/third_party/heimdal/lib/hdb/test_namespace.c >@@ -106,7 +106,7 @@ TDB_unlock(krb5_context context, HDB *db) > } > > static krb5_error_code >-TDB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+TDB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > /* XXX Implement */ > /* Tricky thing: heim_dict_iterate_f() is inconvenient here */ >@@ -115,7 +115,7 @@ TDB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) > } > > static krb5_error_code >-TDB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+TDB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > /* XXX Implement */ > /* Tricky thing: heim_dict_iterate_f() is inconvenient here */ >@@ -151,14 +151,13 @@ TDB__put(krb5_context context, HDB *db, int rplc, krb5_data kd, krb5_data vd) > { > krb5_error_code ret = 0; > TEST_HDB *tdb = (void *)db; >- heim_object_t e = NULL; > heim_object_t k = NULL; > heim_object_t v = NULL; > > if ((k = heim_data_create(kd.data, kd.length)) == NULL || > (v = heim_data_create(vd.data, vd.length)) == NULL) > ret = krb5_enomem(context); >- if (ret == 0 && !rplc && (e = heim_dict_get_value(tdb->dict, k)) != NULL) >+ if (ret == 0 && !rplc && heim_dict_get_value(tdb->dict, k) != NULL) > ret = HDB_ERR_EXISTS; > if (ret == 0 && heim_dict_set_value(tdb->dict, k, v)) > ret = krb5_enomem(context); >@@ -172,11 +171,11 @@ TDB__del(krb5_context context, HDB *db, krb5_data key) > { > krb5_error_code ret = 0; > TEST_HDB *tdb = (void *)db; >- heim_object_t k, v; >+ heim_object_t k; > > if ((k = heim_data_create(key.data, key.length)) == NULL) > ret = krb5_enomem(context); >- if (ret == 0 && (v = heim_dict_get_value(tdb->dict, k)) == NULL) >+ if (ret == 0 && heim_dict_get_value(tdb->dict, k) == NULL) > ret = HDB_ERR_NOENTRY; > if (ret == 0) > heim_dict_delete_key(tdb->dict, k); >@@ -198,7 +197,8 @@ hdb_test_create(krb5_context context, struct HDB **db, const char *arg) > if ((tdb = calloc(1, sizeof(tdb[0]))) == NULL || > (tdb->hdb.hdb_name = strdup(arg)) == NULL || > (tdb->dict = heim_dict_create(10)) == NULL) { >- free(tdb->hdb.hdb_name); >+ if (tdb) >+ free(tdb->hdb.hdb_name); > free(tdb); > return krb5_enomem(context); > } >@@ -337,7 +337,7 @@ static void > make_namespace(krb5_context context, HDB *db, const char *name) > { > krb5_error_code ret = 0; >- hdb_entry_ex e; >+ hdb_entry e; > Key k; > > memset(&k, 0, sizeof(k)); >@@ -346,85 +346,83 @@ make_namespace(krb5_context context, HDB *db, const char *name) > > /* Setup the HDB entry */ > memset(&e, 0, sizeof(e)); >- e.ctx = 0; >- e.free_entry = 0; >- e.entry.created_by.time = krs[0].epoch; >- e.entry.valid_start = e.entry.valid_end = e.entry.pw_end = 0; >- e.entry.generation = 0; >- e.entry.flags = int2HDBFlags(0); >- e.entry.flags.server = e.entry.flags.client = 1; >- e.entry.flags.virtual = 1; >+ e.created_by.time = krs[0].epoch; >+ e.valid_start = e.valid_end = e.pw_end = 0; >+ e.generation = 0; >+ e.flags = int2HDBFlags(0); >+ e.flags.server = e.flags.client = 1; >+ e.flags.virtual = 1; > > /* Setup etypes */ > if (ret == 0 && >- (e.entry.etypes = malloc(sizeof(*e.entry.etypes))) == NULL) >+ (e.etypes = malloc(sizeof(*e.etypes))) == NULL) > ret = krb5_enomem(context); > if (ret == 0) >- e.entry.etypes->len = 3; >+ e.etypes->len = 3; > if (ret == 0 && >- (e.entry.etypes->val = calloc(e.entry.etypes->len, >- sizeof(e.entry.etypes->val[0]))) == NULL) >+ (e.etypes->val = calloc(e.etypes->len, >+ sizeof(e.etypes->val[0]))) == NULL) > ret = krb5_enomem(context); > if (ret == 0) { >- e.entry.etypes->val[0] = KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128; >- e.entry.etypes->val[1] = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192; >- e.entry.etypes->val[2] = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96; >+ e.etypes->val[0] = KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128; >+ e.etypes->val[1] = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192; >+ e.etypes->val[2] = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96; > } > > /* Setup max_life and max_renew */ > if (ret == 0 && >- (e.entry.max_life = malloc(sizeof(*e.entry.max_life))) == NULL) >+ (e.max_life = malloc(sizeof(*e.max_life))) == NULL) > ret = krb5_enomem(context); > if (ret == 0 && >- (e.entry.max_renew = malloc(sizeof(*e.entry.max_renew))) == NULL) >+ (e.max_renew = malloc(sizeof(*e.max_renew))) == NULL) > ret = krb5_enomem(context); > if (ret == 0) > /* Make it long, so we see the clamped max */ >- *e.entry.max_renew = 2 * ((*e.entry.max_life = 15 * 24 * 3600)); >+ *e.max_renew = 2 * ((*e.max_life = 15 * 24 * 3600)); > > /* Setup principal name and created_by */ > if (ret == 0) >- ret = krb5_parse_name(context, name, &e.entry.principal); >+ ret = krb5_parse_name(context, name, &e.principal); > if (ret == 0) > ret = krb5_parse_name(context, "admin@BAR.EXAMPLE", >- &e.entry.created_by.principal); >+ &e.created_by.principal); > > /* Make base keys for first epoch */ > if (ret == 0) >- ret = make_base_key(context, e.entry.principal, base_pw[0], &k.key); >+ ret = make_base_key(context, e.principal, base_pw[0], &k.key); > if (ret == 0) >- add_Keys(&e.entry.keys, &k); >+ add_Keys(&e.keys, &k); > if (ret == 0) >- ret = hdb_entry_set_pw_change_time(context, &e.entry, krs[0].epoch); >+ ret = hdb_entry_set_pw_change_time(context, &e, krs[0].epoch); > free_Key(&k); >- e.entry.kvno = krs[0].base_key_kvno; >+ e.kvno = krs[0].base_key_kvno; > > /* Move them to history */ > if (ret == 0) >- ret = hdb_add_current_keys_to_history(context, &e.entry); >- free_Keys(&e.entry.keys); >+ ret = hdb_add_current_keys_to_history(context, &e); >+ free_Keys(&e.keys); > > /* Make base keys for second epoch */ > if (ret == 0) >- ret = make_base_key(context, e.entry.principal, base_pw[1], &k.key); >+ ret = make_base_key(context, e.principal, base_pw[1], &k.key); > if (ret == 0) >- add_Keys(&e.entry.keys, &k); >- e.entry.kvno = krs[1].base_key_kvno; >+ add_Keys(&e.keys, &k); >+ e.kvno = krs[1].base_key_kvno; > if (ret == 0) >- ret = hdb_entry_set_pw_change_time(context, &e.entry, krs[1].epoch); >+ ret = hdb_entry_set_pw_change_time(context, &e, krs[1].epoch); > > /* Add the key rotation metadata */ > if (ret == 0) >- ret = hdb_entry_add_key_rotation(context, &e.entry, 0, &krs[0]); >+ ret = hdb_entry_add_key_rotation(context, &e, 0, &krs[0]); > if (ret == 0) >- ret = hdb_entry_add_key_rotation(context, &e.entry, 0, &krs[1]); >+ ret = hdb_entry_add_key_rotation(context, &e, 0, &krs[1]); > > if (ret == 0) > ret = db->hdb_store(context, db, 0, &e); > if (ret) > krb5_err(context, 1, ret, "failed to setup a namespace principal"); > free_Key(&k); >- hdb_free_entry(context, &e); >+ hdb_free_entry(context, db, &e); > } > > #define WK_PREFIX "WELLKNOWN/" HDB_WK_NAMESPACE "/" >@@ -449,7 +447,7 @@ static const char *unexpected[] = { > * different time offsets in each period. > */ > #define NUM_OFFSETS 5 >-static hdb_entry_ex e[ >+static hdb_entry e[ > (sizeof(expected) / sizeof(expected[0])) * > (sizeof(krs) / sizeof(krs[0])) * > NUM_OFFSETS >@@ -481,8 +479,8 @@ fetch_entries(krb5_context context, > krb5_error_code ret = 0; > krb5_principal p = NULL; > krb5_keyblock base_key, dk; >- hdb_entry_ex *ep; >- hdb_entry_ex no; >+ hdb_entry *ep; >+ hdb_entry no; > size_t i, b; > int toffset = 0; > >@@ -543,14 +541,14 @@ fetch_entries(krb5_context context, > } > } else { > if (ret == 0 && >- !krb5_principal_compare(context, p, ep->entry.principal)) >+ !krb5_principal_compare(context, p, ep->principal)) > krb5_errx(context, 1, "wrong principal in fetched entry"); > } > > { > HDB_Ext_KeySet *hist_keys; > HDB_extension *ext; >- ext = hdb_find_extension(&ep->entry, >+ ext = hdb_find_extension(ep, > choice_HDB_extension_data_hist_keys); > if (ext) { > /* Sort key history by kvno, why not */ >@@ -613,23 +611,23 @@ fetch_entries(krb5_context context, > if (ret) > krb5_err(context, 1, ret, "deriving keys for comparison"); > >- if (kvno != ep->entry.kvno) >- krb5_errx(context, 1, "kvno mismatch (%u != %u)", kvno, ep->entry.kvno); >- (void) hdb_entry_get_pw_change_time(&ep->entry, &chg_time); >+ if (kvno != ep->kvno) >+ krb5_errx(context, 1, "kvno mismatch (%u != %u)", kvno, ep->kvno); >+ (void) hdb_entry_get_pw_change_time(ep, &chg_time); > if (set_time != chg_time) > krb5_errx(context, 1, "key change time mismatch"); >- if (ep->entry.keys.len == 0) >+ if (ep->keys.len == 0) > krb5_errx(context, 1, "no keys!"); >- if (ep->entry.keys.val[0].key.keytype != dk.keytype) >+ if (ep->keys.val[0].key.keytype != dk.keytype) > krb5_errx(context, 1, "enctype mismatch!"); >- if (ep->entry.keys.val[0].key.keyvalue.length != >+ if (ep->keys.val[0].key.keyvalue.length != > dk.keyvalue.length) > krb5_errx(context, 1, "key length mismatch!"); >- if (memcmp(ep->entry.keys.val[0].key.keyvalue.data, >+ if (memcmp(ep->keys.val[0].key.keyvalue.data, > dk.keyvalue.data, dk.keyvalue.length) != 0) > krb5_errx(context, 1, "key mismatch!"); >- if (memcmp(ep->entry.keys.val[0].key.keyvalue.data, >- e[b + i - 1].entry.keys.val[0].key.keyvalue.data, >+ if (memcmp(ep->keys.val[0].key.keyvalue.data, >+ e[b + i - 1].keys.val[0].key.keyvalue.data, > dk.keyvalue.length) == 0) > krb5_errx(context, 1, "different virtual principals have the same keys!"); > /* XXX Add check that we have the expected number of history keys */ >@@ -655,14 +653,14 @@ check_kvnos(krb5_context context) > for (k = 0; k < sizeof(e)/sizeof(e[0]); k++) { > HDB_Ext_KeySet *hist_keys; > HDB_extension *ext; >- hdb_entry_ex *ep; >+ hdb_entry *ep; > int match = 0; > > if ((k % NUM_OFFSETS) != i) > continue; > > ep = &e[k]; >- if (ep->entry.principal == NULL) >+ if (ep->principal == NULL) > continue; /* Didn't fetch this one */ > > /* >@@ -670,15 +668,15 @@ check_kvnos(krb5_context context) > * or else add them to `keysets'. > */ > for (m = 0; m < keysets.len; m++) { >- if (ep->entry.kvno == keysets.val[m].kvno) { >+ if (ep->kvno == keysets.val[m].kvno) { > /* Check the key is the same */ >- if (ep->entry.keys.val[0].key.keytype != >+ if (ep->keys.val[0].key.keytype != > keysets.val[m].keys.val[0].key.keytype || >- ep->entry.keys.val[0].key.keyvalue.length != >+ ep->keys.val[0].key.keyvalue.length != > keysets.val[m].keys.val[0].key.keyvalue.length || >- memcmp(ep->entry.keys.val[0].key.keyvalue.data, >+ memcmp(ep->keys.val[0].key.keyvalue.data, > keysets.val[m].keys.val[0].key.keyvalue.data, >- ep->entry.keys.val[0].key.keyvalue.length) != 0) >+ ep->keys.val[0].key.keyvalue.length) != 0) > krb5_errx(context, 1, > "key mismatch for same princ & kvno"); > match = 1; >@@ -687,8 +685,8 @@ check_kvnos(krb5_context context) > if (m == keysets.len) { > hdb_keyset ks; > >- ks.kvno = ep->entry.kvno; >- ks.keys = ep->entry.keys; >+ ks.kvno = ep->kvno; >+ ks.keys = ep->keys; > ks.set_time = 0; > if (add_HDB_Ext_KeySet(&keysets, &ks)) > krb5_err(context, 1, ENOMEM, "out of memory"); >@@ -698,7 +696,7 @@ check_kvnos(krb5_context context) > continue; > > /* For all non-current keysets, repeat the above */ >- ext = hdb_find_extension(&ep->entry, >+ ext = hdb_find_extension(ep, > choice_HDB_extension_data_hist_keys); > if (!ext) > continue; >@@ -706,20 +704,20 @@ check_kvnos(krb5_context context) > for (p = 0; p < hist_keys->len; p++) { > for (m = 0; m < keysets.len; m++) { > if (keysets.val[m].kvno == hist_keys->val[p].kvno) >- if (ep->entry.keys.val[0].key.keytype != >+ if (ep->keys.val[0].key.keytype != > keysets.val[m].keys.val[0].key.keytype || >- ep->entry.keys.val[0].key.keyvalue.length != >+ ep->keys.val[0].key.keyvalue.length != > keysets.val[m].keys.val[0].key.keyvalue.length || >- memcmp(ep->entry.keys.val[0].key.keyvalue.data, >+ memcmp(ep->keys.val[0].key.keyvalue.data, > keysets.val[m].keys.val[0].key.keyvalue.data, >- ep->entry.keys.val[0].key.keyvalue.length) != 0) >+ ep->keys.val[0].key.keyvalue.length) != 0) > krb5_errx(context, 1, > "key mismatch for same princ & kvno"); > } > if (m == keysets.len) { > hdb_keyset ks; >- ks.kvno = ep->entry.kvno; >- ks.keys = ep->entry.keys; >+ ks.kvno = ep->kvno; >+ ks.keys = ep->keys; > ks.set_time = 0; > if (add_HDB_Ext_KeySet(&keysets, &ks)) > krb5_err(context, 1, ENOMEM, "out of memory"); >@@ -743,15 +741,14 @@ print_em(krb5_context context) > > if (0 == i % (sizeof(expected)/sizeof(expected[0]))) > continue; >- if (e[i].entry.principal == NULL) >+ if (e[i].principal == NULL) > continue; >- hex_encode(e[i].entry.keys.val[0].key.keyvalue.data, >- e[i].entry.keys.val[0].key.keyvalue.length, &x); >- printf("%s %u %s\n", x, e[i].entry.kvno, name); >+ hex_encode(e[i].keys.val[0].key.keyvalue.data, >+ e[i].keys.val[0].key.keyvalue.length, &x); >+ printf("%s %u %s\n", x, e[i].kvno, name); > free(x); > >- ext = hdb_find_extension(&e[i].entry, >- choice_HDB_extension_data_hist_keys); >+ ext = hdb_find_extension(&e[i], choice_HDB_extension_data_hist_keys); > if (!ext) > continue; > hist_keys = &ext->data.u.hist_keys; >@@ -759,6 +756,7 @@ print_em(krb5_context context) > hex_encode(hist_keys->val[p].keys.val[0].key.keyvalue.data, > hist_keys->val[p].keys.val[0].key.keyvalue.length, &x); > printf("%s %u %s\n", x, hist_keys->val[p].kvno, name); >+ free(x); > } > } > } >@@ -773,12 +771,12 @@ check_expected_kvnos(krb5_context context) > > for (i = 0; i < sizeof(expected)/sizeof(expected[0]); i++) { > for (k = 0; k < sizeof(krs)/sizeof(krs[0]); k++) { >- hdb_entry_ex *ep = &e[k * sizeof(expected)/sizeof(expected[0]) + i]; >+ hdb_entry *ep = &e[k * sizeof(expected)/sizeof(expected[0]) + i]; > >- if (ep->entry.principal == NULL) >+ if (ep->principal == NULL) > continue; > for (m = 0; m < NUM_OFFSETS; m++) { >- ext = hdb_find_extension(&ep->entry, >+ ext = hdb_find_extension(ep, > choice_HDB_extension_data_hist_keys); > if (!ext) > continue; >@@ -789,7 +787,7 @@ check_expected_kvnos(krb5_context context) > } > } > fprintf(stderr, "%s at %lu: kvno %u\n", expected[i], k, >- ep->entry.kvno); >+ ep->kvno); > } > } > } >@@ -936,7 +934,7 @@ main(int argc, char **argv) > > /* Cleanup */ > for (i = 0; ret == 0 && i < sizeof(e) / sizeof(e[0]); i++) >- hdb_free_entry(context, &e[i]); >+ hdb_free_entry(context, db, &e[i]); > db->hdb_destroy(context, db); > krb5_free_context(context); > return 0; >diff --git a/third_party/heimdal/lib/hdb/version-script.map b/third_party/heimdal/lib/hdb/version-script.map >index 0846f7337430..058060dae0c1 100644 >--- a/third_party/heimdal/lib/hdb/version-script.map >+++ b/third_party/heimdal/lib/hdb/version-script.map >@@ -70,7 +70,6 @@ HEIMDAL_HDB_1.0 { > hdb_prune_keys; > hdb_prune_keys_kvno; > hdb_read_master_key; >- hdb_remove_base_keys; > hdb_remove_keys; > hdb_replace_extension; > hdb_seal_key; >diff --git a/third_party/heimdal/lib/hx509/Makefile.am b/third_party/heimdal/lib/hx509/Makefile.am >index e32da3b93c3d..214dabf0e831 100644 >--- a/third_party/heimdal/lib/hx509/Makefile.am >+++ b/third_party/heimdal/lib/hx509/Makefile.am >@@ -11,7 +11,7 @@ BUILT_SOURCES = \ > hx509_err.c \ > hx509_err.h > >-AM_YFLAGS = -d >+AM_YFLAGS = -o sel-gram.c > > dist_libhx509_la_SOURCES = \ > ca.c \ >@@ -50,6 +50,7 @@ dist_libhx509_la_SOURCES = \ > > dist_libhx509template_la_SOURCES = $(dist_libhx509_la_SOURCES) > >+sel-gram.h: sel-gram.c > sel-lex.c: sel-gram.h > > libhx509_la_DEPENDENCIES = version-script.map >diff --git a/third_party/heimdal/lib/hx509/ca.c b/third_party/heimdal/lib/hx509/ca.c >index 807621c21d15..3d62b93fa57e 100644 >--- a/third_party/heimdal/lib/hx509/ca.c >+++ b/third_party/heimdal/lib/hx509/ca.c >@@ -2353,7 +2353,6 @@ count_sans(hx509_request req, size_t *n) > for (i = 0; ret == 0; i++) { > hx509_san_type san_type; > >- frees(&s); > ret = hx509_request_get_san(req, i, &san_type, &s); > if (ret) > break; >@@ -2370,6 +2369,7 @@ count_sans(hx509_request req, size_t *n) > } > frees(&s); > } >+ free(s); > return ret == HX509_NO_ITEM ? 0 : ret; > } > >@@ -2565,9 +2565,9 @@ get_cf(hx509_context context, > } > > *out = heim_config_get_list(context->hcontext, cf, label, svc, NULL); >- if (*out) >+ if (*out) { > ret = 0; >- if (ret) { >+ } else { > heim_log_msg(context->hcontext, logf, 3, NULL, > "No configuration for %s %s certificate's realm " > "-> %s -> kx509 -> %s%s%s", def, label, realm, label, >@@ -2741,7 +2741,8 @@ set_tbs(hx509_context context, > realm); > > /* Populate requested certificate extensions from CSR/CSRPlus if allowed */ >- ret = hx509_ca_tbs_set_from_csr(context, tbs, req); >+ if (ret == 0) >+ ret = hx509_ca_tbs_set_from_csr(context, tbs, req); > if (ret == 0) > ret = set_template(context, logf, cf, tbs); > >@@ -2939,6 +2940,8 @@ _hx509_ca_issue_certificate(hx509_context context, > hx509_request_authorize_ku(req, ku); > > ret = get_cf(context, cf, logf, req, cprinc, &cf); >+ if (ret) >+ return ret; > > if ((ca = heim_config_get_string(context->hcontext, cf, > "ca", NULL)) == NULL) { >@@ -3050,9 +3053,8 @@ _hx509_ca_issue_certificate(hx509_context context, > hx509_env_free(&env); > > /* All done with the TBS, sign/issue the certificate */ >- ret = hx509_ca_sign(context, tbs, signer, &cert); >- if (ret) >- goto out; >+ if (ret == 0) >+ ret = hx509_ca_sign(context, tbs, signer, &cert); > > /* > * Gather the certificate and chain into a MEMORY store, being careful not >@@ -3063,8 +3065,9 @@ _hx509_ca_issue_certificate(hx509_context context, > * the full chain in the issuer credential store and copying only the certs > * (but not the private keys) is safer and easier to configure. > */ >- ret = hx509_certs_init(context, "MEMORY:certs", >- HX509_CERTS_NO_PRIVATE_KEYS, NULL, out); >+ if (ret == 0) >+ ret = hx509_certs_init(context, "MEMORY:certs", >+ HX509_CERTS_NO_PRIVATE_KEYS, NULL, out); > if (ret == 0) > ret = hx509_certs_add(context, *out, cert); > if (ret == 0 && send_chain) { >diff --git a/third_party/heimdal/lib/hx509/cert.c b/third_party/heimdal/lib/hx509/cert.c >index 0d99a748fc6a..33805b8ed1a7 100644 >--- a/third_party/heimdal/lib/hx509/cert.c >+++ b/third_party/heimdal/lib/hx509/cert.c >@@ -893,9 +893,12 @@ HX509_LIB_FUNCTION void HX509_LIB_CALL > hx509_free_octet_string_list(hx509_octet_string_list *list) > { > size_t i; >- for (i = 0; i < list->len; i++) >- der_free_octet_string(&list->val[i]); >- free(list->val); >+ >+ if (list->val) { >+ for (i = 0; i < list->len; i++) >+ der_free_octet_string(&list->val[i]); >+ free(list->val); >+ } > list->val = NULL; > list->len = 0; > } >@@ -2438,10 +2441,9 @@ hx509_verify_path(hx509_context context, > * EE checking below. > */ > type = EE_CERT; >- /* FALLTHROUGH */ > } > } >- /* FALLTHROUGH */ >+ fallthrough; > case EE_CERT: > /* > * If there where any proxy certificates in the chain >@@ -2808,6 +2810,12 @@ _hx509_set_cert_attribute(hx509_context context, > { > hx509_cert_attribute a; > void *d; >+ int ret; >+ >+ /* >+ * TODO: Rewrite this (and hx509_cert_attribute, and _hx509_cert_attrs) to >+ * use the add_AttributeValues() util generated by asn1_compile. >+ */ > > if (hx509_cert_get_attribute(cert, oid) != NULL) > return 0; >@@ -2824,13 +2832,18 @@ _hx509_set_cert_attribute(hx509_context context, > if (a == NULL) > return ENOMEM; > >- der_copy_octet_string(attr, &a->data); >- der_copy_oid(oid, &a->oid); >- >- cert->attrs.val[cert->attrs.len] = a; >- cert->attrs.len++; >+ ret = der_copy_octet_string(attr, &a->data); >+ if (ret == 0) >+ ret = der_copy_oid(oid, &a->oid); >+ if (ret == 0) { >+ cert->attrs.val[cert->attrs.len] = a; >+ cert->attrs.len++; >+ } else { >+ der_free_octet_string(&a->data); >+ free(a); >+ } > >- return 0; >+ return ret; > } > > /** >@@ -3705,13 +3718,12 @@ _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env) > goto out; > > ret = hx509_name_to_string(name, &buf); >- if (ret) { >- hx509_name_free(&name); >+ hx509_name_free(&name); >+ if (ret) > goto out; >- } > > ret = hx509_env_add(context, &envcert, "subject", buf); >- hx509_name_free(&name); >+ hx509_xfree(buf); > if (ret) > goto out; > >diff --git a/third_party/heimdal/lib/hx509/cms.c b/third_party/heimdal/lib/hx509/cms.c >index 453762bd10f6..d2728a38c2f9 100644 >--- a/third_party/heimdal/lib/hx509/cms.c >+++ b/third_party/heimdal/lib/hx509/cms.c >@@ -182,7 +182,7 @@ fill_CMSIdentifier(const hx509_cert cert, > &id->u.subjectKeyIdentifier); > if (ret == 0) > break; >- /* FALLTHROUGH */ >+ fallthrough; > case CMS_ID_NAME: { > hx509_name name; > >@@ -1565,7 +1565,9 @@ hx509_cms_create_signed(hx509_context context, > > sigctx.sd.version = cMSVersion_v3; > >- der_copy_oid(eContentType, &sigctx.sd.encapContentInfo.eContentType); >+ ret = der_copy_oid(eContentType, &sigctx.sd.encapContentInfo.eContentType); >+ if (ret) >+ goto out; > > /** > * Use HX509_CMS_SIGNATURE_DETACHED to create detached signatures. >diff --git a/third_party/heimdal/lib/hx509/collector.c b/third_party/heimdal/lib/hx509/collector.c >index dd6222687af4..7b46809816cf 100644 >--- a/third_party/heimdal/lib/hx509/collector.c >+++ b/third_party/heimdal/lib/hx509/collector.c >@@ -191,8 +191,9 @@ match_localkeyid(hx509_context context, > q.local_key_id = &value->localKeyId; > > ret = hx509_certs_find(context, certs, &q, &cert); >+ if (ret == 0 && cert == NULL) >+ ret = HX509_CERT_NOT_FOUND; > if (ret == 0) { >- > if (value->private_key) > _hx509_cert_assign_key(cert, value->private_key); > hx509_cert_free(cert); >diff --git a/third_party/heimdal/lib/hx509/crypto.c b/third_party/heimdal/lib/hx509/crypto.c >index 77e721064ef1..8d368ed9c4d1 100644 >--- a/third_party/heimdal/lib/hx509/crypto.c >+++ b/third_party/heimdal/lib/hx509/crypto.c >@@ -436,6 +436,8 @@ rsa_private_key2SPKI(hx509_context context, > memset(spki, 0, sizeof(*spki)); > > len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL); >+ if (len < 0) >+ return -1; > > spki->subjectPublicKey.data = malloc(len); > if (spki->subjectPublicKey.data == NULL) { >@@ -1625,6 +1627,8 @@ _hx509_private_key_export(hx509_context context, > hx509_key_format_t format, > heim_octet_string *data) > { >+ data->length = 0; >+ data->data = NULL; > if (key->ops->export == NULL) { > hx509_clear_error_string(context); > return HX509_UNIMPLEMENTED_OPERATION; >diff --git a/third_party/heimdal/lib/hx509/error.c b/third_party/heimdal/lib/hx509/error.c >index d3ebd1bf6487..aee4f79e747d 100644 >--- a/third_party/heimdal/lib/hx509/error.c >+++ b/third_party/heimdal/lib/hx509/error.c >@@ -147,48 +147,28 @@ hx509_enomem(hx509_context context) > HX509_LIB_FUNCTION char * HX509_LIB_CALL > hx509_get_error_string(hx509_context context, int error_code) > { >- heim_error_t msg; >- heim_string_t s; >- char *str = NULL; >- >- if (context == NULL) { >- const char *sys_err_msg; >- >- /* This case should only happen on hx509_context_init() failure */ >- if ((sys_err_msg = strerror(error_code))) { >- if (asprintf(&str, "hx509_context_init system error: %s (%d)", >- sys_err_msg, error_code) == -1) >- return NULL; >- return str; >- } >- if (asprintf(&str, "hx509_context_init unknown error: %d", >- error_code) == -1) >- return NULL; >- return str; >- } >+ heim_string_t s = NULL; >+ const char *cstr = NULL; >+ char *str; > >- msg = context->error; >- if (msg == NULL || heim_error_get_code(msg) != error_code) { >- const char *cstr; >- >- cstr = com_right(context->et_list, error_code); >- if (cstr) >- return strdup(cstr); >- cstr = strerror(error_code); >- if (cstr) >- return strdup(cstr); >- if (asprintf(&str, "<unknown error: %d>", error_code) == -1) >- return NULL; >- return str; >- } >+ if (context) { >+ if (context->error && >+ heim_error_get_code(context->error) == error_code && >+ (s = heim_error_copy_string(context->error))) >+ cstr = heim_string_get_utf8(s); > >- s = heim_error_copy_string(msg); >- if (s) { >- const char *cstr = heim_string_get_utf8(s); >- if (cstr) >- str = strdup(cstr); >- heim_release(s); >- } >+ if (cstr == NULL) >+ cstr = com_right(context->et_list, error_code); >+ >+ if (cstr == NULL && error_code > -1) >+ cstr = strerror(error_code); >+ } /* else this could be an error in hx509_context_init() */ >+ >+ if (cstr == NULL) >+ cstr = error_message(error_code); /* never returns NULL */ >+ >+ str = strdup(cstr); >+ heim_release(s); > return str; > } > >@@ -218,9 +198,11 @@ hx509_free_error_string(char *str) > * @ingroup hx509_error > */ > >-HX509_LIB_FUNCTION void HX509_LIB_CALL >+HX509_LIB_NORETURN_FUNCTION >+ __attribute__ ((__noreturn__, __format__ (__printf__, 4, 5))) >+void HX509_LIB_CALL > hx509_err(hx509_context context, int exit_code, >- int error_code, const char *fmt, ...) >+ int error_code, const char *fmt, ...) > { > va_list ap; > const char *msg; >diff --git a/third_party/heimdal/lib/hx509/file.c b/third_party/heimdal/lib/hx509/file.c >index 1b5ca3eae710..a22f6252cfa7 100644 >--- a/third_party/heimdal/lib/hx509/file.c >+++ b/third_party/heimdal/lib/hx509/file.c >@@ -230,7 +230,7 @@ hx509_pem_read(hx509_context context, > where = INDATA; > goto indata; > } >- /* FALLTHROUGH */ >+ fallthrough; > case INHEADER: > if (buf[0] == '\0') { > where = INDATA; >@@ -342,17 +342,15 @@ _hx509_erase_file(hx509_context context, const char *fn) > if (ret == -1 && errno == ENOENT) > return 0; > if (ret == -1) { >- hx509_set_error_string(context, 0, ret, "hx509_certs_destroy: " >- "stat of \"%s\": %s", fn, strerror(ret)); >+ hx509_set_error_string(context, 0, errno, "hx509_certs_destroy: " >+ "stat of \"%s\": %s", fn, strerror(errno)); > return errno; > } > > fd = open(fn, O_RDWR | O_BINARY | O_CLOEXEC | O_NOFOLLOW); >+ if (fd < 0) >+ return errno == ENOENT ? 0 : errno; > rk_cloexec(fd); >- if (ret == -1 && errno == ENOENT) >- return 0; >- if (ret == -1) >- return errno; > > if (unlink(fn) < 0) { > ret = errno; >diff --git a/third_party/heimdal/lib/hx509/hxtool.c b/third_party/heimdal/lib/hx509/hxtool.c >index 43c4713d1163..1bcfdfa44e9d 100644 >--- a/third_party/heimdal/lib/hx509/hxtool.c >+++ b/third_party/heimdal/lib/hx509/hxtool.c >@@ -412,17 +412,19 @@ cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv) > size_t sz; > void *p; > int ret, flags = 0; >- char *infile, *outfile = NULL; >+ const char *outfile = NULL; >+ char *infile, *freeme = NULL; > > memset(&contentType, 0, sizeof(contentType)); > > infile = argv[0]; > > if (argc < 2) { >- ret = asprintf(&outfile, "%s.%s", infile, >+ ret = asprintf(&freeme, "%s.%s", infile, > opt->pem_flag ? "pem" : "cms-signeddata"); >- if (ret == -1 || outfile == NULL) >+ if (ret == -1 || freeme == NULL) > errx(1, "out of memory"); >+ outfile = freeme; > } else > outfile = argv[1]; > >@@ -549,6 +551,7 @@ cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv) > > hx509_certs_free(&signer); > free(o.data); >+ free(freeme); > > return 0; > } >@@ -843,6 +846,7 @@ pcert_validate(struct validate_options *opt, int argc, char **argv) > hx509_certs_iter_f(context, certs, validate_f, ctx); > hx509_certs_free(&certs); > argv++; >+ free(sn); > } > hx509_validate_ctx_free(ctx); > >@@ -1263,6 +1267,7 @@ revoke_print(struct revoke_print_options *opt, int argc, char **argv) > if (ret) > warnx("hx509_revoke_print: %d", ret); > >+ hx509_revoke_free(&revoke_ctx); > return ret; > } > >@@ -1363,7 +1368,7 @@ get_key(const char *fn, const char *type, int optbits, > int ret = 0; > > if (type) { >- struct hx509_generate_private_context *gen_ctx; >+ struct hx509_generate_private_context *gen_ctx = NULL; > > if (strcasecmp(type, "rsa") != 0) > errx(1, "can only handle rsa keys for now"); >@@ -1375,6 +1380,7 @@ get_key(const char *fn, const char *type, int optbits, > ret = _hx509_generate_private_key_bits(context, gen_ctx, optbits); > if (ret == 0) > ret = _hx509_generate_private_key(context, gen_ctx, signer); >+ _hx509_generate_private_key_free(&gen_ctx); > if (ret) > hx509_err(context, 1, ret, "failed to generate private key of type %s", type); > >@@ -1420,6 +1426,7 @@ generate_key(struct generate_key_options *opt, int argc, char **argv) > const char *type = opt->type_string ? opt->type_string : "rsa"; > int bits = opt->key_bits_integer ? opt->key_bits_integer : 2048; > >+ memset(&signer, 0, sizeof(signer)); > get_key(argv[0], type, bits, &signer); > hx509_private_key_free(&signer); > return 0; >@@ -1436,6 +1443,7 @@ request_create(struct request_create_options *opt, int argc, char **argv) > const char *outfile = argv[0]; > > memset(&key, 0, sizeof(key)); >+ memset(&signer, 0, sizeof(signer)); > > get_key(opt->key_string, > opt->generate_key_string, >@@ -2416,6 +2424,7 @@ test_crypto(struct test_crypto_options *opt, int argc, char ** argv) > hx509_err(context, 1, ret, "hx509_cert_iter"); > > hx509_certs_free(&certs); >+ hx509_verify_destroy_ctx(vctx); > > return 0; > } >@@ -2507,6 +2516,7 @@ crl_sign(struct crl_sign_options *opt, int argc, char **argv) > ret = hx509_certs_append(context, revoked, lock, sn); > if (ret) > hx509_err(context, 1, ret, "hx509_certs_append: %s", sn); >+ free(sn); > } > > hx509_crl_add_revoked_certs(context, crl, revoked); >@@ -2775,9 +2785,12 @@ acert1_kus(struct acert_options *opt, > size_t unwanted = 0; > size_t wanted = opt->has_ku_strings.num_strings; > size_t i, k, sz; >+ int ret; > > memset(&ku, 0, sizeof(ku)); >- decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &sz); >+ ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &sz); >+ if (ret) >+ return ret; > ku_num = KeyUsage2int(ku); > > /* Validate requested key usage values */ >@@ -2983,7 +2996,7 @@ acert1(struct acert_options *opt, size_t cert_num, hx509_cert cert, int *matched > ekus_wanted = opt->has_eku_strings.num_strings; > kus_wanted = opt->has_ku_strings.num_strings; > wanted = sans_wanted + ekus_wanted + kus_wanted; >- found = sans_found = ekus_found = kus_found = 0; >+ sans_found = ekus_found = kus_found = 0; > > if (e == NULL) { > if (wanted) >@@ -3080,6 +3093,8 @@ acert(struct acert_options *opt, int argc, char **argv) > ret = acert1(opt, n++, cert, &matched); > if (matched) > break; >+ hx509_cert_free(cert); >+ cert = NULL; > } > if (cursor) > (void) hx509_certs_end_seq(context, certs, cursor); >@@ -3093,6 +3108,7 @@ acert(struct acert_options *opt, int argc, char **argv) > if (ret) > hx509_err(context, 1, ret, "Matching certificate did not meet " > "requirements"); >+ hx509_cert_free(cert); > free(sn); > return 0; > } >diff --git a/third_party/heimdal/lib/hx509/keyset.c b/third_party/heimdal/lib/hx509/keyset.c >index ef3465050225..f25cdf4e419b 100644 >--- a/third_party/heimdal/lib/hx509/keyset.c >+++ b/third_party/heimdal/lib/hx509/keyset.c >@@ -561,11 +561,14 @@ hx509_certs_find(hx509_context context, > break; > if (_hx509_query_match_cert(context, q, c)) { > *r = c; >+ c = NULL; > break; > } > hx509_cert_free(c); >+ c = NULL; > } > >+ hx509_cert_free(c); > hx509_certs_end_seq(context, certs, cursor); > if (ret) > return ret; >@@ -573,7 +576,7 @@ hx509_certs_find(hx509_context context, > * Return HX509_CERT_NOT_FOUND if no certificate in certs matched > * the query. > */ >- if (c == NULL) { >+ if (*r == NULL) { > hx509_clear_error_string(context); > return HX509_CERT_NOT_FOUND; > } >diff --git a/third_party/heimdal/lib/hx509/ks_file.c b/third_party/heimdal/lib/hx509/ks_file.c >index b22093cd4526..880668b45616 100644 >--- a/third_party/heimdal/lib/hx509/ks_file.c >+++ b/third_party/heimdal/lib/hx509/ks_file.c >@@ -548,7 +548,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c) > { > struct store_ctx *sc = ctx; > heim_octet_string data; >- int ret; >+ int ret = 0; > > if (hx509_cert_have_private_key_only(c)) { > data.length = 0; >@@ -564,15 +564,17 @@ store_func(hx509_context context, void *ctx, hx509_cert c) > /* Can't store both. Well, we could, but nothing will support it */ > if (data.data) { > fwrite(data.data, data.length, 1, sc->f); >- free(data.data); > } else if (_hx509_cert_private_key_exportable(c) && > !(sc->store_flags & HX509_CERTS_STORE_NO_PRIVATE_KEYS)) { > hx509_private_key key = _hx509_cert_private_key(c); > >+ free(data.data); >+ data.length = 0; >+ data.data = NULL; > ret = _hx509_private_key_export(context, key, > HX509_KEY_FORMAT_DER, &data); >- fwrite(data.data, data.length, 1, sc->f); >- free(data.data); >+ if (ret == 0 && data.length) >+ fwrite(data.data, data.length, 1, sc->f); > } > break; > case USE_PEM: >@@ -583,23 +585,20 @@ store_func(hx509_context context, void *ctx, hx509_cert c) > > ret = _hx509_private_key_export(context, key, > HX509_KEY_FORMAT_DER, &priv_key); >- if (ret) { >- free(data.data); >- break; >- } >- hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f, >- priv_key.data, priv_key.length); >+ if (ret == 0) >+ ret = hx509_pem_write(context, _hx509_private_pem_name(key), NULL, >+ sc->f, priv_key.data, priv_key.length); > free(priv_key.data); > } >- if (data.data) { >- hx509_pem_write(context, "CERTIFICATE", NULL, sc->f, >- data.data, data.length); >- free(data.data); >+ if (ret == 0 && data.data) { >+ ret = hx509_pem_write(context, "CERTIFICATE", NULL, sc->f, >+ data.data, data.length); > } > break; > } > >- return 0; >+ free(data.data); >+ return ret; > } > > static int >diff --git a/third_party/heimdal/lib/hx509/name.c b/third_party/heimdal/lib/hx509/name.c >index 9b6a156af6c5..7d67716b953a 100644 >--- a/third_party/heimdal/lib/hx509/name.c >+++ b/third_party/heimdal/lib/hx509/name.c >@@ -358,29 +358,29 @@ _hx509_Name_to_string(const Name *n, char **str) > return 0; > } > >-#define COPYCHARARRAY(_ds,_el,_l,_n) \ >- (_l) = strlen(_ds->u._el); \ >- (_n) = malloc((_l) * sizeof((_n)[0])); \ >- if ((_n) == NULL) \ >- return ENOMEM; \ >- for (i = 0; i < (_l); i++) \ >+#define COPYCHARARRAY(_ds,_el,_l,_n) \ >+ (_l) = strlen(_ds->u._el); \ >+ (_n) = malloc((_l + 1) * sizeof((_n)[0])); \ >+ if ((_n) == NULL) \ >+ return ENOMEM; \ >+ for (i = 0; i < (_l); i++) \ > (_n)[i] = _ds->u._el[i] > > >-#define COPYVALARRAY(_ds,_el,_l,_n) \ >- (_l) = _ds->u._el.length; \ >- (_n) = malloc((_l) * sizeof((_n)[0])); \ >- if ((_n) == NULL) \ >- return ENOMEM; \ >- for (i = 0; i < (_l); i++) \ >+#define COPYVALARRAY(_ds,_el,_l,_n) \ >+ (_l) = _ds->u._el.length; \ >+ (_n) = malloc((_l + 1) * sizeof((_n)[0])); \ >+ if ((_n) == NULL) \ >+ return ENOMEM; \ >+ for (i = 0; i < (_l); i++) \ > (_n)[i] = _ds->u._el.data[i] > >-#define COPYVOIDARRAY(_ds,_el,_l,_n) \ >- (_l) = _ds->u._el.length; \ >- (_n) = malloc((_l) * sizeof((_n)[0])); \ >- if ((_n) == NULL) \ >- return ENOMEM; \ >- for (i = 0; i < (_l); i++) \ >+#define COPYVOIDARRAY(_ds,_el,_l,_n) \ >+ (_l) = _ds->u._el.length; \ >+ (_n) = malloc((_l + 1) * sizeof((_n)[0])); \ >+ if ((_n) == NULL) \ >+ return ENOMEM; \ >+ for (i = 0; i < (_l); i++) \ > (_n)[i] = ((unsigned char *)_ds->u._el.data)[i] > > >@@ -423,7 +423,7 @@ dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen) > ret = wind_utf8ucs4_length(ds->u.utf8String, &len); > if (ret) > return ret; >- name = malloc(len * sizeof(name[0])); >+ name = malloc((len + 1) * sizeof(name[0])); > if (name == NULL) > return ENOMEM; > ret = wind_utf8ucs4(ds->u.utf8String, name, &len); >@@ -440,7 +440,7 @@ dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen) > /* try a couple of times to get the length right, XXX gross */ > for (i = 0; i < 4; i++) { > *rlen = *rlen * 2; >- if ((*rname = malloc(*rlen * sizeof((*rname)[0]))) == NULL) { >+ if ((*rname = malloc((rlen[0] + 1) * sizeof((*rname)[0]))) == NULL) { > ret = ENOMEM; > break; > } >@@ -579,9 +579,9 @@ _hx509_name_modify(hx509_context context, > { > RelativeDistinguishedName rdn; > size_t max_len = oidtomaxlen(oid); >- int type_choice, ret; >- const char *a = oidtostring(oid, &type_choice); > char *s = NULL; >+ int type_choice = choice_DirectoryString_printableString; >+ int ret; > > /* > * Check string length upper bounds. >@@ -591,10 +591,13 @@ _hx509_name_modify(hx509_context context, > * here. > */ > if (max_len && strlen(str) > max_len) { >+ char *a = oidtostring(oid, &type_choice); >+ > ret = HX509_PARSING_NAME_FAILED; > hx509_set_error_string(context, 0, ret, "RDN attribute %s value too " > "long (max %llu): %s", a ? a : "<unknown>", > max_len, str); >+ free(a); > return ret; > } > >@@ -622,7 +625,7 @@ _hx509_name_modify(hx509_context context, > */ > rdn.val[0].value.element = type_choice; > if ((s = strdup(str)) == NULL || >- (ret = der_copy_oid(oid, &rdn.val[0].type))) { >+ der_copy_oid(oid, &rdn.val[0].type)) { > free(rdn.val); > free(s); > return hx509_enomem(context); >@@ -934,9 +937,6 @@ hx509_name_expand(hx509_context context, > return ENOMEM; > } > } >- free(s); >- sval = NULL; >- s = NULL; > > while (p != NULL) { > /* expand variables */ >@@ -945,6 +945,7 @@ hx509_name_expand(hx509_context context, > if (p2 == NULL) { > hx509_set_error_string(context, 0, EINVAL, "missing }"); > rk_strpoolfree(strpool); >+ free(s); > return EINVAL; > } > p += 2; >@@ -954,11 +955,13 @@ hx509_name_expand(hx509_context context, > "variable %.*s missing", > (int)(p2 - p), p); > rk_strpoolfree(strpool); >+ free(s); > return EINVAL; > } > strpool = rk_strpoolprintf(strpool, "%s", value); > if (strpool == NULL) { > hx509_set_error_string(context, 0, ENOMEM, "out of memory"); >+ free(s); > return ENOMEM; > } > p2++; >@@ -971,9 +974,14 @@ hx509_name_expand(hx509_context context, > strpool = rk_strpoolprintf(strpool, "%s", p2); > if (strpool == NULL) { > hx509_set_error_string(context, 0, ENOMEM, "out of memory"); >+ free(s); > return ENOMEM; > } > } >+ >+ free(s); >+ s = NULL; >+ > if (strpool) { > size_t max_bytes; > >@@ -1392,7 +1400,9 @@ hx509_general_name_unparse(GeneralName *name, char **str) > > if ((ret = hx509_context_init(&context))) > return ret; >- return hx509_general_name_unparse2(context, name, str); >+ ret = hx509_general_name_unparse2(context, name, str); >+ hx509_context_free(&context); >+ return ret; > } > > /** >@@ -1511,8 +1521,9 @@ hx509_general_name_unparse2(hx509_context context, > default: > return EINVAL; > } >- if (strpool == NULL || >- (*str = rk_strpoolcollect(strpool)) == NULL) >+ if (ret) >+ rk_strpoolfree(strpool); >+ else if (strpool == NULL || (*str = rk_strpoolcollect(strpool)) == NULL) > return ENOMEM; >- return 0; >+ return ret; > } >diff --git a/third_party/heimdal/lib/hx509/print.c b/third_party/heimdal/lib/hx509/print.c >index 544001ebc0df..3309913f3575 100644 >--- a/third_party/heimdal/lib/hx509/print.c >+++ b/third_party/heimdal/lib/hx509/print.c >@@ -361,6 +361,7 @@ check_authorityKeyIdentifier(hx509_validate_ctx ctx, > } > } > >+ free_AuthorityKeyIdentifier(&ai); > return 0; > } > >@@ -771,6 +772,7 @@ check_certificatePolicies(hx509_validate_ctx ctx, > validate_print(ctx, HX509_VALIDATE_F_VERBOSE, > " Unknown:%s", qoid); > } >+ free_UserNotice(&un); > } > } else { > validate_print(ctx, HX509_VALIDATE_F_VERBOSE, >@@ -842,8 +844,11 @@ check_policyMappings(hx509_validate_ctx ctx, > else > validate_print(ctx, HX509_VALIDATE_F_VALIDATE, > "ret=%d while decoding PolicyMappings\n", ret); >+ free(sdpoid); >+ free(idpoid); > } > >+ free_PolicyMappings(&pm); > return 0; > } > >diff --git a/third_party/heimdal/lib/hx509/req.c b/third_party/heimdal/lib/hx509/req.c >index f0a7c2186575..2b3f46d532a6 100644 >--- a/third_party/heimdal/lib/hx509/req.c >+++ b/third_party/heimdal/lib/hx509/req.c >@@ -518,14 +518,13 @@ get_exts(hx509_context context, > const hx509_request req, > Extensions *exts) > { >- uint64_t ku_num; > size_t size; > int ret = 0; > > exts->val = NULL; > exts->len = 0; > >- if ((ku_num = KeyUsage2int(req->ku))) { >+ if (KeyUsage2int(req->ku)) { > Extension e; > > memset(&e, 0, sizeof(e)); >@@ -718,6 +717,7 @@ hx509_request_to_pkcs10(hx509_context context, > abort(); > > free_CertificationRequest(&r); >+ free_Extensions(&exts); > return ret; > } > >@@ -899,9 +899,9 @@ hx509_request_parse_der(hx509_context context, > > out: > free_CertificationRequest(&r); >+ free_Extensions(&exts); > if (ret) > hx509_request_free(req); >- free_CertificationRequest(&r); > return ret; > } > >@@ -1046,7 +1046,7 @@ authorize_feat(hx509_request req, abitstring a, size_t n, int idx) > switch (ret) { > case 0: > req->nauthorized++; >- /*fallthrough*/ >+ fallthrough; > case -1: > return 0; > default: >@@ -1063,7 +1063,7 @@ reject_feat(hx509_request req, abitstring a, size_t n, int idx) > switch (ret) { > case 0: > req->nauthorized--; >- /*fallthrough*/ >+ fallthrough; > case -1: > return 0; > default: >@@ -1245,7 +1245,7 @@ san_map_type(GeneralName *san) > if (der_heim_oid_cmp(&san->u.otherName.type_id, map[i].oid) == 0) > return map[i].type; > } >- /*fallthrough*/ >+ fallthrough; > default: return HX509_SAN_TYPE_UNSUPPORTED; > } > } >@@ -1360,14 +1360,13 @@ hx509_request_get_san(hx509_request req, > case HX509_SAN_TYPE_REGISTERED_ID: > return der_print_heim_oid(&san->u.registeredID, '.', out); > case HX509_SAN_TYPE_XMPP: >- /*fallthrough*/ >+ fallthrough; > case HX509_SAN_TYPE_MS_UPN: { > int ret; > > ret = _hx509_unparse_utf8_string_name(req->context, &pool, > &san->u.otherName.value); >- if (ret == 0 && >- (*out = rk_strpoolcollect(pool)) == NULL) >+ if ((*out = rk_strpoolcollect(pool)) == NULL) > return hx509_enomem(req->context); > return ret; > } >@@ -1376,10 +1375,9 @@ hx509_request_get_san(hx509_request req, > > ret = _hx509_unparse_KRB5PrincipalName(req->context, &pool, > &san->u.otherName.value); >- if (ret == 0 && >- (*out = rk_strpoolcollect(pool)) == NULL) >+ if ((*out = rk_strpoolcollect(pool)) == NULL) > return hx509_enomem(req->context); >- return 0; >+ return ret; > } > default: > *type = HX509_SAN_TYPE_UNSUPPORTED; >diff --git a/third_party/heimdal/lib/hx509/revoke.c b/third_party/heimdal/lib/hx509/revoke.c >index c2f2e00cc297..18b2f8f8f96d 100644 >--- a/third_party/heimdal/lib/hx509/revoke.c >+++ b/third_party/heimdal/lib/hx509/revoke.c >@@ -202,6 +202,8 @@ verify_ocsp(hx509_context context, > ret = hx509_certs_find(context, certs, &q, &signer); > if (ret && ocsp->certs) > ret = hx509_certs_find(context, ocsp->certs, &q, &signer); >+ if (ret == 0 && signer == NULL) >+ ret = HX509_CERT_NOT_FOUND; > if (ret) > goto out; > >@@ -500,6 +502,8 @@ verify_crl(hx509_context context, > q.subject_name = &crl->tbsCertList.issuer; > > ret = hx509_certs_find(context, certs, &q, &signer); >+ if (ret == 0 && signer == NULL) >+ ret = HX509_CERT_NOT_FOUND; > if (ret) { > hx509_set_error_string(context, HX509_ERROR_APPEND, ret, > "Failed to find certificate for CRL"); >diff --git a/third_party/heimdal/lib/hx509/sel-gram.y b/third_party/heimdal/lib/hx509/sel-gram.y >index 7e9d4f26d9c2..09f641d7c051 100644 >--- a/third_party/heimdal/lib/hx509/sel-gram.y >+++ b/third_party/heimdal/lib/hx509/sel-gram.y >@@ -78,6 +78,10 @@ > %token <string> STRING > %token <string> IDENTIFIER > >+%left '!' >+%left kw_AND >+%left kw_OR >+ > %start start > > %% >diff --git a/third_party/heimdal/lib/hx509/softp11.c b/third_party/heimdal/lib/hx509/softp11.c >index 0a1445ba5233..75f675579c77 100644 >--- a/third_party/heimdal/lib/hx509/softp11.c >+++ b/third_party/heimdal/lib/hx509/softp11.c >@@ -311,7 +311,7 @@ add_st_object(void) > return NULL; > > for (i = 0; i < soft_token.object.num_objs; i++) { >- if (soft_token.object.objs == NULL) { >+ if (soft_token.object.objs[i] == NULL) { > soft_token.object.objs[i] = o; > break; > } >@@ -342,6 +342,9 @@ add_object_attribute(struct st_object *o, > struct st_attr *a; > int i; > >+ if (pValue == NULL && ulValueLen) >+ return CKR_ARGUMENTS_BAD; >+ > i = o->num_attributes; > a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0])); > if (a == NULL) >@@ -352,7 +355,8 @@ add_object_attribute(struct st_object *o, > o->attrs[i].attribute.pValue = malloc(ulValueLen); > if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0) > return CKR_DEVICE_MEMORY; >- memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen); >+ if (ulValueLen) >+ memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen); > o->attrs[i].attribute.ulValueLen = ulValueLen; > o->num_attributes++; > >diff --git a/third_party/heimdal/lib/ipc/Makefile.am b/third_party/heimdal/lib/ipc/Makefile.am >index 9338b141e171..6915175618e5 100644 >--- a/third_party/heimdal/lib/ipc/Makefile.am >+++ b/third_party/heimdal/lib/ipc/Makefile.am >@@ -38,6 +38,10 @@ EXTRA_DIST = heim_ipc.defs heim_ipc_async.defs heim_ipc_reply.defs > > if have_gcd > >+# We still use dispatch_get_current_queue(), which is deprecated, and that >+# stops building on recent OS X releases unless we disable this warning. >+WFLAGS += -Wno-deprecated-declarations >+ > heim_ipc.h heim_ipcUser.c heim_ipcServer.c heim_ipcServer.h: heim_ipc.defs > mig -header heim_ipc.h -user heim_ipcUser.c -sheader heim_ipcServer.h -server heim_ipcServer.c -I$(srcdir) $(srcdir)/heim_ipc.defs > >diff --git a/third_party/heimdal/lib/ipc/server.c b/third_party/heimdal/lib/ipc/server.c >index 839a596388a5..40601b9744fa 100644 >--- a/third_party/heimdal/lib/ipc/server.c >+++ b/third_party/heimdal/lib/ipc/server.c >@@ -1014,15 +1014,12 @@ process_loop(void) > for (n = 0 ; n < num_fds; n++) { > if (clients[n] == NULL) > continue; >- if (fds[n].revents & POLLERR) { >- clients[n]->flags |= WAITING_CLOSE; >- continue; >- } >- > if (fds[n].revents & POLLIN) > handle_read(clients[n]); > if (fds[n].revents & POLLOUT) > handle_write(clients[n]); >+ if (fds[n].revents & POLLERR) >+ clients[n]->flags |= WAITING_CLOSE; > } > > n = 0; >@@ -1055,12 +1052,16 @@ heim_sipc_stream_listener(int fd, int type, > heim_ipc_callback callback, > void *user, heim_sipc *ctx) > { >- heim_sipc ct = calloc(1, sizeof(*ct)); >+ heim_sipc ct; > struct client *c; > > if ((type & HEIM_SIPC_TYPE_IPC) && (type & (HEIM_SIPC_TYPE_UINT32|HEIM_SIPC_TYPE_HTTP))) > return EINVAL; > >+ ct = calloc(1, sizeof(*ct)); >+ if (ct == NULL) >+ return ENOMEM; >+ > switch (type) { > case HEIM_SIPC_TYPE_IPC: > c = add_new_socket(fd, LISTEN_SOCKET|WAITING_READ|INCLUDE_ERROR_CODE, callback, user); >@@ -1111,7 +1112,7 @@ heim_sipc_service_unix(const char *service, > #ifdef LOCAL_CREDS > { > int one = 1; >- setsockopt(fd, 0, LOCAL_CREDS, (void *)&one, sizeof(one)); >+ (void) setsockopt(fd, 0, LOCAL_CREDS, (void *)&one, sizeof(one)); > } > #endif > >diff --git a/third_party/heimdal/lib/kadm5/ad.c b/third_party/heimdal/lib/kadm5/ad.c >index 0b4ee656604e..58ccf32eacdd 100644 >--- a/third_party/heimdal/lib/kadm5/ad.c >+++ b/third_party/heimdal/lib/kadm5/ad.c >@@ -1438,6 +1438,7 @@ kadm5_ad_init_with_password_ctx(krb5_context context, > ret = ad_get_cred(ctx, NULL); > if(ret) { > kadm5_ad_destroy(ctx); >+ free(ctx); > return ret; > } > >@@ -1445,6 +1446,7 @@ kadm5_ad_init_with_password_ctx(krb5_context context, > ret = _kadm5_ad_connect(ctx); > if (ret) { > kadm5_ad_destroy(ctx); >+ free(ctx); > return ret; > } > #endif >diff --git a/third_party/heimdal/lib/kadm5/chpass_s.c b/third_party/heimdal/lib/kadm5/chpass_s.c >index e0d63d2ef421..c89448f4882a 100644 >--- a/third_party/heimdal/lib/kadm5/chpass_s.c >+++ b/third_party/heimdal/lib/kadm5/chpass_s.c >@@ -111,7 +111,7 @@ change(void *server_handle, > int cond) > { > kadm5_server_context *context = server_handle; >- hdb_entry_ex ent; >+ hdb_entry ent; > kadm5_ret_t ret; > Key *keys; > size_t num_keys; >@@ -167,7 +167,7 @@ change(void *server_handle, > * We save these for now so we can handle password history checking; > * we handle keepold further below. > */ >- ret = hdb_add_current_keys_to_history(context->context, &ent.entry); >+ ret = hdb_add_current_keys_to_history(context->context, &ent); > if (ret) > goto out3; > } >@@ -179,13 +179,13 @@ change(void *server_handle, > goto out3; > } else { > >- num_keys = ent.entry.keys.len; >- keys = ent.entry.keys.val; >+ num_keys = ent.keys.len; >+ keys = ent.keys.val; > >- ent.entry.keys.len = 0; >- ent.entry.keys.val = NULL; >+ ent.keys.len = 0; >+ ent.keys.val = NULL; > >- ret = _kadm5_set_keys(context, &ent.entry, n_ks_tuple, ks_tuple, >+ ret = _kadm5_set_keys(context, &ent, n_ks_tuple, ks_tuple, > password); > if(ret) { > _kadm5_free_keys(context->context, num_keys, keys); >@@ -196,10 +196,10 @@ change(void *server_handle, > if (cond) { > HDB_extension *ext; > >- ext = hdb_find_extension(&ent.entry, choice_HDB_extension_data_hist_keys); >+ ext = hdb_find_extension(&ent, choice_HDB_extension_data_hist_keys); > if (ext != NULL) >- existsp = _kadm5_exists_keys_hist(ent.entry.keys.val, >- ent.entry.keys.len, >+ existsp = _kadm5_exists_keys_hist(ent.keys.val, >+ ent.keys.len, > &ext->data.u.hist_keys); > } > >@@ -210,9 +210,9 @@ change(void *server_handle, > goto out3; > } > } >- ent.entry.kvno++; >+ ent.kvno++; > >- ent.entry.flags.require_pwchange = 0; >+ ent.flags.require_pwchange = 0; > > if (!keepold) { > HDB_extension ext; >@@ -220,25 +220,25 @@ change(void *server_handle, > memset(&ext, 0, sizeof (ext)); > ext.mandatory = FALSE; > ext.data.element = choice_HDB_extension_data_hist_keys; >- ret = hdb_replace_extension(context->context, &ent.entry, &ext); >+ ret = hdb_replace_extension(context->context, &ent, &ext); > if (ret) > goto out3; > } > >- ret = hdb_seal_keys(context->context, context->db, &ent.entry); >+ ret = hdb_seal_keys(context->context, context->db, &ent); > if (ret) > goto out3; > >- ret = _kadm5_set_modifier(context, &ent.entry); >+ ret = _kadm5_set_modifier(context, &ent); > if(ret) > goto out3; > >- ret = _kadm5_bump_pw_expire(context, &ent.entry); >+ ret = _kadm5_bump_pw_expire(context, &ent); > if (ret) > goto out3; > > /* This logs the change for iprop and writes to the HDB */ >- ret = kadm5_log_modify(context, &ent.entry, >+ ret = kadm5_log_modify(context, &ent, > KADM5_ATTRIBUTES | KADM5_PRINCIPAL | > KADM5_MOD_NAME | KADM5_MOD_TIME | > KADM5_KEY_DATA | KADM5_KVNO | >@@ -249,7 +249,7 @@ change(void *server_handle, > n_ks_tuple, ks_tuple, password); > > out3: >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > out2: > (void) kadm5_log_end(context); > out: >@@ -367,7 +367,7 @@ kadm5_s_chpass_principal_with_key(void *server_handle, > krb5_key_data *key_data) > { > kadm5_server_context *context = server_handle; >- hdb_entry_ex ent; >+ hdb_entry ent; > kadm5_ret_t ret; > uint32_t hook_flags = 0; > >@@ -396,23 +396,23 @@ kadm5_s_chpass_principal_with_key(void *server_handle, > goto out3; > > if (keepold) { >- ret = hdb_add_current_keys_to_history(context->context, &ent.entry); >+ ret = hdb_add_current_keys_to_history(context->context, &ent); > if (ret) > goto out3; > } >- ret = _kadm5_set_keys2(context, &ent.entry, n_key_data, key_data); >+ ret = _kadm5_set_keys2(context, &ent, n_key_data, key_data); > if (ret) > goto out3; >- ent.entry.kvno++; >- ret = _kadm5_set_modifier(context, &ent.entry); >+ ent.kvno++; >+ ret = _kadm5_set_modifier(context, &ent); > if (ret) > goto out3; >- ret = _kadm5_bump_pw_expire(context, &ent.entry); >+ ret = _kadm5_bump_pw_expire(context, &ent); > if (ret) > goto out3; > > if (keepold) { >- ret = hdb_seal_keys(context->context, context->db, &ent.entry); >+ ret = hdb_seal_keys(context->context, context->db, &ent); > if (ret) > goto out3; > } else { >@@ -423,11 +423,11 @@ kadm5_s_chpass_principal_with_key(void *server_handle, > ext.data.element = choice_HDB_extension_data_hist_keys; > ext.data.u.hist_keys.len = 0; > ext.data.u.hist_keys.val = NULL; >- hdb_replace_extension(context->context, &ent.entry, &ext); >+ hdb_replace_extension(context->context, &ent, &ext); > } > > /* This logs the change for iprop and writes to the HDB */ >- ret = kadm5_log_modify(context, &ent.entry, >+ ret = kadm5_log_modify(context, &ent, > KADM5_PRINCIPAL | KADM5_MOD_NAME | > KADM5_MOD_TIME | KADM5_KEY_DATA | KADM5_KVNO | > KADM5_PW_EXPIRATION | KADM5_TL_DATA); >@@ -437,7 +437,7 @@ kadm5_s_chpass_principal_with_key(void *server_handle, > n_key_data, key_data); > > out3: >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > out2: > (void) kadm5_log_end(context); > out: >diff --git a/third_party/heimdal/lib/kadm5/context_s.c b/third_party/heimdal/lib/kadm5/context_s.c >index b5674f19ab6e..0c154ecfef08 100644 >--- a/third_party/heimdal/lib/kadm5/context_s.c >+++ b/third_party/heimdal/lib/kadm5/context_s.c >@@ -161,29 +161,37 @@ find_db_spec(kadm5_server_context *ctx) > p = hdb_dbinfo_get_dbname(context, d); > if (p) { > ctx->config.dbname = strdup(p); >- if (ctx->config.dbname == NULL) >+ if (ctx->config.dbname == NULL) { >+ hdb_free_dbinfo(context, &info); > return krb5_enomem(context); >+ } > } > > p = hdb_dbinfo_get_acl_file(context, d); > if (p) { > ctx->config.acl_file = strdup(p); >- if (ctx->config.acl_file == NULL) >+ if (ctx->config.acl_file == NULL) { >+ hdb_free_dbinfo(context, &info); > return krb5_enomem(context); >+ } > } > > p = hdb_dbinfo_get_mkey_file(context, d); > if (p) { > ctx->config.stash_file = strdup(p); >- if (ctx->config.stash_file == NULL) >+ if (ctx->config.stash_file == NULL) { >+ hdb_free_dbinfo(context, &info); > return krb5_enomem(context); >+ } > } > > p = hdb_dbinfo_get_log_file(context, d); > if (p) { > ctx->log_context.log_file = strdup(p); >- if (ctx->log_context.log_file == NULL) >+ if (ctx->log_context.log_file == NULL) { >+ hdb_free_dbinfo(context, &info); > return krb5_enomem(context); >+ } > } > break; > } >diff --git a/third_party/heimdal/lib/kadm5/create_s.c b/third_party/heimdal/lib/kadm5/create_s.c >index 42125e28a7e0..1c2ab15f30db 100644 >--- a/third_party/heimdal/lib/kadm5/create_s.c >+++ b/third_party/heimdal/lib/kadm5/create_s.c >@@ -57,7 +57,7 @@ static kadm5_ret_t > create_principal(kadm5_server_context *context, > kadm5_principal_ent_t princ, > uint32_t mask, >- hdb_entry_ex *ent, >+ hdb_entry *ent, > uint32_t required_mask, > uint32_t forbidden_mask) > { >@@ -74,7 +74,7 @@ create_principal(kadm5_server_context *context, > /* XXX no real policies for now */ > return KADM5_UNK_POLICY; > ret = krb5_copy_principal(context->context, princ->principal, >- &ent->entry.principal); >+ &ent->principal); > if(ret) > return ret; > >@@ -96,10 +96,10 @@ create_principal(kadm5_server_context *context, > if (ret) > return ret; > >- ent->entry.created_by.time = time(NULL); >+ ent->created_by.time = time(NULL); > > return krb5_copy_principal(context->context, context->caller, >- &ent->entry.created_by.principal); >+ &ent->created_by.principal); > } > > struct create_principal_hook_ctx { >@@ -167,7 +167,7 @@ kadm5_s_create_principal_with_key(void *server_handle, > uint32_t mask) > { > kadm5_ret_t ret; >- hdb_entry_ex ent; >+ hdb_entry ent; > kadm5_server_context *context = server_handle; > > if ((mask & KADM5_KVNO) == 0) { >@@ -194,7 +194,7 @@ kadm5_s_create_principal_with_key(void *server_handle, > if (!context->keep_open) { > ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0); > if (ret) { >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > return ret; > } > } >@@ -203,7 +203,7 @@ kadm5_s_create_principal_with_key(void *server_handle, > if (ret) > goto out; > >- ret = hdb_seal_keys(context->context, context->db, &ent.entry); >+ ret = hdb_seal_keys(context->context, context->db, &ent); > if (ret) > goto out2; > >@@ -213,7 +213,7 @@ kadm5_s_create_principal_with_key(void *server_handle, > * Creation of would-be virtual principals w/o the materialize flag will be > * rejected in kadm5_log_create(). > */ >- ret = kadm5_log_create(context, &ent.entry); >+ ret = kadm5_log_create(context, &ent); > > (void) create_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT, > ret, princ, mask, NULL); >@@ -227,7 +227,7 @@ kadm5_s_create_principal_with_key(void *server_handle, > if (ret == 0 && ret2 != 0) > ret = ret2; > } >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > return _kadm5_error_code(ret); > } > >@@ -241,7 +241,7 @@ kadm5_s_create_principal(void *server_handle, > const char *password) > { > kadm5_ret_t ret; >- hdb_entry_ex ent; >+ hdb_entry ent; > kadm5_server_context *context = server_handle; > int use_pw = 1; > >@@ -315,7 +315,7 @@ kadm5_s_create_principal(void *server_handle, > if (!context->keep_open) { > ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0); > if (ret) { >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > return ret; > } > } >@@ -324,20 +324,20 @@ kadm5_s_create_principal(void *server_handle, > if (ret) > goto out; > >- free_Keys(&ent.entry.keys); >+ free_Keys(&ent.keys); > > if (use_pw) { >- ret = _kadm5_set_keys(context, &ent.entry, n_ks_tuple, ks_tuple, password); >+ ret = _kadm5_set_keys(context, &ent, n_ks_tuple, ks_tuple, password); > if (ret) > goto out2; > } > >- ret = hdb_seal_keys(context->context, context->db, &ent.entry); >+ ret = hdb_seal_keys(context->context, context->db, &ent); > if (ret) > goto out2; > > /* This logs the change for iprop and writes to the HDB */ >- ret = kadm5_log_create(context, &ent.entry); >+ ret = kadm5_log_create(context, &ent); > > (void) create_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT, > ret, princ, mask, password); >@@ -351,7 +351,7 @@ kadm5_s_create_principal(void *server_handle, > if (ret == 0 && ret2 != 0) > ret = ret2; > } >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > return _kadm5_error_code(ret); > } > >diff --git a/third_party/heimdal/lib/kadm5/delete_s.c b/third_party/heimdal/lib/kadm5/delete_s.c >index 6942148dbb53..aa9fdb4fc0a2 100644 >--- a/third_party/heimdal/lib/kadm5/delete_s.c >+++ b/third_party/heimdal/lib/kadm5/delete_s.c >@@ -92,7 +92,7 @@ kadm5_s_delete_principal(void *server_handle, krb5_principal princ) > { > kadm5_server_context *context = server_handle; > kadm5_ret_t ret; >- hdb_entry_ex ent; >+ hdb_entry ent; > > memset(&ent, 0, sizeof(ent)); > if (!context->keep_open) { >@@ -112,7 +112,7 @@ kadm5_s_delete_principal(void *server_handle, krb5_principal princ) > 0, &ent); > if (ret == HDB_ERR_NOENTRY) > goto out2; >- if (ent.entry.flags.immutable) { >+ if (ent.flags.immutable) { > ret = KADM5_PROTECT_PRINCIPAL; > goto out3; > } >@@ -121,7 +121,7 @@ kadm5_s_delete_principal(void *server_handle, krb5_principal princ) > if (ret) > goto out3; > >- ret = hdb_seal_keys(context->context, context->db, &ent.entry); >+ ret = hdb_seal_keys(context->context, context->db, &ent); > if (ret) > goto out3; > >@@ -131,7 +131,7 @@ kadm5_s_delete_principal(void *server_handle, krb5_principal princ) > (void) delete_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT, ret, princ); > > out3: >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > out2: > (void) kadm5_log_end(context); > out: >diff --git a/third_party/heimdal/lib/kadm5/ent_setup.c b/third_party/heimdal/lib/kadm5/ent_setup.c >index 677bda6d8973..24a7983b6e1f 100644 >--- a/third_party/heimdal/lib/kadm5/ent_setup.c >+++ b/third_party/heimdal/lib/kadm5/ent_setup.c >@@ -73,7 +73,7 @@ attr_to_flags(unsigned attr, HDBFlags *flags) > static kadm5_ret_t > perform_tl_data(krb5_context context, > HDB *db, >- hdb_entry_ex *ent, >+ hdb_entry *ent, > const krb5_tl_data *tl_data) > { > kadm5_ret_t ret = 0; >@@ -84,7 +84,7 @@ perform_tl_data(krb5_context context, > if (pw[tl_data->tl_data_length] != '\0') > return KADM5_BAD_TL_TYPE; > >- ret = hdb_entry_set_password(context, db, &ent->entry, pw); >+ ret = hdb_entry_set_password(context, db, ent, pw); > > } else if (tl_data->tl_data_type == KRB5_TL_LAST_PWD_CHANGE) { > unsigned long t; >@@ -96,7 +96,7 @@ perform_tl_data(krb5_context context, > s = tl_data->tl_data_contents; > > (void) _krb5_get_int(s, &t, tl_data->tl_data_length); >- ret = hdb_entry_set_pw_change_time(context, &ent->entry, t); >+ ret = hdb_entry_set_pw_change_time(context, ent, t); > > } else if (tl_data->tl_data_type == KRB5_TL_KEY_ROTATION) { > HDB_Ext_KeyRotation *prev_kr = 0; >@@ -105,7 +105,7 @@ perform_tl_data(krb5_context context, > > ext.mandatory = 0; > ext.data.element = choice_HDB_extension_data_key_rotation; >- prev_ext = hdb_find_extension(&ent->entry, ext.data.element); >+ prev_ext = hdb_find_extension(ent, ext.data.element); > if (prev_ext) > prev_kr = &prev_ext->data.u.key_rotation; > ret = decode_HDB_Ext_KeyRotation(tl_data->tl_data_contents, >@@ -115,7 +115,7 @@ perform_tl_data(krb5_context context, > ret = hdb_validate_key_rotations(context, prev_kr, > &ext.data.u.key_rotation); > if (ret == 0) >- ret = hdb_replace_extension(context, &ent->entry, &ext); >+ ret = hdb_replace_extension(context, ent, &ext); > free_HDB_extension(&ext); > } else if (tl_data->tl_data_type == KRB5_TL_EXTENSION) { > HDB_extension ext; >@@ -128,7 +128,7 @@ perform_tl_data(krb5_context context, > return KADM5_BAD_TL_TYPE; > > if (ext.data.element == choice_HDB_extension_data_key_rotation) { >- HDB_extension *prev_ext = hdb_find_extension(&ent->entry, >+ HDB_extension *prev_ext = hdb_find_extension(ent, > ext.data.element); > HDB_Ext_KeyRotation *prev_kr = 0; > >@@ -140,19 +140,19 @@ perform_tl_data(krb5_context context, > if (ret) > ret = KADM5_BAD_TL_TYPE; /* XXX Need new error code */ > if (ret == 0) >- ret = hdb_replace_extension(context, &ent->entry, &ext); >+ ret = hdb_replace_extension(context, ent, &ext); > free_HDB_extension(&ext); > } else if (tl_data->tl_data_type == KRB5_TL_ETYPES) { >- if (!ent->entry.etypes && >- (ent->entry.etypes = calloc(1, >- sizeof(ent->entry.etypes[0]))) == NULL) >+ if (!ent->etypes && >+ (ent->etypes = calloc(1, >+ sizeof(ent->etypes[0]))) == NULL) > ret = krb5_enomem(context); >- if (ent->entry.etypes) >- free_HDB_EncTypeList(ent->entry.etypes); >+ if (ent->etypes) >+ free_HDB_EncTypeList(ent->etypes); > if (ret == 0) > ret = decode_HDB_EncTypeList(tl_data->tl_data_contents, > tl_data->tl_data_length, >- ent->entry.etypes, NULL); >+ ent->etypes, NULL); > if (ret) > return KADM5_BAD_TL_TYPE; > } else if (tl_data->tl_data_type == KRB5_TL_ALIASES) { >@@ -164,14 +164,14 @@ perform_tl_data(krb5_context context, > } > > static void >-default_flags(hdb_entry_ex *ent) >+default_flags(hdb_entry *ent) > { >- ent->entry.flags.client = 1; >- ent->entry.flags.server = 1; >- ent->entry.flags.forwardable = 1; >- ent->entry.flags.proxiable = 1; >- ent->entry.flags.renewable = 1; >- ent->entry.flags.postdate = 1; >+ ent->flags.client = 1; >+ ent->flags.server = 1; >+ ent->flags.forwardable = 1; >+ ent->flags.proxiable = 1; >+ ent->flags.renewable = 1; >+ ent->flags.postdate = 1; > } > > >@@ -183,7 +183,7 @@ default_flags(hdb_entry_ex *ent) > > kadm5_ret_t > _kadm5_setup_entry(kadm5_server_context *context, >- hdb_entry_ex *ent, >+ hdb_entry *ent, > uint32_t mask, > kadm5_principal_ent_t princ, > uint32_t princ_mask, >@@ -193,23 +193,23 @@ _kadm5_setup_entry(kadm5_server_context *context, > if(mask & KADM5_PRINC_EXPIRE_TIME > && princ_mask & KADM5_PRINC_EXPIRE_TIME) { > if (princ->princ_expire_time) >- set_value(ent->entry.valid_end, princ->princ_expire_time); >+ set_value(ent->valid_end, princ->princ_expire_time); > else >- set_null(ent->entry.valid_end); >+ set_null(ent->valid_end); > } > if(mask & KADM5_PW_EXPIRATION > && princ_mask & KADM5_PW_EXPIRATION) { > if (princ->pw_expiration) >- set_value(ent->entry.pw_end, princ->pw_expiration); >+ set_value(ent->pw_end, princ->pw_expiration); > else >- set_null(ent->entry.pw_end); >+ set_null(ent->pw_end); > } > if(mask & KADM5_ATTRIBUTES) { > if (princ_mask & KADM5_ATTRIBUTES) { >- attr_to_flags(princ->attributes, &ent->entry.flags); >+ attr_to_flags(princ->attributes, &ent->flags); > } else if(def_mask & KADM5_ATTRIBUTES) { >- attr_to_flags(def->attributes, &ent->entry.flags); >- ent->entry.flags.invalid = 0; >+ attr_to_flags(def->attributes, &ent->flags); >+ ent->flags.invalid = 0; > } else { > default_flags(ent); > } >@@ -218,41 +218,41 @@ _kadm5_setup_entry(kadm5_server_context *context, > if(mask & KADM5_MAX_LIFE) { > if(princ_mask & KADM5_MAX_LIFE) { > if(princ->max_life) >- set_value(ent->entry.max_life, princ->max_life); >+ set_value(ent->max_life, princ->max_life); > else >- set_null(ent->entry.max_life); >+ set_null(ent->max_life); > } else if(def_mask & KADM5_MAX_LIFE) { > if(def->max_life) >- set_value(ent->entry.max_life, def->max_life); >+ set_value(ent->max_life, def->max_life); > else >- set_null(ent->entry.max_life); >+ set_null(ent->max_life); > } > } > if(mask & KADM5_KVNO > && (princ_mask & KADM5_KVNO)) { > krb5_error_code ret; > >- ret = hdb_change_kvno(context->context, princ->kvno, &ent->entry); >+ ret = hdb_change_kvno(context->context, princ->kvno, ent); > if (ret && ret != HDB_ERR_KVNO_NOT_FOUND) > return ret; >- ent->entry.kvno = princ->kvno; /* force it */ >+ ent->kvno = princ->kvno; /* force it */ > } > if(mask & KADM5_MAX_RLIFE) { > if(princ_mask & KADM5_MAX_RLIFE) { > if(princ->max_renewable_life) >- set_value(ent->entry.max_renew, princ->max_renewable_life); >+ set_value(ent->max_renew, princ->max_renewable_life); > else >- set_null(ent->entry.max_renew); >+ set_null(ent->max_renew); > } else if(def_mask & KADM5_MAX_RLIFE) { > if(def->max_renewable_life) >- set_value(ent->entry.max_renew, def->max_renewable_life); >+ set_value(ent->max_renew, def->max_renewable_life); > else >- set_null(ent->entry.max_renew); >+ set_null(ent->max_renew); > } > } > if(mask & KADM5_KEY_DATA > && princ_mask & KADM5_KEY_DATA) { >- _kadm5_set_keys2(context, &ent->entry, >+ _kadm5_set_keys2(context, ent, > princ->n_key_data, princ->key_data); > } > if(mask & KADM5_TL_DATA) { >diff --git a/third_party/heimdal/lib/kadm5/get_princs_s.c b/third_party/heimdal/lib/kadm5/get_princs_s.c >index f7182d7ec88d..27fac2bbb0bc 100644 >--- a/third_party/heimdal/lib/kadm5/get_princs_s.c >+++ b/third_party/heimdal/lib/kadm5/get_princs_s.c >@@ -55,12 +55,12 @@ add_princ(krb5_context context, struct foreach_data *d, char *princ) > } > > static krb5_error_code >-foreach(krb5_context context, HDB *db, hdb_entry_ex *ent, void *data) >+foreach(krb5_context context, HDB *db, hdb_entry *ent, void *data) > { > struct foreach_data *d = data; > char *princ; > krb5_error_code ret; >- ret = krb5_unparse_name(context, ent->entry.principal, &princ); >+ ret = krb5_unparse_name(context, ent->principal, &princ); > if(ret) > return ret; > if(d->exp){ >@@ -98,7 +98,9 @@ kadm5_s_get_principals(void *server_handle, > krb5_realm r; > int aret; > >- krb5_get_default_realm(context->context, &r); >+ ret = krb5_get_default_realm(context->context, &r); >+ if (ret) >+ goto out; > aret = asprintf(&d.exp2, "%s@%s", expression, r); > free(r); > if (aret == -1 || d.exp2 == NULL) { >diff --git a/third_party/heimdal/lib/kadm5/get_s.c b/third_party/heimdal/lib/kadm5/get_s.c >index 56aec67a2231..0c87343d2e17 100644 >--- a/third_party/heimdal/lib/kadm5/get_s.c >+++ b/third_party/heimdal/lib/kadm5/get_s.c >@@ -122,7 +122,7 @@ kadm5_s_get_principal(void *server_handle, > { > kadm5_server_context *context = server_handle; > kadm5_ret_t ret; >- hdb_entry_ex ent; >+ hdb_entry ent; > unsigned int flags = HDB_F_GET_ANY | HDB_F_ADMIN_DATA; > > if ((mask & KADM5_KEY_DATA) || (mask & KADM5_KVNO)) >@@ -157,57 +157,57 @@ kadm5_s_get_principal(void *server_handle, > return _kadm5_error_code(ret); > > if(mask & KADM5_PRINCIPAL) >- ret = krb5_copy_principal(context->context, ent.entry.principal, >+ ret = krb5_copy_principal(context->context, ent.principal, > &out->principal); > if(ret) > goto out; >- if(mask & KADM5_PRINC_EXPIRE_TIME && ent.entry.valid_end) >- out->princ_expire_time = *ent.entry.valid_end; >- if(mask & KADM5_PW_EXPIRATION && ent.entry.pw_end) >- out->pw_expiration = *ent.entry.pw_end; >+ if(mask & KADM5_PRINC_EXPIRE_TIME && ent.valid_end) >+ out->princ_expire_time = *ent.valid_end; >+ if(mask & KADM5_PW_EXPIRATION && ent.pw_end) >+ out->pw_expiration = *ent.pw_end; > if(mask & KADM5_LAST_PWD_CHANGE) >- hdb_entry_get_pw_change_time(&ent.entry, &out->last_pwd_change); >+ hdb_entry_get_pw_change_time(&ent, &out->last_pwd_change); > if(mask & KADM5_ATTRIBUTES){ >- out->attributes |= ent.entry.flags.postdate ? 0 : KRB5_KDB_DISALLOW_POSTDATED; >- out->attributes |= ent.entry.flags.forwardable ? 0 : KRB5_KDB_DISALLOW_FORWARDABLE; >- out->attributes |= ent.entry.flags.initial ? KRB5_KDB_DISALLOW_TGT_BASED : 0; >- out->attributes |= ent.entry.flags.renewable ? 0 : KRB5_KDB_DISALLOW_RENEWABLE; >- out->attributes |= ent.entry.flags.proxiable ? 0 : KRB5_KDB_DISALLOW_PROXIABLE; >- out->attributes |= ent.entry.flags.invalid ? KRB5_KDB_DISALLOW_ALL_TIX : 0; >- out->attributes |= ent.entry.flags.require_preauth ? KRB5_KDB_REQUIRES_PRE_AUTH : 0; >- out->attributes |= ent.entry.flags.require_pwchange ? KRB5_KDB_REQUIRES_PWCHANGE : 0; >- out->attributes |= ent.entry.flags.client ? 0 : KRB5_KDB_DISALLOW_CLIENT; >- out->attributes |= ent.entry.flags.server ? 0 : KRB5_KDB_DISALLOW_SVR; >- out->attributes |= ent.entry.flags.change_pw ? KRB5_KDB_PWCHANGE_SERVICE : 0; >- out->attributes |= ent.entry.flags.ok_as_delegate ? KRB5_KDB_OK_AS_DELEGATE : 0; >- out->attributes |= ent.entry.flags.trusted_for_delegation ? KRB5_KDB_TRUSTED_FOR_DELEGATION : 0; >- out->attributes |= ent.entry.flags.allow_kerberos4 ? KRB5_KDB_ALLOW_KERBEROS4 : 0; >- out->attributes |= ent.entry.flags.allow_digest ? KRB5_KDB_ALLOW_DIGEST : 0; >- out->attributes |= ent.entry.flags.virtual_keys ? KRB5_KDB_VIRTUAL_KEYS : 0; >- out->attributes |= ent.entry.flags.virtual ? KRB5_KDB_VIRTUAL : 0; >- out->attributes |= ent.entry.flags.no_auth_data_reqd ? KRB5_KDB_NO_AUTH_DATA_REQUIRED : 0; >+ out->attributes |= ent.flags.postdate ? 0 : KRB5_KDB_DISALLOW_POSTDATED; >+ out->attributes |= ent.flags.forwardable ? 0 : KRB5_KDB_DISALLOW_FORWARDABLE; >+ out->attributes |= ent.flags.initial ? KRB5_KDB_DISALLOW_TGT_BASED : 0; >+ out->attributes |= ent.flags.renewable ? 0 : KRB5_KDB_DISALLOW_RENEWABLE; >+ out->attributes |= ent.flags.proxiable ? 0 : KRB5_KDB_DISALLOW_PROXIABLE; >+ out->attributes |= ent.flags.invalid ? KRB5_KDB_DISALLOW_ALL_TIX : 0; >+ out->attributes |= ent.flags.require_preauth ? KRB5_KDB_REQUIRES_PRE_AUTH : 0; >+ out->attributes |= ent.flags.require_pwchange ? KRB5_KDB_REQUIRES_PWCHANGE : 0; >+ out->attributes |= ent.flags.client ? 0 : KRB5_KDB_DISALLOW_CLIENT; >+ out->attributes |= ent.flags.server ? 0 : KRB5_KDB_DISALLOW_SVR; >+ out->attributes |= ent.flags.change_pw ? KRB5_KDB_PWCHANGE_SERVICE : 0; >+ out->attributes |= ent.flags.ok_as_delegate ? KRB5_KDB_OK_AS_DELEGATE : 0; >+ out->attributes |= ent.flags.trusted_for_delegation ? KRB5_KDB_TRUSTED_FOR_DELEGATION : 0; >+ out->attributes |= ent.flags.allow_kerberos4 ? KRB5_KDB_ALLOW_KERBEROS4 : 0; >+ out->attributes |= ent.flags.allow_digest ? KRB5_KDB_ALLOW_DIGEST : 0; >+ out->attributes |= ent.flags.virtual_keys ? KRB5_KDB_VIRTUAL_KEYS : 0; >+ out->attributes |= ent.flags.virtual ? KRB5_KDB_VIRTUAL : 0; >+ out->attributes |= ent.flags.no_auth_data_reqd ? KRB5_KDB_NO_AUTH_DATA_REQUIRED : 0; > } > if(mask & KADM5_MAX_LIFE) { >- if(ent.entry.max_life) >- out->max_life = *ent.entry.max_life; >+ if(ent.max_life) >+ out->max_life = *ent.max_life; > else > out->max_life = INT_MAX; > } > if(mask & KADM5_MOD_TIME) { >- if(ent.entry.modified_by) >- out->mod_date = ent.entry.modified_by->time; >+ if(ent.modified_by) >+ out->mod_date = ent.modified_by->time; > else >- out->mod_date = ent.entry.created_by.time; >+ out->mod_date = ent.created_by.time; > } > if(mask & KADM5_MOD_NAME) { >- if(ent.entry.modified_by) { >- if (ent.entry.modified_by->principal != NULL) >+ if(ent.modified_by) { >+ if (ent.modified_by->principal != NULL) > ret = krb5_copy_principal(context->context, >- ent.entry.modified_by->principal, >+ ent.modified_by->principal, > &out->mod_name); >- } else if(ent.entry.created_by.principal != NULL) >+ } else if(ent.created_by.principal != NULL) > ret = krb5_copy_principal(context->context, >- ent.entry.created_by.principal, >+ ent.created_by.principal, > &out->mod_name); > else > out->mod_name = NULL; >@@ -216,13 +216,13 @@ kadm5_s_get_principal(void *server_handle, > goto out; > > if(mask & KADM5_KVNO) >- out->kvno = ent.entry.kvno; >+ out->kvno = ent.kvno; > if(mask & KADM5_MKVNO) { > size_t n; > out->mkvno = 0; /* XXX */ >- for(n = 0; n < ent.entry.keys.len; n++) >- if(ent.entry.keys.val[n].mkvno) { >- out->mkvno = *ent.entry.keys.val[n].mkvno; /* XXX this isn't right */ >+ for(n = 0; n < ent.keys.len; n++) >+ if(ent.keys.val[n].mkvno) { >+ out->mkvno = *ent.keys.val[n].mkvno; /* XXX this isn't right */ > break; > } > } >@@ -239,7 +239,7 @@ kadm5_s_get_principal(void *server_handle, > if(mask & KADM5_POLICY) { > HDB_extension *ext; > >- ext = hdb_find_extension(&ent.entry, choice_HDB_extension_data_policy); >+ ext = hdb_find_extension(&ent, choice_HDB_extension_data_policy); > if (ext == NULL) { > out->policy = strdup("default"); > /* It's OK if we retun NULL instead of "default" */ >@@ -252,27 +252,27 @@ kadm5_s_get_principal(void *server_handle, > } > } > if(mask & KADM5_MAX_RLIFE) { >- if(ent.entry.max_renew) >- out->max_renewable_life = *ent.entry.max_renew; >+ if(ent.max_renew) >+ out->max_renewable_life = *ent.max_renew; > else > out->max_renewable_life = INT_MAX; > } > if(mask & KADM5_KEY_DATA){ > size_t i; >- size_t n_keys = ent.entry.keys.len; >+ size_t n_keys = ent.keys.len; > krb5_salt salt; > HDB_extension *ext; > HDB_Ext_KeySet *hist_keys = NULL; > > /* Don't return stale keys to kadm5 clients */ >- ret = hdb_prune_keys(context->context, &ent.entry); >+ ret = hdb_prune_keys(context->context, &ent); > if (ret) > goto out; >- ext = hdb_find_extension(&ent.entry, choice_HDB_extension_data_hist_keys); >+ ext = hdb_find_extension(&ent, choice_HDB_extension_data_hist_keys); > if (ext != NULL) > hist_keys = &ext->data.u.hist_keys; > >- krb5_get_pw_salt(context->context, ent.entry.principal, &salt); >+ krb5_get_pw_salt(context->context, ent.principal, &salt); > for (i = 0; hist_keys != NULL && i < hist_keys->len; i++) > n_keys += hist_keys->val[i].keys.len; > out->key_data = malloc(n_keys * sizeof(*out->key_data)); >@@ -281,8 +281,8 @@ kadm5_s_get_principal(void *server_handle, > goto out; > } > out->n_key_data = 0; >- ret = copy_keyset_to_kadm5(context, ent.entry.kvno, ent.entry.keys.len, >- ent.entry.keys.val, &salt, out); >+ ret = copy_keyset_to_kadm5(context, ent.kvno, ent.keys.len, >+ ent.keys.val, &salt, out); > if (ret) > goto out; > for (i = 0; hist_keys != NULL && i < hist_keys->len; i++) { >@@ -296,8 +296,7 @@ kadm5_s_get_principal(void *server_handle, > krb5_free_salt(context->context, salt); > assert( out->n_key_data == n_keys ); > } >- if (ret) >- goto out; >+ assert(ret == 0); > if(mask & KADM5_TL_DATA) { > time_t last_pw_expire; > const HDB_Ext_PKINIT_acl *acl; >@@ -305,12 +304,12 @@ kadm5_s_get_principal(void *server_handle, > const HDB_Ext_KeyRotation *kr; > heim_octet_string krb5_config; > >- if (ent.entry.etypes) { >+ if (ent.etypes) { > krb5_data buf; > size_t len; > > ASN1_MALLOC_ENCODE(HDB_EncTypeList, buf.data, buf.length, >- ent.entry.etypes, &len, ret); >+ ent.etypes, &len, ret); > if (ret == 0) { > ret = add_tl_data(out, KRB5_TL_ETYPES, buf.data, buf.length); > free(buf.data); >@@ -319,20 +318,22 @@ kadm5_s_get_principal(void *server_handle, > goto out; > } > >- ret = hdb_entry_get_pw_change_time(&ent.entry, &last_pw_expire); >+ ret = hdb_entry_get_pw_change_time(&ent, &last_pw_expire); > if (ret == 0 && last_pw_expire) { > unsigned char buf[4]; > _krb5_put_int(buf, last_pw_expire, sizeof(buf)); > ret = add_tl_data(out, KRB5_TL_LAST_PWD_CHANGE, buf, sizeof(buf)); >+ if (ret) >+ goto out; > } >- if (ret == 0) >- ret = hdb_entry_get_krb5_config(&ent.entry, &krb5_config); >+ >+ ret = hdb_entry_get_krb5_config(&ent, &krb5_config); > if (ret == 0 && krb5_config.length) { > ret = add_tl_data(out, KRB5_TL_KRB5_CONFIG, krb5_config.data, > krb5_config.length); >+ if (ret) >+ goto out; > } >- if (ret) >- goto out; > /* > * If the client was allowed to get key data, let it have the > * password too. >@@ -342,15 +343,17 @@ kadm5_s_get_principal(void *server_handle, > > /* XXX But not if the client doesn't have ext-keys */ > ret = hdb_entry_get_password(context->context, >- context->db, &ent.entry, &pw); >+ context->db, &ent, &pw); > if (ret == 0) { > ret = add_tl_data(out, KRB5_TL_PASSWORD, pw, strlen(pw) + 1); > free(pw); >+ if (ret) >+ goto out; > } > krb5_clear_error_message(context->context); > } > >- ret = hdb_entry_get_pkinit_acl(&ent.entry, &acl); >+ ret = hdb_entry_get_pkinit_acl(&ent, &acl); > if (ret == 0 && acl) { > krb5_data buf; > size_t len; >@@ -367,10 +370,8 @@ kadm5_s_get_principal(void *server_handle, > if (ret) > goto out; > } >- if (ret) >- goto out; > >- ret = hdb_entry_get_aliases(&ent.entry, &aliases); >+ ret = hdb_entry_get_aliases(&ent, &aliases); > if (ret == 0 && aliases) { > krb5_data buf; > size_t len; >@@ -387,34 +388,24 @@ kadm5_s_get_principal(void *server_handle, > if (ret) > goto out; > } >- if (ret) >- goto out; > >- ret = hdb_entry_get_key_rotation(context->context, &ent.entry, &kr); >+ ret = hdb_entry_get_key_rotation(context->context, &ent, &kr); > if (ret == 0 && kr) { > krb5_data buf; > size_t len; > > ASN1_MALLOC_ENCODE(HDB_Ext_KeyRotation, buf.data, buf.length, > kr, &len, ret); >- if (ret) >- goto out; >- if (len != buf.length) >- krb5_abortx(context->context, >- "internal ASN.1 encoder error"); >- ret = add_tl_data(out, KRB5_TL_KEY_ROTATION, buf.data, buf.length); >+ if (ret == 0) >+ ret = add_tl_data(out, KRB5_TL_KEY_ROTATION, buf.data, buf.length); > free(buf.data); >- if (ret) >- goto out; > } >- if (ret) >- goto out; > } > > out: > if (ret) > kadm5_free_principal_ent(context, out); >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > > return _kadm5_error_code(ret); > } >diff --git a/third_party/heimdal/lib/kadm5/init_c.c b/third_party/heimdal/lib/kadm5/init_c.c >index a0a3443898a5..5d585d1a2951 100644 >--- a/third_party/heimdal/lib/kadm5/init_c.c >+++ b/third_party/heimdal/lib/kadm5/init_c.c >@@ -427,12 +427,15 @@ _kadm5_c_get_cred_cache(krb5_context context, > user = roken_get_username(userbuf, sizeof(userbuf)); > if (user == NULL) { > krb5_set_error_message(context, KADM5_FAILURE, "Unable to find local user name"); >+ krb5_free_principal(context, client); > return KADM5_FAILURE; > } > ret = krb5_make_principal(context, &default_client, > NULL, user, "admin", NULL); >- if(ret) >+ if (ret) { >+ krb5_free_principal(context, client); > return ret; >+ } > } > } > >@@ -509,9 +512,9 @@ kadm_connect(kadm5_client_context *ctx) > hints.ai_socktype = SOCK_STREAM; > hints.ai_protocol = IPPROTO_TCP; > >- snprintf(portstr, sizeof(portstr), "%u", ntohs(ctx->kadmind_port)); >+ snprintf(portstr, sizeof(portstr), "%u", ntohs(kadmin_port)); > >- hostname = ctx->admin_server; >+ hostname = admin_server; > slash = strchr(hostname, '/'); > if (slash != NULL) > hostname = slash + 1; >@@ -530,6 +533,7 @@ kadm_connect(kadm5_client_context *ctx) > if (connect(s, a->ai_addr, a->ai_addrlen) < 0) { > krb5_warn(context, errno, "connect(%s)", hostname); > rk_closesocket(s); >+ s = rk_INVALID_SOCKET; > continue; > } > break; >@@ -640,7 +644,7 @@ kadm5_c_init_with_context(krb5_context context, > void **server_handle) > { > kadm5_ret_t ret; >- kadm5_client_context *ctx; >+ kadm5_client_context *ctx = NULL; > krb5_ccache cc; > > ret = _kadm5_c_init_context(&ctx, realm_params, context); >diff --git a/third_party/heimdal/lib/kadm5/init_s.c b/third_party/heimdal/lib/kadm5/init_s.c >index 926c23510e9e..1b1d7f2ff58c 100644 >--- a/third_party/heimdal/lib/kadm5/init_s.c >+++ b/third_party/heimdal/lib/kadm5/init_s.c >@@ -45,14 +45,16 @@ kadm5_s_init_with_context(krb5_context context, > void **server_handle) > { > kadm5_ret_t ret; >- kadm5_server_context *ctx; >+ kadm5_server_context *ctx = NULL; > char *dbname; > char *stash_file; > > *server_handle = NULL; > ret = _kadm5_s_init_context(&ctx, realm_params, context); >- if (ret) >+ if (ret) { >+ kadm5_s_destroy(ctx); > return ret; >+ } > > if (realm_params->mask & KADM5_CONFIG_DBNAME) > dbname = realm_params->dbname; >diff --git a/third_party/heimdal/lib/kadm5/iprop-log.c b/third_party/heimdal/lib/kadm5/iprop-log.c >index 9c18f832e132..a2ad51e7d081 100644 >--- a/third_party/heimdal/lib/kadm5/iprop-log.c >+++ b/third_party/heimdal/lib/kadm5/iprop-log.c >@@ -137,21 +137,29 @@ print_entry(kadm5_server_context *server_context, > entry_kind, op_names[op], ver, t, len); > switch(op) { > case kadm_delete: >- krb5_ret_principal(sp, &source); >- krb5_unparse_name(scontext, source, &name1); >+ ret = krb5_ret_principal(sp, &source); >+ if (ret == 0) >+ ret = krb5_unparse_name(scontext, source, &name1); >+ if (ret) >+ krb5_err(scontext, 1, ret, "Failed to read a delete record"); > printf(" %s\n", name1); > free(name1); > krb5_free_principal(scontext, source); > break; > case kadm_rename: > ret = krb5_data_alloc(&data, len); >- if (ret) >- krb5_err (scontext, 1, ret, "kadm_rename: data alloc: %d", len); >- krb5_ret_principal(sp, &source); >- krb5_storage_read(sp, data.data, data.length); >- hdb_value2entry(scontext, &data, &ent); >- krb5_unparse_name(scontext, source, &name1); >- krb5_unparse_name(scontext, ent.principal, &name2); >+ if (ret == 0) >+ ret = krb5_ret_principal(sp, &source); >+ if (ret == 0 && krb5_storage_read(sp, data.data, data.length) == -1) >+ ret = errno; >+ if (ret == 0) >+ ret = hdb_value2entry(scontext, &data, &ent); >+ if (ret == 0) >+ ret = krb5_unparse_name(scontext, source, &name1); >+ if (ret == 0) >+ ret = krb5_unparse_name(scontext, ent.principal, &name2); >+ if (ret) >+ krb5_err(scontext, 1, ret, "Failed to read a rename record"); > printf(" %s -> %s\n", name1, name2); > free(name1); > free(name2); >@@ -160,26 +168,30 @@ print_entry(kadm5_server_context *server_context, > break; > case kadm_create: > ret = krb5_data_alloc(&data, len); >+ if (ret == 0 && krb5_storage_read(sp, data.data, data.length) == -1) >+ ret = errno; >+ if (ret == 0) >+ ret = hdb_value2entry(scontext, &data, &ent); > if (ret) >- krb5_err (scontext, 1, ret, "kadm_create: data alloc: %d", len); >- krb5_storage_read(sp, data.data, data.length); >- ret = hdb_value2entry(scontext, &data, &ent); >- if(ret) >- abort(); >+ krb5_err(scontext, 1, ret, "Failed to read a create record"); > mask = ~0; > goto foo; > case kadm_modify: > ret = krb5_data_alloc(&data, len); >+ if (ret == 0) >+ ret = krb5_ret_int32(sp, &mask); >+ if (ret == 0 && krb5_storage_read(sp, data.data, data.length) == -1) >+ ret = errno; >+ if (ret == 0) >+ ret = hdb_value2entry(scontext, &data, &ent); > if (ret) >- krb5_err (scontext, 1, ret, "kadm_modify: data alloc: %d", len); >- krb5_ret_int32(sp, &mask); >- krb5_storage_read(sp, data.data, data.length); >- ret = hdb_value2entry(scontext, &data, &ent); >- if(ret) >- abort(); >+ krb5_err(scontext, 1, ret, "Failed to read a modify record"); > foo: > if(ent.principal /* mask & KADM5_PRINCIPAL */) { >- krb5_unparse_name(scontext, ent.principal, &name1); >+ ret = krb5_unparse_name(scontext, ent.principal, &name1); >+ if (ret) >+ krb5_err(scontext, 1, ret, >+ "Failed to process a create or modify record"); > printf(" principal = %s\n", name1); > free(name1); > } >@@ -263,14 +275,19 @@ print_entry(kadm5_server_context *server_context, > case kadm_nop : > if (len == 16) { > uint64_t off; >- krb5_ret_uint64(sp, &off); >+ ret = krb5_ret_uint64(sp, &off); >+ if (ret) >+ krb5_err(scontext, 1, ret, "Failed to read a no-op record"); > printf("uberblock offset %llu ", (unsigned long long)off); > } else { > printf("nop"); > } > if (len == 16 || len == 8) { >- krb5_ret_int32(sp, &nop_time); >- krb5_ret_uint32(sp, &nop_ver); >+ ret = krb5_ret_int32(sp, &nop_time); >+ if (ret == 0) >+ ret = krb5_ret_uint32(sp, &nop_ver); >+ if (ret) >+ krb5_err(scontext, 1, ret, "Failed to read a no-op record"); > > timestamp = nop_time; > strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); >@@ -279,7 +296,7 @@ print_entry(kadm5_server_context *server_context, > printf("\n"); > break; > default: >- abort(); >+ krb5_errx(scontext, 1, "Unknown record type"); > } > krb5_data_free(&data); > >diff --git a/third_party/heimdal/lib/kadm5/ipropd_common.c b/third_party/heimdal/lib/kadm5/ipropd_common.c >index be0adc1b3802..1decfe3333d9 100644 >--- a/third_party/heimdal/lib/kadm5/ipropd_common.c >+++ b/third_party/heimdal/lib/kadm5/ipropd_common.c >@@ -53,6 +53,7 @@ setup_signal(void) > { > struct sigaction sa; > >+ memset(&sa, 0, sizeof(sa)); > sa.sa_flags = 0; > sa.sa_handler = sigterm; > sigemptyset(&sa.sa_mask); >diff --git a/third_party/heimdal/lib/kadm5/ipropd_master.c b/third_party/heimdal/lib/kadm5/ipropd_master.c >index a27d8f75a38b..b3f7d8105ea7 100644 >--- a/third_party/heimdal/lib/kadm5/ipropd_master.c >+++ b/third_party/heimdal/lib/kadm5/ipropd_master.c >@@ -95,7 +95,7 @@ make_listen_socket (krb5_context context, const char *port_str) > fd = socket (AF_INET, SOCK_STREAM, 0); > if (rk_IS_BAD_SOCKET(fd)) > krb5_err (context, 1, rk_SOCK_ERRNO, "socket AF_INET"); >- setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)); >+ (void) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)); > memset (&addr, 0, sizeof(addr)); > addr.sin_family = AF_INET; > >@@ -392,14 +392,14 @@ error: > } > > static int >-dump_one (krb5_context context, HDB *db, hdb_entry_ex *entry, void *v) >+dump_one (krb5_context context, HDB *db, hdb_entry *entry, void *v) > { > krb5_error_code ret; > krb5_storage *dump = (krb5_storage *)v; > krb5_storage *sp; > krb5_data data; > >- ret = hdb_entry2value (context, &entry->entry, &data); >+ ret = hdb_entry2value (context, entry, &data); > if (ret) > return ret; > ret = krb5_data_realloc (&data, data.length + 4); >@@ -450,6 +450,8 @@ write_dump (krb5_context context, krb5_storage *dump, > */ > > ret = krb5_store_uint32(dump, 0); >+ if (ret) >+ return ret; > > ret = hdb_create (context, &db, database); > if (ret) >@@ -1117,7 +1119,7 @@ send_diffs(kadm5_server_context *server_context, slave *s, int log_fd, > krb5_storage *sp; > uint32_t initial_version; > uint32_t initial_tstamp; >- uint32_t ver; >+ uint32_t ver = 0; > off_t left = 0; > off_t right = 0; > krb5_ssize_t bytes; >@@ -1251,7 +1253,8 @@ fill_input(krb5_context context, slave *s) > return EWOULDBLOCK; > > buf = s->input.header_buf; >- len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; >+ len = ((unsigned long)buf[0] << 24) | (buf[1] << 16) >+ | (buf[2] << 8) | buf[3]; > if (len > SLAVE_MSG_MAX) > return EINVAL; > ret = krb5_data_alloc(&s->input.packet, len); >@@ -1432,11 +1435,13 @@ write_master_down(krb5_context context) > fp = fopen(slave_stats_temp_file, "w"); > if (fp == NULL) > return; >- krb5_format_time(context, t, str, sizeof(str), TRUE); >- fprintf(fp, "master down at %s\n", str); >+ if (krb5_format_time(context, t, str, sizeof(str), TRUE) == 0) >+ fprintf(fp, "master down at %s\n", str); >+ else >+ fprintf(fp, "master down\n"); > > if (fclose(fp) != EOF) >- rk_rename(slave_stats_temp_file, slave_stats_file); >+ (void) rk_rename(slave_stats_temp_file, slave_stats_file); > } > > static void >@@ -1452,7 +1457,8 @@ write_stats(krb5_context context, slave *slaves, uint32_t current_version) > if (fp == NULL) > return; > >- krb5_format_time(context, t, str, sizeof(str), TRUE); >+ if (krb5_format_time(context, t, str, sizeof(str), TRUE)) >+ snprintf(str, sizeof(str), "<unknown-time>"); > fprintf(fp, "Status for slaves, last updated: %s\n\n", str); > > fprintf(fp, "Master version: %lu\n\n", (unsigned long)current_version); >@@ -1494,7 +1500,10 @@ write_stats(krb5_context context, slave *slaves, uint32_t current_version) > rtbl_add_column_entry(tbl, SLAVE_STATUS, "Up"); > > ret = krb5_format_time(context, slaves->seen, str, sizeof(str), TRUE); >- rtbl_add_column_entry(tbl, SLAVE_SEEN, str); >+ if (ret) >+ rtbl_add_column_entry(tbl, SLAVE_SEEN, "<error-formatting-time>"); >+ else >+ rtbl_add_column_entry(tbl, SLAVE_SEEN, str); > > slaves = slaves->next; > } >@@ -1503,7 +1512,7 @@ write_stats(krb5_context context, slave *slaves, uint32_t current_version) > rtbl_destroy(tbl); > > if (fclose(fp) != EOF) >- rk_rename(slave_stats_temp_file, slave_stats_file); >+ (void) rk_rename(slave_stats_temp_file, slave_stats_file); > } > > >diff --git a/third_party/heimdal/lib/kadm5/ipropd_slave.c b/third_party/heimdal/lib/kadm5/ipropd_slave.c >index cd9a6f57a3b9..2b1be00ea606 100644 >--- a/third_party/heimdal/lib/kadm5/ipropd_slave.c >+++ b/third_party/heimdal/lib/kadm5/ipropd_slave.c >@@ -184,6 +184,8 @@ ihave(krb5_context context, krb5_auth_context auth_context, > krb5_data data; > > sp = krb5_storage_from_mem(buf, 8); >+ if (sp == NULL) >+ krb5_err(context, IPROPD_RESTART_SLOW, ENOMEM, "Out of memory"); > ret = krb5_store_uint32(sp, I_HAVE); > if (ret == 0) > ret = krb5_store_uint32(sp, version); >@@ -571,7 +573,7 @@ receive_everything(krb5_context context, int fd, > krb5_ret_uint32(sp, &opcode); > if (opcode == ONE_PRINC) { > krb5_data fake_data; >- hdb_entry_ex entry; >+ hdb_entry entry; > > krb5_storage_free(sp); > >@@ -580,7 +582,7 @@ receive_everything(krb5_context context, int fd, > > memset(&entry, 0, sizeof(entry)); > >- ret = hdb_value2entry(context, &fake_data, &entry.entry); >+ ret = hdb_value2entry(context, &fake_data, &entry); > if (ret) > krb5_err(context, IPROPD_RESTART, ret, "hdb_value2entry"); > ret = mydb->hdb_store(server_context->context, >@@ -589,7 +591,7 @@ receive_everything(krb5_context context, int fd, > if (ret) > krb5_err(context, IPROPD_RESTART_SLOW, ret, "hdb_store"); > >- hdb_free_entry(context, &entry); >+ hdb_free_entry(context, mydb, &entry); > krb5_data_free(&data); > } else if (opcode == NOW_YOU_HAVE) > ; >diff --git a/third_party/heimdal/lib/kadm5/log.c b/third_party/heimdal/lib/kadm5/log.c >index 376cecd9e40b..4f66426c4ca6 100644 >--- a/third_party/heimdal/lib/kadm5/log.c >+++ b/third_party/heimdal/lib/kadm5/log.c >@@ -974,14 +974,12 @@ kadm5_log_create(kadm5_server_context *context, hdb_entry *entry) > krb5_ssize_t bytes; > kadm5_ret_t ret; > krb5_data value; >- hdb_entry_ex ent, existing; >+ hdb_entry ent, existing; > kadm5_log_context *log_context = &context->log_context; > > memset(&existing, 0, sizeof(existing)); > memset(&ent, 0, sizeof(ent)); >- ent.ctx = 0; >- ent.free_entry = 0; >- ent.entry = *entry; >+ ent = *entry; > > /* > * Do not allow creation of concrete entries within namespaces unless >@@ -991,14 +989,14 @@ kadm5_log_create(kadm5_server_context *context, hdb_entry *entry) > 0, 0, 0, &existing); > if (ret != 0 && ret != HDB_ERR_NOENTRY) > return ret; >- if (ret == 0 && !ent.entry.flags.materialize && >- (existing.entry.flags.virtual || existing.entry.flags.virtual_keys)) { >- hdb_free_entry(context->context, &existing); >+ if (ret == 0 && !ent.flags.materialize && >+ (existing.flags.virtual || existing.flags.virtual_keys)) { >+ hdb_free_entry(context->context, context->db, &existing); > return HDB_ERR_EXISTS; > } > if (ret == 0) >- hdb_free_entry(context->context, &existing); >- ent.entry.flags.materialize = 0; /* Clear in stored entry */ >+ hdb_free_entry(context->context, context->db, &existing); >+ ent.flags.materialize = 0; /* Clear in stored entry */ > > /* > * If we're not logging then we can't recover-to-perform, so just >@@ -1057,7 +1055,7 @@ kadm5_log_replay_create(kadm5_server_context *context, > { > krb5_error_code ret; > krb5_data data; >- hdb_entry_ex ent; >+ hdb_entry ent; > > memset(&ent, 0, sizeof(ent)); > >@@ -1067,7 +1065,7 @@ kadm5_log_replay_create(kadm5_server_context *context, > return ret; > } > krb5_storage_read(sp, data.data, len); >- ret = hdb_value2entry(context->context, &data, &ent.entry); >+ ret = hdb_value2entry(context->context, &data, &ent); > krb5_data_free(&data); > if (ret) { > krb5_set_error_message(context->context, ret, >@@ -1076,7 +1074,7 @@ kadm5_log_replay_create(kadm5_server_context *context, > return ret; > } > ret = context->db->hdb_store(context->context, context->db, 0, &ent); >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > return ret; > } > >@@ -1198,13 +1196,11 @@ kadm5_log_rename(kadm5_server_context *context, > off_t end_off = 0; /* Ditto; this allows de-indentation by two levels */ > off_t off; > krb5_data value; >- hdb_entry_ex ent; >+ hdb_entry ent; > kadm5_log_context *log_context = &context->log_context; > > memset(&ent, 0, sizeof(ent)); >- ent.ctx = 0; >- ent.free_entry = 0; >- ent.entry = *entry; >+ ent = *entry; > > if (strcmp(log_context->log_file, "/dev/null") == 0) { > ret = context->db->hdb_store(context->context, context->db, 0, &ent); >@@ -1310,7 +1306,7 @@ kadm5_log_replay_rename(kadm5_server_context *context, > { > krb5_error_code ret; > krb5_principal source; >- hdb_entry_ex target_ent; >+ hdb_entry target_ent; > krb5_data value; > off_t off; > size_t princ_len, data_len; >@@ -1332,7 +1328,7 @@ kadm5_log_replay_rename(kadm5_server_context *context, > return ret; > } > krb5_storage_read(sp, value.data, data_len); >- ret = hdb_value2entry(context->context, &value, &target_ent.entry); >+ ret = hdb_value2entry(context->context, &value, &target_ent); > krb5_data_free(&value); > if (ret) { > krb5_free_principal(context->context, source); >@@ -1340,7 +1336,7 @@ kadm5_log_replay_rename(kadm5_server_context *context, > } > ret = context->db->hdb_store(context->context, context->db, > 0, &target_ent); >- hdb_free_entry(context->context, &target_ent); >+ hdb_free_entry(context->context, context->db, &target_ent); > if (ret) { > krb5_free_principal(context->context, source); > return ret; >@@ -1364,13 +1360,11 @@ kadm5_log_modify(kadm5_server_context *context, > kadm5_ret_t ret; > krb5_data value; > uint32_t len; >- hdb_entry_ex ent; >+ hdb_entry ent; > kadm5_log_context *log_context = &context->log_context; > > memset(&ent, 0, sizeof(ent)); >- ent.ctx = 0; >- ent.free_entry = 0; >- ent.entry = *entry; >+ ent = *entry; > > if (strcmp(log_context->log_file, "/dev/null") == 0) > return context->db->hdb_store(context->context, context->db, >@@ -1434,7 +1428,7 @@ kadm5_log_replay_modify(kadm5_server_context *context, > krb5_error_code ret; > uint32_t mask; > krb5_data value; >- hdb_entry_ex ent, log_ent; >+ hdb_entry ent, log_ent; > > memset(&log_ent, 0, sizeof(log_ent)); > >@@ -1452,7 +1446,7 @@ kadm5_log_replay_modify(kadm5_server_context *context, > ret = errno ? errno : EIO; > return ret; > } >- ret = hdb_value2entry (context->context, &value, &log_ent.entry); >+ ret = hdb_value2entry (context->context, &value, &log_ent); > krb5_data_free(&value); > if (ret) > return ret; >@@ -1460,37 +1454,37 @@ kadm5_log_replay_modify(kadm5_server_context *context, > memset(&ent, 0, sizeof(ent)); > /* NOTE: We do not use hdb_fetch_kvno() here */ > ret = context->db->hdb_fetch_kvno(context->context, context->db, >- log_ent.entry.principal, >+ log_ent.principal, > HDB_F_DECRYPT|HDB_F_ALL_KVNOS| > HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent); > if (ret) > goto out; > if (mask & KADM5_PRINC_EXPIRE_TIME) { >- if (log_ent.entry.valid_end == NULL) { >- ent.entry.valid_end = NULL; >+ if (log_ent.valid_end == NULL) { >+ ent.valid_end = NULL; > } else { >- if (ent.entry.valid_end == NULL) { >- ent.entry.valid_end = malloc(sizeof(*ent.entry.valid_end)); >- if (ent.entry.valid_end == NULL) { >+ if (ent.valid_end == NULL) { >+ ent.valid_end = malloc(sizeof(*ent.valid_end)); >+ if (ent.valid_end == NULL) { > ret = krb5_enomem(context->context); > goto out; > } > } >- *ent.entry.valid_end = *log_ent.entry.valid_end; >+ *ent.valid_end = *log_ent.valid_end; > } > } > if (mask & KADM5_PW_EXPIRATION) { >- if (log_ent.entry.pw_end == NULL) { >- ent.entry.pw_end = NULL; >+ if (log_ent.pw_end == NULL) { >+ ent.pw_end = NULL; > } else { >- if (ent.entry.pw_end == NULL) { >- ent.entry.pw_end = malloc(sizeof(*ent.entry.pw_end)); >- if (ent.entry.pw_end == NULL) { >+ if (ent.pw_end == NULL) { >+ ent.pw_end = malloc(sizeof(*ent.pw_end)); >+ if (ent.pw_end == NULL) { > ret = krb5_enomem(context->context); > goto out; > } > } >- *ent.entry.pw_end = *log_ent.entry.pw_end; >+ *ent.pw_end = *log_ent.pw_end; > } > } > if (mask & KADM5_LAST_PWD_CHANGE) { >@@ -1498,39 +1492,39 @@ kadm5_log_replay_modify(kadm5_server_context *context, > "Unimplemented mask KADM5_LAST_PWD_CHANGE"); > } > if (mask & KADM5_ATTRIBUTES) { >- ent.entry.flags = log_ent.entry.flags; >+ ent.flags = log_ent.flags; > } > if (mask & KADM5_MAX_LIFE) { >- if (log_ent.entry.max_life == NULL) { >- ent.entry.max_life = NULL; >+ if (log_ent.max_life == NULL) { >+ ent.max_life = NULL; > } else { >- if (ent.entry.max_life == NULL) { >- ent.entry.max_life = malloc (sizeof(*ent.entry.max_life)); >- if (ent.entry.max_life == NULL) { >+ if (ent.max_life == NULL) { >+ ent.max_life = malloc (sizeof(*ent.max_life)); >+ if (ent.max_life == NULL) { > ret = krb5_enomem(context->context); > goto out; > } > } >- *ent.entry.max_life = *log_ent.entry.max_life; >+ *ent.max_life = *log_ent.max_life; > } > } > if ((mask & KADM5_MOD_TIME) && (mask & KADM5_MOD_NAME)) { >- if (ent.entry.modified_by == NULL) { >- ent.entry.modified_by = malloc(sizeof(*ent.entry.modified_by)); >- if (ent.entry.modified_by == NULL) { >+ if (ent.modified_by == NULL) { >+ ent.modified_by = malloc(sizeof(*ent.modified_by)); >+ if (ent.modified_by == NULL) { > ret = krb5_enomem(context->context); > goto out; > } > } else >- free_Event(ent.entry.modified_by); >- ret = copy_Event(log_ent.entry.modified_by, ent.entry.modified_by); >+ free_Event(ent.modified_by); >+ ret = copy_Event(log_ent.modified_by, ent.modified_by); > if (ret) { > ret = krb5_enomem(context->context); > goto out; > } > } > if (mask & KADM5_KVNO) { >- ent.entry.kvno = log_ent.entry.kvno; >+ ent.kvno = log_ent.kvno; > } > if (mask & KADM5_MKVNO) { > krb5_warnx(context->context, "Unimplemented mask KADM5_KVNO"); >@@ -1543,17 +1537,17 @@ kadm5_log_replay_modify(kadm5_server_context *context, > krb5_warnx(context->context, "Unimplemented mask KADM5_POLICY_CLR"); > } > if (mask & KADM5_MAX_RLIFE) { >- if (log_ent.entry.max_renew == NULL) { >- ent.entry.max_renew = NULL; >+ if (log_ent.max_renew == NULL) { >+ ent.max_renew = NULL; > } else { >- if (ent.entry.max_renew == NULL) { >- ent.entry.max_renew = malloc (sizeof(*ent.entry.max_renew)); >- if (ent.entry.max_renew == NULL) { >+ if (ent.max_renew == NULL) { >+ ent.max_renew = malloc (sizeof(*ent.max_renew)); >+ if (ent.max_renew == NULL) { > ret = krb5_enomem(context->context); > goto out; > } > } >- *ent.entry.max_renew = *log_ent.entry.max_renew; >+ *ent.max_renew = *log_ent.max_renew; > } > } > if (mask & KADM5_LAST_SUCCESS) { >@@ -1579,70 +1573,70 @@ kadm5_log_replay_modify(kadm5_server_context *context, > */ > mask |= KADM5_TL_DATA; > >- for (i = 0; i < ent.entry.keys.len; ++i) >- free_Key(&ent.entry.keys.val[i]); >- free (ent.entry.keys.val); >+ for (i = 0; i < ent.keys.len; ++i) >+ free_Key(&ent.keys.val[i]); >+ free (ent.keys.val); > >- num = log_ent.entry.keys.len; >+ num = log_ent.keys.len; > >- ent.entry.keys.len = num; >- ent.entry.keys.val = malloc(len * sizeof(*ent.entry.keys.val)); >- if (ent.entry.keys.val == NULL) { >+ ent.keys.len = num; >+ ent.keys.val = malloc(len * sizeof(*ent.keys.val)); >+ if (ent.keys.val == NULL) { > krb5_enomem(context->context); > goto out; > } >- for (i = 0; i < ent.entry.keys.len; ++i) { >- ret = copy_Key(&log_ent.entry.keys.val[i], >- &ent.entry.keys.val[i]); >+ for (i = 0; i < ent.keys.len; ++i) { >+ ret = copy_Key(&log_ent.keys.val[i], >+ &ent.keys.val[i]); > if (ret) { > krb5_set_error_message(context->context, ret, "out of memory"); > goto out; > } > } > } >- if ((mask & KADM5_TL_DATA) && log_ent.entry.etypes) { >- if (ent.entry.etypes) >- free_HDB_EncTypeList(ent.entry.etypes); >- free(ent.entry.etypes); >- ent.entry.etypes = calloc(1, sizeof(*ent.entry.etypes)); >- if (ent.entry.etypes == NULL) >+ if ((mask & KADM5_TL_DATA) && log_ent.etypes) { >+ if (ent.etypes) >+ free_HDB_EncTypeList(ent.etypes); >+ free(ent.etypes); >+ ent.etypes = calloc(1, sizeof(*ent.etypes)); >+ if (ent.etypes == NULL) > ret = ENOMEM; > if (ret == 0) >- ret = copy_HDB_EncTypeList(log_ent.entry.etypes, ent.entry.etypes); >+ ret = copy_HDB_EncTypeList(log_ent.etypes, ent.etypes); > if (ret) { > ret = krb5_enomem(context->context); >- free(ent.entry.etypes); >- ent.entry.etypes = NULL; >+ free(ent.etypes); >+ ent.etypes = NULL; > goto out; > } > } > >- if ((mask & KADM5_TL_DATA) && log_ent.entry.extensions) { >- if (ent.entry.extensions) { >- free_HDB_extensions(ent.entry.extensions); >- free(ent.entry.extensions); >- ent.entry.extensions = NULL; >+ if ((mask & KADM5_TL_DATA) && log_ent.extensions) { >+ if (ent.extensions) { >+ free_HDB_extensions(ent.extensions); >+ free(ent.extensions); >+ ent.extensions = NULL; > } > >- ent.entry.extensions = calloc(1, sizeof(*ent.entry.extensions)); >- if (ent.entry.extensions == NULL) >+ ent.extensions = calloc(1, sizeof(*ent.extensions)); >+ if (ent.extensions == NULL) > ret = ENOMEM; > > if (ret == 0) >- ret = copy_HDB_extensions(log_ent.entry.extensions, >- ent.entry.extensions); >+ ret = copy_HDB_extensions(log_ent.extensions, >+ ent.extensions); > if (ret) { > ret = krb5_enomem(context->context); >- free(ent.entry.extensions); >- ent.entry.extensions = NULL; >+ free(ent.extensions); >+ ent.extensions = NULL; > goto out; > } > } > ret = context->db->hdb_store(context->context, context->db, > HDB_F_REPLACE, &ent); > out: >- hdb_free_entry(context->context, &ent); >- hdb_free_entry(context->context, &log_ent); >+ hdb_free_entry(context->context, context->db, &ent); >+ hdb_free_entry(context->context, context->db, &log_ent); > return ret; > } > >diff --git a/third_party/heimdal/lib/kadm5/marshall.c b/third_party/heimdal/lib/kadm5/marshall.c >index c66bcd75ae67..9d24233ba6ea 100644 >--- a/third_party/heimdal/lib/kadm5/marshall.c >+++ b/third_party/heimdal/lib/kadm5/marshall.c >@@ -33,7 +33,7 @@ > > #include "kadm5_locl.h" > >-RCSID("$Id$"); >+#define CHECK(e) do { if ((ret = e)) goto out; } while (0) > > int > kadm5_some_keys_are_bogus(size_t n_keys, krb5_key_data *keys) >@@ -72,29 +72,34 @@ kadm5_ret_t > kadm5_store_key_data(krb5_storage *sp, > krb5_key_data *key) > { >+ kadm5_ret_t ret; > krb5_data c; >- krb5_store_int32(sp, key->key_data_ver); >- krb5_store_int32(sp, key->key_data_kvno); >- krb5_store_int32(sp, key->key_data_type[0]); >+ >+ CHECK(krb5_store_int32(sp, key->key_data_ver)); >+ CHECK(krb5_store_int32(sp, key->key_data_kvno)); >+ CHECK(krb5_store_int32(sp, key->key_data_type[0])); > c.length = key->key_data_length[0]; > c.data = key->key_data_contents[0]; >- krb5_store_data(sp, c); >- krb5_store_int32(sp, key->key_data_type[1]); >+ CHECK(krb5_store_data(sp, c)); >+ CHECK(krb5_store_int32(sp, key->key_data_type[1])); > c.length = key->key_data_length[1]; > c.data = key->key_data_contents[1]; >- krb5_store_data(sp, c); >- return 0; >+ CHECK(krb5_store_data(sp, c)); >+ >+out: >+ return ret; > } > > kadm5_ret_t > kadm5_store_fake_key_data(krb5_storage *sp, > krb5_key_data *key) > { >+ kadm5_ret_t ret; > krb5_data c; > >- krb5_store_int32(sp, key->key_data_ver); >- krb5_store_int32(sp, key->key_data_kvno); >- krb5_store_int32(sp, key->key_data_type[0]); >+ CHECK(krb5_store_int32(sp, key->key_data_ver)); >+ CHECK(krb5_store_int32(sp, key->key_data_kvno)); >+ CHECK(krb5_store_int32(sp, key->key_data_type[0])); > > /* > * This is the key contents. We want it to be obvious to the client >@@ -106,63 +111,88 @@ kadm5_store_fake_key_data(krb5_storage *sp, > */ > c.length = sizeof (KADM5_BOGUS_KEY_DATA) - 1; > c.data = KADM5_BOGUS_KEY_DATA; >- krb5_store_data(sp, c); >+ CHECK(krb5_store_data(sp, c)); > > /* This is the salt -- no need to send garbage */ >- krb5_store_int32(sp, key->key_data_type[1]); >+ CHECK(krb5_store_int32(sp, key->key_data_type[1])); > c.length = key->key_data_length[1]; > c.data = key->key_data_contents[1]; >- krb5_store_data(sp, c); >- return 0; >+ CHECK(krb5_store_data(sp, c)); >+ >+out: >+ return ret; > } > > kadm5_ret_t > kadm5_ret_key_data(krb5_storage *sp, > krb5_key_data *key) > { >+ kadm5_ret_t ret; > krb5_data c; > int32_t tmp; >- krb5_ret_int32(sp, &tmp); >- key->key_data_ver = tmp; >- krb5_ret_int32(sp, &tmp); >- key->key_data_kvno = tmp; >- krb5_ret_int32(sp, &tmp); >- key->key_data_type[0] = tmp; >- krb5_ret_data(sp, &c); >- key->key_data_length[0] = c.length; >- key->key_data_contents[0] = c.data; >- krb5_ret_int32(sp, &tmp); >- key->key_data_type[1] = tmp; >- krb5_ret_data(sp, &c); >- key->key_data_length[1] = c.length; >- key->key_data_contents[1] = c.data; >- return 0; >+ >+ ret = krb5_ret_int32(sp, &tmp); >+ if (ret == 0) { >+ key->key_data_ver = tmp; >+ ret = krb5_ret_int32(sp, &tmp); >+ } >+ if (ret == 0) { >+ key->key_data_kvno = tmp; >+ ret = krb5_ret_int32(sp, &tmp); >+ } >+ if (ret == 0) { >+ key->key_data_type[0] = tmp; >+ ret = krb5_ret_data(sp, &c); >+ } >+ if (ret == 0) { >+ key->key_data_length[0] = c.length; >+ key->key_data_contents[0] = c.data; >+ ret = krb5_ret_int32(sp, &tmp); >+ } >+ if (ret == 0) { >+ key->key_data_type[1] = tmp; >+ ret = krb5_ret_data(sp, &c); >+ } >+ if (ret == 0) { >+ key->key_data_length[1] = c.length; >+ key->key_data_contents[1] = c.data; >+ return 0; >+ } >+ return KADM5_FAILURE; > } > > kadm5_ret_t > kadm5_store_tl_data(krb5_storage *sp, > krb5_tl_data *tl) > { >+ kadm5_ret_t ret; > krb5_data c; >- krb5_store_int32(sp, tl->tl_data_type); >+ >+ CHECK(krb5_store_int32(sp, tl->tl_data_type)); > c.length = tl->tl_data_length; > c.data = tl->tl_data_contents; >- krb5_store_data(sp, c); >- return 0; >+ CHECK(krb5_store_data(sp, c)); >+ >+out: >+ return ret; > } > > kadm5_ret_t > kadm5_ret_tl_data(krb5_storage *sp, > krb5_tl_data *tl) > { >+ kadm5_ret_t ret; > krb5_data c; > int32_t tmp; >- krb5_ret_int32(sp, &tmp); >+ >+ CHECK(krb5_ret_int32(sp, &tmp)); > tl->tl_data_type = tmp; >- krb5_ret_data(sp, &c); >+ CHECK(krb5_ret_data(sp, &c)); > tl->tl_data_length = c.length; > tl->tl_data_contents = c.data; >- return 0; >+ >+out: >+ return ret; > } > > static kadm5_ret_t >@@ -170,63 +200,66 @@ store_principal_ent(krb5_storage *sp, > kadm5_principal_ent_t princ, > uint32_t mask, int wkeys) > { >+ kadm5_ret_t ret = 0; > int i; > > if (mask & KADM5_PRINCIPAL) >- krb5_store_principal(sp, princ->principal); >+ CHECK(krb5_store_principal(sp, princ->principal)); > if (mask & KADM5_PRINC_EXPIRE_TIME) >- krb5_store_int32(sp, princ->princ_expire_time); >+ CHECK(krb5_store_int32(sp, princ->princ_expire_time)); > if (mask & KADM5_PW_EXPIRATION) >- krb5_store_int32(sp, princ->pw_expiration); >+ CHECK(krb5_store_int32(sp, princ->pw_expiration)); > if (mask & KADM5_LAST_PWD_CHANGE) >- krb5_store_int32(sp, princ->last_pwd_change); >+ CHECK(krb5_store_int32(sp, princ->last_pwd_change)); > if (mask & KADM5_MAX_LIFE) >- krb5_store_int32(sp, princ->max_life); >+ CHECK(krb5_store_int32(sp, princ->max_life)); > if (mask & KADM5_MOD_NAME) { >- krb5_store_int32(sp, princ->mod_name != NULL); >+ CHECK(krb5_store_int32(sp, princ->mod_name != NULL)); > if(princ->mod_name) >- krb5_store_principal(sp, princ->mod_name); >+ CHECK(krb5_store_principal(sp, princ->mod_name)); > } > if (mask & KADM5_MOD_TIME) >- krb5_store_int32(sp, princ->mod_date); >+ CHECK(krb5_store_int32(sp, princ->mod_date)); > if (mask & KADM5_ATTRIBUTES) >- krb5_store_int32(sp, princ->attributes); >+ CHECK(krb5_store_int32(sp, princ->attributes)); > if (mask & KADM5_KVNO) >- krb5_store_int32(sp, princ->kvno); >+ CHECK(krb5_store_int32(sp, princ->kvno)); > if (mask & KADM5_MKVNO) >- krb5_store_int32(sp, princ->mkvno); >+ CHECK(krb5_store_int32(sp, princ->mkvno)); > if (mask & KADM5_POLICY) { >- krb5_store_int32(sp, princ->policy != NULL); >+ CHECK(krb5_store_int32(sp, princ->policy != NULL)); > if(princ->policy) >- krb5_store_string(sp, princ->policy); >+ CHECK(krb5_store_string(sp, princ->policy)); > } > if (mask & KADM5_AUX_ATTRIBUTES) >- krb5_store_int32(sp, princ->aux_attributes); >+ CHECK(krb5_store_int32(sp, princ->aux_attributes)); > if (mask & KADM5_MAX_RLIFE) >- krb5_store_int32(sp, princ->max_renewable_life); >+ CHECK(krb5_store_int32(sp, princ->max_renewable_life)); > if (mask & KADM5_LAST_SUCCESS) >- krb5_store_int32(sp, princ->last_success); >+ CHECK(krb5_store_int32(sp, princ->last_success)); > if (mask & KADM5_LAST_FAILED) >- krb5_store_int32(sp, princ->last_failed); >+ CHECK(krb5_store_int32(sp, princ->last_failed)); > if (mask & KADM5_FAIL_AUTH_COUNT) >- krb5_store_int32(sp, princ->fail_auth_count); >+ CHECK(krb5_store_int32(sp, princ->fail_auth_count)); > if (mask & KADM5_KEY_DATA) { >- krb5_store_int32(sp, princ->n_key_data); >+ CHECK(krb5_store_int32(sp, princ->n_key_data)); > for(i = 0; i < princ->n_key_data; i++) { > if (wkeys) >- kadm5_store_key_data(sp, &princ->key_data[i]); >- else >- kadm5_store_fake_key_data(sp, &princ->key_data[i]); >+ CHECK(kadm5_store_key_data(sp, &princ->key_data[i])); >+ else >+ CHECK(kadm5_store_fake_key_data(sp, &princ->key_data[i])); > } > } > if (mask & KADM5_TL_DATA) { > krb5_tl_data *tp; > >- krb5_store_int32(sp, princ->n_tl_data); >- for(tp = princ->tl_data; tp; tp = tp->tl_data_next) >- kadm5_store_tl_data(sp, tp); >+ CHECK(krb5_store_int32(sp, princ->n_tl_data)); >+ for (tp = princ->tl_data; tp; tp = tp->tl_data_next) >+ CHECK(kadm5_store_tl_data(sp, tp)); > } >- return 0; >+ >+out: >+ return ret; > } > > >@@ -249,8 +282,12 @@ kadm5_store_principal_ent_mask(krb5_storage *sp, > kadm5_principal_ent_t princ, > uint32_t mask) > { >- krb5_store_int32(sp, mask); >- return store_principal_ent (sp, princ, mask, 1); >+ kadm5_ret_t ret; >+ >+ ret = krb5_store_int32(sp, mask); >+ if (ret == 0) >+ ret = store_principal_ent(sp, princ, mask, 1); >+ return ret; > } > > static kadm5_ret_t >@@ -258,101 +295,112 @@ ret_principal_ent(krb5_storage *sp, > kadm5_principal_ent_t princ, > uint32_t mask) > { >+ kadm5_ret_t ret = 0; > int i; > int32_t tmp; > > if (mask & KADM5_PRINCIPAL) >- krb5_ret_principal(sp, &princ->principal); >+ CHECK(krb5_ret_principal(sp, &princ->principal)); > > if (mask & KADM5_PRINC_EXPIRE_TIME) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->princ_expire_time = tmp; > } > if (mask & KADM5_PW_EXPIRATION) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->pw_expiration = tmp; > } > if (mask & KADM5_LAST_PWD_CHANGE) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->last_pwd_change = tmp; > } > if (mask & KADM5_MAX_LIFE) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->max_life = tmp; > } > if (mask & KADM5_MOD_NAME) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > if(tmp) >- krb5_ret_principal(sp, &princ->mod_name); >+ CHECK(krb5_ret_principal(sp, &princ->mod_name)); > else > princ->mod_name = NULL; > } > if (mask & KADM5_MOD_TIME) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->mod_date = tmp; > } > if (mask & KADM5_ATTRIBUTES) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->attributes = tmp; > } > if (mask & KADM5_KVNO) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->kvno = tmp; > } > if (mask & KADM5_MKVNO) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->mkvno = tmp; > } > if (mask & KADM5_POLICY) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > if(tmp) >- krb5_ret_string(sp, &princ->policy); >+ CHECK(krb5_ret_string(sp, &princ->policy)); > else > princ->policy = NULL; > } > if (mask & KADM5_AUX_ATTRIBUTES) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->aux_attributes = tmp; > } > if (mask & KADM5_MAX_RLIFE) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->max_renewable_life = tmp; > } > if (mask & KADM5_LAST_SUCCESS) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->last_success = tmp; > } > if (mask & KADM5_LAST_FAILED) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->last_failed = tmp; > } > if (mask & KADM5_FAIL_AUTH_COUNT) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->fail_auth_count = tmp; > } > if (mask & KADM5_KEY_DATA) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->n_key_data = tmp; > princ->key_data = malloc(princ->n_key_data * sizeof(*princ->key_data)); > if (princ->key_data == NULL && princ->n_key_data != 0) > return ENOMEM; > for(i = 0; i < princ->n_key_data; i++) >- kadm5_ret_key_data(sp, &princ->key_data[i]); >+ ret = kadm5_ret_key_data(sp, &princ->key_data[i]); > } > if (mask & KADM5_TL_DATA) { >- krb5_ret_int32(sp, &tmp); >+ CHECK(krb5_ret_int32(sp, &tmp)); > princ->n_tl_data = tmp; > princ->tl_data = NULL; > for(i = 0; i < princ->n_tl_data; i++){ > krb5_tl_data *tp = malloc(sizeof(*tp)); >- if (tp == NULL) >- return ENOMEM; >- kadm5_ret_tl_data(sp, tp); >- tp->tl_data_next = princ->tl_data; >- princ->tl_data = tp; >+ if (tp == NULL) { >+ ret = ENOMEM; >+ goto out; >+ } >+ ret = kadm5_ret_tl_data(sp, tp); >+ if (ret == 0) { >+ tp->tl_data_next = princ->tl_data; >+ princ->tl_data = tp; >+ } else { >+ free(tp); >+ goto out; >+ } > } > } >- return 0; >+ >+out: >+ /* Can't free princ here -- we don't have a context */ >+ return ret; > } > > kadm5_ret_t >@@ -367,9 +415,14 @@ kadm5_ret_principal_ent_mask(krb5_storage *sp, > kadm5_principal_ent_t princ, > uint32_t *mask) > { >+ kadm5_ret_t ret; > int32_t tmp; > >- krb5_ret_int32 (sp, &tmp); >+ ret = krb5_ret_int32 (sp, &tmp); >+ if (ret) { >+ *mask = 0; >+ return ret; >+ } > *mask = tmp; > return ret_principal_ent (sp, princ, *mask); > } >@@ -379,18 +432,19 @@ _kadm5_marshal_params(krb5_context context, > kadm5_config_params *params, > krb5_data *out) > { >+ kadm5_ret_t ret; >+ > krb5_storage *sp = krb5_storage_emem(); > if (sp == NULL) > return krb5_enomem(context); > >- krb5_store_int32(sp, params->mask & (KADM5_CONFIG_REALM)); >- >- if(params->mask & KADM5_CONFIG_REALM) >- krb5_store_string(sp, params->realm); >- krb5_storage_to_data(sp, out); >+ ret = krb5_store_int32(sp, params->mask & (KADM5_CONFIG_REALM)); >+ if (ret == 0 && (params->mask & KADM5_CONFIG_REALM)) >+ ret = krb5_store_string(sp, params->realm); >+ if (ret == 0) >+ ret = krb5_storage_to_data(sp, out); > krb5_storage_free(sp); >- >- return 0; >+ return ret; > } > > kadm5_ret_t >@@ -398,7 +452,7 @@ _kadm5_unmarshal_params(krb5_context context, > krb5_data *in, > kadm5_config_params *params) > { >- krb5_error_code ret; >+ kadm5_ret_t ret; > krb5_storage *sp; > int32_t mask; > >diff --git a/third_party/heimdal/lib/kadm5/modify_s.c b/third_party/heimdal/lib/kadm5/modify_s.c >index cb2e1fd1deca..2159caf5517c 100644 >--- a/third_party/heimdal/lib/kadm5/modify_s.c >+++ b/third_party/heimdal/lib/kadm5/modify_s.c >@@ -97,7 +97,7 @@ modify_principal(void *server_handle, > uint32_t forbidden_mask) > { > kadm5_server_context *context = server_handle; >- hdb_entry_ex ent; >+ hdb_entry ent; > kadm5_ret_t ret; > > memset(&ent, 0, sizeof(ent)); >@@ -139,7 +139,7 @@ modify_principal(void *server_handle, > ret = _kadm5_setup_entry(context, &ent, mask, princ, mask, NULL, 0); > if (ret) > goto out3; >- ret = _kadm5_set_modifier(context, &ent.entry); >+ ret = _kadm5_set_modifier(context, &ent); > if (ret) > goto out3; > >@@ -157,7 +157,7 @@ modify_principal(void *server_handle, > goto out3; > } > >- ret = hdb_seal_keys(context->context, context->db, &ent.entry); >+ ret = hdb_seal_keys(context->context, context->db, &ent); > if (ret) > goto out3; > >@@ -174,21 +174,21 @@ modify_principal(void *server_handle, > goto out3; > } > /* This calls free_HDB_extension(), freeing ext.data.u.policy */ >- ret = hdb_replace_extension(context->context, &ent.entry, &ext); >+ ret = hdb_replace_extension(context->context, &ent, &ext); > free(ext.data.u.policy); > if (ret) > goto out3; > } > > /* This logs the change for iprop and writes to the HDB */ >- ret = kadm5_log_modify(context, &ent.entry, >+ ret = kadm5_log_modify(context, &ent, > mask | KADM5_MOD_NAME | KADM5_MOD_TIME); > > (void) modify_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT, > ret, princ, mask); > > out3: >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > out2: > (void) kadm5_log_end(context); > out: >diff --git a/third_party/heimdal/lib/kadm5/prune_s.c b/third_party/heimdal/lib/kadm5/prune_s.c >index e5d77f6cfd74..96133f242a9f 100644 >--- a/third_party/heimdal/lib/kadm5/prune_s.c >+++ b/third_party/heimdal/lib/kadm5/prune_s.c >@@ -95,7 +95,7 @@ kadm5_s_prune_principal(void *server_handle, > int kvno) > { > kadm5_server_context *context = server_handle; >- hdb_entry_ex ent; >+ hdb_entry ent; > kadm5_ret_t ret; > > memset(&ent, 0, sizeof(ent)); >@@ -121,21 +121,21 @@ kadm5_s_prune_principal(void *server_handle, > if (ret) > goto out3; > >- ret = hdb_prune_keys_kvno(context->context, &ent.entry, kvno); >+ ret = hdb_prune_keys_kvno(context->context, &ent, kvno); > if (ret) > goto out3; > >- ret = hdb_seal_keys(context->context, context->db, &ent.entry); >+ ret = hdb_seal_keys(context->context, context->db, &ent); > if (ret) > goto out3; > >- ret = kadm5_log_modify(context, &ent.entry, KADM5_KEY_DATA); >+ ret = kadm5_log_modify(context, &ent, KADM5_KEY_DATA); > > (void) prune_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT, > ret, princ, kvno); > > out3: >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > out2: > (void) kadm5_log_end(context); > out: >diff --git a/third_party/heimdal/lib/kadm5/randkey_c.c b/third_party/heimdal/lib/kadm5/randkey_c.c >index ace0687613c3..cb0ec86ae570 100644 >--- a/third_party/heimdal/lib/kadm5/randkey_c.c >+++ b/third_party/heimdal/lib/kadm5/randkey_c.c >@@ -93,7 +93,7 @@ kadm5_c_randkey_principal(void *server_handle, > for (i = 0; ret == 0 && i < n_ks_tuple; i++) { > ret = krb5_store_int32(sp, ks_tuple[i].ks_enctype); > if (ret == 0) >- krb5_store_int32(sp, ks_tuple[i].ks_salttype); >+ ret = krb5_store_int32(sp, ks_tuple[i].ks_salttype); > } > /* Future extensions go here */ > if (ret) >diff --git a/third_party/heimdal/lib/kadm5/randkey_s.c b/third_party/heimdal/lib/kadm5/randkey_s.c >index 9bb83cd14a14..cb3696720f91 100644 >--- a/third_party/heimdal/lib/kadm5/randkey_s.c >+++ b/third_party/heimdal/lib/kadm5/randkey_s.c >@@ -102,7 +102,7 @@ kadm5_s_randkey_principal(void *server_handle, > int *n_keys) > { > kadm5_server_context *context = server_handle; >- hdb_entry_ex ent; >+ hdb_entry ent; > kadm5_ret_t ret; > size_t i; > >@@ -129,36 +129,36 @@ kadm5_s_randkey_principal(void *server_handle, > goto out3; > > if (keepold) { >- ret = hdb_add_current_keys_to_history(context->context, &ent.entry); >+ ret = hdb_add_current_keys_to_history(context->context, &ent); > if (ret == 0 && keepold == 1) >- ret = hdb_prune_keys_kvno(context->context, &ent.entry, 0); >+ ret = hdb_prune_keys_kvno(context->context, &ent, 0); > if (ret) > goto out3; > } else { > /* Remove all key history */ >- ret = hdb_clear_extension(context->context, &ent.entry, >+ ret = hdb_clear_extension(context->context, &ent, > choice_HDB_extension_data_hist_keys); > if (ret) > goto out3; > } > >- ret = _kadm5_set_keys_randomly(context, &ent.entry, n_ks_tuple, ks_tuple, >+ ret = _kadm5_set_keys_randomly(context, &ent, n_ks_tuple, ks_tuple, > new_keys, n_keys); > if (ret) > goto out3; >- ent.entry.kvno++; >+ ent.kvno++; > >- ent.entry.flags.require_pwchange = 0; >+ ent.flags.require_pwchange = 0; > >- ret = _kadm5_set_modifier(context, &ent.entry); >+ ret = _kadm5_set_modifier(context, &ent); > if(ret) > goto out4; >- ret = _kadm5_bump_pw_expire(context, &ent.entry); >+ ret = _kadm5_bump_pw_expire(context, &ent); > if (ret) > goto out4; > > if (keepold) { >- ret = hdb_seal_keys(context->context, context->db, &ent.entry); >+ ret = hdb_seal_keys(context->context, context->db, &ent); > if (ret) > goto out4; > } else { >@@ -169,11 +169,11 @@ kadm5_s_randkey_principal(void *server_handle, > ext.data.element = choice_HDB_extension_data_hist_keys; > ext.data.u.hist_keys.len = 0; > ext.data.u.hist_keys.val = NULL; >- hdb_replace_extension(context->context, &ent.entry, &ext); >+ hdb_replace_extension(context->context, &ent, &ext); > } > > /* This logs the change for iprop and writes to the HDB */ >- ret = kadm5_log_modify(context, &ent.entry, >+ ret = kadm5_log_modify(context, &ent, > KADM5_ATTRIBUTES | KADM5_PRINCIPAL | > KADM5_MOD_NAME | KADM5_MOD_TIME | > KADM5_KEY_DATA | KADM5_KVNO | >@@ -190,7 +190,7 @@ kadm5_s_randkey_principal(void *server_handle, > *n_keys = 0; > } > out3: >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > out2: > (void) kadm5_log_end(context); > out: >diff --git a/third_party/heimdal/lib/kadm5/rename_s.c b/third_party/heimdal/lib/kadm5/rename_s.c >index 1052042af05a..9143318176b7 100644 >--- a/third_party/heimdal/lib/kadm5/rename_s.c >+++ b/third_party/heimdal/lib/kadm5/rename_s.c >@@ -97,7 +97,7 @@ kadm5_s_rename_principal(void *server_handle, > { > kadm5_server_context *context = server_handle; > kadm5_ret_t ret; >- hdb_entry_ex ent; >+ hdb_entry ent; > krb5_principal oldname; > size_t i; > >@@ -121,14 +121,14 @@ kadm5_s_rename_principal(void *server_handle, > 0, &ent); > if (ret) > goto out2; >- oldname = ent.entry.principal; >+ oldname = ent.principal; > > ret = rename_principal_hook(context, KADM5_HOOK_STAGE_PRECOMMIT, > 0, source, target); > if (ret) > goto out3; > >- ret = _kadm5_set_modifier(context, &ent.entry); >+ ret = _kadm5_set_modifier(context, &ent); > if (ret) > goto out3; > { >@@ -136,17 +136,19 @@ kadm5_s_rename_principal(void *server_handle, > Salt salt; > krb5_salt salt2; > memset(&salt, 0, sizeof(salt)); >- krb5_get_pw_salt(context->context, source, &salt2); >+ ret = krb5_get_pw_salt(context->context, source, &salt2); >+ if (ret) >+ goto out3; > salt.type = hdb_pw_salt; > salt.salt = salt2.saltvalue; >- for(i = 0; i < ent.entry.keys.len; i++){ >- if(ent.entry.keys.val[i].salt == NULL){ >- ent.entry.keys.val[i].salt = >- malloc(sizeof(*ent.entry.keys.val[i].salt)); >- if (ent.entry.keys.val[i].salt == NULL) >+ for(i = 0; i < ent.keys.len; i++){ >+ if(ent.keys.val[i].salt == NULL){ >+ ent.keys.val[i].salt = >+ malloc(sizeof(*ent.keys.val[i].salt)); >+ if (ent.keys.val[i].salt == NULL) > ret = krb5_enomem(context->context); > else >- ret = copy_Salt(&salt, ent.entry.keys.val[i].salt); >+ ret = copy_Salt(&salt, ent.keys.val[i].salt); > if (ret) > break; > } >@@ -157,20 +159,20 @@ kadm5_s_rename_principal(void *server_handle, > goto out3; > > /* Borrow target */ >- ent.entry.principal = target; >- ret = hdb_seal_keys(context->context, context->db, &ent.entry); >+ ent.principal = target; >+ ret = hdb_seal_keys(context->context, context->db, &ent); > if (ret) > goto out3; > > /* This logs the change for iprop and writes to the HDB */ >- ret = kadm5_log_rename(context, source, &ent.entry); >+ ret = kadm5_log_rename(context, source, &ent); > > (void) rename_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT, > ret, source, target); > > out3: >- ent.entry.principal = oldname; /* Unborrow target */ >- hdb_free_entry(context->context, &ent); >+ ent.principal = oldname; /* Unborrow target */ >+ hdb_free_entry(context->context, context->db, &ent); > > out2: > (void) kadm5_log_end(context); >diff --git a/third_party/heimdal/lib/kadm5/set_keys.c b/third_party/heimdal/lib/kadm5/set_keys.c >index 1f458258592f..c30c5d829347 100644 >--- a/third_party/heimdal/lib/kadm5/set_keys.c >+++ b/third_party/heimdal/lib/kadm5/set_keys.c >@@ -177,6 +177,8 @@ _kadm5_set_keys2(kadm5_server_context *context, > /* A current key; add to current key set */ > setup_Key(&key, &salt, key_data, i); > ret = add_Keys(&keys, &key); >+ if (ret) >+ goto out; > continue; > } > >diff --git a/third_party/heimdal/lib/kadm5/setkey3_s.c b/third_party/heimdal/lib/kadm5/setkey3_s.c >index 2f8eda54c093..584c194dd183 100644 >--- a/third_party/heimdal/lib/kadm5/setkey3_s.c >+++ b/third_party/heimdal/lib/kadm5/setkey3_s.c >@@ -115,7 +115,7 @@ kadm5_s_setkey_principal_3(void *server_handle, > krb5_keyblock *keyblocks, int n_keys) > { > kadm5_server_context *context = server_handle; >- hdb_entry_ex ent; >+ hdb_entry ent; > kadm5_ret_t ret = 0; > size_t i; > >@@ -154,9 +154,9 @@ kadm5_s_setkey_principal_3(void *server_handle, > } > > if (keepold) { >- ret = hdb_add_current_keys_to_history(context->context, &ent.entry); >+ ret = hdb_add_current_keys_to_history(context->context, &ent); > } else >- ret = hdb_clear_extension(context->context, &ent.entry, >+ ret = hdb_clear_extension(context->context, &ent, > choice_HDB_extension_data_hist_keys); > > /* >@@ -167,7 +167,7 @@ kadm5_s_setkey_principal_3(void *server_handle, > * each ks_tuple's enctype matches the corresponding key enctype. > */ > if (ret == 0) { >- free_Keys(&ent.entry.keys); >+ free_Keys(&ent.keys); > for (i = 0; i < n_keys; ++i) { > Key k; > Salt s; >@@ -186,22 +186,22 @@ kadm5_s_setkey_principal_3(void *server_handle, > s.opaque = 0; > k.salt = &s; > } >- if ((ret = add_Keys(&ent.entry.keys, &k)) != 0) >+ if ((ret = add_Keys(&ent.keys, &k)) != 0) > break; > } > } > > if (ret == 0) { >- ent.entry.kvno++; >- ent.entry.flags.require_pwchange = 0; >- hdb_entry_set_pw_change_time(context->context, &ent.entry, 0); >- hdb_entry_clear_password(context->context, &ent.entry); >+ ent.kvno++; >+ ent.flags.require_pwchange = 0; >+ hdb_entry_set_pw_change_time(context->context, &ent, 0); >+ hdb_entry_clear_password(context->context, &ent); > > if ((ret = hdb_seal_keys(context->context, context->db, >- &ent.entry)) == 0 >- && (ret = _kadm5_set_modifier(context, &ent.entry)) == 0 >- && (ret = _kadm5_bump_pw_expire(context, &ent.entry)) == 0) >- ret = kadm5_log_modify(context, &ent.entry, >+ &ent)) == 0 >+ && (ret = _kadm5_set_modifier(context, &ent)) == 0 >+ && (ret = _kadm5_bump_pw_expire(context, &ent)) == 0) >+ ret = kadm5_log_modify(context, &ent, > KADM5_ATTRIBUTES | KADM5_PRINCIPAL | > KADM5_MOD_NAME | KADM5_MOD_TIME | > KADM5_KEY_DATA | KADM5_KVNO | >@@ -212,7 +212,7 @@ kadm5_s_setkey_principal_3(void *server_handle, > princ, keepold, n_ks_tuple, ks_tuple, > n_keys, keyblocks); > >- hdb_free_entry(context->context, &ent); >+ hdb_free_entry(context->context, context->db, &ent); > (void) kadm5_log_end(context); > if (!context->keep_open) > context->db->hdb_close(context->context, context->db); >diff --git a/third_party/heimdal/lib/kafs/Makefile.am b/third_party/heimdal/lib/kafs/Makefile.am >index dd23aef7665a..50d4878ae6cd 100644 >--- a/third_party/heimdal/lib/kafs/Makefile.am >+++ b/third_party/heimdal/lib/kafs/Makefile.am >@@ -2,6 +2,8 @@ > > include $(top_srcdir)/Makefile.am.common > >+WFLAGS += $(WFLAGS_ENUM_CONV) >+ > AM_CPPFLAGS += $(AFS_EXTRA_DEFS) $(ROKEN_RENAME) > > if KRB5 >diff --git a/third_party/heimdal/lib/kafs/afskrb5.c b/third_party/heimdal/lib/kafs/afskrb5.c >index 6033f2958b45..0077016f6242 100644 >--- a/third_party/heimdal/lib/kafs/afskrb5.c >+++ b/third_party/heimdal/lib/kafs/afskrb5.c >@@ -85,8 +85,6 @@ v5_to_kt(krb5_creds *cred, uid_t uid, struct kafs_token *kt, int local524) > return ENOMEM; > kt->ticket_len = cred->ticket.length; > memcpy(kt->ticket, cred->ticket.data, kt->ticket_len); >- >- ret = 0; > } > > >diff --git a/third_party/heimdal/lib/kafs/afssys.c b/third_party/heimdal/lib/kafs/afssys.c >index ae33ff182994..b400626075ce 100644 >--- a/third_party/heimdal/lib/kafs/afssys.c >+++ b/third_party/heimdal/lib/kafs/afssys.c >@@ -106,7 +106,9 @@ int _kafs_debug; /* this should be done in a better way */ > #define SUN_PROC_POINT 8 > > static int afs_entry_point = UNKNOWN_ENTRY_POINT; >+#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) || defined(AFS_PIOCTL) > static int afs_syscalls[2]; >+#endif > static char *afs_ioctlpath; > static unsigned long afs_ioctlnum; > >diff --git a/third_party/heimdal/lib/kafs/rxkad_kdf.c b/third_party/heimdal/lib/kafs/rxkad_kdf.c >index 174fa3a6189a..5af391ed99b5 100644 >--- a/third_party/heimdal/lib/kafs/rxkad_kdf.c >+++ b/third_party/heimdal/lib/kafs/rxkad_kdf.c >@@ -89,12 +89,16 @@ rxkad_derive_des_key(const void *in, size_t insize, char out[8]) > /* stop when 8 bit counter wraps to 0 */ > for (i = 1; i; i++) { > HMAC_CTX_init(&mctx); >- HMAC_Init_ex(&mctx, in, insize, EVP_md5(), NULL); >+ if (HMAC_Init_ex(&mctx, in, insize, EVP_md5(), NULL) == 0) { >+ HMAC_CTX_cleanup(&mctx); >+ return ENOMEM; >+ } > HMAC_Update(&mctx, &i, 1); > HMAC_Update(&mctx, label, sizeof(label)); /* includes label and separator */ > HMAC_Update(&mctx, Lbuf, 4); > mdsize = sizeof(tmp); > HMAC_Final(&mctx, tmp, &mdsize); >+ HMAC_CTX_cleanup(&mctx); > memcpy(ktmp, tmp, 8); > DES_set_odd_parity(&ktmp); > if (!DES_is_weak_key(&ktmp)) { >@@ -205,7 +209,7 @@ _kafs_derive_des_key(krb5_enctype enctype, void *keydata, size_t keylen, > ret = compress_parity_bits(keydata, &keylen); > if (ret) > return ret; >- /* FALLTHROUGH */ >+ fallthrough; > default: > if (enctype < 0) > return KRB5_PROG_ETYPE_NOSUPP; >diff --git a/third_party/heimdal/lib/krb5/Makefile.am b/third_party/heimdal/lib/krb5/Makefile.am >index 99171e727ce8..c1345c28a5ab 100644 >--- a/third_party/heimdal/lib/krb5/Makefile.am >+++ b/third_party/heimdal/lib/krb5/Makefile.am >@@ -2,7 +2,9 @@ > > include $(top_srcdir)/Makefile.am.common > >-AM_CPPFLAGS += -I../com_err -I$(srcdir)/../com_err $(INCLUDE_sqlite3) $(INCLUDE_libintl) $(INCLUDE_openssl_crypto) >+WFLAGS += $(WFLAGS_ENUM_CONV) >+ >+AM_CPPFLAGS += -I../com_err -I$(srcdir)/../com_err -I../base -I$(srcdir)/../base $(INCLUDE_sqlite3) $(INCLUDE_libintl) $(INCLUDE_openssl_crypto) > > bin_PROGRAMS = verify_krb5_conf > >diff --git a/third_party/heimdal/lib/krb5/NTMakefile b/third_party/heimdal/lib/krb5/NTMakefile >index d32025130989..40ca0fb0bccc 100644 >--- a/third_party/heimdal/lib/krb5/NTMakefile >+++ b/third_party/heimdal/lib/krb5/NTMakefile >@@ -31,6 +31,8 @@ > > RELDIR=lib\krb5 > >+intcflags=-I$(SRCDIR) -I$(SRCDIR)\..\com_err -I$(SRCDIR)\..\base >+ > !include ../../windows/NTMakefile.w32 > > libkrb5_OBJS = \ >diff --git a/third_party/heimdal/lib/krb5/acache.c b/third_party/heimdal/lib/krb5/acache.c >index 5bc976263245..63d56c400bf5 100644 >--- a/third_party/heimdal/lib/krb5/acache.c >+++ b/third_party/heimdal/lib/krb5/acache.c >@@ -121,10 +121,9 @@ init_ccapi(krb5_context context) > > if (cc_handle == NULL) { > HEIMDAL_MUTEX_unlock(&acc_mutex); >- if (context) >- krb5_set_error_message(context, KRB5_CC_NOSUPP, >- N_("Failed to load API cache module %s", "file"), >- lib); >+ krb5_set_error_message(context, KRB5_CC_NOSUPP, >+ N_("Failed to load API cache module %s", "file"), >+ lib); > return KRB5_CC_NOSUPP; > } > >@@ -135,10 +134,9 @@ init_ccapi(krb5_context context) > dlsym(cc_handle, "krb5_ipc_client_clear_target"); > HEIMDAL_MUTEX_unlock(&acc_mutex); > if (init_func == NULL) { >- if (context) >- krb5_set_error_message(context, KRB5_CC_NOSUPP, >- N_("Failed to find cc_initialize" >- "in %s: %s", "file, error"), lib, dlerror()); >+ krb5_set_error_message(context, KRB5_CC_NOSUPP, >+ N_("Failed to find cc_initialize" >+ "in %s: %s", "file, error"), lib, dlerror()); > dlclose(cc_handle); > return KRB5_CC_NOSUPP; > } >@@ -146,9 +144,8 @@ init_ccapi(krb5_context context) > return 0; > #else > HEIMDAL_MUTEX_unlock(&acc_mutex); >- if (context) >- krb5_set_error_message(context, KRB5_CC_NOSUPP, >- N_("no support for shared object", "")); >+ krb5_set_error_message(context, KRB5_CC_NOSUPP, >+ N_("no support for shared object", "")); > return KRB5_CC_NOSUPP; > #endif > } >@@ -988,6 +985,7 @@ acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) > static krb5_error_code KRB5_CALLCONV > acc_move(krb5_context context, krb5_ccache from, krb5_ccache to) > { >+ krb5_error_code ret; > krb5_acc *afrom = ACACHE(from); > krb5_acc *ato = ACACHE(to); > int32_t error; >@@ -1011,9 +1009,10 @@ acc_move(krb5_context context, krb5_ccache from, krb5_ccache to) > } > > error = (*ato->ccache->func->move)(afrom->ccache, ato->ccache); >- >- krb5_cc_destroy(context, from); >- return translate_cc_error(context, error); >+ ret = translate_cc_error(context, error); >+ if (ret == 0) >+ krb5_cc_destroy(context, from); >+ return ret; > } > > static krb5_error_code KRB5_CALLCONV >diff --git a/third_party/heimdal/lib/krb5/acl.c b/third_party/heimdal/lib/krb5/acl.c >index b53c179b72ed..d3196148287e 100644 >--- a/third_party/heimdal/lib/krb5/acl.c >+++ b/third_party/heimdal/lib/krb5/acl.c >@@ -246,7 +246,7 @@ krb5_acl_match_file(krb5_context context, > ...) > { > krb5_error_code ret; >- struct acl_field *acl; >+ struct acl_field *acl = NULL; > char buf[256]; > va_list ap; > FILE *f; >diff --git a/third_party/heimdal/lib/krb5/addr_families.c b/third_party/heimdal/lib/krb5/addr_families.c >index 4d235fff4318..864c9cde8845 100644 >--- a/third_party/heimdal/lib/krb5/addr_families.c >+++ b/third_party/heimdal/lib/krb5/addr_families.c >@@ -525,7 +525,7 @@ arange_parse_addr (krb5_context context, > return ret; > } > >- if(high.len != 1 && high.val[0].addr_type != low.val[0].addr_type) { >+ if(high.len != 1 || high.val[0].addr_type != low.val[0].addr_type) { > krb5_free_addresses(context, &low); > krb5_free_addresses(context, &high); > return -1; >@@ -543,7 +543,13 @@ arange_parse_addr (krb5_context context, > return ret; > } > >- krb5_data_alloc(&addr->address, sizeof(*a)); >+ ret = krb5_data_alloc(&addr->address, sizeof(*a)); >+ if (ret) { >+ krb5_free_address(context, &low0); >+ krb5_free_address(context, &high0); >+ return ret; >+ } >+ > addr->addr_type = KRB5_ADDRESS_ARANGE; > a = addr->address.data; > >@@ -1208,7 +1214,7 @@ krb5_parse_address(krb5_context context, > if (error) { > krb5_error_code ret2; > save_errno = errno; >- ret2 = krb5_eai_to_heim_errno(error, save_errno); >+ ret2 = krb5_eai_to_heim_errno(save_errno, error); > krb5_set_error_message (context, ret2, "%s: %s", > string, gai_strerror(error)); > return ret2; >@@ -1377,12 +1383,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL > krb5_free_addresses(krb5_context context, > krb5_addresses *addresses) > { >- size_t i; >- for(i = 0; i < addresses->len; i++) >- krb5_free_address(context, &addresses->val[i]); >- free(addresses->val); >- addresses->len = 0; >- addresses->val = NULL; >+ free_HostAddresses(addresses); > return 0; > } > >diff --git a/third_party/heimdal/lib/krb5/aes-test.c b/third_party/heimdal/lib/krb5/aes-test.c >index 7bca78ab6068..01522dd593ab 100644 >--- a/third_party/heimdal/lib/krb5/aes-test.c >+++ b/third_party/heimdal/lib/krb5/aes-test.c >@@ -754,6 +754,9 @@ krb_enc_test(krb5_context context) > kb.keyvalue.data = krbencs[i].key; > > ret = krb5_crypto_init(context, &kb, krbencs[i].enctype, &crypto); >+ if (ret) >+ krb5_err(context, 1, ret, "krb5_crypto_init failed with %d for test %d", >+ ret, i); > > cipher.length = krbencs[i].elen; > cipher.data = krbencs[i].edata; >@@ -763,20 +766,24 @@ krb_enc_test(krb5_context context) > ret = krb_enc(context, crypto, krbencs[i].usage, &cipher, &plain); > > if (ret) >- errx(1, "krb_enc failed with %d for test %d", ret, i); >+ krb5_err(context, 1, ret, "krb_enc failed with %d for test %d", >+ ret, i); > > ret = krb_enc_iov(context, crypto, krbencs[i].usage, &cipher, &plain); > if (ret) >- errx(1, "krb_enc_iov failed with %d for test %d", ret, i); >+ krb5_err(context, 1, ret, "krb_enc_iov failed with %d for test %d", >+ ret, i); > > ret = krb_enc_iov2(context, crypto, krbencs[i].usage, > cipher.length, &plain); > if (ret) >- errx(1, "krb_enc_iov2 failed with %d for test %d", ret, i); >+ krb5_err(context, 1, ret, "krb_enc_iov2 failed with %d for test %d", >+ ret, i); > > ret = krb_checksum_iov(context, crypto, krbencs[i].usage, &plain, NULL); > if (ret) >- errx(1, "krb_checksum_iov failed with %d for test %d", ret, i); >+ krb5_err(context, 1, ret, >+ "krb_checksum_iov failed with %d for test %d", ret, i); > > if (krbencs[i].cdata) { > krb5_data checksum; >@@ -787,7 +794,9 @@ krb_enc_test(krb5_context context) > ret = krb_checksum_iov(context, crypto, krbencs[i].usage, > &plain, &checksum); > if (ret) >- errx(1, "krb_checksum_iov(2) failed with %d for test %d", ret, i); >+ krb5_err(context, 1, ret, >+ "krb_checksum_iov(2) failed with %d for test %d", >+ ret, i); > } > > krb5_crypto_destroy(context, crypto); >@@ -795,7 +804,8 @@ krb_enc_test(krb5_context context) > ret = krb_enc_mit(context, krbencs[i].enctype, &kb, > krbencs[i].usage, &cipher, &plain); > if (ret) >- errx(1, "krb_enc_mit failed with %d for test %d", ret, i); >+ krb5_err(context, 1, ret, "krb_enc_mit failed with %d for test %d", >+ ret, i); > } > > return 0; >diff --git a/third_party/heimdal/lib/krb5/asn1_glue.c b/third_party/heimdal/lib/krb5/asn1_glue.c >index 6df8defbce9a..16eda2f6f73d 100644 >--- a/third_party/heimdal/lib/krb5/asn1_glue.c >+++ b/third_party/heimdal/lib/krb5/asn1_glue.c >@@ -38,8 +38,8 @@ > #include "krb5_locl.h" > > KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL >-_krb5_principal2principalname (PrincipalName *p, >- const krb5_principal from) >+_krb5_principal2principalname(PrincipalName *p, >+ krb5_const_principal from) > { > return copy_PrincipalName(&from->name, p); > } >@@ -70,3 +70,93 @@ _krb5_principalname2krb5_principal (krb5_context context, > *principal = p; > return 0; > } >+ >+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL >+_krb5_ticket2krb5_principal(krb5_context context, >+ krb5_principal *principal, >+ const EncTicketPart *ticket, >+ const AuthorizationData *authenticator_ad) >+{ >+ krb5_error_code ret; >+ krb5_principal p = NULL; >+ >+ *principal = NULL; >+ >+ ret = _krb5_principalname2krb5_principal(context, >+ &p, >+ ticket->cname, >+ ticket->crealm); >+ if (ret == 0 && >+ (p->nameattrs = calloc(1, sizeof(p->nameattrs[0]))) == NULL) >+ ret = krb5_enomem(context); >+ if (ret == 0) >+ p->nameattrs->authenticated = 1; >+ if (ret == 0 && >+ (p->nameattrs->source = >+ calloc(1, sizeof(p->nameattrs->source[0]))) == NULL) >+ ret = krb5_enomem(context); >+ if (ret == 0) { >+ p->nameattrs->source->element = >+ choice_PrincipalNameAttrSrc_enc_ticket_part; >+ ret = copy_EncTicketPart(ticket, >+ &p->nameattrs->source->u.enc_ticket_part); >+ /* NOTE: we don't want to keep a copy of the session key here! */ >+ if (ret == 0) >+ der_free_octet_string(&p->nameattrs->source->u.enc_ticket_part.key.keyvalue); >+ } >+ if (ret == 0 && authenticator_ad) { >+ p->nameattrs->authenticator_ad = >+ calloc(1, sizeof(p->nameattrs->authenticator_ad[0])); >+ if (p->nameattrs->authenticator_ad == NULL) >+ ret = krb5_enomem(context); >+ if (ret == 0) >+ ret = copy_AuthorizationData(authenticator_ad, >+ p->nameattrs->authenticator_ad); >+ } >+ >+ if (ret == 0) >+ *principal = p; >+ else >+ krb5_free_principal(context, p); >+ return ret; >+} >+ >+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL >+_krb5_kdcrep2krb5_principal(krb5_context context, >+ krb5_principal *principal, >+ const EncKDCRepPart *kdcrep) >+{ >+ krb5_error_code ret; >+ krb5_principal p = NULL; >+ >+ *principal = NULL; >+ >+ ret = _krb5_principalname2krb5_principal(context, >+ &p, >+ kdcrep->sname, >+ kdcrep->srealm); >+ if (ret == 0 && >+ (p->nameattrs = calloc(1, sizeof(p->nameattrs[0]))) == NULL) >+ ret = krb5_enomem(context); >+ if (ret == 0) >+ p->nameattrs->authenticated = 1; >+ if (ret == 0 && >+ (p->nameattrs->source = >+ calloc(1, sizeof(p->nameattrs->source[0]))) == NULL) >+ ret = krb5_enomem(context); >+ if (ret == 0) { >+ p->nameattrs->source->element = >+ choice_PrincipalNameAttrSrc_enc_kdc_rep_part; >+ ret = copy_EncKDCRepPart(kdcrep, >+ &p->nameattrs->source->u.enc_kdc_rep_part); >+ /* NOTE: we don't want to keep a copy of the session key here! */ >+ if (ret == 0) >+ der_free_octet_string(&p->nameattrs->source->u.enc_kdc_rep_part.key.keyvalue); >+ } >+ >+ if (ret == 0) >+ *principal = p; >+ else >+ krb5_free_principal(context, p); >+ return ret; >+} >diff --git a/third_party/heimdal/lib/krb5/auth_context.c b/third_party/heimdal/lib/krb5/auth_context.c >index 43c762b7699b..8b43b63706c9 100644 >--- a/third_party/heimdal/lib/krb5/auth_context.c >+++ b/third_party/heimdal/lib/krb5/auth_context.c >@@ -557,9 +557,8 @@ krb5_auth_con_getauthenticator(krb5_context context, > if (*authenticator == NULL) > return krb5_enomem(context); > >- copy_Authenticator(auth_context->authenticator, >- *authenticator); >- return 0; >+ return copy_Authenticator(auth_context->authenticator, >+ *authenticator); > } > > >diff --git a/third_party/heimdal/lib/krb5/cache.c b/third_party/heimdal/lib/krb5/cache.c >index 1920796ffc3c..75083f828408 100644 >--- a/third_party/heimdal/lib/krb5/cache.c >+++ b/third_party/heimdal/lib/krb5/cache.c >@@ -514,7 +514,7 @@ krb5_cc_get_subsidiary(krb5_context context, krb5_ccache id) > const char *name = NULL; > > if (id->ops->version >= KRB5_CC_OPS_VERSION_5 >- && id->ops->get_name_2 == NULL) >+ && id->ops->get_name_2 != NULL) > (void) id->ops->get_name_2(context, id, NULL, NULL, &name); > return name; > } >@@ -822,6 +822,17 @@ krb5_cc_configured_default_name(krb5_context context) > return context->configured_default_cc_name = expanded; > } > >+KRB5_LIB_FUNCTION char * KRB5_LIB_CALL >+krb5_cccol_get_default_ccname(krb5_context context) >+{ >+ const char *cfg = get_default_cc_type(context, 1); >+ char *cccol_default_ccname; >+ const krb5_cc_ops *ops = krb5_cc_get_prefix_ops(context, cfg); >+ >+ (void) (*ops->get_default_name)(context, &cccol_default_ccname); >+ return cccol_default_ccname; >+} >+ > /** > * Open the default ccache in `id'. > * >@@ -923,7 +934,7 @@ krb5_cc_destroy(krb5_context context, > /* > * Destroy associated hx509 PKIX credential store created by krb5_kx509*(). > */ >- if ((ret = krb5_cc_get_config(context, id, NULL, "kx509store", &d)) == 0) { >+ if (krb5_cc_get_config(context, id, NULL, "kx509store", &d) == 0) { > char *name; > > if ((name = strndup(d.data, d.length)) == NULL) { >@@ -1001,7 +1012,6 @@ krb5_cc_close(krb5_context context, > _krb5_debug(context, 2, "failed to fetch a certificate"); > else > _krb5_debug(context, 2, "fetched a certificate"); >- ret = 0; > } > } > >@@ -1607,8 +1617,7 @@ krb5_cc_cache_match (krb5_context context, > } else if (cache == NULL) { > char *str; > >- krb5_unparse_name(context, client, &str); >- >+ (void) krb5_unparse_name(context, client, &str); > krb5_set_error_message(context, KRB5_CC_NOTFOUND, > N_("Principal %s not found in any " > "credential cache", ""), >@@ -1653,7 +1662,8 @@ krb5_cc_move(krb5_context context, krb5_ccache from, krb5_ccache to) > ret = (*to->ops->move)(context, from, to); > if (ret == 0) > return 0; >- if (ret != EXDEV && ret != ENOTSUP) >+ if (ret != EXDEV && ret != ENOTSUP && ret != KRB5_CC_NOSUPP && >+ ret != KRB5_FCC_INTERNAL) > return ret; > /* Fallback to high-level copy */ > } /* Else high-level copy */ >@@ -1766,7 +1776,8 @@ krb5_cc_set_config(krb5_context context, krb5_ccache id, > > /* Remove old configuration */ > ret = krb5_cc_remove_cred(context, id, 0, &cred); >- if (ret && ret != KRB5_CC_NOTFOUND) >+ if (ret && ret != KRB5_CC_NOTFOUND && ret != KRB5_CC_NOSUPP && >+ ret != KRB5_FCC_INTERNAL) > goto out; > > if (data) { >diff --git a/third_party/heimdal/lib/krb5/context.c b/third_party/heimdal/lib/krb5/context.c >index 51faf8de99d6..4040a983518e 100644 >--- a/third_party/heimdal/lib/krb5/context.c >+++ b/third_party/heimdal/lib/krb5/context.c >@@ -106,7 +106,7 @@ init_context_from_config_file(krb5_context context) > krb5_error_code ret; > const char * tmp; > char **s; >- krb5_enctype *tmptypes; >+ krb5_enctype *tmptypes = NULL; > > INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew"); > INIT_FIELD(context, time, kdc_timeout, 30, "kdc_timeout"); >@@ -246,10 +246,10 @@ init_context_from_config_file(krb5_context context) > if (context->flags & KRB5_CTX_F_REPORT_CANONICAL_CLIENT_NAME) > context->flags |= KRB5_CTX_F_CHECK_PAC; > >- if (context->default_cc_name) >- free(context->default_cc_name); >+ free(context->default_cc_name); > context->default_cc_name = NULL; > context->default_cc_name_set = 0; >+ free(context->configured_default_cc_name); > context->configured_default_cc_name = NULL; > > tmp = secure_getenv("KRB5_TRACE"); >@@ -646,12 +646,9 @@ KRB5_LIB_FUNCTION void KRB5_LIB_CALL > krb5_free_context(krb5_context context) > { > _krb5_free_name_canon_rules(context, context->name_canon_rules); >- if (context->default_cc_name) >- free(context->default_cc_name); >- if (context->default_cc_name_env) >- free(context->default_cc_name_env); >- if (context->configured_default_cc_name) >- free(context->configured_default_cc_name); >+ free(context->default_cc_name); >+ free(context->default_cc_name_env); >+ free(context->configured_default_cc_name); > free(context->etypes); > free(context->cfg_etypes); > free(context->etypes_des); >diff --git a/third_party/heimdal/lib/krb5/crypto-evp.c b/third_party/heimdal/lib/krb5/crypto-evp.c >index a16b83cb0e07..a03cdca2ebc1 100644 >--- a/third_party/heimdal/lib/krb5/crypto-evp.c >+++ b/third_party/heimdal/lib/krb5/crypto-evp.c >@@ -137,8 +137,11 @@ _krb5_evp_hmac_iov(krb5_context context, > if (ctx == NULL) > return krb5_enomem(context); > >- HMAC_Init_ex(ctx, key->key->keyvalue.data, key->key->keyvalue.length, >- md, engine); >+ if (HMAC_Init_ex(ctx, key->key->keyvalue.data, key->key->keyvalue.length, >+ md, engine) == 0) { >+ HMAC_CTX_free(ctx); >+ return krb5_enomem(context); >+ } > > for (i = 0; i < niov; i++) { > if (_krb5_crypto_iov_should_sign(&iov[i])) { >diff --git a/third_party/heimdal/lib/krb5/crypto.c b/third_party/heimdal/lib/krb5/crypto.c >index 524b2e78681d..2fb4f0620f76 100644 >--- a/third_party/heimdal/lib/krb5/crypto.c >+++ b/third_party/heimdal/lib/krb5/crypto.c >@@ -2152,7 +2152,10 @@ krb5_crypto_length(krb5_context context, > *len = 0; > return 0; > case KRB5_CRYPTO_TYPE_TRAILER: >- *len = CHECKSUMSIZE(crypto->et->keyed_checksum); >+ if (crypto->et->keyed_checksum) >+ *len = CHECKSUMSIZE(crypto->et->keyed_checksum); >+ else >+ *len = 0; > return 0; > case KRB5_CRYPTO_TYPE_CHECKSUM: > if (crypto->et->keyed_checksum) >@@ -2572,7 +2575,7 @@ krb5_crypto_init(krb5_context context, > ALLOC(*crypto, 1); > if (*crypto == NULL) > return krb5_enomem(context); >- if(etype == (krb5_enctype)ETYPE_NULL) >+ if(etype == ETYPE_NULL) > etype = key->keytype; > (*crypto)->et = _krb5_find_enctype(etype); > if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) { >diff --git a/third_party/heimdal/lib/krb5/data.c b/third_party/heimdal/lib/krb5/data.c >index eafc4520b9e0..abfa0531f0ef 100644 >--- a/third_party/heimdal/lib/krb5/data.c >+++ b/third_party/heimdal/lib/krb5/data.c >@@ -200,9 +200,12 @@ krb5_copy_data(krb5_context context, > KRB5_LIB_FUNCTION int KRB5_LIB_CALL > krb5_data_cmp(const krb5_data *data1, const krb5_data *data2) > { >- if (data1->length != data2->length) >+ size_t len = data1->length < data2->length ? data1->length : data2->length; >+ int cmp = memcmp(data1->data, data2->data, len); >+ >+ if (cmp == 0) > return data1->length - data2->length; >- return memcmp(data1->data, data2->data, data1->length); >+ return cmp; > } > > /** >diff --git a/third_party/heimdal/lib/krb5/dcache.c b/third_party/heimdal/lib/krb5/dcache.c >index 22183efcafbe..af88aed91561 100644 >--- a/third_party/heimdal/lib/krb5/dcache.c >+++ b/third_party/heimdal/lib/krb5/dcache.c >@@ -452,7 +452,7 @@ dcc_resolve_2(krb5_context context, > /* Strip off extra slashes on the end */ > for (len = strlen(dc->dir); > len && ISPATHSEP(dc->dir[len - 1]); >- len -= len ? 1 : 0) >+ len--) > dc->dir[len - 1] = '\0'; > > /* If we got here then `dc->dir' and `dc->sub' must both be set */ >@@ -676,17 +676,17 @@ dcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) > /* Strip off extra slashes on the end */ > for (len = strlen(iter->dc->dir); > len && ISPATHSEP(iter->dc->dir[len - 1]); >- len -= len ? 1 : 0) { >+ len--) { > iter->dc->dir[len - 1] = '\0'; > } > > if ((iter->d = opendir(iter->dc->dir)) == NULL) { >- free(iter->dc->dir); >- free(iter->dc); >- free(iter); > krb5_set_error_message(context, KRB5_CC_FORMAT, > N_("Can't open DIR %s: %s", ""), > iter->dc->dir, strerror(errno)); >+ free(iter->dc->dir); >+ free(iter->dc); >+ free(iter); > return KRB5_CC_FORMAT; > } > >@@ -709,8 +709,8 @@ dcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) > > /* Emit primary subsidiary first */ > if (iter->first && >- (ret = get_default_cache(context, iter->dc, NULL, &iter->primary)) == 0 && >- is_filename_cacheish(iter->primary)) { >+ get_default_cache(context, iter->dc, NULL, &iter->primary) == 0 && >+ iter->primary && is_filename_cacheish(iter->primary)) { > iter->first = 0; > ret = KRB5_CC_END; > if (asprintf(&p, "FILE:%s/%s", iter->dc->dir, iter->primary) > -1 && p != NULL && >diff --git a/third_party/heimdal/lib/krb5/deprecated.c b/third_party/heimdal/lib/krb5/deprecated.c >index bcd07e3c2d83..0efa162702cb 100644 >--- a/third_party/heimdal/lib/krb5/deprecated.c >+++ b/third_party/heimdal/lib/krb5/deprecated.c >@@ -324,15 +324,13 @@ krb5_keytab_key_proc (krb5_context context, > > ret = krb5_kt_get_entry (context, real_keytab, principal, > 0, enctype, &entry); >+ if (ret == 0) { >+ ret = krb5_copy_keyblock (context, &entry.keyblock, key); >+ krb5_kt_free_entry(context, &entry); >+ } > > if (keytab == NULL) > krb5_kt_close (context, real_keytab); >- >- if (ret) >- return ret; >- >- ret = krb5_copy_keyblock (context, &entry.keyblock, key); >- krb5_kt_free_entry(context, &entry); > return ret; > } > >diff --git a/third_party/heimdal/lib/krb5/enomem.c b/third_party/heimdal/lib/krb5/enomem.c >index 371b07ff5833..b4444e5a2cdc 100644 >--- a/third_party/heimdal/lib/krb5/enomem.c >+++ b/third_party/heimdal/lib/krb5/enomem.c >@@ -33,10 +33,10 @@ > > #include "krb5_locl.h" > >+#undef krb5_enomem > KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL > krb5_enomem(krb5_context context) > { > krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); > return ENOMEM; > } >- >diff --git a/third_party/heimdal/lib/krb5/error_string.c b/third_party/heimdal/lib/krb5/error_string.c >index 0e42f51bc211..da86b375f83c 100644 >--- a/third_party/heimdal/lib/krb5/error_string.c >+++ b/third_party/heimdal/lib/krb5/error_string.c >@@ -95,15 +95,16 @@ krb5_vset_error_message(krb5_context context, krb5_error_code ret, > const char *fmt, va_list args) > __attribute__ ((__format__ (__printf__, 3, 0))) > { >- if (context) { >- const char *msg; >- >- heim_vset_error_message(context->hcontext, ret, fmt, args); >- msg = heim_get_error_message(context->hcontext, ret); >- if (msg) { >- _krb5_debug(context, 100, "error message: %s: %d", msg, ret); >- heim_free_error_message(context->hcontext, msg); >- } >+ const char *msg; >+ >+ if (context == NULL) >+ return; >+ >+ heim_vset_error_message(context->hcontext, ret, fmt, args); >+ msg = heim_get_error_message(context->hcontext, ret); >+ if (msg) { >+ _krb5_debug(context, 100, "error message: %s: %d", msg, ret); >+ heim_free_error_message(context->hcontext, msg); > } > } > >diff --git a/third_party/heimdal/lib/krb5/expand_path.c b/third_party/heimdal/lib/krb5/expand_path.c >index a1f4dfcfcf78..a0402350d0f3 100644 >--- a/third_party/heimdal/lib/krb5/expand_path.c >+++ b/third_party/heimdal/lib/krb5/expand_path.c >@@ -55,8 +55,8 @@ _krb5_expand_path_tokens(krb5_context context, > int filepath, > char **ppath_out) > { >- return heim_expand_path_tokens(context->hcontext, path_in, filepath, >- ppath_out, NULL); >+ return heim_expand_path_tokens(context ? context->hcontext : NULL, path_in, >+ filepath, ppath_out, NULL); > } > > /** >diff --git a/third_party/heimdal/lib/krb5/fast.c b/third_party/heimdal/lib/krb5/fast.c >index dcca7cc5eec3..617446c36342 100644 >--- a/third_party/heimdal/lib/krb5/fast.c >+++ b/third_party/heimdal/lib/krb5/fast.c >@@ -138,6 +138,12 @@ make_local_fast_ap_fxarmor(krb5_context context, > krb5_data empty; > krb5_const_realm tgs_realm; > >+ if (armor_ccache == NULL) { >+ krb5_set_error_message(context, EINVAL, >+ "Armor credential cache required"); >+ return EINVAL; >+ } >+ > krb5_data_zero(&empty); > memset(&cred, 0, sizeof(cred)); > >@@ -225,6 +231,8 @@ make_fast_ap_fxarmor(krb5_context context, > KrbFastArmor *fxarmor = NULL; > krb5_error_code ret; > >+ *armor = NULL; >+ > ALLOC(fxarmor, 1); > if (fxarmor == NULL) { > ret = ENOMEM; >@@ -429,6 +437,7 @@ _krb5_fast_create_armor(krb5_context context, > if (state->armor_data) { > free_KrbFastArmor(state->armor_data); > free(state->armor_data); >+ state->armor_data = NULL; > } > ret = make_fast_ap_fxarmor(context, state, realm, > &state->armor_data); >@@ -539,8 +548,6 @@ _krb5_fast_wrap_req(krb5_context context, > if (state->type == choice_PA_FX_FAST_REQUEST_armored_data) { > fxreq.u.armored_data.armor = state->armor_data; > state->armor_data = NULL; >- if (ret) >- goto out; > > heim_assert(state->armor_crypto != NULL, > "FAST armor key missing when FAST started"); >@@ -850,7 +857,7 @@ _krb5_fast_anon_pkinit_step(krb5_context context, > > ret = krb5_cc_set_config(context, ccache, cred.server, > "fast_avail", &data); >- if (ret) >+ if (ret && ret != KRB5_CC_NOSUPP) > return ret; > > if (_krb5_pk_is_kdc_verified(context, state->anon_pkinit_opt)) >diff --git a/third_party/heimdal/lib/krb5/fcache.c b/third_party/heimdal/lib/krb5/fcache.c >index 08d4f4217e4c..30dff35893b3 100644 >--- a/third_party/heimdal/lib/krb5/fcache.c >+++ b/third_party/heimdal/lib/krb5/fcache.c >@@ -477,7 +477,6 @@ fcc_open(krb5_context context, > return krb5_einval(context, 2); > > if ((flags & O_EXCL)) { >- flags &= ~O_EXCL; > /* > * FIXME Instead of mkostemp()... we could instead try to use a .new > * file... with care. Or the O_TMPFILE / linkat() extensions. We need >@@ -1177,7 +1176,7 @@ fcc_remove_cred(krb5_context context, > krb5_free_cred_contents(context, &found_cred); > } > ret2 = krb5_cc_end_seq_get(context, id, &cursor); >- if (ret == 0) >+ if (ret2) /* not expected to fail */ > return ret2; > if (ret == KRB5_CC_END) > return 0; >@@ -1548,8 +1547,10 @@ static krb5_error_code KRB5_CALLCONV > fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) > { > krb5_error_code ret = 0; >+ krb5_fcache *f = FCACHE(from); >+ krb5_fcache *t = FCACHE(to); > >- if (TMPFILENAME(from)) { >+ if (f->tmpfn) { > /* > * If `from' has a temp file and we haven't renamed it into place yet, > * then we should rename TMPFILENAME(from) to FILENAME(to). >@@ -1557,13 +1558,13 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) > * This can only happen if we're moving a ccache where only cc config > * entries, or no entries, have been written. That's not likely. > */ >- if (rk_rename(TMPFILENAME(from), FILENAME(to))) { >+ if (rk_rename(f->tmpfn, t->filename)) { > ret = errno; > } else { >- free(TMPFILENAME(from)); >- TMPFILENAME(from) = NULL; >+ free(f->tmpfn); >+ f->tmpfn = NULL; > } >- } else if ((ret = rk_rename(FILENAME(from), FILENAME(to)))) { >+ } else if (rk_rename(f->filename, t->filename)) { > ret = errno; > } > /* >diff --git a/third_party/heimdal/lib/krb5/generate_subkey.c b/third_party/heimdal/lib/krb5/generate_subkey.c >index 07047461ee77..767d94cf7fe6 100644 >--- a/third_party/heimdal/lib/krb5/generate_subkey.c >+++ b/third_party/heimdal/lib/krb5/generate_subkey.c >@@ -58,7 +58,7 @@ krb5_generate_subkey_extended(krb5_context context, > if (*subkey == NULL) > return krb5_enomem(context); > >- if (etype == (krb5_enctype)ETYPE_NULL) >+ if (etype == ETYPE_NULL) > etype = key->keytype; /* use session key etype */ > > /* XXX should we use the session key as input to the RF? */ >diff --git a/third_party/heimdal/lib/krb5/get_cred.c b/third_party/heimdal/lib/krb5/get_cred.c >index 3072cbf5f6bf..ec757797866d 100644 >--- a/third_party/heimdal/lib/krb5/get_cred.c >+++ b/third_party/heimdal/lib/krb5/get_cred.c >@@ -50,7 +50,7 @@ get_cred_kdc_capath(krb5_context, krb5_kdc_flags, > > static krb5_error_code > make_pa_tgs_req(krb5_context context, >- krb5_auth_context ac, >+ krb5_auth_context *ac, > KDC_REQ_BODY *body, > krb5_ccache ccache, > krb5_creds *creds, >@@ -71,7 +71,7 @@ make_pa_tgs_req(krb5_context context, > > in_data.length = len; > in_data.data = buf; >- ret = _krb5_mk_req_internal(context, &ac, 0, &in_data, >+ ret = _krb5_mk_req_internal(context, ac, 0, &in_data, > creds, tgs_req, > KRB5_KU_TGS_REQ_AUTH_CKSUM, > KRB5_KU_TGS_REQ_AUTH); >@@ -114,19 +114,20 @@ set_auth_data (krb5_context context, > req_body->enc_authorization_data = NULL; > return ret; > } >- krb5_encrypt_EncryptedData(context, >- crypto, >- KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, >- buf, >- len, >- 0, >- req_body->enc_authorization_data); >+ ret = krb5_encrypt_EncryptedData(context, >+ crypto, >+ KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, >+ buf, >+ len, >+ 0, >+ req_body->enc_authorization_data); > free (buf); > krb5_crypto_destroy(context, crypto); >+ return ret; > } else { > req_body->enc_authorization_data = NULL; >+ return 0; > } >- return 0; > } > > /* >@@ -286,7 +287,7 @@ init_tgs_req (krb5_context context, > } > > ret = make_pa_tgs_req(context, >- ac, >+ &ac, > &t->req_body, > ccache, > krbtgt, >@@ -516,7 +517,7 @@ get_cred_kdc(krb5_context context, > TGS_REQ req; > krb5_data enc; > krb5_data resp; >- krb5_kdc_rep rep = {0}; >+ krb5_kdc_rep rep; > krb5_error_code ret; > unsigned nonce; > krb5_keyblock *subkey = NULL; >@@ -524,6 +525,7 @@ get_cred_kdc(krb5_context context, > Ticket second_ticket_data; > METHOD_DATA padata; > >+ memset(&rep, 0, sizeof(rep)); > krb5_data_zero(&resp); > krb5_data_zero(&enc); > padata.val = NULL; >@@ -777,7 +779,9 @@ get_cred_kdc_address(krb5_context context, > "no-addresses", FALSE, &noaddr); > > if (!noaddr) { >- krb5_get_all_client_addrs(context, &addresses); >+ ret = krb5_get_all_client_addrs(context, &addresses); >+ if (ret) >+ return ret; > /* XXX this sucks. */ > addrs = &addresses; > if(addresses.len == 0) >@@ -1375,6 +1379,8 @@ _krb5_get_cred_kdc_any(krb5_context context, > krb5_deltat offset; > krb5_data data; > >+ krb5_data_zero(&data); >+ > /* > * If we are using LKDC, lets pull out the addreses from the > * ticket and use that. >@@ -1382,23 +1388,19 @@ _krb5_get_cred_kdc_any(krb5_context context, > > ret = krb5_cc_get_config(context, ccache, NULL, "lkdc-hostname", &data); > if (ret == 0) { >- kdc_hostname = malloc(data.length + 1); >- if (kdc_hostname == NULL) >- return krb5_enomem(context); >- >- memcpy(kdc_hostname, data.data, data.length); >- kdc_hostname[data.length] = '\0'; >+ if ((kdc_hostname = strndup(data.data, data.length)) == NULL) { >+ ret = krb5_enomem(context); >+ goto out; >+ } > krb5_data_free(&data); > } > > ret = krb5_cc_get_config(context, ccache, NULL, "sitename", &data); > if (ret == 0) { >- sitename = malloc(data.length + 1); >- if (sitename == NULL) >- return krb5_enomem(context); >- >- memcpy(sitename, data.data, data.length); >- sitename[data.length] = '\0'; >+ if ((sitename = strndup(data.data, data.length)) == NULL) { >+ ret = krb5_enomem(context); >+ goto out; >+ } > krb5_data_free(&data); > } > >@@ -1441,9 +1443,9 @@ _krb5_get_cred_kdc_any(krb5_context context, > out_creds); > > out: >+ krb5_data_free(&data); > free(kdc_hostname); > free(sitename); >- > return ret; > } > >diff --git a/third_party/heimdal/lib/krb5/get_in_tkt.c b/third_party/heimdal/lib/krb5/get_in_tkt.c >index d6a1a9345dca..c19fc6992816 100644 >--- a/third_party/heimdal/lib/krb5/get_in_tkt.c >+++ b/third_party/heimdal/lib/krb5/get_in_tkt.c >@@ -115,7 +115,7 @@ add_padata(krb5_context context, > if (!enctypes) { > enctypes = context->etypes; > netypes = 0; >- for (ep = enctypes; *ep != (krb5_enctype)ETYPE_NULL; ep++) >+ for (ep = enctypes; *ep != ETYPE_NULL; ep++) > netypes++; > } > pa2 = realloc (md->val, (md->len + netypes) * sizeof(*md->val)); >diff --git a/third_party/heimdal/lib/krb5/init_creds_pw.c b/third_party/heimdal/lib/krb5/init_creds_pw.c >index 4ad5deba0900..e42fcf10bc17 100644 >--- a/third_party/heimdal/lib/krb5/init_creds_pw.c >+++ b/third_party/heimdal/lib/krb5/init_creds_pw.c >@@ -35,7 +35,8 @@ > */ > > #include "krb5_locl.h" >-#include "../base/heimbasepriv.h" /* XXX */ >+ >+#include <heimbasepriv.h> > > struct pa_info_data { > krb5_enctype etype; >@@ -431,8 +432,8 @@ krb5_init_creds_warn_user(krb5_context context, > if (!suppress) { > char *str = NULL, *p = NULL; > int aret; >- krb5_enctype_to_string(context, weak_enctype, &str); > >+ (void) krb5_enctype_to_string(context, weak_enctype, &str); > aret = asprintf(&p, "Encryption type %s(%d) used for authentication is weak and will be deprecated", > str ? str : "unknown", weak_enctype); > if (aret >= 0 && p) { >@@ -467,7 +468,9 @@ get_init_creds_common(krb5_context context, > if (options == NULL) { > const char *realm = krb5_principal_get_realm(context, client); > >- krb5_get_init_creds_opt_alloc (context, &default_opt); >+ ret = krb5_get_init_creds_opt_alloc(context, &default_opt); >+ if (ret) >+ return ret; > options = default_opt; > krb5_get_init_creds_opt_set_default_flags(context, NULL, realm, options); > } >@@ -501,11 +504,8 @@ get_init_creds_common(krb5_context context, > ctx->pre_auth_types = NULL; > > ret = init_cred(context, &ctx->cred, client, start_time, options); >- if (ret) { >- if (default_opt) >- krb5_get_init_creds_opt_free(context, default_opt); >- return ret; >- } >+ if (ret) >+ goto out; > > ret = krb5_init_creds_set_service(context, ctx, NULL); > if (ret) >@@ -579,10 +579,6 @@ get_init_creds_common(krb5_context context, > else > ctx->runflags.change_password_prompt = ctx->prompter != NULL; > >- if (default_opt) >- krb5_get_init_creds_opt_free(context, default_opt); >- return 0; >- > out: > if (default_opt) > krb5_get_init_creds_opt_free(context, default_opt); >@@ -703,8 +699,7 @@ change_password (krb5_context context, > strlcpy (newpw, buf1, newpw_sz); > ret = 0; > } else { >- ret = ENOTTY; >- krb5_set_error_message(context, ret, >+ krb5_set_error_message(context, ret = KRB5_CHPW_FAIL, > N_("failed changing password: %s", ""), p); > } > free (p); >@@ -1089,7 +1084,7 @@ add_enc_ts_padata(krb5_context context, > if (!enctypes) { > enctypes = context->etypes; > netypes = 0; >- for (ep = enctypes; *ep != (krb5_enctype)ETYPE_NULL; ep++) >+ for (ep = enctypes; *ep != ETYPE_NULL; ep++) > netypes++; > } > >@@ -1427,12 +1422,13 @@ pa_gss_step(krb5_context context, > char *from = NULL; > char *to = NULL; > >- if (krb5_unparse_name(context, ctx->cred.client, &from) == 0 && >- krb5_unparse_name(context, cname, &to) == 0) { >- _krb5_debug(context, 1, "pa_gss_step: %s as %s", >- from, to); >+ if (krb5_unparse_name(context, ctx->cred.client, &from) == 0) { >+ if (krb5_unparse_name(context, cname, &to) == 0) { >+ _krb5_debug(context, 1, "pa_gss_step: %s as %s", >+ from, to); >+ krb5_xfree(to); >+ } > krb5_xfree(from); >- krb5_xfree(to); > } > } > >@@ -1661,11 +1657,6 @@ enc_chal_step(krb5_context context, krb5_init_creds_context ctx, void *pa_ctx, P > EncryptedData enc_data; > size_t size; > >- if (ret) { >- _krb5_debug(context, 5, "enc-chal: failed to create reply key"); >- return ret; >- } >- > _krb5_debug(context, 5, "ENC_CHAL rep key"); > > if (ctx->fast_state.strengthen_key == NULL) { >@@ -2139,28 +2130,30 @@ process_pa_info(krb5_context context, > return p; > } > >-static void >+static krb5_error_code > pa_announce(krb5_context context, > int types, > krb5_init_creds_context ctx, > METHOD_DATA *in_md, > METHOD_DATA *out_md) > { >+ krb5_error_code ret = 0; > size_t n; > >- for (n = 0; n < sizeof(patypes)/sizeof(patypes[0]); n++) { >+ for (n = 0; ret == 0 && n < sizeof(patypes)/sizeof(patypes[0]); n++) { > if ((patypes[n].flags & types) == 0) > continue; > > if (patypes[n].step) > patypes[n].step(context, ctx, NULL, NULL, NULL, NULL, NULL, in_md, out_md); > else >- krb5_padata_add(context, out_md, patypes[n].type, NULL, 0); >+ ret = krb5_padata_add(context, out_md, patypes[n].type, NULL, 0); > } >+ return ret; > } > > >-static void >+static void HEIM_CALLCONV > mech_dealloc(void *ctx) > { > struct pa_auth_mech *pa_mech = ctx; >@@ -2406,8 +2399,7 @@ process_pa_data_to_md(krb5_context context, > * Send announcement (what we support) and configuration (user > * introduced behavior change) > */ >- >- pa_announce(context, PA_F_ANNOUNCE|PA_F_CONFIG, ctx, in_md, *out_md); >+ ret = pa_announce(context, PA_F_ANNOUNCE|PA_F_CONFIG, ctx, in_md, *out_md); > > /* > * >@@ -2418,7 +2410,7 @@ process_pa_data_to_md(krb5_context context, > *out_md = NULL; > } > >- return 0; >+ return ret; > } > > static krb5_error_code >@@ -2634,7 +2626,11 @@ krb5_init_creds_set_service(krb5_context context, > ret = krb5_parse_name (context, service, &principal); > if (ret) > return ret; >- krb5_principal_set_realm (context, principal, client_realm); >+ ret = krb5_principal_set_realm (context, principal, client_realm); >+ if (ret) { >+ krb5_free_principal(context, principal); >+ return ret; >+ } > } else { > ret = krb5_make_principal(context, &principal, > client_realm, KRB5_TGS_NAME, client_realm, >@@ -2704,27 +2700,23 @@ keytab_key_proc(krb5_context context, krb5_enctype enctype, > krb5_keytab keytab = args->keytab; > krb5_principal principal = args->principal; > krb5_error_code ret; >- krb5_keytab real_keytab; >+ krb5_keytab real_keytab = NULL; > krb5_keytab_entry entry; > > if (keytab == NULL) { > ret = krb5_kt_default(context, &real_keytab); > if (ret) > return ret; >- } else >- real_keytab = keytab; >- >- ret = krb5_kt_get_entry (context, real_keytab, principal, >- 0, enctype, &entry); >- >- if (keytab == NULL) >- krb5_kt_close (context, real_keytab); >+ keytab = real_keytab; >+ } > >- if (ret) >- return ret; >+ ret = krb5_kt_get_entry (context, keytab, principal, 0, enctype, &entry); >+ if (ret == 0) { >+ ret = krb5_copy_keyblock(context, &entry.keyblock, key); >+ krb5_kt_free_entry(context, &entry); >+ } > >- ret = krb5_copy_keyblock (context, &entry.keyblock, key); >- krb5_kt_free_entry(context, &entry); >+ krb5_kt_close(context, real_keytab); > return ret; > } > >@@ -2870,25 +2862,9 @@ krb5_init_creds_set_fast_ccache(krb5_context context, > krb5_init_creds_context ctx, > krb5_ccache fast_ccache) > { >- krb5_creds *cred = NULL; >- krb5_error_code ret; >- krb5_data data; >- >- ret = _krb5_get_krbtgt(context, fast_ccache, NULL, &cred); >- if (ret) >- return ret; >- >- ret = krb5_cc_get_config(context, fast_ccache, cred->server, >- "fast_avail", &data); >- krb5_free_creds(context, cred); >- if (ret == 0) { >- ctx->fast_state.armor_ccache = fast_ccache; >- ctx->fast_state.flags |= KRB5_FAST_REQUIRED; >- ctx->fast_state.flags |= KRB5_FAST_KDC_VERIFIED; >- } else { >- krb5_set_error_message(context, EINVAL, N_("FAST not available for the KDC in the armor ccache", "")); >- return EINVAL; >- } >+ ctx->fast_state.armor_ccache = fast_ccache; >+ ctx->fast_state.flags |= KRB5_FAST_REQUIRED; >+ ctx->fast_state.flags |= KRB5_FAST_KDC_VERIFIED; > return 0; > } > >@@ -2956,6 +2932,19 @@ krb5_init_creds_set_fast_anon_pkinit(krb5_context context, > return 0; > } > >+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL >+_krb5_init_creds_set_fast_anon_pkinit_optimistic(krb5_context context, >+ krb5_init_creds_context ctx) >+{ >+ if (ctx->fast_state.armor_ccache) >+ return EINVAL; >+ >+ ctx->fast_state.flags |= KRB5_FAST_REQUIRED; >+ ctx->fast_state.flags |= KRB5_FAST_ANON_PKINIT_ARMOR; >+ ctx->fast_state.flags |= KRB5_FAST_OPTIMISTIC; >+ return 0; >+} >+ > static size_t > available_padata_count(METHOD_DATA *md) > { >@@ -3352,16 +3341,6 @@ init_creds_step(krb5_context context, > goto out; > } > >- if ((ctx->fast_state.flags & KRB5_FAST_OPTIMISTIC) == 0) { >- _krb5_debug(context, 10, "Preauth failed"); >- goto out; >- } >- >- _krb5_debug(context, 10, "preauth failed with optimistic FAST, trying w/o FAST"); >- >- ctx->fast_state.flags &= ~KRB5_FAST_OPTIMISTIC; >- ctx->fast_state.flags |= KRB5_FAST_DISABLED; >- > retry: > pa_restart(context, ctx); > >@@ -3370,6 +3349,8 @@ init_creds_step(krb5_context context, > "Some other error %d failed with optimistic FAST, trying w/o FAST", ret); > > ctx->fast_state.flags &= ~KRB5_FAST_OPTIMISTIC; >+ ctx->fast_state.flags &= ~KRB5_FAST_REQUIRED; >+ ctx->fast_state.flags &= ~KRB5_FAST_ANON_PKINIT_ARMOR; > ctx->fast_state.flags |= KRB5_FAST_DISABLED; > pa_restart(context, ctx); > } else { >@@ -3485,9 +3466,15 @@ krb5_init_creds_step(krb5_context context, > ctx->fast_state.armor_ccache == NULL) { > ret = _krb5_fast_anon_pkinit_step(context, ctx, &ctx->fast_state, > in, out, hostinfo, flags); >- if (ret || >- ((*flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE) == 0) || >- out->length) >+ if (ret && (ctx->fast_state.flags & KRB5_FAST_OPTIMISTIC)) { >+ _krb5_debug(context, 5, "Preauth failed with optimistic " >+ "FAST, trying w/o FAST"); >+ ctx->fast_state.flags &= ~KRB5_FAST_OPTIMISTIC; >+ ctx->fast_state.flags &= ~KRB5_FAST_REQUIRED; >+ ctx->fast_state.flags &= ~KRB5_FAST_ANON_PKINIT_ARMOR; >+ } else if (ret || >+ ((*flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE) == 0) || >+ out->length) > return ret; > > in = ∅ >@@ -3649,7 +3636,7 @@ krb5_init_creds_store(krb5_context context, > krb5_data data = { 3, rk_UNCONST("yes") }; > ret = krb5_cc_set_config(context, id, ctx->cred.server, > "fast_avail", &data); >- if (ret) >+ if (ret && ret != KRB5_CC_NOSUPP) > return ret; > } > >@@ -4001,7 +3988,7 @@ _krb5_init_creds_init_gss(krb5_context context, > const struct gss_OID_desc_struct *gss_mech, > unsigned int flags) > { >- krb5_gss_init_ctx gssic = ctx->gss_init_ctx; >+ krb5_gss_init_ctx gssic; > > gssic = calloc(1, sizeof(*gssic)); > if (gssic == NULL) >diff --git a/third_party/heimdal/lib/krb5/kcm.c b/third_party/heimdal/lib/krb5/kcm.c >index 760abf5c59dd..a75fc03f985d 100644 >--- a/third_party/heimdal/lib/krb5/kcm.c >+++ b/third_party/heimdal/lib/krb5/kcm.c >@@ -73,6 +73,8 @@ kcm_send_request(krb5_context context, > krb5_error_code ret = 0; > krb5_data request_data; > >+ krb5_data_zero(response_data); >+ > HEIMDAL_MUTEX_lock(&kcm_mutex); > if (kcm_ipc == NULL) > ret = heim_ipc_init_context(kcm_ipc_name, &kcm_ipc); >@@ -82,18 +84,11 @@ kcm_send_request(krb5_context context, > > ret = krb5_storage_to_data(request, &request_data); > if (ret) { >- krb5_clear_error_message(context); >- return KRB5_CC_NOMEM; >+ return krb5_enomem(context); > } > > ret = heim_ipc_call(kcm_ipc, &request_data, response_data, NULL); > krb5_data_free(&request_data); >- >- if (ret) { >- krb5_clear_error_message(context); >- ret = KRB5_CC_NOSUPP; >- } >- > return ret; > } > >@@ -108,10 +103,8 @@ krb5_kcm_storage_request(krb5_context context, > *storage_p = NULL; > > sp = krb5_storage_emem(); >- if (sp == NULL) { >- krb5_set_error_message(context, KRB5_CC_NOMEM, N_("malloc: out of memory", "")); >- return KRB5_CC_NOMEM; >- } >+ if (sp == NULL) >+ return krb5_enomem(context); > > /* Send MAJOR | VERSION | OPCODE */ > ret = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MAJOR); >@@ -135,31 +128,166 @@ krb5_kcm_storage_request(krb5_context context, > return ret; > } > >+/* >+ * A sort of a state() for caches -- we use this to see if the local default >+ * cache name for KCM happens to exist. See kcm_alloc() below. >+ */ >+static krb5_error_code >+kcm_stat(krb5_context context, const char *name) >+{ >+ krb5_error_code ret; >+ krb5_storage *request = NULL; >+ krb5_data response_data; >+ >+ krb5_data_zero(&response_data); >+ >+ ret = krb5_kcm_storage_request(context, KCM_OP_GET_PRINCIPAL, &request); >+ if (ret == 0) >+ ret = krb5_store_stringz(request, name); >+ if (ret == 0) >+ ret = krb5_kcm_call(context, request, NULL, &response_data); >+ krb5_storage_free(request); >+ krb5_data_free(&response_data); >+ return ret; >+} >+ >+static krb5_error_code kcm_get_default_name(krb5_context, >+ const krb5_cc_ops *, >+ const char *, char **); >+ > static krb5_error_code > kcm_alloc(krb5_context context, >- const char *name, >+ const krb5_cc_ops *ops, >+ const char *residual, >+ const char *sub, > krb5_ccache *id) > { >+ krb5_error_code ret; > krb5_kcmcache *k; >+ size_t ops_prefix_len = strlen(ops->prefix); >+ size_t plen = 0; >+ size_t local_def_name_len; >+ char *local_def_name = NULL; /* Our idea of default KCM cache name */ >+ char *kcm_def_name = NULL; /* KCM's knowledge of default cache name */ >+ int aret; > >- k = malloc(sizeof(*k)); >- if (k == NULL) { >- krb5_set_error_message(context, KRB5_CC_NOMEM, >- N_("malloc: out of memory", "")); >- return KRB5_CC_NOMEM; >+ /* Get the KCM:%{UID} default */ >+ if (ops == &krb5_kcm_ops) >+ ret = _krb5_expand_default_cc_name(context, KRB5_DEFAULT_CCNAME_KCM_KCM, &local_def_name); >+ else >+ ret = _krb5_expand_default_cc_name(context, KRB5_DEFAULT_CCNAME_KCM_API, &local_def_name); >+ if (ret) >+ return ret; >+ local_def_name_len = strlen(local_def_name); >+ >+ /* Get the default ccache name from KCM if possible */ >+ (void) kcm_get_default_name(context, ops, NULL, &kcm_def_name); >+ >+ /* >+ * We have a sticky situation in that applications that call >+ * krb5_cc_default() will be getting the locally configured or compiled-in >+ * default KCM cache name, which may not exist in the user's KCM session, >+ * and which the KCM daemon may not be able to alias to the actual default >+ * for the user's session. >+ * >+ * To deal with this we heuristically detect when an application uses the >+ * default KCM ccache name. >+ * >+ * If the residual happens to be the local default KCM name we may end up >+ * using whatever the default KCM cache name is instead of the local >+ * default. >+ * >+ * Note that here `residual' may be any of: >+ * >+ * - %{UID} >+ * - %{UID}: >+ * - %{UID}:<subsidiary> >+ * - <something not starting with %{UID}:> >+ * - <empty string> >+ * - <NULL> >+ * >+ * Only the first two count as "maybe I mean the default KCM cache". >+ */ >+ if (residual && !sub && >+ strncmp(residual, local_def_name + ops_prefix_len + 1, >+ local_def_name_len - (ops_prefix_len + 1)) == 0) { >+ if (residual[local_def_name_len - (ops_prefix_len + 1)] == '\0' || >+ (residual[local_def_name_len - (ops_prefix_len + 1)] == ':' && >+ residual[local_def_name_len - ops_prefix_len] == '\0')) { >+ /* >+ * If we got a default cache name from KCM and the requested default >+ * cache does not exist, use the former. >+ */ >+ if (kcm_def_name && kcm_stat(context, residual)) >+ residual = kcm_def_name + ops_prefix_len + 1; >+ } > } > >- if (name != NULL) { >- k->name = strdup(name); >- if (k->name == NULL) { >- free(k); >- krb5_set_error_message(context, KRB5_CC_NOMEM, >- N_("malloc: out of memory", "")); >- return KRB5_CC_NOMEM; >- } >- } else >- k->name = NULL; >+ if (residual && residual[0] == '\0') >+ residual = NULL; >+ if (sub && sub[0] == '\0') >+ sub = NULL; >+ >+ if (residual == NULL && sub == NULL) { >+ /* Use the default cache name, either from KCM or local default */ >+ if (kcm_def_name) >+ residual = kcm_def_name + ops_prefix_len + 1; >+ else >+ residual = local_def_name + ops_prefix_len + 1; >+ } >+ >+ if (residual) { >+ /* KCM cache names must start with {UID} or {UID}: */ >+ if (residual[0] != '0') >+ plen = strspn(residual, "0123456789"); >+ if (plen && residual[plen] != ':' && residual[plen] != '\0') >+ plen = 0; >+ /* >+ * If `plen', then residual is such a residual, else we'll want to >+ * prefix the {UID}:. >+ */ >+ } >+ >+ k = calloc(1, sizeof(*k)); >+ if (k == NULL) { >+ free(local_def_name); >+ free(kcm_def_name); >+ return krb5_enomem(context); >+ } >+ k->name = NULL; >+ >+ if (residual == NULL && sub == NULL) { >+ /* One more way to get a default */ >+ aret = asprintf(&k->name, "%llu", (unsigned long long)getuid()); >+ } else if (residual == NULL) { >+ /* >+ * Treat the subsidiary as the residual (maybe this will turn out to be >+ * wrong). >+ */ >+ aret = asprintf(&k->name, "%llu:%s", (unsigned long long)getuid(), >+ sub); >+ } else if (plen) { >+ /* The residual is a UID */ >+ aret = asprintf(&k->name, "%s%s%s", residual, >+ sub ? ":" : "", sub ? sub : ""); >+ } else if (sub == NULL) { >+ /* The residual is NOT a UID */ >+ aret = asprintf(&k->name, "%llu:%s", (unsigned long long)getuid(), >+ residual); >+ } else { >+ /* Ditto, plus we have a subsidiary. `residual && sub && !plen' */ >+ aret = asprintf(&k->name, "%llu:%s:%s", (unsigned long long)getuid(), >+ residual, sub); >+ } >+ if (aret == -1 || k->name == NULL) { >+ free(local_def_name); >+ free(kcm_def_name); >+ free(k); >+ return krb5_enomem(context); >+ } > >+ free(local_def_name); >+ free(kcm_def_name); > (*id)->data.data = k; > (*id)->data.length = sizeof(*k); > >@@ -181,10 +309,11 @@ krb5_kcm_call(krb5_context context, > *response_p = NULL; > > krb5_data_zero(&response_data); >- > ret = kcm_send_request(context, request, &response_data); >- if (ret) >- return ret; >+ if (ret) { >+ krb5_data_free(&response_data); >+ return ret; >+ } > > response = krb5_storage_from_data(&response_data); > if (response == NULL) { >@@ -224,8 +353,7 @@ kcm_free(krb5_context context, krb5_ccache *id) > krb5_kcmcache *k = KCMCACHE(*id); > > if (k != NULL) { >- if (k->name != NULL) >- free(k->name); >+ free(k->name); > memset_s(k, sizeof(*k), 0, sizeof(*k)); > krb5_data_free(&(*id)->data); > } >@@ -255,10 +383,10 @@ kcm_get_name_2(krb5_context context, > } > > static krb5_error_code >-kcm_resolve_2(krb5_context context, >- krb5_ccache *id, >- const char *res, >- const char *sub) >+kcm_resolve_2_kcm(krb5_context context, >+ krb5_ccache *id, >+ const char *res, >+ const char *sub) > { > /* > * For now, for KCM the `res' is the `sub'. >@@ -266,7 +394,22 @@ kcm_resolve_2(krb5_context context, > * TODO: We should use `res' as the IPC name instead of the one currently > * hard-coded in `kcm_ipc_name'. > */ >- return kcm_alloc(context, sub && *sub ? sub : res, id); >+ return kcm_alloc(context, &krb5_kcm_ops, res, sub, id); >+} >+ >+static krb5_error_code >+kcm_resolve_2_api(krb5_context context, >+ krb5_ccache *id, >+ const char *res, >+ const char *sub) >+{ >+ /* >+ * For now, for KCM the `res' is the `sub'. >+ * >+ * TODO: We should use `res' as the IPC name instead of the one currently >+ * hard-coded in `kcm_ipc_name'. >+ */ >+ return kcm_alloc(context, &krb5_akcm_ops, res, sub, id); > } > > /* >@@ -276,14 +419,14 @@ kcm_resolve_2(krb5_context context, > * NameZ > */ > static krb5_error_code >-kcm_gen_new(krb5_context context, krb5_ccache *id) >+kcm_gen_new(krb5_context context, const krb5_cc_ops *ops, krb5_ccache *id) > { > krb5_kcmcache *k; > krb5_error_code ret; > krb5_storage *request, *response; > krb5_data response_data; > >- ret = kcm_alloc(context, NULL, id); >+ ret = kcm_alloc(context, ops, NULL, NULL, id); > if (ret) > return ret; > >@@ -302,6 +445,8 @@ kcm_gen_new(krb5_context context, krb5_ccache *id) > return ret; > } > >+ free(k->name); >+ k->name = NULL; > ret = krb5_ret_stringz(response, &k->name); > if (ret) > ret = KRB5_CC_IO; >@@ -316,6 +461,18 @@ kcm_gen_new(krb5_context context, krb5_ccache *id) > return ret; > } > >+static krb5_error_code >+kcm_gen_new_kcm(krb5_context context, krb5_ccache *id) >+{ >+ return kcm_gen_new(context, &krb5_kcm_ops, id); >+} >+ >+static krb5_error_code >+kcm_gen_new_api(krb5_context context, krb5_ccache *id) >+{ >+ return kcm_gen_new(context, &krb5_akcm_ops, id); >+} >+ > /* > * Request: > * NameZ >@@ -666,8 +823,7 @@ kcm_get_next (krb5_context context, > c->offset++; > if (sret != sizeof(c->uuids[c->offset])) { > krb5_storage_free(request); >- krb5_clear_error_message(context); >- return ENOMEM; >+ return krb5_enomem(context); > } > > ret = krb5_kcm_call(context, request, &response, &response_data); >@@ -895,8 +1051,7 @@ kcm_get_cache_next(krb5_context context, krb5_cc_cursor cursor, const krb5_cc_op > c->offset++; > if (sret != sizeof(c->uuids[c->offset])) { > krb5_storage_free(request); >- krb5_clear_error_message(context); >- return ENOMEM; >+ return krb5_enomem(context); > } > > ret = krb5_kcm_call(context, request, &response, &response_data); >@@ -913,7 +1068,7 @@ kcm_get_cache_next(krb5_context context, krb5_cc_cursor cursor, const krb5_cc_op > if (ret == 0) { > ret = _krb5_cc_allocate(context, ops, id); > if (ret == 0) >- ret = kcm_alloc(context, name, id); >+ ret = kcm_alloc(context, ops, name, NULL, id); > krb5_xfree(name); > } > >@@ -998,8 +1153,11 @@ kcm_get_default_name(krb5_context context, const krb5_cc_ops *ops, > > ret = krb5_kcm_call(context, request, &response, &response_data); > krb5_storage_free(request); >- if (ret) >- return _krb5_expand_default_cc_name(context, defstr, str); >+ if (ret) { >+ if (defstr) >+ return _krb5_expand_default_cc_name(context, defstr, str); >+ return ret; >+ } > > ret = krb5_ret_stringz(response, &name); > krb5_storage_free(response); >@@ -1009,8 +1167,8 @@ kcm_get_default_name(krb5_context context, const krb5_cc_ops *ops, > > aret = asprintf(str, "%s:%s", ops->prefix, name); > free(name); >- if (aret == -1 || str == NULL) >- return ENOMEM; >+ if (aret == -1 || *str == NULL) >+ return krb5_enomem(context); > > return 0; > } >@@ -1133,7 +1291,7 @@ KRB5_LIB_VARIABLE const krb5_cc_ops krb5_kcm_ops = { > "KCM", > NULL, > NULL, >- kcm_gen_new, >+ kcm_gen_new_kcm, > kcm_initialize, > kcm_destroy, > kcm_close, >@@ -1156,7 +1314,7 @@ KRB5_LIB_VARIABLE const krb5_cc_ops krb5_kcm_ops = { > kcm_set_kdc_offset, > kcm_get_kdc_offset, > kcm_get_name_2, >- kcm_resolve_2 >+ kcm_resolve_2_kcm > }; > > KRB5_LIB_VARIABLE const krb5_cc_ops krb5_akcm_ops = { >@@ -1164,7 +1322,7 @@ KRB5_LIB_VARIABLE const krb5_cc_ops krb5_akcm_ops = { > "API", > NULL, > NULL, >- kcm_gen_new, >+ kcm_gen_new_api, > kcm_initialize, > kcm_destroy, > kcm_close, >@@ -1187,10 +1345,9 @@ KRB5_LIB_VARIABLE const krb5_cc_ops krb5_akcm_ops = { > NULL, > NULL, > kcm_get_name_2, >- kcm_resolve_2 >+ kcm_resolve_2_api > }; > >- > KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL > _krb5_kcm_is_running(krb5_context context) > { >@@ -1199,7 +1356,7 @@ _krb5_kcm_is_running(krb5_context context) > krb5_ccache id = &ccdata; > krb5_boolean running; > >- ret = kcm_alloc(context, NULL, &id); >+ ret = kcm_alloc(context, NULL, NULL, NULL, &id); > if (ret) > return 0; > >diff --git a/third_party/heimdal/lib/krb5/keytab.c b/third_party/heimdal/lib/krb5/keytab.c >index 6ec14b8e1719..559d640f002c 100644 >--- a/third_party/heimdal/lib/krb5/keytab.c >+++ b/third_party/heimdal/lib/krb5/keytab.c >@@ -358,10 +358,11 @@ krb5_kt_read_service_key(krb5_context context, > krb5_enctype enctype, > krb5_keyblock **key) > { >- krb5_keytab keytab; >+ krb5_keytab keytab = NULL; /* Quiet lint */ > krb5_keytab_entry entry; > krb5_error_code ret; > >+ memset(&entry, 0, sizeof(entry)); > if (keyprocarg) > ret = krb5_kt_resolve (context, keyprocarg, &keytab); > else >@@ -371,11 +372,11 @@ krb5_kt_read_service_key(krb5_context context, > return ret; > > ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry); >+ if (ret == 0) { >+ ret = krb5_copy_keyblock (context, &entry.keyblock, key); >+ krb5_kt_free_entry(context, &entry); >+ } > krb5_kt_close (context, keytab); >- if (ret) >- return ret; >- ret = krb5_copy_keyblock (context, &entry.keyblock, key); >- krb5_kt_free_entry(context, &entry); > return ret; > } > >@@ -482,11 +483,13 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL > krb5_kt_close(krb5_context context, > krb5_keytab id) > { >- krb5_error_code ret; >+ krb5_error_code ret = 0; > >- ret = (*id->close)(context, id); >- memset(id, 0, sizeof(*id)); >- free(id); >+ if (id) { >+ ret = (id->close)(context, id); >+ memset(id, 0, sizeof(*id)); >+ free(id); >+ } > return ret; > } > >@@ -579,29 +582,31 @@ _krb5_kt_principal_not_found(krb5_context context, > krb5_enctype enctype, > int kvno) > { >- char princ[256], kvno_str[25], *kt_name; >+ char kvno_str[25]; > char *enctype_str = NULL; >+ char *kt_name = NULL; >+ char *princ = NULL; > >- krb5_unparse_name_fixed (context, principal, princ, sizeof(princ)); >- krb5_kt_get_full_name (context, id, &kt_name); >+ (void) krb5_unparse_name(context, principal, &princ); >+ (void) krb5_kt_get_full_name(context, id, &kt_name); > if (enctype) >- krb5_enctype_to_string(context, enctype, &enctype_str); >+ (void) krb5_enctype_to_string(context, enctype, &enctype_str); > > if (kvno) > snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno); > else > kvno_str[0] = '\0'; > >- krb5_set_error_message (context, ret, >- N_("Failed to find %s%s in keytab %s (%s)", >- "principal, kvno, keytab file, enctype"), >- princ, >- kvno_str, >- kt_name ? kt_name : "unknown keytab", >- enctype_str ? enctype_str : "unknown enctype"); >+ krb5_set_error_message(context, ret, >+ N_("Failed to find %s%s in keytab %s (%s)", >+ "principal, kvno, keytab file, enctype"), >+ princ ? princ : "<unknown>", >+ kvno_str, >+ kt_name ? kt_name : "unknown keytab", >+ enctype_str ? enctype_str : "unknown enctype"); >+ free(princ); > free(kt_name); >- if (enctype_str) >- free(enctype_str); >+ free(enctype_str); > return ret; > } > >@@ -620,6 +625,7 @@ krb5_kt_get_entry_wrapped(krb5_context context, > if(id->get) > return (*id->get)(context, id, principal, kvno, enctype, entry); > >+ memset(&tmp, 0, sizeof(tmp)); > ret = krb5_kt_start_seq_get (context, id, &cursor); > if (ret) { > /* This is needed for krb5_verify_init_creds, but keep error >@@ -683,7 +689,8 @@ krb5_kt_get_entry(krb5_context context, > krb5_name_canon_iterator name_canon_iter; > > if (!principal) >- return krb5_kt_get_entry_wrapped(context, id, principal, kvno, enctype, >+ /* Use `NULL' instead of `principal' to quiet static analizers */ >+ return krb5_kt_get_entry_wrapped(context, id, NULL, kvno, enctype, > entry); > > ret = krb5_name_canon_iterator_start(context, principal, &name_canon_iter); >@@ -731,21 +738,21 @@ krb5_kt_copy_entry_contents(krb5_context context, > krb5_error_code ret; > > memset(out, 0, sizeof(*out)); >- out->vno = in->vno; > > ret = krb5_copy_principal (context, in->principal, &out->principal); > if (ret) >- goto fail; >+ return ret; > ret = krb5_copy_keyblock_contents (context, > &in->keyblock, > &out->keyblock); >- if (ret) >- goto fail; >+ if (ret) { >+ krb5_free_principal(context, out->principal); >+ memset(out, 0, sizeof(*out)); >+ return ret; >+ } >+ out->vno = in->vno; > out->timestamp = in->timestamp; > return 0; >-fail: >- krb5_kt_free_entry (context, out); >- return ret; > } > > /** >@@ -927,6 +934,7 @@ krb5_kt_have_content(krb5_context context, > krb5_error_code ret; > char *name; > >+ memset(&entry, 0, sizeof(entry)); > ret = krb5_kt_start_seq_get(context, id, &cursor); > if (ret) > goto notfound; >diff --git a/third_party/heimdal/lib/krb5/keytab_file.c b/third_party/heimdal/lib/krb5/keytab_file.c >index 595966ed3876..61b5d6d29cf8 100644 >--- a/third_party/heimdal/lib/krb5/keytab_file.c >+++ b/third_party/heimdal/lib/krb5/keytab_file.c >@@ -371,6 +371,7 @@ fkt_start_seq_get_int(krb5_context context, > struct fkt_data *d = id->data; > const char *stdio_mode = "rb"; > >+ memset(c, 0, sizeof(*c)); > c->fd = open (d->filename, flags); > if (c->fd < 0) { > ret = errno; >@@ -797,7 +798,7 @@ fkt_remove_entry(krb5_context context, > krb5_set_error_message(context, ret, > N_("Could not remove keytab entry from %s: %s", ""), > fkt->filename, >- krb5_get_error_message(context, ret)); >+ emsg); > krb5_free_error_message(context, emsg); > } else if (!found) { > krb5_clear_error_message(context); >diff --git a/third_party/heimdal/lib/krb5/keytab_keyfile.c b/third_party/heimdal/lib/krb5/keytab_keyfile.c >index cb865a794c08..af3ac86faf0a 100644 >--- a/third_party/heimdal/lib/krb5/keytab_keyfile.c >+++ b/third_party/heimdal/lib/krb5/keytab_keyfile.c >@@ -403,7 +403,7 @@ akf_add_entry(krb5_context context, > ret = errno; > krb5_set_error_message (context, ret, > N_("keytab keyfile failed new length", "")); >- return ret; >+ goto out; > } > > if(krb5_storage_seek(sp, (len - 1) * (8 + 4), SEEK_CUR) < 0) { >diff --git a/third_party/heimdal/lib/krb5/krb5.conf.5 b/third_party/heimdal/lib/krb5/krb5.conf.5 >index bac94b5f7dfe..1013a78d8731 100644 >--- a/third_party/heimdal/lib/krb5/krb5.conf.5 >+++ b/third_party/heimdal/lib/krb5/krb5.conf.5 >@@ -1077,12 +1077,6 @@ an optional unit (the default unit is > Indicates whether a client may request longer lifetimes than > their authentication credentials. > Defaults to false. >-If a >-.Li force_cert_lifetime >-is specified, then >-.Li allow_extra_lifetime >-is implicitly forced to >-.Va true . > .It Li require_initial_kca_tickets = Va boolean > Specified whether to require that tickets for the > .Li kca_service >diff --git a/third_party/heimdal/lib/krb5/krb5.h b/third_party/heimdal/lib/krb5/krb5.h >index 3950bd30a4ec..e78edcac9af5 100644 >--- a/third_party/heimdal/lib/krb5/krb5.h >+++ b/third_party/heimdal/lib/krb5/krb5.h >@@ -95,6 +95,7 @@ typedef struct krb5_ntlm_data *krb5_ntlm; > > struct krb5_pac_data; > typedef struct krb5_pac_data *krb5_pac; >+typedef const struct krb5_pac_data *krb5_const_pac; > > typedef struct krb5_rd_req_in_ctx_data *krb5_rd_req_in_ctx; > typedef struct krb5_rd_req_out_ctx_data *krb5_rd_req_out_ctx; >@@ -122,55 +123,53 @@ typedef struct krb5_enc_data { > } krb5_enc_data; > > /* alternative names */ >-enum { >- ENCTYPE_NULL = KRB5_ENCTYPE_NULL, >- ENCTYPE_DES_CBC_CRC = KRB5_ENCTYPE_DES_CBC_CRC, >- ENCTYPE_DES_CBC_MD4 = KRB5_ENCTYPE_DES_CBC_MD4, >- ENCTYPE_DES_CBC_MD5 = KRB5_ENCTYPE_DES_CBC_MD5, >- ENCTYPE_DES3_CBC_MD5 = KRB5_ENCTYPE_DES3_CBC_MD5, >- ENCTYPE_OLD_DES3_CBC_SHA1 = KRB5_ENCTYPE_OLD_DES3_CBC_SHA1, >- ENCTYPE_SIGN_DSA_GENERATE = KRB5_ENCTYPE_SIGN_DSA_GENERATE, >- ENCTYPE_ENCRYPT_RSA_PRIV = KRB5_ENCTYPE_ENCRYPT_RSA_PRIV, >- ENCTYPE_ENCRYPT_RSA_PUB = KRB5_ENCTYPE_ENCRYPT_RSA_PUB, >- ENCTYPE_DES3_CBC_SHA1 = KRB5_ENCTYPE_DES3_CBC_SHA1, >- ENCTYPE_AES128_CTS_HMAC_SHA1_96 = KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96, >- ENCTYPE_AES256_CTS_HMAC_SHA1_96 = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96, >- ENCTYPE_ARCFOUR_HMAC = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5, >- ENCTYPE_ARCFOUR_HMAC_MD5 = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5, >- ENCTYPE_ARCFOUR_HMAC_MD5_56 = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56, >- ENCTYPE_ENCTYPE_PK_CROSS = KRB5_ENCTYPE_ENCTYPE_PK_CROSS, >- ENCTYPE_DES_CBC_NONE = KRB5_ENCTYPE_DES_CBC_NONE, >- ENCTYPE_DES3_CBC_NONE = KRB5_ENCTYPE_DES3_CBC_NONE, >- ENCTYPE_DES_CFB64_NONE = KRB5_ENCTYPE_DES_CFB64_NONE, >- ENCTYPE_DES_PCBC_NONE = KRB5_ENCTYPE_DES_PCBC_NONE, >- ETYPE_NULL = KRB5_ENCTYPE_NULL, >- ETYPE_DES_CBC_CRC = KRB5_ENCTYPE_DES_CBC_CRC, >- ETYPE_DES_CBC_MD4 = KRB5_ENCTYPE_DES_CBC_MD4, >- ETYPE_DES_CBC_MD5 = KRB5_ENCTYPE_DES_CBC_MD5, >- ETYPE_DES3_CBC_MD5 = KRB5_ENCTYPE_DES3_CBC_MD5, >- ETYPE_OLD_DES3_CBC_SHA1 = KRB5_ENCTYPE_OLD_DES3_CBC_SHA1, >- ETYPE_SIGN_DSA_GENERATE = KRB5_ENCTYPE_SIGN_DSA_GENERATE, >- ETYPE_ENCRYPT_RSA_PRIV = KRB5_ENCTYPE_ENCRYPT_RSA_PRIV, >- ETYPE_ENCRYPT_RSA_PUB = KRB5_ENCTYPE_ENCRYPT_RSA_PUB, >- ETYPE_DES3_CBC_SHA1 = KRB5_ENCTYPE_DES3_CBC_SHA1, >- ETYPE_AES128_CTS_HMAC_SHA1_96 = KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96, >- ETYPE_AES256_CTS_HMAC_SHA1_96 = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96, >- ETYPE_AES128_CTS_HMAC_SHA256_128 = KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128, >- ETYPE_AES256_CTS_HMAC_SHA384_192 = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192, >- ETYPE_ARCFOUR_HMAC_MD5 = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5, >- ETYPE_ARCFOUR_HMAC_MD5_56 = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56, >- ETYPE_ENCTYPE_PK_CROSS = KRB5_ENCTYPE_ENCTYPE_PK_CROSS, >- ETYPE_ARCFOUR_MD4 = KRB5_ENCTYPE_ARCFOUR_MD4, >- ETYPE_ARCFOUR_HMAC_OLD = KRB5_ENCTYPE_ARCFOUR_HMAC_OLD, >- ETYPE_ARCFOUR_HMAC_OLD_EXP = KRB5_ENCTYPE_ARCFOUR_HMAC_OLD_EXP, >- ETYPE_DES_CBC_NONE = KRB5_ENCTYPE_DES_CBC_NONE, >- ETYPE_DES3_CBC_NONE = KRB5_ENCTYPE_DES3_CBC_NONE, >- ETYPE_DES_CFB64_NONE = KRB5_ENCTYPE_DES_CFB64_NONE, >- ETYPE_DES_PCBC_NONE = KRB5_ENCTYPE_DES_PCBC_NONE, >- ETYPE_DIGEST_MD5_NONE = KRB5_ENCTYPE_DIGEST_MD5_NONE, >- ETYPE_CRAM_MD5_NONE = KRB5_ENCTYPE_CRAM_MD5_NONE >- >-}; >+#define ENCTYPE_NULL KRB5_ENCTYPE_NULL >+#define ENCTYPE_DES_CBC_CRC KRB5_ENCTYPE_DES_CBC_CRC >+#define ENCTYPE_DES_CBC_MD4 KRB5_ENCTYPE_DES_CBC_MD4 >+#define ENCTYPE_DES_CBC_MD5 KRB5_ENCTYPE_DES_CBC_MD5 >+#define ENCTYPE_DES3_CBC_MD5 KRB5_ENCTYPE_DES3_CBC_MD5 >+#define ENCTYPE_OLD_DES3_CBC_SHA1 KRB5_ENCTYPE_OLD_DES3_CBC_SHA1 >+#define ENCTYPE_SIGN_DSA_GENERATE KRB5_ENCTYPE_SIGN_DSA_GENERATE >+#define ENCTYPE_ENCRYPT_RSA_PRIV KRB5_ENCTYPE_ENCRYPT_RSA_PRIV >+#define ENCTYPE_ENCRYPT_RSA_PUB KRB5_ENCTYPE_ENCRYPT_RSA_PUB >+#define ENCTYPE_DES3_CBC_SHA1 KRB5_ENCTYPE_DES3_CBC_SHA1 >+#define ENCTYPE_AES128_CTS_HMAC_SHA1_96 KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96 >+#define ENCTYPE_AES256_CTS_HMAC_SHA1_96 KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96 >+#define ENCTYPE_ARCFOUR_HMAC KRB5_ENCTYPE_ARCFOUR_HMAC_MD5 >+#define ENCTYPE_ARCFOUR_HMAC_MD5 KRB5_ENCTYPE_ARCFOUR_HMAC_MD5 >+#define ENCTYPE_ARCFOUR_HMAC_MD5_56 KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56 >+#define ENCTYPE_ENCTYPE_PK_CROSS KRB5_ENCTYPE_ENCTYPE_PK_CROSS >+#define ENCTYPE_DES_CBC_NONE KRB5_ENCTYPE_DES_CBC_NONE >+#define ENCTYPE_DES3_CBC_NONE KRB5_ENCTYPE_DES3_CBC_NONE >+#define ENCTYPE_DES_CFB64_NONE KRB5_ENCTYPE_DES_CFB64_NONE >+#define ENCTYPE_DES_PCBC_NONE KRB5_ENCTYPE_DES_PCBC_NONE >+#define ETYPE_NULL KRB5_ENCTYPE_NULL >+#define ETYPE_DES_CBC_CRC KRB5_ENCTYPE_DES_CBC_CRC >+#define ETYPE_DES_CBC_MD4 KRB5_ENCTYPE_DES_CBC_MD4 >+#define ETYPE_DES_CBC_MD5 KRB5_ENCTYPE_DES_CBC_MD5 >+#define ETYPE_DES3_CBC_MD5 KRB5_ENCTYPE_DES3_CBC_MD5 >+#define ETYPE_OLD_DES3_CBC_SHA1 KRB5_ENCTYPE_OLD_DES3_CBC_SHA1 >+#define ETYPE_SIGN_DSA_GENERATE KRB5_ENCTYPE_SIGN_DSA_GENERATE >+#define ETYPE_ENCRYPT_RSA_PRIV KRB5_ENCTYPE_ENCRYPT_RSA_PRIV >+#define ETYPE_ENCRYPT_RSA_PUB KRB5_ENCTYPE_ENCRYPT_RSA_PUB >+#define ETYPE_DES3_CBC_SHA1 KRB5_ENCTYPE_DES3_CBC_SHA1 >+#define ETYPE_AES128_CTS_HMAC_SHA1_96 KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96 >+#define ETYPE_AES256_CTS_HMAC_SHA1_96 KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96 >+#define ETYPE_AES128_CTS_HMAC_SHA256_128 KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128 >+#define ETYPE_AES256_CTS_HMAC_SHA384_192 KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192 >+#define ETYPE_ARCFOUR_HMAC_MD5 KRB5_ENCTYPE_ARCFOUR_HMAC_MD5 >+#define ETYPE_ARCFOUR_HMAC_MD5_56 KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56 >+#define ETYPE_ENCTYPE_PK_CROSS KRB5_ENCTYPE_ENCTYPE_PK_CROSS >+#define ETYPE_ARCFOUR_MD4 KRB5_ENCTYPE_ARCFOUR_MD4 >+#define ETYPE_ARCFOUR_HMAC_OLD KRB5_ENCTYPE_ARCFOUR_HMAC_OLD >+#define ETYPE_ARCFOUR_HMAC_OLD_EXP KRB5_ENCTYPE_ARCFOUR_HMAC_OLD_EXP >+#define ETYPE_DES_CBC_NONE KRB5_ENCTYPE_DES_CBC_NONE >+#define ETYPE_DES3_CBC_NONE KRB5_ENCTYPE_DES3_CBC_NONE >+#define ETYPE_DES_CFB64_NONE KRB5_ENCTYPE_DES_CFB64_NONE >+#define ETYPE_DES_PCBC_NONE KRB5_ENCTYPE_DES_PCBC_NONE >+#define ETYPE_DIGEST_MD5_NONE KRB5_ENCTYPE_DIGEST_MD5_NONE >+#define ETYPE_CRAM_MD5_NONE KRB5_ENCTYPE_CRAM_MD5_NONE >+#define DOMAIN_X500_COMPRESS domain_X500_Compress > > /* PDU types */ > typedef enum krb5_pdu { >@@ -1043,5 +1042,24 @@ extern KRB5_LIB_VARIABLE const char *krb5_cc_type_scc; > extern KRB5_LIB_VARIABLE const char *krb5_cc_type_dcc; > extern KRB5_LIB_VARIABLE const char *krb5_cc_type_keyring; > >+/* clang analyzer workarounds */ >+ >+#ifdef __clang_analyzer__ >+/* >+ * The clang analyzer (lint) can't know that krb5_enomem() always returns >+ * non-zero, so code like: >+ * >+ * if ((x = malloc(...)) == NULL) >+ * ret = krb5_enomem(context) >+ * if (ret == 0) >+ * *x = ...; >+ * >+ * causes false positives. >+ * >+ * The fix is to make krb5_enomem() a macro that always evaluates to ENOMEM. >+ */ >+#define krb5_enomem(c) (krb5_enomem(c), ENOMEM) >+#endif >+ > #endif /* __KRB5_H__ */ > >diff --git a/third_party/heimdal/lib/krb5/krb5_locl.h b/third_party/heimdal/lib/krb5/krb5_locl.h >index 6b74653f565b..7045c5bb6016 100644 >--- a/third_party/heimdal/lib/krb5/krb5_locl.h >+++ b/third_party/heimdal/lib/krb5/krb5_locl.h >@@ -87,8 +87,10 @@ struct mbuf; > > #ifdef LIBINTL > #include <libintl.h> >+#undef N_ > #define N_(x,y) dgettext(HEIMDAL_TEXTDOMAIN, x) > #else >+#undef N_ > #define N_(x,y) (x) > #define bindtextdomain(package, localedir) > #endif >diff --git a/third_party/heimdal/lib/krb5/krbhst-test.c b/third_party/heimdal/lib/krb5/krbhst-test.c >index 873734fce77a..cd388ecfaaa0 100644 >--- a/third_party/heimdal/lib/krb5/krbhst-test.c >+++ b/third_party/heimdal/lib/krb5/krbhst-test.c >@@ -59,6 +59,7 @@ usage (int ret) > int > main(int argc, char **argv) > { >+ krb5_error_code ret; > int i, j; > krb5_context context; > int types[] = {KRB5_KRBHST_KDC, KRB5_KRBHST_ADMIN, KRB5_KRBHST_CHANGEPW, >@@ -82,7 +83,9 @@ main(int argc, char **argv) > argc -= optidx; > argv += optidx; > >- krb5_init_context (&context); >+ ret = krb5_init_context(&context); >+ if (ret) >+ krb5_err(NULL, 1, ret, "Failed to initialize context"); > for(i = 0; i < argc; i++) { > krb5_krbhst_handle handle; > char host[MAXHOSTNAMELEN]; >@@ -90,12 +93,16 @@ main(int argc, char **argv) > for (j = 0; j < sizeof(types)/sizeof(*types); ++j) { > printf ("%s for %s:\n", type_str[j], argv[i]); > >- krb5_krbhst_init(context, argv[i], types[j], &handle); >- while(krb5_krbhst_next_as_string(context, handle, >- host, sizeof(host)) == 0) >+ ret = krb5_krbhst_init(context, argv[i], types[j], &handle); >+ if (ret) >+ krb5_err(context, 1, ret, "Could not init krbhst iterator"); >+ while ((ret = krb5_krbhst_next_as_string(context, handle, host, >+ sizeof(host))) == 0) > printf("\thost: %s\n", host); > krb5_krbhst_reset(context, handle); >- printf ("\n"); >+ printf("\n"); >+ if (ret) >+ krb5_err(context, 1, ret, "Could not iterate all krbhst"); > } > } > return 0; >diff --git a/third_party/heimdal/lib/krb5/krbhst.c b/third_party/heimdal/lib/krb5/krbhst.c >index adb8e00e6dc8..3688d6ad7ce9 100644 >--- a/third_party/heimdal/lib/krb5/krbhst.c >+++ b/third_party/heimdal/lib/krb5/krbhst.c >@@ -107,8 +107,24 @@ srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count, > } > > for(num_srv = 0, rr = r->head; rr; rr = rr->next) >- if(rr->type == rk_ns_t_srv) >+ if(rr->type == rk_ns_t_srv) { >+ if (num_srv >= INT_MAX) { >+ rk_dns_free_data(r); >+ return KRB5_KDC_UNREACH; >+ } >+ if (num_srv >= SIZE_MAX / sizeof(**res)) { >+ rk_dns_free_data(r); >+ return KRB5_KDC_UNREACH; >+ } > num_srv++; >+ } >+ >+ if (num_srv == 0) { >+ _krb5_debug(context, 0, >+ "DNS SRV RR lookup domain nodata: %s", domain); >+ rk_dns_free_data(r); >+ return KRB5_KDC_UNREACH; >+ } > > *res = malloc(num_srv * sizeof(**res)); > if(*res == NULL) { >@@ -431,7 +447,7 @@ krb5_krbhst_get_addrinfo(krb5_context context, krb5_krbhst_info *host, > static krb5_boolean > get_next(struct krb5_krbhst_data *kd, krb5_krbhst_info **host) > { >- struct krb5_krbhst_info *hi = *kd->index; >+ struct krb5_krbhst_info *hi = kd ? *kd->index : NULL; > if(hi != NULL) { > *host = hi; > kd->index = &(*kd->index)->next; >@@ -555,6 +571,7 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, > "Realm %s needs immediate attention " > "see https://icann.org/namecollision", > kd->realm); >+ freeaddrinfo(ai); > return KRB5_KDC_UNREACH; > } > } >@@ -563,6 +580,7 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, > hi = calloc(1, sizeof(*hi) + hostlen); > if(hi == NULL) { > free(host); >+ freeaddrinfo(ai); > return krb5_enomem(context); > } > >@@ -920,7 +938,7 @@ kpasswd_get_next(krb5_context context, > return KRB5_KDC_UNREACH; > } > >-static void >+static void KRB5_CALLCONV > krbhost_dealloc(void *ptr) > { > struct krb5_krbhst_data *handle = (struct krb5_krbhst_data *)ptr; >diff --git a/third_party/heimdal/lib/krb5/krcache.c b/third_party/heimdal/lib/krb5/krcache.c >index dbf81850ea34..9e992216153d 100644 >--- a/third_party/heimdal/lib/krb5/krcache.c >+++ b/third_party/heimdal/lib/krb5/krcache.c >@@ -367,6 +367,9 @@ parse_residual(krb5_context context, > *pcollection_name = NULL; > *psubsidiary_name = NULL; > >+ if (residual == NULL) >+ residual = ""; >+ > /* Parse out the anchor name. Use the legacy anchor if not present. */ > sep = strchr(residual, ':'); > if (sep == NULL) { >@@ -473,7 +476,7 @@ make_subsidiary_residual(krb5_context context, > char **presidual) > { > if (asprintf(presidual, "%s:%s:%s", anchor_name, collection_name, >- subsidiary_name) < 0) { >+ subsidiary_name ? subsidiary_name : "tkt") < 0) { > *presidual = NULL; > return krb5_enomem(context); > } >@@ -498,6 +501,9 @@ get_collection(krb5_context context, > > heim_base_atomic_init(pcollection_id, 0); > >+ if (!anchor_name || !collection_name) >+ return KRB5_KCC_INVALID_ANCHOR; >+ > if (strcmp(anchor_name, KRCC_PERSISTENT_ANCHOR) == 0) { > /* > * The collection name is a uid (or empty for the current effective >@@ -1262,7 +1268,7 @@ alloc_cache(krb5_context context, > subsidiary_name, &data->krc_name); > if (ret || > (data->krc_collection = strdup(collection_name)) == NULL || >- (data->krc_subsidiary = strdup(subsidiary_name)) == NULL) { >+ (data->krc_subsidiary = strdup(subsidiary_name ? subsidiary_name : "tkt")) == NULL) { > if (data) { > free(data->krc_collection); > free(data->krc_name); >@@ -1702,7 +1708,7 @@ krcc_get_kdc_offset(krb5_context context, > key_serial_t key, cache_id; > krb5_storage *sp = NULL; > krb5_data payload; >- int32_t sec_offset, usec_offset; >+ int32_t sec_offset = 0; > > if (data == NULL) > return krb5_einval(context, 2); >@@ -1730,26 +1736,22 @@ krcc_get_kdc_offset(krb5_context context, > > sp = krb5_storage_from_data(&payload); > if (sp == NULL) { >- ret = KRB5_CC_IO; >+ ret = krb5_enomem(context);; > goto cleanup; > } > > krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); > > ret = krb5_ret_int32(sp, &sec_offset); >- if (ret == 0) >- krb5_ret_int32(sp, &usec_offset); >- if (ret) { >- ret = KRB5_CC_END; >- goto cleanup; >- } >- >- *offset = sec_offset; >+ /* >+ * We can't output nor use the usec_offset here, so we don't bother to read >+ * it, though we do write it. >+ */ > > cleanup: >+ *offset = sec_offset; > krb5_storage_free(sp); > krb5_data_free(&payload); >- > return ret; > } > >@@ -1887,7 +1889,8 @@ krcc_get_cache_next(krb5_context context, > continue; > > /* Don't repeat the primary cache. */ >- if (strcmp(subsidiary_name, iter->primary_name) == 0) >+ if (iter->primary_name && >+ strcmp(subsidiary_name, iter->primary_name) == 0) > continue; > > /* We found a valid key */ >diff --git a/third_party/heimdal/lib/krb5/kx509.c b/third_party/heimdal/lib/krb5/kx509.c >index bd5991fcbf81..7525739f66ca 100644 >--- a/third_party/heimdal/lib/krb5/kx509.c >+++ b/third_party/heimdal/lib/krb5/kx509.c >@@ -376,10 +376,13 @@ load_priv_key(krb5_context context, > ret = ENOENT; > if (ret == 0) > kx509_ctx->priv_key = _hx509_private_key_ref(keys[0]); >- if (ret) >+ if (ret) { >+ char *emsg = hx509_get_error_string(context->hx509ctx, ret); >+ > krb5_set_error_message(context, ret, "Could not load private key " >- "from %s for kx509: %s", fn, >- hx509_get_error_string(context->hx509ctx, ret)); >+ "from %s for kx509: %s", fn, emsg); >+ hx509_free_error_string(emsg); >+ } > hx509_certs_free(&certs); > return ret; > } >@@ -443,10 +446,13 @@ gen_priv_key(krb5_context context, > if (ret == 0) > ret = _hx509_generate_private_key(context->hx509ctx, key_gen_ctx, key); > _hx509_generate_private_key_free(&key_gen_ctx); >- if (ret) >+ if (ret) { >+ char *emsg = hx509_get_error_string(context->hx509ctx, ret); >+ > krb5_set_error_message(context, ret, >- "Could not generate a private key: %s", >- hx509_get_error_string(context->hx509ctx, ret)); >+ "Could not generate a private key: %s", emsg); >+ hx509_free_error_string(emsg); >+ } > return ret; > } > >@@ -848,21 +854,28 @@ mk_kx509_req(krb5_context context, > > /* Add the the key and HMAC to the message */ > HMAC_CTX_init(&ctx); >- HMAC_Init_ex(&ctx, kx509_ctx->hmac_key->keyvalue.data, >- kx509_ctx->hmac_key->keyvalue.length, EVP_sha1(), NULL); >- HMAC_Update(&ctx, version_2_0, sizeof(version_2_0)); >- if (private_key || kx509_ctx->given_csr.data) { >- HMAC_Update(&ctx, kx509_req.pk_key.data, kx509_req.pk_key.length); >+ if (HMAC_Init_ex(&ctx, kx509_ctx->hmac_key->keyvalue.data, >+ kx509_ctx->hmac_key->keyvalue.length, >+ EVP_sha1(), NULL) == 0) { >+ HMAC_CTX_cleanup(&ctx); >+ ret = krb5_enomem(context); > } else { >- /* Probe */ >- HMAC_Update(&ctx, kx509_req.authenticator.data, kx509_req.authenticator.length); >+ HMAC_Update(&ctx, version_2_0, sizeof(version_2_0)); >+ if (private_key || kx509_ctx->given_csr.data) { >+ HMAC_Update(&ctx, kx509_req.pk_key.data, kx509_req.pk_key.length); >+ } else { >+ /* Probe */ >+ HMAC_Update(&ctx, kx509_req.authenticator.data, kx509_req.authenticator.length); >+ } >+ HMAC_Final(&ctx, kx509_req.pk_hash.data, 0); >+ HMAC_CTX_cleanup(&ctx); > } >- HMAC_Final(&ctx, kx509_req.pk_hash.data, 0); >- HMAC_CTX_cleanup(&ctx); > > /* Encode the message, prefix `version_2_0', output the result */ >- ASN1_MALLOC_ENCODE(Kx509Request, pre_req.data, pre_req.length, &kx509_req, &len, ret); >- ret = krb5_data_alloc(req, pre_req.length + sizeof(version_2_0)); >+ if (ret == 0) >+ ASN1_MALLOC_ENCODE(Kx509Request, pre_req.data, pre_req.length, &kx509_req, &len, ret); >+ if (ret == 0) >+ ret = krb5_data_alloc(req, pre_req.length + sizeof(version_2_0)); > if (ret == 0) { > memcpy(req->data, version_2_0, sizeof(version_2_0)); > memcpy(((unsigned char *)req->data) + sizeof(version_2_0), >@@ -984,8 +997,13 @@ rd_kx509_resp(krb5_context context, > } > > HMAC_CTX_init(&ctx); >- HMAC_Init_ex(&ctx, kx509_ctx->hmac_key->keyvalue.data, >- kx509_ctx->hmac_key->keyvalue.length, EVP_sha1(), NULL); >+ if (HMAC_Init_ex(&ctx, kx509_ctx->hmac_key->keyvalue.data, >+ kx509_ctx->hmac_key->keyvalue.length, EVP_sha1(), NULL) == 0) { >+ free_Kx509Response(&r); >+ HMAC_CTX_cleanup(&ctx); >+ return krb5_enomem(context); >+ } >+ > HMAC_Update(&ctx, version_2_0, sizeof(version_2_0)); > > { >@@ -1090,7 +1108,7 @@ rd_kx509_resp(krb5_context context, > ret = errno; > } > free_Kx509Response(&r); >- if (cert) { >+ if (*cert) { > heim_release(herr); > return 0; > } >@@ -1250,7 +1268,9 @@ krb5_kx509(krb5_context context, krb5_ccache cc, const char *realm) > char *store_exp = NULL; > > ret = krb5_kx509_ctx_init(context, &kx509_ctx); >- if (ret == 0 && realm) >+ if (ret) >+ return ret; >+ if (realm) > ret = krb5_kx509_ctx_set_realm(context, kx509_ctx, realm); > > /* >diff --git a/third_party/heimdal/lib/krb5/libkrb5-exports.def.in b/third_party/heimdal/lib/krb5/libkrb5-exports.def.in >index 245f4b1bf437..191a0c48c861 100644 >--- a/third_party/heimdal/lib/krb5/libkrb5-exports.def.in >+++ b/third_party/heimdal/lib/krb5/libkrb5-exports.def.in >@@ -23,6 +23,8 @@ EXPORTS > krb5_appdefault_time > krb5_append_addresses > krb5_auth_con_addflags >+ krb5_auth_con_add_AuthorizationData >+ krb5_auth_con_add_AuthorizationDataIfRelevant > krb5_auth_con_free > krb5_auth_con_genaddrs > krb5_auth_con_generatelocalsubkey >@@ -500,6 +502,7 @@ EXPORTS > krb5_pac_add_buffer > krb5_pac_free > krb5_pac_get_buffer >+ _krb5_pac_get_buffer_by_name > krb5_pac_get_kdc_checksum_info > krb5_pac_get_types > krb5_pac_init >@@ -747,6 +750,7 @@ EXPORTS > krb5_cccol_cursor_new > krb5_cccol_cursor_next > krb5_cccol_cursor_free >+ krb5_cccol_get_default_ccname > > ; com_err error tables > initialize_krb5_error_table_r >@@ -837,6 +841,8 @@ EXPORTS > _krb5_enctype_requires_random_salt > _krb5_principal2principalname > _krb5_principalname2krb5_principal >+ _krb5_kdcrep2krb5_principal >+ _krb5_ticket2krb5_principal > _krb5_put_int > _krb5_s4u2self_to_checksumdata > _krb5_HMAC_MD5_checksum >@@ -857,6 +863,7 @@ EXPORTS > krb5_init_creds_get_error > krb5_init_creds_init > krb5_init_creds_set_fast_anon_pkinit >+ _krb5_init_creds_set_fast_anon_pkinit_optimistic > krb5_init_creds_set_fast_ccache > krb5_init_creds_set_keytab > krb5_init_creds_set_kdc_hostname >diff --git a/third_party/heimdal/lib/krb5/mcache.c b/third_party/heimdal/lib/krb5/mcache.c >index 4ccc415a2619..fdd5674c3b87 100644 >--- a/third_party/heimdal/lib/krb5/mcache.c >+++ b/third_party/heimdal/lib/krb5/mcache.c >@@ -112,10 +112,10 @@ again: > if (strcmp(m->name, m_c->name) == 0) > break; > if (m_c) { >- free(m->name); >- free(m); > if (name && !create_anonymous) { > /* We raced with another thread to create this cache */ >+ free(m->name); >+ free(m); > m = m_c; > HEIMDAL_MUTEX_lock(&(m->mutex)); > m->refcnt++; >diff --git a/third_party/heimdal/lib/krb5/mk_cred.c b/third_party/heimdal/lib/krb5/mk_cred.c >index 33e62e5b0d26..41e858f80588 100644 >--- a/third_party/heimdal/lib/krb5/mk_cred.c >+++ b/third_party/heimdal/lib/krb5/mk_cred.c >@@ -258,15 +258,16 @@ _krb5_mk_ncred(krb5_context context, > */ > > ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto); >+ if (ret == 0) >+ ret = krb5_encrypt_EncryptedData(context, >+ crypto, >+ KRB5_KU_KRB_CRED, >+ buf, >+ len, >+ 0, >+ &cred.enc_part); > if (ret) > goto out; >- ret = krb5_encrypt_EncryptedData(context, >- crypto, >- KRB5_KU_KRB_CRED, >- buf, >- len, >- 0, >- &cred.enc_part); > DISOWN_BUF(buf); > krb5_crypto_destroy(context, crypto); > } >diff --git a/third_party/heimdal/lib/krb5/pac.c b/third_party/heimdal/lib/krb5/pac.c >index cd9a6d6d3107..2bdeae8ecd1d 100644 >--- a/third_party/heimdal/lib/krb5/pac.c >+++ b/third_party/heimdal/lib/krb5/pac.c >@@ -32,7 +32,10 @@ > */ > > #include "krb5_locl.h" >+ >+#include <heimbasepriv.h> > #include <wind.h> >+#include <assert.h> > > struct PAC_INFO_BUFFER { > uint32_t type; >@@ -73,6 +76,8 @@ struct krb5_pac_data { > #define PACTYPE_SIZE 8 > #define PAC_INFO_BUFFER_SIZE 16 > >+#define PAC_LOGON_INFO 1 >+#define PAC_CREDENTIALS_INFO 2 > #define PAC_SERVER_CHECKSUM 6 > #define PAC_PRIVSVR_CHECKSUM 7 > #define PAC_LOGON_NAME 10 >@@ -94,7 +99,39 @@ struct krb5_pac_data { > } \ > } while(0) > >-static const char zeros[PAC_ALIGNMENT] = { 0 }; >+static const char zeros[PAC_ALIGNMENT]; >+ >+static void HEIM_CALLCONV >+pac_dealloc(void *ctx) >+{ >+ krb5_pac pac = (krb5_pac)ctx; >+ >+ krb5_data_free(&pac->data); >+ krb5_data_free(&pac->ticket_sign_data); >+ >+ if (pac->upn_princ) { >+ free_Principal(pac->upn_princ); >+ free(pac->upn_princ); >+ } >+ if (pac->canon_princ) { >+ free_Principal(pac->canon_princ); >+ free(pac->canon_princ); >+ } >+ krb5_data_free(&pac->sid); >+ >+ free(pac->pac); >+} >+ >+struct heim_type_data pac_object = { >+ HEIM_TID_PAC, >+ "heim-pac", >+ NULL, >+ pac_dealloc, >+ NULL, >+ NULL, >+ NULL, >+ NULL >+}; > > /* > * HMAC-MD5 checksum over any key (needed for the PAC routines) >@@ -152,7 +189,7 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, > krb5_storage *sp = NULL; > uint32_t i, tmp, tmp2, header_end; > >- p = calloc(1, sizeof(*p)); >+ p = _heim_alloc_object(&pac_object, sizeof(*p)); > if (p == NULL) { > ret = krb5_enomem(context); > goto out; >@@ -302,7 +339,7 @@ out: > if (p) { > if (p->pac) > free(p->pac); >- free(p); >+ krb5_pac_free(context, p); > } > *pac = NULL; > >@@ -315,21 +352,21 @@ krb5_pac_init(krb5_context context, krb5_pac *pac) > krb5_error_code ret; > krb5_pac p; > >- p = calloc(1, sizeof(*p)); >+ p = _heim_alloc_object(&pac_object, sizeof(*p)); > if (p == NULL) { > return krb5_enomem(context); > } > > p->pac = calloc(1, sizeof(*p->pac)); > if (p->pac == NULL) { >- free(p); >+ krb5_pac_free(context, p); > return krb5_enomem(context); > } > > ret = krb5_data_alloc(&p->data, PACTYPE_SIZE); > if (ret) { > free (p->pac); >- free(p); >+ krb5_pac_free(context, p); > return krb5_enomem(context); > } > >@@ -346,6 +383,8 @@ krb5_pac_add_buffer(krb5_context context, krb5_pac p, > size_t len, offset, header_end, old_end; > uint32_t i; > >+ assert(data->length > 0 && data->data != NULL); >+ > len = p->pac->numbuffers; > > ptr = realloc(p->pac, >@@ -394,9 +433,8 @@ krb5_pac_add_buffer(krb5_context context, krb5_pac p, > * copy in new data part > */ > >- if (data->data != NULL) >- memcpy((unsigned char *)p->data.data + offset, >- data->data, data->length); >+ memcpy((unsigned char *)p->data.data + offset, >+ data->data, data->length); > memset((unsigned char *)p->data.data + offset + data->length, > 0, p->data.length - offset - data->length); > >@@ -433,11 +471,14 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p, > if (p->pac->buffers[i].type != type) > continue; > >- ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len); >- if (ret) { >- krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); >- return ret; >+ if (data) { >+ ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len); >+ if (ret) { >+ krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); >+ return ret; >+ } > } >+ > return 0; > } > krb5_set_error_message(context, ENOENT, "No PAC buffer of type %lu was found", >@@ -445,6 +486,45 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p, > return ENOENT; > } > >+static struct { >+ uint32_t type; >+ krb5_data name; >+} pac_buffer_name_map[] = { >+#define PAC_MAP_ENTRY(type, name) { PAC_##type, { sizeof(name) - 1, name } } >+ PAC_MAP_ENTRY(LOGON_INFO, "logon-info" ), >+ PAC_MAP_ENTRY(CREDENTIALS_INFO, "credentials-info" ), >+ PAC_MAP_ENTRY(SERVER_CHECKSUM, "server-checksum" ), >+ PAC_MAP_ENTRY(PRIVSVR_CHECKSUM, "privsvr-checksum" ), >+ PAC_MAP_ENTRY(LOGON_NAME, "client-info" ), >+ PAC_MAP_ENTRY(CONSTRAINED_DELEGATION, "delegation-info" ), >+ PAC_MAP_ENTRY(UPN_DNS_INFO, "upn-dns-info" ), >+ PAC_MAP_ENTRY(TICKET_CHECKSUM, "ticket-checksum" ), >+ PAC_MAP_ENTRY(ATTRIBUTES_INFO, "attributes-info" ), >+ PAC_MAP_ENTRY(REQUESTOR_SID, "requestor-sid" ) >+}; >+ >+/* >+ * >+ */ >+ >+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL >+_krb5_pac_get_buffer_by_name(krb5_context context, krb5_pac p, >+ const krb5_data *name, krb5_data *data) >+{ >+ size_t i; >+ >+ for (i = 0; >+ i < sizeof(pac_buffer_name_map) / sizeof(pac_buffer_name_map[0]); >+ i++) { >+ if (krb5_data_cmp(name, &pac_buffer_name_map[i].name) == 0) >+ return krb5_pac_get_buffer(context, p, pac_buffer_name_map[i].type, data); >+ } >+ >+ krb5_set_error_message(context, ENOENT, "No PAC buffer with name %.*s was found", >+ (int)name->length, (char *)name->data); >+ return ENOENT; >+} >+ > /* > * > */ >@@ -476,17 +556,7 @@ krb5_pac_get_types(krb5_context context, > KRB5_LIB_FUNCTION void KRB5_LIB_CALL > krb5_pac_free(krb5_context context, krb5_pac pac) > { >- if (pac == NULL) >- return; >- krb5_data_free(&pac->data); >- krb5_data_free(&pac->ticket_sign_data); >- >- krb5_free_principal(context, pac->upn_princ); >- krb5_free_principal(context, pac->canon_princ); >- krb5_data_free(&pac->sid); >- >- free(pac->pac); >- free(pac); >+ heim_release(pac); > } > > /* >@@ -889,7 +959,7 @@ build_logon_name(krb5_context context, > krb5_error_code ret; > krb5_storage *sp; > uint64_t t; >- char *s, *s2; >+ char *s, *s2 = NULL; > size_t s2_len; > > t = unix2nttime(authtime); >@@ -936,7 +1006,7 @@ build_logon_name(krb5_context context, > krb5_set_error_message(context, ret, "Principal %s is not valid UTF-8", s); > free(s); > return ret; >- } else >+ } else > free(s); > > s2_len = (ucs2_len + 1) * 2; >@@ -965,18 +1035,14 @@ build_logon_name(krb5_context context, > CHECK(ret, krb5_store_uint16(sp, s2_len), out); > > ret = krb5_storage_write(sp, s2, s2_len); >- free(s2); > if (ret != (int)s2_len) { > ret = krb5_enomem(context); > goto out; > } > ret = krb5_storage_to_data(sp, logon); >- if (ret) >- goto out; >- krb5_storage_free(sp); > >- return 0; >-out: >+ out: >+ free(s2); > krb5_storage_free(sp); > return ret; > } >@@ -1350,10 +1416,8 @@ _krb5_pac_sign(krb5_context context, > if (ret == 0) { > krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); > spdata = krb5_storage_emem(); >- if (spdata == NULL) { >- krb5_storage_free(sp); >+ if (spdata == NULL) > ret = krb5_enomem(context); >- } > } > > if (ret) >@@ -1472,7 +1536,8 @@ _krb5_pac_sign(krb5_context context, > krb5_storage *rs = krb5_storage_emem(); > if (rs == NULL) > ret = krb5_enomem(context); >- krb5_storage_set_flags(rs, KRB5_STORAGE_BYTEORDER_LE); >+ else >+ krb5_storage_set_flags(rs, KRB5_STORAGE_BYTEORDER_LE); > if (ret == 0) > ret = krb5_store_uint16(rs, rodc_id); > if (ret == 0) >diff --git a/third_party/heimdal/lib/krb5/pkinit.c b/third_party/heimdal/lib/krb5/pkinit.c >index 0198400d9eb1..c9a6e3e8f8b9 100644 >--- a/third_party/heimdal/lib/krb5/pkinit.c >+++ b/third_party/heimdal/lib/krb5/pkinit.c >@@ -114,6 +114,14 @@ select_dh_group(krb5_context context, DH *dh, unsigned long bits, > { > const struct krb5_dh_moduli *m; > >+ if (moduli[0] == NULL) { >+ krb5_set_error_message(context, EINVAL, >+ N_("Did not find a DH group parameter " >+ "matching requirement of %lu bits", ""), >+ bits); >+ return EINVAL; >+ } >+ > if (bits == 0) { > m = moduli[1]; /* XXX */ > if (m == NULL) >@@ -1198,11 +1206,13 @@ pk_rd_pa_reply_enckey(krb5_context context, > &contentType, > &unwrapped, > &host); >+ if (ret == 0) { >+ krb5_data_free(&content); >+ ret = krb5_data_copy(&content, unwrapped.data, unwrapped.length); >+ der_free_octet_string(&unwrapped); >+ } > if (ret) > goto out; >- krb5_data_free(&content); >- ret = krb5_data_copy(&content, unwrapped.data, unwrapped.length); >- der_free_octet_string(&unwrapped); > > heim_assert(host || (ctx->id->flags & PKINIT_NO_KDC_ANCHOR), > "KDC signature must be verified unless PKINIT_NO_KDC_ANCHOR set"); >@@ -1831,7 +1841,7 @@ _krb5_pk_set_user_id(krb5_context context, > ret = der_print_hex_heim_integer(&i, &sn); > der_free_heim_integer(&i); > if (ret) { >- free(name); >+ free(str); > goto out; > } > >@@ -1857,7 +1867,7 @@ _krb5_pk_load_id(krb5_context context, > { > struct krb5_pk_identity *id = NULL; > struct prompter p; >- int ret; >+ krb5_error_code ret; > > *ret_id = NULL; > >@@ -2100,7 +2110,6 @@ _krb5_parse_moduli_line(krb5_context context, > m1->q.length = 0; > m1->q.data = 0; > krb5_clear_error_message(context); >- ret = 0; > } > > *m = m1; >diff --git a/third_party/heimdal/lib/krb5/principal.c b/third_party/heimdal/lib/krb5/principal.c >index ee25f6acb59d..6080e4623415 100644 >--- a/third_party/heimdal/lib/krb5/principal.c >+++ b/third_party/heimdal/lib/krb5/principal.c >@@ -103,6 +103,8 @@ krb5_free_principal(krb5_context context, > krb5_principal p) > { > if(p){ >+ if (p->nameattrs && p->nameattrs->pac) >+ heim_release(p->nameattrs->pac); > free_Principal(p); > free(p); > } >@@ -457,6 +459,22 @@ unparse_name_fixed(krb5_context context, > int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0; > int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0; > >+ if (name == NULL) { >+ krb5_set_error_message(context, EINVAL, >+ N_("Invalid name buffer, " >+ "can't unparse", "")); >+ return EINVAL; >+ } >+ >+ if (len == 0) { >+ krb5_set_error_message(context, ERANGE, >+ N_("Invalid name buffer length, " >+ "can't unparse", "")); >+ return ERANGE; >+ } >+ >+ name[0] = '\0'; >+ > if (!no_realm && princ_realm(principal) == NULL) { > krb5_set_error_message(context, ERANGE, > N_("Realm missing from principal, " >@@ -932,6 +950,9 @@ krb5_copy_principal(krb5_context context, > free(p); > return krb5_enomem(context); > } >+ if (inprinc->nameattrs && inprinc->nameattrs->pac) >+ p->nameattrs->pac = heim_retain(inprinc->nameattrs->pac); >+ > *outprinc = p; > return 0; > } >@@ -1766,7 +1787,7 @@ _krb5_get_name_canon_rules(krb5_context context, krb5_name_canon_rule *rules) > "libdefaults", "safe_name_canon", NULL)) > make_rules_safe(context, *rules); > >- heim_assert(rules != NULL && (*rules)[0].type != KRB5_NCRT_BOGUS, >+ heim_assert((*rules)[0].type != KRB5_NCRT_BOGUS, > "internal error in parsing principal name " > "canonicalization rules"); > >@@ -1968,10 +1989,12 @@ apply_name_canon_rule(krb5_context context, krb5_name_canon_rule rules, > new_hostname = hostname_with_port; > } > >- if (new_realm != NULL) >- krb5_principal_set_realm(context, *out_princ, new_realm); >- if (new_hostname != NULL) >- krb5_principal_set_comp_string(context, *out_princ, 1, new_hostname); >+ if (new_realm != NULL && >+ (ret = krb5_principal_set_realm(context, *out_princ, new_realm))) >+ goto out; >+ if (new_hostname != NULL && >+ (ret = krb5_principal_set_comp_string(context, *out_princ, 1, new_hostname))) >+ goto out; > if (princ_type(*out_princ) == KRB5_NT_SRV_HST_NEEDS_CANON) > princ_type(*out_princ) = KRB5_NT_SRV_HST; > >diff --git a/third_party/heimdal/lib/krb5/rd_cred.c b/third_party/heimdal/lib/krb5/rd_cred.c >index b24973978409..f8d57362310b 100644 >--- a/third_party/heimdal/lib/krb5/rd_cred.c >+++ b/third_party/heimdal/lib/krb5/rd_cred.c >@@ -96,7 +96,7 @@ krb5_rd_cred(krb5_context context, > goto out; > } > >- if (cred.enc_part.etype == (krb5_enctype)ETYPE_NULL) { >+ if (cred.enc_part.etype == ETYPE_NULL) { > /* DK: MIT GSS-API Compatibility */ > enc_krb_cred_part_data.length = cred.enc_part.cipher.length; > enc_krb_cred_part_data.data = cred.enc_part.cipher.data; >diff --git a/third_party/heimdal/lib/krb5/rd_req.c b/third_party/heimdal/lib/krb5/rd_req.c >index bd0b68b9cfb5..371037c8403f 100644 >--- a/third_party/heimdal/lib/krb5/rd_req.c >+++ b/third_party/heimdal/lib/krb5/rd_req.c >@@ -351,11 +351,6 @@ krb5_verify_ap_req2(krb5_context context, > ap_req->ticket.sname, > ap_req->ticket.realm); > if (ret) goto out; >- ret = _krb5_principalname2krb5_principal(context, >- &t->client, >- t->ticket.cname, >- t->ticket.crealm); >- if (ret) goto out; > > ret = decrypt_authenticator (context, > &t->ticket.key, >@@ -387,6 +382,27 @@ krb5_verify_ap_req2(krb5_context context, > } > } > >+ /* >+ * The ticket authenticates the client, and conveys naming attributes that >+ * we want to expose in GSS using RFC6680 APIs. >+ * >+ * So we same the ticket enc-part in the client's krb5_principal object >+ * (note though that the session key will be absent in that copy of the >+ * ticket enc-part). >+ */ >+ ret = _krb5_ticket2krb5_principal(context, &t->client, &t->ticket, >+ ac->authenticator->authorization_data); >+ if (ret) goto out; >+ >+ t->client->nameattrs->peer_realm = >+ calloc(1, sizeof(t->client->nameattrs->peer_realm[0])); >+ if (t->client->nameattrs->peer_realm == NULL) { >+ ret = krb5_enomem(context); >+ goto out; >+ } >+ ret = copy_Realm(&ap_req->ticket.realm, t->client->nameattrs->peer_realm); >+ if (ret) goto out; >+ > /* check addresses */ > > if (t->ticket.caddr >@@ -458,7 +474,7 @@ krb5_verify_ap_req2(krb5_context context, > > if (ap_req_options) { > *ap_req_options = 0; >- if (ac->keytype != (krb5_enctype)ETYPE_NULL) >+ if (ac->keytype != ETYPE_NULL) > *ap_req_options |= AP_OPTS_USE_SUBKEY; > if (ap_req->ap_options.use_session_key) > *ap_req_options |= AP_OPTS_USE_SESSION_KEY; >@@ -791,11 +807,10 @@ get_key_from_keytab(krb5_context context, > kvno, > ap_req->ticket.enc_part.etype, > &entry); >- if(ret) >- goto out; >- ret = krb5_copy_keyblock(context, &entry.keyblock, out_key); >- krb5_kt_free_entry (context, &entry); >-out: >+ if(ret == 0) { >+ ret = krb5_copy_keyblock(context, &entry.keyblock, out_key); >+ krb5_kt_free_entry(context, &entry); >+ } > if(keytab == NULL) > krb5_kt_close(context, real_keytab); > >@@ -840,7 +855,8 @@ krb5_rd_req_ctx(krb5_context context, > krb5_keytab id = NULL, keytab = NULL; > krb5_principal service = NULL; > >- *outctx = NULL; >+ if (outctx) >+ *outctx = NULL; > > o = calloc(1, sizeof(*o)); > if (o == NULL) >@@ -1021,6 +1037,12 @@ krb5_rd_req_ctx(krb5_context context, > goto out; > } > >+ ret = krb5_ticket_get_authorization_data_type(context, o->ticket, >+ KRB5_AUTHDATA_KDC_ISSUED, >+ NULL); >+ if (ret == 0) >+ o->ticket->client->nameattrs->kdc_issued_verified = 1; >+ > /* If there is a PAC, verify its server signature */ > if (inctx == NULL || inctx->check_pac) { > krb5_pac pac; >@@ -1042,28 +1064,36 @@ krb5_rd_req_ctx(krb5_context context, > o->ticket->client, > o->keyblock, > NULL); >+ if (ret == 0) >+ o->ticket->client->nameattrs->pac_verified = 1; > if (ret == 0 && (context->flags & KRB5_CTX_F_REPORT_CANONICAL_CLIENT_NAME)) { > krb5_error_code ret2; > krb5_principal canon_name; > > ret2 = _krb5_pac_get_canon_principal(context, pac, &canon_name); > if (ret2 == 0) { >- krb5_free_principal(context, o->ticket->client); >- o->ticket->client = canon_name; >+ free_Realm(&o->ticket->client->realm); >+ free_PrincipalName(&o->ticket->client->name); >+ ret = copy_Realm(&canon_name->realm, &o->ticket->client->realm); >+ if (ret == 0) >+ ret = copy_PrincipalName(&canon_name->name, &o->ticket->client->name); >+ krb5_free_principal(context, canon_name); > } else if (ret2 != ENOENT) > ret = ret2; > } >- krb5_pac_free(context, pac); >- if (ret) >+ if (ret) { >+ krb5_pac_free(context, pac); > goto out; >+ } >+ o->ticket->client->nameattrs->pac = pac; > } else > ret = 0; > } > out: > >- if (ret || outctx == NULL) { >+ if (ret || outctx == NULL) > krb5_rd_req_out_ctx_free(context, o); >- } else >+ else > *outctx = o; > > free_AP_REQ(&ap_req); >diff --git a/third_party/heimdal/lib/krb5/replay.c b/third_party/heimdal/lib/krb5/replay.c >index d9c442bb27da..2fec8afd1043 100644 >--- a/third_party/heimdal/lib/krb5/replay.c >+++ b/third_party/heimdal/lib/krb5/replay.c >@@ -220,8 +220,10 @@ krb5_rc_store(krb5_context context, > } > rk_cloexec_file(f); > count = fread(&tmp, sizeof(ent), 1, f); >- if(count != 1) >+ if (count != 1) { >+ fclose(f); > return KRB5_RC_IO_UNKNOWN; >+ } > t = ent.stamp - tmp.stamp; > while(fread(&tmp, sizeof(ent), 1, f)){ > if(tmp.stamp < t) >diff --git a/third_party/heimdal/lib/krb5/salt-arcfour.c b/third_party/heimdal/lib/krb5/salt-arcfour.c >index 38aaa25024e6..033128ed803d 100644 >--- a/third_party/heimdal/lib/krb5/salt-arcfour.c >+++ b/third_party/heimdal/lib/krb5/salt-arcfour.c >@@ -47,10 +47,8 @@ ARCFOUR_string_to_key(krb5_context context, > EVP_MD_CTX *m; > > m = EVP_MD_CTX_create(); >- if (m == NULL) { >- ret = krb5_enomem(context); >- goto out; >- } >+ if (m == NULL) >+ return krb5_enomem(context); > > EVP_DigestInit_ex(m, EVP_md4(), NULL); > >diff --git a/third_party/heimdal/lib/krb5/scache.c b/third_party/heimdal/lib/krb5/scache.c >index 554f377125e3..7a39664946b8 100644 >--- a/third_party/heimdal/lib/krb5/scache.c >+++ b/third_party/heimdal/lib/krb5/scache.c >@@ -276,9 +276,9 @@ make_dir(krb5_context context, const char *name) > static krb5_error_code > default_db(krb5_context context, const char *name, sqlite3 **db, char **file) > { >+ krb5_error_code ret = 0; > char *s = NULL; > char *f = NULL; >- int ret; > > if (file) > *file = NULL; >@@ -315,13 +315,24 @@ default_db(krb5_context context, const char *name, sqlite3 **db, char **file) > #endif > > ret = make_dir(context, f); >- if (ret == 0) >- ret = sqlite3_open_v2(f, db, SQLITE_OPEN_READWRITE, NULL); >- if (ret != SQLITE_OK) { >- sqlite3_close(*db); >- krb5_clear_error_message(context); >- free(f); >- return ENOENT; >+ if (ret == 0) { >+ int sret; >+ >+ sret = sqlite3_open_v2(f, db, SQLITE_OPEN_READWRITE, NULL); >+ if (sret != SQLITE_OK) { >+ if (*db) { >+ krb5_set_error_message(context, ENOENT, >+ N_("Error opening scache file %s: %s (%d)", ""), >+ f, sqlite3_errmsg(*db), sret); >+ sqlite3_close(*db); >+ *db = NULL; >+ } else >+ krb5_set_error_message(context, ENOENT, >+ N_("Error opening scache file %s: %s (%d)", ""), >+ f, sqlite3_errstr(sret), sret); >+ free(f); >+ return ENOENT; >+ } > } > > #ifndef WIN32 >@@ -341,7 +352,7 @@ default_db(krb5_context context, const char *name, sqlite3 **db, char **file) > sqlite3_trace(*db, trace, NULL); > #endif > >- return 0; >+ return ret; > } > > static krb5_error_code >@@ -435,10 +446,8 @@ scc_alloc(krb5_context context, > name += sizeof("SCC:") - 1; > > if ((s->file = strdup(name)) == NULL) { >- (void) krb5_enomem(context); >- scc_free(s); >- free(freeme); >- return NULL; >+ ret = krb5_enomem(context); >+ goto out; > } > > if ((subsidiary = strrchr(s->file, ':'))) { >@@ -469,19 +478,23 @@ scc_alloc(krb5_context context, > if (ret == 0 && s->file && s->sub && > (asprintf(&s->name, "%s:%s", s->file, s->sub) < 0 || s->name == NULL)) > ret = krb5_enomem(context); >+ >+ out: > if (ret || s->file == NULL || s->sub == NULL || s->name == NULL) { > scc_free(s); >- free(freeme); >- return NULL; >+ s = NULL; > } >+ >+ free(freeme); > return s; > } > > static krb5_error_code > open_database(krb5_context context, krb5_scache *s, int flags) > { >+ krb5_error_code ret; > struct stat st; >- int ret; >+ int sret; > > > if (!(flags & SQLITE_OPEN_CREATE) && stat(s->file, &st) == 0 && >@@ -489,18 +502,20 @@ open_database(krb5_context context, krb5_scache *s, int flags) > return ENOENT; > > ret = make_dir(context, s->file); >- if (ret == 0) >- ret = sqlite3_open_v2(s->file, &s->db, SQLITE_OPEN_READWRITE|flags, NULL); >- if (ret) { >+ if (ret) >+ return ret; >+ sret = sqlite3_open_v2(s->file, &s->db, SQLITE_OPEN_READWRITE|flags, NULL); >+ if (sret != SQLITE_OK) { > if (s->db) { > krb5_set_error_message(context, ENOENT, >- N_("Error opening scache file %s: %s", ""), >- s->file, sqlite3_errmsg(s->db)); >+ N_("Error opening scache file %s: %s (%d)", ""), >+ s->file, sqlite3_errmsg(s->db), sret); > sqlite3_close(s->db); > s->db = NULL; > } else > krb5_set_error_message(context, ENOENT, >- N_("malloc: out of memory", "")); >+ N_("Error opening scache file %s: %s (%d)", ""), >+ s->file, sqlite3_errstr(sret), sret); > return ENOENT; > } > return 0; >@@ -1270,24 +1285,22 @@ scc_remove_cred(krb5_context context, > > sqlite3_finalize(stmt); > >- if (id) { >- ret = prepare_stmt(context, s->db, &stmt, >- "DELETE FROM credentials WHERE oid=?"); >- if (ret) >- return ret; >- sqlite3_bind_int(stmt, 1, credid); >+ ret = prepare_stmt(context, s->db, &stmt, >+ "DELETE FROM credentials WHERE oid=?"); >+ if (ret) >+ return ret; >+ sqlite3_bind_int(stmt, 1, credid); > >- do { >- ret = sqlite3_step(stmt); >- } while (ret == SQLITE_ROW); >- sqlite3_finalize(stmt); >- if (ret != SQLITE_DONE) { >- ret = KRB5_CC_IO; >- krb5_set_error_message(context, ret, >- N_("failed to delete scache credental", "")); >- } else >- ret = 0; >- } >+ do { >+ ret = sqlite3_step(stmt); >+ } while (ret == SQLITE_ROW); >+ sqlite3_finalize(stmt); >+ if (ret != SQLITE_DONE) { >+ ret = KRB5_CC_IO; >+ krb5_set_error_message(context, ret, >+ N_("failed to delete scache credental", "")); >+ } else >+ ret = 0; > > return ret; > } >diff --git a/third_party/heimdal/lib/krb5/send_to_kdc.c b/third_party/heimdal/lib/krb5/send_to_kdc.c >index 704b095b5355..086f2edcd5db 100644 >--- a/third_party/heimdal/lib/krb5/send_to_kdc.c >+++ b/third_party/heimdal/lib/krb5/send_to_kdc.c >@@ -176,7 +176,7 @@ struct krb5_sendto_ctx_data { > unsigned int stid; > }; > >-static void >+static void KRB5_CALLCONV > dealloc_sendto_ctx(void *ptr) > { > krb5_sendto_ctx ctx = (krb5_sendto_ctx)ptr; >@@ -386,7 +386,7 @@ debug_host(krb5_context context, int level, struct host *host, const char *fmt, > } > > >-static void >+static void HEIM_CALLCONV > deallocate_host(void *ptr) > { > struct host *host = ptr; >@@ -1180,7 +1180,7 @@ krb5_sendto_context(krb5_context context, > > action = KRB5_SENDTO_INITIAL; > >- while (action != KRB5_SENDTO_DONE && action != KRB5_SENDTO_FAILED) { >+ while (1) { > krb5_krbhst_info *hi; > > switch (action) { >@@ -1192,7 +1192,7 @@ krb5_sendto_context(krb5_context context, > break; > } > action = KRB5_SENDTO_KRBHST; >- /* FALLTHROUGH */ >+ fallthrough; > case KRB5_SENDTO_KRBHST: > if (ctx->krbhst == NULL) { > ret = krb5_krbhst_init_flags(context, realm, type, >@@ -1214,7 +1214,7 @@ krb5_sendto_context(krb5_context context, > handle = heim_retain(ctx->krbhst); > } > action = KRB5_SENDTO_TIMEOUT; >- /* FALLTHROUGH */ >+ fallthrough; > case KRB5_SENDTO_TIMEOUT: > > /* >@@ -1308,10 +1308,10 @@ krb5_sendto_context(krb5_context context, > break; > case KRB5_SENDTO_FAILED: > ret = KRB5_KDC_UNREACH; >- break; >+ goto out; > case KRB5_SENDTO_DONE: > ret = 0; >- break; >+ goto out; > default: > heim_abort("invalid krb5_sendto_context state"); > } >diff --git a/third_party/heimdal/lib/krb5/sp800-108-kdf.c b/third_party/heimdal/lib/krb5/sp800-108-kdf.c >index 37e06dec3e84..4a12067c68bd 100755 >--- a/third_party/heimdal/lib/krb5/sp800-108-kdf.c >+++ b/third_party/heimdal/lib/krb5/sp800-108-kdf.c >@@ -73,7 +73,10 @@ _krb5_SP800_108_HMAC_KDF(krb5_context context, > unsigned char tmp[4]; > size_t len; > >- HMAC_Init_ex(&c, kdf_K1->data, kdf_K1->length, md, NULL); >+ if (HMAC_Init_ex(&c, kdf_K1->data, kdf_K1->length, md, NULL) == 0) { >+ HMAC_CTX_cleanup(&c); >+ return krb5_enomem(context); >+ } > > _krb5_put_int(tmp, i + 1, 4); > HMAC_Update(&c, tmp, 4); >diff --git a/third_party/heimdal/lib/krb5/store.c b/third_party/heimdal/lib/krb5/store.c >index 6a287bdf950d..79f8e3adbab0 100644 >--- a/third_party/heimdal/lib/krb5/store.c >+++ b/third_party/heimdal/lib/krb5/store.c >@@ -975,6 +975,10 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL > krb5_store_string(krb5_storage *sp, const char *s) > { > krb5_data data; >+ >+ if (s == NULL) >+ return EINVAL; >+ > data.length = strlen(s); > data.data = rk_UNCONST(s); > return krb5_store_data(sp, data); >@@ -1025,9 +1029,13 @@ krb5_ret_string(krb5_storage *sp, > KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL > krb5_store_stringz(krb5_storage *sp, const char *s) > { >- size_t len = strlen(s) + 1; >+ size_t len; > ssize_t ret; > >+ if (s == NULL) >+ return EINVAL; >+ >+ len = strlen(s) + 1; > ret = sp->store(sp, s, len); > if(ret < 0) > return ret; >@@ -1089,9 +1097,13 @@ krb5_ret_stringz(krb5_storage *sp, > KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL > krb5_store_stringnl(krb5_storage *sp, const char *s) > { >- size_t len = strlen(s); >+ size_t len; > ssize_t ret; > >+ if (s == NULL) >+ return EINVAL; >+ >+ len = strlen(s); > ret = sp->store(sp, s, len); > if(ret < 0) > return ret; >@@ -1370,16 +1382,18 @@ krb5_ret_times(krb5_storage *sp, krb5_times *times) > { > int ret; > int32_t tmp; >+ > ret = krb5_ret_int32(sp, &tmp); >+ if (ret) return ret; > times->authtime = tmp; >- if(ret) return ret; > ret = krb5_ret_int32(sp, &tmp); >+ if (ret) return ret; > times->starttime = tmp; >- if(ret) return ret; > ret = krb5_ret_int32(sp, &tmp); >+ if (ret) return ret; > times->endtime = tmp; >- if(ret) return ret; > ret = krb5_ret_int32(sp, &tmp); >+ if (ret) return ret; > times->renew_till = tmp; > return ret; > } >diff --git a/third_party/heimdal/lib/krb5/store_emem.c b/third_party/heimdal/lib/krb5/store_emem.c >index da66e5fa75e5..6a3908f74635 100644 >--- a/third_party/heimdal/lib/krb5/store_emem.c >+++ b/third_party/heimdal/lib/krb5/store_emem.c >@@ -33,6 +33,7 @@ > > #include "krb5_locl.h" > #include "store-int.h" >+#include <assert.h> > > typedef struct emem_storage{ > unsigned char *base; >@@ -45,10 +46,12 @@ static ssize_t > emem_fetch(krb5_storage *sp, void *data, size_t size) > { > emem_storage *s = (emem_storage*)sp->data; >+ >+ assert(data != NULL && s->ptr != NULL); >+ > if((size_t)(s->base + s->len - s->ptr) < size) > size = s->base + s->len - s->ptr; >- if (data != NULL) >- memmove(data, s->ptr, size); >+ memmove(data, s->ptr, size); > sp->seek(sp, size, SEEK_CUR); > return size; > } >@@ -56,7 +59,17 @@ emem_fetch(krb5_storage *sp, void *data, size_t size) > static ssize_t > emem_store(krb5_storage *sp, const void *data, size_t size) > { >- emem_storage *s = (emem_storage*)sp->data; >+ emem_storage *s; >+ >+ if (size == 0) { >+ sp->seek(sp, 0, SEEK_CUR); >+ return 0; >+ } >+ >+ s = (emem_storage*)sp->data; >+ >+ assert(data != NULL); >+ > if(size > (size_t)(s->base + s->size - s->ptr)){ > void *base; > size_t sz, off; >@@ -71,8 +84,7 @@ emem_store(krb5_storage *sp, const void *data, size_t size) > s->base = base; > s->ptr = (unsigned char*)base + off; > } >- if (data != NULL) >- memmove(s->ptr, data, size); >+ memmove(s->ptr, data, size); > sp->seek(sp, size, SEEK_CUR); > return size; > } >@@ -141,6 +153,9 @@ static void > emem_free(krb5_storage *sp) > { > emem_storage *s = sp->data; >+ >+ assert(s->base != NULL); >+ > memset_s(s->base, s->len, 0, s->len); > free(s->base); > } >diff --git a/third_party/heimdal/lib/krb5/store_stdio.c b/third_party/heimdal/lib/krb5/store_stdio.c >index 80323e1d8f26..dddaa9245782 100644 >--- a/third_party/heimdal/lib/krb5/store_stdio.c >+++ b/third_party/heimdal/lib/krb5/store_stdio.c >@@ -137,6 +137,8 @@ stdio_trunc(krb5_storage * sp, off_t offset) > if (fflush(F(sp)) == EOF) > return errno; > tmpoff = ftello(F(sp)); >+ if (tmpoff < 0) >+ return errno; > if (tmpoff > offset) > tmpoff = offset; > if (ftruncate(fileno(F(sp)), offset) == -1) >diff --git a/third_party/heimdal/lib/krb5/test_alname.c b/third_party/heimdal/lib/krb5/test_alname.c >index 120143e51e7b..36775adef1b4 100644 >--- a/third_party/heimdal/lib/krb5/test_alname.c >+++ b/third_party/heimdal/lib/krb5/test_alname.c >@@ -81,8 +81,8 @@ test_alname(krb5_context context, krb5_const_realm realm, > } > krb5_err(context, 1, ret, "krb5_aname_to_localname: %s -> %s", > princ, localuser); >- free(princ); > } >+ free(princ); > > if (strcmp(localname, localuser) != 0) { > if (ok) >diff --git a/third_party/heimdal/lib/krb5/test_ap-req.c b/third_party/heimdal/lib/krb5/test_ap-req.c >index c3aaef3606a7..0fd107833976 100644 >--- a/third_party/heimdal/lib/krb5/test_ap-req.c >+++ b/third_party/heimdal/lib/krb5/test_ap-req.c >@@ -153,6 +153,7 @@ test_ap(krb5_context context, > krb5_err(context, 1, ret, "pac parse"); > > krb5_pac_free(context, pac); >+ krb5_data_free(&data); > } > > krb5_free_ticket(context, ticket); >diff --git a/third_party/heimdal/lib/krb5/test_cc.c b/third_party/heimdal/lib/krb5/test_cc.c >index 213bb0780d9b..0ca582eaaca6 100644 >--- a/third_party/heimdal/lib/krb5/test_cc.c >+++ b/third_party/heimdal/lib/krb5/test_cc.c >@@ -670,6 +670,8 @@ test_move(krb5_context context, const char *type) > krb5_err(context, 1, ret, "krb5_cc_new_unique"); > > ret = krb5_cc_move(context, fromid, toid); >+ if (ret) >+ krb5_err(context, 1, ret, "krb5_cc_move"); > > ret = krb5_cc_get_principal(context, toid, &p2); > if (ret) >@@ -916,7 +918,7 @@ test_cccol_dcache(krb5_context context) > ret = test_cccol(context, dcc, &what); > free(dcc); > if (ret) >- krb5_err(context, 1, errno, "%s", what); >+ krb5_err(context, 1, ret, "%s", what); > } > > static void >@@ -1117,9 +1119,6 @@ main(int argc, char **argv) > > test_move(context, krb5_cc_type_file); > test_move(context, krb5_cc_type_memory); >-#ifdef HAVE_KCM >- test_move(context, krb5_cc_type_kcm); >-#endif > test_move(context, krb5_cc_type_scc); > #if 0 > test_move(context, krb5_cc_type_dcc); >@@ -1204,6 +1203,9 @@ main(int argc, char **argv) > ret = test_cccol(context, fname, &what); > if (ret) > krb5_err(context, 1, ret, "%s", what); >+ free(config); >+ free(fname); >+ free(d); > } > > krb5_free_context(context); >diff --git a/third_party/heimdal/lib/krb5/test_hostname.c b/third_party/heimdal/lib/krb5/test_hostname.c >index fbdb5c9c322a..f722353f664a 100644 >--- a/third_party/heimdal/lib/krb5/test_hostname.c >+++ b/third_party/heimdal/lib/krb5/test_hostname.c >@@ -48,11 +48,11 @@ expand_hostname(krb5_context context, const char *host) > if (ret) > krb5_err(context, 1, ret, "krb5_expand_hostname(%s)", host); > >- free(h); >- > if (debug_flag) > printf("hostname: %s -> %s\n", host, h); > >+ free(h); >+ > ret = krb5_expand_hostname_realms(context, host, &h, &r); > if (ret) > krb5_err(context, 1, ret, "krb5_expand_hostname_realms(%s)", host); >diff --git a/third_party/heimdal/lib/krb5/test_rfc3961.c b/third_party/heimdal/lib/krb5/test_rfc3961.c >index f1255948fc46..ed8ee9b5f3f4 100644 >--- a/third_party/heimdal/lib/krb5/test_rfc3961.c >+++ b/third_party/heimdal/lib/krb5/test_rfc3961.c >@@ -133,6 +133,7 @@ time_hmac_evp(krb5_context context, size_t size, int iterations) > > free(buf); > krb5_free_keyblock_contents(context, &key); >+ krb5_crypto_destroy(context, crypto); > } > > static void >diff --git a/third_party/heimdal/lib/krb5/test_set_kvno0.c b/third_party/heimdal/lib/krb5/test_set_kvno0.c >index 526c240f1c4b..0c7e6b447ae8 100644 >--- a/third_party/heimdal/lib/krb5/test_set_kvno0.c >+++ b/third_party/heimdal/lib/krb5/test_set_kvno0.c >@@ -119,8 +119,11 @@ main(int argc, char **argv) > during = "decode_Ticket"; > memset(&t, 0, sizeof (t)); > ret = decode_Ticket(cred.ticket.data, cred.ticket.length, &t, &len); >- if (ret == ASN1_MISSING_FIELD) >+ if (ret == ASN1_MISSING_FIELD) { >+ krb5_free_cred_contents(context, &cred); >+ memset(&cred, 0, sizeof (cred)); > continue; >+ } > if (ret) goto err; > if (t.enc_part.kvno) { > *t.enc_part.kvno = 0; >diff --git a/third_party/heimdal/lib/krb5/ticket.c b/third_party/heimdal/lib/krb5/ticket.c >index 11e4e84963b2..e2f2ab2085c6 100644 >--- a/third_party/heimdal/lib/krb5/ticket.c >+++ b/third_party/heimdal/lib/krb5/ticket.c >@@ -204,13 +204,38 @@ krb5_ticket_get_flags(krb5_context context, > return TicketFlags2int(ticket->ticket.flags); > } > >+/* >+ * Find an authz-data element in the given `ad'. If `failp', then validate any >+ * containing AD-KDC-ISSUED's keyed checksum with the `sessionkey' (if given). >+ * >+ * All AD-KDC-ISSUED will be validated (if requested) even when `type' is >+ * `KRB5_AUTHDATA_KDC_ISSUED'. >+ * >+ * Only the first matching element will be output (via `data'). >+ * >+ * Note that all AD-KDC-ISSUEDs found while traversing the authz-data will be >+ * validated, though only the first one will be returned. >+ * >+ * XXX We really need a better interface though. First, forget AD-AND-OR -- >+ * just remove it. Second, probably forget AD-KDC-ISSUED, but still, between >+ * that, the PAC, and the CAMMAC, we need an interface that can: >+ * >+ * a) take the derived keys instead of the service key or the session key, >+ * b) can indicate whether the element was marked critical, >+ * c) can indicate whether the element was authenticated to the KDC, >+ * d) can iterate over all the instances found (if more than one is found). >+ * >+ * Also, we need to know here if the authz-data is from a Ticket or from an >+ * Authenticator -- if the latter then we must refuse to find AD-KDC-ISSUED / >+ * PAC / CAMMAC or anything of the sort, ever. >+ */ > static int > find_type_in_ad(krb5_context context, > int type, >- krb5_data *data, >+ krb5_data *data, /* optional */ > krb5_boolean *found, >- krb5_boolean failp, >- krb5_keyblock *sessionkey, >+ krb5_boolean failp, /* validate AD-KDC-ISSUED */ >+ krb5_keyblock *sessionkey, /* ticket session key */ > const AuthorizationData *ad, > int level) > { >@@ -233,14 +258,19 @@ find_type_in_ad(krb5_context context, > */ > for (i = 0; i < ad->len; i++) { > if (!*found && ad->val[i].ad_type == type) { >- ret = der_copy_octet_string(&ad->val[i].ad_data, data); >- if (ret) { >- krb5_set_error_message(context, ret, >- N_("malloc: out of memory", "")); >- goto out; >- } >+ if (data) { >+ ret = der_copy_octet_string(&ad->val[i].ad_data, data); >+ if (ret) { >+ krb5_set_error_message(context, ret, >+ N_("malloc: out of memory", "")); >+ goto out; >+ } >+ } > *found = TRUE; >- continue; >+ if (type != KRB5_AUTHDATA_KDC_ISSUED || >+ !failp || !sessionkey || !sessionkey->keyvalue.length) >+ continue; >+ /* else go on to validate the AD-KDC-ISSUED's keyed checksum */ > } > switch (ad->val[i].ad_type) { > case KRB5_AUTHDATA_IF_RELEVANT: { >@@ -263,7 +293,6 @@ find_type_in_ad(krb5_context context, > goto out; > break; > } >-#if 0 /* XXX test */ > case KRB5_AUTHDATA_KDC_ISSUED: { > AD_KDCIssued child; > >@@ -278,7 +307,7 @@ find_type_in_ad(krb5_context context, > ret); > goto out; > } >- if (failp) { >+ if (failp && sessionkey && sessionkey->keyvalue.length) { > krb5_boolean valid; > krb5_data buf; > size_t len; >@@ -306,7 +335,12 @@ find_type_in_ad(krb5_context context, > free_AD_KDCIssued(&child); > goto out; > } >- } >+ } else if (failp) { >+ krb5_clear_error_message(context); >+ ret = ENOENT; >+ free_AD_KDCIssued(&child); >+ goto out; >+ } > ret = find_type_in_ad(context, type, data, found, failp, sessionkey, > &child.elements, level + 1); > free_AD_KDCIssued(&child); >@@ -314,7 +348,6 @@ find_type_in_ad(krb5_context context, > goto out; > break; > } >-#endif > case KRB5_AUTHDATA_AND_OR: > if (!failp) > break; >@@ -338,7 +371,8 @@ find_type_in_ad(krb5_context context, > out: > if (ret) { > if (*found) { >- krb5_data_free(data); >+ if (data) >+ krb5_data_free(data); > *found = 0; > } > } >@@ -355,7 +389,8 @@ _krb5_get_ad(krb5_context context, > krb5_boolean found = FALSE; > krb5_error_code ret; > >- krb5_data_zero(data); >+ if (data) >+ krb5_data_zero(data); > > if (ad == NULL) { > krb5_set_error_message(context, ENOENT, >@@ -399,7 +434,8 @@ krb5_ticket_get_authorization_data_type(krb5_context context, > krb5_error_code ret; > krb5_boolean found = FALSE; > >- krb5_data_zero(data); >+ if (data) >+ krb5_data_zero(data); > > ad = ticket->ticket.authorization_data; > if (ticket->ticket.authorization_data == NULL) { >@@ -752,9 +788,9 @@ _krb5_extract_ticket(krb5_context context, > > /* compare client and save */ > ret = _krb5_principalname2krb5_principal(context, >- &tmp_principal, >- rep->kdc_rep.cname, >- rep->kdc_rep.crealm); >+ &tmp_principal, >+ rep->kdc_rep.cname, >+ rep->kdc_rep.crealm); > if (ret) > goto out; > >@@ -785,12 +821,19 @@ _krb5_extract_ticket(krb5_context context, > creds->client = tmp_principal; > > /* check server referral and save principal */ >- ret = _krb5_principalname2krb5_principal (context, >- &tmp_principal, >- rep->enc_part.sname, >- rep->enc_part.srealm); >+ ret = _krb5_kdcrep2krb5_principal(context, &tmp_principal, &rep->enc_part); > if (ret) > goto out; >+ >+ tmp_principal->nameattrs->peer_realm = >+ calloc(1, sizeof(tmp_principal->nameattrs->peer_realm[0])); >+ if (tmp_principal->nameattrs->peer_realm == NULL) { >+ ret = krb5_enomem(context); >+ goto out; >+ } >+ ret = copy_Realm(&creds->client->realm, tmp_principal->nameattrs->peer_realm); >+ if (ret) goto out; >+ > if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){ > ret = check_server_referral(context, > rep, >diff --git a/third_party/heimdal/lib/krb5/transited.c b/third_party/heimdal/lib/krb5/transited.c >index 35c00e65add4..484fd398c296 100644 >--- a/third_party/heimdal/lib/krb5/transited.c >+++ b/third_party/heimdal/lib/krb5/transited.c >@@ -274,13 +274,17 @@ decode_realms(krb5_context context, > } > if(tr[i] == ','){ > tmp = malloc(tr + i - start + 1); >- if(tmp == NULL) >+ if(tmp == NULL) { >+ free_realms(*realms); >+ *realms = NULL; > return krb5_enomem(context); >+ } > memcpy(tmp, start, tr + i - start); > tmp[tr + i - start] = '\0'; > r = make_realm(tmp); > if(r == NULL){ > free_realms(*realms); >+ *realms = NULL; > return krb5_enomem(context); > } > *realms = append_realm(*realms, r); >@@ -289,7 +293,8 @@ decode_realms(krb5_context context, > } > tmp = malloc(tr + i - start + 1); > if(tmp == NULL){ >- free(*realms); >+ free_realms(*realms); >+ *realms = NULL; > return krb5_enomem(context); > } > memcpy(tmp, start, tr + i - start); >@@ -297,6 +302,7 @@ decode_realms(krb5_context context, > r = make_realm(tmp); > if(r == NULL){ > free_realms(*realms); >+ *realms = NULL; > return krb5_enomem(context); > } > *realms = append_realm(*realms, r); >@@ -353,8 +359,6 @@ krb5_domain_x500_decode(krb5_context context, > { > char **R; > R = malloc((*num_realms + 1) * sizeof(*R)); >- if (R == NULL) >- return krb5_enomem(context); > *realms = R; > while(r){ > *R++ = r->realm; >@@ -362,6 +366,8 @@ krb5_domain_x500_decode(krb5_context context, > free(r); > r = p; > } >+ if (*realms == NULL) >+ return krb5_enomem(context); > } > return 0; > } >@@ -621,11 +627,12 @@ krb5_check_transited(krb5_context context, > return ret; > > for (i = 0; i < num_realms; i++) { >- for (j = 0; j < num_capath; ++j) { >+ for (j = 0; j < num_capath && capath[j]; ++j) { >+ /* `capath[j]' can't be NULL, but compilers be dumb */ > if (strcmp(realms[i], capath[j]) == 0) > break; > } >- if (j == num_capath) { >+ if (j == num_capath || !capath[j]) { > _krb5_free_capath(context, capath); > krb5_set_error_message (context, KRB5KRB_AP_ERR_ILL_CR_TKT, > N_("no transit allowed " >diff --git a/third_party/heimdal/lib/krb5/verify_user.c b/third_party/heimdal/lib/krb5/verify_user.c >index 663196b29b15..c6ead8e42b2d 100644 >--- a/third_party/heimdal/lib/krb5/verify_user.c >+++ b/third_party/heimdal/lib/krb5/verify_user.c >@@ -40,7 +40,7 @@ verify_common (krb5_context context, > krb5_keytab keytab, > krb5_boolean secure, > const char *service, >- krb5_creds cred) >+ krb5_creds *cred) > { > krb5_error_code ret; > krb5_principal server; >@@ -56,7 +56,7 @@ verify_common (krb5_context context, > krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, secure); > > ret = krb5_verify_init_creds(context, >- &cred, >+ cred, > server, > keytab, > NULL, >@@ -71,12 +71,11 @@ verify_common (krb5_context context, > if(ret == 0){ > ret = krb5_cc_initialize(context, id, principal); > if(ret == 0){ >- ret = krb5_cc_store_cred(context, id, &cred); >+ ret = krb5_cc_store_cred(context, id, cred); > } > if(ccache == NULL) > krb5_cc_close(context, id); > } >- krb5_free_cred_contents(context, &cred); > return ret; > } > >@@ -172,10 +171,12 @@ verify_user_opt_int(krb5_context context, > if(ret) > return ret; > #define OPT(V, D) ((vopt && (vopt->V)) ? (vopt->V) : (D)) >- return verify_common (context, principal, OPT(ccache, NULL), >+ ret = verify_common (context, principal, OPT(ccache, NULL), > OPT(keytab, NULL), vopt ? vopt->secure : TRUE, >- OPT(service, "host"), cred); >+ OPT(service, "host"), &cred); > #undef OPT >+ krb5_free_cred_contents(context, &cred); >+ return ret; > } > > KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL >diff --git a/third_party/heimdal/lib/krb5/version-script.map b/third_party/heimdal/lib/krb5/version-script.map >index ce2783c35752..f6278e9ecbf6 100644 >--- a/third_party/heimdal/lib/krb5/version-script.map >+++ b/third_party/heimdal/lib/krb5/version-script.map >@@ -24,6 +24,8 @@ HEIMDAL_KRB5_2.0 { > krb5_appdefault_time; > krb5_append_addresses; > krb5_auth_con_addflags; >+ krb5_auth_con_add_AuthorizationData; >+ krb5_auth_con_add_AuthorizationDataIfRelevant; > krb5_auth_con_free; > krb5_auth_con_genaddrs; > krb5_auth_con_generatelocalsubkey; >@@ -493,6 +495,7 @@ HEIMDAL_KRB5_2.0 { > krb5_pac_add_buffer; > krb5_pac_free; > krb5_pac_get_buffer; >+ _krb5_pac_get_buffer_by_name; > krb5_pac_get_kdc_checksum_info; > krb5_pac_get_types; > krb5_pac_init; >@@ -739,6 +742,7 @@ HEIMDAL_KRB5_2.0 { > krb5_cccol_cursor_new; > krb5_cccol_cursor_next; > krb5_cccol_cursor_free; >+ krb5_cccol_get_default_ccname; > > # com_err error tables > initialize_krb5_error_table_r; >@@ -828,6 +832,8 @@ HEIMDAL_KRB5_2.0 { > _krb5_plugin_run_f; > _krb5_principal2principalname; > _krb5_principalname2krb5_principal; >+ _krb5_kdcrep2krb5_principal; >+ _krb5_ticket2krb5_principal; > _krb5_put_int; > _krb5_s4u2self_to_checksumdata; > _krb5_HMAC_MD5_checksum; >@@ -842,6 +848,7 @@ HEIMDAL_KRB5_2.0 { > krb5_init_creds_init; > krb5_init_creds_set_service; > krb5_init_creds_set_fast_anon_pkinit; >+ _krb5_init_creds_set_fast_anon_pkinit_optimistic; > krb5_init_creds_set_fast_ccache; > krb5_init_creds_set_keytab; > krb5_init_creds_set_kdc_hostname; >diff --git a/third_party/heimdal/lib/ntlm/digest.c b/third_party/heimdal/lib/ntlm/digest.c >index a1d6b5f3a649..761e1f497fcb 100644 >--- a/third_party/heimdal/lib/ntlm/digest.c >+++ b/third_party/heimdal/lib/ntlm/digest.c >@@ -471,7 +471,7 @@ heim_digest_generate_challenge(heim_digest_t context) > break; > case HEIM_DIGEST_TYPE_AUTO: > context->type = HEIM_DIGEST_TYPE_RFC2831; >- /* FALLTHROUGH */ >+ fallthrough; > case HEIM_DIGEST_TYPE_RFC2831: > asprintf(&challenge, "realm=\"%s\",nonce=\"%s\",qop=\"%s\",algorithm=md5-sess,charset=utf-8,maxbuf=%s", > context->serverRealm, context->serverNonce, context->serverQOP, context->serverMaxbuf); >diff --git a/third_party/heimdal/lib/ntlm/ntlm.c b/third_party/heimdal/lib/ntlm/ntlm.c >index 9670a9718301..d75752ea0007 100644 >--- a/third_party/heimdal/lib/ntlm/ntlm.c >+++ b/third_party/heimdal/lib/ntlm/ntlm.c >@@ -354,7 +354,7 @@ ret_string(krb5_storage *sp, int ucs2, size_t len, char **s) > utf8len += 1; > > *s = malloc(utf8len); >- if (s == NULL) { >+ if (*s == NULL) { > ret = ENOMEM; > goto out; > } >@@ -1324,7 +1324,10 @@ heim_ntlm_v2_base_session(void *key, size_t len, > > /* Note: key is the NTLMv2 key */ > HMAC_CTX_init(&c); >- HMAC_Init_ex(&c, key, len, EVP_md5(), NULL); >+ if (HMAC_Init_ex(&c, key, len, EVP_md5(), NULL) == 0) { >+ HMAC_CTX_cleanup(&c); >+ return ENOMEM; >+ } > HMAC_Update(&c, ntlmResponse->data, 16); > HMAC_Final(&c, session->data, &hmaclen); > HMAC_CTX_cleanup(&c); >@@ -1443,7 +1446,7 @@ heim_ntlm_build_ntlm2_master(void *key, size_t len, > > ret = heim_ntlm_v2_base_session(key, len, blob, &sess); > if (ret) >- return ret; >+ return ret; > > ret = heim_ntlm_keyex_wrap(&sess, session, master); > heim_ntlm_free_buf(&sess); >@@ -1523,25 +1526,26 @@ heim_ntlm_ntlmv2_key(const void *key, size_t len, > { > int ret; > unsigned int hmaclen; >+ struct ntlm_buf buf; > HMAC_CTX c; > > HMAC_CTX_init(&c); >- HMAC_Init_ex(&c, key, len, EVP_md5(), NULL); >- { >- struct ntlm_buf buf; >- /* uppercase username and turn it into ucs2-le */ >- ret = ascii2ucs2le(username, 1, &buf); >- if (ret) >- goto out; >- HMAC_Update(&c, buf.data, buf.length); >- free(buf.data); >- /* turn target into ucs2-le */ >- ret = ascii2ucs2le(target, upper_case_target, &buf); >- if (ret) >- goto out; >- HMAC_Update(&c, buf.data, buf.length); >- free(buf.data); >+ if (HMAC_Init_ex(&c, key, len, EVP_md5(), NULL) == 0) { >+ ret = ENOMEM; >+ goto out; > } >+ /* uppercase username and turn it into ucs2-le */ >+ ret = ascii2ucs2le(username, 1, &buf); >+ if (ret) >+ goto out; >+ HMAC_Update(&c, buf.data, buf.length); >+ free(buf.data); >+ /* turn target into ucs2-le */ >+ ret = ascii2ucs2le(target, upper_case_target, &buf); >+ if (ret) >+ goto out; >+ HMAC_Update(&c, buf.data, buf.length); >+ free(buf.data); > HMAC_Final(&c, ntlmv2, &hmaclen); > out: > HMAC_CTX_cleanup(&c); >@@ -1599,6 +1603,7 @@ heim_ntlm_calculate_lm2(const void *key, size_t len, > struct ntlm_buf *answer) > { > unsigned char clientchallenge[8]; >+ krb5_error_code ret; > > if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1) > return HNTLM_ERR_RAND; >@@ -1612,12 +1617,12 @@ heim_ntlm_calculate_lm2(const void *key, size_t len, > return ENOMEM; > answer->length = 24; > >- heim_ntlm_derive_ntlm2_sess(ntlmv2, clientchallenge, 8, >- serverchallenge, answer->data); >- >- memcpy(((unsigned char *)answer->data) + 16, clientchallenge, 8); >+ ret = heim_ntlm_derive_ntlm2_sess(ntlmv2, clientchallenge, 8, >+ serverchallenge, answer->data); >+ if (ret == 0) >+ memcpy(((unsigned char *)answer->data) + 16, clientchallenge, 8); > >- return 0; >+ return ret; > } > > >@@ -1695,7 +1700,10 @@ heim_ntlm_calculate_ntlm2(const void *key, size_t len, > krb5_storage_free(sp); > sp = NULL; > >- heim_ntlm_derive_ntlm2_sess(ntlmv2, data.data, data.length, serverchallenge, ntlmv2answer); >+ ret = heim_ntlm_derive_ntlm2_sess(ntlmv2, data.data, data.length, >+ serverchallenge, ntlmv2answer); >+ if (ret) >+ return ret; > > sp = krb5_storage_emem(); > if (sp == NULL) { >@@ -1809,10 +1817,13 @@ verify_ntlm2(const void *key, size_t len, > goto out; > } > >- heim_ntlm_derive_ntlm2_sess(ntlmv2, >- ((unsigned char *)answer->data) + 16, answer->length - 16, >- serverchallenge, >- serveranswer); >+ ret = heim_ntlm_derive_ntlm2_sess(ntlmv2, >+ ((unsigned char *)answer->data) + 16, >+ answer->length - 16, >+ serverchallenge, >+ serveranswer); >+ if (ret) >+ goto out; > > if (memcmp(serveranswer, clientanswer, 16) != 0) { > heim_ntlm_free_buf(infotarget); >@@ -1995,7 +2006,7 @@ heim_ntlm_calculate_ntlm2_sess_hash(const unsigned char clnt_nonce[8], > * @ingroup ntlm_core > */ > >-void >+int > heim_ntlm_derive_ntlm2_sess(const unsigned char sessionkey[16], > const unsigned char *clnt_nonce, size_t clnt_nonce_length, > const unsigned char svr_chal[8], >@@ -2006,10 +2017,14 @@ heim_ntlm_derive_ntlm2_sess(const unsigned char sessionkey[16], > > /* HMAC(Ksession, serverchallenge || clientchallenge) */ > HMAC_CTX_init(&c); >- HMAC_Init_ex(&c, sessionkey, 16, EVP_md5(), NULL); >+ if (HMAC_Init_ex(&c, sessionkey, 16, EVP_md5(), NULL) == 0) { >+ HMAC_CTX_cleanup(&c); >+ return ENOMEM; >+ } > HMAC_Update(&c, svr_chal, 8); > HMAC_Update(&c, clnt_nonce, clnt_nonce_length); > HMAC_Final(&c, derivedkey, &hmaclen); > HMAC_CTX_cleanup(&c); > memset(&c, 0, sizeof(c)); >+ return 0; > } >diff --git a/third_party/heimdal/lib/otp/otp_md.c b/third_party/heimdal/lib/otp/otp_md.c >index 1d6fe9594373..9338a204def5 100644 >--- a/third_party/heimdal/lib/otp/otp_md.c >+++ b/third_party/heimdal/lib/otp/otp_md.c >@@ -92,8 +92,6 @@ otp_md_init (OtpKey key, > char *p; > int len; > >- ctx = EVP_MD_CTX_create(); >- > len = strlen(pwd) + strlen(seed); > p = malloc (len + 1); > if (p == NULL) >@@ -102,6 +100,8 @@ otp_md_init (OtpKey key, > strlwr (p); > strlcat (p, pwd, len + 1); > >+ ctx = EVP_MD_CTX_create(); >+ > EVP_DigestInit_ex(ctx, md, NULL); > EVP_DigestUpdate(ctx, p, len); > EVP_DigestFinal_ex(ctx, res, NULL); >diff --git a/third_party/heimdal/lib/roken/Makefile.am b/third_party/heimdal/lib/roken/Makefile.am >index a6168f944d47..35d753204e79 100644 >--- a/third_party/heimdal/lib/roken/Makefile.am >+++ b/third_party/heimdal/lib/roken/Makefile.am >@@ -21,7 +21,7 @@ AM_CPPFLAGS += -I$(DBHEADER) > endif > > bin_PROGRAMS = rkvis rkbase32 rkbase64 >-noinst_PROGRAMS = snprintf-test resolve-test rkpty test-detach test-auxval rtbl >+noinst_PROGRAMS = snprintf-test resolve-test rkpty test-detach test-auxval rtbl timeval > > CHECK_LOCAL = snprintf-test resolve-test rkpty make-roken > >@@ -40,6 +40,7 @@ check_PROGRAMS = \ > parse_time-test \ > snprintf-test \ > strpftime-test \ >+ timeval \ > tsearch-test > > TESTS = $(check_PROGRAMS) >@@ -89,6 +90,9 @@ else > vis_h = vis.h > endif > >+timeval_SOURCES = timeval.c >+timeval_CPPFLAGS = -DTEST >+ > rkvis_SOURCES = vis.c $(vis_h) vis-extras.h > rkvis_CPPFLAGS = -DTEST > >diff --git a/third_party/heimdal/lib/roken/base32-test.c b/third_party/heimdal/lib/roken/base32-test.c >index bea2866e47d3..e30c193c478e 100644 >--- a/third_party/heimdal/lib/roken/base32-test.c >+++ b/third_party/heimdal/lib/roken/base32-test.c >@@ -66,7 +66,8 @@ main(int argc, char **argv) > for(t = tests; t->data; t++) { > char *str; > int len; >- len = rk_base32_encode(t->data, t->len, &str, t->preserve_order); >+ >+ (void) rk_base32_encode(t->data, t->len, &str, t->preserve_order); > if (strcmp(str, t->result) != 0) { > fprintf(stderr, "failed test %d: %s != %s\n", numtest, > str, t->result); >diff --git a/third_party/heimdal/lib/roken/base32.c b/third_party/heimdal/lib/roken/base32.c >index 638ec2925f2e..ef74336d70a6 100644 >--- a/third_party/heimdal/lib/roken/base32.c >+++ b/third_party/heimdal/lib/roken/base32.c >@@ -100,10 +100,10 @@ rk_base32_encode(const void *data, int size, char **str, enum rk_base32_flags fl > p[6] = chars[(c & 0x0000000000000003e0ULL) >> 5]; > p[7] = chars[(c & 0x00000000000000001fULL) >> 0]; > switch (i - size) { >- case 4: p[2] = p[3] = '='; /*fallthrough*/ >- case 3: p[4] = '='; /*fallthrough*/ >- case 2: p[5] = p[6] = '='; /*fallthrough*/ >- case 1: p[7] = '='; /*fallthrough*/ >+ case 4: p[2] = p[3] = '='; fallthrough; >+ case 3: p[4] = '='; fallthrough; >+ case 2: p[5] = p[6] = '='; fallthrough; >+ case 1: p[7] = '='; fallthrough; > default: break; > } > p += 8; >@@ -271,7 +271,7 @@ main(int argc, char **argv) > } else { > void *d; > >- if ((ret = rk_undumpdata(argv[0], &d, &bufsz))) >+ if ((errno = rk_undumpdata(argv[0], &d, &bufsz))) > err(1, "Could not read %s", argv[0]); > buflen = bufsz; > buf = d; >@@ -298,7 +298,7 @@ main(int argc, char **argv) > if (fwrite(d, ret, 1, stdout) != 1) > err(1, "Could not write decoded data"); > free(d); >- } else { >+ } else if (buf) { /* buf can be NULL if we read from an empty file */ > char *e; > > if ((ret = rk_base32_encode(buf, buflen, &e, flags)) < 0) >diff --git a/third_party/heimdal/lib/roken/base64-test.c b/third_party/heimdal/lib/roken/base64-test.c >index 86cccbb1d4f9..8fb3f528001f 100644 >--- a/third_party/heimdal/lib/roken/base64-test.c >+++ b/third_party/heimdal/lib/roken/base64-test.c >@@ -58,7 +58,8 @@ main(int argc, char **argv) > for(t = tests; t->data; t++) { > char *str; > int len; >- len = rk_base64_encode(t->data, t->len, &str); >+ >+ (void) rk_base64_encode(t->data, t->len, &str); > if(strcmp(str, t->result) != 0) { > fprintf(stderr, "failed test %d: %s != %s\n", numtest, > str, t->result); >diff --git a/third_party/heimdal/lib/roken/base64.c b/third_party/heimdal/lib/roken/base64.c >index a6dacdd1d294..582d183bcf73 100644 >--- a/third_party/heimdal/lib/roken/base64.c >+++ b/third_party/heimdal/lib/roken/base64.c >@@ -214,7 +214,7 @@ main(int argc, char **argv) > err(1, "Could not read stdin"); > } else { > void *d; >- if ((ret = rk_undumpdata(argv[0], &d, &bufsz))) >+ if ((errno = rk_undumpdata(argv[0], &d, &bufsz))) > err(1, "Could not read %s", argv[0]); > buflen = bufsz; > buf = d; >@@ -241,7 +241,7 @@ main(int argc, char **argv) > if (fwrite(d, ret, 1, stdout) != 1) > err(1, "Could not write decoded data"); > free(d); >- } else { >+ } else if (buf) { /* buf can be NULL if we read from an empty file */ > char *e; > > if ((ret = rk_base64_encode(buf, buflen, &e)) < 0) >diff --git a/third_party/heimdal/lib/roken/copyhostent.c b/third_party/heimdal/lib/roken/copyhostent.c >index 4ed630210fc8..9b9dba2aea59 100644 >--- a/third_party/heimdal/lib/roken/copyhostent.c >+++ b/third_party/heimdal/lib/roken/copyhostent.c >@@ -40,7 +40,7 @@ > */ > > ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL >-copyhostent (const struct hostent *h) >+rk_copyhostent(const struct hostent *h) > { > struct hostent *res; > char **p; >@@ -96,4 +96,3 @@ copyhostent (const struct hostent *h) > } > return res; > } >- >diff --git a/third_party/heimdal/lib/roken/detach.c b/third_party/heimdal/lib/roken/detach.c >index 36e6cda1e027..4a00682511fa 100644 >--- a/third_party/heimdal/lib/roken/detach.c >+++ b/third_party/heimdal/lib/roken/detach.c >@@ -75,7 +75,8 @@ roken_detach_prep(int argc, char **argv, char *special_arg) > if (pipefds[1] == -1) > err(1, "Out of memory"); > #else >- fcntl(pipefds[1], F_SETFD, fcntl(pipefds[1], F_GETFD & ~(O_CLOEXEC))); >+ (void) fcntl(pipefds[1], F_SETFD, >+ fcntl(pipefds[1], F_GETFD & ~(O_CLOEXEC))); > #endif > > if (snprintf(fildes, sizeof(fildes), "%d", pipefds[1]) >= sizeof(fildes)) >diff --git a/third_party/heimdal/lib/roken/dirent-test.c b/third_party/heimdal/lib/roken/dirent-test.c >index f1035a1aed6a..dc4518ad5b04 100644 >--- a/third_party/heimdal/lib/roken/dirent-test.c >+++ b/third_party/heimdal/lib/roken/dirent-test.c >@@ -28,7 +28,7 @@ > * OF THE POSSIBILITY OF SUCH DAMAGE. > * > **********************************************************************/ >- >+#include <config.h> > #include <stdio.h> > #include <stdlib.h> > #include <stdarg.h> >@@ -148,7 +148,7 @@ int teardown_test(void) > > strcmp(dirname + len + 1 - sizeof(TESTDIR)/sizeof(char), TESTDIR) == 0) { > >- /* fallthrough */ >+ fallthrough; > > } else { > /* did we create the directory? */ >@@ -162,7 +162,7 @@ int teardown_test(void) > fprintf(stderr, "Can't change to test directory. Aborting cleanup.\n"); > return -1; > } else { >- /* fallthrough */ >+ fallthrough; > } > } else { > return -1; >diff --git a/third_party/heimdal/lib/roken/environment.c b/third_party/heimdal/lib/roken/environment.c >index 64c354d62bbd..a14f27b8a931 100644 >--- a/third_party/heimdal/lib/roken/environment.c >+++ b/third_party/heimdal/lib/roken/environment.c >@@ -62,7 +62,8 @@ find_var(char **env, char *assignment, size_t len) > static int > read_env_file(FILE *F, char ***env, int *assigned) > { >- int idx = 0; >+ size_t alloced = 0; >+ size_t idx = 0; > int i; > char **l; > char buf[BUFSIZ], *p, *r; >@@ -71,8 +72,11 @@ read_env_file(FILE *F, char ***env, int *assigned) > > *assigned = 0; > >- for(idx = 0; *env != NULL && (*env)[idx] != NULL; idx++); > l = *env; >+ for (idx = 0; l != NULL && l[idx] != NULL; idx++) >+ ; >+ if (l) >+ alloced = idx + 1; > > /* This is somewhat more relaxed on what it accepts then > * Wietses sysv_environ from K4 was... >@@ -90,7 +94,11 @@ read_env_file(FILE *F, char ***env, int *assigned) > continue; > > if((i = find_var(l, p, r - p + 1)) >= 0) { >- char *val = strdup(p); >+ char *val; >+ >+ if ((size_t)i >= alloced) >+ continue; /* Doesn't happen (fix scan-build noise) */ >+ val = strdup(p); > if(val == NULL) { > ret = ENOMEM; > break; >@@ -114,6 +122,7 @@ read_env_file(FILE *F, char ***env, int *assigned) > break; > } > l[++idx] = NULL; >+ alloced = idx + 1; > (*assigned)++; > } > if(ferror(F)) >diff --git a/third_party/heimdal/lib/roken/fnmatch.c b/third_party/heimdal/lib/roken/fnmatch.c >index 7dfe492179d1..74f35283d357 100644 >--- a/third_party/heimdal/lib/roken/fnmatch.c >+++ b/third_party/heimdal/lib/roken/fnmatch.c >@@ -129,7 +129,7 @@ rk_fnmatch(const char *pattern, const char *string, int flags) > --pattern; > } > } >- /* FALLTHROUGH */ >+ fallthrough; > default: > if (c != *string++) > return (FNM_NOMATCH); >diff --git a/third_party/heimdal/lib/roken/freeaddrinfo.c b/third_party/heimdal/lib/roken/freeaddrinfo.c >index 7132e95dd38d..80a7487b8d5e 100644 >--- a/third_party/heimdal/lib/roken/freeaddrinfo.c >+++ b/third_party/heimdal/lib/roken/freeaddrinfo.c >@@ -40,7 +40,7 @@ > */ > > ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL >-freeaddrinfo(struct addrinfo *ai) >+rk_freeaddrinfo(struct addrinfo *ai) > { > struct addrinfo *tofree; > >diff --git a/third_party/heimdal/lib/roken/freehostent.c b/third_party/heimdal/lib/roken/freehostent.c >index 61fbb223b5ec..05dd0fe385ce 100644 >--- a/third_party/heimdal/lib/roken/freehostent.c >+++ b/third_party/heimdal/lib/roken/freehostent.c >@@ -40,7 +40,7 @@ > */ > > ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL >-freehostent (struct hostent *h) >+rk_freehostent(struct hostent *h) > { > char **p; > >diff --git a/third_party/heimdal/lib/roken/getaddrinfo.c b/third_party/heimdal/lib/roken/getaddrinfo.c >index c8ed95413fe3..12a26a712259 100644 >--- a/third_party/heimdal/lib/roken/getaddrinfo.c >+++ b/third_party/heimdal/lib/roken/getaddrinfo.c >@@ -366,10 +366,10 @@ get_nodes (const char *nodename, > */ > > ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >-getaddrinfo(const char *nodename, >- const char *servname, >- const struct addrinfo *hints, >- struct addrinfo **res) >+rk_getaddrinfo(const char *nodename, >+ const char *servname, >+ const struct addrinfo *hints, >+ struct addrinfo **res) > { > int ret; > int port = 0; >@@ -409,6 +409,6 @@ getaddrinfo(const char *nodename, > ret = get_null (hints, port, protocol, socktype, res); > } > if (ret) >- freeaddrinfo (*res); >+ rk_freeaddrinfo(*res); > return ret; > } >diff --git a/third_party/heimdal/lib/roken/getcap.c b/third_party/heimdal/lib/roken/getcap.c >deleted file mode 100644 >index a8dd94bef9a9..000000000000 >--- a/third_party/heimdal/lib/roken/getcap.c >+++ /dev/null >@@ -1,996 +0,0 @@ >-/* $NetBSD: getcap.c,v 1.29 1999/03/29 09:27:29 abs Exp $ */ >- >-/*- >- * Copyright (c) 1992, 1993 >- * The Regents of the University of California. All rights reserved. >- * >- * This code is derived from software contributed to Berkeley by >- * Casey Leedom of Lawrence Livermore National Laboratory. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * 3. Neither the name of the University nor the names of its contributors >- * may be used to endorse or promote products derived from this software >- * without specific prior written permission. >- * >- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND >- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE >- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >- * SUCH DAMAGE. >- */ >- >-#include <config.h> >- >-#include "roken.h" >- >-#include <sys/types.h> >-#include <ctype.h> >-#if defined(HAVE_DB_185_H) >-#include <db_185.h> >-#elif defined(HAVE_DB_H) >-#include <db.h> >-#endif >-#include <errno.h> >-#include <fcntl.h> >-#include <limits.h> >-#include <stdio.h> >-#include <stdlib.h> >-#include <string.h> >-#include <unistd.h> >- >-#define BFRAG 1024 >-#define ESC ('[' & 037) /* ASCII ESC */ >-#define MAX_RECURSION 32 /* maximum getent recursion */ >-#define SFRAG 100 /* cgetstr mallocs in SFRAG chunks */ >- >-#define RECOK (char)0 >-#define TCERR (char)1 >-#define SHADOW (char)2 >- >-static size_t topreclen; /* toprec length */ >-static char *toprec; /* Additional record specified by cgetset() */ >-static int gottoprec; /* Flag indicating retrieval of toprecord */ >- >-#ifdef USE_DB >-static int cdbget (DB *, char **, const char *); >-#endif >-static int getent (char **, size_t *, char **, int, const char *, int, char *); >-static int nfcmp (char *, char *); >- >- >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetset(const char *ent); >-ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL cgetcap(char *buf, const char *cap, int type); >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetent(char **buf, char **db_array, const char *name); >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetmatch(const char *buf, const char *name); >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetclose(void); >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetstr(char *buf, const char *cap, char **str); >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetustr(char *buf, const char *cap, char **str); >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetnum(char *buf, const char *cap, long *num); >-/* >- * Cgetset() allows the addition of a user specified buffer to be added >- * to the database array, in effect "pushing" the buffer on top of the >- * virtual database. 0 is returned on success, -1 on failure. >- */ >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >-cgetset(const char *ent) >-{ >- const char *source, *check; >- char *dest; >- >- if (ent == NULL) { >- if (toprec) >- free(toprec); >- toprec = NULL; >- topreclen = 0; >- return (0); >- } >- topreclen = strlen(ent); >- if ((toprec = malloc (topreclen + 1)) == NULL) { >- errno = ENOMEM; >- return (-1); >- } >- gottoprec = 0; >- >- source=ent; >- dest=toprec; >- while (*source) { /* Strip whitespace */ >- *dest++ = *source++; /* Do not check first field */ >- while (*source == ':') { >- check=source+1; >- while (*check && (isspace((unsigned char)*check) || >- (*check=='\\' && isspace((unsigned char)check[1])))) >- ++check; >- if( *check == ':' ) >- source=check; >- else >- break; >- >- } >- } >- *dest=0; >- >- return (0); >-} >- >-/* >- * Cgetcap searches the capability record buf for the capability cap with >- * type `type'. A pointer to the value of cap is returned on success, NULL >- * if the requested capability couldn't be found. >- * >- * Specifying a type of ':' means that nothing should follow cap (:cap:). >- * In this case a pointer to the terminating ':' or NUL will be returned if >- * cap is found. >- * >- * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator) >- * return NULL. >- */ >-ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL >-cgetcap(char *buf, const char *cap, int type) >-{ >- char *bp; >- const char *cp; >- >- bp = buf; >- for (;;) { >- /* >- * Skip past the current capability field - it's either the >- * name field if this is the first time through the loop, or >- * the remainder of a field whose name failed to match cap. >- */ >- for (;;) >- if (*bp == '\0') >- return (NULL); >- else >- if (*bp++ == ':') >- break; >- >- /* >- * Try to match (cap, type) in buf. >- */ >- for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++) >- continue; >- if (*cp != '\0') >- continue; >- if (*bp == '@') >- return (NULL); >- if (type == ':') { >- if (*bp != '\0' && *bp != ':') >- continue; >- return(bp); >- } >- if (*bp != type) >- continue; >- bp++; >- return (*bp == '@' ? NULL : bp); >- } >- /* NOTREACHED */ >-} >- >-/* >- * Cgetent extracts the capability record name from the NULL terminated file >- * array db_array and returns a pointer to a malloc'd copy of it in buf. >- * Buf must be retained through all subsequent calls to cgetcap, cgetnum, >- * cgetflag, and cgetstr, but may then be free'd. 0 is returned on success, >- * -1 if the requested record couldn't be found, -2 if a system error was >- * encountered (couldn't open/read a file, etc.), and -3 if a potential >- * reference loop is detected. >- */ >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >-cgetent(char **buf, char **db_array, const char *name) >-{ >- size_t dummy; >- >- return (getent(buf, &dummy, db_array, -1, name, 0, NULL)); >-} >- >-/* >- * Getent implements the functions of cgetent. If fd is non-negative, >- * *db_array has already been opened and fd is the open file descriptor. We >- * do this to save time and avoid using up file descriptors for tc= >- * recursions. >- * >- * Getent returns the same success/failure codes as cgetent. On success, a >- * pointer to a malloc'ed capability record with all tc= capabilities fully >- * expanded and its length (not including trailing ASCII NUL) are left in >- * *cap and *len. >- * >- * Basic algorithm: >- * + Allocate memory incrementally as needed in chunks of size BFRAG >- * for capability buffer. >- * + Recurse for each tc=name and interpolate result. Stop when all >- * names interpolated, a name can't be found, or depth exceeds >- * MAX_RECURSION. >- */ >-static int >-getent(char **cap, size_t *len, char **db_array, int fd, >- const char *name, int depth, char *nfield) >-{ >- char *r_end, *rp = NULL, **db_p; /* pacify gcc */ >- int myfd = 0, eof, foundit; >- char *record; >- int tc_not_resolved; >- >- /* >- * Return with ``loop detected'' error if we've recursed more than >- * MAX_RECURSION times. >- */ >- if (depth > MAX_RECURSION) >- return (-3); >- >- /* >- * Check if we have a top record from cgetset(). >- */ >- if (depth == 0 && toprec != NULL && cgetmatch(toprec, name) == 0) { >- size_t tmplen = topreclen + BFRAG; >- if ((record = malloc (tmplen)) == NULL) { >- errno = ENOMEM; >- return (-2); >- } >- (void)strlcpy(record, toprec, tmplen); >- db_p = db_array; >- rp = record + topreclen + 1; >- r_end = rp + BFRAG; >- goto tc_exp; >- } >- /* >- * Allocate first chunk of memory. >- */ >- if ((record = malloc(BFRAG)) == NULL) { >- errno = ENOMEM; >- return (-2); >- } >- r_end = record + BFRAG; >- foundit = 0; >- /* >- * Loop through database array until finding the record. >- */ >- >- for (db_p = db_array; *db_p != NULL; db_p++) { >- eof = 0; >- >- /* >- * Open database if not already open. >- */ >- >- if (fd >= 0) { >- (void)lseek(fd, (off_t)0, SEEK_SET); >- } else { >-#ifdef USE_DB >- char pbuf[_POSIX_PATH_MAX]; >- char *cbuf; >- size_t clen; >- int retval; >- DB *capdbp; >- >- (void)snprintf(pbuf, sizeof(pbuf), "%s.db", *db_p); >- if ((capdbp = dbopen(pbuf, O_RDONLY, 0, DB_HASH, 0)) >- != NULL) { >- free(record); >- retval = cdbget(capdbp, &record, name); >- /* record is no longer for us to free here */ >- if (retval < 0) { >- /* no record available */ >- (void)capdbp->close(capdbp); >- return (retval); >- } >- /* save the data; close frees it */ >- clen = strlen(record); >- cbuf = malloc(clen + 1); >- if (cbuf == NULL) >- return (-2); >- memmove(cbuf, record, clen + 1); >- if (capdbp->close(capdbp) < 0) { >- free(cbuf); >- return (-2); >- } >- *len = clen; >- *cap = cbuf; >- return (retval); >- } else >-#endif >- { >- fd = open(*db_p, O_RDONLY, 0); >- if (fd < 0) { >- /* No error on unfound file. */ >- continue; >- } >- myfd = 1; >- } >- } >- /* >- * Find the requested capability record ... >- */ >- { >- char buf[BUFSIZ]; >- char *b_end, *bp, *cp; >- int c, slash; >- >- /* >- * Loop invariants: >- * There is always room for one more character in record. >- * R_end always points just past end of record. >- * Rp always points just past last character in record. >- * B_end always points just past last character in buf. >- * Bp always points at next character in buf. >- * Cp remembers where the last colon was. >- */ >- b_end = buf; >- bp = buf; >- cp = 0; >- slash = 0; >- for (;;) { >- >- /* >- * Read in a line implementing (\, newline) >- * line continuation. >- */ >- rp = record; >- for (;;) { >- if (bp >= b_end) { >- int n; >- >- n = read(fd, buf, sizeof(buf)); >- if (n <= 0) { >- if (myfd) >- (void)close(fd); >- if (n < 0) { >- free(record); >- return (-2); >- } else { >- fd = -1; >- eof = 1; >- break; >- } >- } >- b_end = buf+n; >- bp = buf; >- } >- >- c = *bp++; >- if (c == '\n') { >- if (slash) { >- slash = 0; >- rp--; >- continue; >- } else >- break; >- } >- if (slash) { >- slash = 0; >- cp = 0; >- } >- if (c == ':') { >- /* >- * If the field was `empty' (i.e. >- * contained only white space), back up >- * to the colon (eliminating the >- * field). >- */ >- if (cp) >- rp = cp; >- else >- cp = rp; >- } else if (c == '\\') { >- slash = 1; >- } else if (c != ' ' && c != '\t') { >- /* >- * Forget where the colon was, as this >- * is not an empty field. >- */ >- cp = 0; >- } >- *rp++ = c; >- >- /* >- * Enforce loop invariant: if no room >- * left in record buffer, try to get >- * some more. >- */ >- if (rp >= r_end) { >- u_int pos; >- char *tmp; >- size_t newsize; >- >- pos = rp - record; >- newsize = r_end - record + BFRAG; >- tmp = realloc(record, newsize); >- if (tmp == NULL) { >- errno = ENOMEM; >- if (myfd) >- (void)close(fd); >- free(record); >- return (-2); >- } >- record = tmp; >- r_end = record + newsize; >- rp = record + pos; >- } >- } >- /* Eliminate any white space after the last colon. */ >- if (cp) >- rp = cp + 1; >- /* Loop invariant lets us do this. */ >- *rp++ = '\0'; >- >- /* >- * If encountered eof check next file. >- */ >- if (eof) >- break; >- >- /* >- * Toss blank lines and comments. >- */ >- if (*record == '\0' || *record == '#') >- continue; >- >- /* >- * See if this is the record we want ... >- */ >- if (cgetmatch(record, name) == 0) { >- if (nfield == NULL || !nfcmp(nfield, record)) { >- foundit = 1; >- break; /* found it! */ >- } >- } >- } >- } >- if (foundit) >- break; >- } >- >- if (!foundit) { >- free(record); >- return (-1); >- } >- >- /* >- * Got the capability record, but now we have to expand all tc=name >- * references in it ... >- */ >- tc_exp: { >- char *newicap, *s; >- size_t ilen, newilen; >- int diff, iret, tclen; >- char *icap, *scan, *tc, *tcstart, *tcend; >- >- /* >- * Loop invariants: >- * There is room for one more character in record. >- * R_end points just past end of record. >- * Rp points just past last character in record. >- * Scan points at remainder of record that needs to be >- * scanned for tc=name constructs. >- */ >- scan = record; >- tc_not_resolved = 0; >- for (;;) { >- if ((tc = cgetcap(scan, "tc", '=')) == NULL) >- break; >- >- /* >- * Find end of tc=name and stomp on the trailing `:' >- * (if present) so we can use it to call ourselves. >- */ >- s = tc; >- for (;;) >- if (*s == '\0') >- break; >- else >- if (*s++ == ':') { >- *(s - 1) = '\0'; >- break; >- } >- tcstart = tc - 3; >- tclen = s - tcstart; >- tcend = s; >- >- iret = getent(&icap, &ilen, db_p, fd, tc, depth+1, >- NULL); >- newicap = icap; /* Put into a register. */ >- newilen = ilen; >- if (iret != 0) { >- /* an error */ >- if (iret < -1) { >- if (myfd) >- (void)close(fd); >- free(record); >- return (iret); >- } >- if (iret == 1) >- tc_not_resolved = 1; >- /* couldn't resolve tc */ >- if (iret == -1) { >- *(s - 1) = ':'; >- scan = s - 1; >- tc_not_resolved = 1; >- continue; >- >- } >- } >- /* not interested in name field of tc'ed record */ >- s = newicap; >- for (;;) >- if (*s == '\0') >- break; >- else >- if (*s++ == ':') >- break; >- newilen -= s - newicap; >- newicap = s; >- >- /* make sure interpolated record is `:'-terminated */ >- s += newilen; >- if (*(s-1) != ':') { >- *s = ':'; /* overwrite NUL with : */ >- newilen++; >- } >- >- /* >- * Make sure there's enough room to insert the >- * new record. >- */ >- diff = newilen - tclen; >- if (diff >= r_end - rp) { >- u_int pos, tcpos, tcposend; >- size_t newsize; >- char *tmp; >- >- pos = rp - record; >- newsize = r_end - record + diff + BFRAG; >- tcpos = tcstart - record; >- tcposend = tcend - record; >- tmp = realloc(record, newsize); >- if (tmp == NULL) { >- errno = ENOMEM; >- if (myfd) >- (void)close(fd); >- free(icap); >- free(record); >- return (-2); >- } >- record = tmp; >- r_end = record + newsize; >- rp = record + pos; >- tcstart = record + tcpos; >- tcend = record + tcposend; >- } >- >- /* >- * Insert tc'ed record into our record. >- */ >- s = tcstart + newilen; >- memmove(s, tcend, (size_t)(rp - tcend)); >- memmove(tcstart, newicap, newilen); >- rp += diff; >- free(icap); >- >- /* >- * Start scan on `:' so next cgetcap works properly >- * (cgetcap always skips first field). >- */ >- scan = s-1; >- } >- >- } >- /* >- * Close file (if we opened it), give back any extra memory, and >- * return capability, length and success. >- */ >- if (myfd) >- (void)close(fd); >- *len = rp - record - 1; /* don't count NUL */ >- if (r_end > rp) { >- char *tmp = realloc(record, (size_t)(rp - record)); >- if (tmp == NULL) { >- errno = ENOMEM; >- free(record); >- return (-2); >- } >- record = tmp; >- } >- >- *cap = record; >- if (tc_not_resolved) >- return (1); >- return (0); >-} >- >-#ifdef USE_DB >-static int >-cdbget(DB *capdbp, char **bp, const char *name) >-{ >- DBT key; >- DBT data; >- >- /* LINTED key is not modified */ >- key.data = (char *)name; >- key.size = strlen(name); >- >- for (;;) { >- /* Get the reference. */ >- switch(capdbp->get(capdbp, &key, &data, 0)) { >- case -1: >- return (-2); >- case 1: >- return (-1); >- } >- >- /* If not an index to another record, leave. */ >- if (((char *)data.data)[0] != SHADOW) >- break; >- >- key.data = (char *)data.data + 1; >- key.size = data.size - 1; >- } >- >- *bp = (char *)data.data + 1; >- return (((char *)(data.data))[0] == TCERR ? 1 : 0); >-} >-#endif /* USE_DB */ >- >-/* >- * Cgetmatch will return 0 if name is one of the names of the capability >- * record buf, -1 if not. >- */ >-int >-cgetmatch(const char *buf, const char *name) >-{ >- const char *np, *bp; >- >- /* >- * Start search at beginning of record. >- */ >- bp = buf; >- for (;;) { >- /* >- * Try to match a record name. >- */ >- np = name; >- for (;;) >- if (*np == '\0') { >- if (*bp == '|' || *bp == ':' || *bp == '\0') >- return (0); >- else >- break; >- } else >- if (*bp++ != *np++) >- break; >- >- /* >- * Match failed, skip to next name in record. >- */ >- bp--; /* a '|' or ':' may have stopped the match */ >- for (;;) >- if (*bp == '\0' || *bp == ':') >- return (-1); /* match failed totally */ >- else >- if (*bp++ == '|') >- break; /* found next name */ >- } >-} >- >-static FILE *pfp; >-static int slash; >-static char **dbp; >- >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >-cgetclose(void) >-{ >- if (pfp != NULL) { >- (void)fclose(pfp); >- pfp = NULL; >- } >- dbp = NULL; >- gottoprec = 0; >- slash = 0; >- return(0); >-} >- >-/* >- * Cgetstr retrieves the value of the string capability cap from the >- * capability record pointed to by buf. A pointer to a decoded, NUL >- * terminated, malloc'd copy of the string is returned in the char * >- * pointed to by str. The length of the string not including the trailing >- * NUL is returned on success, -1 if the requested string capability >- * couldn't be found, -2 if a system error was encountered (storage >- * allocation failure). >- */ >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >-cgetstr(char *buf, const char *cap, char **str) >-{ >- u_int m_room; >- const char *bp; >- char *mp; >- int len; >- char *mem, *nmem; >- >- *str = NULL; >- >- /* >- * Find string capability cap >- */ >- bp = cgetcap(buf, cap, '='); >- if (bp == NULL) >- return (-1); >- >- /* >- * Conversion / storage allocation loop ... Allocate memory in >- * chunks SFRAG in size. >- */ >- if ((mem = malloc(SFRAG)) == NULL) { >- errno = ENOMEM; >- return (-2); /* couldn't even allocate the first fragment */ >- } >- m_room = SFRAG; >- mp = mem; >- >- while (*bp != ':' && *bp != '\0') { >- /* >- * Loop invariants: >- * There is always room for one more character in mem. >- * Mp always points just past last character in mem. >- * Bp always points at next character in buf. >- */ >- if (*bp == '^') { >- bp++; >- if (*bp == ':' || *bp == '\0') >- break; /* drop unfinished escape */ >- *mp++ = *bp++ & 037; >- } else if (*bp == '\\') { >- bp++; >- if (*bp == ':' || *bp == '\0') >- break; /* drop unfinished escape */ >- if ('0' <= *bp && *bp <= '7') { >- int n, i; >- >- n = 0; >- i = 3; /* maximum of three octal digits */ >- do { >- n = n * 8 + (*bp++ - '0'); >- } while (--i && '0' <= *bp && *bp <= '7'); >- *mp++ = n; >- } >- else switch (*bp++) { >- case 'b': case 'B': >- *mp++ = '\b'; >- break; >- case 't': case 'T': >- *mp++ = '\t'; >- break; >- case 'n': case 'N': >- *mp++ = '\n'; >- break; >- case 'f': case 'F': >- *mp++ = '\f'; >- break; >- case 'r': case 'R': >- *mp++ = '\r'; >- break; >- case 'e': case 'E': >- *mp++ = ESC; >- break; >- case 'c': case 'C': >- *mp++ = ':'; >- break; >- default: >- /* >- * Catches '\', '^', and >- * everything else. >- */ >- *mp++ = *(bp-1); >- break; >- } >- } else >- *mp++ = *bp++; >- m_room--; >- >- /* >- * Enforce loop invariant: if no room left in current >- * buffer, try to get some more. >- */ >- if (m_room == 0) { >- size_t size = mp - mem; >- >- if ((nmem = realloc(mem, size + SFRAG)) == NULL) { >- free(mem); >- return (-2); >- } >- mem = nmem; >- m_room = SFRAG; >- mp = mem + size; >- } >- } >- *mp++ = '\0'; /* loop invariant let's us do this */ >- m_room--; >- len = mp - mem - 1; >- >- /* >- * Give back any extra memory and return value and success. >- */ >- if (m_room != 0) { >- if ((nmem = realloc(mem, (size_t)(mp - mem))) == NULL) { >- free(mem); >- return (-2); >- } >- mem = nmem; >- } >- *str = mem; >- return (len); >-} >- >-/* >- * Cgetustr retrieves the value of the string capability cap from the >- * capability record pointed to by buf. The difference between cgetustr() >- * and cgetstr() is that cgetustr does not decode escapes but rather treats >- * all characters literally. A pointer to a NUL terminated malloc'd >- * copy of the string is returned in the char pointed to by str. The >- * length of the string not including the trailing NUL is returned on success, >- * -1 if the requested string capability couldn't be found, -2 if a system >- * error was encountered (storage allocation failure). >- */ >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >-cgetustr(char *buf, const char *cap, char **str) >-{ >- u_int m_room; >- const char *bp; >- char *mp; >- int len; >- char *mem; >- >- /* >- * Find string capability cap >- */ >- if ((bp = cgetcap(buf, cap, '=')) == NULL) >- return (-1); >- >- /* >- * Conversion / storage allocation loop ... Allocate memory in >- * chunks SFRAG in size. >- */ >- if ((mem = malloc(SFRAG)) == NULL) { >- errno = ENOMEM; >- return (-2); /* couldn't even allocate the first fragment */ >- } >- m_room = SFRAG; >- mp = mem; >- >- while (*bp != ':' && *bp != '\0') { >- /* >- * Loop invariants: >- * There is always room for one more character in mem. >- * Mp always points just past last character in mem. >- * Bp always points at next character in buf. >- */ >- *mp++ = *bp++; >- m_room--; >- >- /* >- * Enforce loop invariant: if no room left in current >- * buffer, try to get some more. >- */ >- if (m_room == 0) { >- size_t size = mp - mem; >- >- if ((mem = realloc(mem, size + SFRAG)) == NULL) >- return (-2); >- m_room = SFRAG; >- mp = mem + size; >- } >- } >- *mp++ = '\0'; /* loop invariant let's us do this */ >- m_room--; >- len = mp - mem - 1; >- >- /* >- * Give back any extra memory and return value and success. >- */ >- if (m_room != 0) { >- char *tmp = realloc(mem, (size_t)(mp - mem)); >- if (tmp == NULL) { >- free(mem); >- return (-2); >- } >- mem = tmp; >- } >- *str = mem; >- return (len); >-} >- >-/* >- * Cgetnum retrieves the value of the numeric capability cap from the >- * capability record pointed to by buf. The numeric value is returned in >- * the long pointed to by num. 0 is returned on success, -1 if the requested >- * numeric capability couldn't be found. >- */ >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >-cgetnum(char *buf, const char *cap, long *num) >-{ >- long n; >- int base, digit; >- const char *bp; >- >- /* >- * Find numeric capability cap >- */ >- bp = cgetcap(buf, cap, '#'); >- if (bp == NULL) >- return (-1); >- >- /* >- * Look at value and determine numeric base: >- * 0x... or 0X... hexadecimal, >- * else 0... octal, >- * else decimal. >- */ >- if (*bp == '0') { >- bp++; >- if (*bp == 'x' || *bp == 'X') { >- bp++; >- base = 16; >- } else >- base = 8; >- } else >- base = 10; >- >- /* >- * Conversion loop ... >- */ >- n = 0; >- for (;;) { >- if ('0' <= *bp && *bp <= '9') >- digit = *bp - '0'; >- else if ('a' <= *bp && *bp <= 'f') >- digit = 10 + *bp - 'a'; >- else if ('A' <= *bp && *bp <= 'F') >- digit = 10 + *bp - 'A'; >- else >- break; >- >- if (digit >= base) >- break; >- >- n = n * base + digit; >- bp++; >- } >- >- /* >- * Return value and success. >- */ >- *num = n; >- return (0); >-} >- >- >-/* >- * Compare name field of record. >- */ >-static int >-nfcmp(char *nf, char *rec) >-{ >- char *cp, tmp; >- int ret; >- >- for (cp = rec; *cp != ':'; cp++) >- ; >- >- tmp = *(cp + 1); >- *(cp + 1) = '\0'; >- ret = strcmp(nf, rec); >- *(cp + 1) = tmp; >- >- return (ret); >-} >diff --git a/third_party/heimdal/lib/roken/getipnodebyaddr.c b/third_party/heimdal/lib/roken/getipnodebyaddr.c >index 7d4095f1d840..afebe9149500 100644 >--- a/third_party/heimdal/lib/roken/getipnodebyaddr.c >+++ b/third_party/heimdal/lib/roken/getipnodebyaddr.c >@@ -41,7 +41,7 @@ > */ > > ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL >-getipnodebyaddr (const void *src, size_t len, int af, int *error_num) >+rk_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) > { > struct hostent *tmp; > >diff --git a/third_party/heimdal/lib/roken/getipnodebyname.c b/third_party/heimdal/lib/roken/getipnodebyname.c >index 2ff282707c23..ee430c76eb65 100644 >--- a/third_party/heimdal/lib/roken/getipnodebyname.c >+++ b/third_party/heimdal/lib/roken/getipnodebyname.c >@@ -45,7 +45,7 @@ static int h_errno = NO_RECOVERY; > */ > > ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL >-getipnodebyname (const char *name, int af, int flags, int *error_num) >+rk_getipnodebyname(const char *name, int af, int flags, int *error_num) > { > struct hostent *tmp; > >diff --git a/third_party/heimdal/lib/roken/getnameinfo.c b/third_party/heimdal/lib/roken/getnameinfo.c >index b23ad01ebdd9..9d118600f264 100644 >--- a/third_party/heimdal/lib/roken/getnameinfo.c >+++ b/third_party/heimdal/lib/roken/getnameinfo.c >@@ -92,10 +92,10 @@ doit (int af, > */ > > ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >-getnameinfo(const struct sockaddr *sa, socklen_t salen, >- char *host, size_t hostlen, >- char *serv, size_t servlen, >- int flags) >+rk_getnameinfo(const struct sockaddr *sa, socklen_t salen, >+ char *host, size_t hostlen, >+ char *serv, size_t servlen, >+ int flags) > { > switch (sa->sa_family) { > #ifdef HAVE_IPV6 >diff --git a/third_party/heimdal/lib/roken/getuserinfo.c b/third_party/heimdal/lib/roken/getuserinfo.c >index 76cd78241be9..7fd2ca9f151f 100644 >--- a/third_party/heimdal/lib/roken/getuserinfo.c >+++ b/third_party/heimdal/lib/roken/getuserinfo.c >@@ -53,12 +53,12 @@ roken_get_shell(char *shell, size_t shellsz) > char *p; > > #ifndef WIN32 >- char user[128]; >- const char *username = roken_get_username(user, sizeof(user)); >+#ifdef HAVE_GETPWNAM_R > size_t buflen = 2048; > > if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0) > buflen = sysconf(_SC_GETPW_R_SIZE_MAX); >+#endif > > if (issuid()) > return "/bin/sh"; >@@ -76,8 +76,11 @@ roken_get_shell(char *shell, size_t shellsz) > struct passwd pwd; > struct passwd *pwdp; > char buf[buflen]; >+ char user[128]; >+ const char *username = roken_get_username(user, sizeof(user)); > >- if (getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 && >+ if (username && >+ getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 && > pwdp != NULL && pwdp->pw_shell != NULL) { > if (strlcpy(shell, pwdp->pw_shell, shellsz) < shellsz) > return shell; >@@ -133,14 +136,14 @@ roken_get_homedir(char *home, size_t homesz) > } > return home; > } >- /* Fallthru to return NULL */ >+ fallthrough; > #else >- char user[128]; >- const char *username = roken_get_username(user, sizeof(user)); >+#ifdef HAVE_GETPWNAM_R > size_t buflen = 2048; > > if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0) > buflen = sysconf(_SC_GETPW_R_SIZE_MAX); >+#endif > > if (issuid()) { > errno = 0; >@@ -156,12 +159,15 @@ roken_get_homedir(char *home, size_t homesz) > } > > #ifdef HAVE_GETPWNAM_R >- if (username) { >+ { >+ char user[128]; >+ const char *username = roken_get_username(user, sizeof(user)); > struct passwd pwd; > struct passwd *pwdp; > char buf[buflen]; > >- if (getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 && >+ if (username && >+ getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 && > pwdp != NULL && pwdp->pw_dir != NULL) { > if (strlcpy(home, pwdp->pw_dir, homesz) < homesz) > return home; >@@ -255,8 +261,13 @@ roken_get_username(char *user, size_t usersz) > } > } > #else >+#ifdef HAVE_GETPWUID_R > size_t buflen = 2048; > >+ if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0) >+ buflen = sysconf(_SC_GETPW_R_SIZE_MAX); >+#endif >+ > p = secure_getenv("USER"); > if (p == NULL || p[0] == '\0') > p = secure_getenv("LOGNAME"); >@@ -268,9 +279,6 @@ roken_get_username(char *user, size_t usersz) > } > > #ifdef HAVE_GETPWUID_R >- if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0) >- buflen = sysconf(_SC_GETPW_R_SIZE_MAX); >- > { > struct passwd pwd; > struct passwd *pwdp; >diff --git a/third_party/heimdal/lib/roken/hex-test.c b/third_party/heimdal/lib/roken/hex-test.c >index a81422e1f4a5..01f21c821d1a 100644 >--- a/third_party/heimdal/lib/roken/hex-test.c >+++ b/third_party/heimdal/lib/roken/hex-test.c >@@ -43,7 +43,7 @@ main(int argc, char **argv) > int numtest = 1; > struct test { > void *data; >- size_t len; >+ ssize_t len; > const char *result; > } *t, tests[] = { > { "", 0 , "" }, >@@ -55,26 +55,35 @@ main(int argc, char **argv) > { "abcdef", 6, "616263646566" }, > { "abcdefg", 7, "61626364656667" }, > { "=", 1, "3D" }, >+ /* Embedded NUL, non-ASCII / binary */ >+ { "\0\x01\x1a\xad\xf1\xff", 6, "00011AADF1FF" }, >+ /* Invalid encodings */ >+ { "", -1, "00.11AADF1FF" }, >+ { "", -1, "000x1AADF1FF" }, >+ { "", -1, "00011?ADF1FF" }, > { NULL, 0, NULL } > }; > for(t = tests; t->data; t++) { >+ ssize_t len; > char *str; >- int len; >- len = hex_encode(t->data, t->len, &str); >- if(strcmp(str, t->result) != 0) { >- fprintf(stderr, "failed test %d: %s != %s\n", numtest, >- str, t->result); >- numerr++; >- } >- free(str); >+ >+ if (t->len > -1) { >+ (void) hex_encode(t->data, t->len, &str); >+ if (strcmp(str, t->result) != 0) { >+ fprintf(stderr, "failed test %d: %s != %s\n", numtest, >+ str, t->result); >+ numerr++; >+ } >+ free(str); >+ } > str = strdup(t->result); > len = strlen(str); > len = hex_decode(t->result, str, len); >- if(len != t->len) { >- fprintf(stderr, "failed test %d: len %lu != %lu\n", numtest, >- (unsigned long)len, (unsigned long)t->len); >+ if (len != t->len) { >+ fprintf(stderr, "failed test %d: len %lu != %ld\n", numtest, >+ (long)len, (long)t->len); > numerr++; >- } else if(memcmp(str, t->data, t->len) != 0) { >+ } else if (t->len > -1 && memcmp(str, t->data, t->len) != 0) { > fprintf(stderr, "failed test %d: data\n", numtest); > numerr++; > } >diff --git a/third_party/heimdal/lib/roken/hex.c b/third_party/heimdal/lib/roken/hex.c >index c66b324f7900..cc47fa4d52de 100644 >--- a/third_party/heimdal/lib/roken/hex.c >+++ b/third_party/heimdal/lib/roken/hex.c >@@ -39,14 +39,15 @@ > > static const char hexchar[16] = "0123456789ABCDEF"; > >-static int >+static inline int > pos(char c) > { >- const char *p; >- c = toupper((unsigned char)c); >- for (p = hexchar; *p; p++) >- if (*p == c) >- return p - hexchar; >+ if (c >= '0' && c <= '9') >+ return c - '0'; >+ if (c >= 'A' && c <= 'F') >+ return 10 + c - 'A'; >+ if (c >= 'a' && c <= 'f') >+ return 10 + c - 'a'; > return -1; > } > >@@ -86,6 +87,7 @@ hex_decode(const char *str, void *data, size_t len) > size_t l; > unsigned char *p = data; > size_t i; >+ int d; > > l = strlen(str); > >@@ -94,11 +96,19 @@ hex_decode(const char *str, void *data, size_t len) > return -1; > > if (l & 1) { >- p[0] = pos(str[0]); >+ if ((d = pos(str[0])) == -1) >+ return -1; >+ p[0] = d; > str++; > p++; > } >- for (i = 0; i < l / 2; i++) >- p[i] = pos(str[i * 2]) << 4 | pos(str[(i * 2) + 1]); >+ for (i = 0; i < l / 2; i++) { >+ if ((d = pos(str[i * 2])) == -1) >+ return -1; >+ p[i] = d << 4; >+ if ((d = pos(str[(i * 2) + 1])) == -1) >+ return -1; >+ p[i] |= d; >+ } > return i + (l & 1); > } >diff --git a/third_party/heimdal/lib/roken/mergesort_r.c b/third_party/heimdal/lib/roken/mergesort_r.c >index 2d551a607a21..39b0301c4543 100644 >--- a/third_party/heimdal/lib/roken/mergesort_r.c >+++ b/third_party/heimdal/lib/roken/mergesort_r.c >@@ -85,7 +85,7 @@ static void insertionsort(u_char *, size_t, size_t, cmp_t, void *); > */ > /* Assumption: PSIZE is a power of 2. */ > #define EVAL(p) (u_char **) \ >- ((((u_char *)p + PSIZE - 1 - (u_char *) 0) & ~(PSIZE - 1))) >+ ((((uintptr_t)p + PSIZE - 1) & ~(PSIZE - 1))) > > /* > * Arguments are as for qsort_r, except thunk is moved to the last >@@ -114,7 +114,7 @@ mergesort_r(void *base, size_t nmemb, size_t size, cmp_t cmp, void *thunk) > * Stupid subtraction for the Cray. > */ > iflag = 0; >- if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE)) >+ if (!(size % ISIZE) && !(((uintptr_t)base) % ISIZE)) > iflag = 1; > > if ((list2 = malloc(nmemb * size + PSIZE)) == NULL) >diff --git a/third_party/heimdal/lib/roken/ndbm_wrap.c b/third_party/heimdal/lib/roken/ndbm_wrap.c >index f7b87f1203e9..f8403da44ab2 100644 >--- a/third_party/heimdal/lib/roken/ndbm_wrap.c >+++ b/third_party/heimdal/lib/roken/ndbm_wrap.c >@@ -36,6 +36,8 @@ > #include "ndbm_wrap.h" > #if defined(HAVE_DBHEADER) > #include <db.h> >+#elif defined(HAVE_DB6_DB_H) >+#include <db6/db.h> > #elif defined(HAVE_DB5_DB_H) > #include <db5/db.h> > #elif defined(HAVE_DB4_DB_H) >diff --git a/third_party/heimdal/lib/roken/net_write.c b/third_party/heimdal/lib/roken/net_write.c >index 1e8361999ea8..e66f56b75952 100644 >--- a/third_party/heimdal/lib/roken/net_write.c >+++ b/third_party/heimdal/lib/roken/net_write.c >@@ -71,7 +71,7 @@ net_write (rk_socket_t fd, const void *buf, size_t nbytes) > return nbytes; > } > >-#else >+#else /* defined(_WIN32) */ > > ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL > net_write(rk_socket_t sock, const void *buf, size_t nbytes) >@@ -102,6 +102,7 @@ net_write(rk_socket_t sock, const void *buf, size_t nbytes) > count = send (sock, cbuf, rem, 0); > #endif > if (count < 0) { >+#ifdef SOCKET_IS_NOT_AN_FD > if (!use_write) { > switch (rk_SOCK_ERRNO) { > case WSAEINTR: >@@ -111,7 +112,9 @@ net_write(rk_socket_t sock, const void *buf, size_t nbytes) > default: > return count; > } >- } else { >+ } else >+#endif >+ { > switch (errno) { > case EINTR: > continue; >diff --git a/third_party/heimdal/lib/roken/resolve-test.c b/third_party/heimdal/lib/roken/resolve-test.c >index 25cc98aafe3a..581600a5937d 100644 >--- a/third_party/heimdal/lib/roken/resolve-test.c >+++ b/third_party/heimdal/lib/roken/resolve-test.c >@@ -159,7 +159,7 @@ test_rk_dns_srv_order(size_t run) > if (rr->u.srv->priority < prio0 || > (rr->u.srv->priority != prio0 && > (i % 4 != 0 || rr->u.srv->priority > prio0 + 1))) { >- printf("SRV RR order run %lu failed\n", run); >+ printf("SRV RR order run %zu failed\n", run); > fail = 1; > } > prio0 = rr->u.srv->priority; >diff --git a/third_party/heimdal/lib/roken/roken-common.h b/third_party/heimdal/lib/roken/roken-common.h >index f05f88668f3d..035b99b8b973 100644 >--- a/third_party/heimdal/lib/roken/roken-common.h >+++ b/third_party/heimdal/lib/roken/roken-common.h >@@ -472,6 +472,12 @@ vstrcollect(va_list *ap); > ROKEN_LIB_FUNCTION char ** ROKEN_LIB_CALL > strcollect(char *first, ...); > >+ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL >+rk_time_add(time_t, time_t); >+ >+ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL >+rk_time_sub(time_t, time_t); >+ > #define timevalfix rk_timevalfix > ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL > timevalfix(struct timeval *t1); >diff --git a/third_party/heimdal/lib/roken/roken.h.in b/third_party/heimdal/lib/roken/roken.h.in >index e1aa6b7b60c0..e1902f582dcb 100644 >--- a/third_party/heimdal/lib/roken/roken.h.in >+++ b/third_party/heimdal/lib/roken/roken.h.in >@@ -356,7 +356,12 @@ ROKEN_CPP_START > > #define fsync _commit > >-/* The MSVC implementation of snprintf is not C99 compliant. */ >+#define _PIPE_BUFFER_SZ 8192 >+#define pipe(fds) _pipe((fds), _PIPE_BUFFER_SZ, O_BINARY); >+ >+#define ftruncate(fd, sz) _chsize((fd), (sz)) >+ >+#if !defined(HAVE_UCRT) > #define snprintf rk_snprintf > #define vsnprintf rk_vsnprintf > #define vasnprintf rk_vasnprintf >@@ -364,11 +369,6 @@ ROKEN_CPP_START > #define asnprintf rk_asnprintf > #define asprintf rk_asprintf > >-#define _PIPE_BUFFER_SZ 8192 >-#define pipe(fds) _pipe((fds), _PIPE_BUFFER_SZ, O_BINARY); >- >-#define ftruncate(fd, sz) _chsize((fd), (sz)) >- > ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL > rk_snprintf (char *str, size_t sz, const char *format, ...); > >@@ -386,6 +386,7 @@ rk_vasnprintf (char **ret, size_t max_sz, const char *format, va_list args); > > ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL > rk_vsnprintf (char *str, size_t sz, const char *format, va_list args); >+#endif /* !defined(HAVE_UCRT) */ > > /* missing stat.h predicates */ > >@@ -716,13 +717,6 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL mkostemp(char *, int); > ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL mkdtemp(char *); > #endif > >-#ifndef HAVE_CGETENT >-#define cgetent rk_cgetent >-#define cgetstr rk_cgetstr >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetent(char **, char **, const char *); >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetstr(char *, const char *, char **); >-#endif >- > #ifndef HAVE_INITGROUPS > #define initgroups rk_initgroups > ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL initgroups(const char *, gid_t); >@@ -912,27 +906,27 @@ ROKEN_LIB_VARIABLE extern int opterr; > > #ifndef HAVE_GETIPNODEBYNAME > #define getipnodebyname rk_getipnodebyname >-ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL >-getipnodebyname (const char *, int, int, int *); > #endif >+ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL >+rk_getipnodebyname(const char *, int, int, int *); > > #ifndef HAVE_GETIPNODEBYADDR > #define getipnodebyaddr rk_getipnodebyaddr >-ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL >-getipnodebyaddr (const void *, size_t, int, int *); > #endif >+ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL >+rk_getipnodebyaddr(const void *, size_t, int, int *); > > #ifndef HAVE_FREEHOSTENT > #define freehostent rk_freehostent >-ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL >-freehostent (struct hostent *); > #endif >+ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL >+rk_freehostent(struct hostent *); > > #ifndef HAVE_COPYHOSTENT > #define copyhostent rk_copyhostent >-ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL >-copyhostent (const struct hostent *); > #endif >+ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL >+rk_copyhostent(const struct hostent *); > > #ifndef HAVE_SOCKLEN_T > typedef int socklen_t; >@@ -998,27 +992,27 @@ struct addrinfo { > > #ifndef HAVE_GETADDRINFO > #define getaddrinfo rk_getaddrinfo >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >-getaddrinfo(const char *, >- const char *, >- const struct addrinfo *, >- struct addrinfo **); > #endif >+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >+rk_getaddrinfo(const char *, >+ const char *, >+ const struct addrinfo *, >+ struct addrinfo **); > > #ifndef HAVE_GETNAMEINFO > #define getnameinfo rk_getnameinfo >-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >-getnameinfo(const struct sockaddr *, socklen_t, >- char *, size_t, >- char *, size_t, >- int); > #endif >+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL >+rk_getnameinfo(const struct sockaddr *, socklen_t, >+ char *, size_t, >+ char *, size_t, >+ int); > > #ifndef HAVE_FREEADDRINFO > #define freeaddrinfo rk_freeaddrinfo >-ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL >-freeaddrinfo(struct addrinfo *); > #endif >+ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL >+rk_freeaddrinfo(struct addrinfo *); > > #ifndef HAVE_GAI_STRERROR > #define gai_strerror rk_gai_strerror >diff --git a/third_party/heimdal/lib/roken/snprintf.c b/third_party/heimdal/lib/roken/snprintf.c >index 620875f379c8..3da48962ee3a 100644 >--- a/third_party/heimdal/lib/roken/snprintf.c >+++ b/third_party/heimdal/lib/roken/snprintf.c >@@ -515,7 +515,7 @@ xyzprintf (struct snprintf_state *state, const char *char_format, va_list ap) > } > case '\0' : > --format; >- /* FALLTHROUGH */ >+ fallthrough; > case '%' : > (*state->append_char)(state, c); > ++len; >diff --git a/third_party/heimdal/lib/roken/socket.c b/third_party/heimdal/lib/roken/socket.c >index 9feb343f5083..a790e082d822 100644 >--- a/third_party/heimdal/lib/roken/socket.c >+++ b/third_party/heimdal/lib/roken/socket.c >@@ -221,16 +221,16 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL > socket_set_portrange (rk_socket_t sock, int restr, int af) > { > #if defined(IP_PORTRANGE) >- if (af == AF_INET) { >- int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; >- setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on)); >- } >+ if (af == AF_INET) { >+ int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; >+ (void) setsockopt(sock, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on)); >+ } > #endif > #if defined(IPV6_PORTRANGE) >- if (af == AF_INET6) { >- int on = restr ? IPV6_PORTRANGE_HIGH : IPV6_PORTRANGE_DEFAULT; >- setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, sizeof(on)); >- } >+ if (af == AF_INET6) { >+ int on = restr ? IPV6_PORTRANGE_HIGH : IPV6_PORTRANGE_DEFAULT; >+ (void) setsockopt(sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, sizeof(on)); >+ } > #endif > } > >@@ -243,7 +243,7 @@ socket_set_debug (rk_socket_t sock) > { > #if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT) > int on = 1; >- setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on)); >+ (void) setsockopt(sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on)); > #endif > } > >@@ -255,7 +255,7 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL > socket_set_tos (rk_socket_t sock, int tos) > { > #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) >- setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(int)); >+ (void) setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(int)); > #endif > } > >@@ -289,7 +289,8 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL > socket_set_reuseaddr (rk_socket_t sock, int val) > { > #if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) >- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(val)); >+ (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, >+ sizeof(val)); > #endif > } > >@@ -301,7 +302,8 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL > socket_set_ipv6only (rk_socket_t sock, int val) > { > #if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT) >- setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val)); >+ (void) setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, >+ sizeof(val)); > #endif > } > >@@ -312,7 +314,8 @@ socket_set_ipv6only (rk_socket_t sock, int val) > ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL > socket_set_keepalive(rk_socket_t sock, int val) > { >- setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&val, sizeof(val)); >+ (void) setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&val, >+ sizeof(val)); > } > > /** >diff --git a/third_party/heimdal/lib/roken/strftime.c b/third_party/heimdal/lib/roken/strftime.c >index 447c1554337f..9a951dd30080 100644 >--- a/third_party/heimdal/lib/roken/strftime.c >+++ b/third_party/heimdal/lib/roken/strftime.c >@@ -36,6 +36,11 @@ > #include "strpftime-test.h" > #endif > >+#if defined(_WIN32) >+# define timezone _timezone >+# define tzname _tzname >+#endif >+ > static const char *abb_weekdays[] = { > "Sun", > "Mon", >@@ -372,7 +377,7 @@ strftime (char *buf, size_t maxsize, const char *format, > break; > case '\0' : > --format; >- /* FALLTHROUGH */ >+ fallthrough; > case '%' : > ret = snprintf (buf, maxsize - n, > "%%"); >diff --git a/third_party/heimdal/lib/roken/strptime.c b/third_party/heimdal/lib/roken/strptime.c >index 75c27a328773..86216d2d6dcc 100644 >--- a/third_party/heimdal/lib/roken/strptime.c >+++ b/third_party/heimdal/lib/roken/strptime.c >@@ -424,7 +424,7 @@ strptime (const char *buf, const char *format, struct tm *timeptr) > abort (); > case '\0' : > --format; >- /* FALLTHROUGH */ >+ fallthrough; > case '%' : > if (*buf == '%') > ++buf; >diff --git a/third_party/heimdal/lib/roken/strtoll.c b/third_party/heimdal/lib/roken/strtoll.c >index 0d895d54a255..96c1b250974d 100644 >--- a/third_party/heimdal/lib/roken/strtoll.c >+++ b/third_party/heimdal/lib/roken/strtoll.c >@@ -38,6 +38,8 @@ > > #include "roken.h" > >+#ifndef HAVE_STRTOLL >+ > /* #include <sys/cdefs.h> */ > > #include <limits.h> >@@ -150,3 +152,4 @@ noconv: > *endptr = (char *)(any ? s - 1 : nptr); > return ret; > } >+#endif /* !HAVE_STRTOLL */ >diff --git a/third_party/heimdal/lib/roken/strtoull.c b/third_party/heimdal/lib/roken/strtoull.c >index 94530e574d12..0516e18f9135 100644 >--- a/third_party/heimdal/lib/roken/strtoull.c >+++ b/third_party/heimdal/lib/roken/strtoull.c >@@ -38,6 +38,8 @@ > > #include "roken.h" > >+#ifndef HAVE_STRTOULL >+ > /* #include <sys/cdefs.h> */ > > #include <limits.h> >@@ -124,3 +126,4 @@ noconv: > *endptr = (char *)(any ? s - 1 : nptr); > return (acc); > } >+#endif /* !HAVE_STRTOULL */ >diff --git a/third_party/heimdal/lib/roken/test-getuserinfo.c b/third_party/heimdal/lib/roken/test-getuserinfo.c >index b3f15214b56a..4feae177aed6 100644 >--- a/third_party/heimdal/lib/roken/test-getuserinfo.c >+++ b/third_party/heimdal/lib/roken/test-getuserinfo.c >@@ -50,7 +50,8 @@ main(void) > char buf2[MAX_PATH * 2]; > int ret = 0; > if (!issuid() && getuid() != 0) { >- const char *s, *s2; >+ const char *s = NULL; >+ const char *s2 = NULL; > > if (getenv("USER") != NULL && strlen(getenv("USER")) != 0 && > (s = roken_get_username(buf, sizeof(buf))) == NULL) { >diff --git a/third_party/heimdal/lib/roken/test-mini_inetd.c b/third_party/heimdal/lib/roken/test-mini_inetd.c >index 079ace266a1f..7ab996ae8b4c 100644 >--- a/third_party/heimdal/lib/roken/test-mini_inetd.c >+++ b/third_party/heimdal/lib/roken/test-mini_inetd.c >@@ -144,7 +144,7 @@ test_simple_echo_client(void) > } > > if (rv != strlen(test_strings[i])) { >- fprintf (stderr, "[%s] Data length mismatch %d != %d\n", prog, rv, strlen(test_strings[i])); >+ fprintf (stderr, "[%s] Data length mismatch %d != %zu\n", prog, rv, strlen(test_strings[i])); > rk_closesocket(s); > return 1; > } >diff --git a/third_party/heimdal/lib/roken/timeval.c b/third_party/heimdal/lib/roken/timeval.c >index 38b1f7ce9c34..3012513ee7d1 100644 >--- a/third_party/heimdal/lib/roken/timeval.c >+++ b/third_party/heimdal/lib/roken/timeval.c >@@ -39,6 +39,93 @@ > > #include "roken.h" > >+ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL >+rk_time_add(time_t t, time_t delta) >+{ >+ if (delta == 0) >+ return t; >+ >+#ifdef TIME_T_SIGNED >+ /* Signed overflow is UB in C */ >+#if SIZEOF_TIME_T == 4 >+ if (t >= 0 && delta > 0 && INT32_MAX - t < delta) >+ /* Time left to hit INT32_MAX is less than what we want to add */ >+ return INT32_MAX; >+ else if (t == INT32_MIN && delta < 0) >+ /* Avoid computing -t when t == INT32_MIN! */ >+ return INT32_MIN; >+ else if (t < 0 && delta < 0 && INT32_MIN + (-t) > delta) >+ /* Time left to hit INT32_MIN is less than what we want to subtract */ >+ return INT32_MIN; >+ else >+ return t + delta; >+#elif SIZEOF_TIME_T == 8 >+ if (t >= 0 && delta > 0 && INT64_MAX - t < delta) >+ return INT64_MAX; >+ else if (t == INT64_MIN && delta < 0) >+ /* Avoid computing -t when t == INT64_MIN! */ >+ return INT64_MIN; >+ else if (t < 0 && delta < 0 && INT64_MIN + (-t) > delta) >+ return INT64_MIN; >+ else >+ return t + delta; >+#else >+#error "Unexpected sizeof(time_t)" >+#endif >+#else >+ >+ /* Unsigned overflow is defined in C */ >+#if SIZEOF_TIME_T == 4 >+ if (t + delta < t) >+ return UINT32_MAX; >+#elif SIZEOF_TIME_T == 8 >+ if (t + delta < t) >+ return UINT64_MAX; >+#else >+#error "Unexpected sizeof(time_t)" >+#endif >+#endif >+ return t + delta; >+} >+ >+ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL >+rk_time_sub(time_t t, time_t delta) >+{ >+ if (delta == 0) >+ return t; >+#ifdef TIME_T_SIGNED >+ if (delta > 0) >+ return rk_time_add(t, -delta); >+#if SIZEOF_TIME_T == 4 >+ if (delta == INT32_MIN) { >+ if (t < 0) { >+ t = t + INT32_MAX; >+ return t + 1; >+ } >+ return INT32_MAX; >+ } >+ /* Safe to compute -delta, so use rk_time_add() to add -delta */ >+ return rk_time_add(t, -delta); >+#elif SIZEOF_TIME_T == 8 >+ if (delta == INT64_MIN) { >+ if (t < 0) { >+ t = t + INT64_MAX; >+ return t + 1; >+ } >+ return INT64_MAX; >+ } >+ return rk_time_add(t, -delta); >+#else >+#error "Unexpected sizeof(time_t)" >+#endif >+#else >+ /* Both t and delta are non-negative. */ >+ if (delta > t) >+ return 0; >+#endif >+ return t - delta; >+} >+ > /* > * Make `t1' consistent. > */ >@@ -47,11 +134,11 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL > timevalfix(struct timeval *t1) > { > if (t1->tv_usec < 0) { >- t1->tv_sec--; >- t1->tv_usec += 1000000; >+ t1->tv_sec = rk_time_sub(t1->tv_sec, 1); >+ t1->tv_usec = 1000000; > } > if (t1->tv_usec >= 1000000) { >- t1->tv_sec++; >+ t1->tv_sec = rk_time_add(t1->tv_sec, 1); > t1->tv_usec -= 1000000; > } > } >@@ -63,7 +150,7 @@ timevalfix(struct timeval *t1) > ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL > timevaladd(struct timeval *t1, const struct timeval *t2) > { >- t1->tv_sec += t2->tv_sec; >+ t1->tv_sec = rk_time_add(t1->tv_sec, t2->tv_sec); > t1->tv_usec += t2->tv_usec; > timevalfix(t1); > } >@@ -75,7 +162,125 @@ timevaladd(struct timeval *t1, const struct timeval *t2) > ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL > timevalsub(struct timeval *t1, const struct timeval *t2) > { >- t1->tv_sec -= t2->tv_sec; >+ t1->tv_sec = rk_time_sub(t1->tv_sec, t2->tv_sec); > t1->tv_usec -= t2->tv_usec; > timevalfix(t1); > } >+ >+#ifdef TEST >+int >+main(int argc, char **argv) >+{ >+ time_t t, delta, r; >+ int e = 0; >+ >+ if (argc == 0) >+ return 0; /* Apparently POSIX and Linux allow this case */ >+ >+ argc--; >+ argv++; >+ >+ while (argc > 0) { >+ int64_t n; >+ time_t a; >+ char *ends; >+ >+ if (argc < 3) >+ errx(1, "Usage: [TIME +|- DELTA [== TIME]]"); >+ >+ errno = 0; >+ n = strtoll(argv[0], &ends, 0); >+ if (errno) >+ err(1, "Time value is invalid"); >+ if (*ends != '\0') >+ errx(1, "Time value is invalid"); >+ t = n; >+ >+ n = strtoll(argv[2], &ends, 0); >+ if (errno) >+ err(1, "Delta value is invalid"); >+ if (*ends != '\0') >+ errx(1, "Delta value is invalid"); >+ delta = n; >+ >+ if (argv[1][0] == '+' && argv[1][1] == '\0') >+ r = rk_time_add(t, delta); >+ else if (argv[1][0] == '-' && argv[1][1] == '\0') >+ r = rk_time_sub(t, delta); >+ else >+ errx(1, "Operator must be a + or a - arithmetic operator"); >+ >+ if (delta == 0 && r != t) { >+ warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[0]); >+ e = 1; >+ } >+ if (t == 0 && r != delta) { >+ warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[2]); >+ e = 1; >+ } >+ >+ if (argc > 4 && strcmp(argv[3], "==") == 0) { >+ n = strtoll(argv[4], &ends, 0); >+ if (errno) >+ err(1, "Time value is invalid"); >+ if (*ends != '\0') >+ errx(1, "Time value is invalid"); >+ a = n; >+ if (a != r) { >+ warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[4]); >+ e = 1; >+ } >+ argc -= 5; >+ argv += 5; >+ } else { >+#ifdef TIME_T_SIGNED >+ printf("%s %s %s == %lld\n", argv[0], argv[1], argv[2], >+ (long long)r); >+#else >+ printf("%s %s %s == %llu\n", argv[0], argv[1], argv[2], >+ (unsigned long long)r); >+#endif >+ argc -= 3; >+ argv += 3; >+ } >+ } >+ >+#define CHECK(e) do { if (!(e)) errx(1, "Expression not true: " #e "!"); } while (0) >+#ifdef TIME_T_SIGNED >+#if SIZEOF_TIME_T == 4 >+ CHECK(rk_time_add(INT32_MIN, -1) == INT32_MIN); >+ CHECK(rk_time_sub(INT32_MIN, 1) == INT32_MIN); >+ CHECK(rk_time_sub(-1, INT32_MAX) == INT32_MIN); >+ CHECK(rk_time_add(INT32_MAX, 0) == INT32_MAX); >+ CHECK(rk_time_add(INT32_MAX, 1) == INT32_MAX); >+ CHECK(rk_time_add(1, INT32_MAX) == INT32_MAX); >+ CHECK(rk_time_add(0, INT32_MAX) == INT32_MAX); >+#elif SIZEOF_TIME_T == 8 >+ CHECK(rk_time_add(INT64_MIN, -1) == INT64_MIN); >+ CHECK(rk_time_sub(INT64_MIN, 1) == INT64_MIN); >+ CHECK(rk_time_sub(-1, INT64_MAX) == INT64_MIN); >+ CHECK(rk_time_add(INT64_MAX, 0) == INT64_MAX); >+ CHECK(rk_time_add(INT64_MAX, 1) == INT64_MAX); >+ CHECK(rk_time_add(1, INT64_MAX) == INT64_MAX); >+ CHECK(rk_time_add(0, INT64_MAX) == INT64_MAX); >+#endif >+ CHECK(rk_time_add(0, -1) == -1); >+ CHECK(rk_time_sub(0, 1) == -1); >+#else >+#if SIZEOF_TIME_T == 4 >+ CHECK(rk_time_add(UINT32_MAX, 0) == UINT32_MAX); >+ CHECK(rk_time_add(UINT32_MAX, 1) == UINT32_MAX); >+ CHECK(rk_time_add(1, UINT32_MAX) == UINT32_MAX); >+ CHECK(rk_time_add(0, UINT32_MAX) == UINT32_MAX); >+#elif SIZEOF_TIME_T == 8 >+ CHECK(rk_time_add(UINT64_MAX, 0) == UINT64_MAX); >+ CHECK(rk_time_add(UINT64_MAX, 1) == UINT64_MAX); >+ CHECK(rk_time_add(1, UINT64_MAX) == UINT64_MAX); >+ CHECK(rk_time_add(0, UINT64_MAX) == UINT64_MAX); >+#endif >+#endif >+ CHECK(rk_time_add(0, 1) == 1); >+ CHECK(rk_time_add(1, 0) == 1); >+ return e; >+} >+#endif >diff --git a/third_party/heimdal/lib/roken/version-script.map b/third_party/heimdal/lib/roken/version-script.map >index 3307341c0494..be1713e82610 100644 >--- a/third_party/heimdal/lib/roken/version-script.map >+++ b/third_party/heimdal/lib/roken/version-script.map >@@ -2,7 +2,6 @@ HEIMDAL_ROKEN_2.0 { > global: > arg_printusage; > arg_printusage_i18n; >- cgetcap; > cgetclose; > cgetmatch; > cgetnum; >@@ -40,8 +39,6 @@ HEIMDAL_ROKEN_2.0 { > rk_bswap16; > rk_bswap32; > rk_bswap64; >- rk_cgetent; >- rk_cgetstr; > rk_cloexec; > rk_cloexec_dir; > rk_cloexec_file; >@@ -164,6 +161,8 @@ HEIMDAL_ROKEN_2.0 { > rk_tdelete; > rk_tfind; > rk_timegm; >+ rk_time_add; >+ rk_time_sub; > rk_timevaladd; > rk_timevalfix; > rk_timevalsub; >diff --git a/third_party/heimdal/lib/roken/vis.c b/third_party/heimdal/lib/roken/vis.c >index c598967fb72a..0fe44ae35023 100644 >--- a/third_party/heimdal/lib/roken/vis.c >+++ b/third_party/heimdal/lib/roken/vis.c >@@ -377,12 +377,12 @@ rk_strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra > if (flag & VIS_HTTPSTYLE) { > for (start = dst; len > 0; len--) { > c = *src++; >- dst = do_hvis(dst, c, flag, len ? *src : '\0', nextra); >+ dst = do_hvis(dst, c, flag, *src, nextra); > } > } else { > for (start = dst; len > 0; len--) { > c = *src++; >- dst = do_svis(dst, c, flag, len ? *src : '\0', nextra); >+ dst = do_svis(dst, c, flag, *src, nextra); > } > } > free(nextra); >@@ -440,16 +440,18 @@ rk_strrasvisx(char **out, > return -1; > } > if (have < want) { >- if ((s = realloc(*out, want)) == NULL) >+ if ((s = realloc(s, want)) == NULL) > return -1; > *outsz = want; > *out = s; > } >+ if (*out == NULL) { >+ errno = EINVAL; >+ return -1; >+ } > **out = '\0'; /* Makes source debugging nicer, that's all */ >- if ((r = strsvisx(*out, csrc, len, flag, extra)) < 0) >- return r; >- errno = *out ? errno : EINVAL; >- return *out ? r : -1; >+ r = strsvisx(*out, csrc, len, flag, extra); >+ return r; > } > > #if !HAVE_VIS >@@ -641,6 +643,7 @@ main(int argc, char **argv) > } > > free(nextra); >+ free(s); > return 0; > } > #endif >diff --git a/third_party/heimdal/lib/sl/Makefile.am b/third_party/heimdal/lib/sl/Makefile.am >index 152b86a330a2..1213d8c9df97 100644 >--- a/third_party/heimdal/lib/sl/Makefile.am >+++ b/third_party/heimdal/lib/sl/Makefile.am >@@ -8,7 +8,7 @@ endif > > AM_CPPFLAGS += $(ROKEN_RENAME) > >-YFLAGS = -d >+YFLAGS = -d -o slc-gram.c > LFLAGS = @FLEXNOUNPUTARGS@ > > include_HEADERS = sl.h >diff --git a/third_party/heimdal/lib/sl/sl.c b/third_party/heimdal/lib/sl/sl.c >index 03f577b5f594..b78f9f675b25 100644 >--- a/third_party/heimdal/lib/sl/sl.c >+++ b/third_party/heimdal/lib/sl/sl.c >@@ -460,6 +460,8 @@ sl_did_you_mean(SL_cmd *cmds, const char *match) > > for (n = 0, c = cmds; c->name; c++, n++) > ; >+ if (n == 0) >+ return; > metrics = calloc(n, sizeof(metrics[0])); > if (metrics == NULL) > return; >diff --git a/third_party/heimdal/lib/sl/slc-gram.y b/third_party/heimdal/lib/sl/slc-gram.y >index 767ffc833c86..38045c10048a 100644 >--- a/third_party/heimdal/lib/sl/slc-gram.y >+++ b/third_party/heimdal/lib/sl/slc-gram.y >@@ -689,6 +689,7 @@ gen_wrapper(struct assignment *as) > cprint(1, "return 0;\n"); > cprint(0, "}\n"); > cprint(0, "\n"); >+ free(n); > } > > char cname[PATH_MAX]; >diff --git a/third_party/heimdal/lib/wind/idn-lookup.c b/third_party/heimdal/lib/wind/idn-lookup.c >index 1bc63a33dd8a..378c912a392d 100644 >--- a/third_party/heimdal/lib/wind/idn-lookup.c >+++ b/third_party/heimdal/lib/wind/idn-lookup.c >@@ -156,7 +156,9 @@ main(int argc, char **argv) > if (argc == 0) > usage(1); > >- for (i = 0; i < argc; ++i) >- lookup(argv[i]); >+ for (i = 0; i < argc; ++i) { >+ if (argv[i][0]) /* Quiet lint */ >+ lookup(argv[i]); >+ } > return 0; > } >diff --git a/third_party/heimdal/lib/wind/utf8.c b/third_party/heimdal/lib/wind/utf8.c >index d69db0c0cec1..452b7b260d84 100644 >--- a/third_party/heimdal/lib/wind/utf8.c >+++ b/third_party/heimdal/lib/wind/utf8.c >@@ -205,18 +205,20 @@ wind_ucs4utf8(const uint32_t *in, size_t in_len, char *out, size_t *out_len) > case 4: > out[3] = (ch | 0x80) & 0xbf; > ch = ch >> 6; >- /* FALLTHROUGH */ >+ fallthrough; > case 3: > out[2] = (ch | 0x80) & 0xbf; > ch = ch >> 6; >- /* FALLTHROUGH */ >+ fallthrough; > case 2: > out[1] = (ch | 0x80) & 0xbf; > ch = ch >> 6; >- /* FALLTHROUGH */ >+ fallthrough; > case 1: > out[0] = ch | first_char[len - 1]; >- /* FALLTHROUGH */ >+ fallthrough; >+ default: >+ break; > } > } > out += len; >@@ -484,14 +486,16 @@ wind_ucs2utf8(const uint16_t *in, size_t in_len, char *out, size_t *out_len) > case 3: > out[2] = (ch | 0x80) & 0xbf; > ch = ch >> 6; >- /* FALLTHROUGH */ >+ fallthrough; > case 2: > out[1] = (ch | 0x80) & 0xbf; > ch = ch >> 6; >- /* FALLTHROUGH */ >+ fallthrough; > case 1: > out[0] = ch | first_char[len - 1]; >- /* FALLTHROUGH */ >+ fallthrough; >+ default: >+ break; > } > out += len; > } >diff --git a/third_party/heimdal/packages/windows/installer/NTMakefile b/third_party/heimdal/packages/windows/installer/NTMakefile >index ad63ae04f4c8..2923e649b969 100644 >--- a/third_party/heimdal/packages/windows/installer/NTMakefile >+++ b/third_party/heimdal/packages/windows/installer/NTMakefile >@@ -133,7 +133,13 @@ clean:: > ###################################################################### > # Runtime modules > >-!if [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==16 >+!if [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==19 >+VCVER=VC2019 >+!elseif [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==18 >+VCVER=VC2018 >+!elseif [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==17 >+VCVER=VC2017 >+!elseif [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==16 > VCVER=VC100 > !elseif [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==15 > VCVER=VC90 >@@ -164,22 +170,27 @@ MMDIR=$(SystemDrive)\Program Files (x86)\Common Files\Merge Modules > !endif > !endif > >-!if exist("$(MMDIR)") >- >-RUNTIMEMODULE32="$(MMDIR)\Microsoft_$(VCVER)_$(CRTNAME)_x86.msm" >-!if "$(VCVER)"=="VC100" >-RUNTIMEMODULE64="$(MMDIR)\Microsoft_$(VCVER)_$(CRTNAME)_x64.msm" >+# >+# Don't specify a runtime module when the Universal C Runtime >+# is available. >+# >+!if "$(APPVER)"=="10.0" >+RUNTIMEMODULE32="" >+RUNTIMEMODULE64="" > !else >+! if exist("$(MMDIR)") >+RUNTIMEMODULE32="$(MMDIR)\Microsoft_$(VCVER)_$(CRTNAME)_x86.msm" >+! if "$(VCVER)"=="VC90" || "$(VCVER)"=="VC80" > RUNTIMEMODULE64="$(MMDIR)\Microsoft_$(VCVER)_$(CRTNAME)_x86_x64.msm" >-!endif >- >-!else >+! else >+RUNTIMEMODULE64="$(MMDIR)\Microsoft_$(VCVER)_$(CRTNAME)_x64.msm" >+! endif >+! else > RUNTIMEMODULE32="$(MSSDK)\Redist\VC\microsoft.vcxx.crt.x86_msm.msm" > RUNTIMEMODULE64="$(MSSDK)\Redist\VC\microsoft.vcxx.crt.x64_msm.msm" >- >+! endif > !endif > >- > ###################################################################### > # Heimdal installer > >diff --git a/third_party/heimdal/packages/windows/installer/heimdal-installer.wxs b/third_party/heimdal/packages/windows/installer/heimdal-installer.wxs >index 0b6000d1bfa0..8ac6cc665fdb 100644 >--- a/third_party/heimdal/packages/windows/installer/heimdal-installer.wxs >+++ b/third_party/heimdal/packages/windows/installer/heimdal-installer.wxs >@@ -99,9 +99,10 @@ > <Merge Id='Heimdal.Policy.32' Language='0' > SourceFile='$(var.InstDir32)\Heimdal.Policy.msm' /> > >- <Merge Id='Runtime.32' Language='0' >- SourceFile='$(var.RuntimeModule32)' /> >- >+ <?if "$(var.RuntimeModule32)" != "" ?> >+ <Merge Id='Runtime.32' Language='0' >+ SourceFile='$(var.RuntimeModule32)' /> >+ <?endif?> > </DirectoryRef> > <?endif?> > >@@ -127,9 +128,10 @@ > <Merge Id='Heimdal.Policy.64' Language='0' > SourceFile='$(var.InstDir64)\Heimdal.Policy.msm' /> > >- <Merge Id='Runtime.64' Language='0' >- SourceFile='$(var.RuntimeModule64)' /> >- >+ <?if "$(var.RuntimeModule64)" != "" ?> >+ <Merge Id='Runtime.64' Language='0' >+ SourceFile='$(var.RuntimeModule64)' /> >+ <?endif?> > </DirectoryRef> > <?endif?> > >@@ -370,12 +372,12 @@ > <MergeRef Id='Heimdal.Assemblies.64' /> > <MergeRef Id='Heimdal.GSS.64' /> > <MergeRef Id='Heimdal.Policy.64' /> >- <MergeRef Id='Runtime.64' /> >+ <?if "$(var.RuntimeModule64)" != "" ?><MergeRef Id='Runtime.64' /><?endif?> > <?else?> > <MergeRef Id='Heimdal.Assemblies.32' /> > <MergeRef Id='Heimdal.GSS.32' /> > <MergeRef Id='Heimdal.Policy.32' /> >- <MergeRef Id='Runtime.32' /> >+ <?if "$(var.RuntimeModule32)" != "" ?><MergeRef Id='Runtime.32' /><?endif?> > <?endif?> > > <?ifdef Target32?> >@@ -393,7 +395,7 @@ > <MergeRef Id='Heimdal.Assemblies.32' /> > <MergeRef Id='Heimdal.GSS.32' /> > <MergeRef Id='Heimdal.Policy.32' /> >- <MergeRef Id='Runtime.32' /> >+ <?if "$(var.RuntimeModule32)" != "" ?><MergeRef Id='Runtime.32' /><?endif?> > </Feature> > <?endif?> > <?endif?> >diff --git a/third_party/heimdal/tests/bin/setup-env.in b/third_party/heimdal/tests/bin/setup-env.in >index 954a2c1d5f5f..c9291d08bf20 100644 >--- a/third_party/heimdal/tests/bin/setup-env.in >+++ b/third_party/heimdal/tests/bin/setup-env.in >@@ -28,6 +28,7 @@ kadmin="${TESTS_ENVIRONMENT} ${top_builddir}/kadmin/kadmin" > kadmind="${TESTS_ENVIRONMENT} ${top_builddir}/kadmin/kadmind" > kdc="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/kdc" > kdc_tester="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/kdc-tester" >+kcm="${TESTS_ENVIRONMENT} ${top_builddir}/kcm/kcm" > test_csr_authorizer="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/test_csr_authorizer" > test_kdc_ca="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/test_kdc_ca" > test_token_validator="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/test_token_validator" >diff --git a/third_party/heimdal/tests/gss/Makefile.am b/third_party/heimdal/tests/gss/Makefile.am >index ca40ae26bd2d..2de36bfe24cf 100644 >--- a/third_party/heimdal/tests/gss/Makefile.am >+++ b/third_party/heimdal/tests/gss/Makefile.am >@@ -95,7 +95,9 @@ EXTRA_DIST = \ > check-spnego.in \ > check-ntlm.in \ > check-context.in \ >+ check-negoex.in \ > ntlm-user-file.txt \ > krb5.conf.in \ >+ include-krb5.conf \ > new_clients_k5.conf.in \ > mech.in >diff --git a/third_party/heimdal/tests/gss/check-basic.in b/third_party/heimdal/tests/gss/check-basic.in >index d4916bd46d4b..c5151c4c94f1 100644 >--- a/third_party/heimdal/tests/gss/check-basic.in >+++ b/third_party/heimdal/tests/gss/check-basic.in >@@ -94,10 +94,10 @@ echo "Doing database check" > ${kadmin} check ${R} || exit 1 > > echo Starting kdc >-${kdc} --testing --detach || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > >-trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >+trap "kill -9 ${kdcpid}; echo signal killing kdc; cat messages.log; exit 1;" EXIT > > exitcode=0 > >diff --git a/third_party/heimdal/tests/gss/check-context.in b/third_party/heimdal/tests/gss/check-context.in >index 42ea15eecb9c..46c058d068b4 100644 >--- a/third_party/heimdal/tests/gss/check-context.in >+++ b/third_party/heimdal/tests/gss/check-context.in >@@ -115,10 +115,10 @@ ${kadmin} check ${R} || exit 1 > echo u1 > ${objdir}/foopassword > > echo Starting kdc >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > >-trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT > > testfailed="echo test failed; cat messages.log; exit 1" > >@@ -245,6 +245,14 @@ for mech in krb5 krb5iov spnego spnegoiov; do > { eval "$testfailed"; } > done > >+echo "======test authz-data (krb5)" >+${context} --mech-type=krb5 \ >+ --mutual \ >+ --wrapunwrap \ >+ --on-behalf-of=foo@BAR.TEST.H5L.SE \ >+ --name-type=hostbased-service host@lucid.test.h5l.se || >+ { eval "$testfailed"; } >+ > echo "======dce-style" > for mech in krb5 krb5iov spnego; do > iov="" >diff --git a/third_party/heimdal/tests/gss/check-gssmask.in b/third_party/heimdal/tests/gss/check-gssmask.in >index 44769eff5840..539e2e94e527 100644 >--- a/third_party/heimdal/tests/gss/check-gssmask.in >+++ b/third_party/heimdal/tests/gss/check-gssmask.in >@@ -93,10 +93,10 @@ echo "Doing database check" > ${kadmin} check ${R} || exit 1 > > echo Starting kdc >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > >-trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT > > exitcode=0 > >diff --git a/third_party/heimdal/tests/gss/check-ntlm.in b/third_party/heimdal/tests/gss/check-ntlm.in >index f5bf3446ae61..f953630d09db 100644 >--- a/third_party/heimdal/tests/gss/check-ntlm.in >+++ b/third_party/heimdal/tests/gss/check-ntlm.in >@@ -107,10 +107,10 @@ echo u1 > ${objdir}/foopassword > echo ds > ${objdir}/barpassword > > echo Starting kdc >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > >-trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT > > exitcode=0 > >diff --git a/third_party/heimdal/tests/gss/check-spnego.in b/third_party/heimdal/tests/gss/check-spnego.in >index 3cf560896021..d6e4d8331529 100644 >--- a/third_party/heimdal/tests/gss/check-spnego.in >+++ b/third_party/heimdal/tests/gss/check-spnego.in >@@ -106,10 +106,10 @@ echo u1 > ${objdir}/foopassword > echo ds > ${objdir}/barpassword > > echo Starting kdc >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > >-trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT > > exitcode=0 > >diff --git a/third_party/heimdal/tests/gss/krb5.conf.in b/third_party/heimdal/tests/gss/krb5.conf.in >index b8e04b65159e..aae031db645e 100644 >--- a/third_party/heimdal/tests/gss/krb5.conf.in >+++ b/third_party/heimdal/tests/gss/krb5.conf.in >@@ -18,6 +18,21 @@ include @srcdirabs@/include-krb5.conf > } > > [kdc] >+ enable-digest = true >+ allow-anonymous = true >+ digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2 >+ strict-nametypes = true >+ synthetic_clients = true >+ enable_gss_preauth = true >+ gss_mechanisms_allowed = sanon-x25519 >+ enable-pkinit = true >+ pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key >+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt >+ pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt >+# pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl >+ pkinit_mappings_file = @srcdir@/pki-mapping >+ pkinit_allow_proxy_certificate = true >+ > database = { > dbname = @objdir@/current-db > realm = TEST.H5L.SE >diff --git a/third_party/heimdal/tests/java/check-kinit.in b/third_party/heimdal/tests/java/check-kinit.in >index 04043ca02e21..820334474095 100644 >--- a/third_party/heimdal/tests/java/check-kinit.in >+++ b/third_party/heimdal/tests/java/check-kinit.in >@@ -90,7 +90,7 @@ ${kadmin} add -p kaka --use-defaults ${server}@${R} || exit 1 > ${kadmin} ext -k ${keytab} ${server}@${R} || exit 1 > > echo Starting kdc >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >diff --git a/third_party/heimdal/tests/kdc/Makefile.am b/third_party/heimdal/tests/kdc/Makefile.am >index a07f776eb23c..f61a7e853077 100644 >--- a/third_party/heimdal/tests/kdc/Makefile.am >+++ b/third_party/heimdal/tests/kdc/Makefile.am >@@ -4,6 +4,7 @@ noinst_DATA = \ > an2ln-db.txt \ > kdc-tester4.json \ > krb5.conf \ >+ krb5-kcm.conf \ > krb5-cccol.conf \ > krb5-authz.conf \ > krb5-authz2.conf \ >@@ -204,6 +205,13 @@ krb5.conf: krb5.conf.in Makefile > -e 's,[@]kdc[@],,g' < $(srcdir)/krb5.conf.in > krb5.conf.tmp && \ > mv krb5.conf.tmp krb5.conf > >+krb5-kcm.conf: krb5-kcm.conf.in Makefile >+ $(do_subst) \ >+ -e 's,[@]WEAK[@],false,g' \ >+ -e 's,[@]dk[@],,g' \ >+ -e 's,[@]kdc[@],,g' < $(srcdir)/krb5-kcm.conf.in > krb5-kcm.conf.tmp && \ >+ mv krb5-kcm.conf.tmp krb5-kcm.conf >+ > krb5-cccol.conf: krb5-cccol.conf.in Makefile > $(do_subst) \ > -e 's,[@]WEAK[@],false,g' \ >@@ -383,23 +391,23 @@ EXTRA_DIST = \ > NTMakefile \ > an2ln-db.txt \ > check-authz.in \ >+ check-bx509.in \ > check-canon.in \ > check-cc.in \ > check-delegation.in \ > check-des.in \ > check-digest.in \ > check-fast.in \ >+ check-hdb-mitdb.in \ >+ check-httpkadmind.in \ > check-iprop.in \ > check-kadmin.in \ >- check-kinit.in \ >- check-hdb-mitdb.in \ >- check-kdc.in \ > check-kdc-weak.in \ >+ check-kdc.in \ > check-keys.in \ >+ check-kinit.in \ > check-kpasswdd.in \ > check-pkinit.in \ >- check-bx509.in \ >- check-httpkadmind.in \ > check-referral.in \ > check-tester.in \ > check-uu.in \ >@@ -409,23 +417,25 @@ EXTRA_DIST = \ > hdb-mitdb.mkey \ > heimdal.acl \ > iprop-acl \ >+ k5login/foo \ >+ k5login/mapped_user1 \ > kdc-tester1.json \ > kdc-tester2.json \ > kdc-tester3.json \ > kdc-tester4.json.in \ >- krb5-pkinit.conf.in \ >- krb5-bx509.conf.in \ >- krb5-httpkadmind.conf.in \ >- krb5.conf.in \ > krb5-authz.conf.in \ > krb5-authz2.conf.in \ >+ krb5-bx509.conf.in \ > krb5-canon.conf.in \ > krb5-canon2.conf.in \ >+ krb5-cccol.conf.in \ > krb5-hdb-mitdb.conf.in \ >+ krb5-httpkadmind.conf.in \ >+ krb5-pkinit.conf.in \ >+ krb5.conf.in \ > krb5.conf.keys.in \ >- k5login/foo \ >- ntlm-user-file.txt \ > leaks-kill.sh \ >+ ntlm-user-file.txt \ > pki-mapping \ > uuserver.txt \ > wait-kdc.sh >diff --git a/third_party/heimdal/tests/kdc/check-bx509.in b/third_party/heimdal/tests/kdc/check-bx509.in >index 1cef2e0e766d..b50239d84400 100644 >--- a/third_party/heimdal/tests/kdc/check-bx509.in >+++ b/third_party/heimdal/tests/kdc/check-bx509.in >@@ -428,7 +428,7 @@ ${kadmin} add -r --use-defaults HTTP/${otherserver}@${R} || exit 1 > ${kadmin} ext_keytab -r -k $ukeytab foo@${R} || exit 1 > > echo "Starting kdc"; >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > trap "kill -9 ${kdcpid} ${bx509pid}; echo signal killing kdc and bx509d; exit 1;" EXIT > >@@ -590,7 +590,8 @@ KRB5CCNAME=$cache $gsstoken HTTP@$server | KRB5_KTNAME="$keytab" $gsstoken -r || > { echo "Trivial offline CA test failed (gss-token)"; exit 2; } > > # Check that we get up to three tixaddrs k/v in the log >-grep 'REQ.*numtixaddrs=4 tixaddrs=IPv4:8.8.8.8 tixaddrs=IPv4:8.9.10.11 tixaddrs=IPv4:11.11.11.11.*wrongaddr=yes' ${objdir}/messages.log || >+grep 'REQ.*wrongaddr=true' ${objdir}/messages.log | >+ grep 'tixaddrs=IPv4:11.11.11.11' || > { echo "KDC not warning about requests from wrong address"; exit 2; } > > echo "Fetching a Negotiate token" >diff --git a/third_party/heimdal/tests/kdc/check-canon.in b/third_party/heimdal/tests/kdc/check-canon.in >index 0bb5a413f3cf..18b83a9b7a69 100644 >--- a/third_party/heimdal/tests/kdc/check-canon.in >+++ b/third_party/heimdal/tests/kdc/check-canon.in >@@ -99,7 +99,7 @@ ${kadmin} check ${R3} || exit 1 > echo foo > ${objdir}/foopassword > > echo "Starting kdc" ; > messages.log >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >diff --git a/third_party/heimdal/tests/kdc/check-cc.in b/third_party/heimdal/tests/kdc/check-cc.in >index ce95b300664a..46e846a10ea1 100644 >--- a/third_party/heimdal/tests/kdc/check-cc.in >+++ b/third_party/heimdal/tests/kdc/check-cc.in >@@ -86,9 +86,16 @@ ${kadmin} check ${R} || exit 1 > echo foo > ${objdir}/foopassword > > echo Starting kdc ; > messages.log >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > >+echo Starting kcm ; > messages.log >+${kcm} -s ${objdir} --detach || { echo "kcm failed to start"; cat messages.log; exit 1; } >+kcmpid=`getpid kcm` >+ >+HEIM_IPC_DIR=${objdir} >+export HEIM_IPC_DIR >+ > trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT > > ec=0 >@@ -133,6 +140,41 @@ ${klist} -l | grep foo@ >/dev/null && { ec=1 ; eval "${testfailed}"; } > echo "check that bar is gone" > ${klist} -l | grep bar@ >/dev/null && { ec=1 ; eval "${testfailed}"; } > >+echo "getting tickets (KCM)"; > messages.log >+KRB5_CONFIG="${objdir}/krb5-kcm.conf" >+export KRB5_CONFIG >+unset KRB5CCNAME >+${kinit} --default-for-principal foo@${R} >+${kinit} --default-for-principal bar@${R} >+${kinit} bar@${R} >+${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+${klist} | grep foo@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; } >+${klist} -l | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+${klist} -l | grep foo@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+${klist} -c KCM: | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+KRB5CCNAME=KCM: ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+if [ -n "$BASH_VERSION" ]; then >+ ${klist} -c KCM:${UID} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+ ${klist} -c KCM:${UID}: | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+ KRB5CCNAME=KCM:${UID} ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+ KRB5CCNAME=KCM:${UID}: ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+fi >+${kdestroy} -A >+${klist} 2>/dev/null && { ec=1 ; eval "${testfailed}"; } >+${klist} -l | grep bar@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; } >+${klist} -l | grep foo@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; } >+${kinit} bar@${R} >+${kinit} --default-for-principal foo@${R} >+${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+${klist} | grep foo@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; } >+${klist} -l | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+${klist} -l | grep foo@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+${klist} -c KCM: | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+KRB5CCNAME=KCM: ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; } >+${kdestroy} -A >+ > echo "getting tickets (DIR)"; > messages.log > KRB5_CONFIG="${objdir}/krb5-cccol.conf" > export KRB5_CONFIG >@@ -150,6 +192,9 @@ ${klist} -l | > grep "bar@TEST.H5L.SE.*FILE:${objdir}/cc_dir/tkt.bar@TEST.H5L.SE" > /dev/null || > { ec=1 ; eval "${testfailed}"; } > >+echo "killing kcm (${kcmpid})" >+sh ${leaks_kill} kcm $kcmpid || exit 1 >+ > echo "killing kdc (${kdcpid})" > sh ${leaks_kill} kdc $kdcpid || exit 1 > >diff --git a/third_party/heimdal/tests/kdc/check-delegation.in b/third_party/heimdal/tests/kdc/check-delegation.in >index 8657946168ad..fdff0f6a0f0f 100644 >--- a/third_party/heimdal/tests/kdc/check-delegation.in >+++ b/third_party/heimdal/tests/kdc/check-delegation.in >@@ -102,7 +102,7 @@ ${kadmin} check ${R4} || exit 1 > echo foo > ${objdir}/foopassword > > echo Starting kdc; > messages.log >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >diff --git a/third_party/heimdal/tests/kdc/check-des.in b/third_party/heimdal/tests/kdc/check-des.in >index d45b119dfa5d..144613df4f99 100644 >--- a/third_party/heimdal/tests/kdc/check-des.in >+++ b/third_party/heimdal/tests/kdc/check-des.in >@@ -96,7 +96,7 @@ ${kadmin} check ${R} || exit 1 > echo foo > ${objdir}/foopassword > > echo Starting kdc; > messages.log >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >diff --git a/third_party/heimdal/tests/kdc/check-digest.in b/third_party/heimdal/tests/kdc/check-digest.in >index 1623783eba6d..d934f4e28983 100644 >--- a/third_party/heimdal/tests/kdc/check-digest.in >+++ b/third_party/heimdal/tests/kdc/check-digest.in >@@ -95,7 +95,7 @@ echo $password > ${objdir}/foopassword > > echo "Starting kdc" ; > messages.log > env ${HEIM_MALLOC_DEBUG} ${kdc} --detach --testing || >- { echo "kdc failed to start"; exit 1; } >+ { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill -9 ${kdcpid}; echo signal killing kdc; cat messages.log; exit 1;" EXIT >diff --git a/third_party/heimdal/tests/kdc/check-fast.in b/third_party/heimdal/tests/kdc/check-fast.in >index 136bf3ed62b0..3fbda813a63b 100644 >--- a/third_party/heimdal/tests/kdc/check-fast.in >+++ b/third_party/heimdal/tests/kdc/check-fast.in >@@ -88,7 +88,7 @@ echo bar > ${objdir}/barpassword > > echo Starting kdc ; > messages.log > env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \ >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill -9 ${kdcpid}; echo signal killing kdc; cat messages.log; exit 1;" EXIT >diff --git a/third_party/heimdal/tests/kdc/check-hdb-mitdb.in b/third_party/heimdal/tests/kdc/check-hdb-mitdb.in >index e9de58799a31..a241aeb4a8ff 100644 >--- a/third_party/heimdal/tests/kdc/check-hdb-mitdb.in >+++ b/third_party/heimdal/tests/kdc/check-hdb-mitdb.in >@@ -85,7 +85,7 @@ echo foo > ${objdir}/foopassword > > echo Starting kdc ; > messages.log > env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \ >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >diff --git a/third_party/heimdal/tests/kdc/check-httpkadmind.in b/third_party/heimdal/tests/kdc/check-httpkadmind.in >index b593925a3524..f57f2af85928 100644 >--- a/third_party/heimdal/tests/kdc/check-httpkadmind.in >+++ b/third_party/heimdal/tests/kdc/check-httpkadmind.in >@@ -519,7 +519,7 @@ ${hxtool} issue-certificate \ > { echo "Failed to make PKINIT client cert"; exit 1; } > > echo "Starting kdc needed for httpkadmind authentication to kadmind" >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > echo "Starting httpkadmind with remote HDBs only" >diff --git a/third_party/heimdal/tests/kdc/check-iprop.in b/third_party/heimdal/tests/kdc/check-iprop.in >index 212968779435..524379393faa 100644 >--- a/third_party/heimdal/tests/kdc/check-iprop.in >+++ b/third_party/heimdal/tests/kdc/check-iprop.in >@@ -314,7 +314,7 @@ cleanup() { > trap cleanup EXIT > > echo Starting kdc ; > messages.log >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > echo "starting master" ; > messages.log >diff --git a/third_party/heimdal/tests/kdc/check-kadmin.in b/third_party/heimdal/tests/kdc/check-kadmin.in >index 3d3f41003d86..45d679ceb4a4 100644 >--- a/third_party/heimdal/tests/kdc/check-kadmin.in >+++ b/third_party/heimdal/tests/kdc/check-kadmin.in >@@ -97,7 +97,7 @@ ${kadmin} -l cpw --pruneall --random-key pruneall@${R} || exit 1 > echo "$foopassword" > ${objdir}/foopassword > > echo Starting kdc ; > messages.log >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill -9 ${kdcpid} ${kadmpid}" EXIT >diff --git a/third_party/heimdal/tests/kdc/check-kdc.in b/third_party/heimdal/tests/kdc/check-kdc.in >index 75626f6ce853..e53293b2427f 100644 >--- a/third_party/heimdal/tests/kdc/check-kdc.in >+++ b/third_party/heimdal/tests/kdc/check-kdc.in >@@ -78,6 +78,8 @@ server=host/datan.test.h5l.se > server2=host/computer.example.com > server3=host/refer-me-out.test.h5l.se > server4=host/no-auth-data-reqd.test.h5l.se >+server5=host/a-host.refer-all-out.test.h5l.se >+namespace=WELLKNOWN/HOSTBASED-NAMESPACE/_/refer-all-out.test.h5l.se > serverip=host/10.11.12.13 > serveripname=host/ip.test.h5l.org > serveripname2=host/10.11.12.14 >@@ -240,6 +242,9 @@ ${kadmin} add -p foo --use-defaults referral-placeholder@${R5} || exit 1 > ${kadmin} add_alias referral-placeholder@${R5} ${server3}@${R} || exit 1 > ${kadmin5} add -p kaka --use-defaults ${server3}@${R5} || exit 1 > ${kadmin5} ext -k ${keytab} ${server3}@${R5} || exit 1 >+${kadmin} add_alias referral-placeholder@${R5} ${namespace}@${R} || exit 1 >+${kadmin5} add -p kaka --use-defaults ${server5}@${R5} || exit 1 >+${kadmin5} ext -k ${keytab} ${server5}@${R5} || exit 1 > ${kadmin} add -p kaka --use-defaults ${serverip}@${R} || exit 1 > ${kadmin} ext -k ${keytab} ${serverip}@${R} || exit 1 > ${kadmin} add -p kaka --use-defaults ${serveripname}@${R} || exit 1 >@@ -364,7 +369,7 @@ echo notfoo > ${objdir}/notfoopassword > echo Starting kdc ; > messages.log > env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \ > ${kdc} --detach --testing || >- { echo "kdc failed to start"; exit 1; } >+ { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > echo Starting kpasswdd; > messages.log >@@ -444,6 +449,8 @@ echo "Getting x-realm tickets with capaths for $R -> $R5" > ${kgetcred} foo@${R5} || { ec=1 ; eval "${testfailed}"; } > echo "Testing HDB referral entry" > ${kgetcred} --canonicalize ${server3}@${R} || { ec=1 ; eval "${testfailed}"; } >+echo "Testing HDB namespace referral entry" >+${kgetcred} --canonicalize ${server5}@${R} || { ec=1 ; eval "${testfailed}"; } > ${klist} > ${kdestroy} > >diff --git a/third_party/heimdal/tests/kdc/check-kinit.in b/third_party/heimdal/tests/kdc/check-kinit.in >index 35ec6deadbfa..c6cb23ff6f8c 100644 >--- a/third_party/heimdal/tests/kdc/check-kinit.in >+++ b/third_party/heimdal/tests/kdc/check-kinit.in >@@ -107,7 +107,7 @@ if (($# == 0)); then > echo foo > ${objdir}/foopassword > > echo Starting kdc ; > messages.log >- ${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+ ${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >diff --git a/third_party/heimdal/tests/kdc/check-kpasswdd.in b/third_party/heimdal/tests/kdc/check-kpasswdd.in >index 4f63ce240fad..39f12e1be8c3 100644 >--- a/third_party/heimdal/tests/kdc/check-kpasswdd.in >+++ b/third_party/heimdal/tests/kdc/check-kpasswdd.in >@@ -103,7 +103,7 @@ echo foo > ${objdir}/foopassword > > echo Starting kdc ; > messages.log > env ${HEIM_MALLOC_DEBUG} ${kdc} --detach --testing || >- { echo "kdc failed to start"; exit 1; } >+ { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > echo Starting kpasswdd >diff --git a/third_party/heimdal/tests/kdc/check-pkinit.in b/third_party/heimdal/tests/kdc/check-pkinit.in >index baa9fb306916..9f90fd040f9a 100644 >--- a/third_party/heimdal/tests/kdc/check-pkinit.in >+++ b/third_party/heimdal/tests/kdc/check-pkinit.in >@@ -199,7 +199,7 @@ echo foo > ${objdir}/foopassword > > echo Starting kdc ; > messages.log > KRB5_CONFIG="${objdir}/krb5-pkinit2.conf" >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap 'kill -9 ${kdcpid}; echo signal killing kdc; cat ca.crt kdc.crt pkinit.crt pkinit-synthetic.crt; exit 1;' EXIT >@@ -232,7 +232,7 @@ ${kdestroy} > echo "Restarting kdc ($kdcpid)" > sh ${leaks_kill} kdc $kdcpid || ec=1 > KRB5_CONFIG="${objdir}/krb5-pkinit.conf" >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > echo "Trying pk-init (principal in cert)"; > messages.log >diff --git a/third_party/heimdal/tests/kdc/check-referral.in b/third_party/heimdal/tests/kdc/check-referral.in >index d028e39ef1fa..73c26c368caa 100644 >--- a/third_party/heimdal/tests/kdc/check-referral.in >+++ b/third_party/heimdal/tests/kdc/check-referral.in >@@ -105,7 +105,7 @@ ${kadmin} check ${R2} || exit 1 > echo foo > ${objdir}/foopassword > > echo Starting kdc ; > messages.log >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT >diff --git a/third_party/heimdal/tests/kdc/check-tester.in b/third_party/heimdal/tests/kdc/check-tester.in >index dba154c299b9..83b48baf27fa 100644 >--- a/third_party/heimdal/tests/kdc/check-tester.in >+++ b/third_party/heimdal/tests/kdc/check-tester.in >@@ -46,6 +46,9 @@ testfailed="echo test failed; cat messages.log; exit 1" > # If there is no useful db support compiled in, disable test > ${have_db} || exit 77 > >+# Do not run in GutHub valgrind builds -- too slow / not necessary >+[ -n "$CHECK_TESTER_NO_VALGRIND" ] && exit 77 >+ > R=TEST.H5L.SE > > keytabfile=${objdir}/server.keytab >diff --git a/third_party/heimdal/tests/kdc/check-uu.in b/third_party/heimdal/tests/kdc/check-uu.in >index 7e819a14ad0d..ef831ca4d94a 100644 >--- a/third_party/heimdal/tests/kdc/check-uu.in >+++ b/third_party/heimdal/tests/kdc/check-uu.in >@@ -86,7 +86,7 @@ ${kadmin} check ${R} || exit 1 > echo foo > ${objdir}/foopassword > > echo Starting kdc ; > messages.log >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill -9 ${kdcpid} ${uuspid}; echo signal killing kdc; exit 1;" EXIT >diff --git a/third_party/heimdal/tests/kdc/krb5-kcm.conf.in b/third_party/heimdal/tests/kdc/krb5-kcm.conf.in >new file mode 100644 >index 000000000000..bdcca073cc02 >--- /dev/null >+++ b/third_party/heimdal/tests/kdc/krb5-kcm.conf.in >@@ -0,0 +1,165 @@ >+[libdefaults] >+ default_realm = TEST.H5L.SE TEST2.H5L.SE >+ default_ccache_name = KCM:%{uid} >+ no-addresses = TRUE >+ allow_weak_crypto = @WEAK@ >+ dns_lookup_kdc = no >+ dns_lookup_realm = no >+ >+ >+[appdefaults] >+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt >+ reconnect-min = 2s >+ reconnect-backoff = 2s >+ reconnect-max = 10s >+ >+[realms] >+ TEST.H5L.SE = { >+ kdc = localhost:@port@ >+ admin_server = localhost:@admport@ >+ kpasswd_server = localhost:@pwport@ >+ } >+ SUB.TEST.H5L.SE = { >+ kdc = localhost:@port@ >+ } >+ TEST2.H5L.SE = { >+ kdc = localhost:@port@ >+ kpasswd_server = localhost:@pwport@ >+ } >+ TEST3.H5L.SE = { >+ kdc = localhost:@port@ >+ } >+ TEST4.H5L.SE = { >+ kdc = localhost:@port@ >+ } >+ SOME-REALM5.FR = { >+ kdc = localhost:@port@ >+ } >+ SOME-REALM6.US = { >+ kdc = localhost:@port@ >+ } >+ SOME-REALM7.UK = { >+ kdc = localhost:@port@ >+ } >+ SOME-REALM8.UK = { >+ kdc = localhost:@port@ >+ } >+ TEST-HTTP.H5L.SE = { >+ kdc = http/localhost:@port@ >+ } >+ H1.TEST.H5L.SE = { >+ kdc = localhost:@port@ >+ } >+ H2.TEST.H5L.SE = { >+ kdc = localhost:@port@ >+ } >+ H3.H2.TEST.H5L.SE = { >+ kdc = localhost:@port@ >+ } >+ H4.H2.TEST.H5L.SE = { >+ kdc = localhost:@port@ >+ } >+ >+[domain_realm] >+ .test.h5l.se = TEST.H5L.SE >+ .sub.test.h5l.se = SUB.TEST.H5L.SE >+ .h1.test.h5l.se = H1.TEST.H5L.SE >+ .h2.test.h5l.se = H2.TEST.H5L.SE >+ .h3.h2.test.h5l.se = H3.H2.TEST.H5L.SE >+ .h4.h2.test.h5l.se = H4.H2.TEST.H5L.SE >+ .example.com = TEST2.H5L.SE >+ localhost = TEST.H5L.SE >+ .localdomain = TEST.H5L.SE >+ localdomain = TEST.H5L.SE >+ .localdomain6 = TEST.H5L.SE >+ localdomain6 = TEST.H5L.SE >+ >+ >+[kdc] >+ enable-digest = true >+ allow-anonymous = true >+ digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2 >+ strict-nametypes = true >+ >+ enable-http = true >+ >+ enable-pkinit = true >+ pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key >+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt >+ pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt >+# pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl >+ pkinit_mappings_file = @srcdir@/pki-mapping >+ pkinit_allow_proxy_certificate = true >+ >+ database = { >+ label = { >+ dbname = @db_type@:@objdir@/current-db@kdc@ >+ realm = TEST.H5L.SE >+ mkey_file = @objdir@/mkey.file >+ acl_file = @srcdir@/heimdal.acl >+ log_file = @objdir@/current@kdc@.log >+ } >+ label2 = { >+ dbname = @db_type@:@objdir@/current-db@kdc@ >+ realm = TEST2.H5L.SE >+ mkey_file = @objdir@/mkey.file >+ acl_file = @srcdir@/heimdal.acl >+ log_file = @objdir@/current@kdc@.log >+ } >+ label3 = { >+ dbname = sqlite:@objdir@/current-db@kdc@.sqlite3 >+ realm = SOME-REALM5.FR >+ mkey_file = @objdir@/mkey.file >+ acl_file = @srcdir@/heimdal.acl >+ log_file = @objdir@/current@kdc@.log >+ } >+ } >+ >+ signal_socket = @objdir@/signal >+ iprop-stats = @objdir@/iprop-stats >+ iprop-acl = @srcdir@/iprop-acl >+ log-max-size = 40000 >+ >+[hdb] >+ db-dir = @objdir@ >+ >+[logging] >+ kdc = 0-/FILE:@objdir@/messages.log >+ krb5 = 0-/FILE:@objdir@/messages.log >+ default = 0-/FILE:@objdir@/messages.log >+ >+# If you are doing preformance measurements on OSX you want to change >+# the kdc LOG line from = to - below to keep the FILE open and avoid >+# open/write/close which is blocking (rdar:// ) on OSX. >+# kdc = 0-/FILE=@objdir@/messages.log >+ >+[kadmin] >+ save-password = true >+ default_key_rules = { >+ */des3-only@* = des3-cbc-sha1:pw-salt >+ */aes-only@* = aes256-cts-hmac-sha1-96:pw-salt >+ } >+ @dk@ >+ >+[capaths] >+ TEST.H5L.SE = { >+ TEST2.H5L.SE = . >+ SOME-REALM5.FR = 1 >+ TEST3.H5L.SE = TEST2.H5L.SE >+ TEST4.H5L.SE = TEST2.H5L.SE >+ TEST4.H5L.SE = TEST3.H5L.SE >+ SOME-REALM6.US = SOME-REALM5.FR >+ SOME-REALM7.UK = SOME-REALM6.US >+ SOME-REALM7.UK = SOME-REALM5.FR >+ SOME-REALM8.UK = SOME-REALM6.US >+ } >+ H4.H2.TEST.H5L.SE = { >+ H1.TEST.H5L.SE = H3.H2.TEST.H5L.SE >+ H1.TEST.H5L.SE = H2.TEST.H5L.SE >+ H1.TEST.H5L.SE = TEST.H5L.SE >+ >+ TEST.H5L.SE = H3.H2.TEST.H5L.SE >+ TEST.H5L.SE = H2.TEST.H5L.SE >+ >+ H2.TEST.H5L.SE = H3.H2.TEST.H5L.SE >+ } >diff --git a/third_party/heimdal/tests/kdc/krb5.conf.in b/third_party/heimdal/tests/kdc/krb5.conf.in >index 19b4e3ef64ea..a85836d76b24 100644 >--- a/third_party/heimdal/tests/kdc/krb5.conf.in >+++ b/third_party/heimdal/tests/kdc/krb5.conf.in >@@ -126,6 +126,9 @@ > > [hdb] > db-dir = @objdir@ >+ enable_virtual_hostbased_princs = true >+ virtual_hostbased_princ_mindots = 1 >+ virtual_hostbased_princ_maxdots = 3 > > [logging] > kdc = 0-/FILE:@objdir@/@messages@.log >diff --git a/third_party/heimdal/tests/ldap/check-ldap.in b/third_party/heimdal/tests/ldap/check-ldap.in >index b99c951032bb..f73eb6e1b88b 100644 >--- a/third_party/heimdal/tests/ldap/check-ldap.in >+++ b/third_party/heimdal/tests/ldap/check-ldap.in >@@ -120,7 +120,7 @@ ${kadmin} list '*' > /dev/null || exit 1 > echo "$foopassword" > ${objdir}/foopassword > > echo Starting kdc >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill ${kdcpid}; echo signal killing kdc; sh ${srcdir}/slapd-stop ; exit 1;" EXIT >diff --git a/third_party/heimdal/tests/plugin/Makefile.am b/third_party/heimdal/tests/plugin/Makefile.am >index 3fb1a2324b9b..5dd43ccb04da 100644 >--- a/third_party/heimdal/tests/plugin/Makefile.am >+++ b/third_party/heimdal/tests/plugin/Makefile.am >@@ -29,10 +29,10 @@ krb5.conf: krb5.conf.in Makefile > $(do_subst) < $(srcdir)/krb5.conf.in > krb5.conf.tmp > mv krb5.conf.tmp krb5.conf > >-lib_LTLIBRARIES = windc.la >+lib_LTLIBRARIES = kdc_test_plugin.la > >-windc_la_SOURCES = windc.c >-windc_la_LDFLAGS = -module >+kdc_test_plugin_la_SOURCES = kdc_test_plugin.c >+kdc_test_plugin_la_LDFLAGS = -module > > CLEANFILES= \ > $(TESTS) \ >diff --git a/third_party/heimdal/tests/plugin/check-pac.in b/third_party/heimdal/tests/plugin/check-pac.in >index 60ec21a31f36..85bf8cd9a98d 100644 >--- a/third_party/heimdal/tests/plugin/check-pac.in >+++ b/third_party/heimdal/tests/plugin/check-pac.in >@@ -108,15 +108,15 @@ echo "Empty log" > > messages.log > > echo Starting kdc >-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; } >+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } > kdcpid=`getpid kdc` > > trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT > > ec=0 > >-echo "Check that WINDC module was loaded " >-grep "windc init" messages.log >/dev/null || \ >+echo "Check that KDC plugin module was loaded " >+grep "kdc plugin init" messages.log >/dev/null || \ > { ec=1 ; eval "${testfailed}"; } > > echo "Getting client initial tickets"; > messages.log >diff --git a/third_party/heimdal/tests/plugin/kdc_test_plugin.c b/third_party/heimdal/tests/plugin/kdc_test_plugin.c >new file mode 100644 >index 000000000000..4fcf311fddfe >--- /dev/null >+++ b/third_party/heimdal/tests/plugin/kdc_test_plugin.c >@@ -0,0 +1,207 @@ >+#include <string.h> >+#include <krb5_locl.h> >+#include <hdb.h> >+#include <hx509.h> >+#include <kdc.h> >+#include <kdc-plugin.h> >+ >+static krb5_error_code KRB5_CALLCONV >+init(krb5_context context, void **ctx) >+{ >+ krb5_warnx(context, "kdc plugin init"); >+ *ctx = NULL; >+ return 0; >+} >+ >+static void KRB5_CALLCONV >+fini(void *ctx) >+{ >+} >+ >+static krb5_error_code KRB5_CALLCONV >+pac_generate(void *ctx, >+ krb5_context context, >+ krb5_kdc_configuration *config, >+ hdb_entry *client, >+ hdb_entry *server, >+ const krb5_keyblock *pk_replykey, >+ uint64_t pac_attributes, >+ krb5_pac *pac) >+{ >+ krb5_error_code ret; >+ krb5_data data; >+ >+ if ((pac_attributes & (KRB5_PAC_WAS_REQUESTED | >+ KRB5_PAC_WAS_GIVEN_IMPLICITLY)) == 0) { >+ *pac = NULL; >+ return 0; >+ } >+ >+ krb5_warnx(context, "pac generate"); >+ >+ data.data = "\x00\x01"; >+ data.length = 2; >+ >+ ret = krb5_pac_init(context, pac); >+ if (ret) >+ return ret; >+ >+ ret = krb5_pac_add_buffer(context, *pac, 1, &data); >+ if (ret) >+ return ret; >+ >+ return 0; >+} >+ >+static krb5_error_code KRB5_CALLCONV >+pac_verify(void *ctx, >+ krb5_context context, >+ krb5_kdc_configuration *config, >+ const krb5_principal new_ticket_client, >+ const krb5_principal delegation_proxy, >+ hdb_entry * client, >+ hdb_entry * server, >+ hdb_entry * krbtgt, >+ krb5_pac *pac) >+{ >+ krb5_error_code ret; >+ krb5_data data; >+ krb5_cksumtype cstype; >+ uint16_t rodc_id; >+ krb5_enctype etype; >+ Key *key; >+ >+ krb5_warnx(context, "pac_verify"); >+ >+ ret = krb5_pac_get_buffer(context, *pac, 1, &data); >+ if (ret) >+ return ret; >+ krb5_data_free(&data); >+ >+ ret = krb5_pac_get_kdc_checksum_info(context, *pac, &cstype, &rodc_id); >+ if (ret) >+ return ret; >+ >+ if (rodc_id == 0 || rodc_id != krbtgt->kvno >> 16) { >+ krb5_warnx(context, "Wrong RODCIdentifier"); >+ return EINVAL; >+ } >+ >+ ret = krb5_cksumtype_to_enctype(context, cstype, &etype); >+ if (ret) >+ return ret; >+ >+ ret = hdb_enctype2key(context, krbtgt, NULL, etype, &key); >+ if (ret) >+ return ret; >+ >+ return krb5_pac_verify(context, *pac, 0, NULL, NULL, &key->key); >+} >+ >+static void logit(const char *what, astgs_request_t r) >+{ >+ krb5_context context = kdc_request_get_context((kdc_request_t)r); >+ const char *cname = kdc_request_get_cname((kdc_request_t)r); >+ const char *sname = kdc_request_get_sname((kdc_request_t)r); >+ >+ krb5_warnx(context, "%s: client %s server %s", >+ what, >+ cname ? cname : "<unknown>", >+ sname ? sname : "<unknown>"); >+} >+ >+static krb5_error_code KRB5_CALLCONV >+client_access(void *ctx, astgs_request_t r) >+{ >+ logit("client_access", r); >+ >+ return 0; >+} >+ >+static krb5_error_code KRB5_CALLCONV >+finalize_reply(void *ctx, astgs_request_t r) >+{ >+ heim_number_t n; >+ krb5_error_code ret; >+ >+ logit("finalize_reply", r); >+ >+ n = heim_number_create(1234); >+ if (n == NULL) >+ return ENOMEM; >+ >+ ret = kdc_request_set_attribute((kdc_request_t)r, >+ HSTR("org.h5l.tests.kdc-plugin"), n); >+ heim_release(n); >+ >+ return ret; >+} >+ >+static krb5_error_code KRB5_CALLCONV >+audit(void *ctx, astgs_request_t r) >+{ >+ krb5_error_code ret = kdc_request_get_error_code((kdc_request_t)r); >+ heim_number_t n; >+ >+ logit("audit", r); >+ >+ if (ret) >+ return 0; /* finalize_reply only called in success */ >+ >+ n = kdc_request_get_attribute((kdc_request_t)r, >+ HSTR("org.h5l.tests.kdc-plugin")); >+ >+ heim_assert(n && heim_number_get_int(n) == 1234, >+ "attribute not passed from finalize_reply"); >+ >+ if (n == NULL || heim_number_get_int(n) != 1234) >+ return EINVAL; /* return value is ignored, but for completeness */ >+ >+ return 0; >+} >+ >+static krb5plugin_kdc_ftable kdc_plugin = { >+ KRB5_PLUGIN_KDC_VERSION_10, >+ init, >+ fini, >+ pac_generate, >+ pac_verify, >+ client_access, >+ NULL, /* referral_policy */ >+ finalize_reply, >+ audit >+}; >+ >+static const krb5plugin_kdc_ftable *const kdc_plugins[] = { >+ &kdc_plugin >+}; >+ >+krb5_error_code KRB5_CALLCONV >+kdc_plugin_load(krb5_context context, >+ krb5_get_instance_func_t *get_instance, >+ size_t *num_plugins, >+ const krb5plugin_kdc_ftable *const **plugins); >+ >+static uintptr_t KRB5_CALLCONV >+kdc_plugin_get_instance(const char *libname) >+{ >+ if (strcmp(libname, "hdb") == 0) >+ return hdb_get_instance(libname); >+ else if (strcmp(libname, "krb5") == 0) >+ return krb5_get_instance(libname); >+ >+ return 0; >+} >+ >+krb5_error_code KRB5_CALLCONV >+kdc_plugin_load(krb5_context context, >+ krb5_get_instance_func_t *get_instance, >+ size_t *num_plugins, >+ const krb5plugin_kdc_ftable *const **plugins) >+{ >+ *get_instance = kdc_plugin_get_instance; >+ *num_plugins = sizeof(kdc_plugins) / sizeof(kdc_plugins[0]); >+ *plugins = kdc_plugins; >+ >+ return 0; >+} >diff --git a/third_party/heimdal/tests/plugin/krb5.conf.in b/third_party/heimdal/tests/plugin/krb5.conf.in >index 8ab2f17177c1..d188c314b360 100644 >--- a/third_party/heimdal/tests/plugin/krb5.conf.in >+++ b/third_party/heimdal/tests/plugin/krb5.conf.in >@@ -19,6 +19,21 @@ > } > > [kdc] >+ enable-digest = true >+ allow-anonymous = true >+ digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2 >+ strict-nametypes = true >+ synthetic_clients = true >+ enable_gss_preauth = true >+ gss_mechanisms_allowed = sanon-x25519 >+ enable-pkinit = true >+ pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key >+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt >+ pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt >+# pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl >+ pkinit_mappings_file = @srcdir@/pki-mapping >+ pkinit_allow_proxy_certificate = true >+ > database = { > dbname = @objdir@/current-db > realm = TEST.H5L.SE >diff --git a/third_party/heimdal/tests/plugin/windc.c b/third_party/heimdal/tests/plugin/windc.c >deleted file mode 100644 >index 357148019ae8..000000000000 >--- a/third_party/heimdal/tests/plugin/windc.c >+++ /dev/null >@@ -1,161 +0,0 @@ >-#include <string.h> >-#include <krb5_locl.h> >-#include <hdb.h> >-#include <hx509.h> >-#include <kdc.h> >-#include <windc_plugin.h> >- >-static krb5_error_code KRB5_CALLCONV >-windc_init(krb5_context context, void **ctx) >-{ >- krb5_warnx(context, "windc init"); >- *ctx = NULL; >- return 0; >-} >- >-static void KRB5_CALLCONV >-windc_fini(void *ctx) >-{ >-} >- >-static krb5_error_code KRB5_CALLCONV >-pac_generate(void *ctx, krb5_context context, >- struct hdb_entry_ex *client, >- struct hdb_entry_ex *server, >- const krb5_keyblock *pk_replykey, >- uint64_t pac_attributes, >- krb5_pac *pac) >-{ >- krb5_error_code ret; >- krb5_data data; >- >- if ((pac_attributes & (KRB5_PAC_WAS_REQUESTED | >- KRB5_PAC_WAS_GIVEN_IMPLICITLY)) == 0) { >- *pac = NULL; >- return 0; >- } >- >- krb5_warnx(context, "pac generate"); >- >- data.data = "\x00\x01"; >- data.length = 2; >- >- ret = krb5_pac_init(context, pac); >- if (ret) >- return ret; >- >- ret = krb5_pac_add_buffer(context, *pac, 1, &data); >- if (ret) >- return ret; >- >- return 0; >-} >- >-static krb5_error_code KRB5_CALLCONV >-pac_verify(void *ctx, krb5_context context, >- const krb5_principal new_ticket_client, >- const krb5_principal delegation_proxy, >- struct hdb_entry_ex * client, >- struct hdb_entry_ex * server, >- struct hdb_entry_ex * krbtgt, >- krb5_pac *pac) >-{ >- krb5_error_code ret; >- krb5_data data; >- krb5_cksumtype cstype; >- uint16_t rodc_id; >- krb5_enctype etype; >- Key *key; >- >- krb5_warnx(context, "pac_verify"); >- >- ret = krb5_pac_get_buffer(context, *pac, 1, &data); >- if (ret) >- return ret; >- krb5_data_free(&data); >- >- ret = krb5_pac_get_kdc_checksum_info(context, *pac, &cstype, &rodc_id); >- if (ret) >- return ret; >- >- if (rodc_id == 0 || rodc_id != krbtgt->entry.kvno >> 16) { >- krb5_warnx(context, "Wrong RODCIdentifier"); >- return EINVAL; >- } >- >- ret = krb5_cksumtype_to_enctype(context, cstype, &etype); >- if (ret) >- return ret; >- >- ret = hdb_enctype2key(context, &krbtgt->entry, NULL, etype, &key); >- if (ret) >- return ret; >- >- return krb5_pac_verify(context, *pac, 0, NULL, NULL, &key->key); >-} >- >-static void logit(const char *what, astgs_request_t r) >-{ >- krb5_warnx(r->context, "%s: client %s server %s", >- what, >- r->cname ? r->cname : "<unknown>", >- r->sname ? r->sname : "<unknown>"); >-} >- >-static krb5_error_code KRB5_CALLCONV >-client_access(void *ctx, astgs_request_t r) >-{ >- logit("client_access", r); >- return 0; >-} >- >-static krb5_error_code KRB5_CALLCONV >-finalize_reply(void *ctx, astgs_request_t r) >-{ >- logit("finalize_reply", r); >- return 0; >-} >- >-static krb5plugin_windc_ftable windc = { >- KRB5_WINDC_PLUGING_MINOR, >- windc_init, >- windc_fini, >- pac_generate, >- pac_verify, >- client_access, >- finalize_reply >-}; >- >-static const krb5plugin_windc_ftable *const windc_plugins[] = { >- &windc >-}; >- >-krb5_error_code KRB5_CALLCONV >-windc_plugin_load(krb5_context context, >- krb5_get_instance_func_t *get_instance, >- size_t *num_plugins, >- const krb5plugin_windc_ftable *const **plugins); >- >-static uintptr_t KRB5_CALLCONV >-windc_get_instance(const char *libname) >-{ >- if (strcmp(libname, "hdb") == 0) >- return hdb_get_instance(libname); >- else if (strcmp(libname, "krb5") == 0) >- return krb5_get_instance(libname); >- >- return 0; >-} >- >-krb5_error_code KRB5_CALLCONV >-windc_plugin_load(krb5_context context, >- krb5_get_instance_func_t *get_instance, >- size_t *num_plugins, >- const krb5plugin_windc_ftable *const **plugins) >-{ >- *get_instance = windc_get_instance; >- *num_plugins = sizeof(windc_plugins) / sizeof(windc_plugins[0]); >- *plugins = windc_plugins; >- >- return 0; >-} >diff --git a/third_party/heimdal/windows/NTMakefile.sdk b/third_party/heimdal/windows/NTMakefile.sdk >new file mode 100644 >index 000000000000..a9f2b30dfdf3 >--- /dev/null >+++ b/third_party/heimdal/windows/NTMakefile.sdk >@@ -0,0 +1,130 @@ >+######################################################################## >+# >+# Copyright (c) 2021, PADL Software Pty Ltd. >+# All rights reserved. >+# >+# Redistribution and use in source and binary forms, with or without >+# modification, are permitted provided that the following conditions >+# are met: >+# >+# - Redistributions of source code must retain the above copyright >+# notice, this list of conditions and the following disclaimer. >+# >+# - Redistributions in binary form must reproduce the above copyright >+# notice, this list of conditions and the following disclaimer in >+# the documentation and/or other materials provided with the >+# distribution. >+# >+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS >+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT >+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS >+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE >+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, >+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, >+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER >+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN >+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN if ADVISED OF THE >+# POSSIBILITY OF SUCH DAMAGE. >+# >+ >+!if !defined(CPU) || "$(CPU)" == "" >+CPU =AMD64 >+!endif >+ >+!if "$(CPU)" == "X86" || "$(CPU)" == "x86" >+CPU =i386 >+!endif >+ >+!if !defined(APPVER) >+APPVER =6.1 >+!endif >+ >+!if "$(APPVER)" == "5.0" >+NMAKE_WINVER=0x0500 >+!elseif "$(APPVER)" == "5.01" >+NMAKE_WINVER=0x0501 >+!elseif "$(APPVER)" == "5.02" >+NMAKE_WINVER=0x0502 >+!elseif "$(APPVER)" == "6.0" >+NMAKE_WINVER=0x0600 >+!elseif "$(APPVER)" == "6.1" >+NMAKE_WINVER=0x0601 >+!elseif "$(APPVER)" == "10.0" >+NMAKE_WINVER=0x0A00 >+!else >+!error Unknown value for APPVER >+!endif >+ >+cc = cl >+link = link >+implib = lib >+ >+cflags = -c -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -W4 >+ >+!if "$(CPU)" == "i386" >+cflags = $(cflags) -D_X86_=1 >+!endif >+!if "$(CPU)" == "AMD64" >+cflags = $(cflags) -D_AMD64_=1 >+!endif >+!if "$(CPU)" == "ARM" >+cflags = $(cflags) -D_ARM_=1 >+!endif >+!if "$(CPU)" == "ARM64" >+cflags = $(cflags) -D_ARM64_=1 >+!endif >+ >+cflags = $(cflags) -DWIN32 -D_WIN32 >+!if "$(CPU)" == "AMD64" || "$(CPU)" == "ARM64" >+cflags = $(cflags) -DWIN64 -D_WIN64 >+!endif >+ >+cflags = $(cflags) -D_WINNT -D_WIN32_WINNT=$(NMAKE_WINVER) >+cflags = $(cflags) -DNTDDI_VERSION=$(NMAKE_WINVER)0000 >+cflags = $(cflags) -D_WIN32_IE=$(NMAKE_WINVER) -DWINVER=$(NMAKE_WINVER) >+ >+!ifdef NODEBUG >+cdebug = -Ox -DNDEBUG >+!else >+cdebug = -Zi -Od -DDEBUG >+!endif >+ >+cvarsmt = -D_MT >+cvarsdll = -D_MT -D_DLL >+!ifdef NODEBUG >+cvarsmt = $(cvarsmt) -MT >+cvarsdll = $(cvarsdll) -MD >+!else >+cvarsmt = $(cvarsmt) -MTd >+cvarsdll = $(cvarsdll) -MDd >+!endif >+cvars = $(cvarsmt) >+ >+lflags = $(lflags) /INCREMENTAL:NO /NOLOGO >+!ifdef NODEBUG >+ldebug = /RELEASE >+!else >+ldebug = /DEBUG /DEBUGTYPE:cv >+!endif >+ >+!if "$(CPU)" == "i386" >+dllentry = _DllMainCRTStartup@12 >+!else >+dllentry = _DllMainCRTStartup >+!endif >+ >+conlflags = $(lflags) -subsystem:console,$(APPVER) >+guilflags = $(lflags) -subsystem:windows,$(APPVER) >+dlllflags = $(lflags) -entry:$(dllentry) -dll >+ >+baselibs = kernel32.lib ws2_32.lib mswsock.lib advapi32.lib >+conlibs = $(baselibs) >+conlibsmt = $(baselibs) >+conlibsdll = $(baselibs) >+ >+winlibs = $(baselibs) user32.lib gdi32.lib comdlg32.lib winspool.lib >+guilibs = $(winlibs) >+guilibsmt = $(winlibs) >+guilibsdll = $(winlibs) >diff --git a/third_party/heimdal/windows/NTMakefile.w32 b/third_party/heimdal/windows/NTMakefile.w32 >index 47df51042a28..471e783912be 100644 >--- a/third_party/heimdal/windows/NTMakefile.w32 >+++ b/third_party/heimdal/windows/NTMakefile.w32 >@@ -39,7 +39,7 @@ prep:: > > all:: prep > >-!include <Win32.Mak> >+!include "NTMakefile.sdk" > > !ifdef NODEBUG > BUILD=rel >@@ -207,6 +207,8 @@ EXEGUILINK_C = $(LINK) $(ldebug) $(guilflags) $(guilibsdll) $(libmach) > DLLCONLINK_C = $(LINK) $(ldebug) $(dlllflags) $(conlibsdll) $(libmach) > DLLGUILINK_C = $(LINK) $(ldebug) $(dlllflags) $(guilibsdll) $(libmach) > >+C2OBJ_C_MT = $(CC) $(cdebug) $(cflags) $(cvarsmt) $(AUXCFLAGS) $(intcflags) $(cdefines) $(cincdirs) $(cwarn) >+ > !else # STATICRUNTIME > > C2OBJ_C = $(CC) $(cdebug) $(cflags) $(cvarsmt) $(AUXCFLAGS) $(intcflags) $(cdefines) $(cincdirs) $(cwarn) >@@ -440,7 +442,7 @@ clean:: > -$(RM) $(OBJ)\*.* > !endif > >-.SUFFIXES: .c .cpp .hin .h .x .hx >+.SUFFIXES: .c .cpp .hin .h .hx > > #---------------------------------------------------------------------- > # Manifest handling >@@ -574,6 +576,7 @@ DLLPREP_MERGE=\ > # > > LIBASN1 =$(LIBDIR)\libasn1.lib >+LIBASN1_S =$(LIBDIR)\libasn1_s.lib > LIBCOMERR =$(LIBDIR)\libcom_err.lib > LIBEDITLINE =$(LIBDIR)\libeditline.lib > LIBGSSAPI =$(LIBDIR)\libgssapi.lib >-- >2.25.1 > > >From b60f45b9f1aebe64cf37d74ebf981071199033ad Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 22 Feb 2022 14:09:52 +1300 >Subject: [PATCH 08/22] third_party/heimdal_build: Add source files to build > >This is an adaptation to Heimdal: > >commit be708ca3cf98900c61919f8ff7ced4428b5d1f32 >Author: Nicolas Williams <nico@twosigma.com> >Date: Wed Dec 22 17:01:12 2021 -0600 > > gsskrb5: Add simple name attributes support > > This adds Kerberos mechanism support for: > > - composite principal name export/import > - getting rudimentary name attributes from GSS names using > gss_get_name_attribute(): > - all (raw) authorization data from the Ticket > - all (raw) authorization data from the Authenticator > - transit path > - realm > - component count > - each component > - gss_inquire_name() > - gss_display_name_ext() (just for the hostbased service name type > though) > > The test exercises almost all of the functionality, except for: > > - getting the PAC > - getting authz-data from the Authenticator > - getting the transit path > > TBD (much) later: > > - amend test_context to do minimal name attribute checks as well > - gss_set_name_attribute() (to request authz-data) > - gss_delete_name_attribute() > - getting specific authorization data elements via URN fragments (as > opposed to all of them) > - parsing the PAC, extracting SIDs (each one as a separate value) > - some configurable local policy (?) > - plugin interface for additional local policy > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit f2ca9c5db7e1bb20cfc6705633b48c32b1496334) >--- > third_party/heimdal_build/wscript_build | 3 +++ > 1 file changed, 3 insertions(+) > >diff --git a/third_party/heimdal_build/wscript_build b/third_party/heimdal_build/wscript_build >index cf7c2b9a3428..76e88bc103e0 100644 >--- a/third_party/heimdal_build/wscript_build >+++ b/third_party/heimdal_build/wscript_build >@@ -549,6 +549,7 @@ if not bld.CONFIG_SET("USING_SYSTEM_GSSAPI"): > lib/gssapi/krb5/inquire_names_for_mech.c > lib/gssapi/krb5/indicate_mechs.c > lib/gssapi/krb5/inquire_sec_context_by_oid.c >+ lib/gssapi/krb5/name_attrs.c > lib/gssapi/krb5/export_sec_context.c > lib/gssapi/krb5/import_sec_context.c > lib/gssapi/krb5/duplicate_name.c >@@ -658,6 +659,8 @@ if not bld.CONFIG_SET("USING_SYSTEM_GSSAPI"): > lib/gssapi/mech/gss_release_name.c > lib/gssapi/mech/gss_set_cred_option.c > lib/gssapi/mech/gss_pseudo_random.c >+ lib/gssapi/mech/gss_authorize_localname.c >+ lib/gssapi/mech/gss_get_name_attribute.c > lib/gssapi/mech/gssspi_exchange_meta_data.c > lib/gssapi/mech/gssspi_query_mechanism_info.c > lib/gssapi/mech/gssspi_query_meta_data.c >-- >2.25.1 > > >From a16c1210440a81f964d1940cd94c414a8aceecae Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Mon, 21 Feb 2022 20:28:42 +1300 >Subject: [PATCH 09/22] s4:kdc: Refactor HDB API > >This is an adaptation to Heimdal: > >commit b1dcc1a47485165ada778ef3c3463cfc0779d183 >Author: Luke Howard <lukeh@padl.com> >Date: Fri Dec 31 17:24:58 2021 +1100 > > kdc: refactor Samba-specific auditing API in terms of existing API > > Make Samba-specific HDB auth status API a wrapper on the existing auditing API, > with a view towards unifying the two APIs in a future commit. > > The term "auth status" is replaced with "auth event", and the HDB auth_status > method is replaced with a more general purpose audit method which has access to > the entire request structure. > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit a2f7987d58372cfc52bc5f9786c0719439956fee) >--- > source4/kdc/hdb-samba4.c | 94 +++++++++++++++++++++++++--------------- > 1 file changed, 59 insertions(+), 35 deletions(-) > >diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c >index 71260d3ed0ab..60b6f94a32d2 100644 >--- a/source4/kdc/hdb-samba4.c >+++ b/source4/kdc/hdb-samba4.c >@@ -500,15 +500,10 @@ static void send_bad_password_netlogon(TALLOC_CTX *mem_ctx, > irpc_handle, &req); > } > >-static krb5_error_code hdb_samba4_auth_status(krb5_context context, >- HDB *db, >- hdb_entry_ex *entry, >- const struct timeval *start_time, >- const struct sockaddr *from_addr, >- const char *original_client_name, >- int hdb_auth_status, >- const char *auth_details, >- const char *pa_type) >+static krb5_error_code hdb_samba4_audit(krb5_context context, >+ HDB *db, >+ hdb_entry_ex *entry, >+ hdb_request_t r) > { > struct samba_kdc_db_context *kdc_db_ctx = talloc_get_type_abort(db->hdb_db, > struct samba_kdc_db_context); >@@ -516,16 +511,47 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, > struct ldb_dn *domain_dn = ldb_get_default_basedn(kdc_db_ctx->samdb); > uint64_t logon_id = generate_random_u64(); > >+ heim_object_t auth_details_obj = NULL; >+ const char *auth_details = NULL; >+ >+ heim_object_t hdb_auth_status_obj = NULL; >+ int hdb_auth_status; >+ >+ heim_object_t pa_type_obj = NULL; >+ const char *pa_type = NULL; >+ >+ struct auth_usersupplied_info ui; >+ >+ size_t sa_socklen = 0; >+ >+ hdb_auth_status_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_AUTH_EVENT_TYPE); >+ if (hdb_auth_status_obj == NULL) { >+ /* No status code found, so just return. */ >+ return 0; >+ } >+ >+ hdb_auth_status = heim_number_get_int(hdb_auth_status_obj); >+ >+ pa_type_obj = heim_audit_getkv((heim_svc_req_desc)r, "pa"); >+ if (pa_type_obj != NULL) { >+ pa_type = heim_string_get_utf8(pa_type_obj); >+ } >+ >+ auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_AUTH_EVENT_DETAILS); >+ if (auth_details_obj != NULL) { >+ auth_details = heim_string_get_utf8(auth_details_obj); >+ } >+ > /* > * Forcing this via the NTLM auth structure is not ideal, but > * it is the most practical option right now, and ensures the > * logs are consistent, even if some elements are always NULL. > */ >- struct auth_usersupplied_info ui = { >+ ui = (struct auth_usersupplied_info) { > .mapped_state = true, > .was_mapped = true, > .client = { >- .account_name = original_client_name, >+ .account_name = r->cname, > .domain_name = NULL, > }, > .service_description = "Kerberos KDC", >@@ -534,9 +560,7 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, > .logon_id = logon_id > }; > >- size_t sa_socklen = 0; >- >- switch (from_addr->sa_family) { >+ switch (r->addr->sa_family) { > case AF_INET: > sa_socklen = sizeof(struct sockaddr_in); > break; >@@ -548,7 +572,7 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, > } > > switch (hdb_auth_status) { >- case HDB_AUTHSTATUS_AUTHORIZATION_SUCCESS: >+ case HDB_AUTH_EVENT_CLIENT_AUTHORIZED: > { > TALLOC_CTX *frame = talloc_stackframe(); > struct samba_kdc_entry *p = talloc_get_type(entry->ctx, >@@ -568,13 +592,13 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, > talloc_free(frame); > break; > } >- case HDB_AUTHSTATUS_CLIENT_LOCKED_OUT: >- case HDB_AUTHSTATUS_CORRECT_PASSWORD: >- case HDB_AUTHSTATUS_WRONG_PASSWORD: >- case HDB_AUTHSTATUS_GENERIC_SUCCESS: >- case HDB_AUTHSTATUS_GENERIC_FAILURE: >- case HDB_AUTHSTATUS_PKINIT_SUCCESS: >- case HDB_AUTHSTATUS_PKINIT_FAILURE: >+ case HDB_AUTH_EVENT_CLIENT_LOCKED_OUT: >+ case HDB_AUTH_EVENT_LTK_PREAUTH_SUCCEEDED: >+ case HDB_AUTH_EVENT_LTK_PREAUTH_FAILED: >+ case HDB_AUTH_EVENT_OTHER_PREAUTH_SUCCEEDED: >+ case HDB_AUTH_EVENT_OTHER_PREAUTH_FAILED: >+ case HDB_AUTH_EVENT_PKINIT_SUCCEEDED: >+ case HDB_AUTH_EVENT_PKINIT_FAILED: > { > TALLOC_CTX *frame = talloc_stackframe(); > struct samba_kdc_entry *p = talloc_get_type(entry->ctx, >@@ -589,7 +613,7 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, > NTSTATUS status; > int ret; > >- ret = tsocket_address_bsd_from_sockaddr(frame, from_addr, >+ ret = tsocket_address_bsd_from_sockaddr(frame, r->addr, > sa_socklen, > &remote_host); > if (ret != 0) { >@@ -613,7 +637,7 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, > } > ui.auth_description = auth_description; > >- if (hdb_auth_status == HDB_AUTHSTATUS_WRONG_PASSWORD) { >+ if (hdb_auth_status == HDB_AUTH_EVENT_LTK_PREAUTH_FAILED) { > authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn); > status = NT_STATUS_WRONG_PASSWORD; > /* >@@ -624,17 +648,17 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, > if (kdc_db_ctx->rodc) { > send_bad_password_netlogon(frame, kdc_db_ctx, &ui); > } >- } else if (hdb_auth_status == HDB_AUTHSTATUS_CLIENT_LOCKED_OUT) { >+ } else if (hdb_auth_status == HDB_AUTH_EVENT_CLIENT_LOCKED_OUT) { > status = NT_STATUS_ACCOUNT_LOCKED_OUT; >- } else if (hdb_auth_status == HDB_AUTHSTATUS_CORRECT_PASSWORD) { >+ } else if (hdb_auth_status == HDB_AUTH_EVENT_LTK_PREAUTH_SUCCEEDED) { > status = NT_STATUS_OK; >- } else if (hdb_auth_status == HDB_AUTHSTATUS_GENERIC_SUCCESS) { >+ } else if (hdb_auth_status == HDB_AUTH_EVENT_OTHER_PREAUTH_SUCCEEDED) { > status = NT_STATUS_OK; >- } else if (hdb_auth_status == HDB_AUTHSTATUS_GENERIC_FAILURE) { >+ } else if (hdb_auth_status == HDB_AUTH_EVENT_OTHER_PREAUTH_FAILED) { > status = NT_STATUS_GENERIC_COMMAND_FAILED; >- } else if (hdb_auth_status == HDB_AUTHSTATUS_PKINIT_SUCCESS) { >+ } else if (hdb_auth_status == HDB_AUTH_EVENT_PKINIT_SUCCEEDED) { > status = NT_STATUS_OK; >- } else if (hdb_auth_status == HDB_AUTHSTATUS_PKINIT_FAILURE) { >+ } else if (hdb_auth_status == HDB_AUTH_EVENT_PKINIT_FAILED) { > status = NT_STATUS_PKINIT_FAILURE; > } else { > status = NT_STATUS_INTERNAL_ERROR; >@@ -642,7 +666,7 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, > > log_authentication_event(kdc_db_ctx->msg_ctx, > kdc_db_ctx->lp_ctx, >- start_time, >+ &r->tv_start, > &ui, > status, > domain_name, >@@ -651,12 +675,12 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, > TALLOC_FREE(frame); > break; > } >- case HDB_AUTHSTATUS_CLIENT_UNKNOWN: >+ case HDB_AUTH_EVENT_CLIENT_UNKNOWN: > { > struct tsocket_address *remote_host; > int ret; > TALLOC_CTX *frame = talloc_stackframe(); >- ret = tsocket_address_bsd_from_sockaddr(frame, from_addr, >+ ret = tsocket_address_bsd_from_sockaddr(frame, r->addr, > sa_socklen, > &remote_host); > if (ret != 0) { >@@ -673,7 +697,7 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, > > log_authentication_event(kdc_db_ctx->msg_ctx, > kdc_db_ctx->lp_ctx, >- start_time, >+ &r->tv_start, > &ui, > NT_STATUS_NO_SUCH_USER, > NULL, NULL, >@@ -736,7 +760,7 @@ NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx, > (*db)->hdb__del = NULL; > (*db)->hdb_destroy = hdb_samba4_destroy; > >- (*db)->hdb_auth_status = hdb_samba4_auth_status; >+ (*db)->hdb_audit = hdb_samba4_audit; > (*db)->hdb_check_constrained_delegation = hdb_samba4_check_constrained_delegation; > (*db)->hdb_check_pkinit_ms_upn_match = hdb_samba4_check_pkinit_ms_upn_match; > (*db)->hdb_check_client_matches_target_service = hdb_samba4_check_client_matches_target_service; >-- >2.25.1 > > >From 71b41ea2e3f6c830aa4b077f9cb7c57161adbc0d Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Mon, 21 Feb 2022 20:45:45 +1300 >Subject: [PATCH 10/22] s4:kdc: Adapt to removal of auth event details > >This is an adaptation to Heimdal: > >commit e15e711b13e2fb33f4480a054cba60b6c4c0183b >Author: Luke Howard <lukeh@padl.com> >Date: Sat Jan 1 18:05:51 2022 +1100 > > kdc: remove auth_event_details audit key > > The auth event details audit key (formerly, parameter to auth_status) > contained, variously, an encryption type name; a PKINIT client certificate > name; or, a GSS initiator name. Audit these instead using individual keys that > reflect the values' contents. > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 7989ef0aa7b75b2e5af7be445fc64cbf49b2985c) >--- > source4/kdc/hdb-samba4.c | 42 ++++++++++++++++++++++++++++++++++++---- > 1 file changed, 38 insertions(+), 4 deletions(-) > >diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c >index 60b6f94a32d2..2f9d51d3c04a 100644 >--- a/source4/kdc/hdb-samba4.c >+++ b/source4/kdc/hdb-samba4.c >@@ -45,6 +45,7 @@ > #include "../lib/tsocket/tsocket.h" > #include "librpc/gen_ndr/ndr_winbind_c.h" > #include "lib/messaging/irpc.h" >+#include "hdb.h" > > static krb5_error_code hdb_samba4_open(krb5_context context, HDB *db, int flags, mode_t mode) > { >@@ -514,6 +515,8 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > heim_object_t auth_details_obj = NULL; > const char *auth_details = NULL; > >+ char *etype_str = NULL; >+ > heim_object_t hdb_auth_status_obj = NULL; > int hdb_auth_status; > >@@ -524,7 +527,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > > size_t sa_socklen = 0; > >- hdb_auth_status_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_AUTH_EVENT_TYPE); >+ hdb_auth_status_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_AUTH_EVENT); > if (hdb_auth_status_obj == NULL) { > /* No status code found, so just return. */ > return 0; >@@ -537,9 +540,37 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > pa_type = heim_string_get_utf8(pa_type_obj); > } > >- auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_AUTH_EVENT_DETAILS); >- if (auth_details_obj != NULL) { >- auth_details = heim_string_get_utf8(auth_details_obj); >+ switch (hdb_auth_status) { >+ case HDB_AUTH_EVENT_PKINIT_SUCCEEDED: >+ case HDB_AUTH_EVENT_PKINIT_FAILED: >+ auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_PKINIT_CLIENT_CERT); >+ if (auth_details_obj != NULL) { >+ auth_details = heim_string_get_utf8(auth_details_obj); >+ } >+ break; >+ >+ case HDB_AUTH_EVENT_GSS_PA_SUCCEEDED: >+ case HDB_AUTH_EVENT_GSS_PA_FAILED: >+ auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_GSS_INITIATOR); >+ if (auth_details_obj != NULL) { >+ auth_details = heim_string_get_utf8(auth_details_obj); >+ } >+ break; >+ >+ default: >+ { >+ heim_object_t etype_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_PA_ETYPE); >+ if (etype_obj != NULL) { >+ int etype = heim_number_get_int(etype_obj); >+ >+ krb5_error_code ret = krb5_enctype_to_string(r->context, etype, &etype_str); >+ if (ret == 0) { >+ auth_details = etype_str; >+ } else { >+ auth_details = "unknown enctype"; >+ } >+ } >+ } > } > > /* >@@ -706,6 +737,9 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > break; > } > } >+ >+ free(etype_str); >+ > return 0; > } > >-- >2.25.1 > > >From 69ba5464c00969d2e6a8a7af3eaab54c8545143f Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 22 Feb 2022 12:16:49 +1300 >Subject: [PATCH 11/22] s4:kdc: Add 'not authorised' auth events > >This is an adaptation to Heimdal: > >commit d683780b1d728bf8c5b794a1f66842e5a25bd360 >Author: Luke Howard <lukeh@padl.com> >Date: Sat Jan 1 23:44:05 2022 +1100 > > kdc: separate PKINIT/GSS authorization failure > > Create a new audit event for PKINIT/GSS authorization (impersonation) failure > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 0d37a1928100e229bea46701b41d4efa72e10266) >--- > source4/kdc/hdb-samba4.c | 2 ++ > 1 file changed, 2 insertions(+) > >diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c >index 2f9d51d3c04a..1d273bf8da08 100644 >--- a/source4/kdc/hdb-samba4.c >+++ b/source4/kdc/hdb-samba4.c >@@ -543,6 +543,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > switch (hdb_auth_status) { > case HDB_AUTH_EVENT_PKINIT_SUCCEEDED: > case HDB_AUTH_EVENT_PKINIT_FAILED: >+ case HDB_AUTH_EVENT_PKINIT_NOT_AUTHORIZED: > auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_PKINIT_CLIENT_CERT); > if (auth_details_obj != NULL) { > auth_details = heim_string_get_utf8(auth_details_obj); >@@ -551,6 +552,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > > case HDB_AUTH_EVENT_GSS_PA_SUCCEEDED: > case HDB_AUTH_EVENT_GSS_PA_FAILED: >+ case HDB_AUTH_EVENT_GSS_PA_NOT_AUTHORIZED: > auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_GSS_INITIATOR); > if (auth_details_obj != NULL) { > auth_details = heim_string_get_utf8(auth_details_obj); >-- >2.25.1 > > >From 0641f24f253f8c52cea84f2fc24fb84fe85cd4df Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Mon, 21 Feb 2022 19:25:06 +1300 >Subject: [PATCH 12/22] s4:kdc: Add referral policy callback > >This is now used instead of a configuration option. > >This is an adaption to Heimdal: > >commit 3fa47f5a1a422e178d968a8ec0d59889eaa71548 >Author: Luke Howard <lukeh@padl.com> >Date: Sun Jan 2 21:51:43 2022 +1100 > > kdc: add referral_policy callback to windc plugin > > Add a referral policy hook to the TGS as a more elegant way of resolving > referral detection for Samba). The hook can either rewrite the server_princ in > the request, or it can return an error to disable built-in referral processing. > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit a5799cea037a4613ba4d1073fff6e6151ed06c76) >--- > source4/kdc/kdc-heimdal.c | 2 -- > source4/kdc/wdc-samba4.c | 8 ++++++++ > 2 files changed, 8 insertions(+), 2 deletions(-) > >diff --git a/source4/kdc/kdc-heimdal.c b/source4/kdc/kdc-heimdal.c >index 2abb5eab9253..46fd8e61946a 100644 >--- a/source4/kdc/kdc-heimdal.c >+++ b/source4/kdc/kdc-heimdal.c >@@ -408,8 +408,6 @@ static void kdc_post_fork(struct task_server *task, struct process_details *pd) > kdc_config->svc_use_strongest_session_key = false; > kdc_config->use_strongest_server_key = true; > >- kdc_config->autodetect_referrals = false; >- > kdc_config->force_include_pa_etype_salt = true; > > /* >diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c >index e670f3226c53..4ba2f7938f56 100644 >--- a/source4/kdc/wdc-samba4.c >+++ b/source4/kdc/wdc-samba4.c >@@ -28,6 +28,7 @@ > #include "sdb.h" > #include "sdb_hdb.h" > #include "librpc/gen_ndr/auth.h" >+#include <krb5_locl.h> > > /* > * Given the right private pointer from hdb_samba4, >@@ -952,6 +953,12 @@ static void samba_wdc_plugin_fini(void *ptr) > return; > } > >+static krb5_error_code samba_wdc_referral_policy(void *priv, >+ astgs_request_t r) >+{ >+ return r->error_code; >+} >+ > struct krb5plugin_windc_ftable windc_plugin_table = { > .minor_version = KRB5_WINDC_PLUGIN_MINOR, > .init = samba_wdc_plugin_init, >@@ -960,6 +967,7 @@ struct krb5plugin_windc_ftable windc_plugin_table = { > .client_access = samba_wdc_check_client_access, > .finalize_reply = samba_wdc_finalize_reply, > .pac_generate = samba_wdc_get_pac, >+ .referral_policy = samba_wdc_referral_policy, > }; > > >-- >2.25.1 > > >From 96057ac8a943cc5fac96abc422d29f70820a754d Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 22 Feb 2022 14:39:13 +1300 >Subject: [PATCH 13/22] s4:kdc: Rename windc to kdc plugin > >This is an adaptation to Heimdal: > >commit fcff5933ade652343d7c169659da92fac0e6e0d4 >Author: Luke Howard <lukeh@padl.com> >Date: Mon Jan 3 11:10:18 2022 +1100 > > kdc: rename windc to kdc plugin > > Rename the "windc" plugin API to the more general "kdc" plugin API, for two > reasons: the Heimdal KDC uses the Windows PAC even when not emulating a domain > controller, and the plugin API has accreted methods that are not specific to > emulating a domain controller (such as referral_policy and finalize_reply). > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 83586e8f5846fff7a8bbe47e743e03166b559584) >--- > source4/kdc/kdc-glue.h | 2 +- > source4/kdc/kdc-heimdal.c | 14 +++++++------- > source4/kdc/wdc-samba4.c | 4 ++-- > third_party/heimdal_build/krb5/kdc-plugin.h | 1 + > third_party/heimdal_build/krb5/windc_plugin.h | 1 - > third_party/heimdal_build/wscript_build | 2 +- > 6 files changed, 12 insertions(+), 12 deletions(-) > create mode 100644 third_party/heimdal_build/krb5/kdc-plugin.h > delete mode 100644 third_party/heimdal_build/krb5/windc_plugin.h > >diff --git a/source4/kdc/kdc-glue.h b/source4/kdc/kdc-glue.h >index 3b85468c499e..2e58fcda1398 100644 >--- a/source4/kdc/kdc-glue.h >+++ b/source4/kdc/kdc-glue.h >@@ -28,7 +28,7 @@ > #include <hdb.h> > #include <heimbase.h> > #include <kdc.h> >-#include <krb5/windc_plugin.h> >+#include <krb5/kdc-plugin.h> > #include "kdc/samba_kdc.h" > #include "kdc/kdc-server.h" > >diff --git a/source4/kdc/kdc-heimdal.c b/source4/kdc/kdc-heimdal.c >index 46fd8e61946a..96322cd1bb76 100644 >--- a/source4/kdc/kdc-heimdal.c >+++ b/source4/kdc/kdc-heimdal.c >@@ -42,7 +42,7 @@ > > NTSTATUS server_service_kdc_init(TALLOC_CTX *); > >-extern struct krb5plugin_windc_ftable windc_plugin_table; >+extern struct krb5plugin_kdc_ftable kdc_plugin_table; > > /** > Wrapper for krb5_kdc_process_krb5_request, converting to/from Samba >@@ -470,19 +470,19 @@ static void kdc_post_fork(struct task_server *task, struct process_details *pd) > return; > } > >- /* Register WinDC hooks */ >+ /* Register KDC hooks */ > ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context, >- PLUGIN_TYPE_DATA, "windc", >- &windc_plugin_table); >+ PLUGIN_TYPE_DATA, "kdc", >+ &kdc_plugin_table); > if(ret) { >- task_server_terminate(task, "kdc: failed to register windc plugin", true); >+ task_server_terminate(task, "kdc: failed to register kdc plugin", true); > return; > } > >- ret = krb5_kdc_windc_init(kdc->smb_krb5_context->krb5_context); >+ ret = krb5_kdc_plugin_init(kdc->smb_krb5_context->krb5_context); > > if(ret) { >- task_server_terminate(task, "kdc: failed to init windc plugin", true); >+ task_server_terminate(task, "kdc: failed to init kdc plugin", true); > return; > } > >diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c >index 4ba2f7938f56..f4ac075e2d46 100644 >--- a/source4/kdc/wdc-samba4.c >+++ b/source4/kdc/wdc-samba4.c >@@ -959,8 +959,8 @@ static krb5_error_code samba_wdc_referral_policy(void *priv, > return r->error_code; > } > >-struct krb5plugin_windc_ftable windc_plugin_table = { >- .minor_version = KRB5_WINDC_PLUGIN_MINOR, >+struct krb5plugin_kdc_ftable kdc_plugin_table = { >+ .minor_version = KRB5_KDC_PLUGIN_MINOR, > .init = samba_wdc_plugin_init, > .fini = samba_wdc_plugin_fini, > .pac_verify = samba_wdc_reget_pac, >diff --git a/third_party/heimdal_build/krb5/kdc-plugin.h b/third_party/heimdal_build/krb5/kdc-plugin.h >new file mode 100644 >index 000000000000..1b99a8d6a73b >--- /dev/null >+++ b/third_party/heimdal_build/krb5/kdc-plugin.h >@@ -0,0 +1 @@ >+#include "../../heimdal/kdc/kdc-plugin.h" >diff --git a/third_party/heimdal_build/krb5/windc_plugin.h b/third_party/heimdal_build/krb5/windc_plugin.h >deleted file mode 100644 >index 538b617d90d8..000000000000 >--- a/third_party/heimdal_build/krb5/windc_plugin.h >+++ /dev/null >@@ -1 +0,0 @@ >-#include "../../heimdal/kdc/windc_plugin.h" >diff --git a/third_party/heimdal_build/wscript_build b/third_party/heimdal_build/wscript_build >index 76e88bc103e0..d43237b0c3bd 100644 >--- a/third_party/heimdal_build/wscript_build >+++ b/third_party/heimdal_build/wscript_build >@@ -439,7 +439,7 @@ if not bld.CONFIG_SET("USING_SYSTEM_KDC"): > directory='lib/asn1' > ) > >- KDC_SOURCE='kdc/default_config.c kdc/fast.c kdc/kerberos5.c kdc/krb5tgs.c kdc/pkinit.c kdc/pkinit-ec.c kdc/log.c kdc/misc.c kdc/digest.c kdc/process.c kdc/windc.c kdc/kx509.c kdc/gss_preauth.c' >+ KDC_SOURCE='kdc/default_config.c kdc/fast.c kdc/kerberos5.c kdc/krb5tgs.c kdc/pkinit.c kdc/pkinit-ec.c kdc/log.c kdc/misc.c kdc/digest.c kdc/process.c kdc/kdc-plugin.c kdc/kx509.c kdc/gss_preauth.c' > > HEIMDAL_LIBRARY('kdc', source=KDC_SOURCE, > includes='../heimdal/kdc', >-- >2.25.1 > > >From c80636c3ff5b442f95db3e6752c13bba50826c26 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 22 Feb 2022 15:48:12 +1300 >Subject: [PATCH 14/22] s4:kdc: Adapt to removal of auth audit event types > >This is an adaptation to Heimdal: > >commit 06f8985c55fcd23e3efe0017ed2480c5b3c4524f >Author: Luke Howard <lukeh@padl.com> >Date: Wed Jan 5 09:42:03 2022 +1100 > > hdb: consolidate preauth audit event types > > Instead of having distinct preauth success/failure events for different > mechanisms, have a single event; the mechanism can be disambiguated by querying > the HDB_REQUEST_KV_PA_NAME key. > > Note: there is still an explicit event for long-term key-based success/failure > in order to help the backend implement lockout. > > Audit failure (HDB_AUTH_EVENT_PREAUTH_FAILED) in the main preauth loop, rather > than in each mechanism. Success is still audited in the mechanism to allow > client pre-authentication success to be noted even if something subsequent > (e.g. encoding a reply, memory allocation) fails. The generic catch-all for > success remains. > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit f234361abea4166ce4e10cfa4e7f4096b83480a9) >--- > source4/kdc/hdb-samba4.c | 71 ++++++++++++++++------------------------ > 1 file changed, 28 insertions(+), 43 deletions(-) > >diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c >index 1d273bf8da08..94809b9c9149 100644 >--- a/source4/kdc/hdb-samba4.c >+++ b/source4/kdc/hdb-samba4.c >@@ -540,40 +540,27 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > pa_type = heim_string_get_utf8(pa_type_obj); > } > >- switch (hdb_auth_status) { >- case HDB_AUTH_EVENT_PKINIT_SUCCEEDED: >- case HDB_AUTH_EVENT_PKINIT_FAILED: >- case HDB_AUTH_EVENT_PKINIT_NOT_AUTHORIZED: >- auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_PKINIT_CLIENT_CERT); >- if (auth_details_obj != NULL) { >- auth_details = heim_string_get_utf8(auth_details_obj); >- } >- break; >- >- case HDB_AUTH_EVENT_GSS_PA_SUCCEEDED: >- case HDB_AUTH_EVENT_GSS_PA_FAILED: >- case HDB_AUTH_EVENT_GSS_PA_NOT_AUTHORIZED: >+ auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_PKINIT_CLIENT_CERT); >+ if (auth_details_obj != NULL) { >+ auth_details = heim_string_get_utf8(auth_details_obj); >+ } else { > auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_GSS_INITIATOR); > if (auth_details_obj != NULL) { > auth_details = heim_string_get_utf8(auth_details_obj); >- } >- break; >- >- default: >- { >- heim_object_t etype_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_PA_ETYPE); >- if (etype_obj != NULL) { >- int etype = heim_number_get_int(etype_obj); >- >- krb5_error_code ret = krb5_enctype_to_string(r->context, etype, &etype_str); >- if (ret == 0) { >- auth_details = etype_str; >- } else { >- auth_details = "unknown enctype"; >+ } else { >+ heim_object_t etype_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_PA_ETYPE); >+ if (etype_obj != NULL) { >+ int etype = heim_number_get_int(etype_obj); >+ >+ krb5_error_code ret = krb5_enctype_to_string(r->context, etype, &etype_str); >+ if (ret == 0) { >+ auth_details = etype_str; >+ } else { >+ auth_details = "unknown enctype"; >+ } > } > } > } >- } > > /* > * Forcing this via the NTLM auth structure is not ideal, but >@@ -626,12 +613,10 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > break; > } > case HDB_AUTH_EVENT_CLIENT_LOCKED_OUT: >- case HDB_AUTH_EVENT_LTK_PREAUTH_SUCCEEDED: >- case HDB_AUTH_EVENT_LTK_PREAUTH_FAILED: >- case HDB_AUTH_EVENT_OTHER_PREAUTH_SUCCEEDED: >- case HDB_AUTH_EVENT_OTHER_PREAUTH_FAILED: >- case HDB_AUTH_EVENT_PKINIT_SUCCEEDED: >- case HDB_AUTH_EVENT_PKINIT_FAILED: >+ case HDB_AUTH_EVENT_VALIDATED_LONG_TERM_KEY: >+ case HDB_AUTH_EVENT_WRONG_LONG_TERM_KEY: >+ case HDB_AUTH_EVENT_PREAUTH_SUCCEEDED: >+ case HDB_AUTH_EVENT_PREAUTH_FAILED: > { > TALLOC_CTX *frame = talloc_stackframe(); > struct samba_kdc_entry *p = talloc_get_type(entry->ctx, >@@ -670,7 +655,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > } > ui.auth_description = auth_description; > >- if (hdb_auth_status == HDB_AUTH_EVENT_LTK_PREAUTH_FAILED) { >+ if (hdb_auth_status == HDB_AUTH_EVENT_WRONG_LONG_TERM_KEY) { > authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn); > status = NT_STATUS_WRONG_PASSWORD; > /* >@@ -683,16 +668,16 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > } > } else if (hdb_auth_status == HDB_AUTH_EVENT_CLIENT_LOCKED_OUT) { > status = NT_STATUS_ACCOUNT_LOCKED_OUT; >- } else if (hdb_auth_status == HDB_AUTH_EVENT_LTK_PREAUTH_SUCCEEDED) { >- status = NT_STATUS_OK; >- } else if (hdb_auth_status == HDB_AUTH_EVENT_OTHER_PREAUTH_SUCCEEDED) { >+ } else if (hdb_auth_status == HDB_AUTH_EVENT_VALIDATED_LONG_TERM_KEY) { > status = NT_STATUS_OK; >- } else if (hdb_auth_status == HDB_AUTH_EVENT_OTHER_PREAUTH_FAILED) { >- status = NT_STATUS_GENERIC_COMMAND_FAILED; >- } else if (hdb_auth_status == HDB_AUTH_EVENT_PKINIT_SUCCEEDED) { >+ } else if (hdb_auth_status == HDB_AUTH_EVENT_PREAUTH_SUCCEEDED) { > status = NT_STATUS_OK; >- } else if (hdb_auth_status == HDB_AUTH_EVENT_PKINIT_FAILED) { >- status = NT_STATUS_PKINIT_FAILURE; >+ } else if (hdb_auth_status == HDB_AUTH_EVENT_PREAUTH_FAILED) { >+ if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) { >+ status = NT_STATUS_PKINIT_FAILURE; >+ } else { >+ status = NT_STATUS_GENERIC_COMMAND_FAILED; >+ } > } else { > status = NT_STATUS_INTERNAL_ERROR; > } >-- >2.25.1 > > >From 2976a541545c32e9f9517c2f2fd6a10dfea51119 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 22 Feb 2022 15:53:34 +1300 >Subject: [PATCH 15/22] third_party/heimdal_build: Add SFU source file > >This is an adaptation to Heimdal: > >commit 0287558838de79313e38026d2f0905ffc987d0b8 >Author: Luke Howard <lukeh@padl.com> >Date: Fri Dec 24 13:49:55 2021 +1100 > > kdc: move Services for User implementation out of krb5tgs.c > > Move the Services for User (SFU/S4U) implementation -- protocol transition and > constrained delegation -- into its own compilation unit, with an interface that > only takes an astgs_request_t, so it can be easily factored out into a plugin > module in the future. > > This refactoring is also careful to update all client names in the request > structure after the SFU/S4U validation has successfully completed. > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit b9f4ea8bdb70476d6cc6df962bf6b28805588ed5) >--- > third_party/heimdal_build/wscript_build | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/third_party/heimdal_build/wscript_build b/third_party/heimdal_build/wscript_build >index d43237b0c3bd..69aeb1201918 100644 >--- a/third_party/heimdal_build/wscript_build >+++ b/third_party/heimdal_build/wscript_build >@@ -439,7 +439,7 @@ if not bld.CONFIG_SET("USING_SYSTEM_KDC"): > directory='lib/asn1' > ) > >- KDC_SOURCE='kdc/default_config.c kdc/fast.c kdc/kerberos5.c kdc/krb5tgs.c kdc/pkinit.c kdc/pkinit-ec.c kdc/log.c kdc/misc.c kdc/digest.c kdc/process.c kdc/kdc-plugin.c kdc/kx509.c kdc/gss_preauth.c' >+ KDC_SOURCE='kdc/default_config.c kdc/fast.c kdc/kerberos5.c kdc/krb5tgs.c kdc/pkinit.c kdc/pkinit-ec.c kdc/mssfu.c kdc/log.c kdc/misc.c kdc/digest.c kdc/process.c kdc/kdc-plugin.c kdc/kx509.c kdc/gss_preauth.c' > > HEIMDAL_LIBRARY('kdc', source=KDC_SOURCE, > includes='../heimdal/kdc', >-- >2.25.1 > > >From 938268374dd260aaf4ab5b2bef68cf14c17f65e4 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 22 Feb 2022 15:56:32 +1300 >Subject: [PATCH 16/22] s4:kdc: Explicitly set plugin minor version > >This is an adaptation to Heimdal: > >commit 7cc4b7a9e624f5eecfbb38607d4cc0870a895671 >Author: Luke Howard <lukeh@padl.com> >Date: Wed Jan 5 13:08:11 2022 +1100 > > kdc: KDC plugin API contract notes > > Add some notes about the KDC plugin API contract, and require plugins to > explicitly indicate which version of the API they support (remove the macro > alias for the current version). > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 675f913e54d8fddb9173c1e67b9d14885cc1d878) >--- > source4/kdc/wdc-samba4.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c >index f4ac075e2d46..3366726597e7 100644 >--- a/source4/kdc/wdc-samba4.c >+++ b/source4/kdc/wdc-samba4.c >@@ -960,7 +960,7 @@ static krb5_error_code samba_wdc_referral_policy(void *priv, > } > > struct krb5plugin_kdc_ftable kdc_plugin_table = { >- .minor_version = KRB5_KDC_PLUGIN_MINOR, >+ .minor_version = KRB5_PLUGIN_KDC_VERSION_8, > .init = samba_wdc_plugin_init, > .fini = samba_wdc_plugin_fini, > .pac_verify = samba_wdc_reget_pac, >-- >2.25.1 > > >From 5b0bc8884d54fff294375e7e20f9fba5cd6b9afe Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Mon, 21 Feb 2022 19:12:28 +1300 >Subject: [PATCH 17/22] third_party/heimdal_build: Don't generate .x source > files > >This is an adaptation to Heimdal: > >commit 9427796f1a65906f12768b28abdb5a928222f3c6 >Author: Jeffrey Altman <jaltman@secure-endpoints.com> >Date: Wed Jan 5 15:45:23 2022 -0500 > > Generate .x source files as .c source files > > The generated .x source and .hx header files are plain C source files. > Generate them as .c source files and avoid unnecessary file copying > and special makefile rules. > > Change-Id: Ifc4bbe3c46dd357fdd642040ad964c7cfe1d395c > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 7cb68fdba75c362cdfd8f3bf08bcd9c22bbe4556) >--- > third_party/heimdal_build/wscript_build | 47 +++++-------------------- > 1 file changed, 8 insertions(+), 39 deletions(-) > >diff --git a/third_party/heimdal_build/wscript_build b/third_party/heimdal_build/wscript_build >index 69aeb1201918..3ea1fc93653f 100644 >--- a/third_party/heimdal_build/wscript_build >+++ b/third_party/heimdal_build/wscript_build >@@ -40,10 +40,10 @@ def HEIMDAL_ASN1(name, source, > bld.set_group('build_source') > > out_files = heimdal_paths([ >- "%s/asn1_%s_asn1.x" % (directory, bname), >- "%s/%s_asn1.hx" % (directory, bname), >- "%s/%s_asn1-priv.hx" % (directory, bname), >- "%s/%s_asn1_oids.x" % (directory, bname), >+ "%s/asn1_%s_asn1.c" % (directory, bname), >+ "%s/%s_asn1.h" % (directory, bname), >+ "%s/%s_asn1-priv.h" % (directory, bname), >+ "%s/%s_asn1_oids.c" % (directory, bname), > ]) > > # the ${TGT[0].parent.abspath(env)} expression gives us the parent directory of >@@ -81,7 +81,7 @@ def HEIMDAL_ASN1(name, source, > deps = 'asn1_compile' > > t = bld(rule=asn1_rule, >- ext_out = '.x', >+ ext_out = '.c', > before = 'c', > update_outputs = True, > shell = True, >@@ -97,40 +97,9 @@ def HEIMDAL_ASN1(name, source, > t.env.OPTION_FILE = "--option-file='%s'" % \ > os.path.normpath(os.path.join(bld.path.abspath(), option_file)) > >- cfile = out_files[0][0:-2] + '.c' >- hfile = out_files[1][0:-3] + '.h' >- hpriv = out_files[2][0:-3] + '.h' >- >- # now generate a .c file from the .x file >- t = bld(rule='''( echo '#include "config.h"' && cat ${SRC} ) > ${TGT}''', >- source = out_files[0], >- target = cfile, >- shell = True, >- update_outputs=True, >- ext_out = '.c', >- ext_in = '.x', >- depends_on = name + '_ASN1', >- name = name + '_C') >- >- # and generate a .h file from the .hx file >- t = bld(rule='cp ${SRC} ${TGT}', >- source = out_files[1], >- ext_out = '.c', >- ext_in = '.x', >- update_outputs=True, >- target = hfile, >- depends_on = name + '_ASN1', >- name = name + '_H') >- >- # and generate a .h file from the .hx file >- t = bld(rule='cp ${SRC} ${TGT}', >- source = out_files[2], >- ext_out = '.c', >- ext_in = '.x', >- update_outputs=True, >- target = hpriv, >- depends_on = name + '_ASN1', >- name = name + '_PRIV_H') >+ cfile = out_files[0] >+ hfile = out_files[1] >+ hpriv = out_files[2] > > bld.set_group('main') > >-- >2.25.1 > > >From c80dafc0e32af599b3f7b1f5b346b5dc773c2bef Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 22 Feb 2022 16:30:27 +1300 >Subject: [PATCH 18/22] s4:kdc: Increment plugin minor version > >This is an adaptation to Heimdal: > >commit 40e4a4df09c2d6c3ba7bf14df1dee74a0bc18110 >Author: Luke Howard <lukeh@padl.com> >Date: Mon Jan 10 12:50:37 2022 +1100 > > kdc: use astgs_request_t for client/server name (TGS) > > Store the client and server principal name from the TGT and request > (respectively) in the astgs_request_t rather than using local variables. > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 068f2bf117ab9968011fdb8d60b98bb37d529658) >--- > source4/kdc/wdc-samba4.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c >index 3366726597e7..9356979dd7dc 100644 >--- a/source4/kdc/wdc-samba4.c >+++ b/source4/kdc/wdc-samba4.c >@@ -960,7 +960,7 @@ static krb5_error_code samba_wdc_referral_policy(void *priv, > } > > struct krb5plugin_kdc_ftable kdc_plugin_table = { >- .minor_version = KRB5_PLUGIN_KDC_VERSION_8, >+ .minor_version = KRB5_PLUGIN_KDC_VERSION_9, > .init = samba_wdc_plugin_init, > .fini = samba_wdc_plugin_fini, > .pac_verify = samba_wdc_reget_pac, >-- >2.25.1 > > >From 8e81e7f5b3938773d7ff87627b63d960a2677a1c Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Tue, 22 Feb 2022 19:41:14 +1300 >Subject: [PATCH 19/22] s4:kdc: Adapt to hdb_entry_ex removal > >Rather than having a 'free_entry' member that can be called to free an >hdb_entry, we now implement the free function in HDB. We perform the >free only if the context pointer is non-NULL. > >We also remove the ZERO_STRUCTP() in sdb_entry_to_hdb_entry(), as the >context pointer is now part of the 'hdb_entry' structure itself, and >this would undesirably zero it out. > >This is an adaptation to Heimdal commits: > >commit c5551775e204d00c7ee8055ab6ddbba7e0590584 >Author: Luke Howard <lukeh@padl.com> >Date: Fri Jan 7 12:15:55 2022 +1100 > > hdb: decorate HDB_entry with context member > > Decorate HDB_entry with context and move free_entry callback into HDB structure > itself. Requires updating hdb_free_entry() signature to include HDB parameter. > A follow-up commit will consolidate hdb_entry_ex (which has a single hdb_entry > member) into hdb_entry. > >commit 0e8c4ccc6ee0123ea39e53e8917fc3f6bb74e8c8 >Author: Luke Howard <lukeh@padl.com> >Date: Fri Jan 7 12:54:40 2022 +1100 > > hdb: eliminate hdb_entry_ex > > Remove hdb_entry_ex and revert to the original design of hdb_entry (except with > an additional context member in hdb_entry which is managed by the free_entry > method in HDB). > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 94d387abd5031c12989f925ee5eb733432402d1d) >--- > source4/kdc/hdb-samba4.c | 51 +++++++++++++++------- > source4/kdc/kdc-glue.c | 4 +- > source4/kdc/kdc-glue.h | 2 +- > source4/kdc/kdc-heimdal.c | 6 +-- > source4/kdc/sdb_to_hdb.c | 26 +++-------- > source4/kdc/wdc-samba4.c | 58 +++++++++++++------------ > third_party/heimdal_build/wscript_build | 5 +-- > 7 files changed, 77 insertions(+), 75 deletions(-) > >diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c >index 94809b9c9149..90cd3a78de8f 100644 >--- a/source4/kdc/hdb-samba4.c >+++ b/source4/kdc/hdb-samba4.c >@@ -79,7 +79,7 @@ static krb5_error_code hdb_samba4_rename(krb5_context context, HDB *db, const ch > return HDB_ERR_DB_INUSE; > } > >-static krb5_error_code hdb_samba4_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) >+static krb5_error_code hdb_samba4_store(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) > { > return HDB_ERR_DB_INUSE; > } >@@ -93,6 +93,24 @@ static krb5_error_code hdb_samba4_set_sync(krb5_context context, struct HDB *db, > return 0; > } > >+static void hdb_samba4_free_entry_context(krb5_context context, struct HDB *db, hdb_entry *entry) >+{ >+ /* >+ * This function is now called for every HDB entry, not just those with >+ * 'context' set, so we have to check that the context is not NULL. >+ */ >+ if (entry->context != NULL) { >+ /* this function is called only from hdb_free_entry(). >+ * Make sure we neutralize the destructor or we will >+ * get a double free later when hdb_free_entry() will >+ * try to call free_hdb_entry() */ >+ talloc_set_destructor(entry->context, NULL); >+ >+ /* now proceed to free the talloc part */ >+ talloc_free(entry->context); >+ } >+} >+ > static int hdb_samba4_fill_fast_cookie(krb5_context context, > struct samba_kdc_db_context *kdc_db_ctx) > { >@@ -131,7 +149,7 @@ static int hdb_samba4_fill_fast_cookie(krb5_context context, > > static krb5_error_code hdb_samba4_fetch_fast_cookie(krb5_context context, > struct samba_kdc_db_context *kdc_db_ctx, >- hdb_entry_ex *entry_ex) >+ hdb_entry *entry_ex) > { > krb5_error_code ret = SDB_ERR_NOENTRY; > TALLOC_CTX *mem_ctx; >@@ -219,7 +237,7 @@ static krb5_error_code hdb_samba4_fetch_kvno(krb5_context context, HDB *db, > krb5_const_principal principal, > unsigned flags, > krb5_kvno kvno, >- hdb_entry_ex *entry_ex) >+ hdb_entry *entry_ex) > { > struct samba_kdc_db_context *kdc_db_ctx; > struct sdb_entry_ex sdb_entry_ex = {}; >@@ -273,7 +291,7 @@ static krb5_error_code hdb_samba4_fetch_kvno(krb5_context context, HDB *db, > } > > static krb5_error_code hdb_samba4_firstkey(krb5_context context, HDB *db, unsigned flags, >- hdb_entry_ex *entry) >+ hdb_entry *entry) > { > struct samba_kdc_db_context *kdc_db_ctx; > struct sdb_entry_ex sdb_entry_ex = {}; >@@ -302,7 +320,7 @@ static krb5_error_code hdb_samba4_firstkey(krb5_context context, HDB *db, unsign > } > > static krb5_error_code hdb_samba4_nextkey(krb5_context context, HDB *db, unsigned flags, >- hdb_entry_ex *entry) >+ hdb_entry *entry) > { > struct samba_kdc_db_context *kdc_db_ctx; > struct sdb_entry_ex sdb_entry_ex = {}; >@@ -338,7 +356,7 @@ static krb5_error_code hdb_samba4_destroy(krb5_context context, HDB *db) > > static krb5_error_code > hdb_samba4_check_constrained_delegation(krb5_context context, HDB *db, >- hdb_entry_ex *entry, >+ hdb_entry *entry, > krb5_const_principal target_principal) > { > struct samba_kdc_db_context *kdc_db_ctx; >@@ -347,7 +365,7 @@ hdb_samba4_check_constrained_delegation(krb5_context context, HDB *db, > > kdc_db_ctx = talloc_get_type_abort(db->hdb_db, > struct samba_kdc_db_context); >- skdc_entry = talloc_get_type_abort(entry->ctx, >+ skdc_entry = talloc_get_type_abort(entry->context, > struct samba_kdc_entry); > > ret = samba_kdc_check_s4u2proxy(context, kdc_db_ctx, >@@ -374,7 +392,7 @@ hdb_samba4_check_constrained_delegation(krb5_context context, HDB *db, > > static krb5_error_code > hdb_samba4_check_pkinit_ms_upn_match(krb5_context context, HDB *db, >- hdb_entry_ex *entry, >+ hdb_entry *entry, > krb5_const_principal certificate_principal) > { > struct samba_kdc_db_context *kdc_db_ctx; >@@ -383,7 +401,7 @@ hdb_samba4_check_pkinit_ms_upn_match(krb5_context context, HDB *db, > > kdc_db_ctx = talloc_get_type_abort(db->hdb_db, > struct samba_kdc_db_context); >- skdc_entry = talloc_get_type_abort(entry->ctx, >+ skdc_entry = talloc_get_type_abort(entry->context, > struct samba_kdc_entry); > > ret = samba_kdc_check_pkinit_ms_upn_match(context, kdc_db_ctx, >@@ -410,14 +428,14 @@ hdb_samba4_check_pkinit_ms_upn_match(krb5_context context, HDB *db, > > static krb5_error_code > hdb_samba4_check_client_matches_target_service(krb5_context context, HDB *db, >- hdb_entry_ex *client_entry, >- hdb_entry_ex *server_target_entry) >+ hdb_entry *client_entry, >+ hdb_entry *server_target_entry) > { > struct samba_kdc_entry *skdc_client_entry >- = talloc_get_type_abort(client_entry->ctx, >+ = talloc_get_type_abort(client_entry->context, > struct samba_kdc_entry); > struct samba_kdc_entry *skdc_server_target_entry >- = talloc_get_type_abort(server_target_entry->ctx, >+ = talloc_get_type_abort(server_target_entry->context, > struct samba_kdc_entry); > > return samba_kdc_check_client_matches_target_service(context, >@@ -503,7 +521,7 @@ static void send_bad_password_netlogon(TALLOC_CTX *mem_ctx, > > static krb5_error_code hdb_samba4_audit(krb5_context context, > HDB *db, >- hdb_entry_ex *entry, >+ hdb_entry *entry, > hdb_request_t r) > { > struct samba_kdc_db_context *kdc_db_ctx = talloc_get_type_abort(db->hdb_db, >@@ -595,7 +613,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > case HDB_AUTH_EVENT_CLIENT_AUTHORIZED: > { > TALLOC_CTX *frame = talloc_stackframe(); >- struct samba_kdc_entry *p = talloc_get_type(entry->ctx, >+ struct samba_kdc_entry *p = talloc_get_type(entry->context, > struct samba_kdc_entry); > struct netr_SendToSamBase *send_to_sam = NULL; > >@@ -619,7 +637,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > case HDB_AUTH_EVENT_PREAUTH_FAILED: > { > TALLOC_CTX *frame = talloc_stackframe(); >- struct samba_kdc_entry *p = talloc_get_type(entry->ctx, >+ struct samba_kdc_entry *p = talloc_get_type(entry->context, > struct samba_kdc_entry); > struct dom_sid *sid > = samdb_result_dom_sid(frame, p->msg, "objectSid"); >@@ -766,6 +784,7 @@ NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx, > (*db)->hdb_dbc = NULL; > (*db)->hdb_open = hdb_samba4_open; > (*db)->hdb_close = hdb_samba4_close; >+ (*db)->hdb_free_entry_context = hdb_samba4_free_entry_context; > (*db)->hdb_fetch_kvno = hdb_samba4_fetch_kvno; > (*db)->hdb_store = hdb_samba4_store; > (*db)->hdb_firstkey = hdb_samba4_firstkey; >diff --git a/source4/kdc/kdc-glue.c b/source4/kdc/kdc-glue.c >index c6cc61ad02d7..671e506b8cc1 100644 >--- a/source4/kdc/kdc-glue.c >+++ b/source4/kdc/kdc-glue.c >@@ -34,7 +34,7 @@ > int kdc_check_pac(krb5_context context, > DATA_BLOB srv_sig, > struct PAC_SIGNATURE_DATA *kdc_sig, >- struct hdb_entry_ex *ent) >+ hdb_entry *ent) > { > krb5_enctype etype; > int ret; >@@ -52,7 +52,7 @@ int kdc_check_pac(krb5_context context, > } > } > >- ret = hdb_enctype2key(context, &ent->entry, NULL, etype, &key); >+ ret = hdb_enctype2key(context, ent, NULL, etype, &key); > > if (ret != 0) { > return ret; >diff --git a/source4/kdc/kdc-glue.h b/source4/kdc/kdc-glue.h >index 2e58fcda1398..47642e124320 100644 >--- a/source4/kdc/kdc-glue.h >+++ b/source4/kdc/kdc-glue.h >@@ -50,5 +50,5 @@ NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx, > int kdc_check_pac(krb5_context krb5_context, > DATA_BLOB server_sig, > struct PAC_SIGNATURE_DATA *kdc_sig, >- hdb_entry_ex *ent); >+ hdb_entry *ent); > #endif >diff --git a/source4/kdc/kdc-heimdal.c b/source4/kdc/kdc-heimdal.c >index 96322cd1bb76..ddf3b649da2d 100644 >--- a/source4/kdc/kdc-heimdal.c >+++ b/source4/kdc/kdc-heimdal.c >@@ -191,7 +191,7 @@ static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg, > (krb5_kdc_configuration *)kdc->private_data; > enum ndr_err_code ndr_err; > int ret; >- hdb_entry_ex ent; >+ hdb_entry ent; > krb5_principal principal; > > >@@ -235,7 +235,7 @@ static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg, > &ent); > > if (ret != 0) { >- hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent); >+ hdb_free_entry(kdc->smb_krb5_context->krb5_context, kdc_config->db[0], &ent); > krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal); > > return NT_STATUS_LOGON_FAILURE; >@@ -247,7 +247,7 @@ static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg, > > ret = kdc_check_pac(kdc->smb_krb5_context->krb5_context, srv_sig, &kdc_sig, &ent); > >- hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent); >+ hdb_free_entry(kdc->smb_krb5_context->krb5_context, kdc_config->db[0], &ent); > krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal); > > if (ret != 0) { >diff --git a/source4/kdc/sdb_to_hdb.c b/source4/kdc/sdb_to_hdb.c >index e5cc84a7e637..e2d6e40c837e 100644 >--- a/source4/kdc/sdb_to_hdb.c >+++ b/source4/kdc/sdb_to_hdb.c >@@ -180,8 +180,6 @@ static int sdb_entry_to_hdb_entry(krb5_context context, > unsigned int i; > int rc; > >- ZERO_STRUCTP(h); >- > rc = krb5_copy_principal(context, > s->principal, > &h->principal); >@@ -311,28 +309,15 @@ error: > > static int samba_kdc_hdb_entry_destructor(struct samba_kdc_entry *p) > { >- struct hdb_entry_ex *entry_ex = p->entry_ex; >- free_hdb_entry(&entry_ex->entry); >+ hdb_entry *entry_ex = p->entry_ex; >+ free_hdb_entry(entry_ex); > > return 0; > } > >-static void samba_kdc_free_hdb_entry(krb5_context context, >- struct hdb_entry_ex *entry_ex) >-{ >- /* this function is called only from hdb_free_entry(). >- * Make sure we neutralize the destructor or we will >- * get a double free later when hdb_free_entry() will >- * try to call free_hdb_entry() */ >- talloc_set_destructor(entry_ex->ctx, NULL); >- >- /* now proceed to free the talloc part */ >- talloc_free(entry_ex->ctx); >-} >- > int sdb_entry_ex_to_hdb_entry_ex(krb5_context context, > const struct sdb_entry_ex *s, >- struct hdb_entry_ex *h) >+ hdb_entry *h) > { > struct samba_kdc_entry *skdc_entry; > >@@ -341,12 +326,11 @@ int sdb_entry_ex_to_hdb_entry_ex(krb5_context context, > if (s->ctx != NULL) { > skdc_entry = talloc_get_type(s->ctx, struct samba_kdc_entry); > >- h->ctx = skdc_entry; >- h->free_entry = samba_kdc_free_hdb_entry; >+ h->context = skdc_entry; > > talloc_set_destructor(skdc_entry, > samba_kdc_hdb_entry_destructor); > } > >- return sdb_entry_to_hdb_entry(context, &s->entry, &h->entry); >+ return sdb_entry_to_hdb_entry(context, &s->entry, h); > } >diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c >index 9356979dd7dc..6325627318ea 100644 >--- a/source4/kdc/wdc-samba4.c >+++ b/source4/kdc/wdc-samba4.c >@@ -37,8 +37,9 @@ > * For PKINIT we also get pk_reply_key and can add PAC_CREDENTIAL_INFO. > */ > static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, >- struct hdb_entry_ex *client, >- struct hdb_entry_ex *server, >+ krb5_kdc_configuration *config, >+ hdb_entry *client, >+ hdb_entry *server, > const krb5_keyblock *pk_reply_key, > uint64_t pac_attributes, > krb5_pac *pac) >@@ -55,11 +56,11 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, > krb5_error_code ret; > NTSTATUS nt_status; > struct samba_kdc_entry *skdc_entry = >- talloc_get_type_abort(client->ctx, >+ talloc_get_type_abort(client->context, > struct samba_kdc_entry); > bool is_krbtgt; > >- mem_ctx = talloc_named(client->ctx, 0, "samba_get_pac context"); >+ mem_ctx = talloc_named(client->context, 0, "samba_get_pac context"); > if (!mem_ctx) { > return ENOMEM; > } >@@ -68,7 +69,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, > cred_ndr_ptr = &cred_ndr; > } > >- is_krbtgt = krb5_principal_is_krbtgt(context, server->entry.principal); >+ is_krbtgt = krb5_principal_is_krbtgt(context, server->principal); > > nt_status = samba_kdc_get_pac_blobs(mem_ctx, skdc_entry, > &logon_blob, >@@ -112,17 +113,17 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, > > static krb5_error_code samba_wdc_reget_pac2(krb5_context context, > const krb5_principal delegated_proxy_principal, >- struct hdb_entry_ex *client, >- struct hdb_entry_ex *server, >- struct hdb_entry_ex *krbtgt, >+ hdb_entry *client, >+ hdb_entry *server, >+ hdb_entry *krbtgt, > krb5_pac *pac, > krb5_cksumtype ctype) > { > struct samba_kdc_entry *server_skdc_entry = >- talloc_get_type_abort(server->ctx, >+ talloc_get_type_abort(server->context, > struct samba_kdc_entry); > struct samba_kdc_entry *krbtgt_skdc_entry = >- talloc_get_type_abort(krbtgt->ctx, >+ talloc_get_type_abort(krbtgt->context, > struct samba_kdc_entry); > TALLOC_CTX *mem_ctx = talloc_named(server_skdc_entry, > 0, >@@ -157,7 +158,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, > if (client != NULL) { > struct samba_kdc_entry *client_skdc_entry = NULL; > >- client_skdc_entry = talloc_get_type_abort(client->ctx, >+ client_skdc_entry = talloc_get_type_abort(client->context, > struct samba_kdc_entry); > > /* >@@ -214,7 +215,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, > return ret; > } > } >- ret = hdb_enctype2key(context, &krbtgt->entry, NULL, etype, &key); >+ ret = hdb_enctype2key(context, krbtgt, NULL, etype, &key); > if (ret != 0) { > talloc_free(mem_ctx); > return ret; >@@ -241,7 +242,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, > > nt_status = samba_kdc_update_delegation_info_blob(mem_ctx, > context, *pac, >- server->entry.principal, >+ server->principal, > delegated_proxy_principal, > deleg_blob); > if (!NT_STATUS_IS_OK(nt_status)) { >@@ -261,7 +262,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, > return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; > } > >- client_skdc_entry = talloc_get_type_abort(client->ctx, >+ client_skdc_entry = talloc_get_type_abort(client->context, > struct samba_kdc_entry); > > nt_status = samba_kdc_get_pac_blobs(mem_ctx, client_skdc_entry, >@@ -485,7 +486,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, > goto out; > } > >- is_krbtgt = krb5_principal_is_krbtgt(context, server->entry.principal); >+ is_krbtgt = krb5_principal_is_krbtgt(context, server->principal); > > if (!is_untrusted && !is_krbtgt) { > /* >@@ -663,19 +664,20 @@ out: > /* Resign (and reform, including possibly new groups) a PAC */ > > static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, >+ krb5_kdc_configuration *config, > const krb5_principal client_principal, > const krb5_principal delegated_proxy_principal, >- struct hdb_entry_ex *client, >- struct hdb_entry_ex *server, >- struct hdb_entry_ex *krbtgt, >+ hdb_entry *client, >+ hdb_entry *server, >+ hdb_entry *krbtgt, > krb5_pac *pac) > { > struct samba_kdc_entry *krbtgt_skdc_entry = >- talloc_get_type_abort(krbtgt->ctx, >+ talloc_get_type_abort(krbtgt->context, > struct samba_kdc_entry); > krb5_error_code ret; > krb5_cksumtype ctype = CKSUMTYPE_NONE; >- struct hdb_entry_ex signing_krbtgt_hdb; >+ hdb_entry signing_krbtgt_hdb; > > if (delegated_proxy_principal) { > uint16_t rodc_id; >@@ -726,7 +728,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, > * different KDC than the one that issued the header > * ticket. > */ >- if (rodc_id != krbtgt->entry.kvno >> 16) { >+ if (rodc_id != krbtgt->kvno >> 16) { > struct sdb_entry_ex signing_krbtgt_sdb; > > /* >@@ -745,7 +747,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, > */ > ret = samba_kdc_fetch(context, > krbtgt_skdc_entry->kdc_db_ctx, >- krbtgt->entry.principal, >+ krbtgt->principal, > SDB_F_GET_KRBTGT | SDB_F_CANON, > 0, > &signing_krbtgt_sdb); >@@ -779,7 +781,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, > ctype); > > if (krbtgt == &signing_krbtgt_hdb) { >- hdb_free_entry(context, &signing_krbtgt_hdb); >+ hdb_free_entry(context, config->db[0], &signing_krbtgt_hdb); > } > > return ret; >@@ -844,9 +846,9 @@ static krb5_error_code samba_wdc_check_client_access(void *priv, > char *workstation; > NTSTATUS nt_status; > >- kdc_entry = talloc_get_type(r->client->ctx, struct samba_kdc_entry); >- password_change = (r->server && r->server->entry.flags.change_pw); >- workstation = get_netbios_name((TALLOC_CTX *)r->client->ctx, >+ kdc_entry = talloc_get_type(r->client->context, struct samba_kdc_entry); >+ password_change = (r->server && r->server->flags.change_pw); >+ workstation = get_netbios_name((TALLOC_CTX *)r->client->context, > r->req.req_body.addresses); > > nt_status = samba_kdc_check_client_access(kdc_entry, >@@ -905,7 +907,7 @@ static krb5_error_code samba_wdc_finalize_reply(void *priv, > struct samba_kdc_entry *server_kdc_entry; > uint32_t supported_enctypes; > >- server_kdc_entry = talloc_get_type(r->server->ctx, struct samba_kdc_entry); >+ server_kdc_entry = talloc_get_type(r->server->context, struct samba_kdc_entry); > > /* > * If the canonicalize flag is set, add PA-SUPPORTED-ENCTYPES padata >@@ -960,7 +962,7 @@ static krb5_error_code samba_wdc_referral_policy(void *priv, > } > > struct krb5plugin_kdc_ftable kdc_plugin_table = { >- .minor_version = KRB5_PLUGIN_KDC_VERSION_9, >+ .minor_version = KRB5_PLUGIN_KDC_VERSION_10, > .init = samba_wdc_plugin_init, > .fini = samba_wdc_plugin_fini, > .pac_verify = samba_wdc_reget_pac, >diff --git a/third_party/heimdal_build/wscript_build b/third_party/heimdal_build/wscript_build >index 3ea1fc93653f..a395430c28fb 100644 >--- a/third_party/heimdal_build/wscript_build >+++ b/third_party/heimdal_build/wscript_build >@@ -433,10 +433,7 @@ if not bld.CONFIG_SET("USING_SYSTEM_HEIMNTLM"): > if not bld.CONFIG_SET("USING_SYSTEM_HDB"): > HEIMDAL_ASN1('HEIMDAL_HDB_ASN1', 'lib/hdb/hdb.asn1', > directory='lib/asn1', >- options="--sequence=HDB-extensions \ >- --sequence=HDB-Ext-KeyRotation \ >- --sequence=HDB-Ext-KeySet \ >- --sequence=Keys", >+ option_file="lib/hdb/hdb.opt", > template=False, > includes='../heimdal/lib/asn1') > >-- >2.25.1 > > >From 7284183c5959540dc4f33b56dc0be55fbb46c63d Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Wed, 23 Feb 2022 09:53:27 +1300 >Subject: [PATCH 20/22] s4:kdc: Adapt to removal of publicly accessible request > structure members > >We now have to use the accessor functions instead. > >This is an adaptation to Heimdal: > >commit ec24edf7005c340018450a202d27ca75fcf322d4 >Author: Luke Howard <lukeh@padl.com> >Date: Thu Jan 20 09:15:24 2022 +1100 > > kdc: add accessor functions for KDC request structure > > Add accessor functions for use by Samba and other plugin developers. > Documentation is in kdc/kdc-accessors.h. > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 9399a15fabb5a1b8470b1069a098132e2fdb7f0f) >--- > source4/kdc/wdc-samba4.c | 40 ++++++++++++++++++---------------------- > 1 file changed, 18 insertions(+), 22 deletions(-) > >diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c >index 6325627318ea..dfca27175a21 100644 >--- a/source4/kdc/wdc-samba4.c >+++ b/source4/kdc/wdc-samba4.c >@@ -846,13 +846,14 @@ static krb5_error_code samba_wdc_check_client_access(void *priv, > char *workstation; > NTSTATUS nt_status; > >- kdc_entry = talloc_get_type(r->client->context, struct samba_kdc_entry); >- password_change = (r->server && r->server->flags.change_pw); >- workstation = get_netbios_name((TALLOC_CTX *)r->client->context, >- r->req.req_body.addresses); >+ >+ kdc_entry = talloc_get_type(kdc_request_get_client(r)->context, struct samba_kdc_entry); >+ password_change = (kdc_request_get_server(r) && kdc_request_get_server(r)->flags.change_pw); >+ workstation = get_netbios_name((TALLOC_CTX *)kdc_request_get_client(r)->context, >+ kdc_request_get_req(r)->req_body.addresses); > > nt_status = samba_kdc_check_client_access(kdc_entry, >- r->cname, >+ kdc_request_get_cname((kdc_request_t)r), > workstation, > password_change); > >@@ -861,12 +862,12 @@ static krb5_error_code samba_wdc_check_client_access(void *priv, > return ENOMEM; > } > >- if (r->rep.padata) { >+ if (kdc_request_get_rep(r)->padata) { > int ret; > krb5_data kd; > > samba_kdc_build_edata_reply(nt_status, &kd); >- ret = krb5_padata_add(r->context, r->rep.padata, >+ ret = krb5_padata_add(kdc_request_get_context((kdc_request_t)r), kdc_request_get_rep(r)->padata, > KRB5_PADATA_PW_SALT, > kd.data, kd.length); > if (ret != 0) { >@@ -907,37 +908,32 @@ static krb5_error_code samba_wdc_finalize_reply(void *priv, > struct samba_kdc_entry *server_kdc_entry; > uint32_t supported_enctypes; > >- server_kdc_entry = talloc_get_type(r->server->context, struct samba_kdc_entry); >+ server_kdc_entry = talloc_get_type(kdc_request_get_server(r)->context, struct samba_kdc_entry); > > /* > * If the canonicalize flag is set, add PA-SUPPORTED-ENCTYPES padata > * type to indicate what encryption types the server supports. > */ > supported_enctypes = server_kdc_entry->supported_enctypes; >- if (r->req.req_body.kdc_options.canonicalize && supported_enctypes != 0) { >+ if (kdc_request_get_req(r)->req_body.kdc_options.canonicalize && supported_enctypes != 0) { > krb5_error_code ret; >- krb5_data kd; > >- if (r->ek.encrypted_pa_data == NULL) { >- r->ek.encrypted_pa_data = calloc(1, sizeof *(r->ek.encrypted_pa_data)); >- if (r->ek.encrypted_pa_data == NULL) { >- return ENOMEM; >- } >- } >+ PA_DATA md; > >- ret = samba_kdc_build_supported_etypes(supported_enctypes, &kd); >+ ret = samba_kdc_build_supported_etypes(supported_enctypes, &md.padata_value); > if (ret != 0) { > return ret; > } >- ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data, >- KRB5_PADATA_SUPPORTED_ETYPES, >- kd.data, kd.length); >+ >+ md.padata_type = KRB5_PADATA_SUPPORTED_ETYPES; >+ >+ ret = kdc_request_add_encrypted_padata(r, &md); > if (ret != 0) { > /* > * So we do not leak the allocated > * memory on kd in the error case > */ >- krb5_data_free(&kd); >+ krb5_data_free(&md.padata_value); > } > } > >@@ -958,7 +954,7 @@ static void samba_wdc_plugin_fini(void *ptr) > static krb5_error_code samba_wdc_referral_policy(void *priv, > astgs_request_t r) > { >- return r->error_code; >+ return kdc_request_get_error_code((kdc_request_t)r); > } > > struct krb5plugin_kdc_ftable kdc_plugin_table = { >-- >2.25.1 > > >From ddc5452be081ab5546e56b93b97ed3d8d1a6c117 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Wed, 2 Mar 2022 10:00:17 +1300 >Subject: [PATCH 21/22] s4-kdc: Adapt to move from HDB auditing to KDC auditing > constants > >This is to adapt to: > > commit 6530021f09a5cab631be19a1b5898a0ba6b32f16 > Author: Luke Howard <lukeh@padl.com> > Date: Thu Jan 13 14:37:29 2022 +1100 > > kdc: move auth event definitions into KDC header > > Move KDC auth event macro definitions out of hdb.h and into a new KDC header, > kdc-audit.h. > >NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz> >(cherry picked from commit c9b0b4bfc4e2e0b08b21f39bf56fd5395d66d66f) >--- > source4/kdc/hdb-samba4.c | 33 +++++++++++++++++---------------- > source4/kdc/wscript_build | 2 +- > 2 files changed, 18 insertions(+), 17 deletions(-) > >diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c >index 90cd3a78de8f..c2f55329cec6 100644 >--- a/source4/kdc/hdb-samba4.c >+++ b/source4/kdc/hdb-samba4.c >@@ -46,6 +46,7 @@ > #include "librpc/gen_ndr/ndr_winbind_c.h" > #include "lib/messaging/irpc.h" > #include "hdb.h" >+#include <kdc-audit.h> > > static krb5_error_code hdb_samba4_open(krb5_context context, HDB *db, int flags, mode_t mode) > { >@@ -545,7 +546,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > > size_t sa_socklen = 0; > >- hdb_auth_status_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_AUTH_EVENT); >+ hdb_auth_status_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_AUTH_EVENT); > if (hdb_auth_status_obj == NULL) { > /* No status code found, so just return. */ > return 0; >@@ -558,15 +559,15 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > pa_type = heim_string_get_utf8(pa_type_obj); > } > >- auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_PKINIT_CLIENT_CERT); >+ auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_PKINIT_CLIENT_CERT); > if (auth_details_obj != NULL) { > auth_details = heim_string_get_utf8(auth_details_obj); > } else { >- auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_GSS_INITIATOR); >+ auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_GSS_INITIATOR); > if (auth_details_obj != NULL) { > auth_details = heim_string_get_utf8(auth_details_obj); > } else { >- heim_object_t etype_obj = heim_audit_getkv((heim_svc_req_desc)r, HDB_REQUEST_KV_PA_ETYPE); >+ heim_object_t etype_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_PA_ETYPE); > if (etype_obj != NULL) { > int etype = heim_number_get_int(etype_obj); > >@@ -610,7 +611,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > } > > switch (hdb_auth_status) { >- case HDB_AUTH_EVENT_CLIENT_AUTHORIZED: >+ case KDC_AUTH_EVENT_CLIENT_AUTHORIZED: > { > TALLOC_CTX *frame = talloc_stackframe(); > struct samba_kdc_entry *p = talloc_get_type(entry->context, >@@ -630,11 +631,11 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > talloc_free(frame); > break; > } >- case HDB_AUTH_EVENT_CLIENT_LOCKED_OUT: >- case HDB_AUTH_EVENT_VALIDATED_LONG_TERM_KEY: >- case HDB_AUTH_EVENT_WRONG_LONG_TERM_KEY: >- case HDB_AUTH_EVENT_PREAUTH_SUCCEEDED: >- case HDB_AUTH_EVENT_PREAUTH_FAILED: >+ case KDC_AUTH_EVENT_CLIENT_LOCKED_OUT: >+ case KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY: >+ case KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY: >+ case KDC_AUTH_EVENT_PREAUTH_SUCCEEDED: >+ case KDC_AUTH_EVENT_PREAUTH_FAILED: > { > TALLOC_CTX *frame = talloc_stackframe(); > struct samba_kdc_entry *p = talloc_get_type(entry->context, >@@ -673,7 +674,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > } > ui.auth_description = auth_description; > >- if (hdb_auth_status == HDB_AUTH_EVENT_WRONG_LONG_TERM_KEY) { >+ if (hdb_auth_status == KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY) { > authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn); > status = NT_STATUS_WRONG_PASSWORD; > /* >@@ -684,13 +685,13 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > if (kdc_db_ctx->rodc) { > send_bad_password_netlogon(frame, kdc_db_ctx, &ui); > } >- } else if (hdb_auth_status == HDB_AUTH_EVENT_CLIENT_LOCKED_OUT) { >+ } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_LOCKED_OUT) { > status = NT_STATUS_ACCOUNT_LOCKED_OUT; >- } else if (hdb_auth_status == HDB_AUTH_EVENT_VALIDATED_LONG_TERM_KEY) { >+ } else if (hdb_auth_status == KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY) { > status = NT_STATUS_OK; >- } else if (hdb_auth_status == HDB_AUTH_EVENT_PREAUTH_SUCCEEDED) { >+ } else if (hdb_auth_status == KDC_AUTH_EVENT_PREAUTH_SUCCEEDED) { > status = NT_STATUS_OK; >- } else if (hdb_auth_status == HDB_AUTH_EVENT_PREAUTH_FAILED) { >+ } else if (hdb_auth_status == KDC_AUTH_EVENT_PREAUTH_FAILED) { > if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) { > status = NT_STATUS_PKINIT_FAILURE; > } else { >@@ -711,7 +712,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > TALLOC_FREE(frame); > break; > } >- case HDB_AUTH_EVENT_CLIENT_UNKNOWN: >+ case KDC_AUTH_EVENT_CLIENT_UNKNOWN: > { > struct tsocket_address *remote_host; > int ret; >diff --git a/source4/kdc/wscript_build b/source4/kdc/wscript_build >index 95cd88bdfb6e..26a68e9c37c4 100644 >--- a/source4/kdc/wscript_build >+++ b/source4/kdc/wscript_build >@@ -48,7 +48,7 @@ if bld.CONFIG_GET('SAMBA_USES_MITKDC'): > > bld.SAMBA_LIBRARY('HDB_SAMBA4', > source='hdb-samba4.c hdb-samba4-plugin.c', >- deps='ldb auth4_sam common_auth samba-credentials hdb db-glue samba-hostconfig com_err sdb_hdb RPC_NDR_WINBIND', >+ deps='ldb auth4_sam common_auth samba-credentials hdb kdc db-glue samba-hostconfig com_err sdb_hdb RPC_NDR_WINBIND', > includes=kdc_include, > private_library=True, > enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL') >-- >2.25.1 > > >From 4fcc8998882586ff6b338afc803050d6d6b7d961 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 2 Mar 2022 10:10:08 +1300 >Subject: [PATCH 22/22] s4:kdc: hdb_samba4_audit() is only called once per > request > >So we need to restructure the logic a bit. > >NOTE: This commit finally works again! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> > >Autobuild-User(master): Joseph Sutton <jsutton@samba.org> >Autobuild-Date(master): Tue Mar 1 23:28:22 UTC 2022 on sn-devel-184 > >(cherry picked from commit 791be84c3eecb95e03611458e2305bae272ba267) >--- > source4/kdc/hdb-samba4.c | 26 +++++++++++++++----------- > 1 file changed, 15 insertions(+), 11 deletions(-) > >diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c >index c2f55329cec6..6e87345e2c31 100644 >--- a/source4/kdc/hdb-samba4.c >+++ b/source4/kdc/hdb-samba4.c >@@ -629,13 +629,9 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > reset_bad_password_netlogon(frame, kdc_db_ctx, send_to_sam); > } > talloc_free(frame); >- break; > } >- case KDC_AUTH_EVENT_CLIENT_LOCKED_OUT: >- case KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY: >- case KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY: >- case KDC_AUTH_EVENT_PREAUTH_SUCCEEDED: >- case KDC_AUTH_EVENT_PREAUTH_FAILED: >+ FALL_THROUGH; >+ default: > { > TALLOC_CTX *frame = talloc_stackframe(); > struct samba_kdc_entry *p = talloc_get_type(entry->context, >@@ -674,7 +670,11 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > } > ui.auth_description = auth_description; > >- if (hdb_auth_status == KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY) { >+ if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_AUTHORIZED) { >+ status = NT_STATUS_OK; >+ } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_TIME_SKEW) { >+ status = NT_STATUS_TIME_DIFFERENCE_AT_DC; >+ } else if (hdb_auth_status == KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY) { > authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn); > status = NT_STATUS_WRONG_PASSWORD; > /* >@@ -687,10 +687,12 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > } > } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_LOCKED_OUT) { > status = NT_STATUS_ACCOUNT_LOCKED_OUT; >- } else if (hdb_auth_status == KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY) { >- status = NT_STATUS_OK; >- } else if (hdb_auth_status == KDC_AUTH_EVENT_PREAUTH_SUCCEEDED) { >- status = NT_STATUS_OK; >+ } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED) { >+ if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) { >+ status = NT_STATUS_PKINIT_NAME_MISMATCH; >+ } else { >+ status = NT_STATUS_ACCOUNT_RESTRICTION; >+ } > } else if (hdb_auth_status == KDC_AUTH_EVENT_PREAUTH_FAILED) { > if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) { > status = NT_STATUS_PKINIT_FAILURE; >@@ -698,6 +700,8 @@ static krb5_error_code hdb_samba4_audit(krb5_context context, > status = NT_STATUS_GENERIC_COMMAND_FAILED; > } > } else { >+ DBG_ERR("Unhandled hdb_auth_status=%d => INTERNAL_ERROR\n", >+ hdb_auth_status); > status = NT_STATUS_INTERNAL_ERROR; > } > >-- >2.25.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
abartlet
:
review+
Actions:
View
Attachments on
bug 14995
: 17181