<div dir="ltr">Hello, <div><br></div><div>I found that negotiate_kerberos_auth helper does not see domain local AD groups.</div><div>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.</div><div>I have slightly patched the negotiate_kerberos_pac.cc to implement ResourceGropIds-block parsing.</div><div>Maybe it will be useful for the community.</div><div>This patch can be included in future Squid-releases.</div><div><br></div><div>Kind regards,</div><div>   Ankor.</div><div><br></div><div>The patch for the file src/auth/negotiate/kerberos/negotiate_kerberos_pac.cc below:</div><div><br></div><div>@@ -362,6 +362,123 @@<br>     return ad_groups;<br> }<br><br>+<br>+char *<br>+get_resource_group_domain_sid(uint32_t ResourceGroupDomainSid){<br>+<br>+    if (ResourceGroupDomainSid!= 0) {<br>+        uint8_t rev;<br>+        uint64_t idauth;<br>+        char dli[256];<br>+        char *ag;<br>+        int l;<br>+<br>+        align(4);<br>+<br>+        uint32_t nauth = get4byt();<br>+<br>+        size_t length = 1+1+6+nauth*4;<br>+<br>+            ag=(char *)xcalloc((length+1)*sizeof(char),1);<br>+            // the first byte is a length of the SID<br>+            ag[0] = (char) length;<br>+            memcpy((void *)&ag[1],(const void*)&p[bpos],1);<br>+            memcpy((void *)&ag[2],(const void*)&p[bpos+1],1);<br>+            ag[2] = ag[2]+1;<br>+            memcpy((void *)&ag[3],(const void*)&p[bpos+2],6+nauth*4);<br>+<br>+<br>+<br>+        /* mainly for debug only */<br>+        rev = get1byt();<br>+        bpos = bpos + 1; /*nsub*/<br>+        idauth = get6byt_be();<br>+<br>+        snprintf(dli,sizeof(dli),"S-%d-%lu",rev,(long unsigned int)idauth);<br>+        for ( l=0; l<(int)nauth; l++ ) {<br>+            uint32_t sauth;<br>+            sauth = get4byt();<br>+            snprintf((char *)&dli[strlen(dli)],sizeof(dli)-strlen(dli),"-%u",sauth);<br>+        }<br>+        debug((char *) "%s| %s: INFO: Got ResourceGroupDomainSid %s\n", LogTime(), PROGRAM, dli);<br>+        return ag;<br>+    }<br>+<br>+    return NULL;<br>+}<br>+<br>+char *<br>+get_resource_groups(char *ad_groups, char *resource_group_domain_sid, uint32_t ResourceGroupIds, uint32_t ResourceGroupCount){<br>+    size_t group_domain_sid_len = resource_group_domain_sid[0];<br>+    char *ag;<br>+    size_t length;<br>+<br>+    resource_group_domain_sid++; //now it points to the actual data<br>+<br>+<br>+    if (ResourceGroupIds!= 0) {<br>+        uint32_t ngroup;<br>+        int l;<br>+<br>+        align(4);<br>+        ngroup = get4byt();<br>+        if ( ngroup != ResourceGroupCount) {<br>+            debug((char *) "%s| %s: ERROR: Group encoding error => ResourceGroupCount: %d Array size: %d\n",<br>+                  LogTime(), PROGRAM, ResourceGroupCount, ngroup);<br>+            return NULL;<br>+        }<br>+        debug((char *) "%s| %s: INFO: Found %d Resource Group rids\n", LogTime(), PROGRAM, ResourceGroupCount);<br>+<br>+        //make a group template which begins with the ResourceGroupDomainID<br>+        length = group_domain_sid_len+4;  //+4 for a rid<br>+        ag=(char *)xcalloc(length*sizeof(char),1);<br>+        memcpy((void *)ag,(const void*)resource_group_domain_sid, group_domain_sid_len);<br>+<br>+<br>+        for ( l=0; l<(int)ResourceGroupCount; l++) {<br>+            uint32_t sauth;<br>+            memcpy((void *)&ag[group_domain_sid_len],(const void*)&p[bpos],4);<br>+<br>+            if (!pstrcat(ad_groups," group=")) {<br>+                debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n",<br>+                      LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);<br>+               xfree(ag);<br>+               return NULL;<br>+            }<br>+<br>+<br>+            struct base64_encode_ctx ctx;<br>+            base64_encode_init(&ctx);<br>+            const uint32_t expectedSz = base64_encode_len(length) +1 /* terminator */;<br>+            char *b64buf = static_cast<char *>(xcalloc(expectedSz, 1));<br>+            size_t blen = base64_encode_update(&ctx, b64buf, length, reinterpret_cast<uint8_t*>(ag));<br>+            blen += base64_encode_final(&ctx, b64buf+blen);<br>+            b64buf[expectedSz-1] = '\0';<br>+            if (!pstrcat(ad_groups, reinterpret_cast<char*>(b64buf))) {<br>+                debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n",<br>+                      LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);<br>+               xfree(ag);<br>+               xfree(b64buf);<br>+               return NULL;<br>+            }<br>+            xfree(b64buf);<br>+<br>+<br>+<br>+            sauth = get4byt();<br>+            debug((char *) "%s| %s: Info: Got rid: %u\n", LogTime(), PROGRAM, sauth);<br>+            /* attribute */<br>+            bpos = bpos+4;<br>+        }<br>+<br>+        xfree(ag);<br>+       return ad_groups;<br>+    }<br>+<br>+    return NULL;<br>+}<br>+<br>+<br> char *<br> get_ad_groups(char *ad_groups, krb5_context context, krb5_pac pac)<br> {<br>@@ -379,14 +496,14 @@<br>     uint32_t LogonDomainId=0;<br>     uint32_t SidCount=0;<br>     uint32_t ExtraSids=0;<br>-    /*<br>     uint32_t ResourceGroupDomainSid=0;<br>     uint32_t ResourceGroupCount=0;<br>     uint32_t ResourceGroupIds=0;<br>-    */<br>     char **Rids=NULL;<br>     int l=0;<br><br>+    char * resource_group_domain_sid=NULL;<br>+<br>     if (!ad_groups) {<br>         debug((char *) "%s| %s: ERR: No space to store groups\n",<br>               LogTime(), PROGRAM);<br>@@ -454,11 +571,11 @@<br>     bpos = bpos+40;<br>     SidCount = get4byt();<br>     ExtraSids = get4byt();<br>-    /* 4 bytes ResourceGroupDomainSid<br>-     * 4 bytes ResourceGroupCount<br>-     * 4 bytes ResourceGroupIds<br>-     */<br>-    bpos = bpos+12;<br>+<br>+    ResourceGroupDomainSid = get4byt();<br>+    ResourceGroupCount = get4byt();<br>+    ResourceGroupIds = get4byt();<br>+<br>     /*<br>      * Read all data from structure => Now check pointers<br>      */<br>@@ -483,7 +600,15 @@<br>     if ((ad_groups = getextrasids(ad_groups,ExtraSids,SidCount))==NULL)<br>         goto k5clean;<br><br>+    resource_group_domain_sid = get_resource_group_domain_sid(ResourceGroupDomainSid);<br>+    if(resource_group_domain_sid && ResourceGroupCount && ResourceGroupIds){<br>+        get_resource_groups(ad_groups, resource_group_domain_sid, ResourceGroupIds, ResourceGroupCount);<br>+    }<br>+<br>     debug((char *) "%s| %s: INFO: Read %d of %d bytes \n", LogTime(), PROGRAM, bpos, (int)ad_data->length);<br>+<br>+    if(resource_group_domain_sid) xfree(resource_group_domain_sid);<br>+<br>     if (Rids) {<br>         for ( l=0; l<(int)GroupCount; l++) {<br>             xfree(Rids[l]);<br>@@ -493,6 +618,8 @@<br>     krb5_free_data(context, ad_data);<br>     return ad_groups;<br> k5clean:<br>+    if(resource_group_domain_sid) xfree(resource_group_domain_sid);<br>+<br>     if (Rids) {<br>         for ( l=0; l<(int)GroupCount; l++) {<br>             xfree(Rids[l]);<br></div></div>