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 (
const auto r = bpos % n)
63 getustr(RPC_UNICODE_STRING *
string)
66 string->length = (uint16_t)((p[bpos]<<0) | (p[bpos+1]<<8));
67 string->maxlength = (uint16_t)((p[bpos+2]<<0) | (p[bpos+2+1]<<8));
68 string->pointer = (uint32_t)((p[bpos+4]<<0) | (p[bpos+4+1]<<8) | (p[bpos+4+2]<<16) | (p[bpos+4+3]<<24));
78 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);
89 var=(uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
100 var=(uint16_t)((p[bpos]<<0) | (p[bpos+1]<<8));
111 var=(uint8_t)((p[bpos]<<0));
118 pstrcpy(
char *src,
const char *dst)
121 if (strlen(dst)>MAX_PAC_GROUP_SIZE)
124 return strcpy(src,dst);
130 pstrcat(
char *src,
const char *dst)
133 if (strlen(src)+strlen(dst)+1>MAX_PAC_GROUP_SIZE)
136 return strcat(src,dst);
142 checkustr(RPC_UNICODE_STRING *
string)
145 if (string->pointer != 0) {
148 size = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
150 off = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
152 len = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
155 string->length > string->maxlength || len != string->length/2) {
156 debug((
char *)
"%s| %s: ERROR: RPC_UNICODE_STRING encoding error => size: %d len: %d/%d maxlength: %d offset: %d\n",
161 bpos = bpos+
string->length;
167 getgids(
char **Rids, uint32_t GroupIds, uint32_t GroupCount)
175 if ( ngroup != GroupCount) {
176 debug((
char *)
"%s| %s: ERROR: Group encoding error => GroupCount: %d Array size: %d\n",
182 Rids=(
char **)
xcalloc(GroupCount*
sizeof(
char*),1);
183 for ( l=0; l<(
int)GroupCount; l++) {
185 Rids[l]=(
char *)
xcalloc(4*
sizeof(
char),1);
186 memcpy((
void *)Rids[l],(
void *)&p[bpos],4);
197 getdomaingids(
char *ad_groups, uint32_t DomainLogonId,
char **Rids, uint32_t GroupCount)
200 debug((
char *)
"%s| %s: ERR: No space to store groups\n",
206 debug((
char *)
"%s| %s: ERR: Invalid RIDS list\n",
211 if (DomainLogonId!= 0) {
220 uint32_t nauth = get4byt();
223 static uint32_t maxGidCount = (
UINT32_MAX-1-1-6)/4;
224 if (nauth > maxGidCount) {
225 debug((
char *)
"%s| %s: ERROR: Too many groups ! count > %d : %s\n",
229 size_t length = 1+1+6+nauth*4;
232 for (l=0; l<(
int)GroupCount; l++) {
233 ag=(
char *)
xcalloc((length+4)*
sizeof(char),1);
234 memcpy((
void *)ag,(
const void*)&p[bpos],1);
235 memcpy((
void *)&ag[1],(
const void*)&p[bpos+1],1);
237 memcpy((
void *)&ag[2],(
const void*)&p[bpos+2],6+nauth*4);
238 memcpy((
void *)&ag[length],(
const void*)Rids[l],4);
240 if (!pstrcpy(ad_groups,
"group=")) {
241 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
245 if (!pstrcat(ad_groups,
" group=")) {
246 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
253 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
256 b64buf[expectedSz-1] =
'\0';
257 if (!pstrcat(ad_groups, b64buf)) {
258 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
268 idauth = get6byt_be();
270 snprintf(dli,
sizeof(dli),
"S-%d-%lu",rev,(
long unsigned int)idauth);
271 for ( l=0; l<(
int)nauth; l++ ) {
274 snprintf((
char *)&dli[strlen(dli)],
sizeof(dli)-strlen(dli),
"-%u",sauth);
282 getextrasids(
char *ad_groups, uint32_t ExtraSids, uint32_t SidCount)
292 if ( ngroup != SidCount) {
293 debug((
char *)
"%s| %s: ERROR: Group encoding error => SidCount: %d Array size: %d\n",
299 pa=(uint32_t *)
xmalloc(SidCount*
sizeof(uint32_t));
300 for ( l=0; l < (
int)SidCount; l++ ) {
305 for ( l=0; l<(
int)SidCount; l++ ) {
312 uint32_t nauth = get4byt();
315 static uint32_t maxGidCount = (
UINT32_MAX-1-1-6)/4;
316 if (nauth > maxGidCount) {
317 debug((
char *)
"%s| %s: ERROR: Too many extra groups ! count > %d : %s\n",
323 size_t length = 1+1+6+nauth*4;
324 ag = (
char *)
xcalloc((length)*
sizeof(char),1);
325 memcpy((
void *)ag,(
const void*)&p[bpos],length);
327 debug((
char *)
"%s| %s: ERR: No space to store groups\n",
333 if (!pstrcat(ad_groups,
" group=")) {
334 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
342 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
345 b64buf[expectedSz-1] =
'\0';
346 if (!pstrcat(ad_groups,
reinterpret_cast<char*
>(b64buf))) {
347 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
355 idauth = get6byt_be();
357 snprintf(es,
sizeof(es),
"S-%d-%lu",rev,(
long unsigned int)idauth);
358 for (
int k=0; k<(
int)nauth; k++ ) {
361 snprintf((
char *)&es[strlen(es)],
sizeof(es)-strlen(es),
"-%u",sauth);
372 get_resource_group_domain_sid(
const uint32_t ResourceGroupDomainSid,
size_t &length)
374 if (ResourceGroupDomainSid != 0) {
390 uint32_t nauth = get4byt();
393 static uint32_t maxGidCount = (
UINT32_MAX - 4 - 1 - 1 - 6)/4;
394 if (nauth > maxGidCount) {
395 debug((
char *)
"%s| %s: ERROR: Too many subAuths in the ResourceGroupDomainSID: nauth = %d > %d\n",
401 length = 1 + 1 + 6 + nauth*4;
403 auto sid =
static_cast<char *
>(
xcalloc(length, 1));
407 memcpy((
void *)&sid[0], (
const void*)&p[bpos], 1);
408 memcpy((
void *)&sid[1], (
const void*)&p[bpos+1], 1);
410 memcpy((
void *)&sid[2], (
const void*)&p[bpos+2], 6 + nauth*4);
415 idauth = get6byt_be();
417 int rv = snprintf(dli,
sizeof(dli),
"S-%d-%lu", rev, (
long unsigned int)idauth);
419 for (
int l=0; l<(
int)nauth; l++) {
422 rv = snprintf((
char *)&dli[strlen(dli)],
sizeof(dli) - strlen(dli),
"-%u", sauth);
434 get_resource_groups(
char *ad_groups, uint32_t ResourceGroupDomainSid, uint32_t ResourceGroupIds, uint32_t ResourceGroupCount)
437 debug((
char *)
"%s| %s: ERR: No space to store resource groups\n",
442 size_t group_domain_sid_len = 0;
443 const auto resource_group_domain_sid = get_resource_group_domain_sid(ResourceGroupDomainSid, group_domain_sid_len);
444 if (!resource_group_domain_sid)
447 if (ResourceGroupIds != 0) {
449 uint32_t ngroup = get4byt();
450 if (ngroup != ResourceGroupCount) {
451 debug((
char *)
"%s| %s: ERROR: Group encoding error => ResourceGroupCount: %d != Array size: %d\n",
453 xfree(resource_group_domain_sid);
456 debug((
char *)
"%s| %s: INFO: Found %d Resource Group rids\n",
LogTime(),
PROGRAM, ResourceGroupCount);
459 size_t length = group_domain_sid_len + 4;
460 auto *st =
static_cast<char *
>(
xcalloc(length, 1));
462 memcpy((
void *)st, (
const void*)resource_group_domain_sid, group_domain_sid_len);
464 for (
int l=0; l < (
int)ResourceGroupCount; l++) {
466 memcpy((
void *)&st[group_domain_sid_len], (
const void*)&p[bpos], 4);
468 if (!pstrcat(ad_groups,
" group=")) {
469 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
476 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
479 b64buf[expectedSz - 1] =
'\0';
480 if (!pstrcat(ad_groups,
reinterpret_cast<char*
>(b64buf))) {
481 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
495 xfree(resource_group_domain_sid);
500 get_ad_groups(
char *ad_groups, krb5_context context, krb5_pac pac)
503 RPC_UNICODE_STRING EffectiveName;
504 RPC_UNICODE_STRING FullName;
505 RPC_UNICODE_STRING LogonScript;
506 RPC_UNICODE_STRING ProfilePath;
507 RPC_UNICODE_STRING HomeDirectory;
508 RPC_UNICODE_STRING HomeDirectoryDrive;
509 RPC_UNICODE_STRING LogonServer;
510 RPC_UNICODE_STRING LogonDomainName;
511 uint32_t GroupCount=0;
513 uint32_t LogonDomainId=0;
515 uint32_t UserFlags=0;
516 uint32_t ExtraSids=0;
517 uint32_t ResourceGroupDomainSid=0;
518 uint32_t ResourceGroupCount=0;
519 uint32_t ResourceGroupIds=0;
524 debug((
char *)
"%s| %s: ERR: No space to store groups\n",
529 ad_data = (krb5_data *)
xcalloc(1,
sizeof(krb5_data));
531 #define KERB_LOGON_INFO 1
532 ret = krb5_pac_get_buffer(context, pac, KERB_LOGON_INFO, ad_data);
536 p = (
unsigned char *)ad_data->data;
538 debug((
char *)
"%s| %s: INFO: Got PAC data of length %d\n",
558 getustr(&EffectiveName);
560 getustr(&LogonScript);
561 getustr(&ProfilePath);
562 getustr(&HomeDirectory);
563 getustr(&HomeDirectoryDrive);
570 GroupCount = get4byt();
571 GroupIds = get4byt();
572 UserFlags = get4byt();
575 getustr(&LogonServer);
576 getustr(&LogonDomainName);
577 LogonDomainId = get4byt();
587 SidCount = get4byt();
588 ExtraSids = get4byt();
590 ResourceGroupDomainSid = get4byt();
591 ResourceGroupCount = get4byt();
592 ResourceGroupIds = get4byt();
597 if (checkustr(&EffectiveName)<0)
599 if (checkustr(&FullName)<0)
601 if (checkustr(&LogonScript)<0)
603 if (checkustr(&ProfilePath)<0)
605 if (checkustr(&HomeDirectory)<0)
607 if (checkustr(&HomeDirectoryDrive)<0)
609 Rids = getgids(Rids,GroupIds,GroupCount);
610 if (checkustr(&LogonServer)<0)
612 if (checkustr(&LogonDomainName)<0)
614 ad_groups = getdomaingids(ad_groups,LogonDomainId,Rids,GroupCount);
617 if ((UserFlags&LOGON_EXTRA_SIDS) != 0) {
620 if ((ad_groups = getextrasids(ad_groups,ExtraSids,SidCount)) ==
nullptr)
624 if ((UserFlags&LOGON_RESOURCE_GROUPS) != 0 && ResourceGroupDomainSid && ResourceGroupIds && ResourceGroupCount) {
627 if (!get_resource_groups(ad_groups, ResourceGroupDomainSid, ResourceGroupIds, ResourceGroupCount))
631 debug((
char *)
"%s| %s: INFO: Read %d of %d bytes \n",
LogTime(),
PROGRAM, bpos, (
int)ad_data->length);
634 for ( l=0; l<(
int)GroupCount; l++) {
639 krb5_free_data(context, ad_data);
644 for ( l=0; l<(
int)GroupCount; l++) {
649 krb5_free_data(context, ad_data);