summaryrefslogtreecommitdiff
path: root/third_party/heimdal/lib
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/lib')
-rw-r--r--third_party/heimdal/lib/asn1/asn1_compile.15
-rw-r--r--third_party/heimdal/lib/asn1/gen_copy.c2
-rw-r--r--third_party/heimdal/lib/asn1/gen_free.c2
-rw-r--r--third_party/heimdal/lib/asn1/main.c8
-rw-r--r--third_party/heimdal/lib/asn1/template.c4
-rw-r--r--third_party/heimdal/lib/base/heimbase.h30
-rw-r--r--third_party/heimdal/lib/base/heimbasepriv.h23
-rw-r--r--third_party/heimdal/lib/base/json.c864
-rw-r--r--third_party/heimdal/lib/base/log.c3
-rw-r--r--third_party/heimdal/lib/base/string.c5
-rw-r--r--third_party/heimdal/lib/base/test_base.c340
-rw-r--r--third_party/heimdal/lib/base/version-script.map2
-rw-r--r--third_party/heimdal/lib/gssapi/Makefile.am12
-rw-r--r--third_party/heimdal/lib/gssapi/gss-token.c6
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/8003.c2
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/init_sec_context.c2
-rw-r--r--third_party/heimdal/lib/gssapi/netlogon/crypto.c2
-rw-r--r--third_party/heimdal/lib/gssapi/ntlm/crypto.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/des.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/dh.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/dsa.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/engine.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-openssl.c4
-rw-r--r--third_party/heimdal/lib/hcrypto/evp.c10
-rw-r--r--third_party/heimdal/lib/hcrypto/hmac.c6
-rw-r--r--third_party/heimdal/lib/hcrypto/md2.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/passwd_dlg.c4
-rw-r--r--third_party/heimdal/lib/hcrypto/rand-fortuna.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/rc2.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/rsa.c4
-rw-r--r--third_party/heimdal/lib/hdb/Makefile.am4
-rw-r--r--third_party/heimdal/lib/hdb/common.c195
-rw-r--r--third_party/heimdal/lib/hdb/hdb-mdb.c2
-rw-r--r--third_party/heimdal/lib/hdb/hdb.asn12
-rw-r--r--third_party/heimdal/lib/hdb/hdb.opt4
-rw-r--r--third_party/heimdal/lib/hdb/keytab.c5
-rw-r--r--third_party/heimdal/lib/hx509/cert.c2
-rw-r--r--third_party/heimdal/lib/hx509/cms.c2
-rw-r--r--third_party/heimdal/lib/hx509/file.c2
-rw-r--r--third_party/heimdal/lib/hx509/hxtool.1207
-rw-r--r--third_party/heimdal/lib/hx509/hxtool.c68
-rw-r--r--third_party/heimdal/lib/hx509/req.c8
-rw-r--r--third_party/heimdal/lib/ipc/server.c46
-rw-r--r--third_party/heimdal/lib/kadm5/ad.c38
-rw-r--r--third_party/heimdal/lib/kadm5/common_glue.c15
-rw-r--r--third_party/heimdal/lib/kadm5/context_s.c10
-rw-r--r--third_party/heimdal/lib/kadm5/create_s.c8
-rw-r--r--third_party/heimdal/lib/kadm5/destroy_s.c12
-rw-r--r--third_party/heimdal/lib/kadm5/get_c.c2
-rw-r--r--third_party/heimdal/lib/kadm5/get_princs_c.c186
-rw-r--r--third_party/heimdal/lib/kadm5/get_princs_s.c124
-rw-r--r--third_party/heimdal/lib/kadm5/init_c.c52
-rw-r--r--third_party/heimdal/lib/kadm5/init_s.c15
-rw-r--r--third_party/heimdal/lib/kadm5/iprop.846
-rw-r--r--third_party/heimdal/lib/kadm5/ipropd_slave.c46
-rw-r--r--third_party/heimdal/lib/kadm5/libkadm5srv-exports.def2
-rw-r--r--third_party/heimdal/lib/kadm5/private.h2
-rw-r--r--third_party/heimdal/lib/kadm5/version-script-client.map5
-rw-r--r--third_party/heimdal/lib/kadm5/version-script.map2
-rw-r--r--third_party/heimdal/lib/kafs/kafs_locl.h1
-rw-r--r--third_party/heimdal/lib/kafs/rxkad_kdf.c2
-rw-r--r--third_party/heimdal/lib/krb5/Makefile.am1
-rw-r--r--third_party/heimdal/lib/krb5/NTMakefile12
-rw-r--r--third_party/heimdal/lib/krb5/aname_to_localname.c1
-rw-r--r--third_party/heimdal/lib/krb5/changepw.c2
-rw-r--r--third_party/heimdal/lib/krb5/context.c115
-rw-r--r--third_party/heimdal/lib/krb5/convert_creds.c3
-rw-r--r--third_party/heimdal/lib/krb5/kcm.c3
-rw-r--r--third_party/heimdal/lib/krb5/keytab.c3
-rw-r--r--third_party/heimdal/lib/krb5/krb5-v4compat.h139
-rw-r--r--third_party/heimdal/lib/krb5/pac.c5
-rw-r--r--third_party/heimdal/lib/krb5/pkinit.c12
-rw-r--r--third_party/heimdal/lib/krb5/send_to_kdc.c4
-rw-r--r--third_party/heimdal/lib/krb5/store.c2
-rw-r--r--third_party/heimdal/lib/libedit/config.h.in100
-rw-r--r--third_party/heimdal/lib/ntlm/digest.c2
-rw-r--r--third_party/heimdal/lib/ntlm/ntlm.c8
-rw-r--r--third_party/heimdal/lib/otp/otp_verify.c2
-rw-r--r--third_party/heimdal/lib/roken/Makefile.am2
-rw-r--r--third_party/heimdal/lib/roken/base32.c8
-rw-r--r--third_party/heimdal/lib/roken/dirent-test.c4
-rw-r--r--third_party/heimdal/lib/roken/fnmatch.c2
-rw-r--r--third_party/heimdal/lib/roken/getaddrinfo.c4
-rw-r--r--third_party/heimdal/lib/roken/getuserinfo.c2
-rw-r--r--third_party/heimdal/lib/roken/parse_units.c3
-rw-r--r--third_party/heimdal/lib/roken/parse_units.h4
-rw-r--r--third_party/heimdal/lib/roken/snprintf.c2
-rw-r--r--third_party/heimdal/lib/roken/strftime.c2
-rw-r--r--third_party/heimdal/lib/roken/strptime.c2
-rw-r--r--third_party/heimdal/lib/sl/slc-gram.y2
-rw-r--r--third_party/heimdal/lib/wind/utf8.c14
91 files changed, 2366 insertions, 570 deletions
diff --git a/third_party/heimdal/lib/asn1/asn1_compile.1 b/third_party/heimdal/lib/asn1/asn1_compile.1
index a7953df5fa1..9af27672c2a 100644
--- a/third_party/heimdal/lib/asn1/asn1_compile.1
+++ b/third_party/heimdal/lib/asn1/asn1_compile.1
@@ -330,6 +330,11 @@ to form the names of the files generated.
.It Fl Fl option-file=FILE
Take additional command-line options from
.Ar FILE .
+The options file must have one command-line option per-line, but
+leading whitespace is ignored, and lines that start with a hash
+symbol
+.Sq ( # )
+are comments and are ignored.
.It Fl Fl original-order
Attempt to preserve the original order of type definition in the
ASN.1 module.
diff --git a/third_party/heimdal/lib/asn1/gen_copy.c b/third_party/heimdal/lib/asn1/gen_copy.c
index bec6f8b059f..c6d420a2f16 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;
+ HEIM_FALLTHROUGH;
case TBoolean:
case TEnumerated :
fprintf(codefile, "*(%s) = *(%s);\n", to, from);
diff --git a/third_party/heimdal/lib/asn1/gen_free.c b/third_party/heimdal/lib/asn1/gen_free.c
index 0507d542180..53b7bfe7b90 100644
--- a/third_party/heimdal/lib/asn1/gen_free.c
+++ b/third_party/heimdal/lib/asn1/gen_free.c
@@ -56,7 +56,7 @@ free_type (const char *name, const Type *t, int preserve)
free_primitive ("heim_integer", name);
break;
}
- /* fallthrough; */
+ /* HEIM_FALLTHROUGH; */
case TBoolean:
case TEnumerated :
case TNull:
diff --git a/third_party/heimdal/lib/asn1/main.c b/third_party/heimdal/lib/asn1/main.c
index bcfdad62e2e..569b4782b4d 100644
--- a/third_party/heimdal/lib/asn1/main.c
+++ b/third_party/heimdal/lib/asn1/main.c
@@ -409,8 +409,16 @@ main(int argc, char **argv)
sz = 2;
while (fgets(buf, sizeof(buf), opt) != NULL) {
+ size_t buflen, ws;
+
buf[strcspn(buf, "\n\r")] = '\0';
+ buflen = strlen(buf);
+ if ((ws = strspn(buf, " \t")))
+ memmove(buf, buf + ws, buflen -= ws);
+ if (buf[0] == '\0' || buf[0] == '#')
+ continue;
+
if (len + 1 >= sz) {
arg = realloc(arg, (sz + (sz>>1) + 2) * sizeof(arg[0]));
if (arg == NULL) {
diff --git a/third_party/heimdal/lib/asn1/template.c b/third_party/heimdal/lib/asn1/template.c
index 7a19e7477e3..31eb66004ec 100644
--- a/third_party/heimdal/lib/asn1/template.c
+++ b/third_party/heimdal/lib/asn1/template.c
@@ -2549,7 +2549,9 @@ _asn1_print(const struct asn1_template *t,
}
default: break;
}
- if (nnames)
+ if (nnames &&
+ (t->tt & A1_OP_MASK) != A1_OP_TYPE_DECORATE_EXTERN &&
+ (t->tt & A1_OP_MASK) != A1_OP_TYPE_DECORATE)
r = rk_strpoolprintf(r, ",%s\"%s\":",
indents ? indents : "",
(const char *)(tnames++)->ptr);
diff --git a/third_party/heimdal/lib/base/heimbase.h b/third_party/heimdal/lib/base/heimbase.h
index 3706fc8710d..5d5c4e3b75e 100644
--- a/third_party/heimdal/lib/base/heimbase.h
+++ b/third_party/heimdal/lib/base/heimbase.h
@@ -134,6 +134,28 @@ typedef struct heim_config_binding heim_config_section;
* CF-like, JSON APIs
*/
+typedef enum heim_tid_enum {
+ HEIM_TID_NUMBER = 0,
+ HEIM_TID_NULL = 1,
+ HEIM_TID_BOOL = 2,
+ HEIM_TID_TAGGED_UNUSED2 = 3, /* reserved for tagged object types */
+ HEIM_TID_TAGGED_UNUSED3 = 4, /* reserved for tagged object types */
+ HEIM_TID_TAGGED_UNUSED4 = 5, /* reserved for tagged object types */
+ HEIM_TID_TAGGED_UNUSED5 = 6, /* reserved for tagged object types */
+ HEIM_TID_TAGGED_UNUSED6 = 7, /* reserved for tagged object types */
+ HEIM_TID_MEMORY = 128,
+ HEIM_TID_ARRAY = 129,
+ HEIM_TID_DICT = 130,
+ HEIM_TID_STRING = 131,
+ HEIM_TID_AUTORELEASE = 132,
+ HEIM_TID_ERROR = 133,
+ HEIM_TID_DATA = 134,
+ HEIM_TID_DB = 135,
+ HEIM_TID_PA_AUTH_MECH = 136,
+ HEIM_TID_PAC = 137,
+ HEIM_TID_USER = 255
+} heim_tid;
+
typedef void * heim_object_t;
typedef unsigned int heim_tid_t;
typedef heim_object_t heim_bool_t;
@@ -463,7 +485,13 @@ typedef enum heim_json_flags {
HEIM_JSON_F_STRICT = 31,
HEIM_JSON_F_CNULL2JSNULL = 32,
HEIM_JSON_F_TRY_DECODE_DATA = 64,
- HEIM_JSON_F_ONE_LINE = 128
+ HEIM_JSON_F_ONE_LINE = 128,
+ HEIM_JSON_F_ESCAPE_NON_ASCII = 256,
+ HEIM_JSON_F_NO_ESCAPE_NON_ASCII = 512,
+ /* The default is to indent with one tab */
+ HEIM_JSON_F_INDENT2 = 1024,
+ HEIM_JSON_F_INDENT4 = 2048,
+ HEIM_JSON_F_INDENT8 = 4096,
} heim_json_flags_t;
heim_object_t heim_json_create(const char *, size_t, heim_json_flags_t,
diff --git a/third_party/heimdal/lib/base/heimbasepriv.h b/third_party/heimdal/lib/base/heimbasepriv.h
index b9f63e56b6a..45ffb12d70e 100644
--- a/third_party/heimdal/lib/base/heimbasepriv.h
+++ b/third_party/heimdal/lib/base/heimbasepriv.h
@@ -47,29 +47,6 @@ typedef heim_string_t (*heim_type_description)(void *);
typedef struct heim_type_data *heim_type_t;
-enum {
- HEIM_TID_NUMBER = 0,
- HEIM_TID_NULL = 1,
- HEIM_TID_BOOL = 2,
- HEIM_TID_TAGGED_UNUSED2 = 3, /* reserved for tagged object types */
- HEIM_TID_TAGGED_UNUSED3 = 4, /* reserved for tagged object types */
- HEIM_TID_TAGGED_UNUSED4 = 5, /* reserved for tagged object types */
- HEIM_TID_TAGGED_UNUSED5 = 6, /* reserved for tagged object types */
- HEIM_TID_TAGGED_UNUSED6 = 7, /* reserved for tagged object types */
- HEIM_TID_MEMORY = 128,
- HEIM_TID_ARRAY = 129,
- HEIM_TID_DICT = 130,
- HEIM_TID_STRING = 131,
- HEIM_TID_AUTORELEASE = 132,
- HEIM_TID_ERROR = 133,
- HEIM_TID_DATA = 134,
- HEIM_TID_DB = 135,
- HEIM_TID_PA_AUTH_MECH = 136,
- HEIM_TID_PAC = 137,
- HEIM_TID_USER = 255
-
-};
-
struct heim_type_data {
heim_tid_t tid;
const char *name;
diff --git a/third_party/heimdal/lib/base/json.c b/third_party/heimdal/lib/base/json.c
index 2ef371b975e..c7ef0658850 100644
--- a/third_party/heimdal/lib/base/json.c
+++ b/third_party/heimdal/lib/base/json.c
@@ -37,10 +37,12 @@
#include <ctype.h>
#include <base64.h>
+#ifndef WIN32
+#include <langinfo.h>
+#endif
+
static heim_base_once_t heim_json_once = HEIM_BASE_ONCE_INIT;
static heim_string_t heim_tid_data_uuid_key = NULL;
-static const char base64_chars[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static void
json_init_once(void *arg)
@@ -66,7 +68,7 @@ struct heim_strbuf {
};
static int
-base2json(heim_object_t, struct twojson *);
+base2json(heim_object_t, struct twojson *, int);
static void
indent(struct twojson *j)
@@ -74,8 +76,18 @@ indent(struct twojson *j)
size_t i = j->indent;
if (j->flags & HEIM_JSON_F_ONE_LINE)
return;
- while (i--)
- j->out(j->ctx, "\t");
+ if (j->flags & HEIM_JSON_F_INDENT2)
+ while (i--)
+ j->out(j->ctx, " ");
+ else if (j->flags & HEIM_JSON_F_INDENT4)
+ while (i--)
+ j->out(j->ctx, " ");
+ else if (j->flags & HEIM_JSON_F_INDENT8)
+ while (i--)
+ j->out(j->ctx, " ");
+ else
+ while (i--)
+ j->out(j->ctx, "\t");
}
static void
@@ -90,7 +102,7 @@ array2json(heim_object_t value, void *ctx, int *stop)
j->out(j->ctx, NULL); /* eat previous '\n' if possible */
j->out(j->ctx, ",\n");
}
- j->ret = base2json(value, j);
+ j->ret = base2json(value, j, 0);
}
static void
@@ -105,19 +117,77 @@ dict2json(heim_object_t key, heim_object_t value, void *ctx)
j->out(j->ctx, NULL); /* eat previous '\n' if possible */
j->out(j->ctx, ",\n");
}
- j->ret = base2json(key, j);
- if (j->ret)
- return;
- j->out(j->ctx, " : \n");
- j->indent++;
- j->ret = base2json(value, j);
+ j->ret = base2json(key, j, 0);
if (j->ret)
return;
- j->indent--;
+ switch (heim_get_tid(value)) {
+ case HEIM_TID_ARRAY:
+ case HEIM_TID_DICT:
+ case HEIM_TID_DATA:
+ j->out(j->ctx, ":\n");
+ j->indent++;
+ j->ret = base2json(value, j, 0);
+ if (j->ret)
+ return;
+ j->indent--;
+ break;
+ default:
+ j->out(j->ctx, ": ");
+ j->ret = base2json(value, j, 1);
+ break;
+ }
+}
+
+#ifndef WIN32
+static void
+init_is_utf8(void *ptr)
+{
+ *(int *)ptr = strcasecmp("utf-8", nl_langinfo(CODESET)) == 0;
+}
+#endif
+
+int
+heim_locale_is_utf8(void)
+{
+#ifdef WIN32
+ return 0; /* XXX Implement */
+#else
+ static int locale_is_utf8 = -1;
+ static heim_base_once_t once = HEIM_BASE_ONCE_INIT;
+
+ heim_base_once_f(&once, &locale_is_utf8, init_is_utf8);
+ return locale_is_utf8;
+#endif
+}
+
+static void
+out_escaped_bmp(struct twojson *j, const unsigned char *p, int nbytes)
+{
+ unsigned char e[sizeof("\\u0000")];
+ unsigned codepoint;
+
+ if (nbytes == 2)
+ codepoint = ((p[0] & 0x1f) << 6) | (p[1] & 0x3f);
+ else if (nbytes == 3)
+ codepoint = ((p[0] & 0x0f) << 12) | ((p[1] & 0x3f) << 6) | (p[2] & 0x3f);
+ else
+ abort();
+ e[0] = '\\';
+ e[1] = 'u';
+ e[2] = codepoint >> 12;
+ e[2] += (e[2] < 10) ? '0' : ('A' - 10);
+ e[3] = (codepoint >> 8) & 0x0f;
+ e[3] += (e[3] < 10) ? '0' : ('A' - 10);
+ e[4] = (codepoint >> 4) & 0x0f;
+ e[4] += (e[4] < 10) ? '0' : ('A' - 10);
+ e[5] = codepoint & 0x0f;
+ e[5] += (e[5] < 10) ? '0' : ('A' - 10);
+ e[6] = '\0';
+ j->out(j->ctx, (char *)e);
}
static int
-base2json(heim_object_t obj, struct twojson *j)
+base2json(heim_object_t obj, struct twojson *j, int skip_indent)
{
heim_tid_t type;
int first = 0;
@@ -166,12 +236,186 @@ base2json(heim_object_t obj, struct twojson *j)
j->first = first;
break;
- case HEIM_TID_STRING:
- indent(j);
+ case HEIM_TID_STRING: {
+ const unsigned char *s = (const unsigned char *)heim_string_get_utf8(obj);
+ const unsigned char *p;
+ unsigned int c, cp, ctop, cbot;
+ char e[sizeof("\\u0123\\u3210")];
+ int good;
+ size_t i;
+
+ if (!skip_indent)
+ indent(j);
j->out(j->ctx, "\"");
- j->out(j->ctx, heim_string_get_utf8(obj));
+ for (p = s; (c = *p); p++) {
+ switch (c) {
+ /* ASCII control characters w/ C-like escapes */
+ case '\b': j->out(j->ctx, "\\b"); continue;
+ case '\f': j->out(j->ctx, "\\f"); continue;
+ case '\n': j->out(j->ctx, "\\n"); continue;
+ case '\r': j->out(j->ctx, "\\r"); continue;
+ case '\t': j->out(j->ctx, "\\t"); continue;
+ /* Other must-escape non-control ASCII characters */
+ case '"': j->out(j->ctx, "\\\""); continue;
+ case '\\': j->out(j->ctx, "\\\\"); continue;
+ default: break;
+ }
+
+ /*
+ * JSON string encoding is... complex.
+ *
+ * Invalid UTF-8 w/ HEIM_JSON_F_STRICT_STRINGS set -> return 1
+ *
+ * Invalid UTF-8 w/o HEIM_JSON_F_STRICT_STRINGS set -> pass
+ * through, a sort of Heimdal WTF-8, but not _the_ WTF-8.
+ */
+ if (c < 0x20) {
+ /* ASCII control character w/o C-like escape */
+ e[0] = '\\';
+ e[1] = 'u';
+ e[2] = '0';
+ e[3] = '0';
+ e[4] = "0123456789ABCDEF"[c>>4];
+ e[5] = "0123456789ABCDEF"[c & 0x0f];
+ e[6] = '\0';
+ j->out(j->ctx, e);
+ continue;
+ }
+ if (c < 0x80) {
+ /* ASCII */
+ e[0] = c;
+ e[1] = '\0';
+ j->out(j->ctx, e);
+ continue;
+ }
+ if ((c & 0xc0) == 0x80) {
+ /* UTF-8 bare non-leading byte */
+ if (!(j->flags & HEIM_JSON_F_STRICT_STRINGS)) {
+ e[0] = c;
+ e[1] = '\0';
+ j->out(j->ctx, e);
+ continue;
+ }
+ return 1;
+ }
+ if ((c & 0xe0) == 0xc0) {
+ /* UTF-8 leading byte of two-byte sequence */
+ good = 1;
+ for (i = 1; i < 2 && good && p[i]; i++) {
+ if ((p[i] & 0xc0) != 0x80)
+ good = 0;
+ }
+ if (i != 2)
+ good = 0;
+ if (!good && !(j->flags & HEIM_JSON_F_STRICT_STRINGS)) {
+ e[0] = c;
+ e[1] = '\0';
+ j->out(j->ctx, e);
+ continue;
+ } else if (!good) {
+ return 1;
+ }
+ if (j->flags & HEIM_JSON_F_ESCAPE_NON_ASCII) {
+ out_escaped_bmp(j, p, 2);
+ p += 1;
+ continue;
+ }
+ e[0] = c;
+ e[1] = p[1];
+ e[2] = '\0';
+ j->out(j->ctx, e);
+ p += 1;
+ continue;
+ }
+ if ((c & 0xf0) == 0xe0) {
+ /* UTF-8 leading byte of three-byte sequence */
+ good = 1;
+ for (i = 1; i < 3 && good && p[i]; i++) {
+ if ((p[i] & 0xc0) != 0x80)
+ good = 0;
+ }
+ if (i != 3)
+ good = 0;
+ if (!good && !(j->flags & HEIM_JSON_F_STRICT_STRINGS)) {
+ e[0] = c;
+ e[1] = '\0';
+ j->out(j->ctx, e);
+ continue;
+ } else if (!good) {
+ return 1;
+ }
+ if (j->flags & HEIM_JSON_F_ESCAPE_NON_ASCII) {
+ out_escaped_bmp(j, p, 3);
+ p += 2;
+ continue;
+ }
+ e[0] = c;
+ e[1] = p[1];
+ e[2] = p[2];
+ e[3] = '\0';
+ j->out(j->ctx, e);
+ p += 2;
+ continue;
+ }
+
+ if (c > 0xf7) {
+ /* Invalid UTF-8 leading byte */
+ if (!(j->flags & HEIM_JSON_F_STRICT_STRINGS)) {
+ e[0] = c;
+ e[1] = '\0';
+ j->out(j->ctx, e);
+ continue;
+ }
+ return 1;
+ }
+
+ /*
+ * A codepoint > U+FFFF, needs encoding a la UTF-16 surrogate
+ * pair because JSON takes after JS which uses UTF-16. Ugly.
+ */
+ cp = c & 0x7;
+ good = 1;
+ for (i = 1; i < 4 && good && p[i]; i++) {
+ if ((p[i] & 0xc0) == 0x80)
+ cp = (cp << 6) | (p[i] & 0x3f);
+ else
+ good = 0;
+ }
+ if (i != 4)
+ good = 0;
+ if (!good && !(j->flags & HEIM_JSON_F_STRICT_STRINGS)) {
+ e[0] = c;
+ e[1] = '\0';
+ j->out(j->ctx, e);
+ continue;
+ } else if (!good) {
+ return 1;
+ }
+ p += 3;
+
+ cp -= 0x10000;
+ ctop = 0xD800 + (cp >> 10);
+ cbot = 0xDC00 + (cp & 0x3ff);
+
+ e[0 ] = '\\';
+ e[1 ] = 'u';
+ e[2 ] = "0123456789ABCDEF"[(ctop ) >> 12];
+ e[3 ] = "0123456789ABCDEF"[(ctop & 0x0f00) >> 8];
+ e[4 ] = "0123456789ABCDEF"[(ctop & 0x00f0) >> 4];
+ e[5 ] = "0123456789ABCDEF"[(ctop & 0x000f) ];
+ e[6 ] = '\\';
+ e[7 ] = 'u';
+ e[8 ] = "0123456789ABCDEF"[(cbot ) >> 12];
+ e[9 ] = "0123456789ABCDEF"[(cbot & 0x0f00) >> 8];
+ e[10] = "0123456789ABCDEF"[(cbot & 0x00f0) >> 4];
+ e[11] = "0123456789ABCDEF"[(cbot & 0x000f) ];
+ e[12] = '\0';
+ j->out(j->ctx, e);
+ continue;
+ }
j->out(j->ctx, "\"");
break;
+ }
case HEIM_TID_DATA: {
heim_dict_t d;
@@ -220,7 +464,7 @@ base2json(heim_object_t obj, struct twojson *j)
heim_release(d);
return ENOMEM;
}
- ret = base2json(d, j);
+ ret = base2json(d, j, 0);
heim_release(d);
if (ret)
return ret;
@@ -230,17 +474,20 @@ base2json(heim_object_t obj, struct twojson *j)
case HEIM_TID_NUMBER: {
char num[32];
- indent(j);
+ if (!skip_indent)
+ indent(j);
snprintf(num, sizeof (num), "%d", heim_number_get_int(obj));
j->out(j->ctx, num);
break;
}
case HEIM_TID_NULL:
- indent(j);
+ if (!skip_indent)
+ indent(j);
j->out(j->ctx, "null");
break;
case HEIM_TID_BOOL:
- indent(j);
+ if (!skip_indent)
+ indent(j);
j->out(j->ctx, heim_bool_val(obj) ? "true" : "false");
break;
default:
@@ -255,9 +502,6 @@ heim_base2json(heim_object_t obj, void *ctx, heim_json_flags_t flags,
{
struct twojson j;
- if (flags & HEIM_JSON_F_STRICT_STRINGS)
- return ENOTSUP; /* Sorry, not yet! */
-
heim_base_once_f(&heim_json_once, NULL, json_init_once);
j.indent = 0;
@@ -267,7 +511,11 @@ heim_base2json(heim_object_t obj, void *ctx, heim_json_flags_t flags,
j.ret = 0;
j.first = 1;
- return base2json(obj, &j);
+ if (!(flags & HEIM_JSON_F_NO_ESCAPE_NON_ASCII) &&
+ !heim_locale_is_utf8())
+ j.flags |= HEIM_JSON_F_ESCAPE_NON_ASCII;
+
+ return base2json(obj, &j, 0);
}
@@ -342,93 +590,425 @@ parse_number(struct parse_ctx *ctx)
return heim_number_create(number * neg);
}
+/*
+ * Read 4 hex digits from ctx->p.
+ *
+ * If we don't have enough, rewind ctx->p and return -1 .
+ */
+static int
+unescape_unicode(struct parse_ctx *ctx)
+{
+ int c = 0;
+ int i;
+
+ for (i = 0; i < 4 && ctx->p < ctx->pend; i++, ctx->p++) {
+ if (*ctx->p >= '0' && *ctx->p <= '9') {
+ c = (c << 4) + (*ctx->p - '0');
+ } else if (*ctx->p >= 'A' && *ctx->p <= 'F') {
+ c = (c << 4) + (10 + *ctx->p - 'A');
+ } else if (*ctx->p >= 'a' && *ctx->p <= 'f') {
+ c = (c << 4) + (10 + *ctx->p - 'a');
+ } else {
+ ctx->p -= i;
+ return -1;
+ }
+ }
+ return c;
+}
+
+static int
+encode_utf8(struct parse_ctx *ctx, char **pp, char *pend, int c)
+{
+ char *p = *pp;
+
+ if (c < 0x80) {
+ /* ASCII */
+ if (p >= pend) return 0;
+ *(p++) = c;
+ *pp = p;
+ return 1;
+ }
+ if (c < 0x800) {
+ /* 2 code unit UTF-8 sequence */
+ if (p >= pend) return 0;
+ *(p++) = 0xc0 | ((c >> 6) );
+ if (p == pend) return 0;
+ *(p++) = 0x80 | ((c ) & 0x3f);
+ *pp = p;
+ return 1;
+ }
+ if (c < 0x10000) {
+ /* 3 code unit UTF-8 sequence */
+ if (p >= pend) return 0;
+ *(p++) = 0xe0 | ((c >> 12) );
+ if (p == pend) return 0;
+ *(p++) = 0x80 | ((c >> 6) & 0x3f);
+ if (p == pend) return 0;
+ *(p++) = 0x80 | ((c) & 0x3f);
+ *pp = p;
+ return 1;
+ }
+ if (c < 0x110000) {
+ /* 4 code unit UTF-8 sequence */
+ if (p >= pend) return 0;
+ *(p++) = 0xf0 | ((c >> 18) );
+ if (p == pend) return 0;
+ *(p++) = 0x80 | ((c >> 12) & 0x3f);
+ if (p == pend) return 0;
+ *(p++) = 0x80 | ((c >> 6) & 0x3f);
+ if (p == pend) return 0;
+ *(p++) = 0x80 | ((c) & 0x3f);
+ *pp = p;
+ return 1;
+ }
+ return 0;
+}
+
+static heim_string_t
+parse_string_error(struct parse_ctx *ctx,
+ char *freeme,
+ const char *msg)
+{
+ free(freeme);
+ ctx->error = heim_error_create(EINVAL, "%s at %lu", msg, ctx->lineno);
+ return NULL;
+}
+
static heim_string_t
parse_string(struct parse_ctx *ctx)
{
const uint8_t *start;
- int quote = 0;
-
- if (ctx->flags & HEIM_JSON_F_STRICT_STRINGS) {
- ctx->error = heim_error_create(EINVAL, "Strict JSON string encoding "
- "not yet supported");
- return NULL;
+ heim_object_t o;
+ size_t alloc_len = 0;
+ size_t need = 0;
+ char *p0, *p, *pend;
+ int strict = ctx->flags & HEIM_JSON_F_STRICT_STRINGS;
+ int binary = 0;
+
+ if (*ctx->p != '"')
+ return parse_string_error(ctx, NULL,
+ "Expected a JSON string but found "
+ "something else");
+ start = ++(ctx->p);
+
+ /* Estimate how many bytes we need to allocate */
+ p0 = p = pend = NULL;
+ for (need = 1; ctx->p < ctx->pend; ctx->p++) {
+ need++;
+ if (*ctx->p == '\\')
+ ctx->p++;
+ else if (*ctx->p == '"')
+ break;
}
+ if (ctx->p == ctx->pend)
+ return parse_string_error(ctx, NULL, "Unterminated JSON string");
- if (*ctx->p != '"') {
- ctx->error = heim_error_create(EINVAL, "Expected a JSON string but "
- "found something else at line %lu",
- ctx->lineno);
- return NULL;
+ ctx->p = start;
+ while (ctx->p < ctx->pend) {
+ const unsigned char *p_save;
+ int32_t ctop, cbot;
+
+ if (*ctx->p == '"') {
+ ctx->p++;
+ break;
+ }
+
+ /* Allocate or resize our output buffer if need be */
+ if (need || p == pend) {
+ char *tmp;
+
+ /*
+ * Work out how far p is into p0 to re-esablish p after
+ * the realloc()
+ */
+ size_t p0_to_p_len = (p - p0);
+
+ tmp = realloc(p0, alloc_len + need + 5 /* slop? */);
+
+ if (tmp == NULL) {
+ ctx->error = heim_error_create_enomem();
+ free(p0);
+ return NULL;
+ }
+ alloc_len += need + 5;
+
+ /*
+ * We have two pointers, p and p0, we want to keep them
+ * pointing into the same memory after the realloc()
+ */
+ p = tmp + p0_to_p_len;
+ p0 = tmp;
+ pend = p0 + alloc_len;
+
+ need = 0;
+ }
+
+ if (*ctx->p != '\\') {
+ unsigned char c = *ctx->p;
+
+ /*
+ * Not backslashed -> consume now.
+ *
+ * NOTE: All cases in this block must continue or return w/ error.
+ */
+
+ /* Check for unescaped ASCII control characters */
+ if (c == '\n') {
+ if (strict)
+ return parse_string_error(ctx, p0,
+ "Unescaped newline in JSON string");
+ /* Count the newline but don't add it to the decoding */
+ ctx->lineno++;
+ } else if (strict && *ctx->p <= 0x1f) {
+ return parse_string_error(ctx, p0, "Unescaped ASCII control character");
+ } else if (c == 0) {
+ binary = 1;
+ }
+ if (!strict || c < 0x80) {
+ /* ASCII, or not strict -> no need to validate */
+ *(p++) = c;
+ ctx->p++;
+ continue;
+ }
+
+ /*
+ * Being strict for parsing means we want to detect malformed UTF-8
+ * sequences.
+ *
+ * If not strict then we just go on below and add to `p' whatever
+ * bytes we find in `ctx->p' as we find them.
+ *
+ * For each two-byte sequence we need one more byte in `p[]'. For
+ * each three-byte sequence we need two more bytes in `p[]'.
+ *
+ * Setting `need' and looping will cause `p0' to be grown.
+ *
+ * NOTE: All cases in this block must continue or return w/ error.
+ */
+ if ((c & 0xe0) == 0xc0) {
+ /* Two-byte UTF-8 encoding */
+ if (pend - p < 2) {
+ need = 2;
+ continue; /* realloc p0 */
+ }
+
+ *(p++) = c;
+ ctx->p++;
+ if (ctx->p == ctx->pend)
+ return parse_string_error(ctx, p0, "Truncated UTF-8");
+ c = *(ctx->p++);
+ if ((c & 0xc0) != 0x80)
+ return parse_string_error(ctx, p0, "Truncated UTF-8");
+ *(p++) = c;
+ continue;
+ }
+ if ((c & 0xf0) == 0xe0) {
+ /* Three-byte UTF-8 encoding */
+ if (pend - p < 3) {
+ need = 3;
+ continue; /* realloc p0 */
+ }
+
+ *(p++) = c;
+ ctx->p++;
+ if (ctx->p == ctx->pend)
+ return parse_string_error(ctx, p0, "Truncated UTF-8");
+ c = *(ctx->p++);
+ if ((c & 0xc0) != 0x80)
+ return parse_string_error(ctx, p0, "Truncated UTF-8");
+ *(p++) = c;
+ c = *(ctx->p++);
+ if ((c & 0xc0) != 0x80)
+ return parse_string_error(ctx, p0, "Truncated UTF-8");
+ *(p++) = c;
+ continue;
+ }
+ if ((c & 0xf8) == 0xf0)
+ return parse_string_error(ctx, p0, "UTF-8 sequence not "
+ "encoded as escaped UTF-16");
+ if ((c & 0xc0) == 0x80)
+ return parse_string_error(ctx, p0,
+ "Invalid UTF-8 "
+ "(bare continuation code unit)");
+
+ return parse_string_error(ctx, p0, "Not UTF-8");
+ }
+
+ /* Backslash-quoted character */
+ ctx->p++;
+ if (ctx->p == ctx->pend) {
+ ctx->error =
+ heim_error_create(EINVAL,
+ "Unterminated JSON string at line %lu",
+ ctx->lineno);
+ free(p0);
+ return NULL;
+ }
+ switch (*ctx->p) {
+ /* Simple escapes */
+ case 'b': *(p++) = '\b'; ctx->p++; continue;
+ case 'f': *(p++) = '\f'; ctx->p++; continue;
+ case 'n': *(p++) = '\n'; ctx->p++; continue;
+ case 'r': *(p++) = '\r'; ctx->p++; continue;
+ case 't': *(p++) = '\t'; ctx->p++; continue;
+ case '"': *(p++) = '"'; ctx->p++; continue;
+ case '\\': *(p++) = '\\'; ctx->p++; continue;
+ /* Escaped Unicode handled below */
+ case 'u':
+ /*
+ * Worst case for !strict we need 11 bytes for a truncated non-BMP
+ * codepoint escape. Call it 12.
+ */
+ if (strict)
+ need = 4;
+ else
+ need = 12;
+ if (pend - p < need) {
+ /* Go back to the backslash, realloc, try again */
+ ctx->p--;
+ continue;
+ }
+
+ need = 0;
+ ctx->p++;
+ break;
+ default:
+ if (!strict) {
+ *(p++) = *ctx->p;
+ ctx->p++;
+ continue;
+ }
+ ctx->error =
+ heim_error_create(EINVAL,
+ "Invalid backslash escape at line %lu",
+ ctx->lineno);
+ free(p0);
+ return NULL;
+ }
+
+ /* Unicode code point */
+ if (pend - p < 12) {
+ need = 12;
+ ctx->p -= 2; /* for "\\u" */
+ continue; /* This will cause p0 to be realloc'ed */
+ }
+ p_save = ctx->p;
+ ctop = cbot = -3;
+ ctop = unescape_unicode(ctx);
+ if (ctop == -1 && strict)
+ return parse_string_error(ctx, p0, "Invalid escaped Unicode");
+ if (ctop == -1) {
+ /*
+ * Not strict; tolerate bad input.
+ *
+ * Output "\\u" and then loop to treat what we expected to be four
+ * digits as if they were not part of an escaped Unicode codepoint.
+ */
+ ctx->p = p_save;
+ if (p < pend)
+ *(p++) = '\\';
+ if (p < pend)
+ *(p++) = 'u';
+ continue;
+ }
+ if (ctop == 0) {
+ *(p++) = '\0';
+ binary = 1;
+ continue;
+ }
+ if (ctop < 0xd800) {
+ if (!encode_utf8(ctx, &p, pend, ctop))
+ return parse_string_error(ctx, p0,
+ "Internal JSON string parse error");
+ continue;
+ }
+
+ /*
+ * We parsed the top escaped codepoint of a surrogate pair encoding
+ * of a non-BMP Unicode codepoint. What follows must be another
+ * escaped codepoint.
+ */
+ if (ctx->p < ctx->pend && ctx->p[0] == '\\')
+ ctx->p++;
+ else
+ ctop = -1;
+ if (ctop > -1 && ctx->p < ctx->pend && ctx->p[0] == 'u')
+ ctx->p++;
+ else
+ ctop = -1;
+ if (ctop > -1) {
+ /* Parse the hex digits of the bottom half of the surrogate pair */
+ cbot = unescape_unicode(ctx);
+ if (cbot == -1 || cbot < 0xdc00)
+ ctop = -1;
+ }
+ if (ctop == -1) {
+ if (strict)
+ return parse_string_error(ctx, p0,
+ "Invalid surrogate pair");
+
+ /*
+ * Output "\\u", rewind, output the digits of `ctop'.
+ *
+ * When we get to what should have been the bottom half of the
+ * pair we'll necessarily fail to parse it as a normal escaped
+ * Unicode codepoint, and once again, rewind and output its digits.
+ */
+ if (p < pend)
+ *(p++) = '\\';
+ if (p < pend)
+ *(p++) = 'u';
+ ctx->p = p_save;
+ continue;
+ }
+
+ /* Finally decode the surrogate pair then encode as UTF-8 */
+ ctop -= 0xd800;
+ cbot -= 0xdc00;
+ if (!encode_utf8(ctx, &p, pend, 0x10000 + ((ctop << 10) | (cbot & 0x3ff))))
+ return parse_string_error(ctx, p0,
+ "Internal JSON string parse error");
}
- start = ++ctx->p;
- while (ctx->p < ctx->pend) {
- if (*ctx->p == '\n') {
- ctx->lineno++;
- } else if (*ctx->p == '\\') {
- if (ctx->p + 1 == ctx->pend)
- goto out;
- ctx->p++;
- quote = 1;
- } else if (*ctx->p == '"') {
- heim_object_t o;
-
- if (quote) {
- char *p0, *p;
- p = p0 = malloc(ctx->p - start);
- if (p == NULL)
- goto out;
- while (start < ctx->p) {
- if (*start == '\\') {
- start++;
- /* XXX validate quoted char */
- }
- *p++ = *start++;
- }
- o = heim_string_create_with_bytes(p0, p - p0);
- free(p0);
- } else {
- o = heim_string_create_with_bytes(start, ctx->p - start);
- if (o == NULL) {
- ctx->error = heim_error_create_enomem();
- return NULL;
- }
-
- /* If we can decode as base64, then let's */
- if (ctx->flags & HEIM_JSON_F_TRY_DECODE_DATA) {
- void *buf;
- size_t len;
- const char *s;
-
- s = heim_string_get_utf8(o);
- len = strlen(s);
-
- if (len >= 4 && strspn(s, base64_chars) >= len - 2) {
- buf = malloc(len);
- if (buf == NULL) {
- heim_release(o);
- ctx->error = heim_error_create_enomem();
- return NULL;
- }
- len = rk_base64_decode(s, buf);
- if (len == -1) {
- free(buf);
- return o;
- }
- heim_release(o);
- o = heim_data_ref_create(buf, len, free);
- }
- }
- }
- ctx->p += 1;
+ if (p0 == NULL)
+ return heim_string_create("");
- return o;
- }
- ctx->p += 1;
+ /* NUL-terminate for rk_base64_decode() and plain paranoia */
+ if (p0 != NULL && p == pend) {
+ /*
+ * Work out how far p is into p0 to re-esablish p after
+ * the realloc()
+ */
+ size_t p0_to_pend_len = (pend - p0);
+ char *tmp = realloc(p0, 1 + p0_to_pend_len);
+
+ if (tmp == NULL) {
+ ctx->error = heim_error_create_enomem();
+ free(p0);
+ return NULL;
+ }
+ /*
+ * We have three pointers, p, pend (which are the same)
+ * and p0, we want to keep them pointing into the same
+ * memory after the realloc()
+ */
+ p = tmp + p0_to_pend_len;
+
+ pend = p + 1;
+ p0 = tmp;
}
- out:
- ctx->error = heim_error_create(EINVAL, "ran out of string");
- return NULL;
+ *(p++) = '\0';
+
+ /* If there's embedded NULs, it's not a C string */
+ if (binary) {
+ o = heim_data_ref_create(p0, (p - 1) - p0, free);
+ return o;
+ }
+
+ /* Sadly this will copy `p0' */
+ o = heim_string_create_with_bytes(p0, p - p0);
+ free(p0);
+ return o;
}
static int
@@ -809,3 +1389,83 @@ heim_json_copy_serialize(heim_object_t obj, heim_json_flags_t flags, heim_error_
}
return str;
}
+
+struct heim_eq_f_ctx {
+ heim_dict_t other;
+ int ret;
+};
+
+static void
+heim_eq_dict_iter_f(heim_object_t key, heim_object_t val, void *d)
+{
+ struct heim_eq_f_ctx *ctx = d;
+ heim_object_t other_val;
+
+ if (!ctx->ret)
+ return;
+
+ /*
+ * This doesn't work if the key is an array or a dict, which, anyways,
+ * isn't allowed in JSON, though we allow it.
+ */
+ other_val = heim_dict_get_value(ctx->other, key);
+ ctx->ret = heim_json_eq(val, other_val);
+}
+
+int
+heim_json_eq(heim_object_t a, heim_object_t b)
+{
+ heim_tid_t atid, btid;
+
+ if (a == b)
+ return 1;
+ if (a == NULL || b == NULL)
+ return 0;
+ atid = heim_get_tid(a);
+ btid = heim_get_tid(b);
+ if (atid != btid)
+ return 0;
+ switch (atid) {
+ case HEIM_TID_ARRAY: {
+ size_t len = heim_array_get_length(b);
+ size_t i;
+
+ if (heim_array_get_length(a) != len)
+ return 0;
+ for (i = 0; i < len; i++) {
+ if (!heim_json_eq(heim_array_get_value(a, i),
+ heim_array_get_value(b, i)))
+ return 0;
+ }
+ return 1;
+ }
+ case HEIM_TID_DICT: {
+ struct heim_eq_f_ctx ctx;
+
+ ctx.other = b;
+ ctx.ret = 1;
+ heim_dict_iterate_f(a, &ctx, heim_eq_dict_iter_f);
+
+ if (ctx.ret) {
+ ctx.other = a;
+ heim_dict_iterate_f(b, &ctx, heim_eq_dict_iter_f);
+ }
+ return ctx.ret;
+ }
+ case HEIM_TID_STRING:
+ return strcmp(heim_string_get_utf8(a), heim_string_get_utf8(b)) == 0;
+ case HEIM_TID_DATA: {
+ return heim_data_get_length(a) == heim_data_get_length(b) &&
+ memcmp(heim_data_get_ptr(a), heim_data_get_ptr(b),
+ heim_data_get_length(a)) == 0;
+ }
+ case HEIM_TID_NUMBER:
+ return heim_number_get_long(a) == heim_number_get_long(b);
+ case HEIM_TID_NULL:
+ case HEIM_TID_BOOL:
+ return heim_bool_val(a) == heim_bool_val(b);
+ default:
+ break;
+ }
+ return 0;
+}
diff --git a/third_party/heimdal/lib/base/log.c b/third_party/heimdal/lib/base/log.c
index 24295b5adbc..1d79c7e45b9 100644
--- a/third_party/heimdal/lib/base/log.c
+++ b/third_party/heimdal/lib/base/log.c
@@ -1051,7 +1051,8 @@ heim_audit_trail(heim_svc_req_desc r, heim_error_code ret, const char *retname)
break;
default:
/* Wish we had a com_err number->symbolic name function */
- (void) snprintf(retvalbuf, sizeof(retvalbuf), "UNKNOWN-%d", ret);
+ (void) snprintf(retvalbuf, sizeof(retvalbuf), "UNKNOWN-%d",
+ ret ? ret : r->error_code);
retval = retvalbuf;
break;
}
diff --git a/third_party/heimdal/lib/base/string.c b/third_party/heimdal/lib/base/string.c
index f942447163d..5e79e00b18c 100644
--- a/third_party/heimdal/lib/base/string.c
+++ b/third_party/heimdal/lib/base/string.c
@@ -153,7 +153,8 @@ heim_string_create_with_bytes(const void *data, size_t len)
s = _heim_alloc_object(&_heim_string_object, len + 1);
if (s) {
- memcpy(s, data, len);
+ if (len)
+ memcpy(s, data, len);
((char *)s)[len] = '\0';
}
return s;
@@ -238,7 +239,7 @@ heim_string_t
__heim_string_constant(const char *_str)
{
static HEIMDAL_MUTEX mutex = HEIMDAL_MUTEX_INITIALIZER;
- static heim_base_once_t once;
+ static heim_base_once_t once = HEIM_BASE_ONCE_INIT;
static heim_dict_t dict = NULL;
heim_string_t s, s2;
diff --git a/third_party/heimdal/lib/base/test_base.c b/third_party/heimdal/lib/base/test_base.c
index be6c860e26b..6d0668663af 100644
--- a/third_party/heimdal/lib/base/test_base.c
+++ b/third_party/heimdal/lib/base/test_base.c
@@ -53,6 +53,7 @@
#include <sys/stat.h>
#ifndef WIN32
#include <sys/file.h>
+#include <locale.h>
#endif
#ifdef HAVE_IO_H
#include <io.h>
@@ -244,26 +245,318 @@ test_json(void)
};
char *s;
size_t i, k;
- heim_object_t o, o2;
+ heim_object_t o, o2, o3;
heim_string_t k1 = heim_string_create("k1");
o = heim_json_create("\"string\"", 10, 0, NULL);
heim_assert(o != NULL, "string");
heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
heim_assert(strcmp("string", heim_string_get_utf8(o)) == 0, "wrong string");
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
+ heim_release(o);
+
+ /*
+ * Test string escaping:
+ *
+ * - C-like must-escapes
+ * - ASCII control character must-escapes
+ * - surrogate pairs
+ *
+ * We test round-tripping. First we parse, then we serialize, then parse,
+ * then compare the second parse to the first for equality.
+ *
+ * We do compare serialized forms in spite of their not being canonical.
+ * That means that some changes to serialization can cause failures here.
+ */
+ o = heim_json_create("\""
+ "\\b\\f\\n\\r\\t" /* ASCII C-like escapes */
+ "\x1e" /* ASCII control character w/o C-like escape */
+ "\\u00e1" /* &aacute; */
+ "\\u07ff"
+ "\\u0801"
+ "\\u8001"
+ "\\uD834\\udd1e" /* U+1D11E, as shown in RFC 7159 */
+ "\"", 10, 0, NULL);
+ heim_assert(o != NULL, "string");
+ heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
+ heim_assert(strcmp(
+ "\b\f\n\r\t"
+ "\x1e"
+ "\xc3\xa1"
+ "\xdf\xbf"
+ "\xe0\xA0\x81"
+ "\xe8\x80\x81"
+ "\xf0\x9d\x84\x9e", heim_string_get_utf8(o)) == 0, "wrong string");
+ o2 = heim_json_copy_serialize(o,
+ HEIM_JSON_F_STRICT |
+ HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
+ heim_assert(strcmp("\"\\b\\f\\n\\r\\t\\u001Eá߿ࠁ老\\uD834\\uDD1E\"",
+ heim_string_get_utf8(o2)) == 0,
+ "JSON encoding changed; please check that it is till valid");
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
+ heim_release(o);
+
+ o = heim_json_create("\""
+ "\\b\\f\\n\\r\\t" /* ASCII C-like escapes */
+ "\x1e" /* ASCII control character w/o C-like escape */
+ "\xc3\xa1"
+ "\xdf\xbf"
+ "\xe0\xa0\x81"
+ "\xE8\x80\x81"
+ "\\uD834\\udd1e" /* U+1D11E, as shown in RFC 7159 */
+ "\"", 10, 0, NULL);
+ heim_assert(o != NULL, "string");
+ heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
+ heim_assert(strcmp(
+ "\b\f\n\r\t"
+ "\x1e"
+ "\xc3\xa1"
+ "\xdf\xbf"
+ "\xe0\xA0\x81"
+ "\xe8\x80\x81"
+ "\xf0\x9d\x84\x9e", heim_string_get_utf8(o)) == 0, "wrong string");
+ o2 = heim_json_copy_serialize(o,
+ HEIM_JSON_F_STRICT |
+ HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
+ heim_assert(strcmp("\"\\b\\f\\n\\r\\t\\u001Eá߿ࠁ老\\uD834\\uDD1E\"",
+ heim_string_get_utf8(o2)) == 0,
+ "JSON encoding changed; please check that it is till valid");
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
+ heim_release(o);
+
+ /*
+ * Test HEIM_JSON_F_ESCAPE_NON_ASCII.
+ *
+ * Also test that we get escaped non-ASCII because we're in a not-UTF-8
+ * locale, since we setlocale(LC_ALL, "C"), so we should escape non-ASCII
+ * by default.
+ */
+ o = heim_json_create("\""
+ "\\b\\f\\n\\r\\t" /* ASCII C-like escapes */
+ "\x1e" /* ASCII control character w/o C-like escape */
+ "\xc3\xa1"
+ "\xdf\xbf"
+ "\xe0\xa0\x81"
+ "\xE8\x80\x81"
+ "\\uD834\\udd1e" /* U+1D11E, as shown in RFC 7159 */
+ "\"", 10, 0, NULL);
+ heim_assert(o != NULL, "string");
+ heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
+ heim_assert(strcmp(
+ "\b\f\n\r\t"
+ "\x1e"
+ "\xc3\xa1"
+ "\xdf\xbf"
+ "\xe0\xA0\x81"
+ "\xe8\x80\x81"
+ "\xf0\x9d\x84\x9e", heim_string_get_utf8(o)) == 0, "wrong string");
+ o2 = heim_json_copy_serialize(o,
+ HEIM_JSON_F_STRICT |
+ HEIM_JSON_F_ESCAPE_NON_ASCII, NULL);
+ heim_assert(strcmp("\"\\b\\f\\n\\r\\t\\u001E\\u00E1\\u07FF\\u0801\\u8001"
+ "\\uD834\\uDD1E\"",
+ heim_string_get_utf8(o2)) == 0,
+ "JSON encoding changed; please check that it is till valid");
+ heim_release(o2);
+ o2 = heim_json_copy_serialize(o, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(strcmp("\"\\b\\f\\n\\r\\t\\u001E\\u00E1\\u07FF\\u0801\\u8001"
+ "\\uD834\\uDD1E\"",
+ heim_string_get_utf8(o2)) == 0,
+ "JSON encoding changed; please check that it is till valid");
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
+ heim_release(o);
+
+ /* Test rejection of unescaped ASCII control characters */
+ o = heim_json_create("\"\b\\f\"", 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(o == NULL, "strict parse accepted bad input");
+ o = heim_json_create("\"\b\x1e\"", 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(o == NULL, "strict parse accepted bad input");
+
+ o = heim_json_create("\"\b\\f\"", 10, 0, NULL);
+ heim_assert(o != NULL, "string");
+ heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
+ heim_assert(strcmp("\b\f", heim_string_get_utf8(o)) == 0, "wrong string");
+ o2 = heim_json_copy_serialize(o,
+ HEIM_JSON_F_STRICT |
+ HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
+ heim_assert(strcmp("\"\\b\\f\"", heim_string_get_utf8(o2)) == 0,
+ "JSON encoding changed; please check that it is till valid");
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
+ heim_release(o);
+
+ /* Test bogus backslash escape */
+ o = heim_json_create("\""
+ "\\ "
+ "\"", 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(o == NULL, "malformed string accepted");
+ o = heim_json_create("\""
+ "\\ "
+ "\"", 10, 0, NULL);
+ heim_assert(o != NULL, "malformed string rejected (not strict)");
+ heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
+ heim_assert(strcmp(" ", heim_string_get_utf8(o)) == 0, "wrong string");
+ o2 = heim_json_copy_serialize(o,
+ HEIM_JSON_F_STRICT |
+ HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
+ heim_assert(strcmp("\" \"", heim_string_get_utf8(o2)) == 0,
+ "JSON encoding changed; please check that it is till valid");
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
+ heim_release(o);
+
+ /* Test truncated surrogate encoding (bottom code unit) */
+ o = heim_json_create("\""
+ "\xE8\x80\x81"
+ "\\uD834\\udd"
+ "\"", 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(o == NULL, "malformed string accepted");
+ o = heim_json_create("\""
+ "\xE8\x80\x81"
+ "\\uD834\\udd"
+ "\"", 10, 0, NULL);
+ heim_assert(o != NULL, "malformed string rejected (not strict)");
+ heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
+ heim_assert(strcmp(
+ "\xe8\x80\x81"
+ "\\uD834\\udd", heim_string_get_utf8(o)) == 0, "wrong string");
+ o2 = heim_json_copy_serialize(o,
+ HEIM_JSON_F_STRICT |
+ HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
+ heim_assert(strcmp("\"老\\\\uD834\\\\udd\"",
+ heim_string_get_utf8(o2)) == 0,
+ "JSON encoding changed; please check that it is till valid");
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
+ heim_release(o);
+
+ /* Test truncated surrogate encodings (top code unit) */
+ o = heim_json_create("\""
+ "\xE8\x80\x81"
+ "\\uD83"
+ "\"", 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(o == NULL, "malformed string accepted");
+ o = heim_json_create("\""
+ "\xE8\x80\x81"
+ "\\uD83"
+ "\"", 10, 0, NULL);
+ heim_assert(o != NULL, "malformed string rejected (not strict)");
+ heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
+ heim_assert(strcmp(
+ "\xe8\x80\x81"
+ "\\uD83", heim_string_get_utf8(o)) == 0, "wrong string");
+ o2 = heim_json_copy_serialize(o,
+ HEIM_JSON_F_STRICT |
+ HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
+ heim_assert(strcmp("\"老\\\\uD83\"",
+ heim_string_get_utf8(o2)) == 0,
+ "JSON encoding changed; please check that it is till valid");
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
heim_release(o);
+ /*
+ * Test handling of truncated UTF-8 multi-byte sequences.
+ */
+ o = heim_json_create("\""
+ "\xE8\x80"
+ "\"", 10, 0, NULL);
+ heim_assert(o != NULL, "malformed string rejected (not strict)");
+ heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
+ heim_assert(strcmp("\xe8\x80",
+ heim_string_get_utf8(o)) == 0, "wrong string");
+ o2 = heim_json_copy_serialize(o,
+ HEIM_JSON_F_STRICT |
+ HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
+ heim_assert(o2 == NULL, "malformed string serialized");
+ o2 = heim_json_copy_serialize(o, HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(o3 == NULL, "malformed string accepted (not strict)");
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(strcmp("\xe8\x80",
+ heim_string_get_utf8(o3)) == 0, "wrong string");
+ heim_release(o3);
+ heim_release(o2);
+ heim_release(o);
+
+ /* Test handling of unescaped / embedded newline */
+ o = heim_json_create("\"\n\"", 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(o == NULL, "malformed string accepted (strict)");
+ o = heim_json_create("\"\n\"", 10, 0, NULL);
+ heim_assert(o != NULL, "malformed string rejected (not strict)");
+ heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
+ heim_assert(strcmp("\n", heim_string_get_utf8(o)) == 0, "wrong string");
+ o2 = heim_json_copy_serialize(o, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(o2 != NULL, "string not serialized");
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(o3 != NULL, "string not accepted");
+ heim_assert(strcmp("\n", heim_string_get_utf8(o3)) == 0, "wrong string");
+ heim_release(o3);
+ heim_release(o2);
+ heim_release(o);
+
+ /* Test handling of embedded NULs (must decode as data, not string) */
+ o = heim_json_create("\"\\u0000\"", 10, HEIM_JSON_F_STRICT, NULL);
+ heim_assert(o != NULL, "string with NULs rejected");
+ heim_assert(heim_get_tid(o) == heim_data_get_type_id(), "data-tid");
+ heim_assert(heim_data_get_length(o) == 1, "wrong data length");
+ heim_assert(((const char *)heim_data_get_ptr(o))[0] == '\0',
+ "wrong data NUL");
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ heim_assert(o2 != NULL, "data not serialized");
+ heim_release(o2);
+ heim_release(o);
+
+ /*
+ * Note that the trailing ']' is not part of the JSON text (which is just a
+ * string).
+ */
o = heim_json_create(" \"foo\\\"bar\" ]", 10, 0, NULL);
heim_assert(o != NULL, "string");
heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
heim_assert(strcmp("foo\"bar", heim_string_get_utf8(o)) == 0, "wrong string");
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
heim_release(o);
o = heim_json_create(" { \"key\" : \"value\" }", 10, 0, NULL);
heim_assert(o != NULL, "dict");
heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
heim_release(o);
+ /*
+ * heim_json_eq() can't handle dicts with dicts as keys, so we don't check
+ * for round-tripping here
+ */
o = heim_json_create("{ { \"k1\" : \"s1\", \"k2\" : \"s2\" } : \"s3\", "
"{ \"k3\" : \"s4\" } : -1 }", 10, 0, NULL);
heim_assert(o != NULL, "dict");
@@ -281,6 +574,11 @@ test_json(void)
o2 = heim_dict_copy_value(o, k1);
heim_assert(heim_get_tid(o2) == heim_string_get_type_id(), "string-tid");
heim_release(o2);
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
heim_release(o);
o = heim_json_create(" { \"k1\" : { \"k2\" : \"s2\" } }", 10, 0, NULL);
@@ -289,6 +587,11 @@ test_json(void)
o2 = heim_dict_copy_value(o, k1);
heim_assert(heim_get_tid(o2) == heim_dict_get_type_id(), "dict-tid");
heim_release(o2);
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
heim_release(o);
o = heim_json_create("{ \"k1\" : 1 }", 10, 0, NULL);
@@ -297,26 +600,51 @@ test_json(void)
o2 = heim_dict_copy_value(o, k1);
heim_assert(heim_get_tid(o2) == heim_number_get_type_id(), "number-tid");
heim_release(o2);
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
heim_release(o);
o = heim_json_create("-10", 10, 0, NULL);
heim_assert(o != NULL, "number");
heim_assert(heim_get_tid(o) == heim_number_get_type_id(), "number-tid");
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
heim_release(o);
o = heim_json_create("99", 10, 0, NULL);
heim_assert(o != NULL, "number");
heim_assert(heim_get_tid(o) == heim_number_get_type_id(), "number-tid");
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
heim_release(o);
o = heim_json_create(" [ 1 ]", 10, 0, NULL);
heim_assert(o != NULL, "array");
heim_assert(heim_get_tid(o) == heim_array_get_type_id(), "array-tid");
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
heim_release(o);
o = heim_json_create(" [ -1 ]", 10, 0, NULL);
heim_assert(o != NULL, "array");
heim_assert(heim_get_tid(o) == heim_array_get_type_id(), "array-tid");
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
heim_release(o);
for (i = 0; i < (sizeof (j) / sizeof (j[0])); i++) {
@@ -325,6 +653,11 @@ test_json(void)
fprintf(stderr, "Failed to parse this JSON: %s\n", j[i]);
return 1;
}
+ o2 = heim_json_copy_serialize(o, 0, NULL);
+ o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
+ heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
+ heim_release(o3);
+ heim_release(o2);
heim_release(o);
/* Simple fuzz test */
for (k = strlen(j[i]) - 1; k > 0; k--) {
@@ -945,6 +1278,11 @@ main(int argc, char **argv)
{
int res = 0;
+#ifndef WIN32
+ setlocale(LC_ALL, "C");
+ heim_assert(!heim_locale_is_utf8(), "setlocale(LC_ALL, \"C\") failed?");
+#endif
+
res |= test_memory();
res |= test_mutex();
res |= test_rwlock();
diff --git a/third_party/heimdal/lib/base/version-script.map b/third_party/heimdal/lib/base/version-script.map
index 928e8619995..9493ee69236 100644
--- a/third_party/heimdal/lib/base/version-script.map
+++ b/third_party/heimdal/lib/base/version-script.map
@@ -146,7 +146,9 @@ HEIMDAL_BASE_1.0 {
heim_json_copy_serialize;
heim_json_create;
heim_json_create_with_bytes;
+ heim_json_eq;
heim_load_plugins;
+ heim_locale_is_utf8;
heim_log;
heim_log_msg;
_heim_make_permanent;
diff --git a/third_party/heimdal/lib/gssapi/Makefile.am b/third_party/heimdal/lib/gssapi/Makefile.am
index a69ebffb04e..3cb8437db28 100644
--- a/third_party/heimdal/lib/gssapi/Makefile.am
+++ b/third_party/heimdal/lib/gssapi/Makefile.am
@@ -264,10 +264,6 @@ dist_libgssapi_la_SOURCES = \
$(sanonsrc)
nodist_libgssapi_la_SOURCES = \
- gkrb5_err.c \
- gkrb5_err.h \
- negoex_err.c \
- negoex_err.h \
$(BUILT_SOURCES)
libgssapi_la_DEPENDENCIES = version-script.map
@@ -333,7 +329,13 @@ $(test_context_OBJECTS): $(BUILTHEADERS)
$(libgssapi_la_OBJECTS): $(srcdir)/version-script.map
-BUILT_SOURCES = $(spnego_files) $(gssapi_files)
+BUILT_SOURCES = \
+ $(spnego_files) \
+ $(gssapi_files) \
+ gkrb5_err.c \
+ gkrb5_err.h \
+ negoex_err.c \
+ negoex_err.h
$(libgssapi_la_OBJECTS): gkrb5_err.h negoex_err.h
gkrb5_err.h: $(srcdir)/krb5/gkrb5_err.et
diff --git a/third_party/heimdal/lib/gssapi/gss-token.c b/third_party/heimdal/lib/gssapi/gss-token.c
index 844fa4d3820..f3f90521c3b 100644
--- a/third_party/heimdal/lib/gssapi/gss-token.c
+++ b/third_party/heimdal/lib/gssapi/gss-token.c
@@ -235,10 +235,9 @@ write_and_free_token(gss_buffer_t out, int negotiate)
printf("\n");
if (len < inc)
inc = len;
- ret = rk_base64_encode(p, inc, &outstr);
- if (ret < 0) {
+ if (rk_base64_encode(p, inc, &outstr) < 0) {
fprintf(stderr, "Out of memory.\n");
- ret = 1;
+ ret = errno;
goto bail;
}
ret = 0;
@@ -247,6 +246,7 @@ write_and_free_token(gss_buffer_t out, int negotiate)
p += inc;
len -= inc;
} while (len > 0);
+ ret = 0;
bail:
gss_release_buffer(&min, out);
diff --git a/third_party/heimdal/lib/gssapi/krb5/8003.c b/third_party/heimdal/lib/gssapi/krb5/8003.c
index 3e213363534..bf7da11c754 100644
--- a/third_party/heimdal/lib/gssapi/krb5/8003.c
+++ b/third_party/heimdal/lib/gssapi/krb5/8003.c
@@ -259,7 +259,7 @@ _gsskrb5_verify_8003_checksum(
}
if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS
- && (memcmp(p, zeros, sizeof(zeros)) != 0 || client_asserted_cb)) {
+ && (ct_memcmp(p, zeros, sizeof(zeros)) != 0 || client_asserted_cb)) {
if(hash_input_chan_bindings(input_chan_bindings, hash) != 0) {
*minor_status = 0;
return GSS_S_BAD_BINDINGS;
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 62b26ed7eb9..a705d03a875 100644
--- a/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c
@@ -932,7 +932,7 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_init_sec_context
time_rec);
if (ret != GSS_S_COMPLETE)
break;
- fallthrough;
+ HEIM_FALLTHROUGH;
case INITIATOR_RESTART:
ret = init_auth_restart(minor_status,
cred,
diff --git a/third_party/heimdal/lib/gssapi/netlogon/crypto.c b/third_party/heimdal/lib/gssapi/netlogon/crypto.c
index 0fc8f019d64..6147eec55e0 100644
--- a/third_party/heimdal/lib/gssapi/netlogon/crypto.c
+++ b/third_party/heimdal/lib/gssapi/netlogon/crypto.c
@@ -588,7 +588,7 @@ _netlogon_unwrap_iov(OM_uint32 *minor_status,
/* [MS-NRPC] 3.3.4.2.2.10: verify signature */
_netlogon_digest(ctx, sig, iov, iov_count, checksum);
- if (memcmp(sig->Checksum, checksum, _netlogon_checksum_length(sig)) != 0)
+ if (ct_memcmp(sig->Checksum, checksum, _netlogon_checksum_length(sig)) != 0)
return GSS_S_BAD_SIG;
HEIMDAL_MUTEX_lock(&ctx->Mutex);
diff --git a/third_party/heimdal/lib/gssapi/ntlm/crypto.c b/third_party/heimdal/lib/gssapi/ntlm/crypto.c
index efa71d911dc..d1a115ff8e3 100644
--- a/third_party/heimdal/lib/gssapi/ntlm/crypto.c
+++ b/third_party/heimdal/lib/gssapi/ntlm/crypto.c
@@ -230,7 +230,7 @@ v2_verify_message(gss_buffer_t in,
if (ret)
return ret;
- if (memcmp(checksum, out, 16) != 0)
+ if (ct_memcmp(checksum, out, 16) != 0)
return GSS_S_BAD_MIC;
return GSS_S_COMPLETE;
diff --git a/third_party/heimdal/lib/hcrypto/des.c b/third_party/heimdal/lib/hcrypto/des.c
index ac174180fb9..32f87b47137 100644
--- a/third_party/heimdal/lib/hcrypto/des.c
+++ b/third_party/heimdal/lib/hcrypto/des.c
@@ -851,7 +851,7 @@ DES_string_to_key(const char *str, DES_cblock *key)
k[7] ^= 0xF0;
DES_set_key(key, &ks);
DES_cbc_cksum(s, key, len, &ks, key);
- memset(&ks, 0, sizeof(ks));
+ memset_s(&ks, sizeof(ks), 0, sizeof(ks));
DES_set_odd_parity(key);
if (DES_is_weak_key(key))
k[7] ^= 0xF0;
diff --git a/third_party/heimdal/lib/hcrypto/dh.c b/third_party/heimdal/lib/hcrypto/dh.c
index 5d2d214f752..b3b25e5186d 100644
--- a/third_party/heimdal/lib/hcrypto/dh.c
+++ b/third_party/heimdal/lib/hcrypto/dh.c
@@ -145,7 +145,7 @@ DH_free(DH *dh)
free_if(dh->counter);
#undef free_if
- memset(dh, 0, sizeof(*dh));
+ memset_s(dh, sizeof(*dh), 0, sizeof(*dh));
free(dh);
}
diff --git a/third_party/heimdal/lib/hcrypto/dsa.c b/third_party/heimdal/lib/hcrypto/dsa.c
index bbb34601c31..eac0ae6498e 100644
--- a/third_party/heimdal/lib/hcrypto/dsa.c
+++ b/third_party/heimdal/lib/hcrypto/dsa.c
@@ -70,7 +70,7 @@ DSA_free(DSA *dsa)
free_if(dsa->r);
#undef free_if
- memset(dsa, 0, sizeof(*dsa));
+ memset_s(dsa, sizeof(*dsa), 0, sizeof(*dsa));
free(dsa);
}
diff --git a/third_party/heimdal/lib/hcrypto/engine.c b/third_party/heimdal/lib/hcrypto/engine.c
index 3dae960fd0c..6a79b7c9907 100644
--- a/third_party/heimdal/lib/hcrypto/engine.c
+++ b/third_party/heimdal/lib/hcrypto/engine.c
@@ -87,7 +87,7 @@ ENGINE_finish(ENGINE *engine)
if (engine->dso_handle)
dlclose(engine->dso_handle);
- memset(engine, 0, sizeof(*engine));
+ memset_s(engine, sizeof(*engine), 0, sizeof(*engine));
engine->references = -1;
diff --git a/third_party/heimdal/lib/hcrypto/evp-openssl.c b/third_party/heimdal/lib/hcrypto/evp-openssl.c
index a651184c6ea..ca02862bf68 100644
--- a/third_party/heimdal/lib/hcrypto/evp-openssl.c
+++ b/third_party/heimdal/lib/hcrypto/evp-openssl.c
@@ -204,7 +204,7 @@ get_EVP_CIPHER_once_cb(void *d)
*/
ossl_evp = EVP_get_cipherbynid(arg->nid);
if (ossl_evp == NULL) {
- (void) memset(hc_evp, 0, sizeof(*hc_evp));
+ (void) memset_s(hc_evp, sizeof(*hc_evp), 0, sizeof(*hc_evp));
#if HCRYPTO_FALLBACK
*arg->hc_memoizep = arg->fallback;
#endif
@@ -348,7 +348,7 @@ get_EVP_MD_once_cb(void *d)
*arg->ossl_memoizep = ossl_evp = EVP_get_digestbynid(arg->nid);
if (ossl_evp == NULL) {
- (void) memset(hc_evp, 0, sizeof(*hc_evp));
+ (void) memset_s(hc_evp, sizeof(*hc_evp), 0, sizeof(*hc_evp));
#if HCRYPTO_FALLBACK
*arg->hc_memoizep = arg->fallback;
#endif
diff --git a/third_party/heimdal/lib/hcrypto/evp.c b/third_party/heimdal/lib/hcrypto/evp.c
index 9cced4c536c..320e85283f7 100644
--- a/third_party/heimdal/lib/hcrypto/evp.c
+++ b/third_party/heimdal/lib/hcrypto/evp.c
@@ -189,12 +189,12 @@ EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) HC_DEPRECATED
if (!ret)
return ret;
} else if (ctx->md) {
- memset(ctx->ptr, 0, ctx->md->ctx_size);
+ memset_s(ctx->ptr, ctx->md->ctx_size, 0, ctx->md->ctx_size);
}
ctx->md = NULL;
ctx->engine = NULL;
free(ctx->ptr);
- memset(ctx, 0, sizeof(*ctx));
+ memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
return 1;
}
@@ -607,7 +607,7 @@ EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)
}
if (c->cipher_data) {
if (c->cipher)
- memset(c->cipher_data, 0, c->cipher->ctx_size);
+ memset_s(c->cipher_data, c->cipher->ctx_size, 0, c->cipher->ctx_size);
free(c->cipher_data);
c->cipher_data = NULL;
}
@@ -905,7 +905,7 @@ EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, void *out, int *outlen,
/* fill in local buffer and encrypt */
memcpy(ctx->buf + ctx->buf_len, in, left);
ret = (*ctx->cipher->do_cipher)(ctx, out, ctx->buf, blocksize);
- memset(ctx->buf, 0, blocksize);
+ memset_s(ctx->buf, blocksize, 0, blocksize);
if (ret != 1)
return ret;
@@ -966,7 +966,7 @@ EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, void *out, int *outlen)
/* zero fill local buffer */
memset(ctx->buf + ctx->buf_len, 0, left);
ret = (*ctx->cipher->do_cipher)(ctx, out, ctx->buf, blocksize);
- memset(ctx->buf, 0, blocksize);
+ memset_s(ctx->buf, blocksize, 0, blocksize);
if (ret != 1)
return ret;
diff --git a/third_party/heimdal/lib/hcrypto/hmac.c b/third_party/heimdal/lib/hcrypto/hmac.c
index 6b387ae90dc..adccee76b26 100644
--- a/third_party/heimdal/lib/hcrypto/hmac.c
+++ b/third_party/heimdal/lib/hcrypto/hmac.c
@@ -46,17 +46,17 @@ void
HMAC_CTX_cleanup(HMAC_CTX *ctx)
{
if (ctx->buf) {
- memset(ctx->buf, 0, ctx->key_length);
+ memset_s(ctx->buf, ctx->key_length, 0, ctx->key_length);
free(ctx->buf);
ctx->buf = NULL;
}
if (ctx->opad) {
- memset(ctx->opad, 0, EVP_MD_block_size(ctx->md));
+ memset_s(ctx->opad, EVP_MD_block_size(ctx->md), 0, EVP_MD_block_size(ctx->md));
free(ctx->opad);
ctx->opad = NULL;
}
if (ctx->ipad) {
- memset(ctx->ipad, 0, EVP_MD_block_size(ctx->md));
+ memset_s(ctx->ipad, EVP_MD_block_size(ctx->md), 0, EVP_MD_block_size(ctx->md));
free(ctx->ipad);
ctx->ipad = NULL;
}
diff --git a/third_party/heimdal/lib/hcrypto/md2.c b/third_party/heimdal/lib/hcrypto/md2.c
index da41e6d83ee..0170d416a1c 100644
--- a/third_party/heimdal/lib/hcrypto/md2.c
+++ b/third_party/heimdal/lib/hcrypto/md2.c
@@ -133,6 +133,6 @@ MD2_Final (void *res, struct md2 *m)
MD2_Update(m, pad, 16);
memcpy(res, m->state, MD2_DIGEST_LENGTH);
- memset(m, 0, sizeof(*m));
+ memset_s(m, sizeof(*m), 0, sizeof(*m));
return 1;
}
diff --git a/third_party/heimdal/lib/hcrypto/passwd_dlg.c b/third_party/heimdal/lib/hcrypto/passwd_dlg.c
index 037fa7436a4..30721160a2a 100644
--- a/third_party/heimdal/lib/hcrypto/passwd_dlg.c
+++ b/third_party/heimdal/lib/hcrypto/passwd_dlg.c
@@ -77,11 +77,11 @@ pwd_dialog(char *buf, int size)
{
case IDOK:
strlcpy(buf, passwd, size);
- memset (passwd, 0, sizeof(passwd));
+ memset_s (passwd, sizeof(passwd), 0, sizeof(passwd));
return 0;
case IDCANCEL:
default:
- memset (passwd, 0, sizeof(passwd));
+ memset_s (passwd, sizeof(passwd), 0, sizeof(passwd));
return 1;
}
}
diff --git a/third_party/heimdal/lib/hcrypto/rand-fortuna.c b/third_party/heimdal/lib/hcrypto/rand-fortuna.c
index 313b86f83cf..74ba12396fd 100644
--- a/third_party/heimdal/lib/hcrypto/rand-fortuna.c
+++ b/third_party/heimdal/lib/hcrypto/rand-fortuna.c
@@ -336,7 +336,7 @@ add_entropy(FState * st, const unsigned char *data, unsigned len)
st->pool0_bytes += len;
memset_s(hash, sizeof(hash), 0, sizeof(hash));
- memset_s(&md, sizeof(hash), 0, sizeof(md));
+ memset_s(&md, sizeof(md), 0, sizeof(md));
}
/*
diff --git a/third_party/heimdal/lib/hcrypto/rc2.c b/third_party/heimdal/lib/hcrypto/rc2.c
index 02b684cbd4b..53d32cf0417 100644
--- a/third_party/heimdal/lib/hcrypto/rc2.c
+++ b/third_party/heimdal/lib/hcrypto/rc2.c
@@ -105,7 +105,7 @@ RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits)
for (j = 0; j < 64; j++)
key->data[j] = k[(j * 2) + 0] | (k[(j * 2) + 1] << 8);
- memset(k, 0, sizeof(k));
+ memset_s(k, sizeof(k), 0, sizeof(k));
}
#define ROT16L(w,n) ((w<<n)|(w>>(16-n)))
diff --git a/third_party/heimdal/lib/hcrypto/rsa.c b/third_party/heimdal/lib/hcrypto/rsa.c
index 6172b25413f..31470d0069a 100644
--- a/third_party/heimdal/lib/hcrypto/rsa.c
+++ b/third_party/heimdal/lib/hcrypto/rsa.c
@@ -160,7 +160,7 @@ RSA_free(RSA *rsa)
free_if(rsa->iqmp);
#undef free_if
- memset(rsa, 0, sizeof(*rsa));
+ memset_s(rsa, sizeof(*rsa), 0, sizeof(*rsa));
free(rsa);
}
@@ -426,7 +426,7 @@ RSA_verify(int type, const unsigned char *from, unsigned int flen,
return -4;
}
- if (flen != di.digest.length || memcmp(di.digest.data, from, flen) != 0) {
+ if (flen != di.digest.length || ct_memcmp(di.digest.data, from, flen) != 0) {
free_DigestInfo(&di);
return -5;
}
diff --git a/third_party/heimdal/lib/hdb/Makefile.am b/third_party/heimdal/lib/hdb/Makefile.am
index 89ab15d9d3e..4a559953243 100644
--- a/third_party/heimdal/lib/hdb/Makefile.am
+++ b/third_party/heimdal/lib/hdb/Makefile.am
@@ -17,7 +17,9 @@ endif
BUILT_SOURCES = \
$(gen_files_hdb) \
hdb_err.c \
- hdb_err.h
+ hdb_err.h \
+ $(srcdir)/hdb-protos.h \
+ $(srcdir)/hdb-private.h
gen_files_hdb = \
asn1_Event.c \
diff --git a/third_party/heimdal/lib/hdb/common.c b/third_party/heimdal/lib/hdb/common.c
index a92cc1372db..56e582abaa8 100644
--- a/third_party/heimdal/lib/hdb/common.c
+++ b/third_party/heimdal/lib/hdb/common.c
@@ -181,6 +181,7 @@ fetch_entry_or_alias(krb5_context context,
ret = decode_HDB_EntryOrAlias(value.data, value.length, &eoa, NULL);
if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_entry) {
*entry = eoa.u.entry;
+ entry->aliased = 0;
} else if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_alias) {
krb5_data_free(&key);
ret = hdb_principal2key(context, eoa.u.alias.principal, &key);
@@ -192,6 +193,7 @@ fetch_entry_or_alias(krb5_context context,
/* No alias chaining */
ret = hdb_value2entry(context, &value, entry);
krb5_free_principal(context, eoa.u.alias.principal);
+ entry->aliased = 1;
} else if (ret == 0)
ret = ENOTSUP;
if (ret == 0 && enterprise_principal) {
@@ -203,6 +205,7 @@ fetch_entry_or_alias(krb5_context context,
entry->flags.force_canonicalize = 1;
}
+#if 0
/* HDB_F_GET_ANY indicates request originated from KDC (not kadmin) */
if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_alias &&
(flags & (HDB_F_CANON|HDB_F_GET_ANY)) == 0) {
@@ -211,6 +214,7 @@ fetch_entry_or_alias(krb5_context context,
free_HDB_entry(entry);
ret = HDB_ERR_NOENTRY;
}
+#endif
krb5_free_principal(context, enterprise_principal);
krb5_data_free(&value);
@@ -219,11 +223,58 @@ fetch_entry_or_alias(krb5_context context,
return ret;
}
+/*
+ * We have only one type of aliases in our HDB entries, but we really need two:
+ * hard and soft.
+ *
+ * Hard aliases should be treated as if they were distinct principals with the
+ * same keys.
+ *
+ * Soft aliases should be treated as configuration to issue referrals, and they
+ * can only result in referrals to other realms.
+ *
+ * Rather than add a type of aliases, we'll use a convention where the form of
+ * the target of the alias indicates whether the alias is hard or soft.
+ *
+ * TODO We could also use an attribute of the aliased entry.
+ */
+static int
+is_soft_alias_p(krb5_context context,
+ krb5_const_principal principal,
+ unsigned int flags,
+ hdb_entry *h)
+{
+ /* Target is a WELLKNOWN/REFERRALS/TARGET/... -> soft alias */
+ if (krb5_principal_get_num_comp(context, h->principal) >= 3 &&
+ strcmp(krb5_principal_get_comp_string(context, h->principal, 0),
+ KRB5_WELLKNOWN_NAME) == 0 &&
+ strcmp(krb5_principal_get_comp_string(context, h->principal, 1),
+ "REFERRALS") == 0 &&
+ strcmp(krb5_principal_get_comp_string(context, h->principal, 2),
+ "TARGET") == 0)
+ return 1;
+
+ /*
+ * Pre-8.0 we had only soft aliases for a while, and one site used aliases
+ * of referrals-targetNN@TARGET-REALM.
+ */
+ if (krb5_principal_get_num_comp(context, h->principal) == 1 &&
+ strncmp("referrals-target",
+ krb5_principal_get_comp_string(context, h->principal, 0),
+ sizeof("referrals-target") - 1) == 0)
+ return 1;
+
+ /* All other cases are hard aliases */
+ return 0;
+}
+
krb5_error_code
_hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
unsigned flags, krb5_kvno kvno, hdb_entry *entry)
{
krb5_error_code ret;
+ int soft_aliased = 0;
+ int same_realm;
ret = fetch_entry_or_alias(context, db, principal, flags, entry);
if (ret)
@@ -278,7 +329,54 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
}
}
- return 0;
+ if (!entry->aliased)
+ return 0;
+
+ soft_aliased = is_soft_alias_p(context, principal, flags, entry);
+
+ /* Never return HDB_ERR_WRONG_REALM to kadm5 or other non-KDC callers */
+ if ((flags & HDB_F_ADMIN_DATA))
+ return 0;
+
+ same_realm = krb5_realm_compare(context, principal, entry->principal);
+
+ if (entry->aliased && !soft_aliased) {
+ /*
+ * This is a hard alias. We'll make the entry's name be the same as
+ * the alias.
+ *
+ * Except, we allow for disabling this for same-realm aliases, mainly
+ * for our tests.
+ */
+ if (same_realm &&
+ krb5_config_get_bool_default(context, NULL, FALSE, "hdb",
+ "same_realm_aliases_are_soft", NULL))
+ return 0;
+
+ /* EPNs are always soft */
+ if (principal->name.name_type != KRB5_NT_ENTERPRISE_PRINCIPAL) {
+ krb5_free_principal(context, entry->principal);
+ ret = krb5_copy_principal(context, principal, &entry->principal);
+ if (ret) {
+ hdb_free_entry(context, db, entry);
+ return ret;
+ }
+ }
+ return 0;
+ }
+
+ /* Same realm -> not a referral, therefore this is a hard alias */
+ if (same_realm) {
+ if (soft_aliased) {
+ /* Soft alias to the same realm?! No. */
+ hdb_free_entry(context, db, entry);
+ return HDB_ERR_NOENTRY;
+ }
+ return 0;
+ }
+
+ /* Not same realm && not hard alias */
+ return HDB_ERR_WRONG_REALM;
}
static krb5_error_code
@@ -313,6 +411,8 @@ hdb_remove_aliases(krb5_context context, HDB *db, krb5_data *key)
if (code == 0) {
code = db->hdb__del(context, db, akey);
krb5_data_free(&akey);
+ if (code == HDB_ERR_NOENTRY)
+ code = 0;
}
if (code) {
free_HDB_entry(&oldentry);
@@ -348,6 +448,12 @@ hdb_add_aliases(krb5_context context, HDB *db,
if (code == 0) {
code = db->hdb__put(context, db, flags, key, value);
krb5_data_free(&key);
+ if (code == HDB_ERR_EXISTS)
+ /*
+ * Assuming hdb_check_aliases() was called, this must be a
+ * duplicate in the alias list.
+ */
+ code = 0;
}
krb5_data_free(&value);
if (code)
@@ -750,6 +856,10 @@ derive_keys_for_kr(krb5_context context,
* (t - krp->epoch < 0) is better than (krp->epoch < t), making us more
* tolerant of signed 32-bit time_t here near 2038. Of course, we have
* signed 32-bit time_t dragons elsewhere.
+ *
+ * We don't need to check for n == 0 && rotation_period_offset < 0 because
+ * only derive_keys_for_current_kr() calls us with non-zero rotation period
+ * offsets, and it will never call us in that case.
*/
if (t - krp->epoch < 0)
return 0; /* This KR is not relevant yet */
@@ -758,6 +868,37 @@ derive_keys_for_kr(krb5_context context,
set_time = krp->epoch + krp->period * n;
kvno = krp->base_kvno + n;
+ /*
+ * Since this principal is virtual, or has virtual keys, we're going to
+ * derive a "password expiration time" for it in order to help httpkadmind
+ * and other tools figure out when to request keys again.
+ *
+ * The kadm5 representation of principals does not include the set_time of
+ * keys/keysets, so we can't have httpkadmind derive a Cache-Control from
+ * that without adding yet another "TL data". Since adding TL data is a
+ * huge pain, we'll just use the `pw_end' field of `HDB_entry' to
+ * communicate when this principal's keys will change next.
+ */
+ if (h->pw_end[0] == 0) {
+ KerberosTime used = (t - krp->epoch) % krp->period;
+ KerberosTime left = krp->period - used;
+
+ /*
+ * If `h->pw_end[0]' == 0 then this must be the current period of the
+ * current KR we're deriving keys for. See upstairs.
+ *
+ * If there's more than a quarter of this time period left, then we'll
+ * set `h->pw_end[0]' to one quarter before the end of this time
+ * period. Else we'll set it to 1/4 after (we'll be including the next
+ * set of derived keys, so there's no harm in waiting that long to
+ * refetch).
+ */
+ if (left > krp->period >> 2)
+ h->pw_end[0] = set_time + krp->period - (krp->period >> 2);
+ else
+ h->pw_end[0] = set_time + krp->period + (krp->period >> 2);
+ }
+
/*
* Do not waste cycles computing keys not wanted or needed.
@@ -1092,6 +1233,11 @@ derive_keys(krb5_context context,
"because last key rotation period "
"marks deletion", p);
+ /* See `derive_keys_for_kr()' */
+ if (h->pw_end == NULL &&
+ (h->pw_end = calloc(1, sizeof(h->pw_end[0]))) == NULL)
+ ret = krb5_enomem(context);
+
/*
* Derive and set in `h' its current kvno and current keys.
*
@@ -1140,6 +1286,12 @@ derive_keys(krb5_context context,
if (ret == 0 && *h->max_life > kr.val[current_kr].period >> 1)
*h->max_life = kr.val[current_kr].period >> 1;
+ if (ret == 0 && h->pw_end[0] == 0)
+ /* Shouldn't happen */
+ h->pw_end[0] = kr.val[current_kr].epoch +
+ kr.val[current_kr].period *
+ (1 + (t - kr.val[current_kr].epoch) / kr.val[current_kr].period);
+
free_HDB_Ext_KeyRotation(&kr);
free_HDB_Ext_KeySet(&base_keys);
free(p);
@@ -1506,6 +1658,10 @@ fetch_it(krb5_context context,
* of labels.
*/
ret = db->hdb_fetch_kvno(context, db, tmpprinc, flags, kvno, ent);
+ if (ret == 0 && nsprinc && ent->flags.invalid) {
+ free_HDB_entry(ent);
+ ret = HDB_ERR_NOENTRY;
+ }
if (ret != HDB_ERR_NOENTRY || hdots == 0 || hdots < mindots || !tmp ||
!do_search)
break;
@@ -1561,7 +1717,9 @@ fetch_it(krb5_context context,
* If unencrypted keys were requested, derive them. There may not be any
* key derivation to do, but that's decided in derive_keys().
*/
- if (ret == 0) {
+ if (ret == 0 || ret == HDB_ERR_WRONG_REALM) {
+ krb5_error_code save_ret = ret;
+
/* Fix the principal name if namespaced */
ret = fix_princ_name(context, princ, nsprinc, ent);
@@ -1572,6 +1730,8 @@ fetch_it(krb5_context context,
/* Pick the best kvno for this principal at the given time */
if (ret == 0)
ret = pick_kvno(context, db, flags, t, kvno, ent);
+ if (ret == 0)
+ ret = save_ret;
}
out:
@@ -1603,7 +1763,7 @@ out:
* @param kvno Key version number (use zero to mean "current")
* @param h Output HDB entry
*
- * @return Zero on success, an error code otherwise.
+ * @return Zero or HDB_ERR_WRONG_REALM on success, an error code otherwise.
*/
krb5_error_code
hdb_fetch_kvno(krb5_context context,
@@ -1615,24 +1775,25 @@ hdb_fetch_kvno(krb5_context context,
krb5uint32 kvno,
hdb_entry *h)
{
- krb5_error_code ret = HDB_ERR_NOENTRY;
+ krb5_error_code ret;
+ krb5_timestamp now;
+
+ krb5_timeofday(context, &now);
flags |= kvno ? HDB_F_KVNO_SPECIFIED : 0; /* XXX is this needed */
- if (t == 0)
- krb5_timeofday(context, &t);
- ret = fetch_it(context, db, principal, flags, t, etype, kvno, h);
+ ret = fetch_it(context, db, principal, flags, t ? t : now, etype, kvno, h);
+ if (ret == 0 && t == 0 && h->flags.virtual &&
+ h->pw_end && h->pw_end[0] < now) {
+ /*
+ * This shouldn't happen!
+ *
+ * Do not allow h->pw_end[0] to be in the past for virtual principals
+ * outside testing. This is just to prevent the AS/TGS from failing.
+ */
+ h->pw_end[0] = now + 3600;
+ }
if (ret == HDB_ERR_NOENTRY)
krb5_set_error_message(context, ret, "no such entry found in hdb");
-
- /*
- * This check is to support aliases in HDB; the force_canonicalize
- * check is to allow HDB backends to support realm name canon
- * independently of principal aliases (used by Samba).
- */
- if (ret == 0 && !(flags & HDB_F_ADMIN_DATA) &&
- !h->flags.force_canonicalize &&
- !krb5_realm_compare(context, principal, h->principal))
- ret = HDB_ERR_WRONG_REALM;
return ret;
}
diff --git a/third_party/heimdal/lib/hdb/hdb-mdb.c b/third_party/heimdal/lib/hdb/hdb-mdb.c
index 6aa5201eb8a..dd1f27453d5 100644
--- a/third_party/heimdal/lib/hdb/hdb-mdb.c
+++ b/third_party/heimdal/lib/hdb/hdb-mdb.c
@@ -146,7 +146,7 @@ my_mdb_env_create_and_open(krb5_context context,
{
struct keep_it_open *p, *n;
MDB_txn *txn = NULL;
- unsigned int flags = MDB_NOSUBDIR;
+ unsigned int flags = MDB_NOSUBDIR | MDB_NOTLS;
struct stat st;
size_t mapsize = 0;
int max_readers;
diff --git a/third_party/heimdal/lib/hdb/hdb.asn1 b/third_party/heimdal/lib/hdb/hdb.asn1
index 9eb96be73d0..abc75f742cc 100644
--- a/third_party/heimdal/lib/hdb/hdb.asn1
+++ b/third_party/heimdal/lib/hdb/hdb.asn1
@@ -59,6 +59,8 @@ HDBFlags ::= BIT STRING {
force-canonicalize(30), -- force the KDC to return the canonical
-- principal irrespective of the setting
-- of the canonicalize KDC option
+ -- (principals cannot have this flag
+ -- set when stored into the HDB)
do-not-store(31) -- Not to be modified and stored in HDB
}
diff --git a/third_party/heimdal/lib/hdb/hdb.opt b/third_party/heimdal/lib/hdb/hdb.opt
index 626f8c7b07a..a96eb632e52 100644
--- a/third_party/heimdal/lib/hdb/hdb.opt
+++ b/third_party/heimdal/lib/hdb/hdb.opt
@@ -3,3 +3,7 @@
--sequence=HDB-Ext-KeySet
--sequence=Keys
--decorate=HDB_entry:void:context?:::
+# The `aliased` field is for indicating whether a name used in an HDB
+# lookup was an alias. This could be useful to applications when hard
+# aliasing is implemented in an HDB backend, as it should be.
+--decorate=HDB_entry:int:aliased:::
diff --git a/third_party/heimdal/lib/hdb/keytab.c b/third_party/heimdal/lib/hdb/keytab.c
index b1aa0207c97..df16cb782fa 100644
--- a/third_party/heimdal/lib/hdb/keytab.c
+++ b/third_party/heimdal/lib/hdb/keytab.c
@@ -223,10 +223,9 @@ hdb_get_entry(krb5_context context,
HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
0, 0, kvno, &ent);
- if(ret == HDB_ERR_NOENTRY) {
+ if (ret == HDB_ERR_WRONG_REALM || ret == HDB_ERR_NOENTRY)
ret = KRB5_KT_NOTFOUND;
- goto out;
- }else if(ret)
+ if (ret)
goto out;
if(kvno && (krb5_kvno)ent.kvno != kvno) {
diff --git a/third_party/heimdal/lib/hx509/cert.c b/third_party/heimdal/lib/hx509/cert.c
index 33805b8ed1a..3dda886edc5 100644
--- a/third_party/heimdal/lib/hx509/cert.c
+++ b/third_party/heimdal/lib/hx509/cert.c
@@ -2443,7 +2443,7 @@ hx509_verify_path(hx509_context context,
type = EE_CERT;
}
}
- fallthrough;
+ HEIM_FALLTHROUGH;
case EE_CERT:
/*
* If there where any proxy certificates in the chain
diff --git a/third_party/heimdal/lib/hx509/cms.c b/third_party/heimdal/lib/hx509/cms.c
index d2728a38c2f..c770b813262 100644
--- a/third_party/heimdal/lib/hx509/cms.c
+++ b/third_party/heimdal/lib/hx509/cms.c
@@ -182,7 +182,7 @@ fill_CMSIdentifier(const hx509_cert cert,
&id->u.subjectKeyIdentifier);
if (ret == 0)
break;
- fallthrough;
+ HEIM_FALLTHROUGH;
case CMS_ID_NAME: {
hx509_name name;
diff --git a/third_party/heimdal/lib/hx509/file.c b/third_party/heimdal/lib/hx509/file.c
index a22f6252cfa..e1fbe7c0688 100644
--- a/third_party/heimdal/lib/hx509/file.c
+++ b/third_party/heimdal/lib/hx509/file.c
@@ -230,7 +230,7 @@ hx509_pem_read(hx509_context context,
where = INDATA;
goto indata;
}
- fallthrough;
+ HEIM_FALLTHROUGH;
case INHEADER:
if (buf[0] == '\0') {
where = INDATA;
diff --git a/third_party/heimdal/lib/hx509/hxtool.1 b/third_party/heimdal/lib/hx509/hxtool.1
new file mode 100644
index 00000000000..377500784ec
--- /dev/null
+++ b/third_party/heimdal/lib/hx509/hxtool.1
@@ -0,0 +1,207 @@
+.\" Copyright (c) 2022 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$
+.\"
+.Dd February 22, 2022
+.Dt HXTOOL 1
+.Os HEIMDAL
+.Sh NAME
+.Nm hxtool
+.Nd PKIX command-line utility
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Oo Fl Fl version Oc
+.Oo Fl Fl help Oc
+.Op Ar sub-command
+.Ek
+.Sh DESCRIPTION
+.Nm
+is a utility for making certificate sigining requests (CSRs),
+displaying CSRs, signing certificates, etc.
+are given, then the value will be parsed and displayed using just
+the self-describing nature of DER.
+.Pp
+All sub-commands have their own help message, shown when invoked
+with the
+.Fl Fl help
+or
+.Fl h
+option.
+.Pp
+Supported commands:
+.Bl -tag -width Ds -offset indent
+.It help
+.It list-oids
+.It verify
+.It print
+.It validate
+.It certificate-copy, cc
+.It ocsp-fetch
+.It ocsp-verify
+.It ocsp-print
+.It revoke-print
+.It generate-key
+.It request-create
+.It request-print
+.It query
+.It info
+.It random-data
+.It crypto-available
+.It crypto-select
+.It hex
+.It certificate-sign, cert-sign, issue-certificate, ca
+.It crl-sign
+.El
+Other sub-commands reported by the
+.Nm help
+sub-command are not stable or fully supported at this time.
+.Sh CERTIFICATE STORES
+Stores of certificates and/or keys have string names that can be
+used with
+.Nm 's
+commands.
+Sub-commands use these certificate store names to refer to files
+and tokens where keys and/or certificates are to be found or
+written.
+For example,
+.Sq FILE:/path/to/some/file .
+.Pp
+Use the
+.Nm certificate-copy
+command to copy certificates from one store to another.
+This is useful for, e.g., converting DER files to PEM or
+vice-versa.
+.Pp
+Heimdal supports a variety of certificate and key store types:
+.Bl -tag -width Ds -offset indent
+.It PEM-FILE:/path
+If writing, PEM will be written.
+If reading, PEM will be expected.
+.It DER-FILE:/path
+If writing, DER will be written.
+If reading, DER will be expected.
+.It FILE:/path
+If writing, PEM will be written.
+If reading, PEM or DER will be detected.
+.It PKCS12:/path
+Barely supported at this time.
+.It DIR:/path
+OpenSSL-style hashed directory of trust anchors.
+.It MEMORY:name
+An in-memory only store, usually never used in
+.NM 's
+commands.
+.It KEYCHAIN:system-anchors
+On OS X this refers to the system's trust anchors.
+.It KEYCHAIN:FILE:/path
+On OS X this refers to an OS X keychain at the given path.
+.It NULL:
+An empty store.
+.It PKCS11:/path/to/shared/object,slot=NUMBER
+Loads the given PKCS#11 provider object and uses the token at the
+given slot number.
+.El
+.Sh CERTIFICATES
+You can validate a certificate with the
+.Nm validate
+sub-command, or verify a certificate and its certification path
+with the
+.Nm verify
+sub-command.
+.Pp
+You can display a certificate using the
+.Nm print
+sub-command:
+.Pp
+.Nm print
+.Oo options Oc
+.Ar STORE
+.Pp
+Options:
+.Bl -tag -width Ds -offset indent
+.Op Fl Fl content
+.Op Fl Fl info
+.Op Fl Fl never-fail
+.Op Fl Fl pass=password
+.Op Fl Fl raw-json
+.El
+.Pp
+The
+.Fl Fl pass=password
+option is for PKCS#12 and PKCS#11 stores, and if needed and not
+given, will be prompted for.
+Note that it's not secure to pass passwords as command-line
+arguments on multi-tenant systems.
+.Pp
+The
+.Fl Fl raw-json
+option prints the certificate(s) in the given
+.Ar STORE
+as a JSON dump of their DER using an experimental (i.e.,
+unstable) schema.
+.Sh KEYS
+The
+.Nm generate-key
+sub-command will generate a key.
+.Sh CERTIFICATE SIGNING REQUESTS
+The
+.Nm request-create
+sub-command will create a CSR.
+The
+.Nm request-print
+sub-command will display a CSR.
+.Sh CERTIFICATE ISSUANCE / CERTIFICATION AUTHORITY
+The
+.Nm certificate-sign
+sub-command will issue a certificate.
+See its usage message.
+.Sh ONLINE CERTIFICATE STATUS PROTOCOL
+The
+.Nm ocsp-fetch
+sub-command will fetch OCSP Responses for the given
+certificates.
+.Pp
+The
+.Nm ocsp-verify
+sub-command will verify OCSP Responses.
+.Pp
+The
+.Nm ocsp-print
+sub-command will display OCSP Responses.
+.Sh CERTIFICATE REVOCATION LIST
+The
+.Nm crl-sign
+sub-command will add certificates to a certificate revocation
+list.
+.Sh SEE ALSO
+.Xr openssl 1
diff --git a/third_party/heimdal/lib/hx509/hxtool.c b/third_party/heimdal/lib/hx509/hxtool.c
index 1bcfdfa44e9..aa9e279c81c 100644
--- a/third_party/heimdal/lib/hx509/hxtool.c
+++ b/third_party/heimdal/lib/hx509/hxtool.c
@@ -2076,39 +2076,33 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv)
}
if (opt->generate_key_string) {
- struct hx509_generate_private_context *keyctx;
+ /*
+ * Note that we used to set isCA in the key gen context. Now that we
+ * use get_key() we no longer set isCA in the key gen context. But
+ * nothing uses that field of the key gen context.
+ */
+ get_key(opt->certificate_private_key_string,
+ opt->generate_key_string,
+ opt->key_bits_integer,
+ &cert_key);
- ret = _hx509_generate_private_key_init(context,
- &asn1_oid_id_pkcs1_rsaEncryption,
- &keyctx);
+ ret = hx509_private_key2SPKI(context, cert_key, &spki);
if (ret)
- hx509_err(context, 1, ret, "generate private key");
-
- if (opt->issue_ca_flag)
- _hx509_generate_private_key_is_ca(context, keyctx);
-
- if (opt->key_bits_integer)
- _hx509_generate_private_key_bits(context, keyctx,
- opt->key_bits_integer);
+ errx(1, "hx509_private_key2SPKI: %d\n", ret);
- ret = _hx509_generate_private_key(context, keyctx,
- &cert_key);
- _hx509_generate_private_key_free(&keyctx);
+ if (opt->self_signed_flag)
+ private_key = cert_key;
+ } else if (opt->certificate_private_key_string) {
+ ret = read_private_key(opt->certificate_private_key_string, &cert_key);
if (ret)
- hx509_err(context, 1, ret, "generate private key");
+ err(1, "read_private_key for certificate");
ret = hx509_private_key2SPKI(context, cert_key, &spki);
if (ret)
errx(1, "hx509_private_key2SPKI: %d\n", ret);
- if (opt->self_signed_flag)
- private_key = cert_key;
- }
-
- if (opt->certificate_private_key_string) {
- ret = read_private_key(opt->certificate_private_key_string, &cert_key);
- if (ret)
- err(1, "read_private_key for certificate");
+ if (opt->self_signed_flag)
+ private_key = cert_key;
}
if (opt->subject_string) {
@@ -2319,7 +2313,31 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv)
hx509_err(context, 1, ret, "hx509_ca_sign");
}
- if (cert_key) {
+ /* Copy the private key to the output store, maybe */
+ if (cert_key && opt->generate_key_string &&
+ !opt->certificate_private_key_string) {
+ /*
+ * Yes: because we're generating the key and --certificate-private-key
+ * was not given.
+ */
+ ret = _hx509_cert_assign_key(cert, cert_key);
+ if (ret)
+ hx509_err(context, 1, ret, "_hx509_cert_assign_key");
+ } else if (opt->certificate_private_key_string && opt->certificate_string &&
+ strcmp(opt->certificate_private_key_string,
+ opt->certificate_string) == 0) {
+ /*
+ * Yes: because we're re-writing the store whence the private key. We
+ * would lose the key otherwise.
+ */
+ ret = _hx509_cert_assign_key(cert, cert_key);
+ if (ret)
+ hx509_err(context, 1, ret, "_hx509_cert_assign_key");
+ } else if (opt->self_signed_flag && opt->ca_private_key_string &&
+ opt->certificate_string &&
+ strcmp(opt->ca_private_key_string,
+ opt->certificate_string) == 0) {
+ /* Yes: same as preceding */
ret = _hx509_cert_assign_key(cert, cert_key);
if (ret)
hx509_err(context, 1, ret, "_hx509_cert_assign_key");
diff --git a/third_party/heimdal/lib/hx509/req.c b/third_party/heimdal/lib/hx509/req.c
index 2b3f46d532a..c8fa42e5f99 100644
--- a/third_party/heimdal/lib/hx509/req.c
+++ b/third_party/heimdal/lib/hx509/req.c
@@ -1046,7 +1046,7 @@ authorize_feat(hx509_request req, abitstring a, size_t n, int idx)
switch (ret) {
case 0:
req->nauthorized++;
- fallthrough;
+ HEIM_FALLTHROUGH;
case -1:
return 0;
default:
@@ -1063,7 +1063,7 @@ reject_feat(hx509_request req, abitstring a, size_t n, int idx)
switch (ret) {
case 0:
req->nauthorized--;
- fallthrough;
+ HEIM_FALLTHROUGH;
case -1:
return 0;
default:
@@ -1245,7 +1245,7 @@ san_map_type(GeneralName *san)
if (der_heim_oid_cmp(&san->u.otherName.type_id, map[i].oid) == 0)
return map[i].type;
}
- fallthrough;
+ HEIM_FALLTHROUGH;
default: return HX509_SAN_TYPE_UNSUPPORTED;
}
}
@@ -1360,7 +1360,7 @@ hx509_request_get_san(hx509_request req,
case HX509_SAN_TYPE_REGISTERED_ID:
return der_print_heim_oid(&san->u.registeredID, '.', out);
case HX509_SAN_TYPE_XMPP:
- fallthrough;
+ HEIM_FALLTHROUGH;
case HX509_SAN_TYPE_MS_UPN: {
int ret;
diff --git a/third_party/heimdal/lib/ipc/server.c b/third_party/heimdal/lib/ipc/server.c
index 40601b9744f..b0b2fa1cb66 100644
--- a/third_party/heimdal/lib/ipc/server.c
+++ b/third_party/heimdal/lib/ipc/server.c
@@ -122,26 +122,19 @@ mach_complete_sync(heim_sipc_call ctx, int returnvalue, heim_idata *reply)
{
struct mach_call_ctx *s = (struct mach_call_ctx *)ctx;
heim_ipc_message_inband_t replyin;
- mach_msg_type_number_t replyinCnt;
- heim_ipc_message_outband_t replyout;
- mach_msg_type_number_t replyoutCnt;
- kern_return_t kr;
+ mach_msg_type_number_t replyinCnt = 0;
+ heim_ipc_message_outband_t replyout = 0;
+ mach_msg_type_number_t replyoutCnt = 0;
if (returnvalue) {
/* on error, no reply */
- replyinCnt = 0;
- replyout = 0; replyoutCnt = 0;
- kr = KERN_SUCCESS;
} else if (reply->length < 2048) {
replyinCnt = reply->length;
memcpy(replyin, reply->data, replyinCnt);
- replyout = 0; replyoutCnt = 0;
- kr = KERN_SUCCESS;
} else {
- replyinCnt = 0;
- kr = vm_read(mach_task_self(),
- (vm_address_t)reply->data, reply->length,
- (vm_address_t *)&replyout, &replyoutCnt);
+ vm_read(mach_task_self(),
+ (vm_address_t)reply->data, reply->length,
+ (vm_address_t *)&replyout, &replyoutCnt);
}
mheim_ripc_call_reply(s->reply_port, returnvalue,
@@ -159,31 +152,24 @@ mach_complete_async(heim_sipc_call ctx, int returnvalue, heim_idata *reply)
{
struct mach_call_ctx *s = (struct mach_call_ctx *)ctx;
heim_ipc_message_inband_t replyin;
- mach_msg_type_number_t replyinCnt;
- heim_ipc_message_outband_t replyout;
- mach_msg_type_number_t replyoutCnt;
- kern_return_t kr;
+ mach_msg_type_number_t replyinCnt = 0;
+ heim_ipc_message_outband_t replyout = 0;
+ mach_msg_type_number_t replyoutCnt = 0;
if (returnvalue) {
/* on error, no reply */
- replyinCnt = 0;
- replyout = 0; replyoutCnt = 0;
- kr = KERN_SUCCESS;
} else if (reply->length < 2048) {
replyinCnt = reply->length;
memcpy(replyin, reply->data, replyinCnt);
- replyout = 0; replyoutCnt = 0;
- kr = KERN_SUCCESS;
} else {
- replyinCnt = 0;
- kr = vm_read(mach_task_self(),
- (vm_address_t)reply->data, reply->length,
- (vm_address_t *)&replyout, &replyoutCnt);
+ vm_read(mach_task_self(),
+ (vm_address_t)reply->data, reply->length,
+ (vm_address_t *)&replyout, &replyoutCnt);
}
- kr = mheim_aipc_acall_reply(s->reply_port, returnvalue,
- replyin, replyinCnt,
- replyout, replyoutCnt);
+ mheim_aipc_acall_reply(s->reply_port, returnvalue,
+ replyin, replyinCnt,
+ replyout, replyoutCnt);
heim_ipc_free_cred(s->cred);
free(s->req.data);
free(s);
@@ -700,6 +686,7 @@ maybe_close(struct client *c)
dispatch_release(c->out);
#endif
close(c->fd); /* ref count fd close */
+ free(c->inmsg);
free(c);
return 1;
}
@@ -1382,4 +1369,3 @@ heim_ipc_main(void)
process_loop();
#endif
}
-
diff --git a/third_party/heimdal/lib/kadm5/ad.c b/third_party/heimdal/lib/kadm5/ad.c
index 58ccf32eacd..b9b9c9023b9 100644
--- a/third_party/heimdal/lib/kadm5/ad.c
+++ b/third_party/heimdal/lib/kadm5/ad.c
@@ -1066,6 +1066,33 @@ kadm5_ad_get_principals(void *server_handle,
}
static kadm5_ret_t
+kadm5_ad_iter_principals(void *server_handle,
+ const char *expression,
+ int (*cb)(void *, const char *),
+ void *cbdata)
+{
+ kadm5_ad_context *context = server_handle;
+
+#ifdef OPENLDAP
+ kadm5_ret_t ret;
+
+ ret = ad_get_cred(context, NULL);
+ if (ret)
+ return ret;
+
+ ret = _kadm5_ad_connect(server_handle);
+ if (ret)
+ return ret;
+
+ krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
+ return KADM5_RPC_ERROR;
+#else
+ krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
+ return KADM5_RPC_ERROR;
+#endif
+}
+
+static kadm5_ret_t
kadm5_ad_get_privs(void *server_handle, uint32_t*privs)
{
kadm5_ad_context *context = server_handle;
@@ -1169,7 +1196,7 @@ kadm5_ad_modify_principal(void *server_handle,
if (entry->attributes & KRB5_KDB_REQUIRES_HW_AUTH)
i |= UF_SMARTCARD_REQUIRED;
else
- i &= UF_SMARTCARD_REQUIRED;
+ i &= ~UF_SMARTCARD_REQUIRED;
if (entry->attributes & KRB5_KDB_DISALLOW_SVR)
i &= ~UF_WORKSTATION_TRUST_ACCOUNT;
else
@@ -1388,6 +1415,9 @@ set_funcs(kadm5_ad_context *c)
SET(c, lock);
SET(c, unlock);
SETNOTIMP(c, setkey_principal_3);
+ SETNOTIMP(c, prune_principal);
+ SET(c, iter_principals);
+ SET(c, dup_context);
}
kadm5_ret_t
@@ -1456,6 +1486,12 @@ kadm5_ad_init_with_password_ctx(krb5_context context,
}
kadm5_ret_t
+kadm5_ad_dup_context(void *in, void **out)
+{
+ return ENOTSUP;
+}
+
+kadm5_ret_t
kadm5_ad_init_with_password(const char *client_name,
const char *password,
const char *service_name,
diff --git a/third_party/heimdal/lib/kadm5/common_glue.c b/third_party/heimdal/lib/kadm5/common_glue.c
index 9993b0a349e..210bf93b91c 100644
--- a/third_party/heimdal/lib/kadm5/common_glue.c
+++ b/third_party/heimdal/lib/kadm5/common_glue.c
@@ -39,6 +39,12 @@ RCSID("$Id$");
#define __CALLABLE(F) (((kadm5_common_context*)server_handle)->funcs.F != 0)
kadm5_ret_t
+kadm5_dup_context(void *server_handle, void **dup_server_handle)
+{
+ return __CALL(dup_context, (server_handle, dup_server_handle));
+}
+
+kadm5_ret_t
kadm5_chpass_principal(void *server_handle,
krb5_principal princ,
const char *password)
@@ -223,6 +229,15 @@ kadm5_get_principals(void *server_handle,
}
kadm5_ret_t
+kadm5_iter_principals(void *server_handle,
+ const char *expression,
+ int (*cb)(void *, const char *),
+ void *cbdata)
+{
+ return __CALL(iter_principals, (server_handle, expression, cb, cbdata));
+}
+
+kadm5_ret_t
kadm5_get_privs(void *server_handle,
uint32_t *privs)
{
diff --git a/third_party/heimdal/lib/kadm5/context_s.c b/third_party/heimdal/lib/kadm5/context_s.c
index 0c154ecfef0..5c9b3e31c81 100644
--- a/third_party/heimdal/lib/kadm5/context_s.c
+++ b/third_party/heimdal/lib/kadm5/context_s.c
@@ -112,6 +112,8 @@ set_funcs(kadm5_server_context *c)
SET(c, lock);
SET(c, unlock);
SET(c, setkey_principal_3);
+ SET(c, iter_principals);
+ SET(c, dup_context);
}
#ifndef NO_UNIX_SOCKETS
@@ -250,6 +252,8 @@ _kadm5_s_init_context(kadm5_server_context **ctx,
krb5_add_et_list (context, initialize_kadm5_error_table_r);
#define is_set(M) (params && params->mask & KADM5_CONFIG_ ## M)
+ if (params)
+ (*ctx)->config.mask = params->mask;
if (is_set(REALM)) {
(*ctx)->config.realm = strdup(params->realm);
if ((*ctx)->config.realm == NULL)
@@ -275,9 +279,9 @@ _kadm5_s_init_context(kadm5_server_context **ctx,
return krb5_enomem(context);
}
- find_db_spec(*ctx);
-
- ret = _kadm5_s_init_hooks(*ctx);
+ ret = find_db_spec(*ctx);
+ if (ret == 0)
+ ret = _kadm5_s_init_hooks(*ctx);
if (ret != 0) {
kadm5_s_destroy(*ctx);
*ctx = NULL;
diff --git a/third_party/heimdal/lib/kadm5/create_s.c b/third_party/heimdal/lib/kadm5/create_s.c
index 1c2ab15f30d..e603497ace2 100644
--- a/third_party/heimdal/lib/kadm5/create_s.c
+++ b/third_party/heimdal/lib/kadm5/create_s.c
@@ -50,6 +50,14 @@ get_default(kadm5_server_context *context, krb5_principal princ,
ret = kadm5_s_get_principal(context, def_principal, def,
KADM5_PRINCIPAL_NORMAL_MASK);
krb5_free_principal (context->context, def_principal);
+
+ if (ret) {
+ /* Copy defaults from kadmin/init.c */
+ memset(def, 0, sizeof(*def));
+ def->max_life = 24 * 60 * 60;
+ def->max_renewable_life = 7 * def->max_life;
+ def->attributes = KRB5_KDB_DISALLOW_ALL_TIX;
+ }
return ret;
}
diff --git a/third_party/heimdal/lib/kadm5/destroy_s.c b/third_party/heimdal/lib/kadm5/destroy_s.c
index fc86e5960e6..0558b45c577 100644
--- a/third_party/heimdal/lib/kadm5/destroy_s.c
+++ b/third_party/heimdal/lib/kadm5/destroy_s.c
@@ -42,10 +42,12 @@ RCSID("$Id$");
static void
destroy_config (kadm5_config_params *c)
{
- free (c->realm);
- free (c->dbname);
- free (c->acl_file);
- free (c->stash_file);
+ if (!c)
+ return;
+ free(c->realm);
+ free(c->dbname);
+ free(c->acl_file);
+ free(c->stash_file);
}
/*
@@ -55,6 +57,8 @@ destroy_config (kadm5_config_params *c)
static void
destroy_kadm5_log_context (kadm5_log_context *c)
{
+ if (!c)
+ return;
free(c->log_file);
if (c->socket_fd != rk_INVALID_SOCKET)
rk_closesocket(c->socket_fd);
diff --git a/third_party/heimdal/lib/kadm5/get_c.c b/third_party/heimdal/lib/kadm5/get_c.c
index 5b2bcca762a..1c1fd9dce80 100644
--- a/third_party/heimdal/lib/kadm5/get_c.c
+++ b/third_party/heimdal/lib/kadm5/get_c.c
@@ -89,7 +89,7 @@ kadm5_c_get_principal(void *server_handle,
out_keep_error:
if (ret == 0)
- kadm5_ret_principal_ent(sp, ent);
+ ret = kadm5_ret_principal_ent(sp, ent);
krb5_storage_free(sp);
krb5_data_free(&reply);
return ret;
diff --git a/third_party/heimdal/lib/kadm5/get_princs_c.c b/third_party/heimdal/lib/kadm5/get_princs_c.c
index 4998223d260..93d7ce7ed1b 100644
--- a/third_party/heimdal/lib/kadm5/get_princs_c.c
+++ b/third_party/heimdal/lib/kadm5/get_princs_c.c
@@ -66,7 +66,7 @@ kadm5_c_get_principals(void *server_handle,
ret = krb5_store_int32(sp, kadm_get_princs);
if (ret)
goto out;
- ret = krb5_store_int32(sp, expression != NULL);
+ ret = krb5_store_int32(sp, expression != NULL ? 1 : 0);
if (ret)
goto out;
if (expression) {
@@ -117,3 +117,187 @@ kadm5_c_get_principals(void *server_handle,
krb5_data_free(&reply);
return ret;
}
+
+kadm5_ret_t
+kadm5_c_iter_principals(void *server_handle,
+ const char *expression,
+ int (*cb)(void *, const char *),
+ void *cbdata)
+{
+ kadm5_client_context *context = server_handle;
+ kadm5_ret_t ret;
+ krb5_storage *sp;
+ unsigned char buf[1024];
+ int32_t tmp;
+ krb5_data reply;
+ size_t i;
+
+ ret = _kadm5_connect(server_handle, 0 /* want_write */);
+ if (ret)
+ return ret;
+
+ krb5_data_zero(&reply);
+
+ sp = krb5_storage_from_mem(buf, sizeof(buf));
+ if (sp == NULL) {
+ ret = krb5_enomem(context->context);
+ goto out_keep_error;
+ }
+ ret = krb5_store_int32(sp, kadm_get_princs);
+ if (ret)
+ goto out;
+
+ /*
+ * Our protocol has an int boolean for this operation to indicate whether
+ * there's an expression. What we'll do here is that instead of sending
+ * just false or trueish, for online iteration we'll send a number other
+ * than 0 or 1 -- a magic value > 0 and < INT_MAX.
+ *
+ * In response we'll expect multiple replies, each with up to some small
+ * number of principal names. See kadmin/server.c.
+ */
+ ret = krb5_store_int32(sp, 0x55555555);
+ if (ret)
+ goto out;
+ ret = krb5_store_string(sp, expression ? expression : "");
+ if (ret)
+ goto out;
+ ret = _kadm5_client_send(context, sp);
+ if (ret)
+ goto out_keep_error;
+ ret = _kadm5_client_recv(context, &reply);
+ if (ret)
+ goto out_keep_error;
+ krb5_storage_free(sp);
+ sp = krb5_storage_from_data (&reply);
+ if (sp == NULL) {
+ ret = krb5_enomem(context->context);
+ goto out_keep_error;
+ }
+ ret = krb5_ret_int32(sp, &tmp);
+ if (ret == 0)
+ ret = tmp;
+
+ if (ret)
+ goto out;
+
+ ret = krb5_ret_int32(sp, &tmp);
+ if (ret)
+ goto out;
+
+ if (tmp < 0) {
+ size_t n = -tmp;
+ int more = 1;
+ int stop = 0;
+
+ /* The server supports online iteration, hooray! */
+
+ while (more) {
+ /*
+ * We expect any number of chunks, each having `n' names, except
+ * the last one would have fewer than `n' (possibly zero, even).
+ *
+ * After that we expect one more reply with just a final return
+ * code.
+ */
+ krb5_data_free(&reply);
+ krb5_storage_free(sp);
+ sp = NULL;
+ ret = _kadm5_client_recv(context, &reply);
+ if (ret == 0 && (sp = krb5_storage_from_data(&reply)) == NULL)
+ ret = krb5_enomem(context->context);
+ if (ret)
+ goto out;
+
+ /* Every chunk begins with a status code */
+ ret = krb5_ret_int32(sp, &tmp);
+ if (ret == 0)
+ ret = tmp;
+ if (ret)
+ goto out;
+
+ /* We expect up to -tmp principals per reply */
+ for (i = 0; i < n; i++) {
+ char *princ = NULL;
+
+ ret = krb5_ret_string(sp, &princ);
+ if (ret == HEIM_ERR_EOF) {
+ /* This was the last reply */
+ more = 0;
+ ret = 0;
+ break;
+ }
+ if (ret)
+ goto out;
+ if (!stop) {
+ stop = cb(cbdata, princ);
+ if (stop) {
+ /*
+ * Tell the server to stop.
+ *
+ * We use a NOP for this, but with a payload that says
+ * "don't reply to the NOP" just in case the NOP
+ * arrives and is processed _after_ the LISTing has
+ * finished.
+ */
+ krb5_storage_free(sp);
+ if ((sp = krb5_storage_emem()) &&
+ krb5_store_int32(sp, kadm_nop) == 0 &&
+ krb5_store_int32(sp, 0))
+ (void) _kadm5_client_send(context, sp);
+ }
+ }
+ free(princ);
+ }
+
+ if (!more) {
+ if (ret == 0)
+ ret = stop;
+ break;
+ }
+ }
+ /* Get the final result code */
+ krb5_data_free(&reply);
+ krb5_storage_free(sp);
+ sp = NULL;
+ ret = _kadm5_client_recv(context, &reply);
+ if (ret == 0 && (sp = krb5_storage_from_data(&reply)) == NULL)
+ ret = krb5_enomem(context->context);
+ if (ret)
+ goto out;
+ ret = krb5_ret_int32(sp, &tmp);
+ if (ret == 0)
+ ret = tmp;
+ if (!stop) {
+ /*
+ * Send our "interrupt" after the last chunk if we hand't
+ * interrupted already.
+ */
+ krb5_storage_free(sp);
+ if ((sp = krb5_storage_emem()) &&
+ krb5_store_int32(sp, kadm_nop) == 0)
+ (void) _kadm5_client_send(context, sp);
+ }
+ } else {
+ size_t n = tmp;
+
+ /* Old server -- listing not online */
+ for (i = 0; i < n; i++) {
+ char *princ = NULL;
+
+ ret = krb5_ret_string(sp, &princ);
+ if (ret)
+ goto out;
+ cb(cbdata, princ);
+ free(princ);
+ }
+ }
+
+ out:
+ krb5_clear_error_message(context->context);
+
+ out_keep_error:
+ krb5_storage_free(sp);
+ krb5_data_free(&reply);
+ return ret;
+}
diff --git a/third_party/heimdal/lib/kadm5/get_princs_s.c b/third_party/heimdal/lib/kadm5/get_princs_s.c
index 27fac2bbb0b..14d3907d759 100644
--- a/third_party/heimdal/lib/kadm5/get_princs_s.c
+++ b/third_party/heimdal/lib/kadm5/get_princs_s.c
@@ -39,17 +39,27 @@ struct foreach_data {
const char *exp;
char *exp2;
char **princs;
- int count;
+ size_t nalloced;
+ size_t count;
};
static krb5_error_code
add_princ(krb5_context context, struct foreach_data *d, char *princ)
{
- char **tmp;
- tmp = realloc(d->princs, (d->count + 1) * sizeof(*tmp));
- if (tmp == NULL)
- return krb5_enomem(context);
- d->princs = tmp;
+
+ if (d->count == INT_MAX)
+ return ERANGE;
+ if (d->nalloced == d->count) {
+ size_t n = d->nalloced + (d->nalloced >> 1) + 128; /* No O(N^2) pls */
+ char **tmp;
+
+ if (SIZE_MAX / sizeof(*tmp) <= n)
+ return ERANGE;
+ if ((tmp = realloc(d->princs, n * sizeof(*tmp))) == NULL)
+ return krb5_enomem(context);
+ d->princs = tmp;
+ d->nalloced = n;
+ }
d->princs[d->count++] = princ;
return 0;
}
@@ -84,7 +94,7 @@ kadm5_s_get_principals(void *server_handle,
{
struct foreach_data d;
kadm5_server_context *context = server_handle;
- kadm5_ret_t ret;
+ kadm5_ret_t ret = 0;
if (!context->keep_open) {
ret = context->db->hdb_open(context->context, context->db, O_RDONLY, 0);
@@ -94,33 +104,103 @@ kadm5_s_get_principals(void *server_handle,
}
}
d.exp = expression;
- {
+ d.exp2 = NULL;
+ if (expression) {
krb5_realm r;
int aret;
ret = krb5_get_default_realm(context->context, &r);
- if (ret)
- goto out;
- aret = asprintf(&d.exp2, "%s@%s", expression, r);
- free(r);
- if (aret == -1 || d.exp2 == NULL) {
- ret = krb5_enomem(context->context);
- goto out;
- }
+ if (ret == 0) {
+ aret = asprintf(&d.exp2, "%s@%s", expression, r);
+ free(r);
+ if (aret == -1 || d.exp2 == NULL)
+ ret = krb5_enomem(context->context);
+ }
}
d.princs = NULL;
+ d.nalloced = 0;
d.count = 0;
- ret = hdb_foreach(context->context, context->db, HDB_F_ADMIN_DATA, foreach, &d);
+ if (ret == 0)
+ ret = hdb_foreach(context->context, context->db, HDB_F_ADMIN_DATA,
+ foreach, &d);
if (ret == 0)
ret = add_princ(context->context, &d, NULL);
- if (ret == 0){
+ if (d.count >= INT_MAX)
+ *count = INT_MAX;
+ else
+ *count = d.count - 1;
+ if (ret == 0)
*princs = d.princs;
- *count = d.count - 1;
- } else
- kadm5_free_name_list(context, d.princs, &d.count);
+ else
+ kadm5_free_name_list(context, d.princs, count);
+ free(d.exp2);
+ if (!context->keep_open)
+ context->db->hdb_close(context->context, context->db);
+ return _kadm5_error_code(ret);
+}
+
+struct foreach_online_data {
+ const char *exp;
+ char *exp2;
+ int (*cb)(void *, const char *);
+ void *cbdata;
+};
+
+static krb5_error_code
+foreach_online(krb5_context context, HDB *db, hdb_entry *ent, void *data)
+{
+ struct foreach_online_data *d = data;
+ krb5_error_code ret;
+ char *princ = NULL;
+
+ ret = krb5_unparse_name(context, ent->principal, &princ);
+ if (ret == 0) {
+ if (!d->exp ||
+ fnmatch(d->exp, princ, 0) == 0 || fnmatch(d->exp2, princ, 0) == 0)
+ ret = d->cb(d->cbdata, princ);
+ free(princ);
+ }
+ return ret;
+}
+
+kadm5_ret_t
+kadm5_s_iter_principals(void *server_handle,
+ const char *expression,
+ int (*cb)(void *, const char *),
+ void *cbdata)
+{
+ struct foreach_online_data d;
+ kadm5_server_context *context = server_handle;
+ kadm5_ret_t ret = 0;
+
+ if (!context->keep_open) {
+ ret = context->db->hdb_open(context->context, context->db, O_RDONLY, 0);
+ if (ret) {
+ krb5_warn(context->context, ret, "opening database");
+ return ret;
+ }
+ }
+ d.exp = expression;
+ d.exp2 = NULL;
+ d.cb = cb;
+ d.cbdata = cbdata;
+ if (expression) {
+ krb5_realm r;
+ int aret;
+
+ ret = krb5_get_default_realm(context->context, &r);
+ if (ret == 0) {
+ aret = asprintf(&d.exp2, "%s@%s", expression, r);
+ free(r);
+ if (aret == -1 || d.exp2 == NULL)
+ ret = krb5_enomem(context->context);
+ }
+ }
+ if (ret == 0)
+ ret = hdb_foreach(context->context, context->db, HDB_F_ADMIN_DATA,
+ foreach_online, &d);
free(d.exp2);
- out:
if (!context->keep_open)
context->db->hdb_close(context->context, context->db);
return _kadm5_error_code(ret);
diff --git a/third_party/heimdal/lib/kadm5/init_c.c b/third_party/heimdal/lib/kadm5/init_c.c
index 5d585d1a295..ffbb639581c 100644
--- a/third_party/heimdal/lib/kadm5/init_c.c
+++ b/third_party/heimdal/lib/kadm5/init_c.c
@@ -78,6 +78,8 @@ set_funcs(kadm5_client_context *c)
SET(c, lock);
SET(c, unlock);
SETNOTIMP(c, setkey_principal_3);
+ SET(c, iter_principals);
+ SET(c, dup_context);
}
kadm5_ret_t
@@ -192,6 +194,56 @@ _kadm5_c_init_context(kadm5_client_context **ctx,
return 0;
}
+kadm5_ret_t
+kadm5_c_dup_context(void *vin, void **out)
+{
+ krb5_error_code ret;
+ kadm5_client_context *in = vin;
+ krb5_context context = in->context;
+ kadm5_client_context *ctx;
+
+ *out = NULL;
+ ctx = malloc(sizeof(*ctx));
+ if (ctx == NULL)
+ return krb5_enomem(in->context);
+
+
+ memset(ctx, 0, sizeof(*ctx));
+ set_funcs(ctx);
+ ctx->readonly_kadmind_port = in->readonly_kadmind_port;
+ ctx->kadmind_port = in->kadmind_port;
+
+ ret = krb5_copy_context(context, &(ctx->context));
+ if (ret == 0) {
+ ctx->my_context = TRUE;
+ ret = krb5_add_et_list(ctx->context, initialize_kadm5_error_table_r);
+ }
+ if (ret == 0 && (ctx->realm = strdup(in->realm)) == NULL)
+ ret = krb5_enomem(context);
+ if (ret == 0 &&
+ (ctx->admin_server = strdup(in->admin_server)) == NULL)
+ ret = krb5_enomem(context);
+ if (in->readonly_admin_server &&
+ (ctx->readonly_admin_server = strdup(in->readonly_admin_server)) == NULL)
+ ret = krb5_enomem(context);
+ if (in->keytab && (ctx->keytab = strdup(in->keytab)) == NULL)
+ ret = krb5_enomem(context);
+ if (in->ccache) {
+ char *fullname = NULL;
+
+ ret = krb5_cc_get_full_name(context, in->ccache, &fullname);
+ if (ret == 0)
+ ret = krb5_cc_resolve(context, fullname, &ctx->ccache);
+ free(fullname);
+ }
+ ctx->sock = -1;
+ if (ret == 0)
+ *out = ctx;
+ else
+ kadm5_c_destroy(ctx);
+ return ret;
+}
+
static krb5_error_code
get_kadm_ticket(krb5_context context,
krb5_ccache id,
diff --git a/third_party/heimdal/lib/kadm5/init_s.c b/third_party/heimdal/lib/kadm5/init_s.c
index 1b1d7f2ff58..35402d88a52 100644
--- a/third_party/heimdal/lib/kadm5/init_s.c
+++ b/third_party/heimdal/lib/kadm5/init_s.c
@@ -109,6 +109,21 @@ kadm5_s_init_with_context(krb5_context context,
}
kadm5_ret_t
+kadm5_s_dup_context(void *vin, void **out)
+{
+ kadm5_server_context *in = vin;
+ kadm5_ret_t ret;
+ char *p = NULL;
+
+ ret = krb5_unparse_name(in->context, in->caller, &p);
+ if (ret == 0)
+ ret = kadm5_s_init_with_context(in->context, p, NULL,
+ &in->config, 0, 0, out);
+ free(p);
+ return ret;
+}
+
+kadm5_ret_t
kadm5_s_init_with_password_ctx(krb5_context context,
const char *client_name,
const char *password,
diff --git a/third_party/heimdal/lib/kadm5/iprop.8 b/third_party/heimdal/lib/kadm5/iprop.8
index b881c441a1a..41aac061829 100644
--- a/third_party/heimdal/lib/kadm5/iprop.8
+++ b/third_party/heimdal/lib/kadm5/iprop.8
@@ -68,6 +68,8 @@
.Oo Fl r Ar string \*(Ba Xo Fl Fl realm= Ns Ar string Xc Oc
.Oo Fl d Ar file \*(Ba Xo Fl Fl database= Ns Ar file Xc Oc
.Oo Fl k Ar kspec \*(Ba Xo Fl Fl keytab= Ns Ar kspec Xc Oc
+.Oo Xo Fl Fl no-keytab Xc Oc
+.Oo Xo Fl Fl cache= Ns Ar cspec Xc Oc
.Op Fl Fl statusfile= Ns Ar file
.Op Fl Fl hostname= Ns Ar hostname
.Op Fl Fl port= Ns Ar port
@@ -125,10 +127,40 @@ This should normally be defined as
in
.Pa /etc/services
or another source of the services database.
-The master and slaves
-must each have access to a keytab with keys for the
-.Nm iprop
-service principal on the local host.
+.Pp
+The
+.Nm ipropd-master
+and
+.Nm ipropd-slave
+programs require acceptor and initiator credentials,
+respectively, for host-based principals for the
+.Ar iprop
+service and the fully-qualified hostnames of the hosts on which
+they run.
+.Pp
+The
+.Nm ipropd-master
+program uses, by default, the HDB-backed keytab
+.Ar HDBGET: ,
+though a file-based keytab can also be specified.
+.Pp
+The
+.Nm ipropd-slave
+program uses the default keytab, which is specified by the
+.Ev KRB5_KTNAME
+environment variable, or the value of the
+.Ar default_keytab_name
+configuration parameter in the
+.Ar [libdefaults]
+section.
+However, if the
+.Fl Fl no-keytab
+option is given, then
+.Nm ipropd-slave
+will use the given or default credentials cache, and it will
+expect that cache to be kept fresh externally (such as by the
+.Nm kinit
+program).
.Pp
There is a keep-alive feature logged in the master's
.Pa slave-stats
@@ -150,6 +182,11 @@ Supported options for
Keytab for authenticating
.Nm ipropd-slave
clients.
+.It Fl Fl cache= Ns Ar cspec
+If the keytab given is the empty string then credentials will be
+used from the default credentials cache, or from the
+.Ar cspec
+if given.
.It Fl d Ar file , Fl Fl database= Ns Ar file
Database (default per KDC)
.It Fl Fl slave-stats-file= Ns Ar file
@@ -201,6 +238,7 @@ in the database directory, or in the directory named by the
.Ev HEIM_PIDFILE_DIR
environment variable.
.Sh SEE ALSO
+.Xr kinit 1 ,
.Xr krb5.conf 5 ,
.Xr hprop 8 ,
.Xr hpropd 8 ,
diff --git a/third_party/heimdal/lib/kadm5/ipropd_slave.c b/third_party/heimdal/lib/kadm5/ipropd_slave.c
index 2b1be00ea60..f92b20c8569 100644
--- a/third_party/heimdal/lib/kadm5/ipropd_slave.c
+++ b/third_party/heimdal/lib/kadm5/ipropd_slave.c
@@ -39,6 +39,9 @@ static const char *config_name = "ipropd-slave";
static int verbose;
static int async_hdb = 0;
+static int no_keytab_flag;
+static char *ccache_str;
+static char *keytab_str;
static krb5_log_facility *log_facility;
static char five_min[] = "5 min";
@@ -115,8 +118,7 @@ connect_to_master (krb5_context context, const char *master,
}
static void
-get_creds(krb5_context context, const char *keytab_str,
- krb5_ccache *cache, const char *serverhost)
+get_creds(krb5_context context, krb5_ccache *cache, const char *serverhost)
{
krb5_keytab keytab;
krb5_principal client;
@@ -127,13 +129,33 @@ get_creds(krb5_context context, const char *keytab_str,
char keytab_buf[256];
int aret;
+ if (no_keytab_flag) {
+ /* We're using an externally refreshed ccache */
+ if (*cache == NULL) {
+ if (ccache_str == NULL)
+ ret = krb5_cc_default(context, cache);
+ else
+ ret = krb5_cc_resolve(context, ccache_str, cache);
+ if (ret)
+ krb5_err(context, 1, ret, "Could not resolve the default cache");
+ }
+ return;
+ }
+
if (keytab_str == NULL) {
ret = krb5_kt_default_name (context, keytab_buf, sizeof(keytab_buf));
- if (ret)
- krb5_err (context, 1, ret, "krb5_kt_default_name");
- keytab_str = keytab_buf;
+ if (ret == 0) {
+ keytab_str = keytab_buf;
+ } else {
+ krb5_warn(context, ret, "Using HDBGET: as the default keytab");
+ keytab_str = "HDBGET:";
+ }
}
+ if (*cache)
+ krb5_cc_destroy(context, *cache);
+ *cache = NULL;
+
ret = krb5_kt_resolve(context, keytab_str, &keytab);
if(ret)
krb5_err(context, 1, ret, "%s", keytab_str);
@@ -690,7 +712,6 @@ static char *status_file;
static char *config_file;
static int version_flag;
static int help_flag;
-static char *keytab_str;
static char *port_str;
static int detach_from_console;
static int daemon_child = -1;
@@ -699,8 +720,12 @@ static struct getargs args[] = {
{ "config-file", 'c', arg_string, &config_file, NULL, NULL },
{ "realm", 'r', arg_string, &realm, NULL, NULL },
{ "database", 'd', arg_string, &database, "database", "file"},
+ { "no-keytab", 0, arg_flag, &no_keytab_flag,
+ "use externally refreshed cache", NULL },
+ { "ccache", 0, arg_string, &ccache_str,
+ "client credentials", "CCACHE" },
{ "keytab", 'k', arg_string, &keytab_str,
- "keytab to get authentication from", "kspec" },
+ "client credentials keytab", "KEYTAB" },
{ "time-lost", 0, arg_string, &server_time_lost,
"time before server is considered lost", "time" },
{ "status-file", 0, arg_string, &status_file,
@@ -740,7 +765,7 @@ main(int argc, char **argv)
kadm5_server_context *server_context;
kadm5_config_params conf;
int master_fd;
- krb5_ccache ccache;
+ krb5_ccache ccache = NULL;
krb5_principal server;
char **files;
int optidx = 0;
@@ -858,7 +883,7 @@ main(int argc, char **argv)
if (ret)
krb5_err(context, 1, ret, "db->close");
- get_creds(context, keytab_str, &ccache, master);
+ get_creds(context, &ccache, master);
ret = krb5_sname_to_principal (context, master, IPROP_NAME,
KRB5_NT_SRV_HST, &server);
@@ -923,8 +948,7 @@ main(int argc, char **argv)
if (auth_context) {
krb5_auth_con_free(context, auth_context);
auth_context = NULL;
- krb5_cc_destroy(context, ccache);
- get_creds(context, keytab_str, &ccache, master);
+ get_creds(context, &ccache, master);
}
if (verbose)
krb5_warnx(context, "authenticating to master");
diff --git a/third_party/heimdal/lib/kadm5/libkadm5srv-exports.def b/third_party/heimdal/lib/kadm5/libkadm5srv-exports.def
index 72ba4174c1f..56366ae2046 100644
--- a/third_party/heimdal/lib/kadm5/libkadm5srv-exports.def
+++ b/third_party/heimdal/lib/kadm5/libkadm5srv-exports.def
@@ -15,6 +15,7 @@ EXPORTS
kadm5_delete_policy
kadm5_delete_principal
kadm5_destroy
+ kadm5_dup_context
kadm5_flush
kadm5_free_key_data
kadm5_free_name_list
@@ -32,6 +33,7 @@ EXPORTS
kadm5_init_with_password_ctx
kadm5_init_with_skey
kadm5_init_with_skey_ctx
+ kadm5_iter_principals
kadm5_lock
kadm5_modify_policy
kadm5_modify_principal
diff --git a/third_party/heimdal/lib/kadm5/private.h b/third_party/heimdal/lib/kadm5/private.h
index 88c2f2823d2..1cb8e3918f5 100644
--- a/third_party/heimdal/lib/kadm5/private.h
+++ b/third_party/heimdal/lib/kadm5/private.h
@@ -68,6 +68,8 @@ struct kadm_func {
int, krb5_key_salt_tuple *,
krb5_keyblock *, int);
kadm5_ret_t (*prune_principal) (void *, krb5_principal, int);
+ kadm5_ret_t (*iter_principals) (void*, const char*, int (*)(void *, const char *), void *);
+ kadm5_ret_t (*dup_context) (void*, void **);
};
typedef struct kadm5_hook_context {
diff --git a/third_party/heimdal/lib/kadm5/version-script-client.map b/third_party/heimdal/lib/kadm5/version-script-client.map
index 4d89fabf308..baae30b1173 100644
--- a/third_party/heimdal/lib/kadm5/version-script-client.map
+++ b/third_party/heimdal/lib/kadm5/version-script-client.map
@@ -11,6 +11,7 @@ HEIMDAL_KADM5_CLIENT_1.0 {
kadm5_c_create_principal;
kadm5_c_delete_principal;
kadm5_c_destroy;
+ kadm5_c_dup_context;
kadm5_c_flush;
kadm5_c_get_principal;
kadm5_c_get_principals;
@@ -21,6 +22,8 @@ HEIMDAL_KADM5_CLIENT_1.0 {
kadm5_c_init_with_password_ctx;
kadm5_c_init_with_skey;
kadm5_c_init_with_skey_ctx;
+ kadm5_c_iter_principals;
+ kadm5_c_get_privs;
kadm5_c_modify_principal;
kadm5_c_prune_principal;
kadm5_c_randkey_principal;
@@ -30,6 +33,7 @@ HEIMDAL_KADM5_CLIENT_1.0 {
kadm5_create_principal;
kadm5_delete_principal;
kadm5_destroy;
+ kadm5_dup_context;
kadm5_flush;
kadm5_free_key_data;
kadm5_free_name_list;
@@ -43,6 +47,7 @@ HEIMDAL_KADM5_CLIENT_1.0 {
kadm5_init_with_password_ctx;
kadm5_init_with_skey;
kadm5_init_with_skey_ctx;
+ kadm5_iter_principals;
kadm5_modify_principal;
kadm5_randkey_principal;
kadm5_randkey_principal_3;
diff --git a/third_party/heimdal/lib/kadm5/version-script.map b/third_party/heimdal/lib/kadm5/version-script.map
index e4b4100f334..6de88fc2217 100644
--- a/third_party/heimdal/lib/kadm5/version-script.map
+++ b/third_party/heimdal/lib/kadm5/version-script.map
@@ -16,6 +16,7 @@ HEIMDAL_KAMD5_SERVER_1.0 {
kadm5_create_principal_3;
kadm5_delete_principal;
kadm5_destroy;
+ kadm5_dup_context;
kadm5_decrypt_key;
kadm5_delete_policy;
kadm5_flush;
@@ -35,6 +36,7 @@ HEIMDAL_KAMD5_SERVER_1.0 {
kadm5_init_with_password_ctx;
kadm5_init_with_skey;
kadm5_init_with_skey_ctx;
+ kadm5_iter_principals;
kadm5_lock;
kadm5_modify_principal;
kadm5_modify_policy;
diff --git a/third_party/heimdal/lib/kafs/kafs_locl.h b/third_party/heimdal/lib/kafs/kafs_locl.h
index 6f34ca63170..f4e2f64b407 100644
--- a/third_party/heimdal/lib/kafs/kafs_locl.h
+++ b/third_party/heimdal/lib/kafs/kafs_locl.h
@@ -96,7 +96,6 @@
#endif
#ifdef KRB5
#include "crypto-headers.h"
-#include <krb5-v4compat.h>
typedef struct credentials CREDENTIALS;
#endif /* KRB5 */
#ifndef NO_AFS
diff --git a/third_party/heimdal/lib/kafs/rxkad_kdf.c b/third_party/heimdal/lib/kafs/rxkad_kdf.c
index 5af391ed99b..b542e8916b5 100644
--- a/third_party/heimdal/lib/kafs/rxkad_kdf.c
+++ b/third_party/heimdal/lib/kafs/rxkad_kdf.c
@@ -209,7 +209,7 @@ _kafs_derive_des_key(krb5_enctype enctype, void *keydata, size_t keylen,
ret = compress_parity_bits(keydata, &keylen);
if (ret)
return ret;
- fallthrough;
+ HEIM_FALLTHROUGH;
default:
if (enctype < 0)
return KRB5_PROG_ETYPE_NOSUPP;
diff --git a/third_party/heimdal/lib/krb5/Makefile.am b/third_party/heimdal/lib/krb5/Makefile.am
index c1345c28a5a..ecce461dd89 100644
--- a/third_party/heimdal/lib/krb5/Makefile.am
+++ b/third_party/heimdal/lib/krb5/Makefile.am
@@ -193,7 +193,6 @@ dist_libkrb5_la_SOURCES = \
keytab_keyfile.c \
keytab_memory.c \
krb5_locl.h \
- krb5-v4compat.h \
krcache.c \
krbhst.c \
kuserok.c \
diff --git a/third_party/heimdal/lib/krb5/NTMakefile b/third_party/heimdal/lib/krb5/NTMakefile
index 40ca0fb0bcc..993e76fcc23 100644
--- a/third_party/heimdal/lib/krb5/NTMakefile
+++ b/third_party/heimdal/lib/krb5/NTMakefile
@@ -2,19 +2,19 @@
#
# Copyright (c) 2009 - 2017, Secure Endpoints Inc.
# All rights reserved.
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
-#
+#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
-#
+#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
-#
+#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
@@ -27,7 +27,7 @@
# 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.
-#
+#
RELDIR=lib\krb5
@@ -184,7 +184,6 @@ INCFILES= \
$(INCDIR)\krb5_locl.h \
$(INCDIR)\krb5-protos.h \
$(INCDIR)\krb5-private.h \
- $(INCDIR)\krb5-v4compat.h \
$(INCDIR)\crypto.h \
$(INCDIR)\an2ln_plugin.h \
$(INCDIR)\ccache_plugin.h \
@@ -267,7 +266,6 @@ dist_libkrb5_la_SOURCES = \
keytab_keyfile.c \
keytab_memory.c \
krb5_locl.h \
- krb5-v4compat.h \
krbhst.c \
kuserok.c \
kx509.c \
diff --git a/third_party/heimdal/lib/krb5/aname_to_localname.c b/third_party/heimdal/lib/krb5/aname_to_localname.c
index 11f270d4978..8515c306e69 100644
--- a/third_party/heimdal/lib/krb5/aname_to_localname.c
+++ b/third_party/heimdal/lib/krb5/aname_to_localname.c
@@ -420,6 +420,7 @@ an2ln_def_plug_an2ln(void *plug_ctx, krb5_context context,
heim_dict_set_value(db_options, HSTR("read-only"),
heim_number_create(1));
dbh = heim_db_create(NULL, an2ln_db_fname, db_options, &error);
+ heim_release(db_options);
if (dbh == NULL) {
krb5_set_error_message(context, heim_error_get_code(error),
N_("Couldn't open aname2lname-text-db", ""));
diff --git a/third_party/heimdal/lib/krb5/changepw.c b/third_party/heimdal/lib/krb5/changepw.c
index 12f0b154689..1982925bf06 100644
--- a/third_party/heimdal/lib/krb5/changepw.c
+++ b/third_party/heimdal/lib/krb5/changepw.c
@@ -384,7 +384,7 @@ process_reply (krb5_context context,
ap_rep_data.data = reply + 6;
ap_rep_data.length = (reply[4] << 8) | (reply[5]);
- if (reply + len < (u_char *)ap_rep_data.data + ap_rep_data.length) {
+ if (len - 6 < ap_rep_data.length) {
str2data (result_string, "client: wrong AP len in reply");
*result_code = KRB5_KPASSWD_MALFORMED;
return 0;
diff --git a/third_party/heimdal/lib/krb5/context.c b/third_party/heimdal/lib/krb5/context.c
index 4040a983518..d6ddd902d64 100644
--- a/third_party/heimdal/lib/krb5/context.c
+++ b/third_party/heimdal/lib/krb5/context.c
@@ -545,7 +545,7 @@ copy_etypes (krb5_context context,
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_copy_context(krb5_context context, krb5_context *out)
{
- krb5_error_code ret;
+ krb5_error_code ret = 0;
krb5_context p;
*out = NULL;
@@ -554,81 +554,80 @@ krb5_copy_context(krb5_context context, krb5_context *out)
if (p == NULL)
return krb5_enomem(context);
- if ((p->hcontext = heim_context_init()) == NULL) {
- ret = ENOMEM;
- goto out;
- }
+ p->cc_ops = NULL;
+ p->etypes = NULL;
+ p->kt_types = NULL;
+ p->cfg_etypes = NULL;
+ p->etypes_des = NULL;
+ p->default_realms = NULL;
+ p->extra_addresses = NULL;
+ p->ignore_addresses = NULL;
- heim_context_set_log_utc(p->hcontext, context->log_utc);
-
- if (context->default_cc_name &&
- (p->default_cc_name = strdup(context->default_cc_name)) == NULL) {
+ if ((p->hcontext = heim_context_init()) == NULL)
ret = ENOMEM;
- goto out;
+
+ if (ret == 0) {
+ heim_context_set_log_utc(p->hcontext, context->log_utc);
+ ret = _krb5_config_copy(context, context->cf, &p->cf);
}
- if (context->default_cc_name_env &&
- (p->default_cc_name_env =
- strdup(context->default_cc_name_env)) == NULL) {
- ret = ENOMEM;
- goto out;
+ if (ret == 0)
+ ret = init_context_from_config_file(p);
+ if (ret == 0 && context->default_cc_name) {
+ free(p->default_cc_name);
+ if ((p->default_cc_name = strdup(context->default_cc_name)) == NULL)
+ ret = ENOMEM;
}
- if (context->configured_default_cc_name &&
- (p->configured_default_cc_name =
- strdup(context->configured_default_cc_name)) == NULL) {
- ret = ENOMEM;
- goto out;
+ if (ret == 0 && context->default_cc_name_env) {
+ free(p->default_cc_name_env);
+ if ((p->default_cc_name_env =
+ strdup(context->default_cc_name_env)) == NULL)
+ ret = ENOMEM;
+ }
+ if (ret == 0 && context->configured_default_cc_name) {
+ free(context->configured_default_cc_name);
+ if ((p->configured_default_cc_name =
+ strdup(context->configured_default_cc_name)) == NULL)
+ ret = ENOMEM;
}
- if (context->etypes) {
+ if (ret == 0 && context->etypes) {
+ free(p->etypes);
ret = copy_etypes(context, context->etypes, &p->etypes);
- if (ret)
- goto out;
}
- if (context->cfg_etypes) {
+ if (ret == 0 && context->cfg_etypes) {
+ free(p->cfg_etypes);
ret = copy_etypes(context, context->cfg_etypes, &p->cfg_etypes);
- if (ret)
- goto out;
}
- if (context->etypes_des) {
+ if (ret == 0 && context->etypes_des) {
+ free(p->etypes_des);
ret = copy_etypes(context, context->etypes_des, &p->etypes_des);
- if (ret)
- goto out;
}
- if (context->default_realms) {
+ if (ret == 0 && context->default_realms) {
+ krb5_free_host_realm(context, p->default_realms);
ret = krb5_copy_host_realm(context,
context->default_realms, &p->default_realms);
- if (ret)
- goto out;
}
- ret = _krb5_config_copy(context, context->cf, &p->cf);
- if (ret)
- goto out;
-
/* XXX should copy */
- _krb5_init_ets(p);
-
- cc_ops_copy(p, context);
- kt_ops_copy(p, context);
-
- ret = krb5_set_extra_addresses(p, context->extra_addresses);
- if (ret)
- goto out;
- ret = krb5_set_extra_addresses(p, context->ignore_addresses);
- if (ret)
- goto out;
-
- ret = _krb5_copy_send_to_kdc_func(p, context);
- if (ret)
- goto out;
-
- *out = p;
-
- return 0;
-
- out:
- krb5_free_context(p);
+ if (ret == 0)
+ _krb5_init_ets(p);
+
+ if (ret == 0)
+ ret = cc_ops_copy(p, context);
+ if (ret == 0)
+ ret = kt_ops_copy(p, context);
+ if (ret == 0)
+ ret = krb5_set_extra_addresses(p, context->extra_addresses);
+ if (ret == 0)
+ ret = krb5_set_extra_addresses(p, context->ignore_addresses);
+ if (ret == 0)
+ ret = _krb5_copy_send_to_kdc_func(p, context);
+
+ if (ret == 0)
+ *out = p;
+ else
+ krb5_free_context(p);
return ret;
}
diff --git a/third_party/heimdal/lib/krb5/convert_creds.c b/third_party/heimdal/lib/krb5/convert_creds.c
index fc371c63776..56261b29fa6 100644
--- a/third_party/heimdal/lib/krb5/convert_creds.c
+++ b/third_party/heimdal/lib/krb5/convert_creds.c
@@ -32,7 +32,6 @@
*/
#include "krb5_locl.h"
-#include "krb5-v4compat.h"
#ifndef HEIMDAL_SMALLER
@@ -58,7 +57,6 @@ krb524_convert_creds_kdc(krb5_context context,
struct credentials *v4creds)
KRB5_DEPRECATED_FUNCTION("Use X instead")
{
- memset(v4creds, 0, sizeof(*v4creds));
krb5_set_error_message(context, EINVAL,
N_("krb524_convert_creds_kdc not supported", ""));
return EINVAL;
@@ -86,7 +84,6 @@ krb524_convert_creds_kdc_ccache(krb5_context context,
struct credentials *v4creds)
KRB5_DEPRECATED_FUNCTION("Use X instead")
{
- memset(v4creds, 0, sizeof(*v4creds));
krb5_set_error_message(context, EINVAL,
N_("krb524_convert_creds_kdc_ccache not supported", ""));
return EINVAL;
diff --git a/third_party/heimdal/lib/krb5/kcm.c b/third_party/heimdal/lib/krb5/kcm.c
index a75fc03f985..f20fc51936f 100644
--- a/third_party/heimdal/lib/krb5/kcm.c
+++ b/third_party/heimdal/lib/krb5/kcm.c
@@ -238,8 +238,7 @@ kcm_alloc(krb5_context context,
if (residual) {
/* KCM cache names must start with {UID} or {UID}: */
- if (residual[0] != '0')
- plen = strspn(residual, "0123456789");
+ plen = strspn(residual, "0123456789");
if (plen && residual[plen] != ':' && residual[plen] != '\0')
plen = 0;
/*
diff --git a/third_party/heimdal/lib/krb5/keytab.c b/third_party/heimdal/lib/krb5/keytab.c
index 559d640f002..bcb3ed83733 100644
--- a/third_party/heimdal/lib/krb5/keytab.c
+++ b/third_party/heimdal/lib/krb5/keytab.c
@@ -883,7 +883,8 @@ krb5_kt_add_entry(krb5_context context,
id->prefix);
return KRB5_KT_NOWRITE;
}
- entry->timestamp = time(NULL);
+ if (entry->timestamp == 0)
+ entry->timestamp = time(NULL);
return (*id->add)(context, id,entry);
}
diff --git a/third_party/heimdal/lib/krb5/krb5-v4compat.h b/third_party/heimdal/lib/krb5/krb5-v4compat.h
deleted file mode 100644
index 2992976e655..00000000000
--- a/third_party/heimdal/lib/krb5/krb5-v4compat.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 1997 - 2003 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 __KRB5_V4COMPAT_H__
-#define __KRB5_V4COMPAT_H__
-
-#include "krb_err.h"
-
-/*
- * This file must only be included with v4 compat glue stuff in
- * heimdal sources.
- *
- * It MUST NOT be installed.
- */
-
-#define KRB_PROT_VERSION 4
-
-#define AUTH_MSG_KDC_REQUEST (1<<1)
-#define AUTH_MSG_KDC_REPLY (2<<1)
-#define AUTH_MSG_APPL_REQUEST (3<<1)
-#define AUTH_MSG_APPL_REQUEST_MUTUAL (4<<1)
-#define AUTH_MSG_ERR_REPLY (5<<1)
-#define AUTH_MSG_PRIVATE (6<<1)
-#define AUTH_MSG_SAFE (7<<1)
-#define AUTH_MSG_APPL_ERR (8<<1)
-#define AUTH_MSG_KDC_FORWARD (9<<1)
-#define AUTH_MSG_KDC_RENEW (10<<1)
-#define AUTH_MSG_DIE (63<<1)
-
-/* General definitions */
-#define KSUCCESS 0
-#define KFAILURE 255
-
-/* */
-
-#define MAX_KTXT_LEN 1250
-
-#define ANAME_SZ 40
-#define REALM_SZ 40
-#define SNAME_SZ 40
-#define INST_SZ 40
-
-struct ktext {
- unsigned int length; /* Length of the text */
- unsigned char dat[MAX_KTXT_LEN]; /* The data itself */
- uint32_t mbz; /* zero to catch runaway strings */
-};
-
-struct credentials {
- char service[ANAME_SZ]; /* Service name */
- char instance[INST_SZ]; /* Instance */
- char realm[REALM_SZ]; /* Auth domain */
- char session[8]; /* Session key */
- int lifetime; /* Lifetime */
- int kvno; /* Key version number */
- struct ktext ticket_st; /* The ticket itself */
- int32_t issue_date; /* The issue time */
- char pname[ANAME_SZ]; /* Principal's name */
- char pinst[INST_SZ]; /* Principal's instance */
-};
-
-#define TKTLIFENUMFIXED 64
-#define TKTLIFEMINFIXED 0x80
-#define TKTLIFEMAXFIXED 0xBF
-#define TKTLIFENOEXPIRE 0xFF
-#define MAXTKTLIFETIME (30*24*3600) /* 30 days */
-#ifndef NEVERDATE
-#define NEVERDATE ((time_t)0x7fffffffL)
-#endif
-
-#define KERB_ERR_NULL_KEY 10
-
-#define CLOCK_SKEW 5*60
-
-#ifndef TKT_ROOT
-#define TKT_ROOT "%{TEMP}/tkt"
-#endif
-
-struct _krb5_krb_auth_data {
- int8_t k_flags; /* Flags from ticket */
- char *pname; /* Principal's name */
- char *pinst; /* His Instance */
- char *prealm; /* His Realm */
- uint32_t checksum; /* Data checksum (opt) */
- krb5_keyblock session; /* Session Key */
- unsigned char life; /* Life of ticket */
- uint32_t time_sec; /* Time ticket issued */
- uint32_t address; /* Address in ticket */
-};
-
-KRB5_LIB_FUNCTION time_t KRB5_LIB_CALL
-_krb5_krb_life_to_time (int, int);
-
-KRB5_LIB_FUNCTION int KRB5_LIB_CALL
-_krb5_krb_time_to_life (time_t, time_t);
-
-KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
-_krb5_krb_tf_setup (krb5_context, struct credentials *,
- const char *, int);
-
-KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
-_krb5_krb_dest_tkt(krb5_context, const char *);
-
-#define krb_time_to_life _krb5_krb_time_to_life
-#define krb_life_to_time _krb5_krb_life_to_time
-
-#endif /* __KRB5_V4COMPAT_H__ */
diff --git a/third_party/heimdal/lib/krb5/pac.c b/third_party/heimdal/lib/krb5/pac.c
index c8f355c8179..b923981908d 100644
--- a/third_party/heimdal/lib/krb5/pac.c
+++ b/third_party/heimdal/lib/krb5/pac.c
@@ -882,6 +882,7 @@ verify_logonname(krb5_context context,
}
ret = krb5_storage_read(sp, s, len);
if (ret != len) {
+ free(s);
krb5_storage_free(sp);
krb5_set_error_message(context, EINVAL, "Failed to read PAC logon name");
return EINVAL;
@@ -894,8 +895,10 @@ verify_logonname(krb5_context context,
unsigned int flags = WIND_RW_LE;
ucs2 = malloc(sizeof(ucs2[0]) * ucs2len);
- if (ucs2 == NULL)
+ if (ucs2 == NULL) {
+ free(s);
return krb5_enomem(context);
+ }
ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len);
free(s);
diff --git a/third_party/heimdal/lib/krb5/pkinit.c b/third_party/heimdal/lib/krb5/pkinit.c
index c9a6e3e8f8b..0501728d3e5 100644
--- a/third_party/heimdal/lib/krb5/pkinit.c
+++ b/third_party/heimdal/lib/krb5/pkinit.c
@@ -109,7 +109,7 @@ integer_to_BN(krb5_context context, const char *field, const heim_integer *f)
}
static krb5_error_code
-select_dh_group(krb5_context context, DH *dh, unsigned long bits,
+select_dh_group(krb5_context context, DH *dh, unsigned long min_bits,
struct krb5_dh_moduli **moduli)
{
const struct krb5_dh_moduli *m;
@@ -118,25 +118,25 @@ select_dh_group(krb5_context context, DH *dh, unsigned long bits,
krb5_set_error_message(context, EINVAL,
N_("Did not find a DH group parameter "
"matching requirement of %lu bits", ""),
- bits);
+ min_bits);
return EINVAL;
}
- if (bits == 0) {
+ if (min_bits == 0) {
m = moduli[1]; /* XXX */
if (m == NULL)
m = moduli[0]; /* XXX */
} else {
int i;
for (i = 0; moduli[i] != NULL; i++) {
- if (bits < moduli[i]->bits)
+ if (moduli[i]->bits >= min_bits)
break;
}
if (moduli[i] == NULL) {
krb5_set_error_message(context, EINVAL,
N_("Did not find a DH group parameter "
"matching requirement of %lu bits", ""),
- bits);
+ min_bits);
return EINVAL;
}
m = moduli[i];
@@ -2164,7 +2164,7 @@ static const char *default_moduli_rfc3526_MODP_group14 =
/* name */
"rfc3526-MODP-group14 "
/* bits */
- "1760 "
+ "2048 "
/* p */
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
diff --git a/third_party/heimdal/lib/krb5/send_to_kdc.c b/third_party/heimdal/lib/krb5/send_to_kdc.c
index 086f2edcd5d..a854e5c4ae9 100644
--- a/third_party/heimdal/lib/krb5/send_to_kdc.c
+++ b/third_party/heimdal/lib/krb5/send_to_kdc.c
@@ -1192,7 +1192,7 @@ krb5_sendto_context(krb5_context context,
break;
}
action = KRB5_SENDTO_KRBHST;
- fallthrough;
+ HEIM_FALLTHROUGH;
case KRB5_SENDTO_KRBHST:
if (ctx->krbhst == NULL) {
ret = krb5_krbhst_init_flags(context, realm, type,
@@ -1214,7 +1214,7 @@ krb5_sendto_context(krb5_context context,
handle = heim_retain(ctx->krbhst);
}
action = KRB5_SENDTO_TIMEOUT;
- fallthrough;
+ HEIM_FALLTHROUGH;
case KRB5_SENDTO_TIMEOUT:
/*
diff --git a/third_party/heimdal/lib/krb5/store.c b/third_party/heimdal/lib/krb5/store.c
index 79f8e3adbab..8b966f83e79 100644
--- a/third_party/heimdal/lib/krb5/store.c
+++ b/third_party/heimdal/lib/krb5/store.c
@@ -1002,6 +1002,8 @@ krb5_ret_string(krb5_storage *sp,
{
int ret;
krb5_data data;
+
+ *string = NULL;
ret = krb5_ret_data(sp, &data);
if(ret)
return ret;
diff --git a/third_party/heimdal/lib/libedit/config.h.in b/third_party/heimdal/lib/libedit/config.h.in
index 059e5abc6a4..a9dbc475598 100644
--- a/third_party/heimdal/lib/libedit/config.h.in
+++ b/third_party/heimdal/lib/libedit/config.h.in
@@ -48,8 +48,8 @@
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
+/* Define to 1 if you have the <minix/config.h> header file. */
+#undef HAVE_MINIX_CONFIG_H
/* Define to 1 if you have the <ncurses.h> header file. */
#undef HAVE_NCURSES_H
@@ -67,6 +67,9 @@
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
@@ -120,6 +123,9 @@
/* Define to 1 if you have the <vfork.h> header file. */
#undef HAVE_VFORK_H
+/* Define to 1 if you have the <wchar.h> header file. */
+#undef HAVE_WCHAR_H
+
/* Define to 1 if you have the `wcsdup' function. */
#undef HAVE_WCSDUP
@@ -160,48 +166,106 @@
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
-/* Define to 1 if you have the ANSI C header files. */
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
#undef STDC_HEADERS
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
+/* Enable general extensions on macOS. */
+#ifndef _DARWIN_C_SOURCE
+# undef _DARWIN_C_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
-/* Enable threading extensions on Solaris. */
+/* Enable X/Open compliant socket functions that do not require linking
+ with -lxnet on HP-UX 11.11. */
+#ifndef _HPUX_ALT_XOPEN_SOCKET_API
+# undef _HPUX_ALT_XOPEN_SOCKET_API
+#endif
+/* Identify the host operating system as Minix.
+ This macro does not affect the system headers' behavior.
+ A future release of Autoconf may stop defining this macro. */
+#ifndef _MINIX
+# undef _MINIX
+#endif
+/* Enable general extensions on NetBSD.
+ Enable NetBSD compatibility extensions on Minix. */
+#ifndef _NETBSD_SOURCE
+# undef _NETBSD_SOURCE
+#endif
+/* Enable OpenBSD compatibility extensions on NetBSD.
+ Oddly enough, this does nothing on OpenBSD. */
+#ifndef _OPENBSD_SOURCE
+# undef _OPENBSD_SOURCE
+#endif
+/* Define to 1 if needed for POSIX-compatible behavior. */
+#ifndef _POSIX_SOURCE
+# undef _POSIX_SOURCE
+#endif
+/* Define to 2 if needed for POSIX-compatible behavior. */
+#ifndef _POSIX_1_SOURCE
+# undef _POSIX_1_SOURCE
+#endif
+/* Enable POSIX-compatible threading on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
+/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
+#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
+# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
+#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
+# undef __STDC_WANT_IEC_60559_BFP_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
+#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
+# undef __STDC_WANT_IEC_60559_DFP_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
+#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
+# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
+#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
+# undef __STDC_WANT_IEC_60559_TYPES_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
+#ifndef __STDC_WANT_LIB_EXT2__
+# undef __STDC_WANT_LIB_EXT2__
+#endif
+/* Enable extensions specified by ISO/IEC 24747:2009. */
+#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
+# undef __STDC_WANT_MATH_SPEC_FUNCS__
+#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
-/* Enable general extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# undef __EXTENSIONS__
+/* Enable X/Open extensions. Define to 500 only if necessary
+ to make mbstate_t available. */
+#ifndef _XOPEN_SOURCE
+# undef _XOPEN_SOURCE
#endif
/* Version number of package */
#undef VERSION
-/* Define to 1 if on MINIX. */
-#undef _MINIX
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
- this defined. */
-#undef _POSIX_1_SOURCE
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-#undef _POSIX_SOURCE
-
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
-/* Define to `int' if <sys/types.h> does not define. */
+/* Define as a signed integer type capable of holding a process identifier. */
#undef pid_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
diff --git a/third_party/heimdal/lib/ntlm/digest.c b/third_party/heimdal/lib/ntlm/digest.c
index 761e1f497fc..42c39ff23e1 100644
--- a/third_party/heimdal/lib/ntlm/digest.c
+++ b/third_party/heimdal/lib/ntlm/digest.c
@@ -471,7 +471,7 @@ heim_digest_generate_challenge(heim_digest_t context)
break;
case HEIM_DIGEST_TYPE_AUTO:
context->type = HEIM_DIGEST_TYPE_RFC2831;
- fallthrough;
+ HEIM_FALLTHROUGH;
case HEIM_DIGEST_TYPE_RFC2831:
asprintf(&challenge, "realm=\"%s\",nonce=\"%s\",qop=\"%s\",algorithm=md5-sess,charset=utf-8,maxbuf=%s",
context->serverRealm, context->serverNonce, context->serverQOP, context->serverMaxbuf);
diff --git a/third_party/heimdal/lib/ntlm/ntlm.c b/third_party/heimdal/lib/ntlm/ntlm.c
index d75752ea000..7384e18076f 100644
--- a/third_party/heimdal/lib/ntlm/ntlm.c
+++ b/third_party/heimdal/lib/ntlm/ntlm.c
@@ -682,7 +682,7 @@ heim_ntlm_decode_type1(const struct ntlm_buf *buf, struct ntlm_type1 *data)
krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE);
CHECK_SIZE(krb5_storage_read(in, sig, sizeof(sig)), sizeof(sig));
- CHECK(memcmp(ntlmsigature, sig, sizeof(ntlmsigature)), 0);
+ CHECK(ct_memcmp(ntlmsigature, sig, sizeof(ntlmsigature)), 0);
CHECK(krb5_ret_uint32(in, &type), 0);
CHECK(type, 1);
CHECK(krb5_ret_uint32(in, &data->flags), 0);
@@ -844,7 +844,7 @@ heim_ntlm_decode_type2(const struct ntlm_buf *buf, struct ntlm_type2 *type2)
krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE);
CHECK_SIZE(krb5_storage_read(in, sig, sizeof(sig)), sizeof(sig));
- CHECK(memcmp(ntlmsigature, sig, sizeof(ntlmsigature)), 0);
+ CHECK(ct_memcmp(ntlmsigature, sig, sizeof(ntlmsigature)), 0);
CHECK(krb5_ret_uint32(in, &type), 0);
CHECK(type, 2);
@@ -1001,7 +1001,7 @@ heim_ntlm_decode_type3(const struct ntlm_buf *buf,
krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE);
CHECK_SIZE(krb5_storage_read(in, sig, sizeof(sig)), sizeof(sig));
- CHECK(memcmp(ntlmsigature, sig, sizeof(ntlmsigature)), 0);
+ CHECK(ct_memcmp(ntlmsigature, sig, sizeof(ntlmsigature)), 0);
CHECK(krb5_ret_uint32(in, &type), 0);
CHECK(type, 3);
CHECK(ret_sec_buffer(in, &lm), 0);
@@ -1825,7 +1825,7 @@ verify_ntlm2(const void *key, size_t len,
if (ret)
goto out;
- if (memcmp(serveranswer, clientanswer, 16) != 0) {
+ if (ct_memcmp(serveranswer, clientanswer, 16) != 0) {
heim_ntlm_free_buf(infotarget);
return HNTLM_ERR_AUTH;
}
diff --git a/third_party/heimdal/lib/otp/otp_verify.c b/third_party/heimdal/lib/otp/otp_verify.c
index 8a1c743cc83..373f9295a5e 100644
--- a/third_party/heimdal/lib/otp/otp_verify.c
+++ b/third_party/heimdal/lib/otp/otp_verify.c
@@ -49,7 +49,7 @@ otp_verify_user_1 (OtpContext *ctx, const char *passwd)
}
memcpy (key2, key1, sizeof(key1));
ctx->alg->next (key2);
- if (memcmp (ctx->key, key2, sizeof(key2)) == 0) {
+ if (ct_memcmp (ctx->key, key2, sizeof(key2)) == 0) {
--ctx->n;
memcpy (ctx->key, key1, sizeof(key1));
return 0;
diff --git a/third_party/heimdal/lib/roken/Makefile.am b/third_party/heimdal/lib/roken/Makefile.am
index 35d753204e7..f6d038f3f6e 100644
--- a/third_party/heimdal/lib/roken/Makefile.am
+++ b/third_party/heimdal/lib/roken/Makefile.am
@@ -201,7 +201,7 @@ libroken_la_LIBADD = @LTLIBOBJS@ $(LIB_crypt) $(LIB_pidfile)
$(LTLIBOBJS) $(libroken_la_OBJECTS): roken.h $(XHEADERS)
-BUILT_SOURCES = roken.h $(err_h) $(fnmatch_h) $(ifadds_h) $(search_h) $(vis_h)
+BUILT_SOURCES = roken.h $(err_h) $(fnmatch_h) $(ifaddrs_h) $(search_h) $(vis_h)
## these are controlled by configure
XHEADERS = $(err_h) $(fnmatch_h) $(ifaddrs_h) $(search_h) $(vis_h)
diff --git a/third_party/heimdal/lib/roken/base32.c b/third_party/heimdal/lib/roken/base32.c
index ef74336d70a..4ec86ae90f1 100644
--- a/third_party/heimdal/lib/roken/base32.c
+++ b/third_party/heimdal/lib/roken/base32.c
@@ -100,10 +100,10 @@ rk_base32_encode(const void *data, int size, char **str, enum rk_base32_flags fl
p[6] = chars[(c & 0x0000000000000003e0ULL) >> 5];
p[7] = chars[(c & 0x00000000000000001fULL) >> 0];
switch (i - size) {
- case 4: p[2] = p[3] = '='; fallthrough;
- case 3: p[4] = '='; fallthrough;
- case 2: p[5] = p[6] = '='; fallthrough;
- case 1: p[7] = '='; fallthrough;
+ case 4: p[2] = p[3] = '='; HEIM_FALLTHROUGH;
+ case 3: p[4] = '='; HEIM_FALLTHROUGH;
+ case 2: p[5] = p[6] = '='; HEIM_FALLTHROUGH;
+ case 1: p[7] = '='; HEIM_FALLTHROUGH;
default: break;
}
p += 8;
diff --git a/third_party/heimdal/lib/roken/dirent-test.c b/third_party/heimdal/lib/roken/dirent-test.c
index dc4518ad5b0..2c6b5055be7 100644
--- a/third_party/heimdal/lib/roken/dirent-test.c
+++ b/third_party/heimdal/lib/roken/dirent-test.c
@@ -148,7 +148,7 @@ int teardown_test(void)
strcmp(dirname + len + 1 - sizeof(TESTDIR)/sizeof(char), TESTDIR) == 0) {
- fallthrough;
+ HEIM_FALLTHROUGH;
} else {
/* did we create the directory? */
@@ -162,7 +162,7 @@ int teardown_test(void)
fprintf(stderr, "Can't change to test directory. Aborting cleanup.\n");
return -1;
} else {
- fallthrough;
+ HEIM_FALLTHROUGH;
}
} else {
return -1;
diff --git a/third_party/heimdal/lib/roken/fnmatch.c b/third_party/heimdal/lib/roken/fnmatch.c
index 74f35283d35..34da19f2cb1 100644
--- a/third_party/heimdal/lib/roken/fnmatch.c
+++ b/third_party/heimdal/lib/roken/fnmatch.c
@@ -129,7 +129,7 @@ rk_fnmatch(const char *pattern, const char *string, int flags)
--pattern;
}
}
- fallthrough;
+ HEIM_FALLTHROUGH;
default:
if (c != *string++)
return (FNM_NOMATCH);
diff --git a/third_party/heimdal/lib/roken/getaddrinfo.c b/third_party/heimdal/lib/roken/getaddrinfo.c
index 12a26a71225..47affba59f5 100644
--- a/third_party/heimdal/lib/roken/getaddrinfo.c
+++ b/third_party/heimdal/lib/roken/getaddrinfo.c
@@ -188,7 +188,7 @@ get_null (const struct addrinfo *hints,
struct addrinfo *first = NULL;
struct addrinfo **current = &first;
int family = PF_UNSPEC;
- int ret;
+ int ret = EAI_FAMILY;
if (hints != NULL)
family = hints->ai_family;
@@ -216,7 +216,7 @@ get_null (const struct addrinfo *hints,
&current, const_v4, &v4_addr, NULL);
}
*res = first;
- return 0;
+ return ret;
}
static int
diff --git a/third_party/heimdal/lib/roken/getuserinfo.c b/third_party/heimdal/lib/roken/getuserinfo.c
index 7fd2ca9f151..09f4c73155a 100644
--- a/third_party/heimdal/lib/roken/getuserinfo.c
+++ b/third_party/heimdal/lib/roken/getuserinfo.c
@@ -136,7 +136,7 @@ roken_get_homedir(char *home, size_t homesz)
}
return home;
}
- fallthrough;
+ HEIM_FALLTHROUGH;
#else
#ifdef HAVE_GETPWNAM_R
size_t buflen = 2048;
diff --git a/third_party/heimdal/lib/roken/parse_units.c b/third_party/heimdal/lib/roken/parse_units.c
index d76578abfe0..017eedf376b 100644
--- a/third_party/heimdal/lib/roken/parse_units.c
+++ b/third_party/heimdal/lib/roken/parse_units.c
@@ -275,8 +275,7 @@ acc_flags(uint64_t res, int64_t val, uint64_t mult)
}
ROKEN_LIB_FUNCTION uint64_t ROKEN_LIB_CALL
-parse_flags (const char *s, const struct units *units,
- int orig)
+parse_flags(const char *s, const struct units *units, uint64_t orig)
{
return parse_something_unsigned (s, units, NULL, acc_flags, orig, 1);
}
diff --git a/third_party/heimdal/lib/roken/parse_units.h b/third_party/heimdal/lib/roken/parse_units.h
index c5b6f2030a8..d17897dda60 100644
--- a/third_party/heimdal/lib/roken/parse_units.h
+++ b/third_party/heimdal/lib/roken/parse_units.h
@@ -97,8 +97,8 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
print_units_table (const struct units *units, FILE *f);
ROKEN_LIB_FUNCTION uint64_t ROKEN_LIB_CALL
-parse_flags (const char *s, const struct units *units,
- int orig);
+parse_flags(const char *s, const struct units *units,
+ uint64_t orig);
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
unparse_units(int64_t num, const struct units *units, char *s, size_t len);
diff --git a/third_party/heimdal/lib/roken/snprintf.c b/third_party/heimdal/lib/roken/snprintf.c
index 3da48962ee3..c8afedb2620 100644
--- a/third_party/heimdal/lib/roken/snprintf.c
+++ b/third_party/heimdal/lib/roken/snprintf.c
@@ -515,7 +515,7 @@ xyzprintf (struct snprintf_state *state, const char *char_format, va_list ap)
}
case '\0' :
--format;
- fallthrough;
+ HEIM_FALLTHROUGH;
case '%' :
(*state->append_char)(state, c);
++len;
diff --git a/third_party/heimdal/lib/roken/strftime.c b/third_party/heimdal/lib/roken/strftime.c
index 9a951dd3008..7be930755ca 100644
--- a/third_party/heimdal/lib/roken/strftime.c
+++ b/third_party/heimdal/lib/roken/strftime.c
@@ -377,7 +377,7 @@ strftime (char *buf, size_t maxsize, const char *format,
break;
case '\0' :
--format;
- fallthrough;
+ HEIM_FALLTHROUGH;
case '%' :
ret = snprintf (buf, maxsize - n,
"%%");
diff --git a/third_party/heimdal/lib/roken/strptime.c b/third_party/heimdal/lib/roken/strptime.c
index 86216d2d6dc..b9345c08323 100644
--- a/third_party/heimdal/lib/roken/strptime.c
+++ b/third_party/heimdal/lib/roken/strptime.c
@@ -424,7 +424,7 @@ strptime (const char *buf, const char *format, struct tm *timeptr)
abort ();
case '\0' :
--format;
- fallthrough;
+ HEIM_FALLTHROUGH;
case '%' :
if (*buf == '%')
++buf;
diff --git a/third_party/heimdal/lib/sl/slc-gram.y b/third_party/heimdal/lib/sl/slc-gram.y
index 38045c10048..eed7fc10f04 100644
--- a/third_party/heimdal/lib/sl/slc-gram.y
+++ b/third_party/heimdal/lib/sl/slc-gram.y
@@ -686,7 +686,7 @@ gen_wrapper(struct assignment *as)
(*th->free)(s);
free(s);
}
- cprint(1, "return 0;\n");
+ cprint(1, "return 1;\n");
cprint(0, "}\n");
cprint(0, "\n");
free(n);
diff --git a/third_party/heimdal/lib/wind/utf8.c b/third_party/heimdal/lib/wind/utf8.c
index 452b7b260d8..4559109f3fd 100644
--- a/third_party/heimdal/lib/wind/utf8.c
+++ b/third_party/heimdal/lib/wind/utf8.c
@@ -205,18 +205,18 @@ wind_ucs4utf8(const uint32_t *in, size_t in_len, char *out, size_t *out_len)
case 4:
out[3] = (ch | 0x80) & 0xbf;
ch = ch >> 6;
- fallthrough;
+ HEIM_FALLTHROUGH;
case 3:
out[2] = (ch | 0x80) & 0xbf;
ch = ch >> 6;
- fallthrough;
+ HEIM_FALLTHROUGH;
case 2:
out[1] = (ch | 0x80) & 0xbf;
ch = ch >> 6;
- fallthrough;
+ HEIM_FALLTHROUGH;
case 1:
out[0] = ch | first_char[len - 1];
- fallthrough;
+ HEIM_FALLTHROUGH;
default:
break;
}
@@ -486,14 +486,14 @@ wind_ucs2utf8(const uint16_t *in, size_t in_len, char *out, size_t *out_len)
case 3:
out[2] = (ch | 0x80) & 0xbf;
ch = ch >> 6;
- fallthrough;
+ HEIM_FALLTHROUGH;
case 2:
out[1] = (ch | 0x80) & 0xbf;
ch = ch >> 6;
- fallthrough;
+ HEIM_FALLTHROUGH;
case 1:
out[0] = ch | first_char[len - 1];
- fallthrough;
+ HEIM_FALLTHROUGH;
default:
break;
}