krb5 commit: Add OSS-Fuzz target for keytab processing
[email protected] Thu, 9 Jul 2026 21:32:56 -0400 (EDT)
| Newsgroups | gmane.comp.encryption.kerberos.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://github.com/krb5/krb5/commit/fa38e2669694ad46816175eb1ac0533d8680e0fc commit fa38e2669694ad46816175eb1ac0533d8680e0fc Author: Arthur Chan <[email protected]> Date: Tue Jun 16 21:21:55 2026 +0100 Add OSS-Fuzz target for keytab processing bigredbutton: whitespace .gitignore | 1 + src/tests/fuzzing/Makefile.in | 6 + src/tests/fuzzing/deps | 10 ++ src/tests/fuzzing/fuzz_keytab.c | 122 +++++++++++++++++++++ .../fuzzing/fuzz_keytab_seed_corpus/v502_one_entry | Bin 0 -> 66 bytes .../fuzzing/fuzz_keytab_seed_corpus/version_0x501 | 1 + .../fuzzing/fuzz_keytab_seed_corpus/version_only | 1 + src/tests/fuzzing/oss-fuzz.sh | 6 +- 8 files changed, 144 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index c7e18066a..e65573f1f 100644 --- a/.gitignore +++ b/.gitignore @@ -444,6 +444,7 @@ local.properties /src/tests/fuzzing/fuzz_gss /src/tests/fuzzing/fuzz_json /src/tests/fuzzing/fuzz_kdc +/src/tests/fuzzing/fuzz_keytab /src/tests/fuzzing/fuzz_krad /src/tests/fuzzing/fuzz_krb /src/tests/fuzzing/fuzz_krb5_ticket diff --git a/src/tests/fuzzing/Makefile.in b/src/tests/fuzzing/Makefile.in index d6aafc17b..03cf91b23 100644 --- a/src/tests/fuzzing/Makefile.in +++ b/src/tests/fuzzing/Makefile.in @@ -18,6 +18,7 @@ OBJS= \ fuzz_gss.o \ fuzz_json.o \ fuzz_kdc.o \ + fuzz_keytab.o \ fuzz_krad.o \ fuzz_krb.o \ fuzz_krb5_ticket.o \ @@ -40,6 +41,7 @@ SRCS= \ $(srcdir)/fuzz_gss.c \ $(srcdir)/fuzz_json.c \ $(srcdir)/fuzz_kdc.c \ + $(srcdir)/fuzz_keytab.c \ $(srcdir)/fuzz_krad.c \ $(srcdir)/fuzz_krb.c \ $(srcdir)/fuzz_krb5_ticket.c \ @@ -62,6 +64,7 @@ FUZZ_TARGETS= \ fuzz_gss \ fuzz_json \ fuzz_kdc \ + fuzz_keytab \ fuzz_krad \ fuzz_krb \ fuzz_krb5_ticket \ @@ -108,6 +111,9 @@ fuzz_json: fuzz_json.o $(KRB5_BASE_DEPLIBS) fuzz_kdc: fuzz_kdc.o $(KRB5_BASE_DEPLIBS) $(CXX_LINK) -o $@ fuzz_kdc.o $(KRB5_BASE_LIBS) $(FUZZ_LDFLAGS) +fuzz_keytab: fuzz_keytab.o $(KRB5_BASE_DEPLIBS) + $(CXX_LINK) -o $@ fuzz_keytab.o $(KRB5_BASE_LIBS) $(FUZZ_LDFLAGS) + fuzz_krad: fuzz_krad.o $(KRB5_BASE_DEPLIBS) $(CXX_LINK) -o $@ fuzz_krad.o -lkrad $(KRB5_BASE_LIBS) $(FUZZ_LDFLAGS) diff --git a/src/tests/fuzzing/deps b/src/tests/fuzzing/deps index 539d4fd2e..c3fd60911 100644 --- a/src/tests/fuzzing/deps +++ b/src/tests/fuzzing/deps @@ -115,6 +115,16 @@ $(OUTPRE)fuzz_kdc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ fuzz_kdc.c +$(OUTPRE)fuzz_keytab.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h fuzz_keytab.c $(OUTPRE)fuzz_krad.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ diff --git a/src/tests/fuzzing/fuzz_keytab.c b/src/tests/fuzzing/fuzz_keytab.c new file mode 100644 index 000000000..da78bc9c6 --- /dev/null +++ b/src/tests/fuzzing/fuzz_keytab.c @@ -0,0 +1,122 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/fuzzing/fuzz_keytab.c - fuzzing harness for the FILE keytab parser */ +/* + * Copyright (C) 2026 by Arthur Chan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This harness fuzzes the FILE keytab parser in lib/krb5/keytab/kt_file.c. + * The fuzz input is written verbatim to a temporary file, which is then + * resolved as a "FILE:" keytab and read back; then each entry is iterated to + * drive the parsing code (version header, and per-entry principal, key and + * metadata unmarshalling). + */ + +#include <k5-int.h> + +#define kMinInputLength 2 +#define kMaxInputLength 4096 + +extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +/* krb5_init_context is expensive, so create the context once and reuse it. */ +static krb5_context +get_context(void) +{ + static krb5_context context = NULL; + static int initialized = 0; + + if (!initialized) { + initialized = 1; + if (krb5_init_context(&context) != 0) + context = NULL; + } + return context; +} + +/* Iterate over every entry in the keytab to exercise the parser. */ +static void +iterate_entries(krb5_context context, krb5_keytab keytab) +{ + krb5_error_code ret; + krb5_kt_cursor cursor; + krb5_keytab_entry entry; + + ret = krb5_kt_start_seq_get(context, keytab, &cursor); + if (ret) + return; + + while (krb5_kt_next_entry(context, keytab, &entry, &cursor) == 0) + krb5_free_keytab_entry_contents(context, &entry); + + krb5_kt_end_seq_get(context, keytab, &cursor); +} + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + krb5_error_code ret; + krb5_context context; + krb5_keytab keytab; + char tmpl[] = "/tmp/fuzz_keytab.XXXXXX"; + char name[64]; + int fd; + + if (size < kMinInputLength || size > kMaxInputLength) + return 0; + + context = get_context(); + if (context == NULL) + return 0; + + /* Write the fuzz input to a temporary file. */ + fd = mkstemp(tmpl); + if (fd < 0) + return 0; + if (write(fd, data, size) != (ssize_t)size) { + close(fd); + unlink(tmpl); + return 0; + } + close(fd); + + snprintf(name, sizeof(name), "FILE:%s", tmpl); + + ret = krb5_kt_resolve(context, name, &keytab); + if (ret) { + unlink(tmpl); + return 0; + } + + iterate_entries(context, keytab); + + krb5_kt_close(context, keytab); + unlink(tmpl); + + return 0; +} diff --git a/src/tests/fuzzing/fuzz_keytab_seed_corpus/v502_one_entry b/src/tests/fuzzing/fuzz_keytab_seed_corpus/v502_one_entry new file mode 100644 index 000000000..7ed964d63 Binary files /dev/null and b/src/tests/fuzzing/fuzz_keytab_seed_corpus/v502_one_entry differ diff --git a/src/tests/fuzzing/fuzz_keytab_seed_corpus/version_0x501 b/src/tests/fuzzing/fuzz_keytab_seed_corpus/version_0x501 new file mode 100644 index 000000000..f635acf9b --- /dev/null +++ b/src/tests/fuzzing/fuzz_keytab_seed_corpus/version_0x501 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/tests/fuzzing/fuzz_keytab_seed_corpus/version_only b/src/tests/fuzzing/fuzz_keytab_seed_corpus/version_only new file mode 100644 index 000000000..2e2a96a3a --- /dev/null +++ b/src/tests/fuzzing/fuzz_keytab_seed_corpus/version_only @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/tests/fuzzing/oss-fuzz.sh b/src/tests/fuzzing/oss-fuzz.sh index 313adfc53..95d389145 100644 --- a/src/tests/fuzzing/oss-fuzz.sh +++ b/src/tests/fuzzing/oss-fuzz.sh @@ -17,9 +17,9 @@ pushd src/tests/fuzzing fuzzers=("fuzz_aes" "fuzz_asn" "fuzz_attrset" "fuzz_ccache" "fuzz_chpw" "fuzz_crypto" "fuzz_des" "fuzz_gss" "fuzz_json" "fuzz_kdc" - "fuzz_krad" "fuzz_krb" "fuzz_krb5_ticket" "fuzz_marshal_cred" - "fuzz_marshal_princ" "fuzz_ndr" "fuzz_oid" "fuzz_pac" "fuzz_profile" - "fuzz_util") + "fuzz_keytab" "fuzz_krad" "fuzz_krb" "fuzz_krb5_ticket" + "fuzz_marshal_cred" "fuzz_marshal_princ" "fuzz_ndr" "fuzz_oid" + "fuzz_pac" "fuzz_profile" "fuzz_util") for fuzzer in "${fuzzers[@]}"; do cp "$fuzzer" "$OUT/$fuzzer"