/* spoolss_EnumForms */ static WERROR dcesrv_spoolss_EnumForms(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_EnumForms *r) { struct ntptr_GenericHandle *handle; struct dcesrv_handle *h; WERROR status; struct smb_iconv_convenience *ic = lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx); DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); handle = talloc_get_type(h->data, struct ntptr_GenericHandle); if (!handle) return WERR_BADFID; switch (handle->type) { case NTPTR_HANDLE_SERVER: status = ntptr_EnumPrintServerForms(handle, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); break; case NTPTR_HANDLE_PRINTER: status = ntptr_EnumPrinterForms(handle, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); break; default: return WERR_FOOBAR; } *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumForms, ic, *r->out.info, r->in.level, *r->out.count); *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL); *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); }
/* spoolss_GetForm */ static WERROR dcesrv_spoolss_GetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_GetForm *r) { struct ntptr_GenericHandle *handle; struct dcesrv_handle *h; WERROR status; struct smb_iconv_convenience *ic = lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx); DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); handle = talloc_get_type(h->data, struct ntptr_GenericHandle); if (!handle) return WERR_BADFID; switch (handle->type) { case NTPTR_HANDLE_SERVER: /* * stupid, but w2k3 returns WERR_BADFID here? */ return WERR_BADFID; case NTPTR_HANDLE_PRINTER: status = ntptr_GetPrinterForm(handle, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); break; default: return WERR_FOOBAR; } *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, ic, r->out.info, r->in.level); r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); }
/* spoolss_SetForm */ static WERROR dcesrv_spoolss_SetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_SetForm *r) { struct ntptr_GenericHandle *handle; struct dcesrv_handle *h; WERROR status; DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); handle = talloc_get_type(h->data, struct ntptr_GenericHandle); if (!handle) return WERR_BADFID; switch (handle->type) { case NTPTR_HANDLE_SERVER: status = ntptr_SetPrintServerForm(handle, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); break; case NTPTR_HANDLE_PRINTER: status = ntptr_SetPrinterForm(handle, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); break; default: return WERR_FOOBAR; } return WERR_OK; }
/* spoolss_XcvData */ static WERROR dcesrv_spoolss_XcvData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_XcvData *r) { struct ntptr_GenericHandle *handle; struct dcesrv_handle *h; WERROR status; DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); handle = talloc_get_type(h->data, struct ntptr_GenericHandle); switch (handle->type) { case NTPTR_HANDLE_SERVER: status = ntptr_XcvDataPrintServer(handle, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); break; case NTPTR_HANDLE_PRINTER: status = ntptr_XcvDataPrinter(handle, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); break; case NTPTR_HANDLE_PORT: status = ntptr_XcvDataPort(handle, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); break; case NTPTR_HANDLE_MONITOR: status = ntptr_XcvDataMonitor(handle, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); break; default: return WERR_FOOBAR; } /* TODO: handle the buffer sizes here! */ return WERR_OK; }
/* drsuapi_DsRemoveDSServer */ static WERROR dcesrv_drsuapi_DsRemoveDSServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsRemoveDSServer *r) { struct drsuapi_bind_state *b_state; struct dcesrv_handle *h; struct ldb_dn *ntds_dn; int ret; bool ok; WERROR status; ZERO_STRUCT(r->out.res); *r->out.level_out = 1; status = drs_security_level_check(dce_call, "DsRemoveDSServer"); if (!W_ERROR_IS_OK(status)) { return status; } DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); b_state = h->data; switch (r->in.level) { case 1: ntds_dn = ldb_dn_new(mem_ctx, b_state->sam_ctx, r->in.req->req1.server_dn); W_ERROR_HAVE_NO_MEMORY(ntds_dn); ok = ldb_dn_validate(ntds_dn); if (!ok) { return WERR_FOOBAR; } /* TODO: it's likely that we need more checks here */ ok = ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings"); if (!ok) { return WERR_FOOBAR; } if (r->in.req->req1.commit) { ret = ldb_delete(b_state->sam_ctx, ntds_dn); if (ret != LDB_SUCCESS) { return WERR_FOOBAR; } } return WERR_OK; default: break; } return WERR_FOOBAR; }
/* spoolss_ReplyClosePrinter */ static WERROR dcesrv_spoolss_ReplyClosePrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_ReplyClosePrinter *r) { struct dcesrv_handle *handle; DCESRV_PULL_HANDLE_WERR(handle, r->in.handle, SPOOLSS_NOTIFY); talloc_free(handle); ZERO_STRUCTP(r->out.handle); return WERR_OK; }
/* drsuapi_DsCrackNames */ static WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsCrackNames *r) { WERROR status; 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.ctr = talloc_zero(mem_ctx, union drsuapi_DsNameCtr); W_ERROR_HAVE_NO_MEMORY(r->out.ctr); switch (r->in.level) { case 1: { struct drsuapi_DsNameCtr1 *ctr1; struct drsuapi_DsNameInfo1 *names; int count; int i; ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1); W_ERROR_HAVE_NO_MEMORY(ctr1); count = r->in.req->req1.count; names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count); W_ERROR_HAVE_NO_MEMORY(names); for (i=0; i < count; i++) { status = DsCrackNameOneName(b_state->sam_ctx, mem_ctx, r->in.req->req1.format_flags, r->in.req->req1.format_offered, r->in.req->req1.format_desired, r->in.req->req1.names[i].str, &names[i]); if (!W_ERROR_IS_OK(status)) { return status; } } ctr1->count = count; ctr1->array = names; r->out.ctr->ctr1 = ctr1; return WERR_OK; } } return WERR_UNKNOWN_LEVEL; }
/* drsuapi_DsGetDomainControllerInfo */ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsGetDomainControllerInfo *r) { struct dcesrv_handle *h; struct drsuapi_bind_state *b_state; DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); b_state = h->data; switch (r->in.level) { case 1: return dcesrv_drsuapi_DsGetDomainControllerInfo_1(b_state, mem_ctx, r); } return WERR_UNKNOWN_LEVEL; }
/* drsuapi_DsUnbind */ static WERROR dcesrv_drsuapi_DsUnbind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsUnbind *r) { struct dcesrv_handle *h; *r->out.bind_handle = *r->in.bind_handle; DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); talloc_free(h); ZERO_STRUCTP(r->out.bind_handle); return WERR_OK; }
/* spoolss_ClosePrinter */ static WERROR dcesrv_spoolss_ClosePrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_ClosePrinter *r) { struct dcesrv_handle *h; *r->out.handle = *r->in.handle; DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); talloc_free(h); ZERO_STRUCTP(r->out.handle); return WERR_OK; }
/* drsuapi_DsCrackNames */ static WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsCrackNames *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.ctr = talloc_zero(mem_ctx, union drsuapi_DsNameCtr); W_ERROR_HAVE_NO_MEMORY(r->out.ctr); switch (r->in.level) { case 1: { switch(r->in.req->req1.format_offered){ case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX: case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN: case DRSUAPI_DS_NAME_FORMAT_STRING_SID_NAME: case DRSUAPI_DS_NAME_FORMAT_ALT_SECURITY_IDENTITIES_NAME: case DRSUAPI_DS_NAME_FORMAT_MAP_SCHEMA_GUID: case DRSUAPI_DS_NAME_FORMAT_LIST_NCS: case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS: case DRSUAPI_DS_NAME_FORMAT_LIST_GLOBAL_CATALOG_SERVERS: case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_WITH_DCS_IN_SITE: case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_FOR_DOMAIN_IN_SITE: case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS_IN_SITE: case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_IN_SITE: case DRSUAPI_DS_NAME_FORMAT_LIST_SITES: case DRSUAPI_DS_NAME_FORMAT_UPN_AND_ALTSECID: case DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON: DEBUG(0, ("DsCrackNames: Unsupported operation requested: %X", r->in.req->req1.format_offered)); return WERR_OK; case DRSUAPI_DS_NAME_FORMAT_LIST_INFO_FOR_SERVER: return dcesrv_drsuapi_ListInfoServer(b_state->sam_ctx, mem_ctx, &r->in.req->req1, &r->out.ctr->ctr1); case DRSUAPI_DS_NAME_FORMAT_LIST_ROLES: return dcesrv_drsuapi_ListRoles(b_state->sam_ctx, mem_ctx, &r->in.req->req1, &r->out.ctr->ctr1); default:/* format_offered is in the enum drsuapi_DsNameFormat*/ return dcesrv_drsuapi_CrackNamesByNameFormat(b_state->sam_ctx, mem_ctx, &r->in.req->req1, &r->out.ctr->ctr1); } } } return WERR_UNKNOWN_LEVEL; }
/* spoolss_GetPrinterData */ static WERROR dcesrv_spoolss_GetPrinterData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_GetPrinterData *r) { struct ntptr_GenericHandle *handle; struct dcesrv_handle *h; WERROR status; struct smb_iconv_convenience *ic = lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx); DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); handle = talloc_get_type(h->data, struct ntptr_GenericHandle); if (!handle) return WERR_BADFID; r->out.type = talloc_zero(mem_ctx, enum winreg_Type); W_ERROR_HAVE_NO_MEMORY(r->out.type); r->out.needed = talloc_zero(mem_ctx, uint32_t); W_ERROR_HAVE_NO_MEMORY(r->out.needed); r->out.data = talloc_zero(mem_ctx, union spoolss_PrinterData); W_ERROR_HAVE_NO_MEMORY(r->out.data); switch (handle->type) { case NTPTR_HANDLE_SERVER: status = ntptr_GetPrintServerData(handle, mem_ctx, r); break; default: status = WERR_FOOBAR; break; } W_ERROR_NOT_OK_RETURN(status); *r->out.needed = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, ic, 0); *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE); r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA); }
/* 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; }
/* 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; uint32_t count; unsigned int i; int ret; unsigned spn_count=0; bool passed_checks = true; struct ldb_context *sam_ctx; 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; } /* construct mods */ for (i = 0; i < count; i++) { if (!writespn_check_spn(b_state, dce_call, msg->dn, req->spn_names[i].str)) { passed_checks = false; } ret = ldb_msg_add_string(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; } } if (passed_checks && b_state->sam_ctx_system) { sam_ctx = b_state->sam_ctx_system; } else { sam_ctx = b_state->sam_ctx; } /* Apply to database */ ret = dsdb_modify(sam_ctx, msg, DSDB_MODIFY_PERMISSIVE); if (ret != LDB_SUCCESS) { DEBUG(0,("Failed to modify SPNs on %s: %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(b_state->sam_ctx))); NDR_PRINT_IN_DEBUG( drsuapi_DsWriteAccountSpn, r); 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; }
/* drsuapi_DsWriteAccountSpn */ static 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; 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; } /* construct mods */ for (i = 0; i < count; i++) { samdb_msg_add_string(b_state->sam_ctx, msg, msg, "servicePrincipalName", req->spn_names[i].str); } 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 { r->out.res->res1.status = WERR_OK; } return WERR_OK; } } return WERR_UNKNOWN_LEVEL; }
/* drsuapi_DsAddEntry */ WERROR dcesrv_drsuapi_DsAddEntry(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsAddEntry *r) { WERROR status; struct drsuapi_bind_state *b_state; struct dcesrv_handle *h; uint32_t num = 0; struct drsuapi_DsReplicaObjectIdentifier2 *ids = NULL; int ret; const struct drsuapi_DsReplicaObjectListItem *first_object; if (DEBUGLVL(4)) { NDR_PRINT_FUNCTION_DEBUG(drsuapi_DsAddEntry, NDR_IN, r); } /* TODO: check which out level the client supports */ ZERO_STRUCTP(r->out.ctr); *r->out.level_out = 3; r->out.ctr->ctr3.err_ver = 1; r->out.ctr->ctr3.err_data = talloc_zero(mem_ctx, union drsuapi_DsAddEntry_ErrData); DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); b_state = h->data; status = drs_security_level_check(dce_call, "DsAddEntry", SECURITY_DOMAIN_CONTROLLER, NULL); if (!W_ERROR_IS_OK(status)) { return status; } switch (r->in.level) { case 2: ret = ldb_transaction_start(b_state->sam_ctx); if (ret != LDB_SUCCESS) { return WERR_DS_DRA_INTERNAL_ERROR; } first_object = &r->in.req->req2.first_object; status = dsdb_origin_objects_commit(b_state->sam_ctx, mem_ctx, first_object, &num, DSDB_REPL_FLAG_ADD_NCNAME, &ids); if (!W_ERROR_IS_OK(status)) { r->out.ctr->ctr3.err_data->v1.status = status; ldb_transaction_cancel(b_state->sam_ctx); DEBUG(0,(__location__ ": DsAddEntry failed - %s\n", win_errstr(status))); return status; } r->out.ctr->ctr3.count = num; r->out.ctr->ctr3.objects = ids; break; default: return WERR_FOOBAR; } /* if any of the added entries are nTDSDSA objects then we * need to add the SPNs to the machine account */ status = drsuapi_add_SPNs(b_state, dce_call, mem_ctx, first_object); if (!W_ERROR_IS_OK(status)) { r->out.ctr->ctr3.err_data->v1.status = status; ldb_transaction_cancel(b_state->sam_ctx); DEBUG(0,(__location__ ": DsAddEntry add SPNs failed - %s\n", win_errstr(status))); return status; } ret = ldb_transaction_commit(b_state->sam_ctx); if (ret != LDB_SUCCESS) { DEBUG(0,(__location__ ": DsAddEntry commit failed: %s\n", ldb_errstring(b_state->sam_ctx))); return WERR_DS_DRA_INTERNAL_ERROR; } return WERR_OK; }