[squid-users] Kerberos pac ResourceGroups parsing
Andrey K
ankor2023 at gmail.com
Thu Nov 16 12:48:48 UTC 2023
Hello,
I found that negotiate_kerberos_auth helper does not see domain local AD
groups.
As it turned out, helper parses only GroupIds and ExtraSids pac-blocks,
while the information about domain local groups is placed in the
ResourceGropIds pac-block.
I have slightly patched the negotiate_kerberos_pac.cc to
implement ResourceGropIds-block parsing.
Maybe it will be useful for the community.
This patch can be included in future Squid-releases.
Kind regards,
Ankor.
The patch for the
file src/auth/negotiate/kerberos/negotiate_kerberos_pac.cc below:
@@ -362,6 +362,123 @@
return ad_groups;
}
+
+char *
+get_resource_group_domain_sid(uint32_t ResourceGroupDomainSid){
+
+ if (ResourceGroupDomainSid!= 0) {
+ uint8_t rev;
+ uint64_t idauth;
+ char dli[256];
+ char *ag;
+ int l;
+
+ align(4);
+
+ uint32_t nauth = get4byt();
+
+ size_t length = 1+1+6+nauth*4;
+
+ ag=(char *)xcalloc((length+1)*sizeof(char),1);
+ // the first byte is a length of the SID
+ ag[0] = (char) length;
+ memcpy((void *)&ag[1],(const void*)&p[bpos],1);
+ memcpy((void *)&ag[2],(const void*)&p[bpos+1],1);
+ ag[2] = ag[2]+1;
+ memcpy((void *)&ag[3],(const void*)&p[bpos+2],6+nauth*4);
+
+
+
+ /* 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++ ) {
+ uint32_t sauth;
+ sauth = get4byt();
+ snprintf((char
*)&dli[strlen(dli)],sizeof(dli)-strlen(dli),"-%u",sauth);
+ }
+ debug((char *) "%s| %s: INFO: Got ResourceGroupDomainSid %s\n",
LogTime(), PROGRAM, dli);
+ return ag;
+ }
+
+ return NULL;
+}
+
+char *
+get_resource_groups(char *ad_groups, char *resource_group_domain_sid,
uint32_t ResourceGroupIds, uint32_t ResourceGroupCount){
+ size_t group_domain_sid_len = resource_group_domain_sid[0];
+ char *ag;
+ size_t length;
+
+ resource_group_domain_sid++; //now it points to the actual data
+
+
+ if (ResourceGroupIds!= 0) {
+ uint32_t ngroup;
+ int l;
+
+ align(4);
+ ngroup = get4byt();
+ if ( ngroup != ResourceGroupCount) {
+ debug((char *) "%s| %s: ERROR: Group encoding error =>
ResourceGroupCount: %d Array size: %d\n",
+ LogTime(), PROGRAM, ResourceGroupCount, ngroup);
+ return NULL;
+ }
+ debug((char *) "%s| %s: INFO: Found %d Resource Group rids\n",
LogTime(), PROGRAM, ResourceGroupCount);
+
+ //make a group template which begins with the ResourceGroupDomainID
+ length = group_domain_sid_len+4; //+4 for a rid
+ ag=(char *)xcalloc(length*sizeof(char),1);
+ memcpy((void *)ag,(const void*)resource_group_domain_sid,
group_domain_sid_len);
+
+
+ for ( l=0; l<(int)ResourceGroupCount; l++) {
+ uint32_t sauth;
+ memcpy((void *)&ag[group_domain_sid_len],(const
void*)&p[bpos],4);
+
+ 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);
+ xfree(ag);
+ return NULL;
+ }
+
+
+ struct base64_encode_ctx ctx;
+ base64_encode_init(&ctx);
+ const uint32_t expectedSz = base64_encode_len(length) +1 /*
terminator */;
+ char *b64buf = static_cast<char *>(xcalloc(expectedSz, 1));
+ size_t blen = base64_encode_update(&ctx, b64buf, length,
reinterpret_cast<uint8_t*>(ag));
+ blen += base64_encode_final(&ctx, b64buf+blen);
+ b64buf[expectedSz-1] = '\0';
+ if (!pstrcat(ad_groups, reinterpret_cast<char*>(b64buf))) {
+ debug((char *) "%s| %s: WARN: Too many groups ! size > %d
: %s\n",
+ LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);
+ xfree(ag);
+ xfree(b64buf);
+ return NULL;
+ }
+ xfree(b64buf);
+
+
+
+ sauth = get4byt();
+ debug((char *) "%s| %s: Info: Got rid: %u\n", LogTime(),
PROGRAM, sauth);
+ /* attribute */
+ bpos = bpos+4;
+ }
+
+ xfree(ag);
+ return ad_groups;
+ }
+
+ return NULL;
+}
+
+
char *
get_ad_groups(char *ad_groups, krb5_context context, krb5_pac pac)
{
@@ -379,14 +496,14 @@
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;
+ char * resource_group_domain_sid=NULL;
+
if (!ad_groups) {
debug((char *) "%s| %s: ERR: No space to store groups\n",
LogTime(), PROGRAM);
@@ -454,11 +571,11 @@
bpos = bpos+40;
SidCount = get4byt();
ExtraSids = get4byt();
- /* 4 bytes ResourceGroupDomainSid
- * 4 bytes ResourceGroupCount
- * 4 bytes ResourceGroupIds
- */
- bpos = bpos+12;
+
+ ResourceGroupDomainSid = get4byt();
+ ResourceGroupCount = get4byt();
+ ResourceGroupIds = get4byt();
+
/*
* Read all data from structure => Now check pointers
*/
@@ -483,7 +600,15 @@
if ((ad_groups = getextrasids(ad_groups,ExtraSids,SidCount))==NULL)
goto k5clean;
+ resource_group_domain_sid =
get_resource_group_domain_sid(ResourceGroupDomainSid);
+ if(resource_group_domain_sid && ResourceGroupCount &&
ResourceGroupIds){
+ get_resource_groups(ad_groups, resource_group_domain_sid,
ResourceGroupIds, ResourceGroupCount);
+ }
+
debug((char *) "%s| %s: INFO: Read %d of %d bytes \n", LogTime(),
PROGRAM, bpos, (int)ad_data->length);
+
+ if(resource_group_domain_sid) xfree(resource_group_domain_sid);
+
if (Rids) {
for ( l=0; l<(int)GroupCount; l++) {
xfree(Rids[l]);
@@ -493,6 +618,8 @@
krb5_free_data(context, ad_data);
return ad_groups;
k5clean:
+ if(resource_group_domain_sid) xfree(resource_group_domain_sid);
+
if (Rids) {
for ( l=0; l<(int)GroupCount; l++) {
xfree(Rids[l]);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squid-cache.org/pipermail/squid-users/attachments/20231116/46994f54/attachment.htm>
More information about the squid-users
mailing list