diff -rubwBEN 3.4/configure.ac 3.4-mm/configure.ac --- 3.4/configure.ac 2013-08-12 00:01:44.458703000 +0100 +++ 3.4-mm/configure.ac 2013-08-23 13:15:58.440167017 +0100 @@ -1,4 +1,4 @@ -AC_INIT([Squid Web Proxy],[3.4.0.1-BZR],[http://bugs.squid-cache.org/],[squid]) +AC_INIT([Squid Web Proxy],[3.4.0.1],[http://bugs.squid-cache.org/],[squid]) AC_PREREQ(2.61) AC_CONFIG_HEADERS([include/autoconf.h]) AC_CONFIG_AUX_DIR(cfgaux) @@ -1924,6 +1924,21 @@ AC_CHECK_LIB(krb5,profile_release, AC_DEFINE(HAVE_PROFILE_RELEASE,1, [Define to 1 if you have profile_release]),) + AC_CHECK_LIB(krb5,krb5_get_renewed_creds, + AC_DEFINE(HAVE_KRB5_GET_RENEWED_CREDS,1, + [Define to 1 if you have krb5_get_renewed_creds]),) + AC_CHECK_LIB(krb5,krb5_principal_get_realm, + AC_DEFINE(HAVE_KRB5_PRINCIPAL_GET_REALM,1, + [Define to 1 if you have krb5_principal_get_realm]),) + AC_CHECK_LIB(krb5, krb5_get_init_creds_opt_alloc, + AC_DEFINE(HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC,1, + [Define to 1 if you have krb5_get_init_creds_opt_alloc]),) + AC_CHECK_FUNCS(gss_map_name_to_any, + AC_DEFINE(HAVE_GSS_MAP_ANY_TO_ANY,1, + [Define to 1 if you have gss_map_name_to_any]),) + AC_CHECK_FUNCS(gsskrb5_extract_authz_data_from_sec_context, + AC_DEFINE(HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT,1, + [Define to 1 if you have gsskrb5_extract_authz_data_from_sec_context]),) SQUID_CHECK_KRB5_CONTEXT_MEMORY_CACHE SQUID_DEFINE_BOOL(HAVE_KRB5_MEMORY_CACHE,$squid_cv_memory_cache, diff -rubwBEN 3.4/helpers/negotiate_auth/kerberos/Makefile.am 3.4-mm/helpers/negotiate_auth/kerberos/Makefile.am --- 3.4/helpers/negotiate_auth/kerberos/Makefile.am 2013-08-12 00:01:44.458703000 +0100 +++ 3.4-mm/helpers/negotiate_auth/kerberos/Makefile.am 2013-08-23 13:16:29.677167792 +0100 @@ -7,7 +7,7 @@ AM_CPPFLAGS = $(INCLUDES) -I$(srcdir) -negotiate_kerberos_auth_SOURCES = negotiate_kerberos_auth.cc +negotiate_kerberos_auth_SOURCES = negotiate_kerberos_auth.cc negotiate_kerberos_pac.cc negotiate_kerberos_auth_LDFLAGS = negotiate_kerberos_auth_LDADD = \ $(top_builddir)/lib/libmiscencoding.la \ diff -rubwBEN 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc --- 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc 2013-08-12 00:01:44.458703000 +0100 +++ 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc 2013-08-23 18:09:47.440604137 +0100 @@ -36,79 +36,7 @@ #if HAVE_GSSAPI -#if HAVE_STRING_H -#include -#endif -#if HAVE_STDOI_H -#include -#endif -#if HAVE_NETDB_H -#include -#endif -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_TIME_H -#include -#endif - -#include "util.h" -#include "base64.h" - -#if HAVE_GSSAPI_GSSAPI_H -#include -#elif HAVE_GSSAPI_H -#include -#endif - -#if !HAVE_HEIMDAL_KERBEROS -#if HAVE_GSSAPI_GSSAPI_KRB5_H -#include -#endif -#if HAVE_GSSAPI_GSSAPI_GENERIC_H -#include -#endif -#if HAVE_GSSAPI_GSSAPI_EXT_H -#include -#endif -#endif - -#ifndef gss_nt_service_name -#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE -#endif - -#define PROGRAM "negotiate_kerberos_auth" - -#ifndef MAX_AUTHTOKEN_LEN -#define MAX_AUTHTOKEN_LEN 65535 -#endif -#ifndef SQUID_KERB_AUTH_VERSION -#define SQUID_KERB_AUTH_VERSION "3.0.4sq" -#endif - -int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, - const char *function, 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) @@ -213,6 +141,19 @@ char buf[MAX_AUTHTOKEN_LEN]; char *c, *p; char *user = NULL; + char *rfc_user = NULL; +#if defined(HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT) || defined(HAVE_GSS_MAP_NAME_TO_ANY) + 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 int length = 0; static int err = 0; int opt, log = 0, norealm = 0; @@ -284,6 +225,8 @@ 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); + host_name = NULL; } while (1) { @@ -351,10 +294,6 @@ xfree(token); token = NULL; } - if (host_name) { - xfree(host_name); - host_name = NULL; - } fprintf(stdout, "BH quit command\n"); exit(0); } @@ -458,8 +397,44 @@ if (norealm && (p = strchr(user, '@')) != NULL) { *p = '\0'; } + +#if defined(HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT) || defined(HAVE_GSS_MAP_NAME_TO_ANY) + ret = krb5_init_context(&context); + if (!check_k5_err(context, "krb5_init_context", ret)) { +#define ADWIN2KPAC 128 +#if HAVE_HEIMDAL_KERBEROS + 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)) { + 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 + type_id.value = (void *)"mspac"; + type_id.length = strlen((char *)type_id.value); + + major_status = gss_map_name_to_any(&minor_status, client_name, 1, &type_id, (gss_any_t *)&pac); + if (!check_gss_err(major_status, minor_status, "gss_map_name_to_any()", log)) { + 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 (ag) { + debug((char *) "%s| %s: DEBUG: Groups %s\n", LogTime(), PROGRAM, ag); + } +#endif fprintf(stdout, "AF %s %s\n", token, user); - debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, token, rfc1738_escape(user)); + rfc_user = rfc1738_escape(user); + debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, token, rfc_user); + xfree(rfc_user); if (log) fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(), PROGRAM, rfc1738_escape(user)); diff -rubwBEN 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos.h 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos.h --- 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos.h 1970-01-01 01:00:00.000000000 +0100 +++ 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos.h 2013-08-23 13:16:44.088168149 +0100 @@ -0,0 +1,154 @@ +/* + * ----------------------------------------------------------------------------- + * + * Author: Markus Moeller (markus_moeller at compuserve.com) + * + * Copyright (C) 2013 Markus Moeller. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * 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. + * + * ----------------------------------------------------------------------------- + */ + +#if HAVE_STRING_H +#include +#endif +#if HAVE_STDIO_H +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_TIME_H +#include +#endif + +#include "util.h" +#include "base64.h" + +#if HAVE_KRB5_H +#if HAVE_BROKEN_SOLARIS_KRB5_H +#warn "Warning! You have a broken Solaris system header" +#warn "http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6837512" +#if defined(__cplusplus) +#define KRB5INT_BEGIN_DECLS extern "C" { +#define KRB5INT_END_DECLS +KRB5INT_BEGIN_DECLS +#endif +#endif /* HAVE_BROKEN_SOLARIS_KRB5_H */ +#if HAVE_BROKEN_HEIMDAL_KRB5_H +extern "C" { +#include +} +#else +#include +#endif +#endif /* HAVE_KRB5_H */ + +#if HAVE_GSSAPI_GSSAPI_H +#include +#elif HAVE_GSSAPI_H +#include +#endif + +#if !HAVE_HEIMDAL_KERBEROS +#if HAVE_GSSAPI_GSSAPI_KRB5_H +#include +#endif +#if HAVE_GSSAPI_GSSAPI_GENERIC_H +#include +#endif +#if HAVE_GSSAPI_GSSAPI_EXT_H +#include +#endif +#else +#if HAVE_GSSAPI_GSSAPI_KRB5_H +#include +#endif +#endif + +#ifndef gss_nt_service_name +#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE +#endif + +#define PROGRAM "negotiate_kerberos_auth" + +#ifndef MAX_AUTHTOKEN_LEN +#define MAX_AUTHTOKEN_LEN 65535 +#endif +#ifndef SQUID_KERB_AUTH_VERSION +#define SQUID_KERB_AUTH_VERSION "3.0.4sq" +#endif + +typedef struct { + uint16_t length; + uint16_t maxlength; + uint32_t pointer; +} RPC_UNICODE_STRING; + +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; +} + +int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, + const char *function, int log); + +int check_k5_err(krb5_context context, const char *msg, krb5_error_code code); + +char *gethost_name(void); + +#if defined(HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT) || defined(HAVE_GSS_MAP_NAME_TO_ANY) +#define MAX_PAC_GROUP_SIZE 200*60 +void align(int n); +void getustr(RPC_UNICODE_STRING *string); +char **getgids(char **Rids, uint32_t GroupIds, uint32_t GroupCount); +char *getdomaingids(char *ad_groups, uint32_t DomainLogonId, char **Rids, uint32_t GroupCount); +char *getextrasids(char *ad_groups, uint32_t ExtraSids, uint32_t SidCount, uint32_t GroupCount); +uint64_t get6byt_be(void); +uint32_t get4byt(void); +uint16_t get2byt(void); +uint8_t get1byt(void); +char *xstrcpy( char *src, const char*dst); +char *xstrcat( char *src, const char*dst); +int checkustr(RPC_UNICODE_STRING *string); +char *get_ad_groups(char *ad_groups, krb5_context context, krb5_pac pac); +#endif diff -rubwBEN 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc --- 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc 1970-01-01 01:00:00.000000000 +0100 +++ 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc 2013-08-23 17:28:45.042543081 +0100 @@ -0,0 +1,450 @@ +/* + * ----------------------------------------------------------------------------- + * + * Author: Markus Moeller (markus_moeller at compuserve.com) + * + * Copyright (C) 2007 Markus Moeller. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * 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. + * + * ----------------------------------------------------------------------------- + */ + +#include "squid.h" +#include "rfc1738.h" +#include "compat/getaddrinfo.h" +#include "compat/getnameinfo.h" + +#if defined(HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT) || defined(HAVE_GSS_MAP_NAME_TO_ANY) + +#include "negotiate_kerberos.h" + +static int bpos; +static krb5_data *ad_data; +static unsigned char *p; + +int +check_k5_err(krb5_context context, const char *function, krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(context, code); + debug((char *) "%s| %s: ERROR: %s failed: %s\n", LogTime(), PROGRAM, function, errmsg); + fprintf(stderr, "%s| %s: ERROR: %s: %s\n", LogTime(), PROGRAM, function, errmsg); + krb5_free_error_message(context, errmsg); + } + return code; +} + +void +align(int n){ + if ( bpos % n != 0 ) { + int al; + al = (bpos/n); + bpos = bpos+(bpos-n*al); + } +} + +void +getustr(RPC_UNICODE_STRING *string) { + + string->length = (p[bpos]<<0) | (p[bpos+1]<<8); + string->maxlength = (p[bpos+2]<<0) | (p[bpos+2+1]<<8); + string->pointer = (p[bpos+4]<<0) | (p[bpos+4+1]<<8) | (p[bpos+4+2]<<16) | (p[bpos+4+3]<<24); + bpos = bpos+8; + +} + +uint64_t +get6byt_be(void) { + uint64_t var; + + var = ((int64_t)p[bpos+5]<<0) | ((int64_t)p[bpos+4]<<8) | ((int64_t)p[bpos+3]<<16) | ((int64_t)p[bpos+2]<<24) | ((int64_t)p[bpos+1]<<32) | ((int64_t)p[bpos]<<40); + bpos = bpos+6; + + return var; +} + +uint32_t +get4byt(void) { + uint32_t var; + + var=(p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24); + bpos = bpos+4; + + return var; +} + +uint16_t +get2byt(void) { + uint16_t var; + + var=(p[bpos]<<0) | (p[bpos+1]<<8); + bpos = bpos+2; + + return var; +} + +uint8_t +get1byt(void) { + uint8_t var; + + var=(p[bpos]<<0); + bpos = bpos+1; + + return var; +} + +char * +xstrcpy( char *src, const char*dst) { + if (dst) { + if (strlen(dst)>MAX_PAC_GROUP_SIZE) + return NULL; + else + return strcpy(src,dst); + } else + return src; +} + +char * +xstrcat( char *src, const char*dst) { + if (dst) { + if (strlen(src)+strlen(dst)+1>MAX_PAC_GROUP_SIZE) + return NULL; + else + return strcat(src,dst); + } else + return src; +} + + +int +checkustr(RPC_UNICODE_STRING *string) { + uint32_t size,off,len; + + if (string->pointer != 0){ + align(4); + size = (p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24); + bpos = bpos+4; + off = (p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24); + bpos = bpos+4; + len = (p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24); + bpos = bpos+4; + if (len > size || off != 0 || + string->length > string->maxlength || len != string->length/2) { + debug((char *) "%s| %s: ERROR: RPC_UNICODE_STRING encoding error => size: %d len: %d/%d maxlength: %d offset: %d\n", + LogTime(), PROGRAM, size, len, string->length, string->maxlength, off); + return -1; + } + /* UNICODE string */ + bpos = bpos+string->length; + } + return 0; +} + +char ** +getgids(char **Rids, uint32_t GroupIds, uint32_t GroupCount) { + if (GroupIds!= 0){ + uint32_t ngroup; + uint32_t sauth; + int l; + + align(4); + ngroup = get4byt(); + if ( ngroup != GroupCount) { + debug((char *) "%s| %s: ERROR: Group encoding error => GroupCount: %d Array size: %d\n", + LogTime(), PROGRAM, GroupCount, ngroup); + return NULL; + } + debug((char *) "%s| %s: INFO: Found %d rids\n", LogTime(), PROGRAM, GroupCount); + + Rids=(char **)xcalloc(GroupCount*sizeof(char*),1); + for ( l=0; l<(int)GroupCount; l++) { + Rids[l]=(char *)xcalloc(4*sizeof(char),1); + memcpy((void *)Rids[l],(void *)&p[bpos],4); + sauth = get4byt(); + debug((char *) "%s| %s: Info: Got rid: %u\n", LogTime(), PROGRAM, sauth); + /* attribute */ + bpos = bpos+4; + } + } + return Rids; +} + +char * +getdomaingids(char *ad_groups, uint32_t DomainLogonId, char **Rids, uint32_t GroupCount) { + if (DomainLogonId!= 0) { + uint32_t nauth; + uint8_t rev; + uint64_t idauth; + uint32_t sauth; + char dli[256]; + char *ag; + int length; + int l; + + align(4); + + nauth = get4byt(); + + /* prepend rids with DomainID */ + length=1+1+6+nauth*4; + for (l=0; l<(int)GroupCount;l++){ + ag=(char *)xcalloc((length+4)*sizeof(char),1); + memcpy((void *)ag,(const void*)&p[bpos],1); + memcpy((void *)&ag[1],(const void*)&p[bpos+1],1); + ag[1] = ag[1]+1; + memcpy((void *)&ag[2],(const void*)&p[bpos+2],6+nauth*4); + memcpy((void *)&ag[length],(const void*)Rids[l],4); + if (l==0) { + if (!xstrcpy(ad_groups,"group=")) { + debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", + LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups); + } + } else { + if (!xstrcat(ad_groups," group=")) { + debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", + LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups); + } + } + if (!xstrcat(ad_groups,base64_encode_bin(ag, length+4))) { + debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", + LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups); + } + xfree(ag); + xfree(Rids[l]); + } + xfree(Rids); + + /* mainly for debug only */ + rev = get1byt(); + bpos = bpos + 1; /*nsub*/ + idauth = get6byt_be(); + + snprintf(dli,sizeof(dli),"S-%d-%lu",rev,(long unsigned int)idauth); + for ( l=0;l<(int)nauth;l++ ) { + sauth = get4byt(); + snprintf((char *)&dli[strlen(dli)],sizeof(dli)-strlen(dli),"-%u",sauth); + } + debug((char *) "%s| %s: INFO: Got DomainLogonId %s\n", LogTime(), PROGRAM, dli); + } + return ad_groups; +} + +char * +getextrasids(char *ad_groups, uint32_t ExtraSids, uint32_t SidCount, uint32_t GroupCount) { + if (ExtraSids!= 0){ + uint32_t ngroup; + uint32_t *pa; + char *ag; + int length; + int l; + + align(4); + ngroup = get4byt(); + if ( ngroup != SidCount) { + debug((char *) "%s| %s: ERROR: Group encoding error => SidCount: %d Array size: %d\n", + LogTime(), PROGRAM, SidCount, ngroup); + return NULL; + } + debug((char *) "%s| %s: INFO: Found %d ExtraSIDs\n", LogTime(), PROGRAM, SidCount); + + pa=(uint32_t *)xmalloc(SidCount*sizeof(uint32_t)); + for ( l=0; l < (int)SidCount; l++ ){ + pa[l] = get4byt(); + bpos = bpos+4; /* attr */ + } + + for ( l=0; l<(int)SidCount; l++ ){ + char es[256]; + uint32_t nauth; + uint8_t rev; + uint64_t idauth; + uint32_t sauth; + int k; + + if (pa[l] != 0){ + nauth = get4byt(); + + length = 1+1+6+nauth*4; + ag = (char *)xcalloc((length)*sizeof(char),1); + memcpy((void *)ag,(const void*)&p[bpos],length); + if (!ad_groups) { + if (!xstrcpy(ad_groups,"group=")) { + debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", + LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups); + } + } else { + if (!xstrcat(ad_groups," group=")) { + debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", + LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups); + } + } + if (!xstrcat(ad_groups,base64_encode_bin(ag, length+4))) { + debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", + LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups); + } + xfree(ag); + + rev = get1byt(); + bpos = bpos + 1; /* nsub */ + idauth = get6byt_be(); + + snprintf(es,sizeof(es),"S-%d-%lu",rev,(long unsigned int)idauth); + for ( k=0;k<(int)nauth;k++ ) { + sauth = get4byt(); + snprintf((char *)&es[strlen(es)],sizeof(es)-strlen(es),"-%u",sauth); + } + debug((char *) "%s| %s: INFO: Got ExtraSid %s\n", LogTime(), PROGRAM, es); + } + } + xfree(pa); + } + return ad_groups; +} + +char * +get_ad_groups(char *ad_groups, krb5_context context, krb5_pac pac){ + krb5_error_code ret; + RPC_UNICODE_STRING EffectiveName; + RPC_UNICODE_STRING FullName; + RPC_UNICODE_STRING LogonScript; + RPC_UNICODE_STRING ProfilePath; + RPC_UNICODE_STRING HomeDirectory; + RPC_UNICODE_STRING HomeDirectoryDrive; + RPC_UNICODE_STRING LogonServer; + RPC_UNICODE_STRING LogonDomainName; + uint32_t GroupCount=0; + uint32_t GroupIds=0; + uint32_t LogonDomainId=0; + uint32_t SidCount=0; + uint32_t ExtraSids=0; + /* + uint32_t ResourceGroupDomainSid=0; + uint32_t ResourceGroupCount=0; + uint32_t ResourceGroupIds=0; + */ + char **Rids=NULL; + int l=0; + + ad_data = (krb5_data *)xmalloc(sizeof(krb5_data)); + +#define KERB_LOGON_INFO 1 + ret = krb5_pac_get_buffer(context, pac, KERB_LOGON_INFO, ad_data); + if (check_k5_err(context, "krb5_pac_get_buffer", ret)) + goto k5clean; + + p = (unsigned char *)ad_data->data; + + debug((char *) "%s| %s: INFO: Got PAC data of lengh %d\n", + LogTime(), PROGRAM, (int)ad_data->length); + + /* Skip 16 bytes icommon RPC header + * Skip 4 bytes RPC unique pointer referent + * http://msdn.microsoft.com/en-gb/library/cc237933.aspx + */ + /* Some data are pointers to data which follows the main KRB5 LOGON structure => + * So need to read the data + * some logical consistency checks are done when analysineg the pointer data + */ + bpos = 20; + /* 8 bytes LogonTime + * 8 bytes LogoffTime + * 8 bytes KickOffTime + * 8 bytes PasswordLastSet + * 8 bytes PasswordCanChange + * 8 bytes PasswordMustChange + */ + bpos = bpos+48; + getustr(&EffectiveName); + getustr(&FullName); + getustr(&LogonScript); + getustr(&ProfilePath); + getustr(&HomeDirectory); + getustr(&HomeDirectoryDrive); + /* 2 bytes LogonCount + * 2 bytes BadPasswordCount + * 4 bytes UserID + * 4 bytes PrimaryGroupId + */ + bpos = bpos+12; + GroupCount = get4byt(); + GroupIds = get4byt(); + /* 4 bytes UserFlags + * 16 bytes UserSessionKey + */ + bpos = bpos+20; + getustr(&LogonServer); + getustr(&LogonDomainName); + LogonDomainId = get4byt(); + /* 8 bytes Reserved1 + * 4 bytes UserAccountControl + * 4 bytes SubAuthStatus + * 8 bytes LastSuccessfullLogon + * 8 bytes LastFailedLogon + * 4 bytes FailedLogonCount + * 4 bytes Reserved2 + */ + bpos = bpos+40; + SidCount = get4byt(); + ExtraSids = get4byt(); + /* 4 bytes ResourceGroupDomainSid + * 4 bytes ResourceGroupCount + * 4 bytes ResourceGroupIds + */ + bpos = bpos+12; + /* + * Read all data from structure => Now check pointers + */ + if (checkustr(&EffectiveName)<0) + goto k5clean; + if (checkustr(&FullName)<0) + goto k5clean; + if (checkustr(&LogonScript)<0) + goto k5clean; + if (checkustr(&ProfilePath)<0) + goto k5clean; + if (checkustr(&HomeDirectory)<0) + goto k5clean; + if (checkustr(&HomeDirectoryDrive)<0) + goto k5clean; + Rids = getgids(Rids,GroupIds,GroupCount); + if (checkustr(&LogonServer)<0) + goto k5clean; + if (checkustr(&LogonDomainName)<0) + goto k5clean; + ad_groups = getdomaingids(ad_groups,LogonDomainId,Rids,GroupCount); + if ((ad_groups = getextrasids(ad_groups,ExtraSids,SidCount,GroupCount))==NULL) + goto k5clean; + + debug((char *) "%s| %s: INFO: Read %d of %d bytes \n", LogTime(), PROGRAM, bpos, (int)ad_data->length); + krb5_free_data(context, ad_data); + return ad_groups; +k5clean: + for ( l=0; l<(int)GroupCount; l++) { + if (Rids[l]) + xfree(Rids[l]); + } + xfree(Rids); + krb5_free_data(context, ad_data); + return NULL; +} +#endif diff -rubwBEN 3.4/src/peer_proxy_negotiate_auth.cc 3.4-mm/src/peer_proxy_negotiate_auth.cc --- 3.4/src/peer_proxy_negotiate_auth.cc 2013-08-12 00:01:44.458703000 +0100 +++ 3.4-mm/src/peer_proxy_negotiate_auth.cc 2013-08-23 13:16:09.959167303 +0100 @@ -210,19 +210,23 @@ static krb5_keytab_entry entry; static krb5_kt_cursor cursor; static krb5_creds *creds = NULL; -#if HAVE_HEIMDAL_KERBEROS +#if defined(HAVE_HEIMDAL_KERBEROS) && !defined(HAVE_KRB5_GET_RENEWED_CREDS) static krb5_creds creds2; #endif static krb5_principal principal = NULL; static krb5_deltat skew; +#if HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC + krb5_get_init_creds_opt *options; +#else krb5_get_init_creds_opt options; +#endif krb5_error_code code = 0; krb5_deltat rlife; #if HAVE_PROFILE_H && HAVE_KRB5_GET_PROFILE && HAVE_PROFILE_GET_INTEGER && HAVE_PROFILE_RELEASE profile_t profile; #endif -#if HAVE_HEIMDAL_KERBEROS +#if defined(HAVE_HEIMDAL_KERBEROS) && !defined(HAVE_KRB5_GET_RENEWED_CREDS) krb5_kdc_flags flags; krb5_realm *client_realm; #endif @@ -236,7 +240,7 @@ (creds->times.endtime - time(0) > skew) && (creds->times.renew_till - time(0) > 2 * skew)) { if (creds->times.endtime - time(0) < 2 * skew) { -#if !HAVE_HEIMDAL_KERBEROS +#if HAVE_KRB5_GET_RENEWED_CREDS /* renew ticket */ code = krb5_get_renewed_creds(kparam.context, creds, principal, @@ -256,7 +260,11 @@ << error_message(code)); return (1); } +#if HAVE_KRB5_PRINCIPAL_GET_REALM + client_realm = krb5_principal_get_realm(kparam.context, principal); +#else client_realm = krb5_princ_realm(kparam.context, creds2.client); +#endif code = krb5_make_principal(kparam.context, &creds2.server, *client_realm, KRB5_TGS_NAME, *client_realm, NULL); @@ -400,7 +408,11 @@ creds = (krb5_creds *) xmalloc(sizeof(*creds)); memset(creds, 0, sizeof(*creds)); +#if HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC + krb5_get_init_creds_opt_alloc(kparam.context, &options); +#else krb5_get_init_creds_opt_init(&options); +#endif code = krb5_string_to_deltat((char *) MAX_RENEW_TIME, &rlife); if (code != 0 || rlife == 0) { debugs(11, 5, @@ -408,8 +420,14 @@ " : " << error_message(code)); return (1); } +#if HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC + krb5_get_init_creds_opt_set_renew_life(options, rlife); + code = + krb5_get_init_creds_keytab(kparam.context, creds, principal, + keytab, 0, NULL, options); + krb5_get_init_creds_opt_free(kparam.context, options); +#else krb5_get_init_creds_opt_set_renew_life(&options, rlife); - code = krb5_get_init_creds_keytab(kparam.context, creds, principal, keytab, 0, NULL, &options); @@ -413,6 +431,7 @@ code = krb5_get_init_creds_keytab(kparam.context, creds, principal, keytab, 0, NULL, &options); +#endif if (code) { debugs(11, 5, HERE <<