/* get pending ops info for a specified DN */ static WERROR kccdrs_replica_get_info_pending_ops(TALLOC_CTX *mem_ctx, struct ldb_context *samdb, struct drsuapi_DsReplicaGetInfo *r, union drsuapi_DsReplicaInfo *reply, struct ldb_dn *dn) { struct timeval now = timeval_current(); if (!ldb_dn_validate(dn)) { return WERR_INVALID_PARAMETER; } reply->pendingops = talloc(mem_ctx, struct drsuapi_DsReplicaOpCtr); W_ERROR_HAVE_NO_MEMORY(reply->pendingops); /* claim no pending ops for now */ reply->pendingops->time = timeval_to_nttime(&now); reply->pendingops->count = 0; reply->pendingops->array = NULL; return WERR_OK; }
static WERROR gp_read_reg_gpo(TALLOC_CTX *mem_ctx, struct registry_key *key, struct GROUP_POLICY_OBJECT **gpo_ret) { struct GROUP_POLICY_OBJECT *gpo = NULL; WERROR werr; if (!gpo_ret || !key) { return WERR_INVALID_PARAM; } gpo = talloc_zero(mem_ctx, struct GROUP_POLICY_OBJECT); W_ERROR_HAVE_NO_MEMORY(gpo); werr = gp_read_reg_gpovals(mem_ctx, key, gpo); W_ERROR_NOT_OK_RETURN(werr); *gpo_ret = gpo; return werr; }
static WERROR handle_question(struct dns_server *dns, TALLOC_CTX *mem_ctx, const struct dns_name_question *question, struct dns_res_rec **answers, uint16_t *ancount) { struct dns_res_rec *ans; WERROR werror; unsigned int ri; struct dnsp_DnssrvRpcRecord *recs; uint16_t rec_count, ai = 0; struct ldb_dn *dn = NULL; werror = dns_name2dn(dns, mem_ctx, question->name, &dn); W_ERROR_NOT_OK_RETURN(werror); werror = dns_lookup_records(dns, mem_ctx, dn, &recs, &rec_count); W_ERROR_NOT_OK_RETURN(werror); ans = talloc_zero_array(mem_ctx, struct dns_res_rec, rec_count); W_ERROR_HAVE_NO_MEMORY(ans); for (ri = 0; ri < rec_count; ri++) { if ((question->question_type != DNS_QTYPE_ALL) && (recs[ri].wType != question->question_type)) { continue; } werror = create_response_rr(question, &recs[ri], &ans, &ai); W_ERROR_NOT_OK_RETURN(werror); } if (ai == 0) { return DNS_ERR(NAME_ERROR); } *ancount = ai; *answers = ans; return WERR_OK; }
static WERROR _dsdb_prefixmap_from_ldb_val(const struct ldb_val *pfm_ldb_val, TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm) { WERROR werr; enum ndr_err_code ndr_err; struct prefixMapBlob pfm_blob; TALLOC_CTX *temp_ctx = talloc_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(temp_ctx); ndr_err = ndr_pull_struct_blob(pfm_ldb_val, temp_ctx, &pfm_blob, (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("_dsdb_prefixmap_from_ldb_val: Failed to parse prefixmap of length %u: %s\n", (unsigned int)pfm_ldb_val->length, ndr_map_error2string(ndr_err))); talloc_free(temp_ctx); return ntstatus_to_werror(nt_status); } if (pfm_blob.version != PREFIX_MAP_VERSION_DSDB) { DEBUG(0,("_dsdb_prefixmap_from_ldb_val: pfm_blob->version %u incorrect\n", (unsigned int)pfm_blob.version)); talloc_free(temp_ctx); return WERR_VERSION_PARSE_ERROR; } /* call the drsuapi version */ werr = dsdb_schema_pfm_from_drsuapi_pfm(&pfm_blob.ctr.dsdb, false, mem_ctx, _pfm, NULL); if (!W_ERROR_IS_OK(werr)) { DEBUG(0, (__location__ " dsdb_schema_pfm_from_drsuapi_pfm failed: %s\n", win_errstr(werr))); talloc_free(temp_ctx); return werr; } talloc_free(temp_ctx); return werr; }
/* get cursors2 info for a specified DN */ static WERROR kccdrs_replica_get_info_cursors2(TALLOC_CTX *mem_ctx, struct ldb_context *samdb, struct drsuapi_DsReplicaGetInfo *r, union drsuapi_DsReplicaInfo *reply, struct ldb_dn *dn) { int ret; if (!ldb_dn_validate(dn)) { return WERR_INVALID_PARAMETER; } reply->cursors2 = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2Ctr); W_ERROR_HAVE_NO_MEMORY(reply->cursors2); ret = dsdb_load_udv_v2(samdb, dn, reply->cursors2, &reply->cursors2->array, &reply->cursors2->count); if (ret != LDB_SUCCESS) { return WERR_DS_DRA_BAD_NC; } reply->cursors2->enumeration_context = reply->cursors2->count; return WERR_OK; }
WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx, struct NetGetJoinInformation *r) { struct rpc_pipe_client *pipe_cli = NULL; NTSTATUS status; WERROR werr; const char *buffer = NULL; struct dcerpc_binding_handle *b; werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_wkssvc, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; } b = pipe_cli->binding_handle; status = dcerpc_wkssvc_NetrGetJoinInformation(b, talloc_tos(), r->in.server_name, &buffer, (enum wkssvc_NetJoinStatus *)r->out.name_type, &werr); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (!W_ERROR_IS_OK(werr)) { goto done; } *r->out.name_buffer = talloc_strdup(ctx, buffer); W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer); done: return werr; }
static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx, uint32_t level, uint8_t *buffer, enum samr_AliasInfoEnum *alias_level, union samr_AliasInfo **alias_info) { struct LOCALGROUP_INFO_0 *info0; struct LOCALGROUP_INFO_1 *info1; struct LOCALGROUP_INFO_1002 *info1002; union samr_AliasInfo *info = NULL; info = talloc_zero(mem_ctx, union samr_AliasInfo); W_ERROR_HAVE_NO_MEMORY(info); switch (level) { case 0: info0 = (struct LOCALGROUP_INFO_0 *)buffer; init_lsa_String(&info->name, info0->lgrpi0_name); *alias_level = ALIASINFONAME; break; case 1: info1 = (struct LOCALGROUP_INFO_1 *)buffer; /* group name will be ignored */ init_lsa_String(&info->description, info1->lgrpi1_comment); *alias_level = ALIASINFODESCRIPTION; break; case 1002: info1002 = (struct LOCALGROUP_INFO_1002 *)buffer; init_lsa_String(&info->description, info1002->lgrpi1002_comment); *alias_level = ALIASINFODESCRIPTION; break; } *alias_info = info; return WERR_OK; }
WERROR rpccli_spoolss_addprinterex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct spoolss_SetPrinterInfoCtr *info_ctr) { WERROR result; NTSTATUS status; struct spoolss_DevmodeContainer devmode_ctr; struct sec_desc_buf secdesc_ctr; struct spoolss_UserLevelCtr userlevel_ctr; struct spoolss_UserLevel1 level1; struct policy_handle handle; ZERO_STRUCT(devmode_ctr); ZERO_STRUCT(secdesc_ctr); level1.size = 28; level1.build = 1381; level1.major = 2; level1.minor = 0; level1.processor = 0; level1.client = talloc_asprintf(mem_ctx, "\\\\%s", global_myname()); W_ERROR_HAVE_NO_MEMORY(level1.client); level1.user = cli->auth->user_name; userlevel_ctr.level = 1; userlevel_ctr.user_info.level1 = &level1; status = rpccli_spoolss_AddPrinterEx(cli, mem_ctx, cli->srv_name_slash, info_ctr, &devmode_ctr, &secdesc_ctr, &userlevel_ctr, &handle, &result); return result; }
WERROR dsdb_subSchema_dITContentRules(const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx) { struct ldb_message_element *e; struct dsdb_class *c; e = talloc_zero(mem_ctx, struct ldb_message_element); W_ERROR_HAVE_NO_MEMORY(e); for (c = schema->classes; c; c = c->next) { char *v; /* * TODO: filter out classes without auxiliary classes */ v = talloc_asprintf(e, "( %s NAME '%s' ", c->governsID_oid, c->lDAPDisplayName); W_ERROR_HAVE_NO_MEMORY(v); v = dsdb_subSchema_list_append(v, "AUX"); W_ERROR_HAVE_NO_MEMORY(v); v = dsdb_subSchema_list_append(v, "MUST"); W_ERROR_HAVE_NO_MEMORY(v); v = dsdb_subSchema_list_append(v, "MAY"); W_ERROR_HAVE_NO_MEMORY(v); v = talloc_asprintf_append(v, ")"); W_ERROR_HAVE_NO_MEMORY(v); DEBUG(0,("%s\n", v)); } return WERR_FOOBAR; }
static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx, struct NetLocalGroupAddMembers *add, struct NetLocalGroupDelMembers *del, struct NetLocalGroupSetMembers *set) { struct NetLocalGroupAddMembers *r = NULL; struct rpc_pipe_client *pipe_cli = NULL; struct rpc_pipe_client *lsa_pipe = NULL; NTSTATUS status, result; WERROR werr; struct lsa_String lsa_account_name; struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle; struct dom_sid2 *domain_sid = NULL; struct dom_sid *member_sids = NULL; int i = 0, k = 0; struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL; struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL; struct dom_sid *add_sids = NULL; struct dom_sid *del_sids = NULL; uint32_t num_add_sids = 0; uint32_t num_del_sids = 0; struct dcerpc_binding_handle *b = NULL; if ((!add && !del && !set) || (add && del && set)) { return WERR_INVALID_PARAM; } if (add) { r = add; } if (del) { r = (struct NetLocalGroupAddMembers *)del; } if (set) { r = (struct NetLocalGroupAddMembers *)set; } if (!r->in.group_name) { return WERR_INVALID_PARAM; } switch (r->in.level) { case 0: case 3: break; default: return WERR_UNKNOWN_LEVEL; } if (r->in.total_entries == 0 || !r->in.buffer) { return WERR_INVALID_PARAM; } ZERO_STRUCT(connect_handle); ZERO_STRUCT(builtin_handle); ZERO_STRUCT(domain_handle); ZERO_STRUCT(alias_handle); member_sids = talloc_zero_array(ctx, struct dom_sid, r->in.total_entries); W_ERROR_HAVE_NO_MEMORY(member_sids); switch (r->in.level) { case 0: info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer; for (i=0; i < r->in.total_entries; i++) { sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid); } break; case 3: info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer; break; default: break; } if (r->in.level == 3) { werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_lsarpc, &lsa_pipe); if (!W_ERROR_IS_OK(werr)) { goto done; } for (i=0; i < r->in.total_entries; i++) { status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe, info3[i].lgrmi3_domainandname, &member_sids[i]); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } TALLOC_FREE(lsa_pipe); } werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; } b = pipe_cli->binding_handle; werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli, SAMR_ACCESS_LOOKUP_DOMAIN | SAMR_ACCESS_ENUM_DOMAINS, SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &builtin_handle); if (!W_ERROR_IS_OK(werr)) { goto done; } init_lsa_String(&lsa_account_name, r->in.group_name); status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &builtin_handle, r->in.group_name, SAMR_ALIAS_ACCESS_ADD_MEMBER | SAMR_ALIAS_ACCESS_REMOVE_MEMBER | SAMR_ALIAS_ACCESS_GET_MEMBERS | SAMR_ALIAS_ACCESS_LOOKUP_INFO, &alias_handle); if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); } if (NT_STATUS_IS_OK(status)) { goto modify_membership; } werr = libnetapi_samr_open_domain(ctx, pipe_cli, SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_LOOKUP_DOMAIN, SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &domain_handle, &domain_sid); if (!W_ERROR_IS_OK(werr)) { goto done; } status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &domain_handle, r->in.group_name, SAMR_ALIAS_ACCESS_ADD_MEMBER | SAMR_ALIAS_ACCESS_REMOVE_MEMBER | SAMR_ALIAS_ACCESS_GET_MEMBERS | SAMR_ALIAS_ACCESS_LOOKUP_INFO, &alias_handle); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); } modify_membership: if (add) { for (i=0; i < r->in.total_entries; i++) { status = add_sid_to_array_unique(ctx, &member_sids[i], &add_sids, &num_add_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } if (del) { for (i=0; i < r->in.total_entries; i++) { status = add_sid_to_array_unique(ctx, &member_sids[i], &del_sids, &num_del_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } if (set) { struct lsa_SidArray current_sids; status = dcerpc_samr_GetMembersInAlias(b, talloc_tos(), &alias_handle, ¤t_sids, &result); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (!NT_STATUS_IS_OK(result)) { werr = ntstatus_to_werror(result); goto done; } /* add list */ for (i=0; i < r->in.total_entries; i++) { bool already_member = false; for (k=0; k < current_sids.num_sids; k++) { if (dom_sid_equal(&member_sids[i], current_sids.sids[k].sid)) { already_member = true; break; } } if (!already_member) { status = add_sid_to_array_unique(ctx, &member_sids[i], &add_sids, &num_add_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } /* del list */ for (k=0; k < current_sids.num_sids; k++) { bool keep_member = false; for (i=0; i < r->in.total_entries; i++) { if (dom_sid_equal(&member_sids[i], current_sids.sids[k].sid)) { keep_member = true; break; } } if (!keep_member) { status = add_sid_to_array_unique(ctx, current_sids.sids[k].sid, &del_sids, &num_del_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } } /* add list */ for (i=0; i < num_add_sids; i++) { status = dcerpc_samr_AddAliasMember(b, talloc_tos(), &alias_handle, &add_sids[i], &result); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (!NT_STATUS_IS_OK(result)) { werr = ntstatus_to_werror(result); goto done; } } /* del list */ for (i=0; i < num_del_sids; i++) { status = dcerpc_samr_DeleteAliasMember(b, talloc_tos(), &alias_handle, &del_sids[i], &result); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (!NT_STATUS_IS_OK(result)) { werr = ntstatus_to_werror(result); goto done; } } werr = WERR_OK; done: if (b && is_valid_policy_hnd(&alias_handle)) { dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result); } if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); libnetapi_samr_close_connect_handle(ctx, &connect_handle); } return werr; }
WERROR dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const struct dsdb_schema *schema) { WERROR status; int ldb_ret; struct ldb_message *msg; struct ldb_dn *schema_dn; struct prefixMapBlob pfm_blob; struct ldb_val ndr_blob; enum ndr_err_code ndr_err; TALLOC_CTX *temp_ctx; struct drsuapi_DsReplicaOIDMapping_Ctr *ctr; schema_dn = ldb_get_schema_basedn(ldb); if (!schema_dn) { DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: no schema dn present\n")); return WERR_FOOBAR; } temp_ctx = talloc_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(temp_ctx); /* convert schema_prefixMap to prefixMap blob */ status = dsdb_get_oid_mappings_drsuapi(schema, false, temp_ctx, &ctr); if (!W_ERROR_IS_OK(status)) { talloc_free(temp_ctx); return status; } pfm_blob.version = PREFIX_MAP_VERSION_DSDB; pfm_blob.ctr.dsdb = *ctr; ndr_err = ndr_push_struct_blob(&ndr_blob, temp_ctx, &pfm_blob, (ndr_push_flags_fn_t)ndr_push_prefixMapBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(temp_ctx); return WERR_FOOBAR; } /* write serialized prefixMap into LDB */ msg = ldb_msg_new(temp_ctx); if (!msg) { talloc_free(temp_ctx); return WERR_NOMEM; } msg->dn = schema_dn; ldb_ret = ldb_msg_add_value(msg, "prefixMap", &ndr_blob, NULL); if (ldb_ret != 0) { talloc_free(temp_ctx); DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: ldb_msg_add_value failed\n")); return WERR_NOMEM; } ldb_ret = dsdb_replace(ldb, msg, DSDB_FLAG_AS_SYSTEM); talloc_free(temp_ctx); if (ldb_ret != 0) { DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: dsdb_replace failed\n")); return WERR_FOOBAR; } return WERR_OK; }
static WERROR ask_forwarder(struct dns_server *dns, TALLOC_CTX *mem_ctx, struct dns_name_question *question, struct dns_res_rec **answers, uint16_t *ancount, struct dns_res_rec **nsrecs, uint16_t *nscount, struct dns_res_rec **additional, uint16_t *arcount) { struct tevent_context *ev = tevent_context_init(mem_ctx); struct dns_name_packet *out_packet, *in_packet; uint16_t id = random(); DATA_BLOB out, in; enum ndr_err_code ndr_err; WERROR werr = WERR_OK; struct tevent_req *req; const char *forwarder = lpcfg_dns_forwarder(dns->task->lp_ctx); if (!is_ipaddress(forwarder)) { DEBUG(0, ("Invalid 'dns forwarder' setting '%s', needs to be " "an IP address\n", forwarder)); return DNS_ERR(NAME_ERROR); } out_packet = talloc_zero(mem_ctx, struct dns_name_packet); W_ERROR_HAVE_NO_MEMORY(out_packet); out_packet->id = id; out_packet->operation |= DNS_OPCODE_QUERY | DNS_FLAG_RECURSION_DESIRED; out_packet->qdcount = 1; out_packet->questions = question; ndr_err = ndr_push_struct_blob(&out, mem_ctx, out_packet, (ndr_push_flags_fn_t)ndr_push_dns_name_packet); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return DNS_ERR(SERVER_FAILURE); } req = dns_udp_request_send(mem_ctx, ev, forwarder, out.data, out.length); W_ERROR_HAVE_NO_MEMORY(req); if(!tevent_req_poll(req, ev)) { return DNS_ERR(SERVER_FAILURE); } werr = dns_udp_request_recv(req, mem_ctx, &in.data, &in.length); W_ERROR_NOT_OK_RETURN(werr); in_packet = talloc_zero(mem_ctx, struct dns_name_packet); W_ERROR_HAVE_NO_MEMORY(in_packet); ndr_err = ndr_pull_struct_blob(&in, in_packet, in_packet, (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return DNS_ERR(SERVER_FAILURE); } if (in_packet->id != id) { DEBUG(0, ("DNS packet id mismatch: 0x%0x, expected 0x%0x\n", in_packet->id, id)); return DNS_ERR(NAME_ERROR); } *ancount = in_packet->ancount; *answers = talloc_move(mem_ctx, &in_packet->answers); *nscount = in_packet->nscount; *nsrecs = talloc_move(mem_ctx, &in_packet->nsrecs); *arcount = in_packet->arcount; *additional = talloc_move(mem_ctx, &in_packet->additional); return werr; }
/* load the partitions list based on replicated NC attributes in our NTDSDSA object */ WERROR dreplsrv_load_partitions(struct dreplsrv_service *s) { WERROR status; static const char *attrs[] = { "hasMasterNCs", "msDs-hasMasterNCs", "hasPartialReplicaNCs", "msDS-HasFullReplicaNCs", NULL }; unsigned int a; int ret; TALLOC_CTX *tmp_ctx; struct ldb_result *res; struct ldb_message_element *el; struct ldb_dn *ntds_dn; tmp_ctx = talloc_new(s); W_ERROR_HAVE_NO_MEMORY(tmp_ctx); ntds_dn = samdb_ntds_settings_dn(s->samdb); if (!ntds_dn) { DEBUG(1,(__location__ ": Unable to find ntds_dn: %s\n", ldb_errstring(s->samdb))); talloc_free(tmp_ctx); return WERR_DS_DRA_INTERNAL_ERROR; } ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, ntds_dn, attrs, DSDB_SEARCH_SHOW_EXTENDED_DN); if (ret != LDB_SUCCESS) { DEBUG(1,("Searching for hasMasterNCs in NTDS DN failed: %s\n", ldb_errstring(s->samdb))); talloc_free(tmp_ctx); return WERR_DS_DRA_INTERNAL_ERROR; } for (a=0; attrs[a]; a++) { int i; el = ldb_msg_find_element(res->msgs[0], attrs[a]); if (el == NULL) { continue; } for (i=0; i<el->num_values; i++) { struct ldb_dn *pdn; struct dreplsrv_partition *p, *tp; bool found; pdn = ldb_dn_from_ldb_val(tmp_ctx, s->samdb, &el->values[i]); if (pdn == NULL) { talloc_free(tmp_ctx); return WERR_DS_DRA_INTERNAL_ERROR; } if (!ldb_dn_validate(pdn)) { return WERR_DS_DRA_INTERNAL_ERROR; } p = talloc_zero(s, struct dreplsrv_partition); W_ERROR_HAVE_NO_MEMORY(p); p->dn = talloc_steal(p, pdn); p->service = s; if (strcasecmp(attrs[a], "hasPartialReplicaNCs") == 0) { p->partial_replica = true; } else if (strcasecmp(attrs[a], "msDS-HasFullReplicaNCs") == 0) { p->rodc_replica = true; } /* Do not add partitions more than once */ found = false; for (tp = s->partitions; tp; tp = tp->next) { if (ldb_dn_compare(tp->dn, p->dn) == 0) { found = true; break; } } if (found) { talloc_free(p); continue; } DLIST_ADD(s->partitions, p); DEBUG(2, ("dreplsrv_partition[%s] loaded\n", ldb_dn_get_linearized(p->dn))); } } talloc_free(tmp_ctx); status = dreplsrv_refresh_partitions(s); W_ERROR_NOT_OK_RETURN(status); return WERR_OK; }
WERROR drsuapi_decrypt_attribute_value(TALLOC_CTX *mem_ctx, const DATA_BLOB *gensec_skey, bool rid_crypt, uint32_t rid, DATA_BLOB *in, DATA_BLOB *out) { DATA_BLOB confounder; DATA_BLOB enc_buffer; MD5_CTX md5; uint8_t _enc_key[16]; DATA_BLOB enc_key; DATA_BLOB dec_buffer; uint32_t crc32_given; uint32_t crc32_calc; DATA_BLOB checked_buffer; DATA_BLOB plain_buffer; /* * users with rid == 0 should not exist */ if (rid_crypt && rid == 0) { return WERR_DS_DRA_INVALID_PARAMETER; } /* * the first 16 bytes at the beginning are the confounder * followed by the 4 byte crc32 checksum */ if (in->length < 20) { return WERR_DS_DRA_INVALID_PARAMETER; } confounder = data_blob_const(in->data, 16); enc_buffer = data_blob_const(in->data + 16, in->length - 16); /* * build the encryption key md5 over the session key followed * by the confounder * * here the gensec session key is used and * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key! */ enc_key = data_blob_const(_enc_key, sizeof(_enc_key)); MD5Init(&md5); MD5Update(&md5, gensec_skey->data, gensec_skey->length); MD5Update(&md5, confounder.data, confounder.length); MD5Final(enc_key.data, &md5); /* * copy the encrypted buffer part and * decrypt it using the created encryption key using arcfour */ dec_buffer = data_blob_const(enc_buffer.data, enc_buffer.length); arcfour_crypt_blob(dec_buffer.data, dec_buffer.length, &enc_key); /* * the first 4 byte are the crc32 checksum * of the remaining bytes */ crc32_given = IVAL(dec_buffer.data, 0); crc32_calc = crc32_calc_buffer(dec_buffer.data + 4 , dec_buffer.length - 4); checked_buffer = data_blob_const(dec_buffer.data + 4, dec_buffer.length - 4); plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length); W_ERROR_HAVE_NO_MEMORY(plain_buffer.data); if (crc32_given != crc32_calc) { return WERR_SEC_E_DECRYPT_FAILURE; } /* * The following rid_crypt obfuscation isn't session specific * and not really needed here, because we allways know the rid of the * user account. * * some attributes with this 'additional encryption' include * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory * * But for the rest of samba it's easier when we remove this static * obfuscation here */ if (rid_crypt) { uint32_t i, num_hashes; if ((checked_buffer.length % 16) != 0) { return WERR_DS_DRA_INVALID_PARAMETER; } num_hashes = plain_buffer.length / 16; for (i = 0; i < num_hashes; i++) { uint32_t offset = i * 16; sam_rid_crypt(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0); } } *out = plain_buffer; return WERR_OK; }
WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx, struct NetUnjoinDomain *r) { struct libnet_UnjoinCtx *u = NULL; struct dom_sid domain_sid; const char *domain = NULL; WERROR werr; if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) { return WERR_SETUP_NOT_JOINED; } werr = libnet_init_UnjoinCtx(mem_ctx, &u); W_ERROR_NOT_OK_RETURN(werr); if (lp_realm()) { domain = lp_realm(); } else { domain = lp_workgroup(); } if (r->in.server_name) { u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name); W_ERROR_HAVE_NO_MEMORY(u->in.dc_name); } else { NTSTATUS status; struct netr_DsRGetDCNameInfo *info = NULL; const char *dc = NULL; uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED | DS_WRITABLE_REQUIRED | DS_RETURN_DNS_NAME; status = dsgetdcname(mem_ctx, NULL, domain, NULL, NULL, flags, &info); if (!NT_STATUS_IS_OK(status)) { libnetapi_set_error_string(mem_ctx, "failed to find DC for domain %s: %s", domain, get_friendly_nt_error_msg(status)); return ntstatus_to_werror(status); } dc = strip_hostname(info->dc_unc); u->in.dc_name = talloc_strdup(mem_ctx, dc); W_ERROR_HAVE_NO_MEMORY(u->in.dc_name); u->in.domain_name = domain; } if (r->in.account) { u->in.admin_account = talloc_strdup(mem_ctx, r->in.account); W_ERROR_HAVE_NO_MEMORY(u->in.admin_account); } if (r->in.password) { u->in.admin_password = talloc_strdup(mem_ctx, r->in.password); W_ERROR_HAVE_NO_MEMORY(u->in.admin_password); } u->in.domain_name = domain; u->in.unjoin_flags = r->in.unjoin_flags; u->in.delete_machine_account = false; u->in.modify_config = true; u->in.debug = true; u->in.domain_sid = &domain_sid; werr = libnet_Unjoin(mem_ctx, u); if (!W_ERROR_IS_OK(werr) && u->out.error_string) { libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string); } TALLOC_FREE(u); return werr; }
/* drsuapi_DsWriteAccountSpn */ WERROR dcesrv_drsuapi_DsWriteAccountSpn(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsWriteAccountSpn *r) { struct drsuapi_bind_state *b_state; struct dcesrv_handle *h; *r->out.level_out = r->in.level; DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); b_state = h->data; r->out.res = talloc(mem_ctx, union drsuapi_DsWriteAccountSpnResult); W_ERROR_HAVE_NO_MEMORY(r->out.res); switch (r->in.level) { case 1: { struct drsuapi_DsWriteAccountSpnRequest1 *req; struct ldb_message *msg; int count, i, ret; struct ldb_result *res; const char *attrs[] = { "servicePrincipalName", NULL }; struct ldb_message_element *el; unsigned spn_count=0; req = &r->in.req->req1; count = req->count; msg = ldb_msg_new(mem_ctx); if (msg == NULL) { return WERR_NOMEM; } msg->dn = ldb_dn_new(msg, b_state->sam_ctx, req->object_dn); if ( ! ldb_dn_validate(msg->dn)) { r->out.res->res1.status = WERR_OK; return WERR_OK; } /* load the existing SPNs, as these are * ignored for adds and deletes (see MS-DRSR * section 4.1.28.3) */ ret = ldb_search(b_state->sam_ctx, msg, &res, msg->dn, LDB_SCOPE_BASE, attrs, NULL); if (ret != LDB_SUCCESS) { DEBUG(0,("Failed to load existing SPNs on %s: %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(b_state->sam_ctx))); r->out.res->res1.status = WERR_DS_OBJ_NOT_FOUND; return WERR_OK; } el = ldb_msg_find_element(res->msgs[0], "servicePrincipalName"); /* construct mods */ for (i = 0; i < count; i++) { bool found = false; int j; for (j=0; el && j<el->num_values; j++) { if (samdb_ldb_val_case_cmp(req->spn_names[i].str, &el->values[j]) == 0) { found = true; break; } } if ((req->operation == DRSUAPI_DS_SPN_OPERATION_ADD && found) || (req->operation == DRSUAPI_DS_SPN_OPERATION_DELETE && !found)) { continue; } ret = samdb_msg_add_string(b_state->sam_ctx, msg, msg, "servicePrincipalName", req->spn_names[i].str); if (ret != LDB_SUCCESS) { return WERR_NOMEM; } spn_count++; } if (msg->num_elements == 0) { DEBUG(2,("No SPNs need changing on %s\n", ldb_dn_get_linearized(msg->dn))); r->out.res->res1.status = WERR_OK; return WERR_OK; } for (i=0;i<msg->num_elements;i++) { switch (req->operation) { case DRSUAPI_DS_SPN_OPERATION_ADD: msg->elements[i].flags = LDB_FLAG_MOD_ADD; break; case DRSUAPI_DS_SPN_OPERATION_REPLACE: msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; break; case DRSUAPI_DS_SPN_OPERATION_DELETE: msg->elements[i].flags = LDB_FLAG_MOD_DELETE; break; } } /* Apply to database */ ret = ldb_modify(b_state->sam_ctx, msg); if (ret != 0) { DEBUG(0,("Failed to modify SPNs on %s: %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(b_state->sam_ctx))); r->out.res->res1.status = WERR_ACCESS_DENIED; } else { DEBUG(2,("Modified %u SPNs on %s\n", spn_count, ldb_dn_get_linearized(msg->dn))); r->out.res->res1.status = WERR_OK; } return WERR_OK; } } return WERR_UNKNOWN_LEVEL; }
static WERROR sptr_SetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, struct spoolss_SetForm *r) { struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context); struct ldb_message *msg,**msgs; const char * const attrs[] = { "flags", NULL}; int count, ret; enum spoolss_FormFlags flags; /* TODO: do checks access here * if (!(server->access_mask & desired_access)) { * return WERR_FOOBAR; * } */ switch (r->in.level) { case 1: if (!r->in.info.info1) { return WERR_FOOBAR; } count = sptr_db_search(sptr_db, mem_ctx, ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"), &msgs, attrs, "(&(form-name=%s)(objectClass=form))", r->in.info.info1->form_name); if (count == 0) return WERR_FOOBAR; if (count > 1) return WERR_FOOBAR; if (count < 0) return WERR_GENERAL_FAILURE; flags = ldb_msg_find_attr_as_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN); if (flags != SPOOLSS_FORM_USER) { return WERR_FOOBAR; } msg = ldb_msg_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(msg); /* add core elements to the ldb_message for the user */ msg->dn = msgs[0]->dn; SET_UINT(sptr_db, msg, "flags", r->in.info.info1->flags); SET_STRING(sptr_db, msg, "form-name", r->in.info.info1->form_name); SET_UINT(sptr_db, msg, "size-width", r->in.info.info1->size.width); SET_UINT(sptr_db, msg, "size-height", r->in.info.info1->size.height); SET_UINT(sptr_db, msg, "area-left", r->in.info.info1->area.left); SET_UINT(sptr_db, msg, "area-top", r->in.info.info1->area.top); SET_UINT(sptr_db, msg, "area-right", r->in.info.info1->area.right); SET_UINT(sptr_db, msg, "area-bottom", r->in.info.info1->area.bottom); break; default: return WERR_UNKNOWN_LEVEL; } ret = dsdb_replace(sptr_db, msg, 0); if (ret != 0) { return WERR_FOOBAR; } return WERR_OK; }
/* get metadata version 2 info for a specified object DN */ static WERROR kccdrs_replica_get_info_obj_metadata2(TALLOC_CTX *mem_ctx, struct ldb_context *samdb, struct drsuapi_DsReplicaGetInfo *r, union drsuapi_DsReplicaInfo *reply, struct ldb_dn *dn, uint32_t base_index) { WERROR status; struct replPropertyMetaDataBlob omd_ctr; struct replPropertyMetaData1 *attr; struct drsuapi_DsReplicaObjMetaData2Ctr *metadata2; const struct dsdb_schema *schema; uint32_t i, j; DEBUG(0, ("kccdrs_replica_get_info_obj_metadata2() called\n")); if (!dn) { return WERR_INVALID_PARAMETER; } if (!ldb_dn_validate(dn)) { return WERR_DS_DRA_BAD_DN; } status = get_repl_prop_metadata_ctr(mem_ctx, samdb, dn, &omd_ctr); W_ERROR_NOT_OK_RETURN(status); schema = dsdb_get_schema(samdb, reply); if (!schema) { DEBUG(0,(__location__": Failed to get the schema\n")); return WERR_INTERNAL_ERROR; } reply->objmetadata2 = talloc_zero(mem_ctx, struct drsuapi_DsReplicaObjMetaData2Ctr); W_ERROR_HAVE_NO_MEMORY(reply->objmetadata2); metadata2 = reply->objmetadata2; metadata2->enumeration_context = 0; /* For each replicated attribute of the object */ for (i = 0, j = 0; i < omd_ctr.ctr.ctr1.count; i++) { const struct dsdb_attribute *schema_attr; uint32_t attr_version; NTTIME attr_change_time; uint32_t attr_originating_usn; /* attr := attrsSeq[i] s := AttrStamp(object, attr) */ /* get a reference to the attribute on 'omd_ctr' */ attr = &omd_ctr.ctr.ctr1.array[j]; schema_attr = dsdb_attribute_by_attributeID_id(schema, attr->attid); DEBUG(0, ("attribute_id = %d, attribute_name: %s\n", attr->attid, schema_attr->lDAPDisplayName)); /* if (attr in Link Attributes of object and dwInVersion = 2 and DS_REPL_INFO_FLAG_IMPROVE_LINKED_ATTRS in msgIn.ulFlags) */ if (schema_attr && schema_attr->linkID != 0 && /* Checks if attribute is a linked attribute */ (schema_attr->linkID % 2) == 0 && /* is it a forward link? only forward links have the LinkValueStamp */ r->in.level == 2 && (r->in.req->req2.flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)) /* on MS-DRSR it is DS_REPL_INFO_FLAG_IMPROVE_LINKED_ATTRS */ { /* ls := LinkValueStamp of the most recent value change in object!attr */ status = get_linked_attribute_value_stamp(mem_ctx, samdb, dn, schema_attr->lDAPDisplayName, &attr_version, &attr_change_time, &attr_originating_usn); W_ERROR_NOT_OK_RETURN(status); /* Aligning to MS-DRSR 4.1.13.3: 's' on the doc is 'attr->originating_change_time' here 'ls' on the doc is 'attr_change_time' here */ /* if (ls is more recent than s (based on order in which the change was applied on server)) then */ if (attr_change_time > attr->originating_change_time) { /* Improve the stamp with the link value stamp. s.dwVersion := ls.dwVersion s.timeChanged := ls.timeChanged s.uuidOriginating := NULLGUID s.usnOriginating := ls.usnOriginating */ attr->version = attr_version; attr->originating_change_time = attr_change_time; attr->originating_invocation_id = GUID_zero(); attr->originating_usn = attr_originating_usn; } } if (i < base_index) { continue; } metadata2->array = talloc_realloc(mem_ctx, metadata2->array, struct drsuapi_DsReplicaObjMetaData2, j + 1); W_ERROR_HAVE_NO_MEMORY(metadata2->array); metadata2->array[j].attribute_name = schema_attr->lDAPDisplayName; metadata2->array[j].local_usn = attr->local_usn; metadata2->array[j].originating_change_time = attr->originating_change_time; metadata2->array[j].originating_invocation_id = attr->originating_invocation_id; metadata2->array[j].originating_usn = attr->originating_usn; metadata2->array[j].version = attr->version; /* originating_dsa_dn := GetDNFromInvocationID(originating_invocation_id) GetDNFromInvocationID() should return the DN of the nTDSDSAobject that has the specified invocation ID See MS-DRSR 4.1.13.3 and 4.1.13.2.1 */ status = get_dn_from_invocation_id(mem_ctx, samdb, &attr->originating_invocation_id, &metadata2->array[j].originating_dsa_dn); W_ERROR_NOT_OK_RETURN(status); j++; metadata2->count = j; } return WERR_OK; }
static WERROR dcesrv_spoolss_parse_printer_name(TALLOC_CTX *mem_ctx, const char *name, const char **_server_name, const char **_object_name, enum ntptr_HandleType *_object_type) { char *p; char *server = NULL; char *server_unc = NULL; const char *object = name; /* no printername is there it's like open server */ if (!name) { *_server_name = NULL; *_object_name = NULL; *_object_type = NTPTR_HANDLE_SERVER; return WERR_OK; } /* just "\\" is invalid */ if (strequal("\\\\", name)) { return WERR_INVALID_PRINTER_NAME; } if (strncmp("\\\\", name, 2) == 0) { server_unc = talloc_strdup(mem_ctx, name); W_ERROR_HAVE_NO_MEMORY(server_unc); server = server_unc + 2; /* here we know we have "\\" in front not followed * by '\0', now see if we have another "\" in the string */ p = strchr_m(server, '\\'); if (!p) { /* there's no other "\", so it's ("\\%s",server) */ *_server_name = server_unc; *_object_name = NULL; *_object_type = NTPTR_HANDLE_SERVER; return WERR_OK; } /* here we know that we have ("\\%s\",server), * if we have '\0' as next then it's an invalid name * otherwise the printer_name */ p[0] = '\0'; /* everything that follows is the printer name */ p++; object = p; /* just "" as server is invalid */ if (strequal(server, "")) { return WERR_INVALID_PRINTER_NAME; } } /* just "" is invalid */ if (strequal(object, "")) { return WERR_INVALID_PRINTER_NAME; } #define XCV_PORT ",XcvPort " #define XCV_MONITOR ",XcvMonitor " if (strncmp(object, XCV_PORT, strlen(XCV_PORT)) == 0) { object += strlen(XCV_PORT); /* just "" is invalid */ if (strequal(object, "")) { return WERR_INVALID_PRINTER_NAME; } *_server_name = server_unc; *_object_name = object; *_object_type = NTPTR_HANDLE_PORT; return WERR_OK; } else if (strncmp(object, XCV_MONITOR, strlen(XCV_MONITOR)) == 0) { object += strlen(XCV_MONITOR); /* just "" is invalid */ if (strequal(object, "")) { return WERR_INVALID_PRINTER_NAME; } *_server_name = server_unc; *_object_name = object; *_object_type = NTPTR_HANDLE_MONITOR; return WERR_OK; } *_server_name = server_unc; *_object_name = object; *_object_type = NTPTR_HANDLE_PRINTER; return WERR_OK; }
/* * Check server_name is: * - "" , functions that don't allow "", * should check that on their own, before calling this function * - our name (only netbios yet, TODO: need to test dns name!) * - our ip address of the current use socket * otherwise return WERR_INVALID_PRINTER_NAME */ static WERROR dcesrv_spoolss_check_server_name(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, const char *server_name) { bool ret; struct socket_address *myaddr; const char **aliases; int i; /* NULL is ok */ if (!server_name) return WERR_OK; /* "" is ok */ ret = strequal("",server_name); if (ret) return WERR_OK; /* just "\\" is invalid */ if (strequal("\\\\", server_name)) { return WERR_INVALID_PRINTER_NAME; } /* then we need "\\" */ if (strncmp("\\\\", server_name, 2) != 0) { return WERR_INVALID_PRINTER_NAME; } server_name += 2; /* NETBIOS NAME is ok */ ret = strequal(lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx), server_name); if (ret) return WERR_OK; aliases = lp_netbios_aliases(dce_call->conn->dce_ctx->lp_ctx); for (i=0; aliases && aliases[i]; i++) { if (strequal(aliases[i], server_name)) { return WERR_OK; } } /* DNS NAME is ok * TODO: we need to check if aliases are also ok */ if (lp_realm(dce_call->conn->dce_ctx->lp_ctx)) { char *str; str = talloc_asprintf(mem_ctx, "%s.%s", lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx), lp_realm(dce_call->conn->dce_ctx->lp_ctx)); W_ERROR_HAVE_NO_MEMORY(str); ret = strequal(str, server_name); talloc_free(str); if (ret) return WERR_OK; } myaddr = dcesrv_connection_get_my_addr(dce_call->conn, mem_ctx); W_ERROR_HAVE_NO_MEMORY(myaddr); ret = strequal(myaddr->addr, server_name); talloc_free(myaddr); if (ret) return WERR_OK; return WERR_INVALID_PRINTER_NAME; }
/* load our local partition list */ static WERROR kccsrv_load_partitions(struct kccsrv_service *s) { struct ldb_dn *basedn; struct ldb_result *r; struct ldb_message_element *el; static const char *attrs[] = { "namingContexts", "configurationNamingContext", NULL }; unsigned int i; int ret; basedn = ldb_dn_new(s, s->samdb, NULL); W_ERROR_HAVE_NO_MEMORY(basedn); ret = ldb_search(s->samdb, s, &r, basedn, LDB_SCOPE_BASE, attrs, "(objectClass=*)"); talloc_free(basedn); if (ret != LDB_SUCCESS) { return WERR_FOOBAR; } else if (r->count != 1) { talloc_free(r); return WERR_FOOBAR; } el = ldb_msg_find_element(r->msgs[0], "namingContexts"); if (!el) { return WERR_FOOBAR; } for (i=0; i < el->num_values; i++) { const char *v = (const char *)el->values[i].data; struct ldb_dn *pdn; struct kccsrv_partition *p; pdn = ldb_dn_new(s, s->samdb, v); if (!ldb_dn_validate(pdn)) { return WERR_FOOBAR; } p = talloc_zero(s, struct kccsrv_partition); W_ERROR_HAVE_NO_MEMORY(p); p->dn = talloc_steal(p, pdn); p->service = s; DLIST_ADD(s->partitions, p); DEBUG(2, ("kccsrv_partition[%s] loaded\n", v)); } el = ldb_msg_find_element(r->msgs[0], "configurationNamingContext"); if (!el) { return WERR_FOOBAR; } s->config_dn = ldb_dn_new(s, s->samdb, (const char *)el->values[0].data); if (!ldb_dn_validate(s->config_dn)) { return WERR_FOOBAR; } talloc_free(r); return WERR_OK; }
WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx, struct NetJoinDomain *r) { struct libnet_JoinCtx *j = NULL; WERROR werr; if (!r->in.domain) { return WERR_INVALID_PARAM; } werr = libnet_init_JoinCtx(mem_ctx, &j); W_ERROR_NOT_OK_RETURN(werr); j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain); W_ERROR_HAVE_NO_MEMORY(j->in.domain_name); if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) { NTSTATUS status; struct netr_DsRGetDCNameInfo *info = NULL; const char *dc = NULL; uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED | DS_WRITABLE_REQUIRED | DS_RETURN_DNS_NAME; status = dsgetdcname(mem_ctx, NULL, r->in.domain, NULL, NULL, flags, &info); if (!NT_STATUS_IS_OK(status)) { libnetapi_set_error_string(mem_ctx, "%s", get_friendly_nt_error_msg(status)); return ntstatus_to_werror(status); } dc = strip_hostname(info->dc_unc); j->in.dc_name = talloc_strdup(mem_ctx, dc); W_ERROR_HAVE_NO_MEMORY(j->in.dc_name); } if (r->in.account_ou) { j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou); W_ERROR_HAVE_NO_MEMORY(j->in.account_ou); } if (r->in.account) { j->in.admin_account = talloc_strdup(mem_ctx, r->in.account); W_ERROR_HAVE_NO_MEMORY(j->in.admin_account); } if (r->in.password) { j->in.admin_password = talloc_strdup(mem_ctx, r->in.password); W_ERROR_HAVE_NO_MEMORY(j->in.admin_password); } j->in.join_flags = r->in.join_flags; j->in.modify_config = true; j->in.debug = true; werr = libnet_Join(mem_ctx, j); if (!W_ERROR_IS_OK(werr) && j->out.error_string) { libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string); } TALLOC_FREE(j); return werr; }
static WERROR sptr_PrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, const char *value_name, union spoolss_PrinterData *r, enum winreg_Type *type) { struct dcerpc_server_info *server_info = lpcfg_dcerpc_server_info(mem_ctx, server->ntptr->lp_ctx); if (strcmp("W3SvcInstalled", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("BeepEnabled", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("EventLog", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("NetPopup", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("NetPopupToComputer", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("MajorVersion", value_name) == 0) { *type = REG_DWORD; r->value = 3; return WERR_OK; } else if (strcmp("MinorVersion", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("DefaultSpoolDirectory", value_name) == 0) { *type = REG_SZ; r->string = "C:\\PRINTERS"; return WERR_OK; } else if (strcmp("Architecture", value_name) == 0) { *type = REG_SZ; r->string = SPOOLSS_ARCHITECTURE_NT_X86; return WERR_OK; } else if (strcmp("DsPresent", value_name) == 0) { *type = REG_DWORD; r->value = 1; return WERR_OK; } else if (strcmp("OSVersion", value_name) == 0) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct spoolss_OSVersion os; os.major = server_info->version_major; os.minor = server_info->version_minor; os.build = server_info->version_build; os.extra_string = ""; ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_GENERAL_FAILURE; } *type = REG_BINARY; r->binary = blob; return WERR_OK; } else if (strcmp("OSVersionEx", value_name) == 0) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct spoolss_OSVersionEx os_ex; os_ex.major = server_info->version_major; os_ex.minor = server_info->version_minor; os_ex.build = server_info->version_build; os_ex.extra_string = ""; os_ex.service_pack_major= 0; os_ex.service_pack_minor= 0; os_ex.suite_mask = 0; os_ex.product_type = 0; os_ex.reserved = 0; ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os_ex, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersionEx); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_GENERAL_FAILURE; } *type = REG_BINARY; r->binary = blob; return WERR_OK; } else if (strcmp("DNSMachineName", value_name) == 0) { const char *dnsdomain = lpcfg_dnsdomain(server->ntptr->lp_ctx); if (dnsdomain == NULL) return WERR_INVALID_PARAM; *type = REG_SZ; r->string = talloc_asprintf(mem_ctx, "%s.%s", lpcfg_netbios_name(server->ntptr->lp_ctx), dnsdomain); W_ERROR_HAVE_NO_MEMORY(r->string); return WERR_OK; } return WERR_INVALID_PARAM; }
static WERROR cmd_drsuapi_writeaccountspn(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status; WERROR werr; struct GUID bind_guid; struct policy_handle bind_handle; struct dcerpc_binding_handle *b = cli->binding_handle; struct drsuapi_DsNameString *spn_names = NULL; int i = 0; uint32_t level_out; union drsuapi_DsWriteAccountSpnRequest req; union drsuapi_DsWriteAccountSpnResult result; if (argc < 4) { printf("usage: %s [add|replace|delete] dn [spn_names]+\n", argv[0]); return WERR_OK; } req.req1.unknown1 = 0; /* Unused, must be 0 */ req.req1.object_dn = argv[2]; req.req1.count = argc - 3; if (strcmp(argv[1], "add") == 0) { req.req1.operation = DRSUAPI_DS_SPN_OPERATION_ADD; } else if (strcmp(argv[1], "replace") == 0) { req.req1.operation = DRSUAPI_DS_SPN_OPERATION_REPLACE; } else if (strcmp(argv[1], "delete") == 0) { req.req1.operation = DRSUAPI_DS_SPN_OPERATION_DELETE; } else { printf("usage: %s [add|replace|delete] dn [spn_names]+\n", argv[0]); return WERR_OK; } spn_names = talloc_zero_array(mem_ctx, struct drsuapi_DsNameString, req.req1.count); W_ERROR_HAVE_NO_MEMORY(spn_names); for (i=0; i<req.req1.count; i++) { spn_names[i].str = argv[i + 3]; } req.req1.spn_names = spn_names; GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid); status = dcerpc_drsuapi_DsBind(b, mem_ctx, &bind_guid, NULL, &bind_handle, &werr); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } if (!W_ERROR_IS_OK(werr)) { return werr; } status = dcerpc_drsuapi_DsWriteAccountSpn(b, mem_ctx, &bind_handle, 1, &req, &level_out, &result, &werr); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto out; } if (!W_ERROR_IS_OK(werr)) { goto out; } out: if (is_valid_policy_hnd(&bind_handle)) { WERROR _werr; dcerpc_drsuapi_DsUnbind(b, mem_ctx, &bind_handle, &_werr); } return werr; }
/* Printer functions */ static WERROR sptr_EnumPrinters(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, struct spoolss_EnumPrinters *r) { struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context); struct ldb_message **msgs; int count; int i; union spoolss_PrinterInfo *info; count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL, "(&(objectclass=printer))"); if (count == 0) return WERR_OK; if (count < 0) return WERR_GENERAL_FAILURE; info = talloc_array(mem_ctx, union spoolss_PrinterInfo, count); W_ERROR_HAVE_NO_MEMORY(info); switch(r->in.level) { case 1: for (i = 0; i < count; i++) { info[i].info1.flags = ldb_msg_find_attr_as_uint(msgs[i], "flags", 0); info[i].info1.name = ldb_msg_find_attr_as_string(msgs[i], "name", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info1.name); info[i].info1.description = ldb_msg_find_attr_as_string(msgs[i], "description", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info1.description); info[i].info1.comment = ldb_msg_find_attr_as_string(msgs[i], "comment", NULL); } break; case 2: for (i = 0; i < count; i++) { info[i].info2.servername = ldb_msg_find_attr_as_string(msgs[i], "servername", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername); info[i].info2.printername = ldb_msg_find_attr_as_string(msgs[i], "printername", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername); info[i].info2.sharename = ldb_msg_find_attr_as_string(msgs[i], "sharename", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info2.sharename); info[i].info2.portname = ldb_msg_find_attr_as_string(msgs[i], "portname", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info2.portname); info[i].info2.drivername = ldb_msg_find_attr_as_string(msgs[i], "drivername", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info2.drivername); info[i].info2.comment = ldb_msg_find_attr_as_string(msgs[i], "comment", NULL); info[i].info2.location = ldb_msg_find_attr_as_string(msgs[i], "location", NULL); info[i].info2.devmode = NULL; info[i].info2.sepfile = ldb_msg_find_attr_as_string(msgs[i], "sepfile", NULL); info[i].info2.printprocessor = ldb_msg_find_attr_as_string(msgs[i], "printprocessor", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info2.printprocessor); info[i].info2.datatype = ldb_msg_find_attr_as_string(msgs[i], "datatype", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info2.datatype); info[i].info2.parameters = ldb_msg_find_attr_as_string(msgs[i], "parameters", NULL); info[i].info2.secdesc = NULL; info[i].info2.attributes = ldb_msg_find_attr_as_uint(msgs[i], "attributes", 0); info[i].info2.priority = ldb_msg_find_attr_as_uint(msgs[i], "priority", 0); info[i].info2.defaultpriority = ldb_msg_find_attr_as_uint(msgs[i], "defaultpriority", 0); info[i].info2.starttime = ldb_msg_find_attr_as_uint(msgs[i], "starttime", 0); info[i].info2.untiltime = ldb_msg_find_attr_as_uint(msgs[i], "untiltime", 0); info[i].info2.status = ldb_msg_find_attr_as_uint(msgs[i], "status", 0); info[i].info2.cjobs = ldb_msg_find_attr_as_uint(msgs[i], "cjobs", 0); info[i].info2.averageppm = ldb_msg_find_attr_as_uint(msgs[i], "averageppm", 0); } break; case 4: for (i = 0; i < count; i++) { info[i].info4.printername = ldb_msg_find_attr_as_string(msgs[i], "printername", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername); info[i].info4.servername = ldb_msg_find_attr_as_string(msgs[i], "servername", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername); info[i].info4.attributes = ldb_msg_find_attr_as_uint(msgs[i], "attributes", 0); } break; case 5: for (i = 0; i < count; i++) { info[i].info5.printername = ldb_msg_find_attr_as_string(msgs[i], "name", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info5.printername); info[i].info5.portname = ldb_msg_find_attr_as_string(msgs[i], "port", ""); W_ERROR_HAVE_NO_MEMORY(info[i].info5.portname); info[i].info5.attributes = ldb_msg_find_attr_as_uint(msgs[i], "attributes", 0); info[i].info5.device_not_selected_timeout = ldb_msg_find_attr_as_uint(msgs[i], "device_not_selected_timeout", 0); info[i].info5.transmission_retry_timeout = ldb_msg_find_attr_as_uint(msgs[i], "transmission_retry_timeout", 0); } break; default: return WERR_UNKNOWN_LEVEL; } *r->out.info = info; *r->out.count = count; return WERR_OK; }
/* drsuapi_DsBind */ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsBind *r) { struct drsuapi_bind_state *b_state; struct dcesrv_handle *handle; struct drsuapi_DsBindInfoCtr *bind_info; struct GUID site_guid; struct ldb_result *site_res; struct ldb_dn *server_site_dn; static const char *site_attrs[] = { "objectGUID", NULL }; struct ldb_result *ntds_res; struct ldb_dn *ntds_dn; static const char *ntds_attrs[] = { "ms-DS-ReplicationEpoch", NULL }; uint32_t pid; uint32_t repl_epoch; int ret; struct auth_session_info *auth_info; WERROR werr; r->out.bind_info = NULL; ZERO_STRUCTP(r->out.bind_handle); b_state = talloc_zero(mem_ctx, struct drsuapi_bind_state); W_ERROR_HAVE_NO_MEMORY(b_state); /* if this is a DC connecting, give them system level access */ werr = drs_security_level_check(dce_call, NULL); if (W_ERROR_IS_OK(werr)) { DEBUG(3,(__location__ ": doing DsBind with system_session\n")); auth_info = system_session(dce_call->conn->dce_ctx->lp_ctx); } else { auth_info = dce_call->conn->auth_state.session_info; } /* * connect to the samdb */ b_state->sam_ctx = samdb_connect(b_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, auth_info); if (!b_state->sam_ctx) { return WERR_FOOBAR; } /* * find out the guid of our own site */ server_site_dn = samdb_server_site_dn(b_state->sam_ctx, mem_ctx); W_ERROR_HAVE_NO_MEMORY(server_site_dn); ret = ldb_search(b_state->sam_ctx, mem_ctx, &site_res, server_site_dn, LDB_SCOPE_BASE, site_attrs, "(objectClass=*)"); if (ret != LDB_SUCCESS) { return WERR_DS_DRA_INTERNAL_ERROR; } if (site_res->count != 1) { return WERR_DS_DRA_INTERNAL_ERROR; } site_guid = samdb_result_guid(site_res->msgs[0], "objectGUID"); /* * lookup the local servers Replication Epoch */ ntds_dn = samdb_ntds_settings_dn(b_state->sam_ctx); W_ERROR_HAVE_NO_MEMORY(ntds_dn); ret = ldb_search(b_state->sam_ctx, mem_ctx, &ntds_res, ntds_dn, LDB_SCOPE_BASE, ntds_attrs, "(objectClass=*)"); if (ret != LDB_SUCCESS) { return WERR_DS_DRA_INTERNAL_ERROR; } if (ntds_res->count != 1) { return WERR_DS_DRA_INTERNAL_ERROR; } repl_epoch = samdb_result_uint(ntds_res->msgs[0], "ms-DS-ReplicationEpoch", 0); /* * The "process identifier" of the client. * According to the WSPP docs, sectin 5.35, this is * for informational and debugging purposes only. * The assignment is implementation specific. */ pid = 0; /* * store the clients bind_guid */ if (r->in.bind_guid) { b_state->remote_bind_guid = *r->in.bind_guid; } /* * store the clients bind_info */ if (r->in.bind_info) { switch (r->in.bind_info->length) { case 24: { struct drsuapi_DsBindInfo24 *info24; info24 = &r->in.bind_info->info.info24; b_state->remote_info28.supported_extensions = info24->supported_extensions; b_state->remote_info28.site_guid = info24->site_guid; b_state->remote_info28.pid = info24->pid; b_state->remote_info28.repl_epoch = 0; break; } case 28: b_state->remote_info28 = r->in.bind_info->info.info28; break; } } /* * fill in our local bind info 28 */ b_state->local_info28.supported_extensions = 0; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2; #if 0 /* we don't support MSZIP compression (only decompression) */ b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS; #endif b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_00100000; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT; #if 0 /* we don't support XPRESS compression yet */ b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS; #endif b_state->local_info28.site_guid = site_guid; b_state->local_info28.pid = pid; b_state->local_info28.repl_epoch = repl_epoch; /* * allocate the return bind_info */ bind_info = talloc(mem_ctx, struct drsuapi_DsBindInfoCtr); W_ERROR_HAVE_NO_MEMORY(bind_info); bind_info->length = 28; bind_info->info.info28 = b_state->local_info28; /* * allocate a bind handle */ handle = dcesrv_handle_new(dce_call->context, DRSUAPI_BIND_HANDLE); W_ERROR_HAVE_NO_MEMORY(handle); handle->data = talloc_steal(handle, b_state); /* * prepare reply */ r->out.bind_info = bind_info; *r->out.bind_handle = handle->wire_handle; return WERR_OK; }
static WERROR cmd_drsuapi_getncchanges(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status; WERROR werr; struct policy_handle bind_handle; struct dcerpc_binding_handle *b = cli->binding_handle; struct GUID bind_guid; struct drsuapi_DsBindInfoCtr bind_info; struct drsuapi_DsBindInfo28 info28; const char *nc_dn = NULL; DATA_BLOB session_key; uint32_t level = 8; bool single = false; uint32_t level_out = 0; union drsuapi_DsGetNCChangesRequest req; union drsuapi_DsGetNCChangesCtr ctr; struct drsuapi_DsReplicaObjectIdentifier nc; struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL; struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL; uint32_t out_level = 0; int y; uint32_t supported_extensions = 0; uint32_t replica_flags = DRSUAPI_DRS_WRIT_REP | DRSUAPI_DRS_INIT_SYNC | DRSUAPI_DRS_PER_SYNC | DRSUAPI_DRS_GET_ANC | DRSUAPI_DRS_NEVER_SYNCED; if (argc > 3) { printf("usage: %s [naming_context_or_object_dn [single]]\n", argv[0]); return WERR_OK; } if (argc >= 2) { nc_dn = argv[1]; } if (argc == 3) { if (strequal(argv[2], "single")) { single = true; } else { printf("warning: ignoring unknown argument '%s'\n", argv[2]); } } ZERO_STRUCT(info28); ZERO_STRUCT(req); GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid); info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT; info28.site_guid = GUID_zero(); info28.pid = 0; info28.repl_epoch = 0; bind_info.length = 28; bind_info.info.info28 = info28; status = dcerpc_drsuapi_DsBind(b, mem_ctx, &bind_guid, &bind_info, &bind_handle, &werr); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } if (!W_ERROR_IS_OK(werr)) { return werr; } if (bind_info.length == 24) { supported_extensions = bind_info.info.info24.supported_extensions; } else if (bind_info.length == 28) { supported_extensions = bind_info.info.info28.supported_extensions; } else if (bind_info.length == 32) { supported_extensions = bind_info.info.info32.supported_extensions; } else if (bind_info.length == 48) { supported_extensions = bind_info.info.info48.supported_extensions; } else if (bind_info.length == 52) { supported_extensions = bind_info.info.info52.supported_extensions; } if (!nc_dn) { union drsuapi_DsNameCtr crack_ctr; const char *name; name = talloc_asprintf(mem_ctx, "%s\\", lp_workgroup()); W_ERROR_HAVE_NO_MEMORY(name); werr = cracknames(cli, mem_ctx, &bind_handle, DRSUAPI_DS_NAME_FORMAT_UNKNOWN, DRSUAPI_DS_NAME_FORMAT_FQDN_1779, 1, &name, &crack_ctr); if (!W_ERROR_IS_OK(werr)) { return werr; } if (crack_ctr.ctr1->count != 1) { return WERR_NO_SUCH_DOMAIN; } if (crack_ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { return WERR_NO_SUCH_DOMAIN; } nc_dn = talloc_strdup(mem_ctx, crack_ctr.ctr1->array[0].result_name); W_ERROR_HAVE_NO_MEMORY(nc_dn); printf("using: %s\n", nc_dn); } nc.dn = nc_dn; nc.guid = GUID_zero(); nc.sid = (struct dom_sid) {0}; if (supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) { level = 8; req.req8.naming_context = &nc; req.req8.replica_flags = replica_flags; req.req8.max_object_count = 402; req.req8.max_ndr_size = 402116; if (single) { req.req8.extended_op = DRSUAPI_EXOP_REPL_OBJ; } } else { level = 5; req.req5.naming_context = &nc; req.req5.replica_flags = replica_flags; req.req5.max_object_count = 402; req.req5.max_ndr_size = 402116; if (single) { req.req5.extended_op = DRSUAPI_EXOP_REPL_OBJ; } } for (y=0; ;y++) { if (level == 8) { DEBUG(1,("start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",y, (long long)req.req8.highwatermark.tmp_highest_usn, (long long)req.req8.highwatermark.highest_usn)); } status = dcerpc_drsuapi_DsGetNCChanges(b, mem_ctx, &bind_handle, level, &req, &level_out, &ctr, &werr); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); printf("Failed to get NC Changes: %s", get_friendly_nt_error_msg(status)); goto out; } if (!W_ERROR_IS_OK(werr)) { printf("Failed to get NC Changes: %s", get_friendly_werror_msg(werr)); goto out; } if (level_out == 1) { out_level = 1; ctr1 = &ctr.ctr1; } else if (level_out == 2 && ctr.ctr2.mszip1.ts) { out_level = 1; ctr1 = &ctr.ctr2.mszip1.ts->ctr1; } status = cli_get_session_key(mem_ctx, cli, &session_key); if (!NT_STATUS_IS_OK(status)) { printf("Failed to get Session Key: %s", nt_errstr(status)); return ntstatus_to_werror(status); } if (out_level == 1) { DEBUG(1,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y, (long long)ctr1->new_highwatermark.tmp_highest_usn, (long long)ctr1->new_highwatermark.highest_usn)); #if 0 libnet_dssync_decrypt_attributes(mem_ctx, &session_key, ctr1->first_object); #endif if (ctr1->more_data) { req.req5.highwatermark = ctr1->new_highwatermark; continue; } } if (level_out == 6) { out_level = 6; ctr6 = &ctr.ctr6; } else if (level_out == 7 && ctr.ctr7.level == 6 && ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP && ctr.ctr7.ctr.mszip6.ts) { out_level = 6; ctr6 = &ctr.ctr7.ctr.mszip6.ts->ctr6; } else if (level_out == 7 && ctr.ctr7.level == 6 && ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_XPRESS && ctr.ctr7.ctr.xpress6.ts) { out_level = 6; ctr6 = &ctr.ctr7.ctr.xpress6.ts->ctr6; } if (out_level == 6) { DEBUG(1,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y, (long long)ctr6->new_highwatermark.tmp_highest_usn, (long long)ctr6->new_highwatermark.highest_usn)); #if 0 libnet_dssync_decrypt_attributes(mem_ctx, &session_key, ctr6->first_object); #endif if (ctr6->more_data) { req.req8.highwatermark = ctr6->new_highwatermark; continue; } } break; } out: return werr; } /* List of commands exported by this module */ struct cmd_set drsuapi_commands[] = { { "DRSUAPI" }, { "dscracknames", RPC_RTYPE_WERROR, NULL, cmd_drsuapi_cracknames, &ndr_table_drsuapi, NULL, "Crack Name", "" }, { "dsgetdcinfo", RPC_RTYPE_WERROR, NULL, cmd_drsuapi_getdcinfo, &ndr_table_drsuapi, NULL, "Get Domain Controller Info", "" }, { "dsgetncchanges", RPC_RTYPE_WERROR, NULL, cmd_drsuapi_getncchanges, &ndr_table_drsuapi, NULL, "Get NC Changes", "" }, { "dswriteaccountspn", RPC_RTYPE_WERROR, NULL, cmd_drsuapi_writeaccountspn, &ndr_table_drsuapi, NULL, "Write Account SPN", "" }, { NULL } };
/* wkssvc_NetWkstaGetInfo */ static WERROR wkssvc_NetWkstaGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct wkssvc_NetWkstaGetInfo *r) { struct dcesrv_context *dce_ctx = dce_call->conn->dce_ctx; ZERO_STRUCT(r->out); r->out.info = talloc_zero(mem_ctx, union wkssvc_NetWkstaInfo); W_ERROR_HAVE_NO_MEMORY(r->out.info); /* NOTE: win2k3 ignores r->in.server_name completly so we do --metze */ switch(r->in.level) { case 100: { struct wkssvc_NetWkstaInfo100 *info100; info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100); W_ERROR_HAVE_NO_MEMORY(info100); info100->platform_id = dcesrv_common_get_platform_id(mem_ctx, dce_ctx); info100->server_name = dcesrv_common_get_server_name(mem_ctx, dce_ctx, NULL); W_ERROR_HAVE_NO_MEMORY(info100->server_name); info100->domain_name = dcesrv_common_get_domain_name(mem_ctx, dce_ctx); W_ERROR_HAVE_NO_MEMORY(info100->domain_name); info100->version_major = dcesrv_common_get_version_major(mem_ctx, dce_ctx); info100->version_minor = dcesrv_common_get_version_minor(mem_ctx, dce_ctx); r->out.info->info100 = info100; return WERR_OK; } case 101: { struct wkssvc_NetWkstaInfo101 *info101; info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101); W_ERROR_HAVE_NO_MEMORY(info101); info101->platform_id = dcesrv_common_get_platform_id(mem_ctx, dce_ctx); info101->server_name = dcesrv_common_get_server_name(mem_ctx, dce_ctx, NULL); W_ERROR_HAVE_NO_MEMORY(info101->server_name); info101->domain_name = dcesrv_common_get_domain_name(mem_ctx, dce_ctx); W_ERROR_HAVE_NO_MEMORY(info101->domain_name); info101->version_major = dcesrv_common_get_version_major(mem_ctx, dce_ctx); info101->version_minor = dcesrv_common_get_version_minor(mem_ctx, dce_ctx); info101->lan_root = dcesrv_common_get_lan_root(mem_ctx, dce_ctx); r->out.info->info101 = info101; return WERR_OK; } case 102: { return WERR_ACCESS_DENIED; } case 502: { return WERR_ACCESS_DENIED; } default: return WERR_UNKNOWN_LEVEL; } return WERR_UNKNOWN_LEVEL; }
/* drsuapi_DsGetDomainControllerInfo */ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx, struct drsuapi_DsGetDomainControllerInfo *r) { struct ldb_dn *sites_dn; struct ldb_result *res; const char *attrs_account_1[] = { "cn", "dnsHostName", NULL }; const char *attrs_account_2[] = { "cn", "dnsHostName", "objectGUID", NULL }; const char *attrs_none[] = { NULL }; const char *attrs_site[] = { "objectGUID", NULL }; const char *attrs_ntds[] = { "options", "objectGUID", NULL }; const char *attrs_1[] = { "serverReference", "cn", "dnsHostName", NULL }; const char *attrs_2[] = { "serverReference", "cn", "dnsHostName", "objectGUID", NULL }; const char **attrs; struct drsuapi_DsGetDCInfoCtr1 *ctr1; struct drsuapi_DsGetDCInfoCtr2 *ctr2; int ret, i; *r->out.level_out = r->in.req->req1.level; r->out.ctr = talloc(mem_ctx, union drsuapi_DsGetDCInfoCtr); W_ERROR_HAVE_NO_MEMORY(r->out.ctr); sites_dn = samdb_sites_dn(b_state->sam_ctx, mem_ctx); if (!sites_dn) { return WERR_DS_OBJ_NOT_FOUND; } switch (*r->out.level_out) { case -1: /* this level is not like the others */ return WERR_UNKNOWN_LEVEL; case 1: attrs = attrs_1; break; case 2: attrs = attrs_2; break; default: return WERR_UNKNOWN_LEVEL; } ret = ldb_search(b_state->sam_ctx, mem_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=server"); if (ret) { DEBUG(1, ("searching for servers in sites DN %s failed: %s\n", ldb_dn_get_linearized(sites_dn), ldb_errstring(b_state->sam_ctx))); return WERR_GENERAL_FAILURE; } switch (*r->out.level_out) { case 1: ctr1 = &r->out.ctr->ctr1; ctr1->count = res->count; ctr1->array = talloc_zero_array(mem_ctx, struct drsuapi_DsGetDCInfo1, res->count); for (i=0; i < res->count; i++) { struct ldb_dn *domain_dn; struct ldb_result *res_domain; struct ldb_result *res_account; struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn); struct ldb_dn *ref_dn = ldb_msg_find_attr_as_dn(b_state->sam_ctx, mem_ctx, res->msgs[i], "serverReference"); if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) { return WERR_NOMEM; } ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn, LDB_SCOPE_BASE, attrs_account_1, "objectClass=computer"); if (ret == LDB_SUCCESS && res_account->count == 1) { const char *errstr; ctr1->array[i].dns_name = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL); ctr1->array[i].netbios_name = ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL); ctr1->array[i].computer_dn = ldb_dn_get_linearized(res_account->msgs[0]->dn); /* Determine if this is the PDC */ ret = samdb_search_for_parent_domain(b_state->sam_ctx, mem_ctx, res_account->msgs[0]->dn, &domain_dn, &errstr); if (ret == LDB_SUCCESS) { ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn, LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s", ldb_dn_get_linearized(ntds_dn)); if (ret) { return WERR_GENERAL_FAILURE; } if (res_domain->count == 1) { ctr1->array[i].is_pdc = true; } } } if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) { DEBUG(5, ("warning: searching for computer DN %s failed: %s\n", ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx))); } /* Look at server DN and extract site component */ ctr1->array[i].site_name = result_site_name(res->msgs[i]->dn); ctr1->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn); ctr1->array[i].is_enabled = true; } break; case 2: ctr2 = &r->out.ctr->ctr2; ctr2->count = res->count; ctr2->array = talloc_zero_array(mem_ctx, struct drsuapi_DsGetDCInfo2, res->count); for (i=0; i < res->count; i++) { struct ldb_dn *domain_dn; struct ldb_result *res_domain; struct ldb_result *res_account; struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn); struct ldb_result *res_ntds; struct ldb_dn *site_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn); struct ldb_result *res_site; struct ldb_dn *ref_dn = ldb_msg_find_attr_as_dn(b_state->sam_ctx, mem_ctx, res->msgs[i], "serverReference"); if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) { return WERR_NOMEM; } /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */ if (!site_dn || !ldb_dn_remove_child_components(site_dn, 2)) { return WERR_NOMEM; } ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_ntds, ntds_dn, LDB_SCOPE_BASE, attrs_ntds, "objectClass=nTDSDSA"); if (ret == LDB_SUCCESS && res_ntds->count == 1) { ctr2->array[i].is_gc = (ldb_msg_find_attr_as_int(res_ntds->msgs[0], "options", 0) == 1); ctr2->array[i].ntds_guid = samdb_result_guid(res_ntds->msgs[0], "objectGUID"); ctr2->array[i].ntds_dn = ldb_dn_get_linearized(res_ntds->msgs[0]->dn); } if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) { DEBUG(5, ("warning: searching for NTDS DN %s failed: %s\n", ldb_dn_get_linearized(ntds_dn), ldb_errstring(b_state->sam_ctx))); } ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_site, site_dn, LDB_SCOPE_BASE, attrs_site, "objectClass=site"); if (ret == LDB_SUCCESS && res_site->count == 1) { ctr2->array[i].site_guid = samdb_result_guid(res_site->msgs[0], "objectGUID"); ctr2->array[i].site_dn = ldb_dn_get_linearized(res_site->msgs[0]->dn); } if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) { DEBUG(5, ("warning: searching for site DN %s failed: %s\n", ldb_dn_get_linearized(site_dn), ldb_errstring(b_state->sam_ctx))); } ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn, LDB_SCOPE_BASE, attrs_account_2, "objectClass=computer"); if (ret == LDB_SUCCESS && res_account->count == 1) { const char *errstr; ctr2->array[i].dns_name = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL); ctr2->array[i].netbios_name = ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL); ctr2->array[i].computer_dn = ldb_dn_get_linearized(res_account->msgs[0]->dn); ctr2->array[i].computer_guid = samdb_result_guid(res_account->msgs[0], "objectGUID"); /* Determine if this is the PDC */ ret = samdb_search_for_parent_domain(b_state->sam_ctx, mem_ctx, res_account->msgs[0]->dn, &domain_dn, &errstr); if (ret == LDB_SUCCESS) { ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn, LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s", ldb_dn_get_linearized(ntds_dn)); if (ret == LDB_SUCCESS && res_domain->count == 1) { ctr2->array[i].is_pdc = true; } if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) { DEBUG(5, ("warning: searching for domain DN %s failed: %s\n", ldb_dn_get_linearized(domain_dn), ldb_errstring(b_state->sam_ctx))); } } } if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) { DEBUG(5, ("warning: searching for computer account DN %s failed: %s\n", ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx))); } /* Look at server DN and extract site component */ ctr2->array[i].site_name = result_site_name(res->msgs[i]->dn); ctr2->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn); ctr2->array[i].server_guid = samdb_result_guid(res->msgs[i], "objectGUID"); ctr2->array[i].is_enabled = true; } break; } return WERR_OK; }
static WERROR drsuapi_encrypt_attribute_value(TALLOC_CTX *mem_ctx, const DATA_BLOB *gensec_skey, bool rid_crypt, uint32_t rid, DATA_BLOB *in, DATA_BLOB *out) { DATA_BLOB rid_crypt_out = data_blob(NULL, 0); DATA_BLOB confounder; MD5_CTX md5; uint8_t _enc_key[16]; DATA_BLOB enc_key; DATA_BLOB enc_buffer; uint32_t crc32_calc; /* * users with rid == 0 should not exist */ if (rid_crypt && rid == 0) { return WERR_DS_DRA_INVALID_PARAMETER; } /* * The following rid_crypt obfuscation isn't session specific * and not really needed here, because we allways know the rid of the * user account. * * some attributes with this 'additional encryption' include * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory * * But for the rest of samba it's easier when we remove this static * obfuscation here */ if (rid_crypt) { uint32_t i, num_hashes; rid_crypt_out = data_blob_talloc(mem_ctx, in->data, in->length); W_ERROR_HAVE_NO_MEMORY(rid_crypt_out.data); if ((rid_crypt_out.length % 16) != 0) { return WERR_DS_DRA_INVALID_PARAMETER; } num_hashes = rid_crypt_out.length / 16; for (i = 0; i < num_hashes; i++) { uint32_t offset = i * 16; sam_rid_crypt(rid, in->data + offset, rid_crypt_out.data + offset, 1); } in = &rid_crypt_out; } /* * the first 16 bytes at the beginning are the confounder * followed by the 4 byte crc32 checksum */ enc_buffer = data_blob_talloc(mem_ctx, NULL, in->length+20); if (!enc_buffer.data) { talloc_free(rid_crypt_out.data); return WERR_NOMEM; }; confounder = data_blob_const(enc_buffer.data, 16); generate_random_buffer(confounder.data, confounder.length); /* * build the encryption key md5 over the session key followed * by the confounder * * here the gensec session key is used and * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key! */ enc_key = data_blob_const(_enc_key, sizeof(_enc_key)); MD5Init(&md5); MD5Update(&md5, gensec_skey->data, gensec_skey->length); MD5Update(&md5, confounder.data, confounder.length); MD5Final(enc_key.data, &md5); /* * the first 4 byte are the crc32 checksum * of the remaining bytes */ crc32_calc = crc32_calc_buffer(in->data, in->length); SIVAL(enc_buffer.data, 16, crc32_calc); /* * copy the plain buffer part and * encrypt it using the created encryption key using arcfour */ memcpy(enc_buffer.data+20, in->data, in->length); talloc_free(rid_crypt_out.data); arcfour_crypt_blob(enc_buffer.data+16, enc_buffer.length-16, &enc_key); *out = enc_buffer; return WERR_OK; }