]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:winbind: Improve generate_krb5_ccache()
authorAndreas Schneider <asn@cryptomilk.org>
Fri, 5 Dec 2025 10:03:23 +0000 (11:03 +0100)
committerAndreas Schneider <asn@cryptomilk.org>
Thu, 26 Mar 2026 09:56:29 +0000 (09:56 +0000)
Signed-off-by: Andreas Schneider <asn@samba.org>
Pair-Programmed-With: Alexander Bokovoy <ab@samba.org>

Reviewed-by: Alexander Bokovoy <ab@samba.org>
source3/winbindd/winbindd_pam.c

index ee534a473d1c9b736656adfd64a35169144781b0..050d8655845ed2abfded7521acfb797b8d43aabd 100644 (file)
@@ -622,75 +622,105 @@ static bool generate_krb5_ccache(TALLOC_CTX *mem_ctx,
         * build the full ccname string based on the user's uid here -
         * Guenther*/
 
+       static const struct {
+               const char *prefix;
+               size_t prefix_len;
+       } ccache_prefixes[] = {
+               {.prefix = "DIR:/", .prefix_len = 5},
+               {.prefix = "FILE:/", .prefix_len = 6},
+               {.prefix = "KCM:", .prefix_len = 4},
+               {.prefix = "KEYRING:", .prefix_len = 8},
+               {.prefix = "WRFILE:/", .prefix_len = 8},
+       };
        const char *gen_cc = NULL;
+       size_t i;
+       bool has_prefix = false;
 
-       if (uid != -1) {
-               if (strequal(type, "FILE")) {
-                       gen_cc = talloc_asprintf(
-                               mem_ctx, "FILE:/tmp/krb5cc_%d", uid);
-                       if (gen_cc == NULL) {
-                               return false;
-                       }
-               }
-               if (strequal(type, "WRFILE")) {
-                       gen_cc = talloc_asprintf(
-                               mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid);
-                       if (gen_cc == NULL) {
-                               return false;
-                       }
-               }
-               if (strequal(type, "KEYRING")) {
-                       gen_cc = talloc_asprintf(
-                               mem_ctx, "KEYRING:persistent:%d", uid);
-                       if (gen_cc == NULL) {
-                               return false;
-                       }
-               }
-               if (strequal(type, "KCM")) {
-                       gen_cc = talloc_asprintf(mem_ctx,
-                                                "KCM:%d",
-                                                uid);
-                       if (gen_cc == NULL) {
-                               return false;
-                       }
-               }
-
-               if (strnequal(type, "FILE:/", 6) ||
-                   strnequal(type, "WRFILE:/", 8) ||
-                   strnequal(type, "DIR:/", 5)) {
+       *user_ccache_file = NULL;
 
-                       /* we allow only one "%u" substitution */
+       /* Check if type has an explicit path prefix */
+       for (i = 0; i < ARRAY_SIZE(ccache_prefixes); i++) {
+               if (strnequal(type,
+                             ccache_prefixes[i].prefix,
+                             ccache_prefixes[i].prefix_len))
+               {
+                       has_prefix = true;
+                       break;
+               }
+       }
 
-                       char *p;
+       /* Handle types with explicit paths and %u substitution */
+       if (has_prefix) {
+               char *p;
 
-                       p = strchr(type, '%');
-                       if (p != NULL) {
+               p = strchr(type, '%');
+               if (p != NULL) {
+                       p++;
 
-                               p++;
+                       /* We support only one "%u" substitution */
+                       if (p != NULL && *p == 'u' && strchr(p, '%') == NULL) {
+                               char uid_str[sizeof("18446744073709551615")];
+                               int rc;
 
-                               if (p != NULL && *p == 'u' && strchr(p, '%') == NULL) {
-                                       char uid_str[sizeof("18446744073709551615")];
+                               /* Unset uid is not an error */
+                               if (uid == (uid_t)-1) {
+                                       return true;
+                               }
 
-                                       snprintf(uid_str, sizeof(uid_str), "%u", uid);
+                               rc = snprintf(uid_str,
+                                             sizeof(uid_str),
+                                             "%u",
+                                             (unsigned int)uid);
+                               if (rc < 1) {
+                                       return false;
+                               }
 
-                                       gen_cc = talloc_string_sub2(mem_ctx,
-                                                       type,
-                                                       "%u",
-                                                       uid_str,
-                                                       /* remove_unsafe_characters */
-                                                       false,
-                                                       /* replace_once */
-                                                       true,
-                                                       /* allow_trailing_dollar */
-                                                       false);
-                                       if (gen_cc == NULL) {
-                                               return false;
-                                       }
+                               gen_cc = talloc_string_sub2(
+                                       mem_ctx,
+                                       type,
+                                       "%u",
+                                       uid_str,
+                                       false, /* remove_unsafe_characters */
+                                       true, /* replace_once */
+                                       false); /* allow_trailing_dollar */
+                               if (gen_cc == NULL) {
+                                       return false;
                                }
                        }
                }
+
+               goto done;
        }
 
+       /* Unset uid is not an error */
+       if (uid == (uid_t)-1) {
+               return true;
+       }
+
+       /*
+        * We can't use a table, as the second argument of talloc_asprintf needs
+        * to be a string literal.
+        */
+       if (strequal(type, "FILE")) {
+               gen_cc = talloc_asprintf(mem_ctx,
+                                        "FILE:/tmp/krb5cc_%u",
+                                        (unsigned int)uid);
+       } else if (strequal(type, "WRFILE")) {
+               gen_cc = talloc_asprintf(mem_ctx,
+                                        "WRFILE:/tmp/krb5cc_%u",
+                                        (unsigned int)uid);
+       } else if (strequal(type, "KEYRING")) {
+               gen_cc = talloc_asprintf(mem_ctx,
+                                        "KEYRING:persistent:%u",
+                                        (unsigned int)uid);
+       } else if (strequal(type, "KCM")) {
+               gen_cc = talloc_asprintf(mem_ctx, "KCM:%u", (unsigned int)uid);
+       }
+       if (gen_cc == NULL) {
+               return false;
+       }
+
+done:
        *user_ccache_file = gen_cc;
 
        DBG_DEBUG("using ccache: %s\n", gen_cc != NULL ? gen_cc : "(internal)");