The branch main has been updated by des:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=42ac41983ee184e818f6e8da791a5c6c7530f87e

commit 42ac41983ee184e818f6e8da791a5c6c7530f87e
Author:     Dag-Erling Smørgrav <d...@freebsd.org>
AuthorDate: 2025-08-13 22:35:17 +0000
Commit:     Dag-Erling Smørgrav <d...@freebsd.org>
CommitDate: 2025-08-13 22:36:36 +0000

    certctl: Fix bootstrap build
    
    Fixes:          81d8827ad875 ("certctl: Reimplement in C")
---
 usr.sbin/certctl/Makefile  |  6 ++-
 usr.sbin/certctl/certctl.8 |  7 +++-
 usr.sbin/certctl/certctl.c | 94 ++++++++++++++++++++++++++++++++--------------
 3 files changed, 77 insertions(+), 30 deletions(-)

diff --git a/usr.sbin/certctl/Makefile b/usr.sbin/certctl/Makefile
index 5430dbf24853..8f19bde8aaf6 100644
--- a/usr.sbin/certctl/Makefile
+++ b/usr.sbin/certctl/Makefile
@@ -3,8 +3,12 @@
 PACKAGE=       certctl
 PROG=  certctl
 MAN=   certctl.8
-LIBADD=        crypto
+LIBADD=        crypto util
 HAS_TESTS=
 SUBDIR.${MK_TESTS}=    tests
 
+.ifdef BOOTSTRAPPING
+CFLAGS+=-DBOOTSTRAPPING
+.endif
+
 .include <bsd.prog.mk>
diff --git a/usr.sbin/certctl/certctl.8 b/usr.sbin/certctl/certctl.8
index 97bdc840c359..c53ad9765544 100644
--- a/usr.sbin/certctl/certctl.8
+++ b/usr.sbin/certctl/certctl.8
@@ -38,7 +38,7 @@
 .Op Fl lv
 .Ic untrusted
 .Nm
-.Op Fl BnUv
+.Op Fl BNnUv
 .Op Fl D Ar destdir
 .Op Fl M Ar metalog
 .Ic rehash
@@ -75,6 +75,11 @@ default:
 This option is only valid in conjunction with the
 .Ic rehash
 command.
+.It Fl N
+Base the file name on the certificate's name instead of its hash.
+This option is only valid in conjunction with the
+.Ic rehash
+command.
 .It Fl n
 Dry-run mode.
 Do not actually perform any actions except write the metalog.
diff --git a/usr.sbin/certctl/certctl.c b/usr.sbin/certctl/certctl.c
index 6687e56f23b4..f5876736d604 100644
--- a/usr.sbin/certctl/certctl.c
+++ b/usr.sbin/certctl/certctl.c
@@ -4,7 +4,6 @@
  * SPDX-License-Identifier: BSD-2-Clause
  */
 
-#include <sys/sysctl.h>
 #include <sys/stat.h>
 #include <sys/tree.h>
 
@@ -13,6 +12,8 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <fts.h>
+#include <libgen.h>
+#include <libutil.h>
 #include <paths.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -20,6 +21,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <openssl/err.h>
 #include <openssl/ssl.h>
 
 #define info(fmt, ...)                                                 \
@@ -58,6 +60,7 @@ static void usage(void);
 static bool dryrun;
 static bool longnames;
 static bool nobundle;
+static bool nohash;
 static bool unprivileged;
 static bool verbose;
 
@@ -381,14 +384,58 @@ write_certs(const char *dir, struct cert_tree *tree)
                if (file->c == INT_MAX)
                        errx(1, "unable to disambiguate %08lx", cert->hash);
                free(cert->path);
-               cert->path = xasprintf("%08lx.%d", cert->hash, file->c);
+               if (nohash) {
+                       X509_NAME *xn;
+                       X509_NAME_ENTRY *xe;
+                       ASN1_STRING *as;
+                       unsigned char *us = NULL;
+                       int xi, usl;
+
+                       xn = X509_get_subject_name(cert->x509);
+                       xi = X509_NAME_get_index_by_NID(xn, NID_commonName, -1);
+                       if (xi < 0) {
+                               warnx("%08lx.%d: certificate has no CN",
+                                   cert->hash, file->c);
+                               xi = X509_NAME_get_index_by_NID(xn,
+                                   NID_organizationalUnitName, -1);
+                       }
+                       if (xi < 0) {
+                               warnx("%08lx.%d: certificate has no OU",
+                                   cert->hash, file->c);
+                               xi = X509_NAME_get_index_by_NID(xn,
+                                   NID_organizationName, -1);
+                       }
+                       if (xi < 0) {
+                               warnx("%08lx.%d: certificate has no O",
+                                   cert->hash, file->c);
+                               cert->path = xasprintf("%08lx.%d", cert->hash,
+                                   file->c);
+                       }
+                       xe = X509_NAME_get_entry(xn, xi);
+                       as = X509_NAME_ENTRY_get_data(xe);
+                       usl = ASN1_STRING_to_UTF8(&us, as);
+                       if (usl < 0) {
+                               errx(1, "%08lx.%d: %s", cert->hash, file->c,
+                                   ERR_error_string(ERR_get_error(), NULL));
+                       }
+                       cert->path = xasprintf("%s.pem", (char *)us);
+                       OPENSSL_free(us);
+               } else {
+                       cert->path = xasprintf("%08lx.%d", cert->hash, file->c);
+               }
        }
        /*
         * Open and scan the directory.
         */
        if ((d = open(dir, O_DIRECTORY | O_RDONLY)) < 0 ||
-           (ndents = fdscandir(d, &dents, NULL, lexisort)) < 0)
+#ifdef BOOTSTRAPPING
+           (ndents = scandir(dir, &dents, NULL, lexisort))
+#else
+           (ndents = fdscandir(d, &dents, NULL, lexisort))
+#endif
+           < 0)
                err(1, "%s", dir);
+
        /*
         * Iterate over the directory listing and the certificate listing
         * in parallel.  If the directory listing gets ahead of the
@@ -598,7 +645,7 @@ load_trusted(bool all, struct cert_tree *exclude)
  * Returns the number of certificates loaded.
  */
 static unsigned int
-load_untrusted(bool all)
+load_untrusted(bool all, struct cert_tree *exclude)
 {
        char *path;
        unsigned int i, n;
@@ -606,19 +653,19 @@ load_untrusted(bool all)
 
        /* load external untrusted certs */
        for (i = n = 0; all && untrusted_paths[i] != NULL; i++) {
-               ret = read_certs(untrusted_paths[i], &untrusted, NULL);
+               ret = read_certs(untrusted_paths[i], &untrusted, exclude);
                if (ret > 0)
                        n += ret;
        }
 
        /* load installed untrusted certs */
-       ret = read_certs(untrusted_dest, &untrusted, NULL);
+       ret = read_certs(untrusted_dest, &untrusted, exclude);
        if (ret > 0)
                n += ret;
 
        /* load legacy untrusted certs */
        path = expand_path(LEGACY_PATH);
-       ret = read_certs(path, &untrusted, NULL);
+       ret = read_certs(path, &untrusted, exclude);
        if (ret > 0) {
                warnx("certificates found in legacy directory %s",
                    path);
@@ -748,7 +795,7 @@ certctl_untrusted(int argc, char **argv __unused)
        if (argc > 1)
                usage();
        /* load untrusted certificates */
-       load_untrusted(false);
+       load_untrusted(false, NULL);
        /* list them */
        list_certs(&untrusted);
        free_certs(&untrusted);
@@ -775,7 +822,7 @@ certctl_rehash(int argc, char **argv __unused)
        }
 
        /* load untrusted certs first */
-       load_untrusted(true);
+       load_untrusted(true, NULL);
 
        /* load trusted certs, excluding any that are already untrusted */
        load_trusted(true, &untrusted);
@@ -808,7 +855,7 @@ certctl_trust(int argc, char **argv)
                usage();
 
        /* load untrusted certs first */
-       load_untrusted(true);
+       load_untrusted(true, NULL);
 
        /* load trusted certs, excluding any that are already untrusted */
        load_trusted(true, &untrusted);
@@ -869,7 +916,7 @@ certctl_untrust(int argc, char **argv)
                usage();
 
        /* load untrusted certs first */
-       load_untrusted(true);
+       load_untrusted(true, NULL);
 
        /* now load the additional untrusted certificates */
        n = 0;
@@ -900,22 +947,10 @@ static void
 set_defaults(void)
 {
        const char *value;
-       char *str;
-       size_t len;
 
        if (localbase == NULL &&
-           (localbase = getenv("LOCALBASE")) == NULL) {
-               if ((str = malloc((len = PATH_MAX) + 1)) == NULL)
-                       err(1, NULL);
-               while (sysctlbyname("user.localbase", str, &len, NULL, 0) < 0) {
-                       if (errno != ENOMEM)
-                               err(1, "sysctl(user.localbase)");
-                       if ((str = realloc(str, len + 1)) == NULL)
-                               err(1, NULL);
-               }
-               str[len] = '\0';
-               localbase = str;
-       }
+           (localbase = getenv("LOCALBASE")) == NULL)
+               localbase = getlocalbase();
 
        if (destdir == NULL &&
            (destdir = getenv("DESTDIR")) == NULL)
@@ -984,7 +1019,7 @@ usage(void)
 {
        fprintf(stderr, "usage: certctl [-lv] [-D destdir] list\n"
            "       certctl [-lv] [-D destdir] untrusted\n"
-           "       certctl [-BnUv] [-D destdir] [-M metalog] rehash\n"
+           "       certctl [-BNnUv] [-D destdir] [-M metalog] rehash\n"
            "       certctl [-nv] [-D destdir] untrust <file>\n"
            "       certctl [-nv] [-D destdir] trust <file>\n");
        exit(1);
@@ -996,7 +1031,7 @@ main(int argc, char *argv[])
        const char *command;
        int opt;
 
-       while ((opt = getopt(argc, argv, "BcD:g:lL:M:no:Uv")) != -1)
+       while ((opt = getopt(argc, argv, "BcD:g:lL:M:Nno:Uv")) != -1)
                switch (opt) {
                case 'B':
                        nobundle = true;
@@ -1019,6 +1054,9 @@ main(int argc, char *argv[])
                case 'M':
                        metalog = optarg;
                        break;
+               case 'N':
+                       nohash = true;
+                       break;
                case 'n':
                        dryrun = true;
                        break;
@@ -1043,7 +1081,7 @@ main(int argc, char *argv[])
 
        command = *argv;
 
-       if ((nobundle || unprivileged || metalog != NULL) &&
+       if ((nobundle || nohash || unprivileged || metalog != NULL) &&
            strcmp(command, "rehash") != 0)
                usage();
        if (!unprivileged && metalog != NULL) {

Reply via email to