From: huaraz Date: Sun, 6 May 2018 16:06:42 +0000 (+0000) Subject: Bug 4042: ext_kerberos_ldap_group: add -P principal option (#195) X-Git-Tag: M-staged-PR195 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=40f1fd09cbaddf589e4e98e3ab28ea4e45b8e84b;p=thirdparty%2Fsquid.git Bug 4042: ext_kerberos_ldap_group: add -P principal option (#195) Added a -P principal option to ext_kerberos_ldap_group to select a principal from the keytab overwriting the automated method which may make it more responsive. --- diff --git a/src/acl/external/kerberos_ldap_group/ext_kerberos_ldap_group_acl.8 b/src/acl/external/kerberos_ldap_group/ext_kerberos_ldap_group_acl.8 index 4c74092f6c..4ee82d893e 100644 --- a/src/acl/external/kerberos_ldap_group/ext_kerberos_ldap_group_acl.8 +++ b/src/acl/external/kerberos_ldap_group/ext_kerberos_ldap_group_acl.8 @@ -7,7 +7,7 @@ Version 1.3.0sq . .SH SYNOPSIS .if !'po4a'hide' .B ext_kerberos_ldap_group_acl -.if !'po4a'hide' .B [\-h] [\-d] [\-i] [\-s] [\-a] [\-D Realm ] [\-N Netbios\-Realm\-List] [\-m Max\-Depth] [\-u Ldap\-User] [\-p Ldap\-Password] [\-b Ldap\-Bind\-Path] [\-l Ldap\-URL] [\-S ldap server list] \-g Group\-Realm\-List \-t Hex\-Group\-Realm\-List \-T Hex\-Group\-Hex\-Realm\-List +.if !'po4a'hide' .B [\-h] [\-d] [\-i] [\-s] [\-a] [\-D Realm ] [\-N Netbios\-Realm\-List] [\-P service principal name] [\-m Max\-Depth] [\-u Ldap\-User] [\-p Ldap\-Password] [\-b Ldap\-Bind\-Path] [\-l Ldap\-URL] [\-S ldap server list] \-g Group\-Realm\-List \-t Hex\-Group\-Realm\-List \-T Hex\-Group\-Hex\-Realm\-List . .SH DESCRIPTION .B ext_kerberos_ldap_group_acl @@ -89,6 +89,8 @@ information (e.g. for users using basic authentication). A list of Netbios name mappings to Kerberos domain names of the form Netbios\-Name@Kerberos\-Realm[:Netbios\-Name@Kerberos\-Realm] (e.g. for users using NTLM authentication). +.if !'po4a'hide' .B \-P service principal name +The principal name in the keytab to use. Avoids automated selection of name. .if !'po4a'hide' .TP 12 .if !'po4a'hide' .B \-m Max\-Depth Maximal depth of recursive group search. @@ -100,7 +102,8 @@ Username for LDAP server. Password for LDAP server. .IP As the password needs to be printed in plain text in your Squid configuration -it is strongly recommended to use an account with minimal associated privileges. +it is strongly recommended to use an account with minimal associated privileges. + This to limit the damage in case someone could get hold of a copy of your Squid configuration file or extracts the password used from a process listing. . @@ -119,7 +122,7 @@ lserver|lserver@|lserver@Realm[:lserver@|lserver@Realm] A list of group name per Kerberos domain of the form Group|Group@|Group@Realm[:Group@|Group@Realm] .if !'po4a'hide' .TP 12 -.if !'po4a'hide' .B \-t Hex\-Group\-Realm\-List +.if !'po4a'hide' .B \-t Hex\-Group\-Realm\-List A list of group name per Kerberos domain of the form Group|Group@|Group@Realm[:Group@|Group@Realm] where group is in UTF\-8 hex format @@ -138,9 +141,9 @@ helper in .if !'po4a'hide' .P .if !'po4a'hide' .ft CR .if !'po4a'hide' .nf -.if !'po4a'hide' external_acl_type kerberos_ldap_group1 ttl=3600 negative_ttl=3600 %LOGIN /path/to/ext_kerberos_ldap_group_acl \-g GROUP1 +.if !'po4a'hide' external_acl_type kerberos_ldap_group1 ttl=3600 negative_ttl=3600 %LOGIN /path/to/ext_kerberos_ldap_group_acl \-g GROUP1 .if !'po4a'hide' .br -.if !'po4a'hide' external_acl_type kerberos_ldap_group2 ttl=3600 negative_ttl=3600 %LOGIN /path/to/ext_kerberos_ldap_group_acl \-g GROUP2 +.if !'po4a'hide' external_acl_type kerberos_ldap_group2 ttl=3600 negative_ttl=3600 %LOGIN /path/to/ext_kerberos_ldap_group_acl \-g GROUP2 .if !'po4a'hide' .br .if !'po4a'hide' acl group1 external kerberos_ldap_group1 .if !'po4a'hide' .br @@ -198,7 +201,7 @@ The Groups to check against are determined as follows: 3) For NDOMAIN\\user a) Use realm given by \-N NDOMAIN@REALM and then use values given by \-g option which contain a @REALM e.g. \-g GROUP1@REALM:GROUP2@REALM -To support Non\-ASCII character use \-t GROUP or \-t GROUP@REALM instead of \-g where GROUP is the hex UTF\-8 representation e.g. +To support Non\-ASCII character use \-t GROUP or \-t GROUP@REALM instead of \-g where GROUP is the hex UTF\-8 representation e.g. \-t 6d61726b7573 instead of \-g markus @@ -210,8 +213,8 @@ For a translation of hex UTF\-8 see for example http://www.utf8\-chartable.de/un The ldap server list can be: server \- In this case server can be used for all Kerberos domains -server@ \- In this case server can be used for all Kerberos domains -server@domain \- In this case server can be used for Kerberos domain domain +server@ \- In this case server can be used for all Kerberos domains +server@domain \- In this case server can be used for Kerberos domain domain server1a@domain1:server1b@domain1:server2@domain2:server3@:server4 \- A list is build with a colon as separator . diff --git a/src/acl/external/kerberos_ldap_group/kerberos_ldap_group.cc b/src/acl/external/kerberos_ldap_group/kerberos_ldap_group.cc index fc548da35d..a12d7c0250 100644 --- a/src/acl/external/kerberos_ldap_group/kerberos_ldap_group.cc +++ b/src/acl/external/kerberos_ldap_group/kerberos_ldap_group.cc @@ -83,6 +83,7 @@ init_args(struct main_args *margs) margs->groups = NULL; margs->ndoms = NULL; margs->lservs = NULL; + margs->principal = NULL; } void clean_gd(struct gdstruct *gdsp); @@ -178,6 +179,7 @@ clean_args(struct main_args *margs) clean_ls(margs->lservs); margs->lservs = NULL; } + safe_free(margs->principal); } void strup(char *s); @@ -202,7 +204,7 @@ main(int argc, char *const argv[]) init_args(&margs); - while (-1 != (opt = getopt(argc, argv, "diasng:D:N:S:u:U:t:T:p:l:b:m:h"))) { + while (-1 != (opt = getopt(argc, argv, "diasng:D:N:P:S:u:U:t:T:p:l:b:m:h"))) { switch (opt) { case 'd': debug_enabled = 1; @@ -228,6 +230,9 @@ main(int argc, char *const argv[]) case 'N': margs.nlist = xstrdup(optarg); break; + case 'P': + margs.principal = xstrdup(optarg); + break; case 'u': margs.luser = xstrdup(optarg); break; @@ -259,7 +264,7 @@ main(int argc, char *const argv[]) break; case 'h': fprintf(stderr, "Usage: \n"); - fprintf(stderr, "squid_kerb_ldap [-d] [-i] -g group list [-D domain] [-N netbios domain map] [-s] [-u ldap user] [-p ldap user password] [-l ldap url] [-b ldap bind path] [-a] [-m max depth] [-h]\n"); + fprintf(stderr, "squid_kerb_ldap [-d] [-i] -g group list [-D domain] [-N netbios domain map] [-P service principal name] [-s] [-u ldap user] [-p ldap user password] [-l ldap url] [-b ldap bind path] [-a] [-m max depth] [-h]\n"); fprintf(stderr, "-d full debug\n"); fprintf(stderr, "-i informational messages\n"); fprintf(stderr, "-n do not use Kerberos to authenticate to AD. Requires -u , -p and -l option\n"); @@ -268,6 +273,7 @@ main(int argc, char *const argv[]) fprintf(stderr, "-T group list (all in hex UTF-8 format - except separator @)\n"); fprintf(stderr, "-D default domain\n"); fprintf(stderr, "-N netbios to dns domain map\n"); + fprintf(stderr, "-P service principal name to be used from keytab\n"); fprintf(stderr, "-S ldap server to dns domain map\n"); fprintf(stderr, "-u ldap user\n"); fprintf(stderr, "-p ldap user password\n"); diff --git a/src/acl/external/kerberos_ldap_group/support.h b/src/acl/external/kerberos_ldap_group/support.h index 14e9decacb..c279e7d9dc 100644 --- a/src/acl/external/kerberos_ldap_group/support.h +++ b/src/acl/external/kerberos_ldap_group/support.h @@ -110,6 +110,7 @@ struct main_args { struct gdstruct *groups; struct ndstruct *ndoms; struct lsstruct *lservs; + char *principal; }; SQUIDCEXTERN int log_enabled; @@ -181,7 +182,7 @@ struct kstruct { char* mem_ccache[MAX_DOMAINS]; int ncache; }; -int krb5_create_cache(char *domain); +int krb5_create_cache(char *domain, char* princ); void krb5_cleanup(void); #endif diff --git a/src/acl/external/kerberos_ldap_group/support_krb5.cc b/src/acl/external/kerberos_ldap_group/support_krb5.cc index e87bab8a1f..77df81b09f 100644 --- a/src/acl/external/kerberos_ldap_group/support_krb5.cc +++ b/src/acl/external/kerberos_ldap_group/support_krb5.cc @@ -70,6 +70,21 @@ k5_error2(const char* msg, char* msg2, krb5_error_code code) #endif } +static void +k5_debug(const char* msg, krb5_error_code code) +{ + const char *errmsg; + errmsg = krb5_get_error_message(kparam.context, code); + debug((char *) "%s| %s: DEBUG: %s : %s\n", LogTime(), PROGRAM, msg, errmsg); +#if HAVE_KRB5_FREE_ERROR_MESSAGE + krb5_free_error_message(kparam.context, errmsg); +#elif HAVE_KRB5_FREE_ERROR_STRING + krb5_free_error_string(kparam.context, (char *)errmsg); +#else + xfree(errmsg); +#endif +} + static void k5_error(const char* msg, krb5_error_code code) { @@ -80,7 +95,7 @@ k5_error(const char* msg, krb5_error_code code) * create Kerberos memory cache */ int -krb5_create_cache(char *domain) +krb5_create_cache(char *domain, char *service_principal_name) { krb5_keytab keytab = NULL; @@ -131,7 +146,7 @@ krb5_create_cache(char *domain) } code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc[ccindex]); if (code) { - k5_error("Error while resolving memory ccache",code); + k5_error("Error while resolving memory ccache", code); retval = 1; goto cleanup; } @@ -145,22 +160,22 @@ krb5_create_cache(char *domain) if (principal) krb5_free_principal(kparam.context, principal); principal = NULL; - k5_error("No default principal found in ccache",code); + k5_debug("No default principal found in ccache", code); } else { /* * Look for krbtgt and check if it is expired (or soon to be expired) */ code = krb5_cc_start_seq_get(kparam.context, kparam.cc[ccindex], &ccursor); if (code) { - k5_error("Error while starting ccache scan",code); + k5_error("Error while starting ccache scan", code); code = krb5_cc_close (kparam.context, kparam.cc[ccindex]); if (code) { - k5_error("Error while closing ccache",code); + k5_error("Error while closing ccache", code); } if (kparam.cc[ccindex]) { code = krb5_cc_destroy(kparam.context, kparam.cc[ccindex]); if (code) { - k5_error("Error while destroying ccache",code); + k5_error("Error while destroying ccache", code); } } } else { @@ -169,10 +184,10 @@ krb5_create_cache(char *domain) while ((krb5_cc_next_cred(kparam.context, kparam.cc[ccindex], &ccursor, creds)) == 0) { code2 = krb5_unparse_name(kparam.context, creds->server, &principal_name); if (code2) { - k5_error("Error while unparsing principal",code2); + k5_error("Error while unparsing principal", code2); code = krb5_cc_destroy(kparam.context, kparam.cc[ccindex]); if (code) { - k5_error("Error while destroying ccache",code); + k5_error("Error while destroying ccache", code); } assert(creds != NULL); krb5_free_creds(kparam.context, creds); @@ -181,7 +196,7 @@ krb5_create_cache(char *domain) debug((char *) "%s| %s: DEBUG: Reset credential cache to %s\n", LogTime(), PROGRAM, mem_cache); code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc[ccindex]); if (code) { - k5_error("Error while resolving memory ccache",code); + k5_error("Error while resolving memory ccache", code); retval = 1; goto cleanup; } @@ -205,7 +220,7 @@ krb5_create_cache(char *domain) principal = NULL; code = krb5_cc_destroy(kparam.context, kparam.cc[ccindex]); if (code) { - k5_error("Error while destroying ccache",code); + k5_error("Error while destroying ccache", code); } assert(creds != NULL); krb5_free_creds(kparam.context, creds); @@ -214,7 +229,7 @@ krb5_create_cache(char *domain) debug((char *) "%s| %s: DEBUG: Reset credential cache to %s\n", LogTime(), PROGRAM, mem_cache); code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc[ccindex]); if (code) { - k5_error("Error while resolving ccache",code); + k5_error("Error while resolving ccache", code); retval = 1; goto cleanup; } @@ -234,7 +249,7 @@ krb5_create_cache(char *domain) creds = NULL; code2 = krb5_cc_end_seq_get(kparam.context, kparam.cc[ccindex], &ccursor); if (code2) { - k5_error("Error while ending ccache scan",code2); + k5_error("Error while ending ccache scan", code2); retval = 1; goto cleanup; } @@ -255,13 +270,13 @@ krb5_create_cache(char *domain) code = krb5_kt_resolve(kparam.context, keytab_name, &keytab); if (code) { - k5_error2("Error while resolving keytab ",keytab_name,code); + k5_error2("Error while resolving keytab ", keytab_name,code); retval = 1; goto cleanup; } code = krb5_kt_start_seq_get(kparam.context, keytab, &cursor); if (code) { - k5_error("Error while starting keytab scan",code); + k5_error("Error while starting keytab scan", code); retval = 1; goto cleanup; } @@ -286,10 +301,15 @@ krb5_create_cache(char *domain) { code = krb5_unparse_name(kparam.context, entry.principal, &principal_name); if (code) { - k5_error("Error while unparsing principal name",code); + k5_error("Error while unparsing principal name", code); } else { debug((char *) "%s| %s: DEBUG: Found principal name: %s\n", LogTime(), PROGRAM, principal_name); found = 1; + if (service_principal_name && strcasecmp(principal_name,service_principal_name) != 0 ) { + debug((char *) "%s| %s: DEBUG: principal name does not match parameter: %s\n", LogTime(), PROGRAM, service_principal_name); + safe_free(principal_name); + found = 0; + } } } #if USE_HEIMDAL_KRB5 || ( HAVE_KRB5_KT_FREE_ENTRY && HAVE_DECL_KRB5_KT_FREE_ENTRY ) @@ -298,7 +318,7 @@ krb5_create_cache(char *domain) code = krb5_free_keytab_entry_contents(kparam.context, &entry); #endif if (code) { - k5_error("Error while freeing keytab entry",code); + k5_error("Error while freeing keytab entry", code); retval = 1; break; } @@ -333,7 +353,7 @@ krb5_create_cache(char *domain) #endif if (code) { - k5_error("Error while initialising credentials from keytab",code); + k5_error("Error while initialising credentials from keytab", code); safe_free(principal_name); if (principal) krb5_free_principal(kparam.context, principal); @@ -345,7 +365,7 @@ krb5_create_cache(char *domain) } code = krb5_cc_initialize(kparam.context, kparam.cc[ccindex], principal); if (code) { - k5_error("Error while initialising memory caches",code); + k5_error("Error while initialising cache", code); safe_free(principal_name); if (principal) krb5_free_principal(kparam.context, principal); @@ -357,7 +377,7 @@ krb5_create_cache(char *domain) } code = krb5_cc_store_cred(kparam.context, kparam.cc[ccindex], creds); if (code) { - k5_error("Error while storing credentials",code); + k5_error("Error while storing credentials", code); if (principal) krb5_free_principal(kparam.context, principal); safe_free(principal_name); @@ -373,13 +393,13 @@ krb5_create_cache(char *domain) } if (code && code != KRB5_KT_END) { - k5_error("Error while scanning keytab",code); + k5_error("Error while scanning keytab", code); retval = 1; goto cleanup; } code = krb5_kt_end_seq_get(kparam.context, keytab, &cursor); if (code) { - k5_error("Error while ending keytab scan",code); + k5_error("Error while ending keytab scan", code); retval = 1; goto cleanup; } @@ -387,7 +407,7 @@ krb5_create_cache(char *domain) /* * if no principal name found in keytab for domain use the prinipal name which can get a TGT */ - if (!principal_name) { + if (!principal_name && !service_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); @@ -401,7 +421,7 @@ krb5_create_cache(char *domain) */ code = krb5_unparse_name(kparam.context, principal_list[i], &principal_name); if (code) { - k5_error("Error while unparsing principal name",code); + k5_error("Error while unparsing principal name", code); goto loop_end; } debug((char *) "%s| %s: DEBUG: Keytab entry has principal: %s\n", LogTime(), PROGRAM, principal_name); @@ -417,17 +437,17 @@ krb5_create_cache(char *domain) code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0); #endif if (code) { - k5_error("Error while initialising credentials from keytab",code); + k5_error("Error while initialising credentials from keytab", code); goto loop_end; } code = krb5_cc_initialize(kparam.context, kparam.cc[ccindex], principal_list[i]); if (code) { - k5_error("Error while initialising memory caches",code); + k5_error("Error while initialising memory caches", code); goto loop_end; } code = krb5_cc_store_cred(kparam.context, kparam.cc[ccindex], creds); if (code) { - k5_error("Error while storing credentials",code); + k5_error("Error while storing credentials", code); goto loop_end; } if (creds->server) @@ -442,12 +462,12 @@ krb5_create_cache(char *domain) code = krb5_parse_name(kparam.context, service, &creds->server); xfree(service); if (code) { - k5_error("Error while initialising TGT credentials",code); + k5_error("Error while initialising TGT credentials", code); goto loop_end; } code = krb5_get_credentials(kparam.context, 0, kparam.cc[ccindex], creds, &tgt_creds); if (code) { - k5_error("Error while getting tgt",code); + k5_error("Error while getting tgt", code); goto loop_end; } else { debug((char *) "%s| %s: DEBUG: Found trusted principal name: %s\n", LogTime(), PROGRAM, principal_name); @@ -479,7 +499,7 @@ loop_end: */ code = krb5_unparse_name(kparam.context, principal, &principal_name); if (code) { - k5_error("Error while unparsing principal name",code); + k5_error("Error while unparsing principal name", code); retval = 1; goto cleanup; } diff --git a/src/acl/external/kerberos_ldap_group/support_ldap.cc b/src/acl/external/kerberos_ldap_group/support_ldap.cc index 057b19d788..5a74399599 100644 --- a/src/acl/external/kerberos_ldap_group/support_ldap.cc +++ b/src/acl/external/kerberos_ldap_group/support_ldap.cc @@ -1013,7 +1013,7 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group) "%s| %s: DEBUG: Kerberos is disabled. Use username/password with ldap url instead\n", LogTime(), PROGRAM); } else { - kc = krb5_create_cache(domain); + kc = krb5_create_cache(domain, margs->principal); if (kc) { error((char *) "%s| %s: ERROR: Error during setup of Kerberos credential cache\n",