Blame SOURCES/sudo-1.8.6p7-digest-backport.patch

0e1944
From c8a6eecf768d8102a9a77f5fdb5b516e571d462e Mon Sep 17 00:00:00 2001
0e1944
From: Radovan Sroka <rsroka@redhat.com>
0e1944
Date: Tue, 23 Aug 2016 13:43:08 +0200
0e1944
Subject: [PATCH] Using libgcrypt
0e1944
0e1944
Using libgcrypt and not sudo implementation of SHA...
0e1944
0e1944
Rebased patch of digest backport.
0e1944
Added option --with-gcrypt
0e1944
0e1944
Rebased from:
0e1944
Patch35: sudo-1.8.6p7-digest-backport.patch
0e1944
0e1944
Resolves:
0e1944
rhbz#1183818
0e1944
---
0e1944
 configure.ac                 |  16 +++++++
0e1944
 plugins/sudoers/Makefile.in  |   9 +++-
0e1944
 plugins/sudoers/filedigest.c | 104 +++++++++++++++++++++++++++++++++++++++++++
0e1944
 plugins/sudoers/filedigest.h |  17 +++++++
0e1944
 plugins/sudoers/match.c      |  94 ++++++++++++++++++++++++++++++--------
0e1944
 5 files changed, 219 insertions(+), 21 deletions(-)
0e1944
 create mode 100644 plugins/sudoers/filedigest.c
0e1944
 create mode 100644 plugins/sudoers/filedigest.h
0e1944
0e1944
diff --git a/configure.ac b/configure.ac
0e1944
index 13c3c1b..54929b2 100644
0e1944
--- a/configure.ac
0e1944
+++ b/configure.ac
0e1944
@@ -35,6 +35,7 @@ AC_SUBST([SUDO_OBJS])
72fdaf
 AC_SUBST([LIBS])
72fdaf
 AC_SUBST([SUDO_LIBS])
72fdaf
 AC_SUBST([SUDOERS_LIBS])
72fdaf
+AC_SUBST([LIBPARSESUDOERS_LIBS])
0e1944
 AC_SUBST([STATIC_SUDOERS])
72fdaf
 AC_SUBST([NET_LIBS])
72fdaf
 AC_SUBST([AFS_LIBS])
0e1944
@@ -1517,6 +1518,19 @@ AC_ARG_WITH(selinux, [AS_HELP_STRING([--with-selinux], [enable SELinux support])
72fdaf
 		;;
0e1944
 esac], [with_selinux=no])
72fdaf
 
72fdaf
+AC_ARG_WITH(gcrypt, [AS_HELP_STRING([--with-gcrypt], [enable libgcrypt support])],
72fdaf
+[case $with_gcrypt in
72fdaf
+    yes)
0e1944
+               AC_DEFINE(HAVE_LIBGCRYPT)
0e1944
+               LIBPARSESUDOERS_LIBS="${LIBPARSESUDOERS_LIBS} -lgcrypt"
0e1944
+               AC_CHECK_LIB([gcrypt], [gcry_md_open],
0e1944
+                   [AC_DEFINE(HAVE_GCRY_MD_OPEN)])
0e1944
+               ;;
0e1944
+    no)                ;;
0e1944
+    *)         AC_MSG_ERROR(["--with-gcrypt does not take an argument."])
0e1944
+               ;;
72fdaf
+esac])
72fdaf
+
72fdaf
 dnl
72fdaf
 dnl gss_krb5_ccache_name() may not work on Heimdal so we don't use it by default
72fdaf
 dnl
0e1944
@@ -4344,6 +4358,8 @@ AH_TEMPLATE(HAVE_PROJECT_H, [Define to 1 if you have the <project.h> header file
72fdaf
 AH_TEMPLATE(HAVE_SECURID, [Define to 1 if you use SecurID for authentication.])
72fdaf
 AH_TEMPLATE(HAVE_SELINUX, [Define to 1 to enable SELinux RBAC support.])
72fdaf
 AH_TEMPLATE(HAVE_SETKEYCREATECON, [Define to 1 if you have the `setkeycreatecon' function.])
72fdaf
+AH_TEMPLATE(HAVE_LIBGCRYPT, [Define to 1 to enable libgcrypt support.])
72fdaf
+AH_TEMPLATE(HAVE_GCRY_MD_OPEN, [Define to 1 if you have the `gcry_md_open' function.])
72fdaf
 AH_TEMPLATE(HAVE_SHL_LOAD, [Define to 1 if you have the `shl_load' function.])
72fdaf
 AH_TEMPLATE(HAVE_SKEY, [Define to 1 if you use S/Key.])
72fdaf
 AH_TEMPLATE(HAVE_SKEYACCESS, [Define to 1 if your S/Key library has skeyaccess().])
0e1944
diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in
0e1944
index f36f9ef..32c0ed0 100644
0e1944
--- a/plugins/sudoers/Makefile.in
0e1944
+++ b/plugins/sudoers/Makefile.in
0e1944
@@ -55,6 +55,7 @@ LT_LIBS = $(top_builddir)/lib/util/libsudo_util.la
0e1944
 LIBS = $(LT_LIBS)
0e1944
 NET_LIBS = @NET_LIBS@
0e1944
 SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ $(LIBS) $(NET_LIBS) @ZLIB@ @LIBMD@
0e1944
+LIBPARSESUDOERS_LIBS = @LIBPARSESUDOERS_LIBS@
0e1944
 REPLAY_LIBS = @REPLAY_LIBS@ @ZLIB@
0e1944
 VISUDO_LIBS = $(NET_LIBS) @LIBMD@
0e1944
 TESTSUDOERS_LIBS = $(NET_LIBS) @LIBMD@
0e1944
@@ -153,7 +154,7 @@ AUTH_OBJS = sudo_auth.lo @AUTH_OBJS@
0e1944
 LIBPARSESUDOERS_OBJS = alias.lo audit.lo base64.lo defaults.lo hexchar.lo \
0e1944
 		       gram.lo match.lo match_addr.lo pwutil.lo pwutil_impl.lo \
0e1944
 		       rcstr.lo redblack.lo sudoers_debug.lo timestr.lo \
0e1944
-		       toke.lo toke_util.lo
0e1944
+		       toke.lo toke_util.lo filedigest.lo
0e1944
 
0e1944
 SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo editor.lo env.lo find_path.lo \
0e1944
 	       gc.lo goodpath.lo group_plugin.lo interfaces.lo iolog.lo \
0e1944
@@ -217,7 +218,7 @@ Makefile: $(srcdir)/Makefile.in
0e1944
 	(cd $(top_builddir) && ./config.status --file plugins/sudoers/Makefile)
0e1944
 
0e1944
 libparsesudoers.la: $(LIBPARSESUDOERS_OBJS)
0e1944
-	$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBPARSESUDOERS_OBJS) -no-install
0e1944
+	$(LIBTOOL) --mode=link $(CC) -o $@ $(LIBPARSESUDOERS_OBJS) $(LIBPARSESUDOERS_LIBS) -no-install
0e1944
 
0e1944
 sudoers.la: $(SUDOERS_OBJS) $(LT_LIBS) libparsesudoers.la @LT_LDDEP@
0e1944
 	case "$(LT_LDFLAGS)" in \
0e1944
@@ -656,6 +657,10 @@ env.lo: $(srcdir)/env.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
0e1944
         $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
0e1944
         $(top_builddir)/pathnames.h
0e1944
 	$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/env.c
0e1944
+filedigest.lo: $(srcdir)/filedigest.c $(top_builddir)/config.h \
0e1944
+        $(incdir)/sudo_debug.h
0e1944
+	$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/filedigest.c
0e1944
+filedigest.o: filedigest.lo
0e1944
 find_path.lo: $(srcdir)/find_path.c $(devdir)/def_data.h \
0e1944
               $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
0e1944
               $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
0e1944
diff --git a/plugins/sudoers/filedigest.c b/plugins/sudoers/filedigest.c
0e1944
new file mode 100644
0e1944
index 0000000..c173741
0e1944
--- /dev/null
0e1944
+++ b/plugins/sudoers/filedigest.c
0e1944
@@ -0,0 +1,104 @@
72fdaf
+#include <config.h>
72fdaf
+#include <errno.h>
72fdaf
+#include <stddef.h>
72fdaf
+#include <sys/types.h>
72fdaf
+#include <sys/stat.h>
72fdaf
+#include <fcntl.h>
72fdaf
+#include <unistd.h>
72fdaf
+#include "filedigest.h"
0e1944
+#include "sudo_compat.h"
72fdaf
+#include "sudo_debug.h"
72fdaf
+
72fdaf
+#if defined(HAVE_LIBGCRYPT)
72fdaf
+#include <gcrypt.h>
72fdaf
+
72fdaf
+static int sudo_filedigest_gcrypt(int fd, int algo, unsigned char **dvalue, size_t *dvalue_size)
72fdaf
+{
72fdaf
+  char buffer[4096];
72fdaf
+  gcry_md_hd_t ctx;
72fdaf
+  int gcry_algo;
72fdaf
+  debug_decl(sudo_filedigest_gcrypt, SUDO_DEBUG_UTIL);
72fdaf
+
72fdaf
+  switch(algo) {
72fdaf
+  case SUDO_DIGEST_SHA224:
72fdaf
+    gcry_algo = GCRY_MD_SHA224; break;
72fdaf
+  case SUDO_DIGEST_SHA256:
72fdaf
+    gcry_algo = GCRY_MD_SHA256; break;
72fdaf
+  case SUDO_DIGEST_SHA384:
72fdaf
+    gcry_algo = GCRY_MD_SHA384; break;
72fdaf
+  case SUDO_DIGEST_SHA512:
72fdaf
+    gcry_algo = GCRY_MD_SHA512; break;
72fdaf
+  default:
72fdaf
+    debug_return_int(-1);
72fdaf
+  }
72fdaf
+
72fdaf
+  gcry_md_open(&ctx, gcry_algo, 0);
72fdaf
+
72fdaf
+  /* Read block of data from fd and digest them */
72fdaf
+  while (1) {
72fdaf
+    const ssize_t read_bytes = read(fd, buffer, sizeof buffer);
72fdaf
+
72fdaf
+    if (read_bytes < 0) {
72fdaf
+      /* Error */
72fdaf
+      gcry_md_close(ctx);
72fdaf
+      debug_return_int(-1);
72fdaf
+    }
72fdaf
+    else if (read_bytes > 0) {
72fdaf
+      /* Some data read -- update the digest */
72fdaf
+      gcry_md_write(ctx, buffer, (size_t)read_bytes);
72fdaf
+    }
72fdaf
+    else {
72fdaf
+      /* EOF */
72fdaf
+      break;
72fdaf
+    }
72fdaf
+  }
72fdaf
+
72fdaf
+  /*
72fdaf
+   * All data digested. Finalize the digest value.
72fdaf
+   */
72fdaf
+  const unsigned char *value = gcry_md_read(ctx, gcry_algo);
72fdaf
+
72fdaf
+  if (value == NULL) {
72fdaf
+    debug_return_int(-1);
72fdaf
+  }
72fdaf
+
72fdaf
+  /*
72fdaf
+   * Make a copy of the digest value. The pointer
72fdaf
+   * returned from gcry_md_read cannot be used after
72fdaf
+   * gcry_md_close was called
72fdaf
+   */
72fdaf
+  (*dvalue_size) = gcry_md_get_algo_dlen(gcry_algo);
0e1944
+  (*dvalue) = malloc(*dvalue_size);
72fdaf
+
72fdaf
+  if (*dvalue == NULL) {
72fdaf
+    debug_return_int(-1);
72fdaf
+  }
72fdaf
+
72fdaf
+  memcpy(*dvalue, value, *dvalue_size);
72fdaf
+  gcry_md_close(ctx);
72fdaf
+
72fdaf
+  debug_return_int(0);
72fdaf
+}
72fdaf
+#endif
72fdaf
+
72fdaf
+#include <stdio.h>
72fdaf
+
72fdaf
+int sudo_filedigest(const char *path, int algo, unsigned char **dvalue, size_t *dvalue_size)
72fdaf
+{
72fdaf
+  int rc = -1;
72fdaf
+  int fd = -1;
72fdaf
+  debug_decl(sudo_filedigest, SUDO_DEBUG_UTIL);
72fdaf
+
72fdaf
+  if ((fd = open(path, O_RDONLY)) < 0) {
72fdaf
+    debug_return_int(rc);
72fdaf
+  }
72fdaf
+
72fdaf
+#if defined(HAVE_LIBGCRYPT)
72fdaf
+  rc = sudo_filedigest_gcrypt(fd, algo, dvalue, dvalue_size);
72fdaf
+  close(fd);
72fdaf
+#else
72fdaf
+  rc = -1;
72fdaf
+  errno = ENOTSUP;
72fdaf
+#endif
72fdaf
+  debug_return_int(rc);
72fdaf
+}
0e1944
diff --git a/plugins/sudoers/filedigest.h b/plugins/sudoers/filedigest.h
0e1944
new file mode 100644
0e1944
index 0000000..437f02f
0e1944
--- /dev/null
0e1944
+++ b/plugins/sudoers/filedigest.h
72fdaf
@@ -0,0 +1,17 @@
72fdaf
+#include <stddef.h>
72fdaf
+
72fdaf
+#define SUDO_DIGEST_SHA224	0
72fdaf
+#define SUDO_DIGEST_SHA256	1
72fdaf
+#define SUDO_DIGEST_SHA384	2
72fdaf
+#define SUDO_DIGEST_SHA512	3
0e1944
+#define SUDO_DIGEST_INVALID     4
72fdaf
+
72fdaf
+#define SUDO_SHA224_DIGEST_LENGTH 28
72fdaf
+#define SUDO_SHA256_DIGEST_LENGTH 32
72fdaf
+#define SUDO_SHA384_DIGEST_LENGTH 48
72fdaf
+#define SUDO_SHA512_DIGEST_LENGTH 64
72fdaf
+
72fdaf
+/*
72fdaf
+ * Compute a digest of a given file. Returns 0 on success, -1 otherwise.
72fdaf
+ */
72fdaf
+int sudo_filedigest(const char *path, int algo, unsigned char **dvalue, size_t *dvalue_size);
0e1944
diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c
0e1944
index 1916bde..2a9ea4b 100644
0e1944
--- a/plugins/sudoers/match.c
0e1944
+++ b/plugins/sudoers/match.c
0e1944
@@ -62,6 +62,7 @@
72fdaf
 
0e1944
 #include "sudoers.h"
0e1944
 #include "parse.h"
0e1944
+#include "filedigest.h"
0e1944
 #include <gram.h>
72fdaf
 
0e1944
 #ifdef HAVE_FNMATCH
0e1944
@@ -576,6 +577,7 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const
72fdaf
 }
0e1944
 #else /* !SUDOERS_NAME_MATCH */
0e1944
 
0e1944
+#ifndef HAVE_LIBGCRYPT /* !!! */
0e1944
 static struct digest_function {
0e1944
     const char *digest_name;
0e1944
     const unsigned int digest_len;
0e1944
@@ -616,24 +618,43 @@ static struct digest_function {
0e1944
 	NULL
0e1944
     }
0e1944
 };
0e1944
+#endif /* !HAVE_LIBGCRYPT */
0e1944
+
0e1944
+static const char *digesttype2str(int digest_type)
0e1944
+{
0e1944
+    switch(digest_type) {
0e1944
+        case SUDO_DIGEST_SHA224:
0e1944
+            return "SHA224";
0e1944
+        case SUDO_DIGEST_SHA256:
0e1944
+            return "SHA256";
0e1944
+        case SUDO_DIGEST_SHA384:
0e1944
+            return "SHA384";
0e1944
+        case SUDO_DIGEST_SHA512:
0e1944
+            return "SHA512";
72fdaf
+    }
0e1944
+    return "<INVALID>";
72fdaf
+}
72fdaf
 
0e1944
 static bool
0e1944
 digest_matches(const char *file, const struct sudo_digest *sd, int *fd)
0e1944
 {
0e1944
-    unsigned char file_digest[SHA512_DIGEST_LENGTH];
0e1944
-    unsigned char sudoers_digest[SHA512_DIGEST_LENGTH];
0e1944
+    unsigned char * file_digest = NULL;
0e1944
+    unsigned char * sudoers_digest = NULL;
0e1944
+    size_t digest_size;
0e1944
     unsigned char buf[32 * 1024];
0e1944
-    struct digest_function *func = NULL;
0e1944
 #ifdef HAVE_FEXECVE
0e1944
     bool first = true;
0e1944
     bool is_script = false;
0e1944
 #endif /* HAVE_FEXECVE */
0e1944
     size_t nread;
0e1944
-    SHA2_CTX ctx;
0e1944
     FILE *fp;
0e1944
     unsigned int i;
0e1944
     debug_decl(digest_matches, SUDOERS_DEBUG_MATCH)
0e1944
 
0e1944
+#ifndef HAVE_LIBGCRYPT /* !!! */
0e1944
+
0e1944
+    SHA2_CTX ctx;
0e1944
+    struct digest_function *func = NULL;
0e1944
     for (i = 0; digest_functions[i].digest_name != NULL; i++) {
0e1944
 	if (sd->digest_type == i) {
0e1944
 	    func = &digest_functions[i];
0e1944
@@ -644,9 +665,33 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd)
0e1944
 	sudo_warnx(U_("unsupported digest type %d for %s"), sd->digest_type, file);
0e1944
 	debug_return_bool(false);
72fdaf
     }
0e1944
-    if (strlen(sd->digest_str) == func->digest_len * 2) {
72fdaf
+
0e1944
+    digest_size = func->digest_len;
72fdaf
+
0e1944
+    file_digest = malloc(digest_size);
0e1944
+    if (file_digest == NULL) {
0e1944
+	debug_return_bool(false);
72fdaf
+    }
72fdaf
+
0e1944
+#elif HAVE_LIBGCRYPT
72fdaf
+
0e1944
+    if (sudo_filedigest(file, sd->digest_type,
0e1944
+        &file_digest, &digest_size) != 0) {
0e1944
+        sudo_warnx(U_("Cannot compute digest type %d for %s"), sd->digest_type, file);
0e1944
+        goto clean_up;
0e1944
+    }
72fdaf
+
0e1944
+#endif /* !HAVE_LIBGCRYPT */
72fdaf
+
0e1944
+    sudoers_digest = malloc(digest_size);
0e1944
+    if (sudoers_digest == NULL) {
0e1944
+        free(file_digest);
0e1944
+	debug_return_bool(false);
0e1944
+    }
72fdaf
+
0e1944
+    if (strlen(sd->digest_str) == digest_size * 2) {
0e1944
 	/* Convert the command digest from ascii hex to binary. */
0e1944
-	for (i = 0; i < func->digest_len; i++) {
0e1944
+	for (i = 0; i < digest_size ; i++) {
0e1944
 	    const int h = hexchar(&sd->digest_str[i + i]);
0e1944
 	    if (h == -1)
0e1944
 		goto bad_format;
0e1944
@@ -654,11 +699,11 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd)
0e1944
 	}
0e1944
     } else {
0e1944
 	size_t len = base64_decode(sd->digest_str, sudoers_digest,
0e1944
-	    sizeof(sudoers_digest));
0e1944
-	if (len != func->digest_len) {
0e1944
+	    digest_size);
0e1944
+	if (len != digest_size) {
0e1944
 	    sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
0e1944
-		"incorrect length for digest, expected %u, got %zu",
0e1944
-		func->digest_len, len);
0e1944
+		"incorrect length for digest, expected %zu, got %zu",
0e1944
+		digest_size, len);
0e1944
 	    goto bad_format;
0e1944
 	}
72fdaf
     }
0e1944
@@ -666,10 +711,11 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd)
0e1944
     if ((fp = fopen(file, "r")) == NULL) {
0e1944
 	sudo_debug_printf(SUDO_DEBUG_INFO, "unable to open %s: %s",
0e1944
 	    file, strerror(errno));
0e1944
-	debug_return_bool(false);
0e1944
+        goto clean_up;
72fdaf
     }
72fdaf
-
0e1944
+#ifndef HAVE_LIBGCRYPT
0e1944
     func->init(&ctx;;
0e1944
+#endif /* !HAVE_LIBGCRYPT */
0e1944
     while ((nread = fread(buf, 1, sizeof(buf), fp)) != 0) {
0e1944
 #ifdef HAVE_FEXECVE
0e1944
 	/* Check for #! cookie and set is_script. */
0e1944
@@ -679,21 +725,24 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd)
0e1944
 		is_script = true;
0e1944
 	}
0e1944
 #endif /* HAVE_FEXECVE */
0e1944
+#ifndef HAVE_LIBGCRYPT
0e1944
 	func->update(&ctx, buf, nread);
0e1944
+#endif /* !HAVE_LIBGCRYPT */
0e1944
     }
0e1944
     if (ferror(fp)) {
0e1944
 	sudo_warnx(U_("%s: read error"), file);
0e1944
 	fclose(fp);
0e1944
-	debug_return_bool(false);
0e1944
+        goto clean_up;
0e1944
     }
0e1944
+#ifndef HAVE_LIBGCRYPT
0e1944
     func->final(file_digest, &ctx;;
0e1944
-
0e1944
-    if (memcmp(file_digest, sudoers_digest, func->digest_len) != 0) {
0e1944
+#endif /* !HAVE_LIBGCRYPT */
0e1944
+    if (memcmp(file_digest, sudoers_digest, digest_size) != 0) {
0e1944
 	fclose(fp);
0e1944
 	sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
0e1944
 	    "%s digest mismatch for %s, expecting %s",
0e1944
-	    func->digest_name, file, sd->digest_str);
0e1944
-	debug_return_bool(false);
0e1944
+	    digesttype2str(sd->digest_type), file, sd->digest_str);
0e1944
+        goto clean_up;
0e1944
     }
72fdaf
 
0e1944
 #ifdef HAVE_FEXECVE
0e1944
@@ -705,7 +754,7 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd)
0e1944
 	sudo_debug_printf(SUDO_DEBUG_INFO, "unable to dup %s: %s",
0e1944
 	    file, strerror(errno));
0e1944
 	fclose(fp);
0e1944
-	debug_return_bool(false);
0e1944
+        goto clean_up;
0e1944
     }
0e1944
     /*
0e1944
      * Shell scripts go through namei twice and so we can't set the close
0e1944
@@ -715,10 +764,17 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd)
0e1944
 	(void)fcntl(*fd, F_SETFD, FD_CLOEXEC);
0e1944
 #endif /* HAVE_FEXECVE */
0e1944
     fclose(fp);
0e1944
+    free(file_digest);
0e1944
+    free(sudoers_digest);
72fdaf
     debug_return_bool(true);
0e1944
 bad_format:
0e1944
     sudo_warnx(U_("digest for %s (%s) is not in %s form"), file,
0e1944
-	sd->digest_str, func->digest_name);
0e1944
+	sd->digest_str, digesttype2str(sd->digest_type));
0e1944
+clean_up:
0e1944
+    if (file_digest)
0e1944
+        free(file_digest);
0e1944
+    if (sudoers_digest)
0e1944
+        free(sudoers_digest);
0e1944
     debug_return_bool(false);
72fdaf
 }
72fdaf
 
0e1944
-- 
0e1944
2.7.4
0e1944