📄 authdata.c
字号:
}static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_BUFFER *hdr, prs_struct *ps, int depth){ if (NULL == hdr) return False; prs_debug(ps, depth, desc, "pac_io_pac_info_hdr_ctr"); depth++; if (!prs_align(ps)) return False; if (hdr->offset != prs_offset(ps)) { DEBUG(5,("offset in header(x%x) and data(x%x) do not match, correcting\n", hdr->offset, prs_offset(ps))); prs_set_offset(ps, hdr->offset); } if (UNMARSHALLING(ps) && hdr->size > 0) { hdr->ctr = PRS_ALLOC_MEM(ps, PAC_INFO_CTR, 1); if (!hdr->ctr) { DEBUG(3, ("No memory available\n")); return False; } } switch(hdr->type) { case PAC_TYPE_LOGON_INFO: DEBUG(5, ("PAC_TYPE_LOGON_INFO\n")); if (UNMARSHALLING(ps)) hdr->ctr->pac.logon_info = PRS_ALLOC_MEM(ps, PAC_LOGON_INFO, 1); if (!hdr->ctr->pac.logon_info) { DEBUG(3, ("No memory available\n")); return False; } if (!pac_io_pac_logon_info(desc, hdr->ctr->pac.logon_info, ps, depth)) return False; break; case PAC_TYPE_SERVER_CHECKSUM: DEBUG(5, ("PAC_TYPE_SERVER_CHECKSUM\n")); if (UNMARSHALLING(ps)) hdr->ctr->pac.srv_cksum = PRS_ALLOC_MEM(ps, PAC_SIGNATURE_DATA, 1); if (!hdr->ctr->pac.srv_cksum) { DEBUG(3, ("No memory available\n")); return False; } if (!pac_io_pac_signature_data(desc, hdr->ctr->pac.srv_cksum, hdr->size, ps, depth)) return False; break; case PAC_TYPE_PRIVSVR_CHECKSUM: DEBUG(5, ("PAC_TYPE_PRIVSVR_CHECKSUM\n")); if (UNMARSHALLING(ps)) hdr->ctr->pac.privsrv_cksum = PRS_ALLOC_MEM(ps, PAC_SIGNATURE_DATA, 1); if (!hdr->ctr->pac.privsrv_cksum) { DEBUG(3, ("No memory available\n")); return False; } if (!pac_io_pac_signature_data(desc, hdr->ctr->pac.privsrv_cksum, hdr->size, ps, depth)) return False; break; case PAC_TYPE_LOGON_NAME: DEBUG(5, ("PAC_TYPE_LOGON_NAME\n")); if (UNMARSHALLING(ps)) hdr->ctr->pac.logon_name = PRS_ALLOC_MEM(ps, PAC_LOGON_NAME, 1); if (!hdr->ctr->pac.logon_name) { DEBUG(3, ("No memory available\n")); return False; } if (!pac_io_logon_name(desc, hdr->ctr->pac.logon_name, ps, depth)) return False; break; default: /* dont' know, so we need to skip it */ DEBUG(3, ("unknown PAC type %d\n", hdr->type)); prs_set_offset(ps, prs_offset(ps) + hdr->size); }#if 0 /* obscure pad */ if (!prs_uint32("pad", ps, depth, &hdr->pad)) return False;#endif return True;}static BOOL pac_io_pac_info_hdr(const char *desc, PAC_BUFFER *hdr, prs_struct *ps, int depth){ if (NULL == hdr) return False; prs_debug(ps, depth, desc, "pac_io_pac_info_hdr"); depth++; if (!prs_align(ps)) return False; if (!prs_uint32("type", ps, depth, &hdr->type)) return False; if (!prs_uint32("size", ps, depth, &hdr->size)) return False; if (!prs_uint32("offset", ps, depth, &hdr->offset)) return False; if (!prs_uint32("offsethi", ps, depth, &hdr->offsethi)) return False; return True;}static BOOL pac_io_pac_data(const char *desc, PAC_DATA *data, prs_struct *ps, int depth){ int i; if (NULL == data) return False; prs_debug(ps, depth, desc, "pac_io_pac_data"); depth++; if (!prs_align(ps)) return False; if (!prs_uint32("num_buffers", ps, depth, &data->num_buffers)) return False; if (!prs_uint32("version", ps, depth, &data->version)) return False; if (UNMARSHALLING(ps) && data->num_buffers > 0) { if ((data->pac_buffer = PRS_ALLOC_MEM(ps, PAC_BUFFER, data->num_buffers)) == NULL) { return False; } } for (i=0; i<data->num_buffers; i++) { if (!pac_io_pac_info_hdr(desc, &data->pac_buffer[i], ps, depth)) return False; } for (i=0; i<data->num_buffers; i++) { if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_buffer[i], ps, depth)) return False; } return True;}static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx, DATA_BLOB pac_data, PAC_SIGNATURE_DATA *sig, krb5_context context, krb5_keyblock *keyblock){ krb5_error_code ret; krb5_checksum cksum; krb5_keyusage usage = 0; smb_krb5_checksum_from_pac_sig(&cksum, sig);#ifdef HAVE_KRB5_KU_OTHER_CKSUM /* Heimdal */ usage = KRB5_KU_OTHER_CKSUM;#elif defined(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM) /* MIT */ usage = KRB5_KEYUSAGE_APP_DATA_CKSUM;#else#error UNKNOWN_KRB5_KEYUSAGE#endif ret = smb_krb5_verify_checksum(context, keyblock, usage, &cksum, pac_data.data, pac_data.length); if (ret) { DEBUG(2,("check_pac_checksum: PAC Verification failed: %s (%d)\n", error_message(ret), ret)); return NT_STATUS_ACCESS_DENIED; } return NT_STATUS_OK;}static NTSTATUS parse_pac_data(TALLOC_CTX *mem_ctx, DATA_BLOB *pac_data_blob, PAC_DATA *pac_data){ prs_struct ps; PAC_DATA *my_pac; if (!prs_init(&ps, pac_data_blob->length, mem_ctx, UNMARSHALL)) return NT_STATUS_NO_MEMORY; if (!prs_copy_data_in(&ps, (char *)pac_data_blob->data, pac_data_blob->length)) return NT_STATUS_INVALID_PARAMETER; prs_set_offset(&ps, 0); my_pac = TALLOC_ZERO_P(mem_ctx, PAC_DATA); if (!pac_io_pac_data("pac data", my_pac, &ps, 0)) return NT_STATUS_INVALID_PARAMETER; prs_mem_free(&ps); *pac_data = *my_pac; return NT_STATUS_OK;}/* just for debugging, will be removed later - Guenther */char *pac_group_attr_string(uint32 attr){ fstring name = ""; if (!attr) return NULL; if (attr & SE_GROUP_MANDATORY) fstrcat(name, "SE_GROUP_MANDATORY "); if (attr & SE_GROUP_ENABLED_BY_DEFAULT) fstrcat(name, "SE_GROUP_ENABLED_BY_DEFAULT "); if (attr & SE_GROUP_ENABLED) fstrcat(name, "SE_GROUP_ENABLED "); if (attr & SE_GROUP_OWNER) fstrcat(name, "SE_GROUP_OWNER "); if (attr & SE_GROUP_USE_FOR_DENY_ONLY) fstrcat(name, "SE_GROUP_USE_FOR_DENY_ONLY "); if (attr & SE_GROUP_LOGON_ID) fstrcat(name, "SE_GROUP_LOGON_ID "); if (attr & SE_GROUP_RESOURCE) fstrcat(name, "SE_GROUP_RESOURCE "); return SMB_STRDUP(name);}/* just for debugging, will be removed later - Guenther */static void dump_pac_logon_info(PAC_LOGON_INFO *logon_info) { DOM_SID dom_sid, res_group_dom_sid; int i; char *attr_string; uint32 user_flgs = logon_info->info3.user_flgs; if (logon_info->info3.ptr_res_group_dom_sid) { sid_copy(&res_group_dom_sid, &logon_info->res_group_dom_sid.sid); } sid_copy(&dom_sid, &logon_info->info3.dom_sid.sid); DEBUG(10,("The PAC:\n")); DEBUGADD(10,("\tUser Flags: 0x%x (%d)\n", user_flgs, user_flgs)); if (user_flgs & LOGON_EXTRA_SIDS) DEBUGADD(10,("\tUser Flags: LOGON_EXTRA_SIDS 0x%x (%d)\n", LOGON_EXTRA_SIDS, LOGON_EXTRA_SIDS)); if (user_flgs & LOGON_RESOURCE_GROUPS) DEBUGADD(10,("\tUser Flags: LOGON_RESOURCE_GROUPS 0x%x (%d)\n", LOGON_RESOURCE_GROUPS, LOGON_RESOURCE_GROUPS)); DEBUGADD(10,("\tUser SID: %s-%d\n", sid_string_static(&dom_sid), logon_info->info3.user_rid)); DEBUGADD(10,("\tGroup SID: %s-%d\n", sid_string_static(&dom_sid), logon_info->info3.group_rid)); DEBUGADD(10,("\tGroup Membership (Global and Universal Groups of own domain):\n")); for (i = 0; i < logon_info->info3.num_groups; i++) { attr_string = pac_group_attr_string(logon_info->info3.gids[i].attr); DEBUGADD(10,("\t\t%d: sid: %s-%d\n\t\t attr: 0x%x == %s\n", i, sid_string_static(&dom_sid), logon_info->info3.gids[i].g_rid, logon_info->info3.gids[i].attr, attr_string)); SAFE_FREE(attr_string); } DEBUGADD(10,("\tGroup Membership (Domain Local Groups and Groups from Trusted Domains):\n")); for (i = 0; i < logon_info->info3.num_other_sids; i++) { attr_string = pac_group_attr_string(logon_info->info3.other_sids_attrib[i]); DEBUGADD(10,("\t\t%d: sid: %s\n\t\t attr: 0x%x == %s\n", i, sid_string_static(&logon_info->info3.other_sids[i].sid), logon_info->info3.other_sids_attrib[i], attr_string)); SAFE_FREE(attr_string); } DEBUGADD(10,("\tGroup Membership (Ressource Groups (SID History ?)):\n")); for (i = 0; i < logon_info->info3.res_group_count; i++) { attr_string = pac_group_attr_string(logon_info->res_groups.group_membership[i].attrs); DEBUGADD(10,("\t\t%d: sid: %s-%d\n\t\t attr: 0x%x == %s\n", i, sid_string_static(&res_group_dom_sid), logon_info->res_groups.group_membership[i].rid, logon_info->res_groups.group_membership[i].attrs, attr_string)); SAFE_FREE(attr_string); }} NTSTATUS decode_pac_data(TALLOC_CTX *mem_ctx, DATA_BLOB *pac_data_blob, krb5_context context, krb5_keyblock *service_keyblock, krb5_const_principal client_principal, time_t tgs_authtime, PAC_DATA **pac_data) { DATA_BLOB modified_pac_blob; PAC_DATA *my_pac; NTSTATUS nt_status; krb5_error_code ret; PAC_SIGNATURE_DATA *srv_sig = NULL; PAC_SIGNATURE_DATA *kdc_sig = NULL; PAC_LOGON_NAME *logon_name = NULL; PAC_LOGON_INFO *logon_info = NULL; krb5_principal client_principal_pac = NULL; NTTIME tgs_authtime_nttime; int i, srv_sig_pos = 0, kdc_sig_pos = 0; fstring username; *pac_data = NULL; my_pac = talloc(mem_ctx, PAC_DATA); if (!my_pac) { return NT_STATUS_NO_MEMORY; } nt_status = parse_pac_data(mem_ctx, pac_data_blob, my_pac); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("decode_pac_data: failed to parse PAC\n")); return nt_status; } modified_pac_blob = data_blob_talloc(mem_ctx, pac_data_blob->data, pac_data_blob->length); if (my_pac->num_buffers < 4) { nt_status = NT_STATUS_INVALID_PARAMETER; goto out; } /* store signatures */ for (i=0; i < my_pac->num_buffers; i++) { switch (my_pac->pac_buffer[i].type) { case PAC_TYPE_SERVER_CHECKSUM: if (!my_pac->pac_buffer[i].ctr->pac.srv_cksum) { break; } srv_sig = my_pac->pac_buffer[i].ctr->pac.srv_cksum; /* get position of signature buffer */ srv_sig_pos = my_pac->pac_buffer[i].offset; srv_sig_pos += sizeof(uint32); break; case PAC_TYPE_PRIVSVR_CHECKSUM: if (!my_pac->pac_buffer[i].ctr->pac.privsrv_cksum) { break; } kdc_sig = my_pac->pac_buffer[i].ctr->pac.privsrv_cksum; /* get position of signature buffer */ kdc_sig_pos = my_pac->pac_buffer[i].offset; kdc_sig_pos += sizeof(uint32); break; case PAC_TYPE_LOGON_NAME: if (!my_pac->pac_buffer[i].ctr->pac.logon_name) { break; } logon_name = my_pac->pac_buffer[i].ctr->pac.logon_name; break; case PAC_TYPE_LOGON_INFO: if (!my_pac->pac_buffer[i].ctr->pac.logon_info) { break; } logon_info = my_pac->pac_buffer[i].ctr->pac.logon_info; break; } } if (!srv_sig || !kdc_sig || !logon_name || !logon_info) { nt_status = NT_STATUS_INVALID_PARAMETER; goto out; } /* zero PAC_SIGNATURE_DATA signature buffer */ memset(&modified_pac_blob.data[srv_sig_pos], '\0', srv_sig->signature.buf_len); memset(&modified_pac_blob.data[kdc_sig_pos], '\0', kdc_sig->signature.buf_len); /* check server signature */ nt_status = check_pac_checksum(mem_ctx, modified_pac_blob, srv_sig, context, service_keyblock); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("decode_pac_data: failed to verify PAC server signature\n")); goto out; } /* Convert to NT time, so as not to loose accuracy in comparison */ unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime); if (!nt_time_equals(&tgs_authtime_nttime, &logon_name->logon_time)) { DEBUG(2,("decode_pac_data: Logon time mismatch between ticket and PAC!\n")); DEBUGADD(2, ("decode_pac_data: PAC: %s\n", http_timestring(nt_time_to_unix(&logon_name->logon_time)))); DEBUGADD(2, ("decode_pac_data: Ticket: %s\n", http_timestring(nt_time_to_unix(&tgs_authtime_nttime)))); nt_status = NT_STATUS_ACCESS_DENIED; goto out; } if (!logon_name->len) { DEBUG(2,("decode_pac_data: No Logon Name available\n")); nt_status = NT_STATUS_INVALID_PARAMETER; goto out; } rpcstr_pull(username, logon_name->username, sizeof(username), logon_name->len, 0); ret = smb_krb5_parse_name_norealm(context, username, &client_principal_pac); if (ret) { DEBUG(2,("decode_pac_data: Could not parse name from incoming PAC: [%s]: %s\n", username, error_message(ret))); nt_status = NT_STATUS_INVALID_PARAMETER; goto out; } if (!smb_krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) { DEBUG(2,("decode_pac_data: Name in PAC [%s] does not match principal name in ticket\n", username)); nt_status = NT_STATUS_ACCESS_DENIED; goto out; } DEBUG(10,("Successfully validated Kerberos PAC\n")); dump_pac_logon_info(logon_info); *pac_data = my_pac; nt_status = NT_STATUS_OK;out: if (client_principal_pac) { krb5_free_principal(context, client_principal_pac); } return nt_status;} PAC_LOGON_INFO *get_logon_info_from_pac(PAC_DATA *pac_data) { PAC_LOGON_INFO *logon_info = NULL; int i; for (i=0; i < pac_data->num_buffers; i++) { if (pac_data->pac_buffer[i].type != PAC_TYPE_LOGON_INFO) continue; logon_info = pac_data->pac_buffer[i].ctr->pac.logon_info; break; } return logon_info;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -