43 #if HAVE_GSSAPI && HAVE_PAC_SUPPORT
45 #define LOGON_EXTRA_SIDS 0x0020
46 #define LOGON_RESOURCE_GROUPS 0x0200
49 static krb5_data *ad_data;
50 static unsigned char *p;
53 check_k5_err(krb5_context context,
const char *
function, krb5_error_code
code);
58 if ( bpos % n != 0 ) {
61 bpos = bpos+(bpos-n*al);
66 getustr(RPC_UNICODE_STRING *
string)
69 string->length = (uint16_t)((p[bpos]<<0) | (p[bpos+1]<<8));
70 string->maxlength = (uint16_t)((p[bpos+2]<<0) | (p[bpos+2+1]<<8));
71 string->pointer = (uint32_t)((p[bpos+4]<<0) | (p[bpos+4+1]<<8) | (p[bpos+4+2]<<16) | (p[bpos+4+3]<<24));
81 var = ((uint64_t)p[bpos+5]<<0) | ((uint64_t)p[bpos+4]<<8) | ((uint64_t)p[bpos+3]<<16) | ((uint64_t)p[bpos+2]<<24) | ((uint64_t)p[bpos+1]<<32) | ((uint64_t)p[bpos]<<40);
92 var=(uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
103 var=(uint16_t)((p[bpos]<<0) | (p[bpos+1]<<8));
114 var=(uint8_t)((p[bpos]<<0));
121 pstrcpy(
char *src,
const char *dst)
124 if (strlen(dst)>MAX_PAC_GROUP_SIZE)
127 return strcpy(src,dst);
133 pstrcat(
char *src,
const char *dst)
136 if (strlen(src)+strlen(dst)+1>MAX_PAC_GROUP_SIZE)
139 return strcat(src,dst);
145 checkustr(RPC_UNICODE_STRING *
string)
148 if (string->pointer != 0) {
151 size = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
153 off = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
155 len = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
158 string->length > string->maxlength || len != string->length/2) {
159 debug((
char *)
"%s| %s: ERROR: RPC_UNICODE_STRING encoding error => size: %d len: %d/%d maxlength: %d offset: %d\n",
164 bpos = bpos+
string->length;
170 getgids(
char **Rids, uint32_t GroupIds, uint32_t GroupCount)
178 if ( ngroup != GroupCount) {
179 debug((
char *)
"%s| %s: ERROR: Group encoding error => GroupCount: %d Array size: %d\n",
185 Rids=(
char **)
xcalloc(GroupCount*
sizeof(
char*),1);
186 for ( l=0; l<(
int)GroupCount; l++) {
188 Rids[l]=(
char *)
xcalloc(4*
sizeof(
char),1);
189 memcpy((
void *)Rids[l],(
void *)&p[bpos],4);
200 getdomaingids(
char *ad_groups, uint32_t DomainLogonId,
char **Rids, uint32_t GroupCount)
203 debug((
char *)
"%s| %s: ERR: No space to store groups\n",
208 if (DomainLogonId!= 0) {
217 uint32_t nauth = get4byt();
220 static uint32_t maxGidCount = (
UINT32_MAX-1-1-6)/4;
221 if (nauth > maxGidCount) {
222 debug((
char *)
"%s| %s: ERROR: Too many groups ! count > %d : %s\n",
226 size_t length = 1+1+6+nauth*4;
229 for (l=0; l<(
int)GroupCount; l++) {
230 ag=(
char *)
xcalloc((length+4)*
sizeof(char),1);
231 memcpy((
void *)ag,(
const void*)&p[bpos],1);
232 memcpy((
void *)&ag[1],(
const void*)&p[bpos+1],1);
234 memcpy((
void *)&ag[2],(
const void*)&p[bpos+2],6+nauth*4);
235 memcpy((
void *)&ag[length],(
const void*)Rids[l],4);
237 if (!pstrcpy(ad_groups,
"group=")) {
238 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
242 if (!pstrcat(ad_groups,
" group=")) {
243 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
250 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
253 b64buf[expectedSz-1] =
'\0';
254 if (!pstrcat(ad_groups, b64buf)) {
255 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
265 idauth = get6byt_be();
267 snprintf(dli,
sizeof(dli),
"S-%d-%lu",rev,(
long unsigned int)idauth);
268 for ( l=0; l<(
int)nauth; l++ ) {
271 snprintf((
char *)&dli[strlen(dli)],
sizeof(dli)-strlen(dli),
"-%u",sauth);
279 getextrasids(
char *ad_groups, uint32_t ExtraSids, uint32_t SidCount)
289 if ( ngroup != SidCount) {
290 debug((
char *)
"%s| %s: ERROR: Group encoding error => SidCount: %d Array size: %d\n",
296 pa=(uint32_t *)
xmalloc(SidCount*
sizeof(uint32_t));
297 for ( l=0; l < (
int)SidCount; l++ ) {
302 for ( l=0; l<(
int)SidCount; l++ ) {
309 uint32_t nauth = get4byt();
312 static uint32_t maxGidCount = (
UINT32_MAX-1-1-6)/4;
313 if (nauth > maxGidCount) {
314 debug((
char *)
"%s| %s: ERROR: Too many extra groups ! count > %d : %s\n",
320 size_t length = 1+1+6+nauth*4;
321 ag = (
char *)
xcalloc((length)*
sizeof(char),1);
322 memcpy((
void *)ag,(
const void*)&p[bpos],length);
324 debug((
char *)
"%s| %s: ERR: No space to store groups\n",
330 if (!pstrcat(ad_groups,
" group=")) {
331 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
339 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
342 b64buf[expectedSz-1] =
'\0';
343 if (!pstrcat(ad_groups,
reinterpret_cast<char*
>(b64buf))) {
344 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
352 idauth = get6byt_be();
354 snprintf(es,
sizeof(es),
"S-%d-%lu",rev,(
long unsigned int)idauth);
355 for (
int k=0; k<(
int)nauth; k++ ) {
358 snprintf((
char *)&es[strlen(es)],
sizeof(es)-strlen(es),
"-%u",sauth);
369 get_resource_group_domain_sid(
const uint32_t ResourceGroupDomainSid,
size_t &length)
371 if (ResourceGroupDomainSid != 0) {
387 uint32_t nauth = get4byt();
390 static uint32_t maxGidCount = (
UINT32_MAX - 4 - 1 - 1 - 6)/4;
391 if (nauth > maxGidCount) {
392 debug((
char *)
"%s| %s: ERROR: Too many subAuths in the ResourceGroupDomainSID: nauth = %d > %d\n",
398 length = 1 + 1 + 6 + nauth*4;
400 auto sid =
static_cast<char *
>(
xcalloc(length, 1));
404 memcpy((
void *)&sid[0], (
const void*)&p[bpos], 1);
405 memcpy((
void *)&sid[1], (
const void*)&p[bpos+1], 1);
407 memcpy((
void *)&sid[2], (
const void*)&p[bpos+2], 6 + nauth*4);
412 idauth = get6byt_be();
414 int rv = snprintf(dli,
sizeof(dli),
"S-%d-%lu", rev, (
long unsigned int)idauth);
416 for (
int l=0; l<(
int)nauth; l++) {
419 rv = snprintf((
char *)&dli[strlen(dli)],
sizeof(dli) - strlen(dli),
"-%u", sauth);
431 get_resource_groups(
char *ad_groups, uint32_t ResourceGroupDomainSid, uint32_t ResourceGroupIds, uint32_t ResourceGroupCount)
434 debug((
char *)
"%s| %s: ERR: No space to store resource groups\n",
439 size_t group_domain_sid_len = 0;
440 const auto resource_group_domain_sid = get_resource_group_domain_sid(ResourceGroupDomainSid, group_domain_sid_len);
441 if (!resource_group_domain_sid)
444 if (ResourceGroupIds != 0) {
446 uint32_t ngroup = get4byt();
447 if (ngroup != ResourceGroupCount) {
448 debug((
char *)
"%s| %s: ERROR: Group encoding error => ResourceGroupCount: %d != Array size: %d\n",
450 xfree(resource_group_domain_sid);
453 debug((
char *)
"%s| %s: INFO: Found %d Resource Group rids\n",
LogTime(),
PROGRAM, ResourceGroupCount);
456 size_t length = group_domain_sid_len + 4;
457 auto *st =
static_cast<char *
>(
xcalloc(length, 1));
459 memcpy((
void *)st, (
const void*)resource_group_domain_sid, group_domain_sid_len);
461 for (
int l=0; l < (
int)ResourceGroupCount; l++) {
463 memcpy((
void *)&st[group_domain_sid_len], (
const void*)&p[bpos], 4);
465 if (!pstrcat(ad_groups,
" group=")) {
466 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
473 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
476 b64buf[expectedSz - 1] =
'\0';
477 if (!pstrcat(ad_groups,
reinterpret_cast<char*
>(b64buf))) {
478 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
492 xfree(resource_group_domain_sid);
497 get_ad_groups(
char *ad_groups, krb5_context context, krb5_pac pac)
500 RPC_UNICODE_STRING EffectiveName;
501 RPC_UNICODE_STRING FullName;
502 RPC_UNICODE_STRING LogonScript;
503 RPC_UNICODE_STRING ProfilePath;
504 RPC_UNICODE_STRING HomeDirectory;
505 RPC_UNICODE_STRING HomeDirectoryDrive;
506 RPC_UNICODE_STRING LogonServer;
507 RPC_UNICODE_STRING LogonDomainName;
508 uint32_t GroupCount=0;
510 uint32_t LogonDomainId=0;
512 uint32_t UserFlags=0;
513 uint32_t ExtraSids=0;
514 uint32_t ResourceGroupDomainSid=0;
515 uint32_t ResourceGroupCount=0;
516 uint32_t ResourceGroupIds=0;
521 debug((
char *)
"%s| %s: ERR: No space to store groups\n",
526 ad_data = (krb5_data *)
xcalloc(1,
sizeof(krb5_data));
528 #define KERB_LOGON_INFO 1
529 ret = krb5_pac_get_buffer(context, pac, KERB_LOGON_INFO, ad_data);
533 p = (
unsigned char *)ad_data->data;
535 debug((
char *)
"%s| %s: INFO: Got PAC data of length %d\n",
555 getustr(&EffectiveName);
557 getustr(&LogonScript);
558 getustr(&ProfilePath);
559 getustr(&HomeDirectory);
560 getustr(&HomeDirectoryDrive);
567 GroupCount = get4byt();
568 GroupIds = get4byt();
569 UserFlags = get4byt();
572 getustr(&LogonServer);
573 getustr(&LogonDomainName);
574 LogonDomainId = get4byt();
584 SidCount = get4byt();
585 ExtraSids = get4byt();
587 ResourceGroupDomainSid = get4byt();
588 ResourceGroupCount = get4byt();
589 ResourceGroupIds = get4byt();
594 if (checkustr(&EffectiveName)<0)
596 if (checkustr(&FullName)<0)
598 if (checkustr(&LogonScript)<0)
600 if (checkustr(&ProfilePath)<0)
602 if (checkustr(&HomeDirectory)<0)
604 if (checkustr(&HomeDirectoryDrive)<0)
606 Rids = getgids(Rids,GroupIds,GroupCount);
607 if (checkustr(&LogonServer)<0)
609 if (checkustr(&LogonDomainName)<0)
611 ad_groups = getdomaingids(ad_groups,LogonDomainId,Rids,GroupCount);
614 if ((UserFlags&LOGON_EXTRA_SIDS) != 0) {
617 if ((ad_groups = getextrasids(ad_groups,ExtraSids,SidCount)) ==
nullptr)
621 if ((UserFlags&LOGON_RESOURCE_GROUPS) != 0 && ResourceGroupDomainSid && ResourceGroupIds && ResourceGroupCount) {
624 if (!get_resource_groups(ad_groups, ResourceGroupDomainSid, ResourceGroupIds, ResourceGroupCount))
628 debug((
char *)
"%s| %s: INFO: Read %d of %d bytes \n",
LogTime(),
PROGRAM, bpos, (
int)ad_data->length);
631 for ( l=0; l<(
int)GroupCount; l++) {
636 krb5_free_data(context, ad_data);
641 for ( l=0; l<(
int)GroupCount; l++) {
646 krb5_free_data(context, ad_data);