[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