42#if HAVE_GSSAPI && HAVE_KRB5_PAC_SUPPORT
44#define LOGON_EXTRA_SIDS 0x0020
45#define LOGON_RESOURCE_GROUPS 0x0200
48static krb5_data *ad_data;
49static unsigned char *p;
52check_k5_err(krb5_context context,
const char *function, krb5_error_code code);
57 if (
const auto r = bpos % n)
62getustr(RPC_UNICODE_STRING *
string)
65 string->length = (uint16_t)((p[bpos]<<0) | (p[bpos+1]<<8));
66 string->maxlength = (uint16_t)((p[bpos+2]<<0) | (p[bpos+2+1]<<8));
67 string->pointer = (uint32_t)((p[bpos+4]<<0) | (p[bpos+4+1]<<8) | (p[bpos+4+2]<<16) | (p[bpos+4+3]<<24));
77 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);
88 var=(uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
99 var=(uint16_t)((p[bpos]<<0) | (p[bpos+1]<<8));
110 var=(uint8_t)((p[bpos]<<0));
117pstrcpy(
char *src,
const char *dst)
120 if (strlen(dst)>MAX_PAC_GROUP_SIZE)
123 return strcpy(src,dst);
129pstrcat(
char *src,
const char *dst)
132 if (strlen(src)+strlen(dst)+1>MAX_PAC_GROUP_SIZE)
135 return strcat(src,dst);
141checkustr(RPC_UNICODE_STRING *
string)
144 if (string->pointer != 0) {
147 size = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
149 off = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
151 len = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
154 string->length > string->maxlength || len != string->length/2) {
155 debug((
char *)
"%s| %s: ERROR: RPC_UNICODE_STRING encoding error => size: %d len: %d/%d maxlength: %d offset: %d\n",
160 bpos = bpos+
string->length;
166getgids(
char **Rids, uint32_t GroupIds, uint32_t GroupCount)
174 if ( ngroup != GroupCount) {
175 debug((
char *)
"%s| %s: ERROR: Group encoding error => GroupCount: %d Array size: %d\n",
181 Rids=(
char **)
xcalloc(GroupCount*
sizeof(
char*),1);
182 for ( l=0; l<(
int)GroupCount; l++) {
184 Rids[l]=(
char *)
xcalloc(4*
sizeof(
char),1);
185 memcpy((
void *)Rids[l],(
void *)&p[bpos],4);
196getdomaingids(
char *ad_groups, uint32_t DomainLogonId,
char **Rids, uint32_t GroupCount)
199 debug((
char *)
"%s| %s: ERR: No space to store groups\n",
205 debug((
char *)
"%s| %s: ERR: Invalid RIDS list\n",
210 if (DomainLogonId!= 0) {
219 uint32_t nauth = get4byt();
222 static uint32_t maxGidCount = (
UINT32_MAX-1-1-6)/4;
223 if (nauth > maxGidCount) {
224 debug((
char *)
"%s| %s: ERROR: Too many groups ! count > %d : %s\n",
228 size_t length = 1+1+6+nauth*4;
231 for (l=0; l<(
int)GroupCount; l++) {
232 ag=(
char *)
xcalloc((length+4)*
sizeof(char),1);
233 memcpy((
void *)ag,(
const void*)&p[bpos],1);
234 memcpy((
void *)&ag[1],(
const void*)&p[bpos+1],1);
236 memcpy((
void *)&ag[2],(
const void*)&p[bpos+2],6+nauth*4);
237 memcpy((
void *)&ag[length],(
const void*)Rids[l],4);
239 if (!pstrcpy(ad_groups,
"group=")) {
240 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
244 if (!pstrcat(ad_groups,
" group=")) {
245 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
252 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
255 b64buf[expectedSz-1] =
'\0';
256 if (!pstrcat(ad_groups, b64buf)) {
257 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
267 idauth = get6byt_be();
269 snprintf(dli,
sizeof(dli),
"S-%d-%lu",rev,(
long unsigned int)idauth);
270 for ( l=0; l<(
int)nauth; l++ ) {
273 snprintf((
char *)&dli[strlen(dli)],
sizeof(dli)-strlen(dli),
"-%u",sauth);
281getextrasids(
char *ad_groups, uint32_t ExtraSids, uint32_t SidCount)
291 if ( ngroup != SidCount) {
292 debug((
char *)
"%s| %s: ERROR: Group encoding error => SidCount: %d Array size: %d\n",
298 pa=(uint32_t *)
xmalloc(SidCount*
sizeof(uint32_t));
299 for ( l=0; l < (
int)SidCount; l++ ) {
304 for ( l=0; l<(
int)SidCount; l++ ) {
311 uint32_t nauth = get4byt();
314 static uint32_t maxGidCount = (
UINT32_MAX-1-1-6)/4;
315 if (nauth > maxGidCount) {
316 debug((
char *)
"%s| %s: ERROR: Too many extra groups ! count > %d : %s\n",
322 size_t length = 1+1+6+nauth*4;
323 ag = (
char *)
xcalloc((length)*
sizeof(char),1);
324 memcpy((
void *)ag,(
const void*)&p[bpos],length);
326 debug((
char *)
"%s| %s: ERR: No space to store groups\n",
332 if (!pstrcat(ad_groups,
" group=")) {
333 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
341 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
344 b64buf[expectedSz-1] =
'\0';
345 if (!pstrcat(ad_groups,
reinterpret_cast<char*
>(b64buf))) {
346 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
354 idauth = get6byt_be();
356 snprintf(es,
sizeof(es),
"S-%d-%lu",rev,(
long unsigned int)idauth);
357 for (
int k=0; k<(
int)nauth; k++ ) {
360 snprintf((
char *)&es[strlen(es)],
sizeof(es)-strlen(es),
"-%u",sauth);
371get_resource_group_domain_sid(
const uint32_t ResourceGroupDomainSid,
size_t &length)
373 if (ResourceGroupDomainSid != 0) {
389 uint32_t nauth = get4byt();
392 static uint32_t maxGidCount = (
UINT32_MAX - 4 - 1 - 1 - 6)/4;
393 if (nauth > maxGidCount) {
394 debug((
char *)
"%s| %s: ERROR: Too many subAuths in the ResourceGroupDomainSID: nauth = %d > %d\n",
400 length = 1 + 1 + 6 + nauth*4;
402 auto sid =
static_cast<char *
>(
xcalloc(length, 1));
406 memcpy((
void *)&sid[0], (
const void*)&p[bpos], 1);
407 memcpy((
void *)&sid[1], (
const void*)&p[bpos+1], 1);
409 memcpy((
void *)&sid[2], (
const void*)&p[bpos+2], 6 + nauth*4);
414 idauth = get6byt_be();
416 int rv = snprintf(dli,
sizeof(dli),
"S-%d-%lu", rev, (
long unsigned int)idauth);
418 for (
int l=0; l<(
int)nauth; l++) {
421 rv = snprintf((
char *)&dli[strlen(dli)],
sizeof(dli) - strlen(dli),
"-%u", sauth);
433get_resource_groups(
char *ad_groups, uint32_t ResourceGroupDomainSid, uint32_t ResourceGroupIds, uint32_t ResourceGroupCount)
436 debug((
char *)
"%s| %s: ERR: No space to store resource groups\n",
441 size_t group_domain_sid_len = 0;
442 const auto resource_group_domain_sid = get_resource_group_domain_sid(ResourceGroupDomainSid, group_domain_sid_len);
443 if (!resource_group_domain_sid)
446 if (ResourceGroupIds != 0) {
448 uint32_t ngroup = get4byt();
449 if (ngroup != ResourceGroupCount) {
450 debug((
char *)
"%s| %s: ERROR: Group encoding error => ResourceGroupCount: %d != Array size: %d\n",
452 xfree(resource_group_domain_sid);
455 debug((
char *)
"%s| %s: INFO: Found %d Resource Group rids\n",
LogTime(),
PROGRAM, ResourceGroupCount);
458 size_t length = group_domain_sid_len + 4;
459 auto *st =
static_cast<char *
>(
xcalloc(length, 1));
461 memcpy((
void *)st, (
const void*)resource_group_domain_sid, group_domain_sid_len);
463 for (
int l=0; l < (
int)ResourceGroupCount; l++) {
465 memcpy((
void *)&st[group_domain_sid_len], (
const void*)&p[bpos], 4);
467 if (!pstrcat(ad_groups,
" group=")) {
468 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
475 char *b64buf =
static_cast<char *
>(
xcalloc(expectedSz, 1));
478 b64buf[expectedSz - 1] =
'\0';
479 if (!pstrcat(ad_groups,
reinterpret_cast<char*
>(b64buf))) {
480 debug((
char *)
"%s| %s: WARN: Too many groups ! size > %d : %s\n",
494 xfree(resource_group_domain_sid);
499get_ad_groups(
char *ad_groups, krb5_context context, krb5_pac pac)
502 RPC_UNICODE_STRING EffectiveName;
503 RPC_UNICODE_STRING FullName;
504 RPC_UNICODE_STRING LogonScript;
505 RPC_UNICODE_STRING ProfilePath;
506 RPC_UNICODE_STRING HomeDirectory;
507 RPC_UNICODE_STRING HomeDirectoryDrive;
508 RPC_UNICODE_STRING LogonServer;
509 RPC_UNICODE_STRING LogonDomainName;
510 uint32_t GroupCount=0;
512 uint32_t LogonDomainId=0;
514 uint32_t UserFlags=0;
515 uint32_t ExtraSids=0;
516 uint32_t ResourceGroupDomainSid=0;
517 uint32_t ResourceGroupCount=0;
518 uint32_t ResourceGroupIds=0;
523 debug((
char *)
"%s| %s: ERR: No space to store groups\n",
528 ad_data = (krb5_data *)
xcalloc(1,
sizeof(krb5_data));
530#define KERB_LOGON_INFO 1
531 ret = krb5_pac_get_buffer(context, pac, KERB_LOGON_INFO, ad_data);
535 p = (
unsigned char *)ad_data->data;
537 debug((
char *)
"%s| %s: INFO: Got PAC data of length %d\n",
557 getustr(&EffectiveName);
559 getustr(&LogonScript);
560 getustr(&ProfilePath);
561 getustr(&HomeDirectory);
562 getustr(&HomeDirectoryDrive);
569 GroupCount = get4byt();
570 GroupIds = get4byt();
571 UserFlags = get4byt();
574 getustr(&LogonServer);
575 getustr(&LogonDomainName);
576 LogonDomainId = get4byt();
586 SidCount = get4byt();
587 ExtraSids = get4byt();
589 ResourceGroupDomainSid = get4byt();
590 ResourceGroupCount = get4byt();
591 ResourceGroupIds = get4byt();
596 if (checkustr(&EffectiveName)<0)
598 if (checkustr(&FullName)<0)
600 if (checkustr(&LogonScript)<0)
602 if (checkustr(&ProfilePath)<0)
604 if (checkustr(&HomeDirectory)<0)
606 if (checkustr(&HomeDirectoryDrive)<0)
608 Rids = getgids(Rids,GroupIds,GroupCount);
609 if (checkustr(&LogonServer)<0)
611 if (checkustr(&LogonDomainName)<0)
613 ad_groups = getdomaingids(ad_groups,LogonDomainId,Rids,GroupCount);
616 if ((UserFlags&LOGON_EXTRA_SIDS) != 0) {
619 if ((ad_groups = getextrasids(ad_groups,ExtraSids,SidCount)) ==
nullptr)
623 if ((UserFlags&LOGON_RESOURCE_GROUPS) != 0 && ResourceGroupDomainSid && ResourceGroupIds && ResourceGroupCount) {
626 if (!get_resource_groups(ad_groups, ResourceGroupDomainSid, ResourceGroupIds, ResourceGroupCount))
630 debug((
char *)
"%s| %s: INFO: Read %d of %d bytes \n",
LogTime(),
PROGRAM, bpos, (
int)ad_data->length);
633 for ( l=0; l<(
int)GroupCount; l++) {
638 krb5_free_data(context, ad_data);
643 for ( l=0; l<(
int)GroupCount; l++) {
648 krb5_free_data(context, ad_data);
const char * LogTime(void)
void base64_encode_init(struct base64_encode_ctx *ctx)
size_t base64_encode_update(struct base64_encode_ctx *ctx, char *dst, size_t length, const uint8_t *src)
size_t base64_encode_final(struct base64_encode_ctx *ctx, char *dst)
#define base64_encode_len(length)
void debug(const char *format,...)
int check_k5_err(krb5_context context, const char *msg, krb5_error_code code)
void * xcalloc(size_t n, size_t sz)