This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "librpc/gen_ndr/ndr_drsuapi.h"
#include "rpc_server/dcerpc_server.h"
#include "rpc_server/common/common.h"
-#include "rpc_server/drsuapi/dcesrv_drsuapi.h"
#include "dsdb/samdb/samdb.h"
-#include "lib/ldb/include/ldb_errors.h"
+#include "rpc_server/drsuapi/dcesrv_drsuapi.h"
+#include "libcli/security/security.h"
+#include "auth/auth.h"
/*
drsuapi_DsBind
struct ldb_result *ntds_res;
struct ldb_dn *ntds_dn;
static const char *ntds_attrs[] = { "ms-DS-ReplicationEpoch", NULL };
- uint32_t u1;
+ 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(2,(__location__ ": doing DsBind with system_session\n"));
+ auth_info = system_session(b_state, 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->conn->auth_state.session_info);
+ 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;
}
server_site_dn = samdb_server_site_dn(b_state->sam_ctx, mem_ctx);
W_ERROR_HAVE_NO_MEMORY(server_site_dn);
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &site_res,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &site_res,
server_site_dn, LDB_SCOPE_BASE, site_attrs,
"(objectClass=*)");
if (ret != LDB_SUCCESS) {
ntds_dn = samdb_ntds_settings_dn(b_state->sam_ctx);
W_ERROR_HAVE_NO_MEMORY(ntds_dn);
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &ntds_res,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &ntds_res,
ntds_dn, LDB_SCOPE_BASE, ntds_attrs,
"(objectClass=*)");
if (ret != LDB_SUCCESS) {
repl_epoch = samdb_result_uint(ntds_res->msgs[0], "ms-DS-ReplicationEpoch", 0);
/*
- * TODO: find out what this is...
+ * 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.
*/
- u1 = 0;
+ pid = 0;
/*
* store the clients bind_guid
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.u1 = info24->u1;
+ b_state->remote_info28.pid = info24->pid;
b_state->remote_info28.repl_epoch = 0;
break;
}
b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
#endif
b_state->local_info28.site_guid = site_guid;
- b_state->local_info28.u1 = u1;
- b_state->local_info28.repl_epoch = repl_epoch;
+ b_state->local_info28.pid = pid;
+ b_state->local_info28.repl_epoch = repl_epoch;
/*
* allocate the return bind_info
drsuapi_DsReplicaSync
*/
static WERROR dcesrv_drsuapi_DsReplicaSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct drsuapi_DsReplicaSync *r)
+ struct drsuapi_DsReplicaSync *r)
{
- /* TODO: implement this call correct!
- * for now we just say yes,
- * because we have no output parameter
- */
- return WERR_OK;
-}
-
+ WERROR status;
-/*
- drsuapi_DsGetNCChanges
-*/
-static WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct drsuapi_DsGetNCChanges *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
+ status = drs_security_level_check(dce_call, "DsReplicaSync");
+ if (!W_ERROR_IS_OK(status)) {
+ return status;
+ }
+ dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSREPLICASYNC,
+ &ndr_table_drsuapi,
+ "dreplsrv", "DsReplicaSync");
-/*
- drsuapi_DsReplicaUpdateRefs
-*/
-static WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct drsuapi_DsReplicaUpdateRefs *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ return WERR_OK;
}
/*
- DRSUAPI_REPLICA_ADD
+ drsuapi_DsReplicaAdd
*/
-static WERROR dcesrv_DRSUAPI_REPLICA_ADD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct DRSUAPI_REPLICA_ADD *r)
+static WERROR dcesrv_drsuapi_DsReplicaAdd(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsReplicaAdd *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
- DRSUAPI_REPLICA_DEL
+ drsuapi_DsReplicaDel
*/
-static WERROR dcesrv_DRSUAPI_REPLICA_DEL(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct DRSUAPI_REPLICA_DEL *r)
+static WERROR dcesrv_drsuapi_DsReplicaDel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsReplicaDel *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
- DRSUAPI_REPLICA_MODIFY
+ drsuapi_DsReplicaModify
*/
-static WERROR dcesrv_DRSUAPI_REPLICA_MODIFY(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct DRSUAPI_REPLICA_MODIFY *r)
+static WERROR dcesrv_drsuapi_DsReplicaMod(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsReplicaMod *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
drsuapi_DsCrackNames
*/
-WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+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 = r->in.level;
- ZERO_STRUCT(r->out.ctr);
+ *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;
ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
W_ERROR_HAVE_NO_MEMORY(ctr1);
- count = r->in.req.req1.count;
+ 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,
+ 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;
+ r->out.ctr->ctr1 = ctr1;
return WERR_OK;
}
struct drsuapi_bind_state *b_state;
struct dcesrv_handle *h;
- r->out.level = r->in.level;
+ *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;
+ req = &r->in.req->req1;
count = req->count;
msg = ldb_msg_new(mem_ctx);
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;
+ r->out.res->res1.status = WERR_OK;
return WERR_OK;
}
/* Apply to database */
- ret = samdb_modify(b_state->sam_ctx, mem_ctx, msg);
+ 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;
+ r->out.res->res1.status = WERR_ACCESS_DENIED;
} else {
- r->out.res.res1.status = WERR_OK;
+ r->out.res->res1.status = WERR_OK;
}
return WERR_OK;
static WERROR dcesrv_drsuapi_DsRemoveDSServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct drsuapi_DsRemoveDSServer *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ 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;
}
}
/* Obtain the site name from a server DN */
-const char *result_site_name(struct ldb_dn *site_dn)
+static const char *result_site_name(struct ldb_dn *site_dn)
{
/* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
const struct ldb_val *val = ldb_dn_get_component_val(site_dn, 2);
int ret, i;
- r->out.level_out = r->in.req.req1.level;
+ *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) {
+ switch (*r->out.level_out) {
case -1:
/* this level is not like the others */
return WERR_UNKNOWN_LEVEL;
return WERR_UNKNOWN_LEVEL;
}
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE, attrs,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE, attrs,
"objectClass=server");
if (ret) {
return WERR_GENERAL_FAILURE;
}
- switch (r->out.level_out) {
+ switch (*r->out.level_out) {
case 1:
- ctr1 = &r->out.ctr.ctr1;
+ ctr1 = &r->out.ctr->ctr1;
ctr1->count = res->count;
ctr1->array = talloc_zero_array(mem_ctx,
struct drsuapi_DsGetDCInfo1,
struct ldb_dn *domain_dn;
struct ldb_result *res_domain;
struct ldb_result *res_account;
- struct ldb_dn *ntds_dn = ldb_dn_copy(b_state->sam_ctx, res->msgs[i]->dn);
+ 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,
return WERR_NOMEM;
}
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
+ 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_dn_get_linearized(res_account->msgs[0]->dn);
/* Determine if this is the PDC */
- domain_dn = samdb_search_for_parent_domain(b_state->sam_ctx,
- mem_ctx, res_account->msgs[0]->dn);
+ ret = samdb_search_for_parent_domain(b_state->sam_ctx,
+ mem_ctx, res_account->msgs[0]->dn,
+ &domain_dn, &errstr);
- if (domain_dn) {
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
+ 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;
+ ctr1->array[i].is_pdc = true;
}
}
}
ctr1->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn);
- ctr1->array[i].is_enabled = True;
+ ctr1->array[i].is_enabled = true;
}
break;
case 2:
- ctr2 = &r->out.ctr.ctr2;
+ ctr2 = &r->out.ctr->ctr2;
ctr2->count = res->count;
ctr2->array = talloc_zero_array(mem_ctx,
struct drsuapi_DsGetDCInfo2,
struct ldb_dn *domain_dn;
struct ldb_result *res_domain;
struct ldb_result *res_account;
- struct ldb_dn *ntds_dn = ldb_dn_copy(b_state->sam_ctx, res->msgs[i]->dn);
+ 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(b_state->sam_ctx, res->msgs[i]->dn);
+ 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,
return WERR_NOMEM;
}
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_ntds, ntds_dn,
+ 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_dn_get_linearized(ntds_dn), ldb_errstring(b_state->sam_ctx)));
}
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_site, site_dn,
+ 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
ldb_dn_get_linearized(site_dn), ldb_errstring(b_state->sam_ctx)));
}
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
+ 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
= samdb_result_guid(res_account->msgs[0], "objectGUID");
/* Determine if this is the PDC */
- domain_dn = samdb_search_for_parent_domain(b_state->sam_ctx,
- mem_ctx, res_account->msgs[0]->dn);
+ ret = samdb_search_for_parent_domain(b_state->sam_ctx,
+ mem_ctx, res_account->msgs[0]->dn,
+ &domain_dn, &errstr);
- if (domain_dn) {
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
+ 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;
+ 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",
ctr2->array[i].server_guid
= samdb_result_guid(res->msgs[i], "objectGUID");
- ctr2->array[i].is_enabled = True;
+ ctr2->array[i].is_enabled = true;
}
break;
}
-/*
- drsuapi_DsAddEntry
-*/
-static WERROR dcesrv_drsuapi_DsAddEntry(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct drsuapi_DsAddEntry *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
/*
- DRSUAPI_EXECUTE_KCC
+ drsuapi_DsExecuteKCC
*/
-static WERROR dcesrv_DRSUAPI_EXECUTE_KCC(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct DRSUAPI_EXECUTE_KCC *r)
+static WERROR dcesrv_drsuapi_DsExecuteKCC(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsExecuteKCC *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}