WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, uint32_t firstjob, uint32_t numjobs, uint32_t level, uint32_t offered, uint32_t *count, union spoolss_JobInfo **info) { NTSTATUS status; WERROR werror; uint32_t needed; DATA_BLOB buffer; struct dcerpc_binding_handle *b = cli->binding_handle; if (offered > 0) { buffer = data_blob_talloc_zero(mem_ctx, offered); W_ERROR_HAVE_NO_MEMORY(buffer.data); } status = dcerpc_spoolss_EnumJobs(b, mem_ctx, handle, firstjob, numjobs, level, (offered > 0) ? &buffer : NULL, offered, count, info, &needed, &werror); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { offered = needed; buffer = data_blob_talloc_zero(mem_ctx, needed); W_ERROR_HAVE_NO_MEMORY(buffer.data); status = dcerpc_spoolss_EnumJobs(b, mem_ctx, handle, firstjob, numjobs, level, (offered > 0) ? &buffer : NULL, offered, count, info, &needed, &werror); } if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } return werror; }
WERROR rpccli_spoolss_getprinterdriver2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, const char *architecture, uint32_t level, uint32_t offered, uint32_t client_major_version, uint32_t client_minor_version, union spoolss_DriverInfo *info, uint32_t *server_major_version, uint32_t *server_minor_version) { NTSTATUS status; WERROR werror; uint32_t needed; DATA_BLOB buffer; if (offered > 0) { buffer = data_blob_talloc_zero(mem_ctx, offered); W_ERROR_HAVE_NO_MEMORY(buffer.data); } status = rpccli_spoolss_GetPrinterDriver2(cli, mem_ctx, handle, architecture, level, (offered > 0) ? &buffer : NULL, offered, client_major_version, client_minor_version, info, &needed, server_major_version, server_minor_version, &werror); if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { offered = needed; buffer = data_blob_talloc_zero(mem_ctx, needed); W_ERROR_HAVE_NO_MEMORY(buffer.data); status = rpccli_spoolss_GetPrinterDriver2(cli, mem_ctx, handle, architecture, level, &buffer, offered, client_major_version, client_minor_version, info, &needed, server_major_version, server_minor_version, &werror); } return werror; }
WERROR rpccli_spoolss_enumprinterdrivers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server, const char *environment, uint32_t level, uint32_t offered, uint32_t *count, union spoolss_DriverInfo **info) { NTSTATUS status; WERROR werror; uint32_t needed; DATA_BLOB buffer; struct dcerpc_binding_handle *b = cli->binding_handle; if (offered > 0) { buffer = data_blob_talloc_zero(mem_ctx, offered); W_ERROR_HAVE_NO_MEMORY(buffer.data); } status = dcerpc_spoolss_EnumPrinterDrivers(b, mem_ctx, server, environment, level, (offered > 0) ? &buffer : NULL, offered, count, info, &needed, &werror); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { offered = needed; buffer = data_blob_talloc_zero(mem_ctx, needed); W_ERROR_HAVE_NO_MEMORY(buffer.data); status = dcerpc_spoolss_EnumPrinterDrivers(b, mem_ctx, server, environment, level, (offered > 0) ? &buffer : NULL, offered, count, info, &needed, &werror); } if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } return werror; }
WERROR rpccli_spoolss_enumprinters(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32_t flags, const char *server, uint32_t level, uint32_t offered, uint32_t *count, union spoolss_PrinterInfo **info) { NTSTATUS status; WERROR werror; uint32_t needed; DATA_BLOB buffer; if (offered > 0) { buffer = data_blob_talloc_zero(mem_ctx, offered); W_ERROR_HAVE_NO_MEMORY(buffer.data); } status = rpccli_spoolss_EnumPrinters(cli, mem_ctx, flags, server, level, (offered > 0) ? &buffer : NULL, offered, count, info, &needed, &werror); if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { offered = needed; buffer = data_blob_talloc_zero(mem_ctx, needed); W_ERROR_HAVE_NO_MEMORY(buffer.data); status = rpccli_spoolss_EnumPrinters(cli, mem_ctx, flags, server, level, (offered > 0) ? &buffer : NULL, offered, count, info, &needed, &werror); } return werror; }
NTSTATUS dcerpc_winreg_set_dword(TALLOC_CTX *mem_ctx, struct dcerpc_binding_handle *h, struct policy_handle *key_handle, const char *value, uint32_t data, WERROR *pwerr) { struct winreg_String wvalue; DATA_BLOB blob; WERROR result = WERR_OK; NTSTATUS status; ZERO_STRUCT(wvalue); wvalue.name = value; blob = data_blob_talloc_zero(mem_ctx, 4); SIVAL(blob.data, 0, data); status = dcerpc_winreg_SetValue(h, mem_ctx, key_handle, wvalue, REG_DWORD, blob.data, blob.length, &result); if (!NT_STATUS_IS_OK(status)) { return status; } if (!W_ERROR_IS_OK(result)) { *pwerr = result; } return status; }
static bool test_GetPrinterDriver2(struct torture_context *tctx, struct dcerpc_binding_handle *b, struct test_spoolss_win_context *ctx, struct policy_handle *handle) { NTSTATUS status; struct spoolss_GetPrinterDriver2 gpd2; DATA_BLOB blob = data_blob_talloc_zero(tctx, 87424); uint32_t needed; uint32_t server_major_version; uint32_t server_minor_version; torture_comment(tctx, "Testing GetPrinterDriver2\n"); gpd2.in.handle = handle; gpd2.in.architecture = "Windows NT x86"; gpd2.in.level = 101; gpd2.in.buffer = &blob; gpd2.in.offered = 87424; gpd2.in.client_major_version = 3; gpd2.in.client_minor_version = 0; gpd2.out.needed = &needed; gpd2.out.server_major_version = &server_major_version; gpd2.out.server_minor_version = &server_minor_version; status = dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &gpd2); torture_assert_ntstatus_ok(tctx, status, "GetPrinterDriver2 failed"); if (ctx->printer_has_driver) { torture_assert_werr_ok(tctx, gpd2.out.result, "GetPrinterDriver2 failed."); } return true; }
WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, uint32_t job_id, uint32_t level, uint32_t offered, union spoolss_JobInfo *info) { NTSTATUS status; WERROR werror; uint32_t needed; DATA_BLOB buffer; if (offered > 0) { buffer = data_blob_talloc_zero(mem_ctx, offered); W_ERROR_HAVE_NO_MEMORY(buffer.data); } status = rpccli_spoolss_GetJob(cli, mem_ctx, handle, job_id, level, (offered > 0) ? &buffer : NULL, offered, info, &needed, &werror); if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { offered = needed; buffer = data_blob_talloc_zero(mem_ctx, needed); W_ERROR_HAVE_NO_MEMORY(buffer.data); status = rpccli_spoolss_GetJob(cli, mem_ctx, handle, job_id, level, &buffer, offered, info, &needed, &werror); } return werror; }
/* set password via encrypted NT and LM hash buffers */ NTSTATUS samr_set_password_buffers(struct dcesrv_call_state *dce_call, struct ldb_context *sam_ctx, struct ldb_dn *account_dn, struct ldb_dn *domain_dn, TALLOC_CTX *mem_ctx, const uint8_t *lm_pwd_hash, const uint8_t *nt_pwd_hash) { struct samr_Password *d_lm_pwd_hash = NULL, *d_nt_pwd_hash = NULL; DATA_BLOB session_key = data_blob(NULL, 0); DATA_BLOB in, out; NTSTATUS nt_status = NT_STATUS_OK; nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } if (lm_pwd_hash != NULL) { in = data_blob_const(lm_pwd_hash, 16); out = data_blob_talloc_zero(mem_ctx, 16); sess_crypt_blob(&out, &in, &session_key, false); d_lm_pwd_hash = (struct samr_Password *) out.data; } if (nt_pwd_hash != NULL) { in = data_blob_const(nt_pwd_hash, 16); out = data_blob_talloc_zero(mem_ctx, 16); sess_crypt_blob(&out, &in, &session_key, false); d_nt_pwd_hash = (struct samr_Password *) out.data; } if ((d_lm_pwd_hash != NULL) || (d_nt_pwd_hash != NULL)) { nt_status = samdb_set_password(sam_ctx, mem_ctx, account_dn, domain_dn, NULL, d_lm_pwd_hash, d_nt_pwd_hash, NULL, NULL, /* this is a password set */ NULL, NULL); } return nt_status; }
static bool test_zero(struct torture_context *tctx) { int i; DATA_BLOB z = data_blob_talloc_zero(tctx, 4); torture_assert_int_equal(tctx, z.length, 4, "length"); for (i = 0; i < z.length; i++) torture_assert_int_equal(tctx, z.data[i], 0, "contents"); data_blob_free(&z); return true; }
static bool test_EnumPrinters_findone(struct torture_context *tctx, struct dcerpc_pipe *p, const char **printername) { struct spoolss_EnumPrinters r; uint32_t count; union spoolss_PrinterInfo *info; uint32_t needed; int i; struct dcerpc_binding_handle *b = p->binding_handle; *printername = NULL; r.in.flags = PRINTER_ENUM_LOCAL; r.in.server = NULL; r.in.level = 1; r.in.buffer = NULL; r.in.offered = 0; r.out.count = &count; r.out.info = &info; r.out.needed = &needed; torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &r), "failed to enum printers"); if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) { DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); r.in.buffer = &blob; r.in.offered = needed; torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &r), "failed to enum printers"); } torture_assert_werr_ok(tctx, r.out.result, "failed to enum printers"); for (i=0; i < count; i++) { if (count > 1 && strequal(info[i].info1.name, "Microsoft XPS Document Writer")) { continue; } torture_comment(tctx, "testing printer: %s\n", info[i].info1.name); *printername = talloc_strdup(tctx, info[i].info1.name); break; } return true; }
static bool test_GetPrinter(struct torture_context *tctx, struct dcerpc_binding_handle *b, struct policy_handle *handle, struct test_spoolss_win_context *ctx, uint32_t level, uint32_t initial_blob_size) { NTSTATUS status; struct spoolss_GetPrinter gp; DATA_BLOB blob = data_blob_talloc_zero(ctx, initial_blob_size); uint32_t needed; torture_comment(tctx, "Test GetPrinter level %d\n", level); gp.in.handle = handle; gp.in.level = level; gp.in.buffer = (initial_blob_size == 0)?NULL:&blob; gp.in.offered = initial_blob_size; gp.out.needed = &needed; status = dcerpc_spoolss_GetPrinter_r(b, tctx, &gp); torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed"); if (W_ERROR_EQUAL(gp.out.result, WERR_INSUFFICIENT_BUFFER)) { blob = data_blob_talloc_zero(ctx, needed); gp.in.buffer = &blob; gp.in.offered = needed; status = dcerpc_spoolss_GetPrinter_r(b, tctx, &gp); torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed"); } torture_assert_werr_ok(tctx, gp.out.result, "GetPrinter failed"); ctx->current_info = gp.out.info; if (level == 2 && gp.out.info) { ctx->printer_has_driver = gp.out.info->info2.drivername && strlen(gp.out.info->info2.drivername); } return true; }
static bool test_EnumPrinters(struct torture_context *tctx, struct dcerpc_pipe *p, struct test_spoolss_win_context *ctx, uint32_t initial_blob_size) { NTSTATUS status; struct spoolss_EnumPrinters ep; DATA_BLOB blob = data_blob_talloc_zero(ctx, initial_blob_size); uint32_t needed; uint32_t count; union spoolss_PrinterInfo *info; struct dcerpc_binding_handle *b = p->binding_handle; ep.in.flags = PRINTER_ENUM_NAME; ep.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); ep.in.level = 2; ep.in.buffer = &blob; ep.in.offered = initial_blob_size; ep.out.needed = &needed; ep.out.count = &count; ep.out.info = &info; status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &ep); torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed."); if (W_ERROR_EQUAL(ep.out.result, WERR_INSUFFICIENT_BUFFER)) { blob = data_blob_talloc_zero(ctx, needed); ep.in.buffer = &blob; ep.in.offered = needed; status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &ep); torture_assert_ntstatus_ok(tctx, status,"EnumPrinters failed."); } torture_assert_werr_ok(tctx, ep.out.result, "EnumPrinters failed."); ctx->printer_count = count; ctx->printer_info = info; torture_comment(tctx, "Found %d printer(s).\n", ctx->printer_count); return true; }
static bool test_EnumForms(struct torture_context *tctx, struct dcerpc_binding_handle *b, struct policy_handle *handle, uint32_t initial_blob_size) { NTSTATUS status; struct spoolss_EnumForms ef; DATA_BLOB blob = data_blob_talloc_zero(tctx, initial_blob_size); uint32_t needed; uint32_t count; union spoolss_FormInfo *info; torture_comment(tctx, "Testing EnumForms\n"); ef.in.handle = handle; ef.in.level = 1; ef.in.buffer = (initial_blob_size == 0)?NULL:&blob; ef.in.offered = initial_blob_size; ef.out.needed = &needed; ef.out.count = &count; ef.out.info = &info; status = dcerpc_spoolss_EnumForms_r(b, tctx, &ef); torture_assert_ntstatus_ok(tctx, status, "EnumForms failed"); if (W_ERROR_EQUAL(ef.out.result, WERR_INSUFFICIENT_BUFFER)) { blob = data_blob_talloc_zero(tctx, needed); ef.in.buffer = &blob; ef.in.offered = needed; status = dcerpc_spoolss_EnumForms_r(b, tctx, &ef); torture_assert_ntstatus_ok(tctx, status, "EnumForms failed"); } torture_assert_werr_ok(tctx, ef.out.result, "EnumForms failed"); return true; }
static bool test_EnumJobs(struct torture_context *tctx, struct dcerpc_binding_handle *b, struct policy_handle *handle) { NTSTATUS status; struct spoolss_EnumJobs ej; DATA_BLOB blob = data_blob_talloc_zero(tctx, 1024); uint32_t needed; uint32_t count; union spoolss_JobInfo *info; torture_comment(tctx, "Test EnumJobs\n"); ZERO_STRUCT(ej); ej.in.handle = handle; ej.in.firstjob = 0; ej.in.numjobs = 0; ej.in.level = 2; ej.in.buffer = &blob; ej.in.offered = 1024; ej.out.needed = &needed; ej.out.count = &count; ej.out.info = &info; status = dcerpc_spoolss_EnumJobs_r(b, tctx, &ej); torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed"); if (W_ERROR_EQUAL(ej.out.result, WERR_INSUFFICIENT_BUFFER)) { blob = data_blob_talloc_zero(tctx, needed); ej.in.offered = needed; ej.in.buffer = &blob; status = dcerpc_spoolss_EnumJobs_r(b, tctx, &ej); torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed"); } torture_assert_werr_ok(tctx, ej.out.result, "EnumJobs failed"); return true; }
bool setup_fault_pdu(struct pipes_struct *p, NTSTATUS fault_status) { NTSTATUS status; union dcerpc_payload u; /* Free any memory in the current return data buffer. */ pipe_init_outgoing_data(p); /* * Initialize a fault header. */ ZERO_STRUCT(u); u.fault.status = NT_STATUS_V(fault_status); u.fault._pad = data_blob_talloc_zero(p->mem_ctx, 4); /* * Marshall directly into the outgoing PDU space. We * must do this as we need to set to the bind response * header and are never sending more than one PDU here. */ status = dcerpc_push_ncacn_packet(p->mem_ctx, DCERPC_PKT_FAULT, DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | DCERPC_PFC_FLAG_DID_NOT_EXECUTE, 0, p->call_id, &u, &p->out_data.frag); if (!NT_STATUS_IS_OK(status)) { return False; } p->out_data.data_sent_length = 0; p->out_data.current_pdu_sent = 0; return True; }
/* fill in the cldap netlogon union for a given version */ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, const char *domain, const char *netbios_domain, struct dom_sid *domain_sid, const char *domain_guid, const char *user, uint32_t acct_control, const char *src_address, uint32_t version, struct loadparm_context *lp_ctx, struct netlogon_samlogon_response *netlogon, bool fill_on_blank_request) { const char *dom_attrs[] = {"objectGUID", NULL}; const char *none_attrs[] = {NULL}; struct ldb_result *dom_res = NULL, *user_res = NULL; int ret; const char **services = lpcfg_server_services(lp_ctx); uint32_t server_type; const char *pdc_name; struct GUID domain_uuid; const char *dns_domain; const char *forest_domain; const char *pdc_dns_name; const char *flatname; const char *server_site; const char *client_site; const char *pdc_ip; struct ldb_dn *domain_dn = NULL; struct interface *ifaces; bool user_known, am_rodc; NTSTATUS status; /* the domain parameter could have an optional trailing "." */ if (domain && domain[strlen(domain)-1] == '.') { domain = talloc_strndup(mem_ctx, domain, strlen(domain)-1); NT_STATUS_HAVE_NO_MEMORY(domain); } /* Lookup using long or short domainname */ if (domain && (strcasecmp_m(domain, lpcfg_dnsdomain(lp_ctx)) == 0)) { domain_dn = ldb_get_default_basedn(sam_ctx); } if (netbios_domain && (strcasecmp_m(netbios_domain, lpcfg_sam_name(lp_ctx)) == 0)) { domain_dn = ldb_get_default_basedn(sam_ctx); } if (domain_dn) { const char *domain_identifier = domain != NULL ? domain : netbios_domain; ret = ldb_search(sam_ctx, mem_ctx, &dom_res, domain_dn, LDB_SCOPE_BASE, dom_attrs, "objectClass=domain"); if (ret != LDB_SUCCESS) { DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", domain_identifier, ldb_dn_get_linearized(domain_dn), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; } if (dom_res->count != 1) { DEBUG(2,("Error finding domain '%s'/'%s' in sam\n", domain_identifier, ldb_dn_get_linearized(domain_dn))); return NT_STATUS_NO_SUCH_DOMAIN; } } /* Lookup using GUID or SID */ if ((dom_res == NULL) && (domain_guid || domain_sid)) { if (domain_guid) { struct GUID binary_guid; struct ldb_val guid_val; /* By this means, we ensure we don't have funny stuff in the GUID */ status = GUID_from_string(domain_guid, &binary_guid); if (!NT_STATUS_IS_OK(status)) { return status; } /* And this gets the result into the binary format we want anyway */ status = GUID_to_ndr_blob(&binary_guid, mem_ctx, &guid_val); if (!NT_STATUS_IS_OK(status)) { return status; } ret = ldb_search(sam_ctx, mem_ctx, &dom_res, NULL, LDB_SCOPE_SUBTREE, dom_attrs, "(&(objectCategory=DomainDNS)(objectGUID=%s))", ldb_binary_encode(mem_ctx, guid_val)); } else { /* domain_sid case */ ret = ldb_search(sam_ctx, mem_ctx, &dom_res, NULL, LDB_SCOPE_SUBTREE, dom_attrs, "(&(objectCategory=DomainDNS)(objectSid=%s))", dom_sid_string(mem_ctx, domain_sid)); } if (ret != LDB_SUCCESS) { DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam: %s\n", domain_guid, dom_sid_string(mem_ctx, domain_sid), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; } else if (dom_res->count == 1) { /* Ok, now just check it is our domain */ if (ldb_dn_compare(ldb_get_default_basedn(sam_ctx), dom_res->msgs[0]->dn) != 0) { DEBUG(2,("The GUID '%s' or SID '%s' doesn't identify our domain\n", domain_guid, dom_sid_string(mem_ctx, domain_sid))); return NT_STATUS_NO_SUCH_DOMAIN; } } else { DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam\n", domain_guid, dom_sid_string(mem_ctx, domain_sid))); return NT_STATUS_NO_SUCH_DOMAIN; } } if (dom_res == NULL && fill_on_blank_request) { /* blank inputs gives our domain - tested against w2k8r2. Without this ADUC on Win7 won't start */ domain_dn = ldb_get_default_basedn(sam_ctx); ret = ldb_search(sam_ctx, mem_ctx, &dom_res, domain_dn, LDB_SCOPE_BASE, dom_attrs, "objectClass=domain"); if (ret != LDB_SUCCESS) { DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", lpcfg_dnsdomain(lp_ctx), ldb_dn_get_linearized(domain_dn), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; } } if (dom_res == NULL) { DEBUG(2,(__location__ ": Unable to get domain information with no inputs\n")); return NT_STATUS_NO_SUCH_DOMAIN; } /* work around different inputs for not-specified users */ if (!user) { user = ""; } /* Enquire about any valid username with just a CLDAP packet - * if kerberos didn't also do this, the security folks would * scream... */ if (user[0]) { \ /* Only allow some bits to be enquired: [MS-ATDS] 7.3.3.2 */ if (acct_control == (uint32_t)-1) { acct_control = 0; } acct_control = acct_control & (ACB_TEMPDUP | ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); /* We must exclude disabled accounts, but otherwise do the bitwise match the client asked for */ ret = ldb_search(sam_ctx, mem_ctx, &user_res, dom_res->msgs[0]->dn, LDB_SCOPE_SUBTREE, none_attrs, "(&(objectClass=user)(samAccountName=%s)" "(!(userAccountControl:" LDB_OID_COMPARATOR_AND ":=%u))" "(userAccountControl:" LDB_OID_COMPARATOR_OR ":=%u))", ldb_binary_encode_string(mem_ctx, user), UF_ACCOUNTDISABLE, ds_acb2uf(acct_control)); if (ret != LDB_SUCCESS) { DEBUG(2,("Unable to find reference to user '%s' with ACB 0x%8x under %s: %s\n", user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_USER; } else if (user_res->count == 1) { user_known = true; } else { user_known = false; } } else { user_known = true; } server_type = DS_SERVER_DS | DS_SERVER_TIMESERV | DS_SERVER_GOOD_TIMESERV; if (samdb_is_pdc(sam_ctx)) { server_type |= DS_SERVER_PDC; } if (dsdb_functional_level(sam_ctx) >= DS_DOMAIN_FUNCTION_2008) { server_type |= DS_SERVER_FULL_SECRET_DOMAIN_6; } if (samdb_is_gc(sam_ctx)) { server_type |= DS_SERVER_GC; } if (str_list_check(services, "ldap")) { server_type |= DS_SERVER_LDAP; } if (str_list_check(services, "kdc")) { server_type |= DS_SERVER_KDC; } if (samdb_rodc(sam_ctx, &am_rodc) == LDB_SUCCESS && !am_rodc) { server_type |= DS_SERVER_WRITABLE; } pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", lpcfg_netbios_name(lp_ctx)); NT_STATUS_HAVE_NO_MEMORY(pdc_name); domain_uuid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); dns_domain = lpcfg_dnsdomain(lp_ctx); forest_domain = samdb_forest_name(sam_ctx, mem_ctx); NT_STATUS_HAVE_NO_MEMORY(forest_domain); pdc_dns_name = talloc_asprintf(mem_ctx, "%s.%s", strlower_talloc(mem_ctx, lpcfg_netbios_name(lp_ctx)), dns_domain); NT_STATUS_HAVE_NO_MEMORY(pdc_dns_name); flatname = lpcfg_workgroup(lp_ctx); server_site = samdb_server_site_name(sam_ctx, mem_ctx); NT_STATUS_HAVE_NO_MEMORY(server_site); client_site = samdb_client_site_name(sam_ctx, mem_ctx, src_address, NULL); NT_STATUS_HAVE_NO_MEMORY(client_site); if (strcasecmp(server_site, client_site) == 0) { server_type |= DS_SERVER_CLOSEST; } load_interface_list(mem_ctx, lp_ctx, &ifaces); if (src_address) { pdc_ip = iface_list_best_ip(ifaces, src_address); } else { pdc_ip = iface_list_first_v4(ifaces); } if (pdc_ip == NULL || !is_ipaddress_v4(pdc_ip)) { /* this matches windows behaviour */ pdc_ip = "127.0.0.1"; } ZERO_STRUCTP(netlogon); /* check if either of these bits is present */ if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) { uint32_t extra_flags = 0; netlogon->ntver = NETLOGON_NT_VERSION_5EX; /* could check if the user exists */ if (user_known) { netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_RESPONSE_EX; } else { netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_USER_UNKNOWN_EX; } netlogon->data.nt5_ex.pdc_name = pdc_name; netlogon->data.nt5_ex.user_name = user; netlogon->data.nt5_ex.domain_name = flatname; netlogon->data.nt5_ex.domain_uuid = domain_uuid; netlogon->data.nt5_ex.forest = forest_domain; netlogon->data.nt5_ex.dns_domain = dns_domain; netlogon->data.nt5_ex.pdc_dns_name = pdc_dns_name; netlogon->data.nt5_ex.server_site = server_site; netlogon->data.nt5_ex.client_site = client_site; if (version & NETLOGON_NT_VERSION_5EX_WITH_IP) { /* note that this is always a IPV4 address */ extra_flags = NETLOGON_NT_VERSION_5EX_WITH_IP; netlogon->data.nt5_ex.sockaddr.sockaddr_family = 2; netlogon->data.nt5_ex.sockaddr.pdc_ip = pdc_ip; netlogon->data.nt5_ex.sockaddr.remaining = data_blob_talloc_zero(mem_ctx, 8); } netlogon->data.nt5_ex.server_type = server_type; netlogon->data.nt5_ex.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5EX|extra_flags; netlogon->data.nt5_ex.lmnt_token = 0xFFFF; netlogon->data.nt5_ex.lm20_token = 0xFFFF; } else if (version & NETLOGON_NT_VERSION_5) { netlogon->ntver = NETLOGON_NT_VERSION_5; /* could check if the user exists */ if (user_known) { netlogon->data.nt5.command = LOGON_SAM_LOGON_RESPONSE; } else { netlogon->data.nt5.command = LOGON_SAM_LOGON_USER_UNKNOWN; } netlogon->data.nt5.pdc_name = pdc_name; netlogon->data.nt5.user_name = user; netlogon->data.nt5.domain_name = flatname; netlogon->data.nt5.domain_uuid = domain_uuid; netlogon->data.nt5.forest = forest_domain; netlogon->data.nt5.dns_domain = dns_domain; netlogon->data.nt5.pdc_dns_name = pdc_dns_name; netlogon->data.nt5.pdc_ip = pdc_ip; netlogon->data.nt5.server_type = server_type; netlogon->data.nt5.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5; netlogon->data.nt5.lmnt_token = 0xFFFF; netlogon->data.nt5.lm20_token = 0xFFFF; } else /* (version & NETLOGON_NT_VERSION_1) and all other cases */ { netlogon->ntver = NETLOGON_NT_VERSION_1; /* could check if the user exists */ if (user_known) { netlogon->data.nt4.command = LOGON_SAM_LOGON_RESPONSE; } else { netlogon->data.nt4.command = LOGON_SAM_LOGON_USER_UNKNOWN; } netlogon->data.nt4.pdc_name = pdc_name; netlogon->data.nt4.user_name = user; netlogon->data.nt4.domain_name = flatname; netlogon->data.nt4.nt_version = NETLOGON_NT_VERSION_1; netlogon->data.nt4.lmnt_token = 0xFFFF; netlogon->data.nt4.lm20_token = 0xFFFF; } return NT_STATUS_OK; }
/* * @brief Load the keys into the encrypted secrets module context. * * @param module the current ldb module * @param data the private data for the current module * * Currently the keys are stored in a binary file in the same directory * as the database. * * @return an LDB result code. * */ static int load_keys(struct ldb_module *module, struct es_data *data) { const char *key_dir = NULL; const char *key_path = NULL; struct ldb_context *ldb = NULL; FILE *fp = NULL; const int key_size = 16; int read; DATA_BLOB key = data_blob_null; TALLOC_CTX *frame = talloc_stackframe(); ldb = ldb_module_get_ctx(module); key_dir = get_key_directory(frame, ldb); if (key_dir == NULL) { TALLOC_FREE(frame); return LDB_ERR_OPERATIONS_ERROR; } key_path = talloc_asprintf(frame, "%s/%s", key_dir, SECRETS_KEY_FILE); if (key_path == NULL) { TALLOC_FREE(frame); return ldb_oom(ldb); } key = data_blob_talloc_zero(module, key_size); key.length = key_size; fp = fopen(key_path, "rb"); if (fp == NULL) { TALLOC_FREE(frame); data_blob_free(&key); if (errno == ENOENT) { ldb_debug(ldb, LDB_DEBUG_WARNING, "No encrypted secrets key file. " "Secret attributes will not be encrypted or " "decrypted\n"); data->encrypt_secrets = false; return LDB_SUCCESS; } else { log_error(ldb, errno, "Opening encrypted_secrets key file\n"); return LDB_ERR_OPERATIONS_ERROR; } } read = fread(key.data, 1, key.length, fp); fclose(fp); if (read == 0) { TALLOC_FREE(frame); ldb_debug(ldb, LDB_DEBUG_WARNING, "Zero length encrypted secrets key file. " "Secret attributes will not be encrypted or " "decrypted\n"); data->encrypt_secrets = false; return LDB_SUCCESS; } if (read != key.length) { TALLOC_FREE(frame); if (errno) { log_error(ldb, errno, "Reading encrypted_secrets key file\n"); } else { ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid encrypted_secrets key file, " "only %d bytes read should be %d bytes\n", read, key_size); } return LDB_ERR_OPERATIONS_ERROR; } data->keys[0] = key; data->encrypt_secrets = true; #ifdef BUILD_WITH_GNUTLS_AEAD data->encryption_algorithm = GNUTLS_CIPHER_AES_128_GCM; #endif TALLOC_FREE(frame); return LDB_SUCCESS; }
static bool fdpass2_parent(pid_t child_pid, int ready_fd) { struct tevent_context *ev = NULL; struct messaging_context *msg_ctx = NULL; bool retval = false; int up_pipe[2]; int down_pipe[2]; int pass_fds[2] = { 0 }; int ret; NTSTATUS status; struct server_id dst; TALLOC_CTX *frame = talloc_stackframe(); uint8_t c1 = 1, c2, c; ssize_t bytes; struct iovec iov; DATA_BLOB blob; struct tevent_fd *child_done_fde; struct child_done_state child_state; ev = samba_tevent_context_init(frame); if (ev == NULL) { fprintf(stderr, "parent: tevent_context_init failed\n"); goto done; } msg_ctx = messaging_init(ev, ev); if (msg_ctx == NULL) { fprintf(stderr, "parent: messaging_init failed\n"); goto done; } /* wait util the child is ready to receive messages */ bytes = read(ready_fd, &c, 1); if (bytes != 1) { perror("parent: read from ready_fd failed"); goto done; } ret = pipe(up_pipe); if (ret != 0) { perror("parent: pipe failed for up_pipe"); goto done; } ret = pipe(down_pipe); if (ret != 0) { perror("parent: pipe failed for down_pipe"); goto done; } child_state.fd = ready_fd; child_state.done = false; child_done_fde = tevent_add_fd(ev, ev, ready_fd, TEVENT_FD_READ, child_done_cb, &child_state); if (child_done_fde == NULL) { fprintf(stderr, "parent: failed tevent_add_fd for child done\n"); goto done; } pass_fds[0] = up_pipe[0]; pass_fds[1] = down_pipe[1]; dst = messaging_server_id(msg_ctx); dst.pid = child_pid; /* * Send a certain payload with the fds, to test to test * that fd-passing works when we have fragmentation and * re-assembly of the datagrams. */ blob = data_blob_talloc_zero(frame, 1000*1000); iov.iov_base = blob.data; iov.iov_len = blob.length; status = messaging_send_iov(msg_ctx, dst, MSG_TORTURE_FDPASS2, &iov, 1, pass_fds, 2); if (!NT_STATUS_IS_OK(status)) { fprintf(stderr, "parent: messaging_send_iov failed: %s\n", nt_errstr(status)); goto done; } printf("parent: waiting for child to confirm\n"); while (!child_state.done) { ret = tevent_loop_once(ev); if (ret != 0) { fprintf(stderr, "parent: tevent_loop_once failed\n"); goto done; } } printf("parent: child confirmed\n"); close(up_pipe[0]); close(down_pipe[1]); bytes = write(up_pipe[1], &c1, 1); if (bytes != 1) { perror("parent: write to up pipe failed"); goto done; } bytes = read(down_pipe[0], &c2, 1); if (bytes != 1) { perror("parent: read from down pipe failed"); goto done; } if (c1 != c2) { fprintf(stderr, "parent: c1[%d] != c2[%d]\n", c1, c2); goto done; } ret = waitpid(child_pid, NULL, 0); if (ret == -1) { perror("parent: waitpid failed"); goto done; } retval = true; done: TALLOC_FREE(frame); return retval; }
NTSTATUS netsec_outgoing_packet(struct schannel_state *state, TALLOC_CTX *mem_ctx, bool do_seal, uint8_t *data, size_t length, DATA_BLOB *sig) { uint32_t min_sig_size = 0; uint32_t used_sig_size = 0; uint8_t header[8]; uint8_t checksum[32]; uint32_t checksum_length = sizeof(checksum_length); uint8_t _confounder[8]; uint8_t *confounder = NULL; uint32_t confounder_ofs = 0; uint8_t seq_num[8]; netsec_offset_and_sizes(state, do_seal, &min_sig_size, &used_sig_size, &checksum_length, &confounder_ofs); RSIVAL(seq_num, 0, state->seq_num); SIVAL(seq_num, 4, state->initiator?0x80:0); if (do_seal) { confounder = _confounder; generate_random_buffer(confounder, 8); } else { confounder = NULL; } netsec_do_sign(state, confounder, data, length, header, checksum); if (do_seal) { netsec_do_seal(state, seq_num, confounder, data, length, true); } netsec_do_seq_num(state, checksum, checksum_length, seq_num); (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size); memcpy(sig->data, header, 8); memcpy(sig->data+8, seq_num, 8); memcpy(sig->data+16, checksum, checksum_length); if (confounder) { memcpy(sig->data+confounder_ofs, confounder, 8); } dump_data_pw("signature:", sig->data+ 0, 8); dump_data_pw("seq_num :", sig->data+ 8, 8); dump_data_pw("digest :", sig->data+16, checksum_length); dump_data_pw("confound :", sig->data+confounder_ofs, 8); return NT_STATUS_OK; }
NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding, struct epm_tower *tower) { const enum epm_protocol *protseq = NULL; int num_protocols = -1, i; NTSTATUS status; /* Find transport */ for (i=0;i<ARRAY_SIZE(transports);i++) { if (transports[i].transport == binding->transport) { protseq = transports[i].protseq; num_protocols = transports[i].num_protocols; break; } } if (num_protocols == -1) { DEBUG(0, ("Unable to find transport with id '%d'\n", binding->transport)); return NT_STATUS_UNSUCCESSFUL; } tower->num_floors = 2 + num_protocols; tower->floors = talloc_array(mem_ctx, struct epm_floor, tower->num_floors); /* Floor 0 */ tower->floors[0].lhs.protocol = EPM_PROTOCOL_UUID; tower->floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx, &binding->object); tower->floors[0].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2); /* Floor 1 */ tower->floors[1].lhs.protocol = EPM_PROTOCOL_UUID; tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx, &ndr_transfer_syntax); tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2); /* Floor 2 to num_protocols */ for (i = 0; i < num_protocols; i++) { tower->floors[2 + i].lhs.protocol = protseq[i]; tower->floors[2 + i].lhs.lhs_data = data_blob_talloc(mem_ctx, NULL, 0); ZERO_STRUCT(tower->floors[2 + i].rhs); dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[2 + i], ""); } /* The 4th floor contains the endpoint */ if (num_protocols >= 2 && binding->endpoint) { status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[3], binding->endpoint); if (NT_STATUS_IS_ERR(status)) { return status; } } /* The 5th contains the network address */ if (num_protocols >= 3 && binding->host) { if (is_ipaddress(binding->host)) { status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4], binding->host); } else { /* note that we don't attempt to resolve the name here - when we get a hostname here we are in the client code, and want to put in a wildcard all-zeros IP for the server to fill in */ status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4], "0.0.0.0"); } if (NT_STATUS_IS_ERR(status)) { return status; } } return NT_STATUS_OK; }
/* send a create request */ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create *io) { struct smb2_request *req; NTSTATUS status; DATA_BLOB blob; struct smb2_create_blobs blobs; int i; ZERO_STRUCT(blobs); req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, true, 0); if (req == NULL) return NULL; SCVAL(req->out.body, 0x02, io->in.security_flags); SCVAL(req->out.body, 0x03, io->in.oplock_level); SIVAL(req->out.body, 0x04, io->in.impersonation_level); SBVAL(req->out.body, 0x08, io->in.create_flags); SBVAL(req->out.body, 0x10, io->in.reserved); SIVAL(req->out.body, 0x18, io->in.desired_access); SIVAL(req->out.body, 0x1C, io->in.file_attributes); SIVAL(req->out.body, 0x20, io->in.share_access); SIVAL(req->out.body, 0x24, io->in.create_disposition); SIVAL(req->out.body, 0x28, io->in.create_options); status = smb2_push_o16s16_string(&req->out, 0x2C, io->in.fname); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } /* now add all the optional blobs */ if (io->in.eas.num_eas != 0) { DATA_BLOB b = data_blob_talloc(req, NULL, ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas, 4)); ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas, 4); status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_EXTA, b); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } data_blob_free(&b); } /* an empty MxAc tag seems to be used to ask the server to return the maximum access mask allowed on the file */ if (io->in.query_maximal_access) { /* TODO: MS-SMB2 2.2.13.2.5 says this can contain a timestamp? What to do with that if it doesn't match? */ status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_MXAC, data_blob(NULL, 0)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.alloc_size != 0) { uint8_t data[8]; SBVAL(data, 0, io->in.alloc_size); status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_ALSI, data_blob_const(data, 8)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.durable_open) { status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_DHNQ, data_blob_talloc_zero(req, 16)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.durable_handle) { uint8_t data[16]; smb2_push_handle(data, io->in.durable_handle); status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_DHNC, data_blob_const(data, 16)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.timewarp) { uint8_t data[8]; SBVAL(data, 0, io->in.timewarp); status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_TWRP, data_blob_const(data, 8)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.sec_desc) { enum ndr_err_code ndr_err; DATA_BLOB sd_blob; ndr_err = ndr_push_struct_blob(&sd_blob, req, io->in.sec_desc, (ndr_push_flags_fn_t)ndr_push_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(req); return NULL; } status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_SECD, sd_blob); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.query_on_disk_id) { status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_QFID, data_blob(NULL, 0)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.lease_request) { uint8_t data[32]; memcpy(&data[0], &io->in.lease_request->lease_key, 16); SIVAL(data, 16, io->in.lease_request->lease_state); SIVAL(data, 20, io->in.lease_request->lease_flags); SBVAL(data, 24, io->in.lease_request->lease_duration); status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_RQLS, data_blob_const(data, 32)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } /* and any custom blobs */ for (i=0;i<io->in.blobs.num_blobs;i++) { status = smb2_create_blob_add(req, &blobs, io->in.blobs.blobs[i].tag, io->in.blobs.blobs[i].data); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } status = smb2_create_blob_push(req, &blob, blobs); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } status = smb2_push_o32s32_blob(&req->out, 0x30, blob); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } data_blob_free(&blob); smb2_transport_send(req); return req; }
NTSTATUS dcerpc_winreg_query_dword(TALLOC_CTX *mem_ctx, struct dcerpc_binding_handle *h, struct policy_handle *key_handle, const char *value, uint32_t *data, WERROR *pwerr) { struct winreg_String wvalue; enum winreg_Type type = REG_NONE; uint32_t value_len = 0; uint32_t data_size = 0; WERROR result = WERR_OK; NTSTATUS status; DATA_BLOB blob; wvalue.name = value; status = dcerpc_winreg_QueryValue(h, mem_ctx, key_handle, &wvalue, &type, NULL, &data_size, &value_len, &result); if (!NT_STATUS_IS_OK(status)) { return status; } if (!W_ERROR_IS_OK(result)) { *pwerr = result; return status; } if (type != REG_DWORD) { *pwerr = WERR_INVALID_DATATYPE; return status; } if (data_size != 4) { *pwerr = WERR_INVALID_DATA; return status; } blob = data_blob_talloc_zero(mem_ctx, data_size); if (blob.data == NULL) { *pwerr = WERR_NOMEM; return status; } value_len = 0; status = dcerpc_winreg_QueryValue(h, mem_ctx, key_handle, &wvalue, &type, blob.data, &data_size, &value_len, &result); if (!NT_STATUS_IS_OK(status)) { return status; } if (!W_ERROR_IS_OK(result)) { *pwerr = result; return status; } if (data) { *data = IVAL(blob.data, 0); } return status; }