diff --git a/src/auth/negotiate/kerberos/negotiate_kerberos_auth.cc b/src/auth/negotiate/kerberos/negotiate_kerberos_auth.cc index 55db7681e8f..1f5d288a8ea 100644 --- a/src/auth/negotiate/kerberos/negotiate_kerberos_auth.cc +++ b/src/auth/negotiate/kerberos/negotiate_kerberos_auth.cc @@ -333,6 +333,7 @@ main(int argc, char *const argv[]) #else gss_buffer_desc type_id = GSS_C_EMPTY_BUFFER; #endif + const char* group_attribute_name = "group"; #endif /* HAVE_KRB5_PAC_SUPPORT */ krb5_context context = nullptr; krb5_error_code ret; @@ -366,7 +367,7 @@ main(int argc, char *const argv[]) setbuf(stdout, nullptr); setbuf(stdin, nullptr); - while (-1 != (opt = getopt(argc, argv, "dirs:k:c:t:"))) { + while (-1 != (opt = getopt(argc, argv, "dirs:k:c:t:a:"))) { switch (opt) { case 'd': debug_enabled = 1; @@ -462,9 +463,23 @@ main(int argc, char *const argv[]) exit(EXIT_FAILURE); } break; +#if HAVE_KRB5_PAC_SUPPORT + case 'a': + if (optarg) + group_attribute_name = optarg; + else { + fprintf(stderr, "ERROR: '-a' value not given\n"); + exit(EXIT_FAILURE); + } + break; +#endif default: fprintf(stderr, "Usage: \n"); - fprintf(stderr, "squid_kerb_auth [-d] [-i] [-s SPN] [-k keytab] [-c rcdir] [-t rctype]\n"); + fprintf(stderr, "squid_kerb_auth [-d] [-i] [-s SPN] [-k keytab] [-c rcdir] [-t rctype]"); +#if HAVE_KRB5_PAC_SUPPORT + fprintf(stderr, " [-a name]"); +#endif + fprintf(stderr, "\n"); fprintf(stderr, "-d full debug\n"); fprintf(stderr, "-i informational messages\n"); fprintf(stderr, "-r remove realm from username\n"); @@ -472,9 +487,13 @@ main(int argc, char *const argv[]) fprintf(stderr, "-k keytab name\n"); fprintf(stderr, "-c replay cache directory\n"); fprintf(stderr, "-t replay cache type\n"); +#if HAVE_KRB5_PAC_SUPPORT + fprintf(stderr, "-a annotation name for reporting user groups (e.g., 'clt_conn_tag'); defaults to '%s'\n", + group_attribute_name); +#endif fprintf(stderr, - "The SPN can be set to GSS_C_NO_NAME to allow any entry from keytab\n"); - fprintf(stderr, "default SPN is HTTP/fqdn@DEFAULT_REALM\n"); + "\nThe SPN can be set to GSS_C_NO_NAME to allow any entry from keytab\n"); + fprintf(stderr, "default SPN is HTTP/fqdn@DEFAULT_REALM\n\n"); exit(EXIT_SUCCESS); } } @@ -786,7 +805,7 @@ main(int argc, char *const argv[]) rfc_user = rfc1738_escape(user); #if HAVE_KRB5_PAC_SUPPORT - fprintf(stdout, "OK token=%s user=%s %s\n", token, rfc_user, ag?ag:"group="); + fprintf(stdout, "OK token=%s user=%s %s=%s\n", token, rfc_user, group_attribute_name, ag?ag:""); #else fprintf(stdout, "OK token=%s user=%s\n", token, rfc_user); #endif /* HAVE_KRB5_PAC_SUPPORT */ @@ -828,7 +847,7 @@ main(int argc, char *const argv[]) } rfc_user = rfc1738_escape(user); #if HAVE_KRB5_PAC_SUPPORT - fprintf(stdout, "OK token=%s user=%s %s\n", "AA==", rfc_user, ag?ag:"group="); + fprintf(stdout, "OK token=%s user=%s %s=%s\n", "AA==", rfc_user, group_attribute_name, ag?ag:""); #else fprintf(stdout, "OK token=%s user=%s\n", "AA==", rfc_user); #endif /* HAVE_KRB5_PAC_SUPPORT */ diff --git a/src/auth/negotiate/kerberos/negotiate_kerberos_pac.cc b/src/auth/negotiate/kerberos/negotiate_kerberos_pac.cc index 37c8577bd68..f82560feefd 100644 --- a/src/auth/negotiate/kerberos/negotiate_kerberos_pac.cc +++ b/src/auth/negotiate/kerberos/negotiate_kerberos_pac.cc @@ -114,28 +114,23 @@ get1byt(void) return var; } + static char * -pstrcpy( char *src, const char *dst) +pstrcat( char *dst, const char *src) { - if (dst) { - if (strlen(dst)>MAX_PAC_GROUP_SIZE) + if (src) { + if ( strlen(dst) + strlen(src) + 1 >= MAX_PAC_GROUP_SIZE ) return nullptr; else - return strcpy(src,dst); + return strcat(dst, src); } else - return src; + return dst; } static char * -pstrcat( char *src, const char *dst) -{ - if (dst) { - if (strlen(src)+strlen(dst)+1>MAX_PAC_GROUP_SIZE) - return nullptr; - else - return strcat(src,dst); - } else - return src; +append_comma(char *buffer){ + if ( buffer && buffer[0] ) return pstrcat(buffer, ","); + return buffer; } int @@ -236,17 +231,8 @@ getdomaingids(char *ad_groups, uint32_t DomainLogonId, char **Rids, uint32_t Gro 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 (!pstrcpy(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 (!pstrcat(ad_groups," group=")) { - debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", - LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups); - } - } + + append_comma(ad_groups); struct base64_encode_ctx ctx; base64_encode_init(&ctx); const uint32_t expectedSz = base64_encode_len(length+4) +1 /* terminator */; @@ -281,6 +267,12 @@ getdomaingids(char *ad_groups, uint32_t DomainLogonId, char **Rids, uint32_t Gro char * getextrasids(char *ad_groups, uint32_t ExtraSids, uint32_t SidCount) { + if (!ad_groups) { + debug((char *) "%s| %s: ERR: No space to store groups\n", + LogTime(), PROGRAM); + return nullptr; + } + if (ExtraSids!= 0) { uint32_t ngroup; uint32_t *pa; @@ -323,19 +315,8 @@ getextrasids(char *ad_groups, uint32_t ExtraSids, uint32_t SidCount) size_t length = 1+1+6+nauth*4; ag = (char *)xcalloc((length)*sizeof(char),1); memcpy((void *)ag,(const void*)&p[bpos],length); - if (!ad_groups) { - debug((char *) "%s| %s: ERR: No space to store groups\n", - LogTime(), PROGRAM); - xfree(pa); - xfree(ag); - return nullptr; - } else { - if (!pstrcat(ad_groups," group=")) { - debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", - LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups); - } - } + append_comma(ad_groups); struct base64_encode_ctx ctx; base64_encode_init(&ctx); const uint32_t expectedSz = base64_encode_len(length) +1 /* terminator */; @@ -465,11 +446,7 @@ get_resource_groups(char *ad_groups, uint32_t ResourceGroupDomainSid, uint32_t uint32_t sauth; memcpy((void *)&st[group_domain_sid_len], (const void*)&p[bpos], 4); // rid concatenation - if (!pstrcat(ad_groups, " group=")) { - debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", - LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups); - } - + append_comma(ad_groups); struct base64_encode_ctx ctx; base64_encode_init(&ctx); const uint32_t expectedSz = base64_encode_len(length) + 1 /* terminator */; @@ -526,6 +503,8 @@ get_ad_groups(char *ad_groups, krb5_context context, krb5_pac pac) return nullptr; } + ad_groups[0] = '\0'; + ad_data = (krb5_data *)xcalloc(1,sizeof(krb5_data)); #define KERB_LOGON_INFO 1 @@ -612,6 +591,8 @@ get_ad_groups(char *ad_groups, krb5_context context, krb5_pac pac) if (checkustr(&LogonDomainName)<0) goto k5clean; ad_groups = getdomaingids(ad_groups,LogonDomainId,Rids,GroupCount); + if (!ad_groups) + goto k5clean; // https://learn.microsoft.com/en-us/previous-versions/aa302203(v=msdn.10)?redirectedfrom=MSDN#top-level-pac-structure if ((UserFlags&LOGON_EXTRA_SIDS) != 0) {