AC_DEFINE(HAVE_KRB5_GET_ERROR_MESSAGE,1,
[Define to 1 if you have krb5_get_error_message]),)
AC_CHECK_DECLS(krb5_kt_free_entry,,,[#include <krb5.h>])
+ AC_CHECK_TYPE(krb5_pac,
+ AC_DEFINE(HAVE_KRB5_PAC,1,
+ [Define to 1 if you have krb5_pac]),,
+ [#include <krb5.h>])
AC_CHECK_LIB(krb5,krb5_kt_free_entry,
AC_DEFINE(HAVE_KRB5_KT_FREE_ENTRY,1,
[Define to 1 if you have krb5_kt_free_entry]),)
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_MSG_CHECKING([for krb5_get_init_creds_free requires krb5_context])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <krb5.h>
+ ]],[[krb5_context context;
+ krb5_get_init_creds_opt *options;
+ krb5_get_init_creds_opt_free(context, options)]])],[
+ AC_DEFINE(HAVE_KRB5_GET_INIT_CREDS_FREE_CONTEXT,1,
+ [Define to 1 if you krb5_get_init_creds_free requires krb5_context])
+ AC_MSG_RESULT(yes)
+ ],[AC_MSG_RESULT(no)],[AC_MSG_RESULT(no)])
+
+
+ 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,
void clean_gd(struct gdstruct *gdsp);
void clean_nd(struct ndstruct *ndsp);
-void clean_ls(struct ndstruct *lssp);
+void clean_ls(struct lsstruct *lssp);
void
clean_gd(struct gdstruct *gdsp)
pp = p;
p = p->next;
}
- if (p->group) {
- xfree(p->group);
- p->group = NULL;
- }
- if (p->domain) {
- xfree(p->domain);
- p->domain = NULL;
- }
- if (pp && pp->next) {
- xfree(pp->next);
- pp->next = NULL;
- }
- if (p == gdsp) {
- xfree(gdsp);
- gdsp = NULL;
- }
+ safe_free(p->group);
+ safe_free(p->domain);
+ if (pp)
+ safe_free(pp->next);
+ if (p == gdsp)
+ safe_free(gdsp);
p = gdsp;
}
}
pp = p;
p = p->next;
}
- if (p->netbios) {
- xfree(p->netbios);
- p->netbios = NULL;
- }
- if (p->domain) {
- xfree(p->domain);
- p->domain = NULL;
- }
- if (pp && pp->next) {
- xfree(pp->next);
- pp->next = NULL;
- }
- if (p == ndsp) {
- xfree(ndsp);
- ndsp = NULL;
- }
+ safe_free(p->netbios);
+ safe_free(p->domain);
+ if (pp)
+ safe_free(pp->next);
+ if (p == ndsp)
+ safe_free(ndsp);
p = ndsp;
}
}
pp = p;
p = p->next;
}
- if (p->lserver) {
- xfree(p->lserver);
- p->lserver = NULL;
- }
- if (p->domain) {
- xfree(p->domain);
- p->domain = NULL;
- }
- if (pp && pp->next) {
- xfree(pp->next);
- pp->next = NULL;
- }
- if (p == lssp) {
- xfree(lssp);
- lssp = NULL;
- }
+ safe_free(p->lserver);
+ safe_free(p->domain);
+ if (pp)
+ safe_free(pp->next);
+ if (p == lssp)
+ safe_free(lssp);
p = lssp;
}
}
void
clean_args(struct main_args *margs)
{
- if (margs->glist) {
- xfree(margs->glist);
- margs->glist = NULL;
- }
- if (margs->ulist) {
- xfree(margs->ulist);
- margs->ulist = NULL;
- }
- if (margs->tlist) {
- xfree(margs->tlist);
- margs->tlist = NULL;
- }
- if (margs->nlist) {
- xfree(margs->nlist);
- margs->nlist = NULL;
- }
- if (margs->llist) {
- xfree(margs->llist);
- margs->llist = NULL;
- }
- if (margs->luser) {
- xfree(margs->luser);
- margs->luser = NULL;
- }
- if (margs->lpass) {
- xfree(margs->lpass);
- margs->lpass = NULL;
- }
- if (margs->lbind) {
- xfree(margs->lbind);
- margs->lbind = NULL;
- }
- if (margs->lurl) {
- xfree(margs->lurl);
- margs->lurl = NULL;
- }
- if (margs->ssl) {
- xfree(margs->ssl);
- margs->ssl = NULL;
- }
- if (margs->ddomain) {
- xfree(margs->ddomain);
- margs->ddomain = NULL;
- }
+ safe_free(margs->glist);
+ safe_free(margs->ulist);
+ safe_free(margs->tlist);
+ safe_free(margs->nlist);
+ safe_free(margs->llist);
+ safe_free(margs->luser);
+ safe_free(margs->lpass);
+ safe_free(margs->lbind);
+ safe_free(margs->lurl);
+ safe_free(margs->ssl);
+ safe_free(margs->ddomain);
if (margs->groups) {
clean_gd(margs->groups);
margs->groups = NULL;
log((char *) "%s| %s: INFO: Got User: %s Netbios Name: %s\n", LogTime(), PROGRAM, up, np);
domain = get_netbios_name(&margs, netbios);
user = nuser;
- xfree(up);
- xfree(np);
+ safe_free(up);
+ safe_free(np);
} else if (domain) {
strup(domain);
*domain = '\0';
else
log((char *) "%s| %s: INFO: Got User: %s Domain: %s\n", LogTime(), PROGRAM, up, domain ? dp : "NULL");
- xfree(up);
- xfree(dp);
+ safe_free(up);
+ safe_free(dp);
if (!strcmp(user, "QQ") && domain && !strcmp(domain, "QQ")) {
clean_args(&margs);
exit(-1);
strup(char *s)
{
while (*s) {
- *s = toupper((unsigned char) *s);
+ *s = (char)toupper((unsigned char) *s);
++s;
}
}
int create_ls(struct main_args *margs);
#ifdef HAVE_KRB5
-int krb5_create_cache(struct main_args *margs, char *domain);
+int krb5_create_cache(char *domain);
void krb5_cleanup(void);
#endif
-int get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, int nhosts, char *domain);
-int get_hostname_list(struct main_args *margs, struct hstruct **hlist, int nhosts, char *name);
-int free_hostname_list(struct hstruct **hlist, int nhosts);
+size_t get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, size_t nhosts, char *domain);
+size_t get_hostname_list(struct hstruct **hlist, size_t nhosts, char *name);
+size_t free_hostname_list(struct hstruct **hlist, size_t nhosts);
#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
int tool_sasl_bind(LDAP * ld, char *binddn, char *ssl);
#include "support.h"
struct gdstruct *init_gd(void);
+void free_gd(struct gdstruct *gdsp);
struct gdstruct *
init_gd(void) {
char *
utf8dup(struct main_args *margs)
{
- int c = 0, s;
+ size_t c = 0;
+ unsigned char s;
size_t n;
char *src;
unsigned char *p, *dupp;
*p = 194;
++p;
*p = s;
- } else if (s > 191 && s < 256) {
+ } else if (s > 191) {
*p = 195;
++p;
*p = s - 64;
return NULL;
char *upd = strrchr(up, '@');
- size_t a = (upd ? (upd - up) : strlen(up) );
+ size_t a = (upd ? (size_t)(upd - up) : strlen(up) );
char *ul = (char *) xmalloc(strlen(up)+1);
size_t n = 0;
if (iUTF2) {
if (iUTF2 == 0xC2 && ichar > 0x7F && ichar < 0xC0) {
iUTF2 = 0;
- ul[nl - 1] = ichar;
+ ul[nl - 1] = (char)ichar;
} else if (iUTF2 == 0xC3 && ichar > 0x7F && ichar < 0xC0) {
iUTF2 = 0;
- ul[nl - 1] = ichar + 64;
+ ul[nl - 1] = (char)(ichar + 64);
} else if (iUTF2 > 0xC3 && iUTF2 < 0xE0 && ichar > 0x7F && ichar < 0xC0) {
iUTF2 = 0;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else {
iUTF2 = 0;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
ul[nl + 1] = '\0';
debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
xfree(ul);
} else if (iUTF3) {
if (iUTF3 == 0xE0 && ichar > 0x9F && ichar < 0xC0) {
iUTF3 = 1;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else if (iUTF3 > 0xE0 && iUTF3 < 0xED && ichar > 0x7F && ichar < 0xC0) {
iUTF3 = 2;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else if (iUTF3 == 0xED && ichar > 0x7F && ichar < 0xA0) {
iUTF3 = 3;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else if (iUTF3 > 0xED && iUTF3 < 0xF0 && ichar > 0x7F && ichar < 0xC0) {
iUTF3 = 4;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else if (iUTF3 > 0 && iUTF3 < 5 && ichar > 0x7F && ichar < 0xC0) {
iUTF3 = 0;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else {
iUTF3 = 0;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
ul[nl + 1] = '\0';
debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
xfree(ul);
} else if (iUTF4) {
if (iUTF4 == 0xF0 && ichar > 0x8F && ichar < 0xC0) {
iUTF4 = 1;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else if (iUTF4 > 0xF0 && iUTF3 < 0xF4 && ichar > 0x7F && ichar < 0xC0) {
iUTF4 = 2;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else if (iUTF4 == 0xF4 && ichar > 0x7F && ichar < 0x90) {
iUTF4 = 3;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else if (iUTF4 > 0 && iUTF4 < 5 && ichar > 0x7F && ichar < 0xC0) {
if (iUTF4 == 4)
iUTF4 = 0;
else
iUTF4 = 4;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else {
iUTF4 = 0;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
ul[nl + 1] = '\0';
debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
xfree(ul);
}
} else if (ichar < 0x80) {
/* UTF1 */
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else if (ichar > 0xC1 && ichar < 0xE0) {
/* UTF2 (Latin) */
iUTF2 = ichar;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else if (ichar > 0xDF && ichar < 0xF0) {
/* UTF3 */
iUTF3 = ichar;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else if (ichar > 0xEF && ichar < 0xF5) {
/* UTF4 */
iUTF4 = ichar;
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
++nl;
} else {
- ul[nl] = ichar;
+ ul[nl] = (char)ichar;
ul[nl + 1] = '\0';
debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
xfree(ul);
krb5_context context;
char *mem_cache_env;
krb5_ccache cc;
-} kparam;
+};
+
+static struct kstruct kparam;
#define KT_PATH_MAX 256
* create Kerberos memory cache
*/
int
-krb5_create_cache(struct main_args *margs, char *domain)
+krb5_create_cache(char *domain)
{
krb5_keytab keytab = 0;
krb5_keytab_entry entry;
krb5_kt_cursor cursor;
krb5_creds *creds = NULL;
- krb5_creds *tgt_creds = NULL;
krb5_principal *principal_list = NULL;
krb5_principal principal = NULL;
char *service;
char *keytab_name = NULL, *principal_name = NULL, *mem_cache = NULL;
char buf[KT_PATH_MAX], *p;
- int nprinc = 0;
- int i;
+ size_t j,nprinc = 0;
int retval = 0;
- int found = 0;
krb5_error_code code = 0;
kparam.context = NULL;
nprinc = 0;
while ((code = krb5_kt_next_entry(kparam.context, keytab, &entry, &cursor)) == 0) {
+ int found = 0;
principal_list = (krb5_principal *) xrealloc(principal_list, sizeof(krb5_principal) * (nprinc + 1));
krb5_copy_principal(kparam.context, entry.principal, &principal_list[nprinc++]);
* if no principal name found in keytab for domain use the prinipal name which can get a TGT
*/
if (!principal_name) {
+ size_t i;
debug((char *) "%s| %s: DEBUG: Did not find a principal in keytab for domain %s.\n", LogTime(), PROGRAM, domain);
debug((char *) "%s| %s: DEBUG: Try to get principal of trusted domain.\n", LogTime(), PROGRAM);
- creds = (krb5_creds *) xmalloc(sizeof(*creds));
- memset(creds, 0, sizeof(*creds));
for (i = 0; i < nprinc; ++i) {
+ krb5_creds *tgt_creds = NULL;
+ creds = (krb5_creds *) xmalloc(sizeof(*creds));
+ memset(creds, 0, sizeof(*creds));
/*
* get credentials
*/
snprintf(service, strlen("krbtgt") + 2 * strlen(domain) + 3, "krbtgt/%s@%s", domain, domain);
creds->client = principal_list[i];
code = krb5_parse_name(kparam.context, service, &creds->server);
- if (service)
- xfree(service);
+ xfree(service);
code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0);
#endif
if (code) {
snprintf(service, strlen("krbtgt") + strlen(domain) + strlen(krb5_princ_realm(kparam.context, principal_list[i])->data) + 3, "krbtgt/%s@%s", domain, krb5_princ_realm(kparam.context, principal_list[i])->data);
#endif
code = krb5_parse_name(kparam.context, service, &creds->server);
- if (service)
- xfree(service);
+ xfree(service);
if (code) {
error((char *) "%s| %s: ERROR: Error while initialising TGT credentials : %s\n", LogTime(), PROGRAM, error_message(code));
goto loop_end;
goto loop_end;
} else {
debug((char *) "%s| %s: DEBUG: Found trusted principal name: %s\n", LogTime(), PROGRAM, principal_name);
- found = 1;
break;
}
loop_end:
- if (principal_name)
- xfree(principal_name);
- principal_name = NULL;
+ safe_free(principal_name);
+ if (tgt_creds) {
+ krb5_free_creds(kparam.context, tgt_creds);
+ tgt_creds = NULL;
+ }
+ if (creds)
+ krb5_free_creds(kparam.context, creds);
+ creds = NULL;
+
}
- if (tgt_creds)
- krb5_free_creds(kparam.context, tgt_creds);
- tgt_creds = NULL;
+ safe_free(principal_name);
if (creds)
krb5_free_creds(kparam.context, creds);
creds = NULL;
snprintf(service, strlen("krbtgt") + 2 * strlen(domain) + 3, "krbtgt/%s@%s", domain, domain);
creds->client = principal;
code = krb5_parse_name(kparam.context, service, &creds->server);
- if (service)
- xfree(service);
+ xfree(service);
code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0);
#endif
if (code) {
cleanup:
if (keytab)
krb5_kt_close(kparam.context, keytab);
- if (keytab_name)
- xfree(keytab_name);
- if (principal_name)
- xfree(principal_name);
- if (mem_cache)
- xfree(mem_cache);
+ xfree(keytab_name);
+ xfree(principal_name);
+ xfree(mem_cache);
if (principal)
krb5_free_principal(kparam.context, principal);
- for (i = 0; i < nprinc; ++i) {
- if (principal_list[i])
- krb5_free_principal(kparam.context, principal_list[i]);
+ for (j = 0; j < nprinc; ++j) {
+ if (principal_list[j])
+ krb5_free_principal(kparam.context, principal_list[j]);
}
- if (principal_list)
- xfree(principal_list);
+ xfree(principal_list);
if (creds)
krb5_free_creds(kparam.context, creds);
char *convert_domain_to_bind_path(char *domain);
char *escape_filter(char *filter);
int check_AD(struct main_args *margs, LDAP * ld);
-int ldap_set_defaults(struct main_args *margs, LDAP * ld);
+int ldap_set_defaults(LDAP * ld);
int ldap_set_ssl_defaults(struct main_args *margs);
LDAP *tool_ldap_open(struct main_args *margs, char *host, int port, char *ssl);
#define FILTER_AD "(samaccountname=%s)"
#define ATTRIBUTE_AD "memberof"
-int get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char *attribute /* IN */ , char ***out_val /* OUT (caller frees) */ );
+size_t get_attributes(LDAP * ld, LDAPMessage * res, const char *attribute /* IN */ , char ***out_val /* OUT (caller frees) */ );
int search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_group, char *group, int depth);
#if defined(HAVE_SUN_LDAP_SDK) || defined(HAVE_MOZILLA_LDAP_SDK)
convert_domain_to_bind_path(char *domain)
{
char *dp, *bindp = NULL, *bp = NULL;
- int i = 0;
+ size_t i = 0;
if (!domain)
return NULL;
char *
escape_filter(char *filter)
{
- int i;
char *ldap_filter_esc, *ldf;
+ size_t i;
i = 0;
for (ldap_filter_esc = filter; *ldap_filter_esc; ++ldap_filter_esc) {
*ldf = '\0';
return ldap_filter_esc;
-};
+}
int
check_AD(struct main_args *margs, LDAP * ld)
LDAPMessage *res;
char **attr_value = NULL;
struct timeval searchtime;
- int max_attr = 0;
- int j, rc = 0;
+ size_t max_attr = 0;
+ int rc = 0;
#define FILTER_SCHEMA "(objectclass=*)"
#define ATTRIBUTE_SCHEMA "schemaNamingContext"
NULL, NULL, &searchtime, 0, &res);
if (rc == LDAP_SUCCESS)
- max_attr = get_attributes(margs, ld, res, ATTRIBUTE_SCHEMA, &attr_value);
+ max_attr = get_attributes(ld, res, ATTRIBUTE_SCHEMA, &attr_value);
if (max_attr == 1) {
ldap_msgfree(res);
* Cleanup
*/
if (attr_value) {
+ size_t j;
for (j = 0; j < max_attr; ++j) {
xfree(attr_value[j]);
}
- xfree(attr_value);
- attr_value = NULL;
+ safe_free(attr_value);
}
ldap_msgfree(res);
return rc;
{
LDAPMessage *res = NULL;
char **attr_value = NULL;
- int max_attr = 0;
+ size_t max_attr = 0;
char *filter = NULL;
char *search_exp = NULL;
- int j, rc = 0, retval = 0;
- char *av = NULL, *avp = NULL;
+ size_t j;
+ int rc = 0, retval = 0;
int ldepth;
char *ldap_filter_esc = NULL;
struct timeval searchtime;
debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
if (margs->AD)
- max_attr = get_attributes(margs, ld, res, ATTRIBUTE_AD, &attr_value);
+ max_attr = get_attributes(ld, res, ATTRIBUTE_AD, &attr_value);
else
- max_attr = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value);
+ max_attr = get_attributes(ld, res, ATTRIBUTE, &attr_value);
/*
* Compare group names
retval = 0;
ldepth = depth + 1;
for (j = 0; j < max_attr; ++j) {
+ char *av = NULL;
/* Compare first CN= value assuming it is the same as the group name itself */
av = attr_value[j];
if (!strncasecmp("CN=", av, 3)) {
+ char *avp = NULL;
av += 3;
if ((avp = strchr(av, ','))) {
*avp = '\0';
}
if (debug_enabled) {
int n;
- debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
+ debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
for (n = 0; av[n] != '\0'; ++n)
fprintf(stderr, "%02x", (unsigned char) av[n]);
fprintf(stderr, "\n");
}
if (!strcasecmp(group, av)) {
retval = 1;
- debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
break;
} else
- debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
/*
* Do recursive group search
*/
if (search_group_tree(margs, ld, bindp, av, group, ldepth)) {
retval = 1;
if (!strncasecmp("CN=", av, 3)) {
+ char *avp = NULL;
av += 3;
if ((avp = strchr(av, ','))) {
*avp = '\0';
}
}
if (debug_enabled)
- debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" is member of group named \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" is member of group named \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
else
break;
for (j = 0; j < max_attr; ++j) {
xfree(attr_value[j]);
}
- xfree(attr_value);
- attr_value = NULL;
+ safe_free(attr_value);
}
ldap_msgfree(res);
}
int
-ldap_set_defaults(struct main_args *margs, LDAP * ld)
+ldap_set_defaults(LDAP * ld)
{
int val, rc = 0;
#ifdef LDAP_OPT_NETWORK_TIMEOUT
#endif
#ifdef HAVE_OPENLDAP
int val;
- char *ssl_cacertfile = NULL;
- int free_path;
#elif defined(HAVE_LDAPSSL_CLIENT_INIT)
char *ssl_certdbpath = NULL;
#endif
#ifdef HAVE_OPENLDAP
if (!margs->rc_allow) {
+ char *ssl_cacertfile = NULL;
+ int free_path;
debug((char *) "%s| %s: DEBUG: Enable server certificate check for ldap server.\n", LogTime(), PROGRAM);
val = LDAP_OPT_X_TLS_DEMAND;
rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ssl_cacertfile);
if (ssl_cacertfile && free_path) {
xfree(ssl_cacertfile);
- ssl_cacertfile = NULL;
}
if (rc != LDAP_OPT_SUCCESS) {
error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0, NULL, 0);
debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM);
}
- if (ssl_certdbpath) {
- xfree(ssl_certdbpath);
- ssl_certdbpath = NULL;
- }
+ xfree(ssl_certdbpath);
if (rc != LDAP_SUCCESS) {
error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM, ldapssl_err2string(rc));
return rc;
return LDAP_SUCCESS;
}
-int
-get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char *attribute, char ***ret_value)
+size_t
+get_attributes(LDAP * ld, LDAPMessage * res, const char *attribute, char ***ret_value)
{
LDAPMessage *msg;
char **attr_value = NULL;
- int max_attr = 0;
+ size_t max_attr = 0;
attr_value = *ret_value;
/*
if ((values = ldap_get_values_len(ld, msg, attr)) != NULL) {
for (il = 0; values[il] != NULL; ++il) {
- attr_value = (char **) xrealloc(attr_value, (il + 1) * sizeof(char *));
+ attr_value = (char **) xrealloc(attr_value, (max_attr + 1) * sizeof(char *));
if (!attr_value)
break;
- attr_value[il] = (char *) xmalloc(values[il]->bv_len + 1);
- memcpy(attr_value[il], values[il]->bv_val, values[il]->bv_len);
- attr_value[il][values[il]->bv_len] = 0;
+ attr_value[max_attr] = (char *) xmalloc(values[il]->bv_len + 1);
+ memcpy(attr_value[max_attr], values[il]->bv_val, values[il]->bv_len);
+ attr_value[max_attr][values[il]->bv_len] = 0;
+ max_attr++;
}
- max_attr = il;
}
ber_bvecfree(values);
}
}
}
- debug((char *) "%s| %s: DEBUG: %d ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM, max_attr, max_attr > 1 || max_attr == 0 ? "ies" : "y", attribute);
+ debug((char *) "%s| %s: DEBUG: %ld ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM, max_attr, max_attr > 1 || max_attr == 0 ? "ies" : "y", attribute);
*ret_value = attr_value;
return max_attr;
if (rc != LDAP_SUCCESS) {
error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
xfree(ldapuri);
- xfree(url);
+ ldap_free_urldesc(url);
return NULL;
}
#else
#error "No URL parsing function"
#endif
- safe_free(url);
+ ldap_free_urldesc(url);
rc = ldap_initialize(&ld, ldapuri);
xfree(ldapuri);
if (rc != LDAP_SUCCESS) {
#else
ld = ldap_init(host, port);
#endif
- rc = ldap_set_defaults(margs, ld);
+ rc = ldap_set_defaults(ld);
if (rc != LDAP_SUCCESS) {
error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind(ld);
if (rc != LDAP_SUCCESS) {
error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
xfree(ldapuri);
- xfree(url);
+ ldap_free_urldesc(url);
return NULL;
}
#else
#error "No URL parsing function"
#endif
- safe_free(url);
+ ldap_free_urldesc(url);
rc = ldap_initialize(&ld, ldapuri);
xfree(ldapuri);
if (rc != LDAP_SUCCESS) {
ld = NULL;
return NULL;
}
- rc = ldap_set_defaults(margs, ld);
+ rc = ldap_set_defaults(ld);
if (rc != LDAP_SUCCESS) {
error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind(ld);
ld = NULL;
return NULL;
}
- rc = ldap_set_defaults(margs, ld);
+ rc = ldap_set_defaults(ld);
if (rc != LDAP_SUCCESS) {
error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind(ld);
char *filter = NULL;
char *search_exp;
struct timeval searchtime;
- int i, j, rc = 0, kc = 1;
+ int rc = 0, kc = 1;
int retval;
char **attr_value = NULL;
- char *av = NULL, *avp = NULL;
- int max_attr = 0;
+ size_t max_attr = 0;
struct hstruct *hlist = NULL;
- int nhosts = 0;
- char *hostname;
- char *host;
- int port;
- char *ssl = NULL;
- char *p;
+ size_t nhosts = 0;
char *ldap_filter_esc = NULL;
searchtime.tv_sec = SEARCH_TIMEOUT;
debug((char *) "%s| %s: DEBUG: Setup Kerberos credential cache\n", LogTime(), PROGRAM);
#ifdef HAVE_KRB5
- kc = krb5_create_cache(margs, domain);
+ kc = krb5_create_cache(domain);
if (kc) {
error((char *) "%s| %s: ERROR: Error during setup of Kerberos credential cache\n", LogTime(), PROGRAM);
}
debug((char *) "%s| %s: DEBUG: Initialise ldap connection\n", LogTime(), PROGRAM);
if (domain && !kc) {
+ size_t i;
if (margs->ssl) {
debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM);
}
*/
nhosts = get_ldap_hostname_list(margs, &hlist, 0, domain);
for (i = 0; i < nhosts; ++i) {
- port = 389;
+ int port = 389;
if (hlist[i].port != -1)
port = hlist[i].port;
debug((char *) "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n", LogTime(), PROGRAM, hlist[i].host, port);
bindp = convert_domain_to_bind_path(domain);
}
if ((!domain || !ld) && margs->lurl && strstr(margs->lurl, "://")) {
+ char *hostname;
+ char *host;
+ int port;
+ char *ssl = NULL;
+ char *p;
+ size_t i;
/*
* If username does not contain a domain and a url was given then try it
*/
++p;
port = atoi(p);
}
- nhosts = get_hostname_list(margs, &hlist, 0, host);
- safe_free(host);
+ nhosts = get_hostname_list(&hlist, 0, host);
+ xfree(host);
for (i = 0; i < nhosts; ++i) {
ld = tool_ldap_open(margs, hlist[i].host, port, ssl);
debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
if (ldap_count_entries(ld, res) != 0) {
+ size_t k;
if (margs->AD)
- max_attr = get_attributes(margs, ld, res, ATTRIBUTE_AD, &attr_value);
+ max_attr = get_attributes(ld, res, ATTRIBUTE_AD, &attr_value);
else {
- max_attr = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value);
+ max_attr = get_attributes(ld, res, ATTRIBUTE, &attr_value);
}
/*
* Compare group names
*/
retval = 0;
- for (j = 0; j < max_attr; ++j) {
+ for (k = 0; k < max_attr; ++k) {
+ char *av = NULL;
/* Compare first CN= value assuming it is the same as the group name itself */
- av = attr_value[j];
+ av = attr_value[k];
if (!strncasecmp("CN=", av, 3)) {
+ char *avp = NULL;
av += 3;
if ((avp = strchr(av, ','))) {
*avp = '\0';
}
if (debug_enabled) {
int n;
- debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
+ debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, k + 1, av);
for (n = 0; av[n] != '\0'; ++n)
fprintf(stderr, "%02x", (unsigned char) av[n]);
fprintf(stderr, "\n");
if (!strcasecmp(group, av)) {
retval = 1;
if (debug_enabled)
- debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, k + 1, av, group);
else
break;
} else
- debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, k + 1, av, group);
}
/*
* Do recursive group search for AD only since posixgroups can not contain other groups
*/
if (!retval && margs->AD) {
+ size_t j;
if (debug_enabled && max_attr > 0) {
debug((char *) "%s| %s: DEBUG: Perform recursive group search\n", LogTime(), PROGRAM);
}
for (j = 0; j < max_attr; ++j) {
+ char *av = NULL;
av = attr_value[j];
if (search_group_tree(margs, ld, bindp, av, group, 1)) {
retval = 1;
if (!strncasecmp("CN=", av, 3)) {
+ char *avp = NULL;
av += 3;
if ((avp = strchr(av, ','))) {
*avp = '\0';
}
}
if (debug_enabled)
- debug((char *) "%s| %s: DEBUG: Entry %d group \"%s\" is (in)direct member of group \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %ld group \"%s\" is (in)direct member of group \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
else
break;
}
* Cleanup
*/
if (attr_value) {
+ size_t j;
for (j = 0; j < max_attr; ++j) {
xfree(attr_value[j]);
}
- xfree(attr_value);
- attr_value = NULL;
+ safe_free(attr_value);
}
ldap_msgfree(res);
} else if (ldap_count_entries(ld, res) == 0 && margs->AD) {
debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
- max_attr = get_attributes(margs, ld, res, ATTRIBUTE_GID, &attr_value);
+ max_attr = get_attributes(ld, res, ATTRIBUTE_GID, &attr_value);
if (max_attr == 1) {
char **attr_value_2 = NULL;
- int max_attr_2 = 0;
+ size_t max_attr_2 = 0;
ldap_msgfree(res);
filter = (char *) FILTER_GID;
NULL, NULL, &searchtime, 0, &res);
xfree(search_exp);
- max_attr_2 = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value_2);
+ max_attr_2 = get_attributes(ld, res, ATTRIBUTE, &attr_value_2);
/*
* Compare group names
*/
retval = 0;
if (max_attr_2 == 1) {
-
/* Compare first CN= value assuming it is the same as the group name itself */
- av = attr_value_2[0];
+ char *av = attr_value_2[0];
if (!strcasecmp(group, av)) {
retval = 1;
debug((char *) "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, av, group);
* Cleanup
*/
if (attr_value_2) {
+ size_t j;
for (j = 0; j < max_attr_2; ++j) {
xfree(attr_value_2[j]);
}
- xfree(attr_value_2);
- attr_value_2 = NULL;
+ safe_free(attr_value_2);
}
ldap_msgfree(res);
* Cleanup
*/
if (attr_value) {
+ size_t j;
for (j = 0; j < max_attr; ++j) {
xfree(attr_value[j]);
}
- xfree(attr_value);
- attr_value = NULL;
+ safe_free(attr_value);
}
}
rc = ldap_unbind(ld);
const char *
LogTime()
{
- struct tm *tm;
- struct timeval now;
static time_t last_t = 0;
+ struct timeval now;
static char buf[128];
gettimeofday(&now, NULL);
if (now.tv_sec != last_t) {
+ struct tm *tm;
time_t tmp = now.tv_sec;
tm = localtime(&tmp);
strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
#include "support.h"
struct lsstruct *init_ls(void);
+void free_ls(struct lsstruct *lssp);
struct lsstruct *
init_ls(void) {
#include "support.h"
struct ndstruct *init_nd(void);
+void free_nd(struct ndstruct *ndsp);
struct ndstruct *
init_nd(void) {
sort(struct hstruct *array, int nitems, int (*cmp) (struct hstruct *, struct hstruct *), int begin, int end)
{
if (end > begin) {
- int pivot = begin;
int l = begin + 1;
int r = end;
while (l < r) {
+ int pivot = begin;
if (cmp(&array[l], &array[pivot]) <= 0) {
l += 1;
} else {
static void
msort(struct hstruct *array, size_t nitems, int (*cmp) (struct hstruct *, struct hstruct *))
{
- sort(array, nitems, cmp, 0, nitems - 1);
+ sort(array, (int)nitems, cmp, 0, (int)(nitems - 1));
}
static int
return 0;
}
-int
-free_hostname_list(struct hstruct **hlist, int nhosts)
+size_t
+free_hostname_list(struct hstruct **hlist, size_t nhosts)
{
struct hstruct *hp = NULL;
- int i;
+ size_t i;
hp = *hlist;
for (i = 0; i < nhosts; ++i) {
- if (hp[i].host)
- xfree(hp[i].host);
- hp[i].host = NULL;
+ xfree(hp[i].host);
}
- if (hp)
- xfree(hp);
- hp = NULL;
+ safe_free(hp);
*hlist = hp;
return 0;
}
-int
-get_hostname_list(struct main_args *margs, struct hstruct **hlist, int nhosts, char *name)
+size_t
+get_hostname_list(struct hstruct **hlist, size_t nhosts, char *name)
{
- /*
- * char host[sysconf(_SC_HOST_NAME_MAX)];
- */
- char host[1024];
struct addrinfo *hres = NULL, *hres_list;
int rc, count;
struct hstruct *hp = NULL;
hres_list = hres;
count = 0;
while (hres_list) {
+ /*
+ * char host[sysconf(_SC_HOST_NAME_MAX)];
+ */
+ char host[1024];
rc = getnameinfo(hres_list->ai_addr, hres_list->ai_addrlen, host, sizeof(host), NULL, 0, 0);
if (rc != 0) {
error((char *) "%s| %s: ERROR: Error while resolving ip address with getnameinfo: %s\n", LogTime(), PROGRAM, gai_strerror(rc));
return (nhosts);
}
-int
-get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, int nh, char *domain)
+size_t
+get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, size_t nh, char *domain)
{
/*
* char name[sysconf(_SC_HOST_NAME_MAX)];
*/
char name[1024];
- char host[NS_MAXDNAME];
char *service = NULL;
struct hstruct *hp = NULL;
struct lsstruct *ls = NULL;
- int nhosts = 0;
+ size_t nhosts = 0;
int size;
- int type, rdlength;
- int priority, weight, port;
int len, olen;
- int i, j, k;
+ size_t i, j, k;
u_char *buffer = NULL;
u_char *p;
}
if (len > PACKETSZ_MULT * NS_PACKETSZ) {
olen = len;
- buffer = (u_char *) xrealloc(buffer, len);
+ buffer = (u_char *) xrealloc(buffer, (size_t)len);
if ((len = res_search(service, ns_c_in, ns_t_srv, (u_char *) buffer, len)) < 0) {
error((char *) "%s| %s: ERROR: Error while resolving service record %s with res_search\n", LogTime(), PROGRAM, service);
nsError(h_errno, service);
error((char *) "%s| %s: ERROR: Message to small: %d < header size\n", LogTime(), PROGRAM, len);
goto finalise;
}
- if ((size = dn_expand(buffer, buffer + len, p, name, sysconf(_SC_HOST_NAME_MAX))) < 0) {
+ if ((size = dn_expand(buffer, buffer + len, p, name, sizeof(name))) < 0) {
error((char *) "%s| %s: ERROR: Error while expanding query name with dn_expand: %s\n", LogTime(), PROGRAM, strerror(errno));
goto finalise;
}
goto finalise;
}
while (p < buffer + len) {
- if ((size = dn_expand(buffer, buffer + len, p, name, sysconf(_SC_HOST_NAME_MAX))) < 0) {
+ int type, rdlength;
+ if ((size = dn_expand(buffer, buffer + len, p, name, sizeof(name))) < 0) {
error((char *) "%s| %s: ERROR: Error while expanding answer name with dn_expand: %s\n", LogTime(), PROGRAM, strerror(errno));
goto finalise;
}
NS_GET16(rdlength, p); /* RR data length (16bit) */
if (type == ns_t_srv) { /* SRV record */
+ int priority, weight, port;
+ char host[NS_MAXDNAME];
if (p > buffer + len) {
error((char *) "%s| %s: ERROR: Message to small: %d < header + query name,type,class + answer name + RR type,class,ttl + RR data length\n", LogTime(), PROGRAM, len);
goto finalise;
}
finalise:
- nhosts = get_hostname_list(margs, &hp, nh, domain);
+ nhosts = get_hostname_list(&hp, nh, domain);
debug("%s| %s: DEBUG: Adding %s to list\n", LogTime(), PROGRAM, domain);
}
/* Sort by Priority / Weight */
- msort(hp, nhosts, compare_hosts);
+ msort(hp, (size_t)nhosts, compare_hosts);
if (debug_enabled) {
debug((char *) "%s| %s: DEBUG: Sorted ldap server names for domain %s:\n", LogTime(), PROGRAM, domain);
debug((char *) "%s| %s: DEBUG: Host: %s Port: %d Priority: %d Weight: %d\n", LogTime(), PROGRAM, hp[i].host, hp[i].port, hp[i].priority, hp[i].weight);
}
}
- if (buffer)
- xfree(buffer);
- if (service)
- xfree(service);
+ xfree(buffer);
+ xfree(service);
*hlist = hp;
return (nhosts);
}
{
lutilSASLdefaults *defs = (lutilSASLdefaults *) defaults;
- if (defs->mech)
- xfree(defs->mech);
- if (defs->realm)
- xfree(defs->realm);
- if (defs->authcid)
- xfree(defs->authcid);
- if (defs->passwd)
- xfree(defs->passwd);
- if (defs->authzid)
- xfree(defs->authzid);
- if (defs->resps)
- xfree(defs->resps);
+ xfree(defs->mech);
+ xfree(defs->realm);
+ xfree(defs->authcid);
+ xfree(defs->passwd);
+ xfree(defs->authzid);
+ xfree(defs->resps);
xfree(defs);
}
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 \
--- /dev/null
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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 <string.h>
+#endif
+#if HAVE_STDIO_H
+#include <stdio.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
+
+#include "util.h"
+#include "base64.h"
+
+#if HAVE_KRB5_H
+#if HAVE_BROKEN_SOLARIS_KRB5_H
+#warn "Warning! You have a broken Solaris <krb5.h> 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 <krb5.h>
+}
+#else
+#include <krb5.h>
+#endif
+#endif /* HAVE_KRB5_H */
+
+#if HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif HAVE_GSSAPI_H
+#include <gssapi.h>
+#endif
+
+#if !HAVE_HEIMDAL_KERBEROS
+#if HAVE_GSSAPI_GSSAPI_KRB5_H
+#include <gssapi/gssapi_krb5.h>
+#endif
+#if HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include <gssapi/gssapi_generic.h>
+#endif
+#if HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#endif
+#else
+#if HAVE_GSSAPI_GSSAPI_KRB5_H
+#include <gssapi/gssapi_krb5.h>
+#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
+
+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 sout);
+
+char *gethost_name(void);
+
+#if (defined(HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT) || defined(HAVE_GSS_MAP_NAME_TO_ANY)) && HAVE_KRB5_PAC
+#define HAVE_PAC_SUPPORT 1
+#define MAX_PAC_GROUP_SIZE 200*60
+typedef struct {
+ uint16_t length;
+ uint16_t maxlength;
+ uint32_t pointer;
+} RPC_UNICODE_STRING;
+
+int check_k5_err(krb5_context context, const char *msg, krb5_error_code code);
+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);
+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);
+#else
+#define HAVE_PAC_SUPPORT 0
+#endif
#if HAVE_GSSAPI
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_STDOI_H
-#include <stdio.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
-
-#include "util.h"
-#include "base64.h"
-
-#if HAVE_GSSAPI_GSSAPI_H
-#include <gssapi/gssapi.h>
-#elif HAVE_GSSAPI_H
-#include <gssapi.h>
-#endif
-
-#if !HAVE_HEIMDAL_KERBEROS
-#if HAVE_GSSAPI_GSSAPI_KRB5_H
-#include <gssapi/gssapi_krb5.h>
-#endif
-#if HAVE_GSSAPI_GSSAPI_GENERIC_H
-#include <gssapi/gssapi_generic.h>
-#endif
-#if HAVE_GSSAPI_GSSAPI_EXT_H
-#include <gssapi/gssapi_ext.h>
-#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)
int
check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
- const char *function, int log)
+ const char *function, int log, int sout)
{
if (GSS_ERROR(major_status)) {
OM_uint32 maj_stat, min_stat;
gss_release_buffer(&min_stat, &status_string);
} while (msg_ctx);
debug((char *) "%s| %s: ERROR: %s failed: %s\n", LogTime(), PROGRAM, function, buf);
- fprintf(stdout, "BH %s failed: %s\n", 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);
char buf[MAX_AUTHTOKEN_LEN];
char *c, *p;
char *user = NULL;
- int length = 0;
+ 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;
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) {
err = 0;
continue;
}
- debug((char *) "%s| %s: DEBUG: Got '%s' from squid (length: %d).\n", LogTime(), PROGRAM, buf, length);
+ debug((char *) "%s| %s: DEBUG: Got '%s' from squid (length: %ld).\n", LogTime(), PROGRAM, buf, length);
if (buf[0] == '\0') {
debug((char *) "%s| %s: ERROR: Invalid request\n", LogTime(), PROGRAM);
if (kerberosToken) {
/* Allocated by parseNegTokenInit, but no matching free function exists.. */
if (!spnego_flag)
- xfree((char *) kerberosToken);
- kerberosToken = NULL;
+ xfree(kerberosToken);
}
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;
+ xfree(spnegoToken);
}
+ xfree(token);
fprintf(stdout, "BH quit command\n");
exit(0);
}
fprintf(stdout, "BH Invalid negotiate request\n");
continue;
}
- input_token.length = base64_decode_len(buf+3);
+ 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 = base64_decode((char *) input_token.value, input_token.length, buf+3);
+ 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))) {
} 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 (check_gss_err(major_status, minor_status, "gss_import_name()", log))
+ 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))
+ if (check_gss_err(major_status, minor_status, "gss_acquire_cred()", log, 1))
goto cleanup;
major_status = gss_accept_sec_context(&minor_status,
if (output_token.length) {
spnegoToken = (const unsigned char *) output_token.value;
spnegoTokenLength = output_token.length;
- token = (char *) xmalloc(base64_encode_len(spnegoTokenLength));
+ 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(spnegoTokenLength),
- (const char *) spnegoToken, spnegoTokenLength);
+ 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))
+ 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);
gss_display_name(&minor_status, client_name, &output_token,
NULL);
- if (check_gss_err(major_status, minor_status, "gss_display_name()", log))
+ 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 (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
+ 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 (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);
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))
+ 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);
gss_display_name(&minor_status, client_name, &output_token,
NULL);
- if (check_gss_err(major_status, minor_status, "gss_display_name()", log))
+ 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
if (kerberosToken) {
/* Allocated by parseNegTokenInit, but no matching free function exists.. */
if (!spnego_flag)
- xfree((char *) kerberosToken);
- kerberosToken = NULL;
+ safe_free(kerberosToken);
}
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;
+ safe_free(spnegoToken);
}
+ safe_free(token);
+ safe_free(user);
continue;
}
}
goto cleanup;
if (output_token.length) {
- token = (char *) xmalloc(base64_encode_len(output_token.length));
- base64_encode_str(token, base64_encode_len(output_token.length),
- (const char *) output_token.value, output_token.length);
+ token = (char *) xmalloc((size_t)base64_encode_len((int)output_token.length));
+ base64_encode_str(token, base64_encode_len((int)output_token.length),
+ (const char *) output_token.value, (int)output_token.length);
}
cleanup:
gss_delete_sec_context(&minor_status, &gss_context, NULL);
--- /dev/null
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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"
+
+#include "negotiate_kerberos.h"
+
+#if HAVE_PAC_SUPPORT
+
+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 = (uint16_t)((p[bpos]<<0) | (p[bpos+1]<<8));
+ string->maxlength = (uint16_t)((p[bpos+2]<<0) | (p[bpos+2+1]<<8));
+ string->pointer = (uint32_t)((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 = ((uint64_t)p[bpos+5]<<0) | ((uint64_t)p[bpos+4]<<8) | ((uint64_t)p[bpos+3]<<16) | ((uint64_t)p[bpos+2]<<24) | ((uint64_t)p[bpos+1]<<32) | ((uint64_t)p[bpos]<<40);
+ bpos = bpos+6;
+
+ return var;
+}
+
+uint32_t
+get4byt(void)
+{
+ uint32_t var;
+
+ var=(uint32_t)((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=(uint16_t)((p[bpos]<<0) | (p[bpos+1]<<8));
+ bpos = bpos+2;
+
+ return var;
+}
+
+uint8_t
+get1byt(void)
+{
+ uint8_t var;
+
+ var=(uint8_t)((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 = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
+ bpos = bpos+4;
+ off = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
+ bpos = bpos+4;
+ len = (uint32_t)((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;
+ size_t 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, (int)(length+4)))) {
+ debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n",
+ LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);
+ }
+ xfree(ag);
+ }
+
+ /* 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)
+{
+ if (ExtraSids!= 0) {
+ uint32_t ngroup;
+ uint32_t *pa;
+ char *ag;
+ size_t 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, (int)length))) {
+ 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))==NULL)
+ goto k5clean;
+
+ debug((char *) "%s| %s: INFO: Read %d of %d bytes \n", LogTime(), PROGRAM, bpos, (int)ad_data->length);
+ if (Rids) {
+ for ( l=0; l<(int)GroupCount; l++) {
+ xfree(Rids[l]);
+ }
+ xfree(Rids);
+ }
+ krb5_free_data(context, ad_data);
+ return ad_groups;
+k5clean:
+ if (Rids) {
+ for ( l=0; l<(int)GroupCount; l++) {
+ xfree(Rids[l]);
+ }
+ xfree(Rids);
+ }
+ krb5_free_data(context, ad_data);
+ return NULL;
+}
+#endif
--- /dev/null
+#!/bin/bash
+if [[ -z "$1" ]]; then
+ echo "Need squid hostname"
+ exit 0
+fi
+dir=`dirname $0`
+$dir/negotiate_kerberos_auth_test $1 | awk '{sub(/Token:/,"YR"); print $0}END{print "QQ"}' | $dir/negotiate_kerberos_auth -d
static krb5_keytab_entry entry;
static krb5_kt_cursor cursor;
static krb5_creds *creds = NULL;
-#if HAVE_HEIMDAL_KERBEROS
+#if HAVE_HEIMDAL_KERBEROS && !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 HAVE_HEIMDAL_KERBEROS && !HAVE_KRB5_GET_RENEWED_CREDS
krb5_kdc_flags flags;
- krb5_realm *client_realm;
+#if HAVE_KRB5_PRINCIPAL_GET_REALM
+ const char *client_realm;
+#else
+ krb5_realm client_realm;
+#endif
#endif
char *mem_cache;
(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,
<< 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);
+ (krb5_const_realm)&client_realm, KRB5_TGS_NAME,
+ (krb5_const_realm)&client_realm, NULL);
if (code) {
debugs(11, 5,
HERE << "Error while getting krbtgt principal : " <<
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,
" : " << 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);
+#if HAVE_KRB5_GET_INIT_CREDS_FREE_CONTEXT
+ krb5_get_init_creds_opt_free(kparam.context, options);
+#else
+ krb5_get_init_creds_opt_free(options);
+#endif
+#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);
+#endif
if (code) {
debugs(11, 5,
HERE <<