]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/auth/negotiate/kerberos/negotiate_kerberos_auth.cc
Source Format Enforcement (#1234)
[thirdparty/squid.git] / src / auth / negotiate / kerberos / negotiate_kerberos_auth.cc
index d08e364a62383823db1866328b145e8c73f02b60..4cce9264f4dae84e6a6ae198ee86bb7698351255 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
@@ -54,7 +54,9 @@ typedef struct _krb5_kt_list {
     struct _krb5_kt_list *next;
     krb5_keytab_entry *entry;
 } *krb5_kt_list;
-krb5_kt_list ktlist = NULL;
+krb5_kt_list ktlist = nullptr;
+
+krb5_keytab memory_keytab;
 
 krb5_error_code krb5_free_kt_list(krb5_context context, krb5_kt_list kt_list);
 krb5_error_code krb5_write_keytab(krb5_context context,
@@ -92,7 +94,7 @@ gethost_name(void)
      * char hostname[sysconf(_SC_HOST_NAME_MAX)];
      */
     char hostname[1024];
-    struct addrinfo *hres = NULL, *hres_list;
+    struct addrinfo *hres = nullptr, *hres_list;
     int rc, count;
 
     rc = gethostname(hostname, sizeof(hostname)-1);
@@ -100,16 +102,16 @@ gethost_name(void)
         debug((char *) "%s| %s: ERROR: resolving hostname '%s' failed\n", LogTime(), PROGRAM, hostname);
         fprintf(stderr, "%s| %s: ERROR: resolving hostname '%s' failed\n",
                 LogTime(), PROGRAM, hostname);
-        return NULL;
+        return nullptr;
     }
-    rc = getaddrinfo(hostname, NULL, NULL, &hres);
-    if (rc != 0 || hres == NULL ) {
+    rc = getaddrinfo(hostname, nullptr, nullptr, &hres);
+    if (rc != 0 || hres == nullptr ) {
         debug((char *) "%s| %s: ERROR: resolving hostname with getaddrinfo: %s failed\n",
               LogTime(), PROGRAM, gai_strerror(rc));
         fprintf(stderr,
                 "%s| %s: ERROR: resolving hostname with getaddrinfo: %s failed\n",
                 LogTime(), PROGRAM, gai_strerror(rc));
-        return NULL;
+        return nullptr;
     }
     hres_list = hres;
     count = 0;
@@ -118,7 +120,7 @@ gethost_name(void)
         hres_list = hres_list->ai_next;
     }
     rc = getnameinfo(hres->ai_addr, hres->ai_addrlen, hostname,
-                     sizeof(hostname), NULL, 0, 0);
+                     sizeof(hostname), nullptr, 0, 0);
     if (rc != 0) {
         debug((char *) "%s| %s: ERROR: resolving ip address with getnameinfo: %s failed\n",
               LogTime(), PROGRAM, gai_strerror(rc));
@@ -126,7 +128,7 @@ gethost_name(void)
                 "%s| %s: ERROR: resolving ip address with getnameinfo: %s failed\n",
                 LogTime(), PROGRAM, gai_strerror(rc));
         freeaddrinfo(hres);
-        return NULL;
+        return nullptr;
     }
     freeaddrinfo(hres);
     hostname[sizeof(hostname)-1] = '\0';
@@ -217,7 +219,7 @@ krb5_error_code krb5_free_kt_list(krb5_context context, krb5_kt_list list)
  */
 krb5_error_code krb5_read_keytab(krb5_context context, char *name, krb5_kt_list *list)
 {
-    krb5_kt_list lp = NULL, tail = NULL, back = NULL;
+    krb5_kt_list lp = nullptr, tail = nullptr, back = nullptr;
     krb5_keytab kt;
     krb5_keytab_entry *entry;
     krb5_kt_cursor cursor;
@@ -273,7 +275,7 @@ krb5_error_code krb5_read_keytab(krb5_context context, char *name, krb5_kt_list
         }
         if (!tail)
             tail = lp;
-        lp->next = NULL;
+        lp->next = nullptr;
         lp->entry = entry;
     }
     xfree(entry);
@@ -282,9 +284,9 @@ krb5_error_code krb5_read_keytab(krb5_context context, char *name, krb5_kt_list
             retval = 0;
         else {
             krb5_free_kt_list(context, tail);
-            tail = NULL;
+            tail = nullptr;
             if (back)
-                back->next = NULL;
+                back->next = nullptr;
         }
     }
     if (!*list)
@@ -300,16 +302,15 @@ close_kt:
  */
 krb5_error_code krb5_write_keytab(krb5_context context, krb5_kt_list list, char *name)
 {
-    krb5_keytab kt;
     char ktname[MAXPATHLEN+sizeof("MEMORY:")+1];
     krb5_error_code retval = 0;
 
     snprintf(ktname, sizeof(ktname), "%s", name);
-    retval = krb5_kt_resolve(context, ktname, &kt);
+    retval = krb5_kt_resolve(context, ktname, &memory_keytab);
     if (retval)
         return retval;
     for (krb5_kt_list lp = list; lp; lp = lp->next) {
-        retval = krb5_kt_add_entry(context, kt, lp->entry);
+        retval = krb5_kt_add_entry(context, memory_keytab, lp->entry);
         if (retval)
             break;
     }
@@ -325,11 +326,11 @@ main(int argc, char *const argv[])
 {
     char buf[MAX_AUTHTOKEN_LEN];
     char *c, *p;
-    char *user = NULL;
-    char *rfc_user = NULL;
+    char *user = nullptr;
+    char *rfc_user = nullptr;
 #if HAVE_PAC_SUPPORT
     char ad_groups[MAX_PAC_GROUP_SIZE];
-    char *ag=NULL;
+    char *ag=nullptr;
     krb5_pac pac;
 #if USE_HEIMDAL_KRB5
     gss_buffer_desc data_set = GSS_C_EMPTY_BUFFER;
@@ -337,25 +338,26 @@ main(int argc, char *const argv[])
     gss_buffer_desc type_id = GSS_C_EMPTY_BUFFER;
 #endif
 #endif
-    krb5_context context = NULL;
+    krb5_context context = nullptr;
     krb5_error_code ret;
     long length = 0;
     static int err = 0;
     int opt, log = 0, norealm = 0;
     OM_uint32 ret_flags = 0, spnego_flag = 0;
-    char *service_name = (char *) "HTTP", *host_name = NULL;
-    char *token = NULL;
-    char *service_principal = NULL;
-    char *keytab_name = NULL;
-    char *keytab_name_env = NULL;
-    char default_keytab[MAXPATHLEN];
+    char *service_name = (char *) "HTTP", *host_name = nullptr;
+    char *token = nullptr;
+    char *service_principal = nullptr;
+    char *keytab_name = nullptr;
+    char *keytab_name_env = nullptr;
+    char default_keytab[MAXPATHLEN] = {};
 #if HAVE_KRB5_MEMORY_KEYTAB
-    char *memory_keytab_name = NULL;
+    char *memory_keytab_name = nullptr;
+    char *memory_keytab_name_env = nullptr;
 #endif
-    char *rcache_type = NULL;
-    char *rcache_type_env = NULL;
-    char *rcache_dir = NULL;
-    char *rcache_dir_env = NULL;
+    char *rcache_type = nullptr;
+    char *rcache_type_env = nullptr;
+    char *rcache_dir = nullptr;
+    char *rcache_dir_env = nullptr;
     OM_uint32 major_status, minor_status;
     gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
     gss_name_t client_name = GSS_C_NO_NAME;
@@ -364,12 +366,12 @@ main(int argc, char *const argv[])
     gss_buffer_desc service = GSS_C_EMPTY_BUFFER;
     gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
     gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
-    const unsigned char *kerberosToken = NULL;
-    const unsigned char *spnegoToken = NULL;
+    const unsigned char *kerberosToken = nullptr;
+    const unsigned char *spnegoToken = nullptr;
     size_t spnegoTokenLength = 0;
 
-    setbuf(stdout, NULL);
-    setbuf(stdin, NULL);
+    setbuf(stdout, nullptr);
+    setbuf(stdin, nullptr);
 
     while (-1 != (opt = getopt(argc, argv, "dirs:k:c:t:"))) {
         switch (opt) {
@@ -560,10 +562,10 @@ main(int argc, char *const argv[])
                 debug((char *) "%s| %s: ERROR: Writing list into keytab %s\n",
                       LogTime(), PROGRAM, memory_keytab_name);
             } else {
-                keytab_name_env = (char *) xmalloc(strlen("KRB5_KTNAME=")+strlen(memory_keytab_name)+1);
-                strcpy(keytab_name_env, "KRB5_KTNAME=");
-                strcat(keytab_name_env, memory_keytab_name);
-                putenv(keytab_name_env);
+                memory_keytab_name_env = (char *) xmalloc(strlen("KRB5_KTNAME=")+strlen(memory_keytab_name)+1);
+                strcpy(memory_keytab_name_env, "KRB5_KTNAME=");
+                strcat(memory_keytab_name_env, memory_keytab_name);
+                putenv(memory_keytab_name_env);
                 xfree(keytab_name);
                 keytab_name = xstrdup(memory_keytab_name);
                 debug((char *) "%s| %s: INFO: Changed keytab to %s\n",
@@ -582,7 +584,7 @@ main(int argc, char *const argv[])
     gsskrb5_register_acceptor_identity(keytab_name);
 #endif
     while (1) {
-        if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
+        if (fgets(buf, sizeof(buf) - 1, stdin) == nullptr) {
             if (ferror(stdin)) {
                 debug((char *) "%s| %s: FATAL: fgets() failed! dying..... errno=%d (%s)\n",
                       LogTime(), PROGRAM, ferror(stdin),
@@ -629,7 +631,7 @@ main(int argc, char *const argv[])
             if (client_name)
                 gss_release_name(&minor_status, &client_name);
             if (gss_context != GSS_C_NO_CONTEXT)
-                gss_delete_sec_context(&minor_status, &gss_context, NULL);
+                gss_delete_sec_context(&minor_status, &gss_context, nullptr);
             if (kerberosToken) {
                 /* Allocated by parseNegTokenInit, but no matching free function exists.. */
                 if (!spnego_flag)
@@ -640,6 +642,18 @@ main(int argc, char *const argv[])
                 xfree(spnegoToken);
             }
             xfree(token);
+            xfree(rcache_type);
+            xfree(rcache_type_env);
+            xfree(rcache_dir);
+            xfree(rcache_dir_env);
+            xfree(keytab_name);
+            xfree(keytab_name_env);
+#if HAVE_KRB5_MEMORY_KEYTAB
+            krb5_kt_close(context, memory_keytab);
+            xfree(memory_keytab_name);
+            xfree(memory_keytab_name_env);
+#endif
+            xfree(rfc_user);
             fprintf(stdout, "BH quit command\n");
             exit(EXIT_SUCCESS);
         }
@@ -650,7 +664,7 @@ main(int argc, char *const argv[])
         }
         if (!strncmp(buf, "YR", 2)) {
             if (gss_context != GSS_C_NO_CONTEXT)
-                gss_delete_sec_context(&minor_status, &gss_context, NULL);
+                gss_delete_sec_context(&minor_status, &gss_context, nullptr);
             gss_context = GSS_C_NO_CONTEXT;
         }
         if (strlen(buf) <= 3) {
@@ -707,7 +721,7 @@ main(int argc, char *const argv[])
 
         major_status =
             gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
-                             GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds, NULL, NULL);
+                             GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds, nullptr, nullptr);
         if (check_gss_err(major_status, minor_status, "gss_acquire_cred()", log, 1))
             goto cleanup;
 
@@ -716,13 +730,13 @@ main(int argc, char *const argv[])
                                               server_creds,
                                               &input_token,
                                               GSS_C_NO_CHANNEL_BINDINGS,
-                                              &client_name, NULL, &output_token, &ret_flags, NULL, NULL);
+                                              &client_name, nullptr, &output_token, &ret_flags, nullptr, nullptr);
 
         if (output_token.length) {
             spnegoToken = (const unsigned char *) output_token.value;
             spnegoTokenLength = output_token.length;
             token = (char *) xmalloc((size_t)base64_encode_len(spnegoTokenLength));
-            if (token == NULL) {
+            if (token == nullptr) {
                 debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
                 fprintf(stdout, "BH Not enough memory\n");
                 goto cleanup;
@@ -737,25 +751,25 @@ main(int argc, char *const argv[])
                 goto cleanup;
             if (major_status & GSS_S_CONTINUE_NEEDED) {
                 debug((char *) "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
-                fprintf(stdout, "TT %s\n", token);
+                fprintf(stdout, "TT token=%s\n", token);
                 goto cleanup;
             }
             gss_release_buffer(&minor_status, &output_token);
             major_status =
                 gss_display_name(&minor_status, client_name, &output_token,
-                                 NULL);
+                                 nullptr);
 
             if (check_gss_err(major_status, minor_status, "gss_display_name()", log, 1))
                 goto cleanup;
             user = (char *) xmalloc(output_token.length + 1);
-            if (user == NULL) {
+            if (user == nullptr) {
                 debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
                 fprintf(stdout, "BH Not enough memory\n");
                 goto cleanup;
             }
             memcpy(user, output_token.value, output_token.length);
             user[output_token.length] = '\0';
-            if (norealm && (p = strchr(user, '@')) != NULL) {
+            if (norealm && (p = strchr(user, '@')) != nullptr) {
                 *p = '\0';
             }
 
@@ -794,11 +808,11 @@ main(int argc, char *const argv[])
 #endif
             rfc_user = rfc1738_escape(user);
 #if HAVE_PAC_SUPPORT
-            fprintf(stdout, "AF %s %s %s\n", token, rfc_user, ag?ag:"group=");
+            fprintf(stdout, "OK token=%s user=%s %s\n", token, rfc_user, ag?ag:"group=");
 #else
-            fprintf(stdout, "AF %s %s\n", token, rfc_user);
+            fprintf(stdout, "OK token=%s user=%s\n", token, rfc_user);
 #endif
-            debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, token, rfc_user);
+            debug((char *) "%s| %s: DEBUG: OK token=%s user=%s\n", LogTime(), PROGRAM, token, rfc_user);
             if (log)
                 fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(),
                         PROGRAM, rfc_user);
@@ -808,13 +822,14 @@ main(int argc, char *const argv[])
                 goto cleanup;
             if (major_status & GSS_S_CONTINUE_NEEDED) {
                 debug((char *) "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
-                fprintf(stdout, "NA %s\n", token);
+                // XXX: where to get the server token for delivery to client? token is nullptr here.
+                fprintf(stdout, "ERR\n");
                 goto cleanup;
             }
             gss_release_buffer(&minor_status, &output_token);
             major_status =
                 gss_display_name(&minor_status, client_name, &output_token,
-                                 NULL);
+                                 nullptr);
 
             if (check_gss_err(major_status, minor_status, "gss_display_name()", log, 1))
                 goto cleanup;
@@ -822,23 +837,23 @@ main(int argc, char *const argv[])
              *  Return dummy token AA. May need an extra return tag then AF
              */
             user = (char *) xmalloc(output_token.length + 1);
-            if (user == NULL) {
+            if (user == nullptr) {
                 debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
                 fprintf(stdout, "BH Not enough memory\n");
                 goto cleanup;
             }
             memcpy(user, output_token.value, output_token.length);
             user[output_token.length] = '\0';
-            if (norealm && (p = strchr(user, '@')) != NULL) {
+            if (norealm && (p = strchr(user, '@')) != nullptr) {
                 *p = '\0';
             }
             rfc_user = rfc1738_escape(user);
 #if HAVE_PAC_SUPPORT
-            fprintf(stdout, "AF %s %s %s\n", "AA==", rfc_user, ag?ag:"group=");
+            fprintf(stdout, "OK token=%s user=%s %s\n", "AA==", rfc_user, ag?ag:"group=");
 #else
-            fprintf(stdout, "AF %s %s\n", "AA==", rfc_user);
+            fprintf(stdout, "OK token=%s user=%s\n", "AA==", rfc_user);
 #endif
-            debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, "AA==", rfc_user);
+            debug((char *) "%s| %s: DEBUG: OK token=%s user=%s\n", LogTime(), PROGRAM, "AA==", rfc_user);
             if (log)
                 fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(),
                         PROGRAM, rfc_user);