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 @@ >-[](https://travis-ci.org/heimdal/heimdal#) >+[](https://github.com/heimdal/heimdal/actions?query=workflow%3Alinux) >+[](https://github.com/heimdal/heimdal/actions?query=workflow%3Aosx) >+[](https://github.com/heimdal/heimdal/actions?query=workflow%3Awindows) > [](https://ci.appveyor.com/project/heimdal/heimdal/branch/master) > [](https://coveralls.io/github/heimdal/heimdal?branch=master) > >@@ -30,5 +32,8 @@ respectively to subscribe. > Build Status > ============ > >-[](https://travis-ci.org/heimdal/heimdal#) >+[](https://github.com/heimdal/heimdal/actions?query=workflow%3Alinux) >+[](https://github.com/heimdal/heimdal/actions?query=workflow%3Aosx) >+[](https://github.com/heimdal/heimdal/actions?query=workflow%3Awindows) > [](https://ci.appveyor.com/project/heimdal/heimdal/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;