/*
* Hosted at http://sourceforge.net/projects/squidkerbauth
*/
-#include "config.h"
+#include "squid.h"
+#include "compat/getaddrinfo.h"
+#include "compat/getnameinfo.h"
+#include "rfc1738.h"
#if HAVE_GSSAPI
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/time.h>
-
-#include "getaddrinfo.h"
-#include "getnameinfo.h"
-#include "util.h"
-
-#include "base64.h"
-#if !HAVE_SPNEGO
-#include "spnegohelp.h"
-#endif
-#if HAVE_HEIMDAL_KERBEROS
-#if HAVE_GSSAPI_GSSAPI_H
-#include <gssapi/gssapi.h>
-#elif HAVE_GSSAPI_H
-#include <gssapi.h>
-#endif /* HAVE_GSSAPI_GSSAPI_H */
-#else /* HAVE_HEIMDAL_KERBEROS */
-#if HAVE_GSSAPI_GSSAPI_H
-#include <gssapi/gssapi.h>
-#elif HAVE_GSSAPI_H
-#include <gssapi.h>
-#endif /* HAVE_GSSAPI_GSSAPI_H */
-#if HAVE_GSSAPI_GSSAPI_KRB5_H
-#include <gssapi/gssapi_krb5.h>
-#endif /* HAVE_GSSAPI_GSSAPI_KRB5_H */
-#if HAVE_GSSAPI_GSSAPI_GENERIC_H
-#include <gssapi/gssapi_generic.h>
-#endif /* HAVE_GSSAPI_GSSAPI_GENERIC_H */
-#endif /* HAVE_HEIMDAL_KERBEROS */
-#ifndef gss_nt_service_name
-#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
-#endif
-
-#define PROGRAM "squid_kerb_auth"
-
-#ifndef MAX_AUTHTOKEN_LEN
-#define MAX_AUTHTOKEN_LEN 65535
-#endif
-#ifndef SQUID_KERB_AUTH_VERSION
-#define SQUID_KERB_AUTH_VERSION "3.0.1sq"
-#endif
-
-int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
- const char *function, int debug, int log);
-char *gethost_name(void);
-static const char *LogTime(void);
-
-static const unsigned char ntlmProtocol[] =
- { 'N', 'T', 'L', 'M', 'S', 'S', 'P', 0 };
-
-static const char *
-LogTime()
-{
- struct tm *tm;
- struct timeval now;
- static time_t last_t = 0;
- static char buf[128];
-
- gettimeofday(&now, NULL);
- if (now.tv_sec != last_t) {
- tm = localtime((time_t *) & now.tv_sec);
- strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
- last_t = now.tv_sec;
- }
- return buf;
-}
+#include "negotiate_kerberos.h"
char *
gethost_name(void)
{
- char hostname[sysconf(_SC_HOST_NAME_MAX)];
+ /*
+ * char hostname[sysconf(_SC_HOST_NAME_MAX)];
+ */
+ char hostname[1024];
struct addrinfo *hres = NULL, *hres_list;
int rc, count;
- rc = gethostname(hostname, sysconf(_SC_HOST_NAME_MAX));
+ rc = gethostname(hostname, sizeof(hostname)-1);
if (rc) {
- fprintf(stderr, "%s| %s: error while resolving hostname '%s'\n",
- LogTime(), PROGRAM, hostname);
- return NULL;
+ fprintf(stderr, "%s| %s: ERROR: resolving hostname '%s' failed\n",
+ LogTime(), PROGRAM, hostname);
+ return NULL;
}
- rc = xgetaddrinfo(hostname, NULL, NULL, &hres);
+ rc = getaddrinfo(hostname, NULL, NULL, &hres);
if (rc != 0) {
- fprintf(stderr,
- "%s| %s: error while resolving hostname with getaddrinfo: %s\n",
- LogTime(), PROGRAM, xgai_strerror(rc));
- return NULL;
+ fprintf(stderr,
+ "%s| %s: ERROR: resolving hostname with getaddrinfo: %s failed\n",
+ LogTime(), PROGRAM, gai_strerror(rc));
+ return NULL;
}
hres_list = hres;
count = 0;
while (hres_list) {
- count++;
- hres_list = hres_list->ai_next;
+ ++count;
+ hres_list = hres_list->ai_next;
}
- rc = xgetnameinfo(hres->ai_addr, hres->ai_addrlen, hostname,
- sizeof(hostname), NULL, 0, 0);
+ rc = getnameinfo(hres->ai_addr, hres->ai_addrlen, hostname,
+ sizeof(hostname), NULL, 0, 0);
if (rc != 0) {
- fprintf(stderr,
- "%s| %s: error while resolving ip address with getnameinfo: %s\n",
- LogTime(), PROGRAM, xgai_strerror(rc));
- xfreeaddrinfo(hres);
- return NULL;
+ fprintf(stderr,
+ "%s| %s: ERROR: resolving ip address with getnameinfo: %s failed\n",
+ LogTime(), PROGRAM, gai_strerror(rc));
+ freeaddrinfo(hres);
+ return NULL;
}
-
- xfreeaddrinfo(hres);
- hostname[sysconf(_SC_HOST_NAME_MAX) - 1] = '\0';
+ freeaddrinfo(hres);
+ hostname[sizeof(hostname)-1] = '\0';
return (xstrdup(hostname));
}
int
check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
- const char *function, int debug, int log)
+ const char *function, int log, int sout)
{
if (GSS_ERROR(major_status)) {
- OM_uint32 maj_stat, min_stat;
- OM_uint32 msg_ctx = 0;
- gss_buffer_desc status_string;
- char buf[1024];
- size_t len;
-
- len = 0;
- msg_ctx = 0;
- while (!msg_ctx) {
- /* convert major status code (GSS-API error) to text */
- maj_stat = gss_display_status(&min_stat, major_status,
- GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string);
- if (maj_stat == GSS_S_COMPLETE) {
- if (sizeof(buf) > len + status_string.length + 1) {
- sprintf(buf + len, "%s", (char *) status_string.value);
- len += status_string.length;
- }
- gss_release_buffer(&min_stat, &status_string);
- break;
- }
- gss_release_buffer(&min_stat, &status_string);
- }
- if (sizeof(buf) > len + 2) {
- sprintf(buf + len, "%s", ". ");
- len += 2;
- }
- msg_ctx = 0;
- while (!msg_ctx) {
- /* convert minor status code (underlying routine error) to text */
- maj_stat = gss_display_status(&min_stat, minor_status,
- GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string);
- if (maj_stat == GSS_S_COMPLETE) {
- if (sizeof(buf) > len + status_string.length) {
- sprintf(buf + len, "%s", (char *) status_string.value);
- len += status_string.length;
- }
- gss_release_buffer(&min_stat, &status_string);
- break;
- }
- gss_release_buffer(&min_stat, &status_string);
- }
- if (debug)
- fprintf(stderr, "%s| %s: %s failed: %s\n", LogTime(), PROGRAM,
- function, buf);
- fprintf(stdout, "BH %s failed: %s\n", function, buf);
- if (log)
- fprintf(stderr, "%s| %s: User not authenticated\n", LogTime(),
- PROGRAM);
- return (1);
+ OM_uint32 maj_stat, min_stat;
+ OM_uint32 msg_ctx = 0;
+ gss_buffer_desc status_string;
+ char buf[1024];
+ size_t len;
+
+ len = 0;
+ msg_ctx = 0;
+ do {
+ /* convert major status code (GSS-API error) to text */
+ maj_stat = gss_display_status(&min_stat, major_status,
+ GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string);
+ if (maj_stat == GSS_S_COMPLETE && status_string.length > 0) {
+ if (sizeof(buf) > len + status_string.length + 1) {
+ snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value);
+ len += status_string.length;
+ }
+ } else
+ msg_ctx = 0;
+ gss_release_buffer(&min_stat, &status_string);
+ } while (msg_ctx);
+ if (sizeof(buf) > len + 2) {
+ snprintf(buf + len, (sizeof(buf) - len), "%s", ". ");
+ len += 2;
+ }
+ msg_ctx = 0;
+ do {
+ /* convert minor status code (underlying routine error) to text */
+ maj_stat = gss_display_status(&min_stat, minor_status,
+ GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string);
+ if (maj_stat == GSS_S_COMPLETE && status_string.length > 0) {
+ if (sizeof(buf) > len + status_string.length) {
+ snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value);
+ len += status_string.length;
+ }
+ } else
+ msg_ctx = 0;
+ gss_release_buffer(&min_stat, &status_string);
+ } while (msg_ctx);
+ debug((char *) "%s| %s: ERROR: %s failed: %s\n", LogTime(), PROGRAM, function, buf);
+ if (sout)
+ fprintf(stdout, "BH %s failed: %s\n", function, buf);
+ if (log)
+ fprintf(stderr, "%s| %s: INFO: User not authenticated\n", LogTime(),
+ PROGRAM);
+ return (1);
}
return (0);
}
-
-
int
main(int argc, char *const argv[])
{
char buf[MAX_AUTHTOKEN_LEN];
char *c, *p;
char *user = NULL;
- int length = 0;
- static int err = 0;
- int opt, debug = 0, log = 0, norealm = 0;
-#if !HAVE_SPNEGO
- int rc;
+ char *rfc_user = NULL;
+#if HAVE_PAC_SUPPORT
+ char ad_groups[MAX_PAC_GROUP_SIZE];
+ char *ag=NULL;
+ krb5_context context = NULL;
+ krb5_error_code ret;
+ krb5_pac pac;
+#if HAVE_HEIMDAL_KERBEROS
+ gss_buffer_desc data_set = GSS_C_EMPTY_BUFFER;
+#else
+ gss_buffer_desc type_id = GSS_C_EMPTY_BUFFER;
+#endif
#endif
+ 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;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
const unsigned char *kerberosToken = NULL;
-#if !HAVE_SPNEGO
- size_t kerberosTokenLength = 0;
-#endif
const unsigned char *spnegoToken = NULL;
size_t spnegoTokenLength = 0;
setbuf(stdin, NULL);
while (-1 != (opt = getopt(argc, argv, "dirs:h"))) {
- switch (opt) {
- case 'd':
- debug = 1;
- break;
- case 'i':
- log = 1;
- break;
- case 'r':
- norealm = 1;
- break;
- case 's':
- service_principal = xstrdup(optarg);
- break;
- case 'h':
- fprintf(stderr, "Usage: \n");
- fprintf(stderr, "squid_kerb_auth [-d] [-i] [-s SPN] [-h]\n");
- fprintf(stderr, "-d full debug\n");
- fprintf(stderr, "-i informational messages\n");
- fprintf(stderr, "-r remove realm from username\n");
- fprintf(stderr, "-s service principal name\n");
- fprintf(stderr, "-h help\n");
- fprintf(stderr,
- "The SPN can be set to GSS_C_NO_NAME to allow any entry from keytab\n");
- fprintf(stderr, "default SPN is HTTP/fqdn@DEFAULT_REALM\n");
- exit(0);
- default:
- fprintf(stderr, "%s| %s: unknown option: -%c.\n", LogTime(),
- PROGRAM, opt);
- }
+ switch (opt) {
+ case 'd':
+ debug_enabled = 1;
+ break;
+ case 'i':
+ log = 1;
+ break;
+ case 'r':
+ norealm = 1;
+ break;
+ case 's':
+ service_principal = xstrdup(optarg);
+ break;
+ case 'h':
+ fprintf(stderr, "Usage: \n");
+ fprintf(stderr, "squid_kerb_auth [-d] [-i] [-s SPN] [-h]\n");
+ fprintf(stderr, "-d full debug\n");
+ fprintf(stderr, "-i informational messages\n");
+ fprintf(stderr, "-r remove realm from username\n");
+ fprintf(stderr, "-s service principal name\n");
+ fprintf(stderr, "-h help\n");
+ fprintf(stderr,
+ "The SPN can be set to GSS_C_NO_NAME to allow any entry from keytab\n");
+ fprintf(stderr, "default SPN is HTTP/fqdn@DEFAULT_REALM\n");
+ exit(0);
+ default:
+ fprintf(stderr, "%s| %s: WARNING: unknown option: -%c.\n", LogTime(),
+ PROGRAM, opt);
+ }
}
- if (debug)
- fprintf(stderr, "%s| %s: Starting version %s\n", LogTime(), PROGRAM,
- SQUID_KERB_AUTH_VERSION);
+ debug((char *) "%s| %s: INFO: Starting version %s\n", LogTime(), PROGRAM, SQUID_KERB_AUTH_VERSION);
if (service_principal && strcasecmp(service_principal, "GSS_C_NO_NAME")) {
- service.value = service_principal;
- service.length = strlen((char *) service.value);
+ service.value = service_principal;
+ service.length = strlen((char *) service.value);
} else {
- host_name = gethost_name();
- if (!host_name) {
- fprintf(stderr,
- "%s| %s: Local hostname could not be determined. Please specify the service principal\n",
- LogTime(), PROGRAM);
- fprintf(stdout, "BH hostname error\n");
- exit(-1);
- }
- service.value = xmalloc(strlen(service_name) + strlen(host_name) + 2);
- snprintf((char*)service.value, strlen(service_name) + strlen(host_name) + 2,
- "%s@%s", service_name, host_name);
- service.length = strlen((char *) service.value);
+ host_name = gethost_name();
+ if (!host_name) {
+ fprintf(stderr,
+ "%s| %s: FATAL: Local hostname could not be determined. Please specify the service principal\n",
+ LogTime(), PROGRAM);
+ fprintf(stdout, "BH hostname error\n");
+ exit(-1);
+ }
+ service.value = xmalloc(strlen(service_name) + strlen(host_name) + 2);
+ snprintf((char *) service.value, strlen(service_name) + strlen(host_name) + 2,
+ "%s@%s", service_name, host_name);
+ service.length = strlen((char *) service.value);
+ xfree(host_name);
}
while (1) {
- if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
- if (ferror(stdin)) {
- if (debug)
- fprintf(stderr,
- "%s| %s: fgets() failed! dying..... errno=%d (%s)\n",
- LogTime(), PROGRAM, ferror(stdin),
- strerror(ferror(stdin)));
-
- fprintf(stdout, "BH input error\n");
- exit(1); /* BIIG buffer */
- }
- fprintf(stdout, "BH input error\n");
- exit(0);
- }
-
- c = (char*)memchr(buf, '\n', sizeof(buf) - 1);
- if (c) {
- *c = '\0';
- length = c - buf;
- } else {
- err = 1;
- }
- if (err) {
- if (debug)
- fprintf(stderr, "%s| %s: Oversized message\n", LogTime(),
- PROGRAM);
- fprintf(stdout, "BH Oversized message\n");
- err = 0;
- continue;
- }
-
- if (debug)
- fprintf(stderr, "%s| %s: Got '%s' from squid (length: %d).\n",
- LogTime(), PROGRAM, buf, length);
-
- if (buf[0] == '\0') {
- if (debug)
- fprintf(stderr, "%s| %s: Invalid request\n", LogTime(),
- PROGRAM);
- fprintf(stdout, "BH Invalid request\n");
- continue;
- }
-
- if (strlen(buf) < 2) {
- if (debug)
- fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(),
- PROGRAM, buf);
- fprintf(stdout, "BH Invalid request\n");
- continue;
- }
-
- if (!strncmp(buf, "QQ", 2)) {
- gss_release_buffer(&minor_status, &input_token);
- gss_release_buffer(&minor_status, &output_token);
- gss_release_buffer(&minor_status, &service);
- gss_release_cred(&minor_status, &server_creds);
- if (server_name)
- gss_release_name(&minor_status, &server_name);
- 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);
- if (kerberosToken) {
- /* Allocated by parseNegTokenInit, but no matching free function exists.. */
- if (!spnego_flag)
- xfree((char *) kerberosToken);
- kerberosToken = NULL;
- }
- if (spnego_flag) {
- /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
- if (spnegoToken)
- xfree((char *) spnegoToken);
- spnegoToken = NULL;
- }
- if (token) {
- xfree(token);
- token = NULL;
- }
- if (host_name) {
- xfree(host_name);
- host_name = NULL;
- }
- fprintf(stdout, "BH quit command\n");
- exit(0);
- }
-
- if (strncmp(buf, "YR", 2) && strncmp(buf, "KK", 2)) {
- if (debug)
- fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(),
- PROGRAM, buf);
- fprintf(stdout, "BH Invalid request\n");
- continue;
- }
- if (!strncmp(buf, "YR", 2)) {
- if (gss_context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context(&minor_status, &gss_context, NULL);
- gss_context = GSS_C_NO_CONTEXT;
- }
-
- if (strlen(buf) <= 3) {
- if (debug)
- fprintf(stderr, "%s| %s: Invalid negotiate request [%s]\n",
- LogTime(), PROGRAM, buf);
- fprintf(stdout, "BH Invalid negotiate request\n");
- continue;
- }
-
- input_token.length = ska_base64_decode_len(buf + 3);
- if (debug)
- fprintf(stderr, "%s| %s: Decode '%s' (decoded length: %d).\n",
- LogTime(), PROGRAM, buf + 3, (int) input_token.length);
- input_token.value = xmalloc(input_token.length);
-
- ska_base64_decode((char*)input_token.value, buf + 3, input_token.length);
-
+ if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
+ if (ferror(stdin)) {
+ debug((char *) "%s| %s: FATAL: fgets() failed! dying..... errno=%d (%s)\n",
+ LogTime(), PROGRAM, ferror(stdin),
+ strerror(ferror(stdin)));
+
+ fprintf(stdout, "BH input error\n");
+ exit(1); /* BIIG buffer */
+ }
+ fprintf(stdout, "BH input error\n");
+ exit(0);
+ }
+ c = (char *) memchr(buf, '\n', sizeof(buf) - 1);
+ if (c) {
+ *c = '\0';
+ length = c - buf;
+ } else {
+ err = 1;
+ }
+ if (err) {
+ debug((char *) "%s| %s: ERROR: Oversized message\n", LogTime(), PROGRAM);
+ fprintf(stdout, "BH Oversized message\n");
+ err = 0;
+ continue;
+ }
+ debug((char *) "%s| %s: DEBUG: Got '%s' from squid (length: %ld).\n", LogTime(), PROGRAM, buf, length);
-#if !HAVE_SPNEGO
- if ((rc = parseNegTokenInit(input_token.value,
- input_token.length,
- &kerberosToken, &kerberosTokenLength)) != 0) {
- if (debug)
- fprintf(stderr, "%s| %s: parseNegTokenInit failed with rc=%d\n",
- LogTime(), PROGRAM, rc);
+ if (buf[0] == '\0') {
+ debug((char *) "%s| %s: ERROR: Invalid request\n", LogTime(), PROGRAM);
+ fprintf(stdout, "BH Invalid request\n");
+ continue;
+ }
+ if (strlen(buf) < 2) {
+ debug((char *) "%s| %s: ERROR: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
+ fprintf(stdout, "BH Invalid request\n");
+ continue;
+ }
+ if (!strncmp(buf, "QQ", 2)) {
+ gss_release_buffer(&minor_status, &input_token);
+ gss_release_buffer(&minor_status, &output_token);
+ gss_release_buffer(&minor_status, &service);
+ gss_release_cred(&minor_status, &server_creds);
+ if (server_name)
+ gss_release_name(&minor_status, &server_name);
+ 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);
+ if (kerberosToken) {
+ /* Allocated by parseNegTokenInit, but no matching free function exists.. */
+ if (!spnego_flag)
+ xfree(kerberosToken);
+ }
+ if (spnego_flag) {
+ /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
+ xfree(spnegoToken);
+ }
+ xfree(token);
+ fprintf(stdout, "BH quit command\n");
+ exit(0);
+ }
+ if (strncmp(buf, "YR", 2) && strncmp(buf, "KK", 2)) {
+ debug((char *) "%s| %s: ERROR: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
+ fprintf(stdout, "BH Invalid request\n");
+ continue;
+ }
+ if (!strncmp(buf, "YR", 2)) {
+ if (gss_context != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&minor_status, &gss_context, NULL);
+ gss_context = GSS_C_NO_CONTEXT;
+ }
+ if (strlen(buf) <= 3) {
+ debug((char *) "%s| %s: ERROR: Invalid negotiate request [%s]\n", LogTime(), PROGRAM, buf);
+ fprintf(stdout, "BH Invalid negotiate request\n");
+ continue;
+ }
+ input_token.length = (size_t)base64_decode_len(buf+3);
+ debug((char *) "%s| %s: DEBUG: Decode '%s' (decoded length: %d).\n",
+ LogTime(), PROGRAM, buf + 3, (int) input_token.length);
+ input_token.value = xmalloc(input_token.length);
+
+ input_token.length = (size_t)base64_decode((char *) input_token.value, (unsigned int)input_token.length, buf+3);
+
+ if ((input_token.length >= sizeof ntlmProtocol + 1) &&
+ (!memcmp(input_token.value, ntlmProtocol, sizeof ntlmProtocol))) {
+ debug((char *) "%s| %s: WARNING: received type %d NTLM token\n",
+ LogTime(), PROGRAM,
+ (int) *((unsigned char *) input_token.value +
+ sizeof ntlmProtocol));
+ fprintf(stdout, "BH received type %d NTLM token\n",
+ (int) *((unsigned char *) input_token.value +
+ sizeof ntlmProtocol));
+ goto cleanup;
+ }
+ if (service_principal) {
+ if (strcasecmp(service_principal, "GSS_C_NO_NAME")) {
+ major_status = gss_import_name(&minor_status, &service,
+ (gss_OID) GSS_C_NULL_OID, &server_name);
+
+ } else {
+ server_name = GSS_C_NO_NAME;
+ major_status = GSS_S_COMPLETE;
+ minor_status = 0;
+ }
+ } else {
+ major_status = gss_import_name(&minor_status, &service,
+ gss_nt_service_name, &server_name);
+ }
- /* if between 100 and 200 it might be a GSSAPI token and not a SPNEGO token */
- if (rc < 100 || rc > 199) {
- if (debug)
- fprintf(stderr, "%s| %s: Invalid GSS-SPNEGO query [%s]\n",
- LogTime(), PROGRAM, buf);
- fprintf(stdout, "BH Invalid GSS-SPNEGO query\n");
- goto cleanup;
- }
- if ((input_token.length >= sizeof ntlmProtocol + 1) &&
- (!memcmp(input_token.value, ntlmProtocol,
- sizeof ntlmProtocol))) {
- if (debug)
- fprintf(stderr, "%s| %s: received type %d NTLM token\n",
- LogTime(), PROGRAM,
- (int) *((unsigned char *) input_token.value +
- sizeof ntlmProtocol));
- fprintf(stdout, "BH received type %d NTLM token\n",
- (int) *((unsigned char *) input_token.value +
- sizeof ntlmProtocol));
- goto cleanup;
- }
- if (debug)
- fprintf(stderr, "%s| %s: Token is possibly a GSSAPI token\n",
- LogTime(), PROGRAM);
- spnego_flag = 0;
- } else {
- gss_release_buffer(&minor_status, &input_token);
- input_token.length = kerberosTokenLength;
- input_token.value = (void *) kerberosToken;
- spnego_flag = 1;
- }
+ if (check_gss_err(major_status, minor_status, "gss_import_name()", log, 1))
+ goto cleanup;
+
+ major_status =
+ gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
+ GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds, NULL, NULL);
+ if (check_gss_err(major_status, minor_status, "gss_acquire_cred()", log, 1))
+ goto cleanup;
+
+ major_status = gss_accept_sec_context(&minor_status,
+ &gss_context,
+ server_creds,
+ &input_token,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &client_name, NULL, &output_token, &ret_flags, NULL, NULL);
+
+ if (output_token.length) {
+ spnegoToken = (const unsigned char *) output_token.value;
+ spnegoTokenLength = output_token.length;
+ token = (char *) xmalloc((size_t)base64_encode_len((int)spnegoTokenLength));
+ if (token == NULL) {
+ debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
+ fprintf(stdout, "BH Not enough memory\n");
+ goto cleanup;
+ }
+ base64_encode_str(token, base64_encode_len((int)spnegoTokenLength),
+ (const char *) spnegoToken, (int)spnegoTokenLength);
+
+ if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log, 1))
+ 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);
+ goto cleanup;
+ }
+ gss_release_buffer(&minor_status, &output_token);
+ major_status =
+ gss_display_name(&minor_status, client_name, &output_token,
+ NULL);
+
+ 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) {
+ 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) {
+ *p = '\0';
+ }
+
+#if HAVE_PAC_SUPPORT
+ ret = krb5_init_context(&context);
+ if (!check_k5_err(context, "krb5_init_context", ret)) {
+#if HAVE_HEIMDAL_KERBEROS
+#define ADWIN2KPAC 128
+ major_status = gsskrb5_extract_authz_data_from_sec_context(&minor_status,
+ gss_context, ADWIN2KPAC, &data_set);
+ if (!check_gss_err(major_status, minor_status,
+ "gsskrb5_extract_authz_data_from_sec_context()", log, 0)) {
+ ret = krb5_pac_parse(context, data_set.value, data_set.length, &pac);
+ gss_release_buffer(&minor_status, &data_set);
+ if (!check_k5_err(context, "krb5_pac_parse", ret)) {
+ ag = get_ad_groups((char *)&ad_groups, context, pac);
+ krb5_pac_free(context, pac);
+ }
+ krb5_free_context(context);
+ }
#else
- if ((input_token.length >= sizeof ntlmProtocol + 1) &&
- (!memcmp(input_token.value, ntlmProtocol, sizeof ntlmProtocol))) {
- if (debug)
- fprintf(stderr, "%s| %s: received type %d NTLM token\n",
- LogTime(), PROGRAM,
- (int) *((unsigned char *) input_token.value +
- sizeof ntlmProtocol));
- fprintf(stdout, "BH received type %d NTLM token\n",
- (int) *((unsigned char *) input_token.value +
- sizeof ntlmProtocol));
- goto cleanup;
- }
+ type_id.value = (void *)"mspac";
+ type_id.length = strlen((char *)type_id.value);
+#define KRB5PACLOGONINFO 1
+ major_status = gss_map_name_to_any(&minor_status, client_name, KRB5PACLOGONINFO, &type_id, (gss_any_t *)&pac);
+ if (!check_gss_err(major_status, minor_status, "gss_map_name_to_any()", log, 0)) {
+ ag = get_ad_groups((char *)&ad_groups,context, pac);
+ }
+ (void)gss_release_any_name_mapping(&minor_status, client_name, &type_id, (gss_any_t *)&pac);
+ krb5_free_context(context);
#endif
-
- if (service_principal) {
- if (strcasecmp(service_principal, "GSS_C_NO_NAME")) {
- major_status = gss_import_name(&minor_status, &service,
- (gss_OID) GSS_C_NULL_OID, &server_name);
-
- } else {
- server_name = GSS_C_NO_NAME;
- major_status = GSS_S_COMPLETE;
- }
- } else {
- major_status = gss_import_name(&minor_status, &service,
- gss_nt_service_name, &server_name);
- }
-
- if (check_gss_err(major_status, minor_status, "gss_import_name()",
- debug, log))
- goto cleanup;
-
- major_status =
- gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
- GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds, NULL, NULL);
- if (check_gss_err(major_status, minor_status, "gss_acquire_cred()",
- debug, log))
- goto cleanup;
-
- major_status = gss_accept_sec_context(&minor_status,
- &gss_context,
- server_creds,
- &input_token,
- GSS_C_NO_CHANNEL_BINDINGS,
- &client_name, NULL, &output_token, &ret_flags, NULL, NULL);
-
-
- if (output_token.length) {
-#if !HAVE_SPNEGO
- if (spnego_flag) {
- if ((rc = makeNegTokenTarg(output_token.value,
- output_token.length,
- &spnegoToken, &spnegoTokenLength)) != 0) {
- if (debug)
- fprintf(stderr,
- "%s| %s: makeNegTokenTarg failed with rc=%d\n",
- LogTime(), PROGRAM, rc);
- fprintf(stdout, "BH makeNegTokenTarg failed with rc=%d\n",
- rc);
- goto cleanup;
- }
- } else {
- spnegoToken = output_token.value;
- spnegoTokenLength = output_token.length;
- }
-#else
- spnegoToken = (unsigned char *)output_token.value;
- spnegoTokenLength = output_token.length;
+ }
+ if (ag) {
+ debug((char *) "%s| %s: DEBUG: Groups %s\n", LogTime(), PROGRAM, ag);
+ }
#endif
- token = (char*)xmalloc(ska_base64_encode_len(spnegoTokenLength));
- if (token == NULL) {
- if (debug)
- fprintf(stderr, "%s| %s: Not enough memory\n", LogTime(),
- PROGRAM);
- fprintf(stdout, "BH Not enough memory\n");
- goto cleanup;
- }
-
- ska_base64_encode(token, (const char *) spnegoToken,
- ska_base64_encode_len(spnegoTokenLength), spnegoTokenLength);
-
- if (check_gss_err(major_status, minor_status,
- "gss_accept_sec_context()", debug, log))
- goto cleanup;
- if (major_status & GSS_S_CONTINUE_NEEDED) {
- if (debug)
- fprintf(stderr, "%s| %s: continuation needed\n", LogTime(),
- PROGRAM);
- fprintf(stdout, "TT %s\n", token);
- goto cleanup;
- }
- gss_release_buffer(&minor_status, &output_token);
- major_status =
- gss_display_name(&minor_status, client_name, &output_token,
- NULL);
-
- if (check_gss_err(major_status, minor_status, "gss_display_name()",
- debug, log))
- goto cleanup;
- user = (char*)xmalloc(output_token.length + 1);
- if (user == NULL) {
- if (debug)
- fprintf(stderr, "%s| %s: 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) {
- *p = '\0';
- }
- fprintf(stdout, "AF %s %s\n", token, user);
- if (debug)
- fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM, token,
- user);
- if (log)
- fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(),
- PROGRAM, user);
- goto cleanup;
- } else {
- if (check_gss_err(major_status, minor_status,
- "gss_accept_sec_context()", debug, log))
- goto cleanup;
- if (major_status & GSS_S_CONTINUE_NEEDED) {
- if (debug)
- fprintf(stderr, "%s| %s: continuation needed\n", LogTime(),
- PROGRAM);
- fprintf(stdout, "NA %s\n", token);
- goto cleanup;
- }
- gss_release_buffer(&minor_status, &output_token);
- major_status =
- gss_display_name(&minor_status, client_name, &output_token,
- NULL);
+ fprintf(stdout, "AF %s %s\n", token, user);
+ rfc_user = rfc1738_escape(user);
+ debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, token, rfc_user);
+ if (log)
+ fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(),
+ PROGRAM, rfc1738_escape(user));
+ goto cleanup;
+ } else {
+ if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log, 1))
+ 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);
+ goto cleanup;
+ }
+ gss_release_buffer(&minor_status, &output_token);
+ major_status =
+ gss_display_name(&minor_status, client_name, &output_token,
+ NULL);
+
+ if (check_gss_err(major_status, minor_status, "gss_display_name()", log, 1))
+ goto cleanup;
+ /*
+ * Return dummy token AA. May need an extra return tag then AF
+ */
+ user = (char *) xmalloc(output_token.length + 1);
+ if (user == NULL) {
+ 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) {
+ *p = '\0';
+ }
+ fprintf(stdout, "AF %s %s\n", "AA==", user);
+ debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, "AA==", rfc1738_escape(user));
+ if (log)
+ fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(),
+ PROGRAM, rfc1738_escape(user));
- if (check_gss_err(major_status, minor_status, "gss_display_name()",
- debug, log))
- goto cleanup;
- /*
- * Return dummy token AA. May need an extra return tag then AF
- */
- user = (char*)xmalloc(output_token.length + 1);
- if (user == NULL) {
- if (debug)
- fprintf(stderr, "%s| %s: 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) {
- *p = '\0';
- }
- fprintf(stdout, "AF %s %s\n", "AA==", user);
- if (debug)
- fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM,
- "AA==", user);
- if (log)
- fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(),
- PROGRAM, user);
-
- }
- cleanup:
- gss_release_buffer(&minor_status, &input_token);
- gss_release_buffer(&minor_status, &output_token);
- gss_release_cred(&minor_status, &server_creds);
- if (server_name)
- gss_release_name(&minor_status, &server_name);
- if (client_name)
- gss_release_name(&minor_status, &client_name);
- if (kerberosToken) {
- /* Allocated by parseNegTokenInit, but no matching free function exists.. */
- if (!spnego_flag)
- xfree((char *) kerberosToken);
- kerberosToken = NULL;
- }
- if (spnego_flag) {
- /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
- if (spnegoToken)
- xfree((char *) spnegoToken);
- spnegoToken = NULL;
- }
- if (token) {
- xfree(token);
- token = NULL;
- }
- if (user) {
- xfree(user);
- user = NULL;
- }
- continue;
+ }
+cleanup:
+ gss_release_buffer(&minor_status, &input_token);
+ gss_release_buffer(&minor_status, &output_token);
+ gss_release_cred(&minor_status, &server_creds);
+ if (server_name)
+ gss_release_name(&minor_status, &server_name);
+ if (client_name)
+ gss_release_name(&minor_status, &client_name);
+ if (kerberosToken) {
+ /* Allocated by parseNegTokenInit, but no matching free function exists.. */
+ if (!spnego_flag)
+ safe_free(kerberosToken);
+ }
+ if (spnego_flag) {
+ /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
+ safe_free(spnegoToken);
+ }
+ safe_free(token);
+ safe_free(user);
+ continue;
}
}
#else