* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
+ * As a special exemption, M Moeller gives permission to link this program
+ * with MIT, Heimdal or other GSS/Kerberos libraries, and distribute
+ * the resulting executable, without including the source code for
+ * the Libraries in the source distribution.
+ *
* -----------------------------------------------------------------------------
*/
/*
* Hosted at http://sourceforge.net/projects/squidkerbauth
*/
+#include "ska_config.h"
+
+#if HAVE_STRING_H
#include <string.h>
+#endif
+#if HAVE_STDIO_H
#include <stdio.h>
+#endif
+#if HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#if HAVE_NETDB_H
#include <netdb.h>
+#endif
+#if HAVE_UNISTD_H
#include <unistd.h>
+#endif
+#if HAVE_TIME_H
#include <time.h>
+#endif
+#if HAVE_SYS_TIME_H
#include <sys/time.h>
+#endif
-#include "getaddrinfo.h"
-#include "getnameinfo.h"
-#include "base64.h"
-#ifndef HAVE_SPNEGO
-#include "spnegohelp.h"
+#if !defined(HAVE_DECL_XGETADDRINFO) || !HAVE_DECL_XGETADDRINFO
+#define xgetaddrinfo getaddrinfo
+#endif
+#if !defined(HAVE_DECL_XFREEADDRINFO) || !HAVE_DECL_XFREEADDRINFO
+#define xfreeaddrinfo freeaddrinfo
+#endif
+#if !defined(HAVE_DECL_XGAI_STRERROR) || !HAVE_DECL_XGAI_STRERROR
+#define xgai_strerror gai_strerror
+#endif
+#if !defined(HAVE_DECL_XGETNAMEINFO) || !HAVE_DECL_XGETNAMEINFO
+#define xgetnameinfo getnameinfo
+#endif
+#if !defined(HAVE_DECL_XMALLOC) || !HAVE_DECL_XMALLOC
+#define xmalloc malloc
+#endif
+#if !defined(HAVE_DECL_XSTRDUP) || !HAVE_DECL_XSTRDUP
+#define xstrdup strdup
+#endif
+#if !defined(HAVE_DECL_XFREE) || !HAVE_DECL_XFREE
+#define xfree free
#endif
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN HOST_NAME_MAX
+#include "base64.h"
+#ifndef HAVE_SPNEGO
+#include "spnegohelp/spnegohelp.h"
#endif
#define PROGRAM "squid_kerb_auth"
-#ifdef HEIMDAL
-#include <gssapi.h>
-#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
-#else
-#include <gssapi/gssapi.h>
-#ifndef SOLARIS_11
-#include <gssapi/gssapi_generic.h>
-#else
-#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
-#endif
+
+#ifndef MAX_AUTHTOKEN_LEN
+#define MAX_AUTHTOKEN_LEN 65535
#endif
-#include <krb5.h>
-int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int loging);
+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);
gettimeofday(&now, NULL);
if (now.tv_sec != last_t) {
- tm = localtime(&now.tv_sec);
+ tm = localtime((time_t *)&now.tv_sec);
strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
last_t = now.tv_sec;
}
return buf;
}
-// AYJ: this looks like a duplicate of the lib/gethostname function */
-char *gethost_name(void) {
- char hostname[MAXHOSTNAMELEN];
- struct addrinfo *hres=NULL, *hres_list;
- int rc,count;
-
- rc = gethostname(hostname,MAXHOSTNAMELEN);
- if (rc)
- {
- fprintf(stderr, "%s| %s: error while resolving hostname '%s'\n", LogTime(), PROGRAM, hostname);
- return NULL;
+char *gethost_name(void)
+{
+ char hostname[sysconf(_SC_HOST_NAME_MAX)];
+ struct addrinfo *hres=NULL, *hres_list;
+ int rc,count;
+
+ rc = gethostname(hostname,sysconf(_SC_HOST_NAME_MAX));
+ if (rc) {
+ fprintf(stderr, "%s| %s: error while resolving hostname '%s'\n", LogTime(), PROGRAM, hostname);
+ return NULL;
+ }
+ rc = xgetaddrinfo(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;
+ }
+ hres_list=hres;
+ count=0;
+ while (hres_list) {
+ count++;
+ hres_list=hres_list->ai_next;
+ }
+ rc = xgetnameinfo (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 ;
}
- rc = xgetaddrinfo(hostname,NULL,NULL,&hres);
- if (rc != 0) {
- fprintf(stderr, "%s| %s: error while resolving hostname with getaddrinfo: %s\n", LogTime(), PROGRAM, xgai_strerror(rc));
- xfreeaddrinfo(hres);
- return NULL;
- }
- hres_list=hres;
- count=0;
- while (hres_list) {
- count++;
- hres_list=hres_list->ai_next;
- }
- rc = xgetnameinfo(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 ;
- }
- xfreeaddrinfo(hres);
- hostname[MAXHOSTNAMELEN]='\0';
- return(strdup(hostname));
+ xfreeaddrinfo(hres);
+ hostname[sysconf(_SC_HOST_NAME_MAX)-1]='\0';
+ return(xstrdup(hostname));
}
-int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int loging) {
- 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);
+int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int log)
+{
+ 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);
}
- if (debug)
- fprintf(stderr, "%s| %s: %s failed: %s\n", LogTime(), PROGRAM, function, buf);
- fprintf(stdout, "NA %s failed: %s\n",function, buf);
- if (loging)
- fprintf(stderr, "%s| %s: User not authenticated\n", LogTime(), PROGRAM);
- return(1);
- }
- return(0);
+ return(0);
}
int main(int argc, char * const argv[])
{
- char buf[6400];
- char *c;
- int length=0;
- static int err=0;
- int opt, rc, debug=0, loging=0;
- OM_uint32 ret_flags=0, spnego_flag=0;
- char *service_name=(char *)"HTTP",*host_name=NULL;
- char *token = NULL;
- char *service_principal = NULL;
- 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;
- gss_name_t server_name = GSS_C_NO_NAME;
- gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL;
- gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
- 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;
- size_t kerberosTokenLength = 0;
- const unsigned char *spnegoToken = NULL ;
- size_t spnegoTokenLength = 0;
-
- setbuf(stdout,NULL);
- setbuf(stdin,NULL);
-
- while (-1 != (opt = getopt(argc, argv, "dis:h"))) {
- switch (opt) {
- case 'd':
- debug = 1;
- break;
- case 'i':
- loging = 1;
- break;
- case 's':
- service_principal = strdup(optarg);
- break;
- case 'h':
- fprintf(stdout, "Usage: \n");
- fprintf(stdout, "squid_kerb_auth -d [-s SPN]\n");
- fprintf(stdout, "SPN = service principal name\n");
- fprintf(stdout, "Can be set to GSS_C_NO_NAME to allow any entry from keytab\n");
- fprintf(stdout, "default SPN is HTTP/fqdn@DEFAULT_REALM\n");
- break;
- default:
- fprintf(stderr, "%s| %s: unknown option: -%c.\n", LogTime(), PROGRAM, opt);
- }
- }
-
- if (service_principal && strcasecmp(service_principal,"GSS_C_NO_NAME") ) {
- 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);
- exit(-1);
- }
- service.value = malloc(strlen(service_name)+strlen(host_name)+2);
- snprintf(service.value,strlen(service_name)+strlen(host_name)+2,"%s@%s",service_name,host_name);
- service.length = strlen((char *)service.value);
- }
-
- 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)));
-
- exit(1); /* BIIG buffer */
- }
- exit(0);
- }
-
- c=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, "NA Oversized message\n");
- err = 0;
- continue;
+ char buf[MAX_AUTHTOKEN_LEN];
+ char *c;
+ char *user=NULL;
+ int length=0;
+ static int err=0;
+ int opt, debug=0, log=0;
+#ifndef HAVE_SPNEGO
+ int rc;
+#endif
+ OM_uint32 ret_flags=0, spnego_flag=0;
+ char *service_name=(char *)"HTTP",*host_name=NULL;
+ char *token = NULL;
+ char *service_principal = NULL;
+ 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;
+ gss_name_t server_name = GSS_C_NO_NAME;
+ gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL;
+ 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;
+#ifndef HAVE_SPNEGO
+ size_t kerberosTokenLength = 0;
+#endif
+ const unsigned char *spnegoToken = NULL ;
+ size_t spnegoTokenLength = 0;
+
+ setbuf(stdout,NULL);
+ setbuf(stdin,NULL);
+
+ while (-1 != (opt = getopt(argc, argv, "dis:h"))) {
+ switch (opt) {
+ case 'd':
+ debug = 1;
+ break;
+ case 'i':
+ log = 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, "-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);
+ }
}
if (debug)
- fprintf(stderr, "%s| %s: Got '%s' from squid (length: %d).\n", LogTime(), PROGRAM, buf?buf:"NULL",length);
-
- if (buf[0] == '\0') {
- if (debug)
- fprintf(stderr, "%s| %s: Invalid request\n", LogTime(), PROGRAM);
- fprintf(stdout, "NA Invalid request\n");
- continue;
- }
-
- if (strlen(buf) < 2) {
- if (debug)
- fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
- fprintf(stdout, "NA 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);
- gss_release_cred(&minor_status, &delegated_cred);
- gss_release_name(&minor_status, &server_name);
- gss_release_name(&minor_status, &client_name);
- gss_delete_sec_context(&minor_status, &gss_context, NULL);
- if (kerberosToken) {
- /* Allocated by parseNegTokenInit, but no matching free function exists.. */
- if (!spnego_flag)
- free((char *)kerberosToken);
- kerberosToken=NULL;
- }
- if (spnego_flag) {
- /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
- if (spnegoToken)
- free((char *)spnegoToken);
- spnegoToken=NULL;
- }
- if (token) {
- free(token);
- token=NULL;
- }
- if (host_name) {
- free(host_name);
- host_name=NULL;
- }
- 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, "NA 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;
+ fprintf(stderr, "%s| %s: Starting version %s\n", LogTime(), PROGRAM, VERSION);
+ if (service_principal && strcasecmp(service_principal,"GSS_C_NO_NAME") ) {
+ 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(service.value,strlen(service_name)+strlen(host_name)+2,"%s@%s",service_name,host_name);
+ service.length = strlen((char *)service.value);
}
- if (strlen(buf) <= 3) {
- if (debug)
- fprintf(stderr, "%s| %s: Invalid negotiate request [%s]\n", LogTime(), PROGRAM, buf);
- fprintf(stdout, "NA Invalid negotiate request\n");
- continue;
- }
-
- input_token.length = base64_decode_len(buf+3);
- input_token.value = malloc(input_token.length);
+ 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=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(input_token.value,buf+3,input_token.length);
- base64_decode(input_token.value,buf+3,input_token.length);
-
#ifndef 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 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, "NA 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, "NA received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
- goto cleanup;
- }
- spnego_flag=0;
- } else {
- gss_release_buffer(&minor_status, &input_token);
- input_token.length=kerberosTokenLength;
- input_token.value=(void *)kerberosToken;
- spnego_flag=1;
- }
+ 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 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;
+ }
#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, "NA received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
- 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;
+ }
#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,loging) )
- 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,loging) )
- 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,
- &delegated_cred);
-
-
- if (output_token.length) {
+ 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) {
#ifndef 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, "NA makeNegTokenTarg failed with rc=%d\n",rc);
- goto cleanup;
- }
- } else {
- spnegoToken = output_token.value;
- spnegoTokenLength = output_token.length;
- }
+ 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 = output_token.value;
- spnegoTokenLength = output_token.length;
+ spnegoToken = output_token.value;
+ spnegoTokenLength = output_token.length;
#endif
- token = malloc(base64_encode_len(spnegoTokenLength));
- if (token == NULL) {
- if (debug)
- fprintf(stderr, "%s| %s: Not enough memory\n", LogTime(), PROGRAM);
- fprintf(stdout, "NA Not enough memory\n");
- goto cleanup;
- }
-
- base64_encode(token,(const char *)spnegoToken,base64_encode_len(spnegoTokenLength),spnegoTokenLength);
-
- if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,loging) )
- 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,loging) )
- goto cleanup;
- fprintf(stdout, "AF %s %s\n",token,(char *)output_token.value);
- if (debug)
- fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM, token,(char *)output_token.value);
- if (loging)
- fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(), PROGRAM, (char *)output_token.value);
- goto cleanup;
- } else {
- if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,loging) )
- goto cleanup;
- if (major_status & GSS_S_CONTINUE_NEEDED) {
- if (debug)
- fprintf(stderr, "%s| %s: continuation needed\n", LogTime(), PROGRAM);
- fprintf(stdout, "NA No token to return to continue\n");
- 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,loging) )
- goto cleanup;
- /*
- * Return dummy token AA. May need an extra return tag then AF
- */
- fprintf(stdout, "AF %s %s\n","AA==",(char *)output_token.value);
- if (debug)
- fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM, "AA==", (char *)output_token.value);
- if (loging)
- fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(), PROGRAM, (char *)output_token.value);
+ token = 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=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';
+ 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);
+
+ 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=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';
+ 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);
- gss_release_cred(&minor_status, &delegated_cred);
- gss_release_name(&minor_status, &server_name);
- gss_release_name(&minor_status, &client_name);
- if (kerberosToken) {
- /* Allocated by parseNegTokenInit, but no matching free function exists.. */
- if (!spnego_flag)
- free((char *)kerberosToken);
- kerberosToken=NULL;
- }
- if (spnego_flag) {
- /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
- if (spnegoToken)
- free((char *)spnegoToken);
- spnegoToken=NULL;
- }
- if (token) {
- free(token);
- token=NULL;
- }
- continue;
+ 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;
+ }
}
- }
}