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",
209 debug((
char *)
"%s| %s: ERR: Invalid RIDS list\n",
214 if (DomainLogonId!= 0) {
223 uint32_t nauth = get4byt();
226 static uint32_t maxGidCount = (
UINT32_MAX-1-1-6)/4;
227 if (nauth > maxGidCount) {
228 debug((
char *)
"%s| %s: ERROR: Too many groups ! count > %d : %s\n",
232 size_t length = 1+1+6+nauth*4;
235 for (l=0; l<(
int)GroupCount; l++) {
236 ag=(
char *)
xcalloc((length+4)*
sizeof(char),1);
237 memcpy((
void *)ag,(
const void*)&p[bpos],1);
238 memcpy((
void *)&ag[1],(
const void*)&p[bpos+1],1);
240 memcpy((
void *)&ag[2],(
const void*)&p[bpos+2],6+nauth*4);
241 memcpy((
void *)&ag[length],(
const void*)Rids[l],4);
243 if (!pstrcpy(ad_groups,
"group=")) {
244 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
248 if (!pstrcat(ad_groups,
" group=")) {
249 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
256 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
259 b64buf[expectedSz-1] =
'\0';
260 if (!pstrcat(ad_groups, b64buf)) {
261 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
271 idauth = get6byt_be();
273 snprintf(dli,
sizeof(dli),
"S-%d-%lu",rev,(
long unsigned int)idauth);
274 for ( l=0; l<(
int)nauth; l++ ) {
277 snprintf((
char *)&dli[strlen(dli)],
sizeof(dli)-strlen(dli),
"-%u",sauth);
285 getextrasids(
char *ad_groups, uint32_t ExtraSids, uint32_t SidCount)
295 if ( ngroup != SidCount) {
296 debug((
char *)
"%s| %s: ERROR: Group encoding error => SidCount: %d Array size: %d\n",
302 pa=(uint32_t *)
xmalloc(SidCount*
sizeof(uint32_t));
303 for ( l=0; l < (
int)SidCount; l++ ) {
308 for ( l=0; l<(
int)SidCount; l++ ) {
315 uint32_t nauth = get4byt();
318 static uint32_t maxGidCount = (
UINT32_MAX-1-1-6)/4;
319 if (nauth > maxGidCount) {
320 debug((
char *)
"%s| %s: ERROR: Too many extra groups ! count > %d : %s\n",
326 size_t length = 1+1+6+nauth*4;
327 ag = (
char *)
xcalloc((length)*
sizeof(char),1);
328 memcpy((
void *)ag,(
const void*)&p[bpos],length);
330 debug((
char *)
"%s| %s: ERR: No space to store groups\n",
336 if (!pstrcat(ad_groups,
" group=")) {
337 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
345 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
348 b64buf[expectedSz-1] =
'\0';
349 if (!pstrcat(ad_groups,
reinterpret_cast<char*
>(b64buf))) {
350 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
358 idauth = get6byt_be();
360 snprintf(es,
sizeof(es),
"S-%d-%lu",rev,(
long unsigned int)idauth);
361 for (
int k=0; k<(
int)nauth; k++ ) {
364 snprintf((
char *)&es[strlen(es)],
sizeof(es)-strlen(es),
"-%u",sauth);
375 get_resource_group_domain_sid(
const uint32_t ResourceGroupDomainSid,
size_t &length)
377 if (ResourceGroupDomainSid != 0) {
393 uint32_t nauth = get4byt();
396 static uint32_t maxGidCount = (
UINT32_MAX - 4 - 1 - 1 - 6)/4;
397 if (nauth > maxGidCount) {
398 debug((
char *)
"%s| %s: ERROR: Too many subAuths in the ResourceGroupDomainSID: nauth = %d > %d\n",
404 length = 1 + 1 + 6 + nauth*4;
406 auto sid =
static_cast<char *
>(
xcalloc(length, 1));
410 memcpy((
void *)&sid[0], (
const void*)&p[bpos], 1);
411 memcpy((
void *)&sid[1], (
const void*)&p[bpos+1], 1);
413 memcpy((
void *)&sid[2], (
const void*)&p[bpos+2], 6 + nauth*4);
418 idauth = get6byt_be();
420 int rv = snprintf(dli,
sizeof(dli),
"S-%d-%lu", rev, (
long unsigned int)idauth);
422 for (
int l=0; l<(
int)nauth; l++) {
425 rv = snprintf((
char *)&dli[strlen(dli)],
sizeof(dli) - strlen(dli),
"-%u", sauth);
437 get_resource_groups(
char *ad_groups, uint32_t ResourceGroupDomainSid, uint32_t ResourceGroupIds, uint32_t ResourceGroupCount)
440 debug((
char *)
"%s| %s: ERR: No space to store resource groups\n",
445 size_t group_domain_sid_len = 0;
446 const auto resource_group_domain_sid = get_resource_group_domain_sid(ResourceGroupDomainSid, group_domain_sid_len);
447 if (!resource_group_domain_sid)
450 if (ResourceGroupIds != 0) {
452 uint32_t ngroup = get4byt();
453 if (ngroup != ResourceGroupCount) {
454 debug((
char *)
"%s| %s: ERROR: Group encoding error => ResourceGroupCount: %d != Array size: %d\n",
456 xfree(resource_group_domain_sid);
459 debug((
char *)
"%s| %s: INFO: Found %d Resource Group rids\n",
LogTime(),
PROGRAM, ResourceGroupCount);
462 size_t length = group_domain_sid_len + 4;
463 auto *st =
static_cast<char *
>(
xcalloc(length, 1));
465 memcpy((
void *)st, (
const void*)resource_group_domain_sid, group_domain_sid_len);
467 for (
int l=0; l < (
int)ResourceGroupCount; l++) {
469 memcpy((
void *)&st[group_domain_sid_len], (
const void*)&p[bpos], 4);
471 if (!pstrcat(ad_groups,
" group=")) {
472 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
479 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
482 b64buf[expectedSz - 1] =
'\0';
483 if (!pstrcat(ad_groups,
reinterpret_cast<char*
>(b64buf))) {
484 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
498 xfree(resource_group_domain_sid);
503 get_ad_groups(
char *ad_groups, krb5_context context, krb5_pac pac)
506 RPC_UNICODE_STRING EffectiveName;
507 RPC_UNICODE_STRING FullName;
508 RPC_UNICODE_STRING LogonScript;
509 RPC_UNICODE_STRING ProfilePath;
510 RPC_UNICODE_STRING HomeDirectory;
511 RPC_UNICODE_STRING HomeDirectoryDrive;
512 RPC_UNICODE_STRING LogonServer;
513 RPC_UNICODE_STRING LogonDomainName;
514 uint32_t GroupCount=0;
516 uint32_t LogonDomainId=0;
518 uint32_t UserFlags=0;
519 uint32_t ExtraSids=0;
520 uint32_t ResourceGroupDomainSid=0;
521 uint32_t ResourceGroupCount=0;
522 uint32_t ResourceGroupIds=0;
527 debug((
char *)
"%s| %s: ERR: No space to store groups\n",
532 ad_data = (krb5_data *)
xcalloc(1,
sizeof(krb5_data));
534 #define KERB_LOGON_INFO 1
535 ret = krb5_pac_get_buffer(context, pac, KERB_LOGON_INFO, ad_data);
539 p = (
unsigned char *)ad_data->data;
541 debug((
char *)
"%s| %s: INFO: Got PAC data of length %d\n",
561 getustr(&EffectiveName);
563 getustr(&LogonScript);
564 getustr(&ProfilePath);
565 getustr(&HomeDirectory);
566 getustr(&HomeDirectoryDrive);
573 GroupCount = get4byt();
574 GroupIds = get4byt();
575 UserFlags = get4byt();
578 getustr(&LogonServer);
579 getustr(&LogonDomainName);
580 LogonDomainId = get4byt();
590 SidCount = get4byt();
591 ExtraSids = get4byt();
593 ResourceGroupDomainSid = get4byt();
594 ResourceGroupCount = get4byt();
595 ResourceGroupIds = get4byt();
600 if (checkustr(&EffectiveName)<0)
602 if (checkustr(&FullName)<0)
604 if (checkustr(&LogonScript)<0)
606 if (checkustr(&ProfilePath)<0)
608 if (checkustr(&HomeDirectory)<0)
610 if (checkustr(&HomeDirectoryDrive)<0)
612 Rids = getgids(Rids,GroupIds,GroupCount);
613 if (checkustr(&LogonServer)<0)
615 if (checkustr(&LogonDomainName)<0)
617 ad_groups = getdomaingids(ad_groups,LogonDomainId,Rids,GroupCount);
620 if ((UserFlags&LOGON_EXTRA_SIDS) != 0) {
623 if ((ad_groups = getextrasids(ad_groups,ExtraSids,SidCount)) ==
nullptr)
627 if ((UserFlags&LOGON_RESOURCE_GROUPS) != 0 && ResourceGroupDomainSid && ResourceGroupIds && ResourceGroupCount) {
630 if (!get_resource_groups(ad_groups, ResourceGroupDomainSid, ResourceGroupIds, ResourceGroupCount))
634 debug((
char *)
"%s| %s: INFO: Read %d of %d bytes \n",
LogTime(),
PROGRAM, bpos, (
int)ad_data->length);
637 for ( l=0; l<(
int)GroupCount; l++) {
642 krb5_free_data(context, ad_data);
647 for ( l=0; l<(
int)GroupCount; l++) {
652 krb5_free_data(context, ad_data);