krb5 commit: Add coverage to existing OSS-Fuzz targets

ghudson at mit.edu ghudson at mit.edu
Tue Nov 5 10:50:14 EST 2024


https://github.com/krb5/krb5/commit/7cc16a52b4ea68939da6407ed66914a792441463
commit 7cc16a52b4ea68939da6407ed66914a792441463
Author: Arjun <pkillarjun at protonmail.com>
Date:   Mon Sep 30 17:14:10 2024 +0530

    Add coverage to existing OSS-Fuzz targets
    
    Also fix the dependencies of fuzz_chpw, remove NDROBJ from Makefile in
    favor of including ndr.c from fuzz_ndr.c, and add one new corpus for
    fuzz_gss.
    
    [ghudson at mit.edu: added initializers to variables used in cleanup
    handlers; edited commit message]

 src/tests/fuzzing/Makefile.in                      |   7 ++--
 src/tests/fuzzing/deps                             |  37 ++++++++++---------
 .../fuzzing/fuzz_gss_seed_corpus/realm_query.bin   | Bin 0 -> 18 bytes
 src/tests/fuzzing/fuzz_json.c                      |  13 +++++--
 src/tests/fuzzing/fuzz_krb5_ticket.c               |  28 ++++++++++++---
 src/tests/fuzzing/fuzz_marshal_cred.c              |  19 +++++-----
 src/tests/fuzzing/fuzz_marshal_princ.c             |  19 +++++-----
 src/tests/fuzzing/fuzz_ndr.c                       |  14 ++++++--
 src/tests/fuzzing/fuzz_pac.c                       |  37 +++++++++++++++++--
 src/tests/fuzzing/fuzz_profile.c                   |  12 +++++--
 src/tests/fuzzing/fuzz_util.c                      |  39 +++++++++++++++++++++
 11 files changed, 171 insertions(+), 54 deletions(-)

diff --git a/src/tests/fuzzing/Makefile.in b/src/tests/fuzzing/Makefile.in
index 05dea371e..2ab3108b1 100644
--- a/src/tests/fuzzing/Makefile.in
+++ b/src/tests/fuzzing/Makefile.in
@@ -2,8 +2,7 @@ mydir=tests$(S)fuzzing
 BUILDTOP=$(REL)..$(S)..
 
 LOCALINCLUDES = -I$(srcdir)/../../lib/krb5/ccache -I$(srcdir)/../../kdc \
-	-I$(srcdir)/../../util/profile
-NDROBJ = $(BUILDTOP)/kdc/ndr.o
+	-I$(srcdir)/../../util/profile -I$(srcdir)/../../util/support
 
 OBJS = \
 	fuzz_chpw.o \
@@ -49,7 +48,7 @@ all: $(FUZZ_TARGETS)
 # OSS-Fuzz requires fuzz targets to be linked with the C++ linker,
 # even if they are written in C.
 
-fuzz_chpw: fuzz_chpw.o $(SUPPORT_DEPLIB)
+fuzz_chpw: fuzz_chpw.o $(KRB5_BASE_DEPLIBS)
 	$(CXX_LINK) -o $@ fuzz_chpw.o $(KRB5_BASE_LIBS) $(FUZZ_LDFLAGS)
 
 fuzz_gss: fuzz_gss.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
@@ -71,7 +70,7 @@ fuzz_marshal_princ: fuzz_marshal_princ.o $(KRB5_BASE_DEPLIBS)
 	$(CXX_LINK) -o $@ fuzz_marshal_princ.o $(KRB5_BASE_LIBS) $(FUZZ_LDFLAGS)
 
 fuzz_ndr: fuzz_ndr.o $(KRB5_BASE_DEPLIBS)
-	$(CXX_LINK) -o $@ fuzz_ndr.o $(NDROBJ) $(KRB5_BASE_LIBS) $(FUZZ_LDFLAGS)
+	$(CXX_LINK) -o $@ fuzz_ndr.o $(KRB5_BASE_LIBS) $(FUZZ_LDFLAGS)
 
 fuzz_pac: fuzz_pac.o $(KRB5_BASE_DEPLIBS)
 	$(CXX_LINK) -o $@ fuzz_pac.o $(KRB5_BASE_LIBS) $(FUZZ_LDFLAGS)
diff --git a/src/tests/fuzzing/deps b/src/tests/fuzzing/deps
index 018fb4ed0..507645a48 100644
--- a/src/tests/fuzzing/deps
+++ b/src/tests/fuzzing/deps
@@ -73,22 +73,23 @@ $(OUTPRE)fuzz_ndr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \
-  $(srcdir)/../../kdc/kdc_util.h $(srcdir)/../../kdc/realm_data.h \
-  $(srcdir)/../../kdc/reqstate.h $(top_srcdir)/include/gssrpc/auth.h \
-  $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \
-  $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \
-  $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \
-  $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \
-  $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \
-  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+  $(srcdir)/../../kdc/kdc_util.h $(srcdir)/../../kdc/ndr.c \
+  $(srcdir)/../../kdc/realm_data.h $(srcdir)/../../kdc/reqstate.h \
+  $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \
+  $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \
+  $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \
+  $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \
+  $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-input.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/kdb.h $(top_srcdir)/include/krb5.h \
-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.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_ndr.c
+  $(top_srcdir)/include/k5-utf8.h $(top_srcdir)/include/kdb.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/kdcpreauth_plugin.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_ndr.c
 $(OUTPRE)fuzz_pac.$(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 \
@@ -106,12 +107,14 @@ $(OUTPRE)fuzz_profile.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   fuzz_profile.c
 $(OUTPRE)fuzz_util.$(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-base64.h \
-  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-hex.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../util/support/hashtab.c \
+  $(top_srcdir)/include/k5-base64.h $(top_srcdir)/include/k5-buf.h \
+  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+  $(top_srcdir)/include/k5-hashtab.h $(top_srcdir)/include/k5-hex.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/k5-queue.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.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_util.c
diff --git a/src/tests/fuzzing/fuzz_gss_seed_corpus/realm_query.bin b/src/tests/fuzzing/fuzz_gss_seed_corpus/realm_query.bin
new file mode 100644
index 000000000..2178d65a0
Binary files /dev/null and b/src/tests/fuzzing/fuzz_gss_seed_corpus/realm_query.bin differ
diff --git a/src/tests/fuzzing/fuzz_json.c b/src/tests/fuzzing/fuzz_json.c
index 0d970125e..a3440eaef 100644
--- a/src/tests/fuzzing/fuzz_json.c
+++ b/src/tests/fuzzing/fuzz_json.c
@@ -48,8 +48,8 @@ int
 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
     krb5_error_code ret;
-    char *data_in;
-    k5_json_value decoded;
+    k5_json_value decoded = NULL;
+    char *data_in = NULL, *data_out;
 
     if (size < kMinInputLength || size > kMaxInputLength)
         return 0;
@@ -58,8 +58,15 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     if (data_in == NULL)
         return 0;
 
-    k5_json_decode(data_in, &decoded);
+    ret = k5_json_decode(data_in, &decoded);
+    if (ret)
+        goto cleanup;
 
+    ret = k5_json_encode(decoded, &data_out);
+    if (!ret)
+        free(data_out);
+
+cleanup:
     free(data_in);
     k5_json_release(decoded);
 
diff --git a/src/tests/fuzzing/fuzz_krb5_ticket.c b/src/tests/fuzzing/fuzz_krb5_ticket.c
index a88f75314..0b541f444 100644
--- a/src/tests/fuzzing/fuzz_krb5_ticket.c
+++ b/src/tests/fuzzing/fuzz_krb5_ticket.c
@@ -46,21 +46,39 @@ extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 int
 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
-    krb5_data data_in;
-    krb5_ticket *ticket;
-    krb5_context context;
+    krb5_error_code ret;
+    krb5_context context = NULL;
+    krb5_keytab defkt = NULL;
+    krb5_data data_in, *data_out;
+    krb5_ticket *ticket = NULL;
 
     if (size < kMinInputLength || size > kMaxInputLength)
         return 0;
 
     data_in = make_data((void *)data, size);
 
-    if (krb5_init_context(&context) != 0)
+    ret = krb5_init_context(&context);
+    if (ret)
         return 0;
 
-    krb5_decode_ticket(&data_in, &ticket);
+    ret = krb5_kt_default(context, &defkt);
+    if (ret)
+        goto cleanup;
 
+    ret = krb5_decode_ticket(&data_in, &ticket);
+    if (ret)
+        goto cleanup;
+
+    ret = encode_krb5_ticket(ticket, &data_out);
+    if (!ret)
+        krb5_free_data(context, data_out);
+
+    krb5_server_decrypt_ticket_keytab(context, defkt, ticket);
+
+cleanup:
     krb5_free_ticket(context, ticket);
+    if (defkt != NULL)
+        krb5_kt_close(context, defkt);
     krb5_free_context(context);
 
     return 0;
diff --git a/src/tests/fuzzing/fuzz_marshal_cred.c b/src/tests/fuzzing/fuzz_marshal_cred.c
index 7181ab9a7..07b130a83 100644
--- a/src/tests/fuzzing/fuzz_marshal_cred.c
+++ b/src/tests/fuzzing/fuzz_marshal_cred.c
@@ -46,21 +46,24 @@ extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 int
 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
+    krb5_error_code ret;
+    krb5_creds cred;
     int version;
-    krb5_creds cred = { 0 };
-    krb5_context context;
+    struct k5buf buf;
 
     if (size < kMinInputLength || size > kMaxInputLength)
         return 0;
 
-    if (krb5_init_context(&context) != 0)
-        return 0;
-
     for (version = FIRST_VERSION; version <= 4; version++) {
-        k5_unmarshal_cred(data, size, version, &cred);
-        krb5_free_cred_contents(context, &cred);
+        ret = k5_unmarshal_cred(data, size, version, &cred);
+        if (!ret) {
+            k5_buf_init_dynamic(&buf);
+            k5_marshal_cred(&buf, version, &cred);
+            k5_buf_free(&buf);
+        }
+
+        krb5_free_cred_contents(NULL, &cred);
     }
 
-    krb5_free_context(context);
     return 0;
 }
diff --git a/src/tests/fuzzing/fuzz_marshal_princ.c b/src/tests/fuzzing/fuzz_marshal_princ.c
index e421ff305..b41fd6269 100644
--- a/src/tests/fuzzing/fuzz_marshal_princ.c
+++ b/src/tests/fuzzing/fuzz_marshal_princ.c
@@ -46,21 +46,24 @@ extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 int
 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
-    int version;
+    krb5_error_code ret;
     krb5_principal princ;
-    krb5_context context;
+    int version;
+    struct k5buf buf;
 
     if (size < kMinInputLength || size > kMaxInputLength)
         return 0;
 
-    if (krb5_init_context(&context) != 0)
-        return 0;
-
     for (version = FIRST_VERSION; version <= 4; version++) {
-        k5_unmarshal_princ(data, size, version, &princ);
-        krb5_free_principal(context, princ);
+        ret = k5_unmarshal_princ(data, size, version, &princ);
+        if (!ret) {
+            k5_buf_init_dynamic(&buf);
+            k5_marshal_princ(&buf, version, princ);
+            k5_buf_free(&buf);
+        }
+
+        krb5_free_principal(NULL, princ);
     }
 
-    krb5_free_context(context);
     return 0;
 }
diff --git a/src/tests/fuzzing/fuzz_ndr.c b/src/tests/fuzzing/fuzz_ndr.c
index 4cc6daa1c..7692bace7 100644
--- a/src/tests/fuzzing/fuzz_ndr.c
+++ b/src/tests/fuzzing/fuzz_ndr.c
@@ -37,6 +37,8 @@
 #include <k5-int.h>
 #include <kdc_util.h>
 
+#include <ndr.c>
+
 #define kMinInputLength 2
 #define kMaxInputLength 1024
 
@@ -45,15 +47,21 @@ extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 int
 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
-    krb5_data data_in;
-    struct pac_s4u_delegation_info *di = NULL;
+    krb5_error_code ret;
+    krb5_data data_in, data_out = empty_data();
+    struct pac_s4u_delegation_info *di;
 
     if (size < kMinInputLength || size > kMaxInputLength)
         return 0;
 
     data_in = make_data((void *)data, size);
-    ndr_dec_delegation_info(&data_in, &di);
+
+    ret = ndr_dec_delegation_info(&data_in, &di);
+    if (!ret)
+        (void)ndr_enc_delegation_info(di, &data_out);
+
     ndr_free_delegation_info(di);
+    krb5_free_data_contents(NULL, &data_out);
 
     return 0;
 }
diff --git a/src/tests/fuzzing/fuzz_pac.c b/src/tests/fuzzing/fuzz_pac.c
index f9f5635f4..38488420e 100644
--- a/src/tests/fuzzing/fuzz_pac.c
+++ b/src/tests/fuzzing/fuzz_pac.c
@@ -36,26 +36,57 @@
 #include "autoconf.h"
 #include <k5-int.h>
 
+#define U(x) (uint8_t *)x
 #define kMinInputLength 2
 #define kMaxInputLength 1024
 
+static const krb5_keyblock kdc_keyblock = {
+    0, ENCTYPE_ARCFOUR_HMAC,
+    16, U("\xB2\x86\x75\x71\x48\xAF\x7F\xD2\x52\xC5\x36\x03\xA1\x50\xB7\xE7")
+};
+
+static const krb5_keyblock member_keyblock = {
+    0, ENCTYPE_ARCFOUR_HMAC,
+    16, U("\xD2\x17\xFA\xEA\xE5\xE6\xB5\xF9\x5C\xCC\x94\x07\x7A\xB8\xA5\xFC")
+};
+
+static time_t authtime = 1120440609;
+static const char *user = "w2003final$@WIN2K3.THINKER.LOCAL";
+
 extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 
 int
 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
+    krb5_error_code ret;
+    krb5_context context = NULL;
     krb5_pac pac;
-    krb5_context context;
+    krb5_principal princ = NULL;
 
     if (size < kMinInputLength || size > kMaxInputLength)
         return 0;
 
-    if (krb5_init_context(&context) != 0)
+    ret = krb5_init_context(&context);
+    if (ret)
         return 0;
 
-    krb5_pac_parse(context, data, size, &pac);
+    ret = krb5_parse_name(context, user, &princ);
+    if (ret)
+        goto cleanup;
+
+    ret = krb5_pac_parse(context, data, size, &pac);
+    if (ret)
+        goto cleanup;
+
+    krb5_pac_verify(context, pac, authtime, princ, NULL, NULL);
+    krb5_pac_verify_ext(context, pac, authtime, princ, NULL, NULL, TRUE);
+    krb5_pac_verify(context, pac, authtime, princ, &member_keyblock,
+                    &kdc_keyblock);
 
     krb5_pac_free(context, pac);
+
+cleanup:
+    krb5_free_principal(context, princ);
     krb5_free_context(context);
 
     return 0;
diff --git a/src/tests/fuzzing/fuzz_profile.c b/src/tests/fuzzing/fuzz_profile.c
index 95a5b488d..e62decf7b 100644
--- a/src/tests/fuzzing/fuzz_profile.c
+++ b/src/tests/fuzzing/fuzz_profile.c
@@ -46,8 +46,9 @@ extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 int
 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
+    errcode_t ret;
     FILE *fp_w, *fp_r;
-    char file_name[256];
+    char file_name[256], *output;
     struct profile_node *root;
 
     if (size < kMinInputLength || size > kMaxInputLength)
@@ -55,7 +56,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 
     snprintf(file_name, sizeof(file_name), "/tmp/libfuzzer.%d", getpid());
 
-    /* Write data into the file.*/
+    /* Write data into the file. */
     fp_w = fopen(file_name, "w");
     if (!fp_w)
         return 1;
@@ -69,7 +70,12 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 
     initialize_prof_error_table();
 
-    if (profile_parse_file(fp_r, &root, NULL) == 0) {
+    ret = profile_parse_file(fp_r, &root, NULL);
+    if (!ret) {
+        ret = profile_write_tree_to_buffer(root, &output);
+        if (!ret)
+            free(output);
+
         profile_verify_node(root);
         profile_free_node(root);
     }
diff --git a/src/tests/fuzzing/fuzz_util.c b/src/tests/fuzzing/fuzz_util.c
index 8779b4c61..91641ad1c 100644
--- a/src/tests/fuzzing/fuzz_util.c
+++ b/src/tests/fuzzing/fuzz_util.c
@@ -39,6 +39,9 @@
 #include <k5-base64.h>
 #include <k5-hex.h>
 #include <string.h>
+#include <k5-utf8.h>
+
+#include <hashtab.c>
 
 #define kMinInputLength 2
 #define kMaxInputLength 256
@@ -54,6 +57,21 @@ fuzz_base64(const char *data_in, size_t size)
     free(k5_base64_decode(data_in, &len));
 }
 
+static void
+fuzz_hashtab(const char *data_in, size_t size)
+{
+    int st;
+    struct k5_hashtab *ht;
+
+    k5_hashtab_create(NULL, 4, &ht);
+    if (ht == NULL)
+        return;
+
+    k5_hashtab_add(ht, data_in, size, &st);
+
+    k5_hashtab_free(ht);
+}
+
 static void
 fuzz_hex(const char *data_in, size_t size)
 {
@@ -96,6 +114,25 @@ fuzz_parse_host(const char *data_in, size_t size)
         free(host_out);
 }
 
+static void
+fuzz_utf8(const char *data_in, size_t size)
+{
+    krb5_ucs4 u = 0;
+    char *utf8;
+    uint8_t *utf16;
+    size_t utf16len;
+
+    krb5int_utf8_to_ucs4(data_in, &u);
+
+    k5_utf8_to_utf16le(data_in, &utf16, &utf16len);
+    if (utf16 != NULL)
+        free(utf16);
+
+    k5_utf16le_to_utf8((const uint8_t *)data_in, size, &utf8);
+    if (utf8 != NULL)
+        free(utf8);
+}
+
 extern int
 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
@@ -110,9 +147,11 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
         return 0;
 
     fuzz_base64(data_in, size);
+    fuzz_hashtab(data_in, size);
     fuzz_hex(data_in, size);
     fuzz_name(data_in, size);
     fuzz_parse_host(data_in, size);
+    fuzz_utf8(data_in, size);
 
     free(data_in);
 


More information about the cvs-krb5 mailing list