static void dump_printer(TALLOC_CTX *mem_ctx, const char *key_name, unsigned char *data, size_t length) { enum ndr_err_code ndr_err; DATA_BLOB blob; char *s; struct ntprinting_printer r; printf("found printer: %s\n", key_name); blob = data_blob_const(data, length); ZERO_STRUCT(r); ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, (ndr_pull_flags_fn_t)ndr_pull_ntprinting_printer); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { d_fprintf(stderr, _("printer pull failed: %s\n"), ndr_errstr(ndr_err)); return; } s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r); if (s) { printf("%s\n", s); } }
static WERROR cmd_netlogon_dsr_getdcnameex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { WERROR result; NTSTATUS status; uint32_t flags = DS_RETURN_DNS_NAME; const char *server_name = cli->desthost; const char *domain_name; const char *site_name = NULL; struct GUID domain_guid = GUID_zero(); struct netr_DsRGetDCNameInfo *info = NULL; struct dcerpc_binding_handle *b = cli->binding_handle; if (argc < 2) { fprintf(stderr, "Usage: %s [domain_name] [domain_guid] " "[site_name] [flags]\n", argv[0]); return WERR_OK; } domain_name = argv[1]; if (argc >= 3) { if (!NT_STATUS_IS_OK(GUID_from_string(argv[2], &domain_guid))) { return WERR_NOMEM; } } if (argc >= 4) { site_name = argv[3]; } if (argc >= 5) { sscanf(argv[4], "%x", &flags); } debug_dsdcinfo_flags(1,flags); status = dcerpc_netr_DsRGetDCNameEx(b, mem_ctx, server_name, domain_name, &domain_guid, site_name, flags, &info, &result); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } if (!W_ERROR_IS_OK(result)) { return result; } d_printf("DsRGetDCNameEx gave %s\n", NDR_PRINT_STRUCT_STRING(mem_ctx, netr_DsRGetDCNameInfo, info)); return result; }
static int net_lookup_dsgetdcname(struct net_context *c, int argc, const char **argv) { NTSTATUS status; const char *domain_name = NULL; const char *site_name = NULL; uint32_t flags = 0; struct netr_DsRGetDCNameInfo *info = NULL; TALLOC_CTX *mem_ctx; char *s = NULL; if (argc < 1 || argc > 3) { d_printf("%s\n%s", _("Usage:"), _(" net lookup dsgetdcname " "<name> <flags> <sitename>\n")); return -1; } mem_ctx = talloc_init("net_lookup_dsgetdcname"); if (!mem_ctx) { return -1; } domain_name = argv[0]; if (argc >= 2) { sscanf(argv[1], "%x", &flags); } if (flags == 0) { flags = DS_DIRECTORY_SERVICE_REQUIRED; } if (argc == 3) { site_name = argv[2]; } if (!c->msg_ctx) { d_fprintf(stderr, _("Could not initialise message context. " "Try running as root\n")); return -1; } status = dsgetdcname(mem_ctx, c->msg_ctx, domain_name, NULL, site_name, flags, &info); if (!NT_STATUS_IS_OK(status)) { d_printf(_("failed with: %s\n"), nt_errstr(status)); TALLOC_FREE(mem_ctx); return -1; } s = NDR_PRINT_STRUCT_STRING(mem_ctx, netr_DsRGetDCNameInfo, info); printf("%s\n", s); TALLOC_FREE(s); TALLOC_FREE(mem_ctx); return 0; }
static int DoDumpCommand(int argc, char **argv, bool debugflag, char *exename) { ELOG_TDB *etdb; TALLOC_CTX *mem_ctx = talloc_tos(); const char *tdb_filename; uint32_t count = 1; if (argc > 2) { return -1; } tdb_filename = argv[0]; if (argc > 1) { count = atoi(argv[1]); } etdb = elog_open_tdb(argv[0], false, true); if (!etdb) { printf("can't open the eventlog TDB (%s)\n", argv[0]); return -1; } while (1) { struct eventlog_Record_tdb *r; char *s; r = evlog_pull_record_tdb(mem_ctx, etdb->tdb, count); if (!r) { break; } printf("displaying record: %d\n", count); s = NDR_PRINT_STRUCT_STRING(mem_ctx, eventlog_Record_tdb, r); if (s) { printf("%s\n", s); talloc_free(s); } count++; } elog_close_tdb(etdb, false); return 0; }
static WERROR cmd_netlogon_dsr_getdcnameex2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { WERROR result; NTSTATUS status; uint32_t flags = DS_RETURN_DNS_NAME; const char *server_name = cli->desthost; const char *domain_name = NULL; const char *client_account = NULL; uint32_t mask = 0; const char *site_name = NULL; struct GUID domain_guid = GUID_zero(); struct netr_DsRGetDCNameInfo *info = NULL; struct dcerpc_binding_handle *b = cli->binding_handle; if (argc < 2) { fprintf(stderr, "Usage: %s [client_account] [acb_mask] " "[domain_name] [domain_guid] [site_name] " "[flags]\n", argv[0]); return WERR_OK; } if (argc >= 2) { client_account = argv[1]; } if (argc >= 3) { mask = atoi(argv[2]); } if (argc >= 4) { domain_name = argv[3]; } if (argc >= 5) { if (!NT_STATUS_IS_OK(GUID_from_string(argv[4], &domain_guid))) { return WERR_NOT_ENOUGH_MEMORY; } } if (argc >= 6) { site_name = argv[5]; } if (argc >= 7) { sscanf(argv[6], "%x", &flags); } status = dcerpc_netr_DsRGetDCNameEx2(b, mem_ctx, server_name, client_account, mask, domain_name, &domain_guid, site_name, flags, &info, &result); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } if (!W_ERROR_IS_OK(result)) { return result; } d_printf("DsRGetDCNameEx2 gave %s\n", NDR_PRINT_STRUCT_STRING(mem_ctx, netr_DsRGetDCNameInfo, info)); return result; }
static WERROR cmd_netlogon_dsr_getdcname(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS result; WERROR werr = WERR_OK; uint32_t flags = DS_RETURN_DNS_NAME; const char *server_name = cli->desthost; const char *domain_name; struct GUID domain_guid = GUID_zero(); struct GUID site_guid = GUID_zero(); struct netr_DsRGetDCNameInfo *info = NULL; struct dcerpc_binding_handle *b = cli->binding_handle; if (argc < 2) { fprintf(stderr, "Usage: %s [domain_name] [domain_guid] " "[site_guid] [flags]\n", argv[0]); return WERR_OK; } if (argc >= 2) domain_name = argv[1]; if (argc >= 3) { if (!NT_STATUS_IS_OK(GUID_from_string(argv[2], &domain_guid))) { return WERR_NOT_ENOUGH_MEMORY; } } if (argc >= 4) { if (!NT_STATUS_IS_OK(GUID_from_string(argv[3], &site_guid))) { return WERR_NOT_ENOUGH_MEMORY; } } if (argc >= 5) sscanf(argv[4], "%x", &flags); result = dcerpc_netr_DsRGetDCName(b, mem_ctx, server_name, domain_name, &domain_guid, &site_guid, flags, &info, &werr); if (!NT_STATUS_IS_OK(result)) { return ntstatus_to_werror(result); } if (W_ERROR_IS_OK(werr)) { d_printf("DsGetDcName gave: %s\n", NDR_PRINT_STRUCT_STRING(mem_ctx, netr_DsRGetDCNameInfo, info)); return WERR_OK; } printf("rpccli_netlogon_dsr_getdcname returned %s\n", win_errstr(werr)); return werr; }
/** * @brief Decode a blob containing a NDR envoded PAC structure * * @param mem_ctx - The memory context * @param pac_data_blob - The data blob containing the NDR encoded data * @param context - The Kerberos Context * @param service_keyblock - The Service Key used to verify the checksum * @param client_principal - The client principal * @param tgs_authtime - The ticket timestamp * @param pac_data_out - [out] The decoded PAC * * @return - A NTSTATUS error code */ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, DATA_BLOB pac_data_blob, krb5_context context, const krb5_keyblock *krbtgt_keyblock, const krb5_keyblock *service_keyblock, krb5_const_principal client_principal, time_t tgs_authtime, struct PAC_DATA **pac_data_out) { NTSTATUS status; enum ndr_err_code ndr_err; krb5_error_code ret; DATA_BLOB modified_pac_blob; NTTIME tgs_authtime_nttime; krb5_principal client_principal_pac = NULL; int i; struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL; struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL; struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL; struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL; struct PAC_LOGON_NAME *logon_name = NULL; struct PAC_LOGON_INFO *logon_info = NULL; struct PAC_DATA *pac_data = NULL; struct PAC_DATA_RAW *pac_data_raw = NULL; DATA_BLOB *srv_sig_blob = NULL; DATA_BLOB *kdc_sig_blob = NULL; bool bool_ret; *pac_data_out = NULL; pac_data = talloc(mem_ctx, struct PAC_DATA); pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW); kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA); srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA); if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) { return NT_STATUS_NO_MEMORY; } ndr_err = ndr_pull_struct_blob(&pac_data_blob, pac_data, pac_data, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't parse the PAC: %s\n", nt_errstr(status))); return status; } if (pac_data->num_buffers < 4) { /* we need logon_ingo, service_key and kdc_key */ DEBUG(0,("less than 4 PAC buffers\n")); return NT_STATUS_INVALID_PARAMETER; } ndr_err = ndr_pull_struct_blob( &pac_data_blob, pac_data_raw, pac_data_raw, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't parse the PAC: %s\n", nt_errstr(status))); return status; } if (pac_data_raw->num_buffers < 4) { /* we need logon_ingo, service_key and kdc_key */ DEBUG(0,("less than 4 PAC buffers\n")); return NT_STATUS_INVALID_PARAMETER; } if (pac_data->num_buffers != pac_data_raw->num_buffers) { /* we need logon_ingo, service_key and kdc_key */ DEBUG(0, ("misparse! PAC_DATA has %d buffers while " "PAC_DATA_RAW has %d\n", pac_data->num_buffers, pac_data_raw->num_buffers)); return NT_STATUS_INVALID_PARAMETER; } for (i=0; i < pac_data->num_buffers; i++) { struct PAC_BUFFER *data_buf = &pac_data->buffers[i]; struct PAC_BUFFER_RAW *raw_buf = &pac_data_raw->buffers[i]; if (data_buf->type != raw_buf->type) { DEBUG(0, ("misparse! PAC_DATA buffer %d has type " "%d while PAC_DATA_RAW has %d\n", i, data_buf->type, raw_buf->type)); return NT_STATUS_INVALID_PARAMETER; } switch (data_buf->type) { case PAC_TYPE_LOGON_INFO: if (!data_buf->info) { break; } logon_info = data_buf->info->logon_info.info; break; case PAC_TYPE_SRV_CHECKSUM: if (!data_buf->info) { break; } srv_sig_ptr = &data_buf->info->srv_cksum; srv_sig_blob = &raw_buf->info->remaining; break; case PAC_TYPE_KDC_CHECKSUM: if (!data_buf->info) { break; } kdc_sig_ptr = &data_buf->info->kdc_cksum; kdc_sig_blob = &raw_buf->info->remaining; break; case PAC_TYPE_LOGON_NAME: logon_name = &data_buf->info->logon_name; break; default: break; } } if (!logon_info) { DEBUG(0,("PAC no logon_info\n")); return NT_STATUS_INVALID_PARAMETER; } if (!logon_name) { DEBUG(0,("PAC no logon_name\n")); return NT_STATUS_INVALID_PARAMETER; } if (!srv_sig_ptr || !srv_sig_blob) { DEBUG(0,("PAC no srv_key\n")); return NT_STATUS_INVALID_PARAMETER; } if (!kdc_sig_ptr || !kdc_sig_blob) { DEBUG(0,("PAC no kdc_key\n")); return NT_STATUS_INVALID_PARAMETER; } /* Find and zero out the signatures, * as required by the signing algorithm */ /* We find the data blobs above, * now we parse them to get at the exact portion we should zero */ ndr_err = ndr_pull_struct_blob( kdc_sig_blob, kdc_sig_wipe, kdc_sig_wipe, (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't parse the KDC signature: %s\n", nt_errstr(status))); return status; } ndr_err = ndr_pull_struct_blob( srv_sig_blob, srv_sig_wipe, srv_sig_wipe, (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't parse the SRV signature: %s\n", nt_errstr(status))); return status; } /* Now zero the decoded structure */ memset(kdc_sig_wipe->signature.data, '\0', kdc_sig_wipe->signature.length); memset(srv_sig_wipe->signature.data, '\0', srv_sig_wipe->signature.length); /* and reencode, back into the same place it came from */ ndr_err = ndr_push_struct_blob( kdc_sig_blob, pac_data_raw, kdc_sig_wipe, (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't repack the KDC signature: %s\n", nt_errstr(status))); return status; } ndr_err = ndr_push_struct_blob( srv_sig_blob, pac_data_raw, srv_sig_wipe, (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't repack the SRV signature: %s\n", nt_errstr(status))); return status; } /* push out the whole structure, but now with zero'ed signatures */ ndr_err = ndr_push_struct_blob( &modified_pac_blob, pac_data_raw, pac_data_raw, (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't repack the RAW PAC: %s\n", nt_errstr(status))); return status; } if (service_keyblock) { /* verify by service_key */ ret = check_pac_checksum(mem_ctx, modified_pac_blob, srv_sig_ptr, context, service_keyblock); if (ret) { DEBUG(1, ("PAC Decode: Failed to verify the service " "signature: %s\n", error_message(ret))); return NT_STATUS_ACCESS_DENIED; } if (krbtgt_keyblock) { /* verify the service key checksum by krbtgt_key */ ret = check_pac_checksum(mem_ctx, srv_sig_ptr->signature, kdc_sig_ptr, context, krbtgt_keyblock); if (ret) { DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n", smb_get_krb5_error_message(context, ret, mem_ctx))); return NT_STATUS_ACCESS_DENIED; } } } if (tgs_authtime) { /* Convert to NT time, so as not to loose accuracy in comparison */ unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime); if (tgs_authtime_nttime != logon_name->logon_time) { DEBUG(2, ("PAC Decode: " "Logon time mismatch between ticket and PAC!\n")); DEBUG(2, ("PAC Decode: PAC: %s\n", nt_time_string(mem_ctx, logon_name->logon_time))); DEBUG(2, ("PAC Decode: Ticket: %s\n", nt_time_string(mem_ctx, tgs_authtime_nttime))); return NT_STATUS_ACCESS_DENIED; } } if (client_principal) { ret = smb_krb5_parse_name_norealm(context, logon_name->account_name, &client_principal_pac); if (ret) { DEBUG(2, ("Could not parse name from PAC: [%s]:%s\n", logon_name->account_name, error_message(ret))); return NT_STATUS_INVALID_PARAMETER; } bool_ret = smb_krb5_principal_compare_any_realm(context, client_principal, client_principal_pac); krb5_free_principal(context, client_principal_pac); if (!bool_ret) { DEBUG(2, ("Name in PAC [%s] does not match principal name " "in ticket\n", logon_name->account_name)); return NT_STATUS_ACCESS_DENIED; } } DEBUG(3,("Found account name from PAC: %s [%s]\n", logon_info->info3.base.account_name.string, logon_info->info3.base.full_name.string)); DEBUG(10,("Successfully validated Kerberos PAC\n")); if (DEBUGLEVEL >= 10) { const char *s; s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_DATA, pac_data); if (s) { DEBUGADD(10,("%s\n", s)); } } *pac_data_out = pac_data; return NT_STATUS_OK; }