git: 9a40ff81f4ea - main - security/sssd2: Reimplement UID-finding using sysctl

From: John Hixson <jhixson_at_FreeBSD.org>
Date: Fri, 06 Dec 2024 20:49:08 UTC
The branch main has been updated by jhixson:

URL: https://cgit.FreeBSD.org/ports/commit/?id=9a40ff81f4ea693025a38f409f8ad1ed6d349b97

commit 9a40ff81f4ea693025a38f409f8ad1ed6d349b97
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-05-17 14:53:06 +0000
Commit:     John Hixson <jhixson@FreeBSD.org>
CommitDate: 2024-12-06 20:48:44 +0000

    security/sssd2: Reimplement UID-finding using sysctl
    
    This avoids a dependency on procfs or linprocfs, so makes sssd2
    marginally more usable when using the krb5_store_password_if_offline
    option.
    
    Sponsored by:   Klara, Inc.
    
    Signed-off-by: John Hixson <jhixson@freebsd.org>
---
 security/sssd2/files/patch-src__util__find_uid.c | 292 ++++++++---------------
 1 file changed, 95 insertions(+), 197 deletions(-)

diff --git a/security/sssd2/files/patch-src__util__find_uid.c b/security/sssd2/files/patch-src__util__find_uid.c
index e319f3289a0a..40f9022a5f9d 100644
--- a/security/sssd2/files/patch-src__util__find_uid.c
+++ b/security/sssd2/files/patch-src__util__find_uid.c
@@ -1,227 +1,125 @@
---- src/util/find_uid.c.orig	2024-01-12 12:05:40 UTC
+--- src/util/find_uid.c.orig	2024-05-16 11:35:27 UTC
 +++ src/util/find_uid.c
-@@ -58,6 +58,97 @@ static void hash_talloc_free(void *ptr, void *pvt)
-     talloc_free(ptr);
+@@ -36,6 +36,10 @@
+ #include <ctype.h>
+ #include <sys/time.h>
+ #include <dhash.h>
++#ifdef __FreeBSD__
++#include <sys/sysctl.h>
++#include <sys/user.h>
++#endif
+ 
+ #include "util/find_uid.h"
+ #include "util/util.h"
+@@ -325,9 +329,86 @@ done:
+     return ret;
  }
-
-+static int parse_procfs_linux(const char* buf, uid_t *uid, bool *is_systemd)
-+{
-+    char *p;
-+    char *e;
-+    char *endptr;
-+    uint32_t num=0;
-+    errno_t error=EOK;
+ 
+-errno_t get_uid_table(TALLOC_CTX *mem_ctx, hash_table_t **table)
++#ifdef __FreeBSD__
++static errno_t get_active_uid_freebsd(hash_table_t *table, uid_t uid)
+ {
++    struct kinfo_proc *kp;
++    hash_key_t key;
++    hash_value_t value;
++    size_t sz;
++    int err, mib[3];
 +
-+    /* Get uid */
-+    p = strstr(buf, "\nUid:\t");
-+    if (p != NULL) {
-+        p += 6;
-+        e = strchr(p,'\t');
-+        if (e == NULL) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "missing delimiter.\n");
-+            return EINVAL;
-+        } else {
-+            *e = '\0';
-+        }
-+        num = (uint32_t) strtoint32(p, &endptr, 10);
-+        error = errno;
-+        if (error != 0) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "strtol failed [%s].\n", strerror(error));
-+            return error;
-+        }
-+        if (*endptr != '\0') {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "uid contains extra characters\n");
-+            return EINVAL;
-+        }
++    mib[0] = CTL_KERN;
++    mib[1] = KERN_PROC;
++    mib[2] = KERN_PROC_PROC;
 +
-+    } else {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "format error\n");
-+        return EINVAL;
++    sz = 0;
++    err = sysctl(mib, 3, NULL, &sz, NULL, 0);
++    if (err) {
++        err = errno;
++        DEBUG(SSSDBG_CRIT_FAILURE, "sysctl failed.\n");
++        return err;
 +    }
++    sz *= 2;
 +
-+    /* Get process name. */
-+    p = strstr(buf, "Name:\t");
-+    if (p == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "format error\n");
-+        return EINVAL;
-+    }
-+    p += 6;
-+    e = strchr(p,'\n');
-+    if (e == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "format error\n");
-+        return EINVAL;
++    kp = talloc_size(NULL, sz);
++    if (kp == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
++        return ENOMEM;
 +    }
-+    if (strncmp(p, "systemd", e-p) == 0 || strncmp(p, "(sd-pam)", e-p) == 0) {
-+        *is_systemd = true;
-+    } else {
-+        *is_systemd = false;
-+    }
-+
-+    *uid = num;
 +
-+    return error;
-+}
-+
-+static int parse_procfs_freebsd(char* buf, uid_t *uid, bool *is_systemd)
-+{
-+    uint32_t field_idx=0;
-+    errno_t error=EOK;
-+    char** str = &buf, *token;
-+
-+    /* See man procfs
-+       nextcloud 21186 4726 110 90383 ttyv0 ctty 1718001838,183475 11,76617 2,473238 select 1001 1001 1001,1001,0,5,44,920 -
-+                                                                                            |uid|
-+    */
-+    while ((token = strsep(str, " ")) != NULL && field_idx < 11) {
-+        field_idx++;
++    err = sysctl(mib, 3, kp, &sz, NULL, 0);
++    if (err) {
++        err = errno;
++        DEBUG(SSSDBG_CRIT_FAILURE, "sysctl failed.\n");
++        talloc_free(kp);
++        return err;
 +    }
 +
-+    if (token == NULL || field_idx != 11) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "format error %d %d\n", token, field_idx);
-+        return EINVAL;
-+    }
-+
-+    *uid = (uint32_t) strtoint32(token, NULL, 10);
-+    error = errno;
-+    if (error != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+                "strtol failed [%s].\n", strerror(error));
-+        return error;
-+    }
++    err = ENOENT;
++    for (size_t i = 0; i < sz / sizeof(struct kinfo_proc); i++) {
++        if (kp[i].ki_uid == 0) {
++            continue;
++        }
 +
-+    *is_systemd = false;
++        if (table != NULL) {
++            key.type = HASH_KEY_ULONG;
++            key.ul = (unsigned long) kp[i].ki_ruid;
++            value.type = HASH_VALUE_ULONG;
++            value.ul = (unsigned long) kp[i].ki_ruid;
 +
-+    return error;
++            err = hash_enter(table, &key, &value);
++            if (err != HASH_SUCCESS) {
++                DEBUG(SSSDBG_CRIT_FAILURE,
++                      "cannot add to table [%s]\n", hash_error_string(err));
++                err = ENOMEM;
++                break;
++            }
++        } else {
++            if (kp[i].ki_ruid == uid) {
++                err = EOK;
++                break;
++            }
++        }
++    }
++    talloc_free(kp);
++    return err;
 +}
++#endif /* __FreeBSD__ */
 +
- static errno_t get_uid_from_pid(const pid_t pid, uid_t *uid, bool *is_systemd)
- {
-     int ret;
-@@ -65,10 +156,6 @@ static errno_t get_uid_from_pid(const pid_t pid, uid_t
-     struct stat stat_buf;
-     int fd;
-     char buf[BUFSIZE];
--    char *p;
--    char *e;
--    char *endptr;
--    uint32_t num=0;
-     errno_t error;
-
-     ret = snprintf(path, PATHLEN, "/proc/%d/status", pid);
-@@ -138,56 +225,14 @@ static errno_t get_uid_from_pid(const pid_t pid, uid_t
-               "close failed [%d][%s].\n", error, strerror(error));
-     }
-
--    /* Get uid */
--    p = strstr(buf, "\nUid:\t");
--    if (p != NULL) {
--        p += 6;
--        e = strchr(p,'\t');
--        if (e == NULL) {
--            DEBUG(SSSDBG_CRIT_FAILURE, "missing delimiter.\n");
--            return EINVAL;
--        } else {
--            *e = '\0';
--        }
--        num = (uint32_t) strtoint32(p, &endptr, 10);
--        error = errno;
--        if (error != 0) {
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "strtol failed [%s].\n", strerror(error));
--            return error;
--        }
--        if (*endptr != '\0') {
--            DEBUG(SSSDBG_CRIT_FAILURE, "uid contains extra characters\n");
--            return EINVAL;
--        }
-+#if defined(__linux__)
-+    return parse_procfs_linux(buf, uid, is_systemd);
++static errno_t get_active_uid(hash_table_t *table, uid_t uid)
++{
+ #ifdef __linux__
++    return get_active_uid_linux(table, uid);
 +#elif defined(__FreeBSD__)
-+    return parse_procfs_freebsd(buf, uid, is_systemd);
++    return get_active_uid_freebsd(table, uid);
 +#else
 +    return ENOSYS;
 +#endif
-
--    } else {
--        DEBUG(SSSDBG_CRIT_FAILURE, "format error\n");
--        return EINVAL;
--    }
--
--    /* Get process name. */
--    p = strstr(buf, "Name:\t");
--    if (p == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "format error\n");
--        return EINVAL;
--    }
--    p += 6;
--    e = strchr(p,'\n');
--    if (e == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "format error\n");
--        return EINVAL;
--    }
--    if (strncmp(p, "systemd", e-p) == 0 || strncmp(p, "(sd-pam)", e-p) == 0) {
--        *is_systemd = true;
--    } else {
--        *is_systemd = false;
--    }
--
--    *uid = num;
--
--    return EOK;
--
- fail_fd:
-     close(fd);
-     return error;
-@@ -212,7 +257,12 @@ static errno_t name_to_pid(const char *name, pid_t *pi
-         return EINVAL;
-     }
-
-+    /* FreeBSD has /proc/0/... */
-+#if defined(__FreeBSD__)
-+    if (num < 0 || num >= INT_MAX) {
-+#else
-     if (num <= 0 || num >= INT_MAX) {
-+#endif
-         DEBUG(SSSDBG_CRIT_FAILURE, "pid out of range.\n");
-         return ERANGE;
-     }
-@@ -228,7 +278,7 @@ static int only_numbers(char *p)
-     return *p;
- }
-
--static errno_t get_active_uid_linux(hash_table_t *table, uid_t search_uid)
-+static errno_t get_active_uid_procfs(hash_table_t *table, uid_t search_uid)
- {
-     DIR *proc_dir = NULL;
-     struct dirent *dirent;
-@@ -327,7 +377,7 @@ errno_t get_uid_table(TALLOC_CTX *mem_ctx, hash_table_
-
- errno_t get_uid_table(TALLOC_CTX *mem_ctx, hash_table_t **table)
- {
--#ifdef __linux__
-+#if defined(__linux__) || defined(__FreeBSD__)
++}
++
++errno_t get_uid_table(TALLOC_CTX *mem_ctx, hash_table_t **table)
++{
      int ret;
-
+ 
      ret = hash_create_ex(0, table, 0, 0, 0, 0,
-@@ -339,7 +389,7 @@ errno_t get_uid_table(TALLOC_CTX *mem_ctx, hash_table_
+@@ -339,10 +420,7 @@ errno_t get_uid_table(TALLOC_CTX *mem_ctx, hash_table_
          return ENOMEM;
      }
-
+ 
 -    return get_active_uid_linux(*table, 0);
-+    return get_active_uid_procfs(*table, 0);
- #else
-     return ENOSYS;
- #endif
-@@ -365,9 +415,9 @@ errno_t check_if_uid_is_active(uid_t uid, bool *result
+-#else
+-    return ENOSYS;
+-#endif
++    return get_active_uid(*table, 0);
+ }
+ 
+ errno_t check_if_uid_is_active(uid_t uid, bool *result)
+@@ -365,9 +443,9 @@ errno_t check_if_uid_is_active(uid_t uid, bool *result
      /* fall back to the old method */
  #endif
-
+ 
 -    ret = get_active_uid_linux(NULL, uid);
-+    ret = get_active_uid_procfs(NULL, uid);
++    ret = get_active_uid(NULL, uid);
      if (ret != EOK && ret != ENOENT) {
 -        DEBUG(SSSDBG_CRIT_FAILURE, "get_active_uid_linux() failed.\n");
-+        DEBUG(SSSDBG_CRIT_FAILURE, "get_active_uid_procfs() failed.\n");
++        DEBUG(SSSDBG_CRIT_FAILURE, "get_active_uid() failed.\n");
          return ret;
      }
-
+