summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/samdb.c1
-rw-r--r--source4/provision.ldif7
-rw-r--r--source4/rpc_server/samr/dcesrv_samr.c211
3 files changed, 214 insertions, 5 deletions
diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c
index 2fcc71a8a9..934e6c240f 100644
--- a/source4/dsdb/samdb/samdb.c
+++ b/source4/dsdb/samdb/samdb.c
@@ -567,6 +567,7 @@ int samdb_copy_template(void *ctx, TALLOC_CTX *mem_ctx,
(strcasecmp((char *)el->values[j].data, "Template") == 0 ||
strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 ||
+ strcasecmp((char *)el->values[j].data, "foreignSecurityTemplate") == 0 ||
strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0)) {
continue;
}
diff --git a/source4/provision.ldif b/source4/provision.ldif
index 51d3db3e3a..b454552eb4 100644
--- a/source4/provision.ldif
+++ b/source4/provision.ldif
@@ -935,3 +935,10 @@ name: TemplateAlias
instanceType: 4
groupType: 0x80000002
sAMAccountType: 0x10000000
+
+dn: CN=TemplateForeignSecurityPrincipal,CN=Templates,${BASEDN}
+objectClass: top
+objectClass: Template
+objectClass: foreignSecurityPrincipalTemplate
+cn: TemplateForeignSecurityPrincipal
+name: TemplateForeignSecurityPrincipal
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 59f5ec9d8a..770f1b2064 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -904,7 +904,7 @@ static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_C
return NT_STATUS_NO_MEMORY;
}
- /* add core elements to the ldb_message for the user */
+ /* add core elements to the ldb_message for the alias */
msg.dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", aliasname,
d_state->domain_dn);
if (!msg.dn) {
@@ -1787,7 +1787,126 @@ static NTSTATUS samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_C
static NTSTATUS samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_AddAliasMember *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct dcesrv_handle *h;
+ struct samr_account_state *a_state;
+ struct samr_domain_state *d_state;
+ const char *sidstr;
+ struct ldb_message mod;
+ struct ldb_message **msgs;
+ const char * const attrs[2] = { "dn", NULL };
+ const char *memberdn = NULL;
+ int ret;
+
+ DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
+
+ a_state = h->data;
+ d_state = a_state->domain_state;
+
+ sidstr = dom_sid_string(mem_ctx, r->in.sid);
+ if (sidstr == NULL)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ ret = samdb_search(d_state->sam_ctx, mem_ctx, NULL,
+ &msgs, attrs, "(objectsid=%s)", sidstr);
+
+ if (ret == 1) {
+ memberdn = ldb_msg_find_string(msgs[0], "dn", NULL);
+ } else if (ret > 1) {
+ DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ } else if (ret == 0) {
+ struct ldb_message msg;
+ struct GUID guid;
+ const char *guidstr, *basedn;
+
+ /* We might have to create a ForeignSecurityPrincipal, but
+ * only if it's not our own domain */
+ if (dom_sid_in_domain(dom_sid_parse_talloc(mem_ctx,
+ d_state->domain_sid),
+ r->in.sid))
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+ ZERO_STRUCT(msg);
+
+ /* pull in all the template attributes */
+ ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
+ "(&(name=TemplateForeignSecurityPrincipal)"
+ "(objectclass=foreignSecurityPrincipalTemplate))");
+ if (ret != 0) {
+ DEBUG(0,("Failed to load "
+ "TemplateForeignSecurityPrincipal "
+ "from samdb\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ /* a new GUID */
+ guid = GUID_random();
+ guidstr = GUID_string(mem_ctx, &guid);
+ if (!guidstr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* TODO: Hmmm. This feels wrong. How do I find the base dn to
+ * put the ForeignSecurityPrincipals? d_state->domain_dn does
+ * not work, this is wrong for the Builtin domain, there's no
+ * cn=For...,cn=Builtin,dc={BASEDN}. -- vl
+ */
+
+ basedn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
+ "dn",
+ "(&(objectClass=container)"
+ "(cn=ForeignSecurityPrincipals))");
+
+ if (basedn == NULL) {
+ DEBUG(0, ("Failed to find DN for "
+ "ForeignSecurityPrincipal container\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ /* add core elements to the ldb_message for the alias */
+ msg.dn = talloc_asprintf(mem_ctx, "CN=%s,%s", sidstr, basedn);
+ if (msg.dn == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ memberdn = msg.dn;
+
+ samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
+ "name", sidstr);
+ samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
+ "objectClass",
+ "foreignSecurityPrincipal");
+ samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
+ "objectSid", sidstr);
+ samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
+ "objectGUID", guidstr);
+
+ /* create the alias */
+ ret = samdb_add(d_state->sam_ctx, mem_ctx, &msg);
+ if (ret != 0) {
+ DEBUG(0,("Failed to create foreignSecurityPrincipal "
+ "record %s\n", msg.dn));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ } else {
+ DEBUG(0, ("samdb_search returned %d\n", ret));
+ }
+
+ if (memberdn == NULL) {
+ DEBUG(0, ("Could not find memberdn\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ ZERO_STRUCT(mod);
+ mod.dn = talloc_reference(mem_ctx, a_state->account_dn);
+
+ if (samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, &mod, "member",
+ memberdn) != 0)
+ return NT_STATUS_UNSUCCESSFUL;
+
+ if (samdb_modify(a_state->sam_ctx, mem_ctx, &mod) != 0)
+ return NT_STATUS_UNSUCCESSFUL;
+
+ return NT_STATUS_OK;
}
@@ -1797,7 +1916,39 @@ static NTSTATUS samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_C
static NTSTATUS samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_DeleteAliasMember *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct dcesrv_handle *h;
+ struct samr_account_state *a_state;
+ struct samr_domain_state *d_state;
+ const char *sidstr;
+ struct ldb_message mod;
+ const char *memberdn;
+
+ DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
+
+ a_state = h->data;
+ d_state = a_state->domain_state;
+
+ sidstr = dom_sid_string(mem_ctx, r->in.sid);
+ if (sidstr == NULL)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
+ "dn", "(objectSid=%s)", sidstr);
+
+ if (memberdn == NULL)
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+ ZERO_STRUCT(mod);
+ mod.dn = talloc_reference(mem_ctx, a_state->account_dn);
+
+ if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, &mod, "member",
+ memberdn) != 0)
+ return NT_STATUS_UNSUCCESSFUL;
+
+ if (samdb_modify(a_state->sam_ctx, mem_ctx, &mod) != 0)
+ return NT_STATUS_UNSUCCESSFUL;
+
+ return NT_STATUS_OK;
}
@@ -1807,9 +1958,59 @@ static NTSTATUS samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLO
static NTSTATUS samr_GetMembersInAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_GetMembersInAlias *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
+ struct dcesrv_handle *h;
+ struct samr_account_state *a_state;
+ struct samr_domain_state *d_state;
+ struct ldb_message **msgs;
+ struct lsa_SidPtr *sids;
+ struct ldb_message_element *el;
+ const char * const attrs[2] = { "member", NULL};
+ int ret;
+
+ DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
+
+ a_state = h->data;
+ d_state = a_state->domain_state;
+
+ ret = samdb_search(d_state->sam_ctx, mem_ctx, NULL, &msgs, attrs,
+ "dn=%s", a_state->account_dn);
+ if (ret != 1)
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+
+ el = ldb_msg_find_element(msgs[0], "member");
+
+ if (el != NULL) {
+ int i;
+
+ sids = talloc_array_p(mem_ctx, struct lsa_SidPtr,
+ el->num_values);
+
+ if (sids == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ for (i=0; i<el->num_values; i++) {
+ struct ldb_message **msgs2;
+ const char * const attrs2[2] = { "objectSid", NULL };
+ ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL,
+ &msgs2, attrs2, "dn=%s",
+ (char *)el->values[i].data);
+ if (ret != 1)
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+
+ sids[i].sid = samdb_result_dom_sid(mem_ctx, msgs2[0],
+ "objectSid");
+
+ if (sids[i].sid == NULL)
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ }
+
+ r->out.sids->num_sids = el->num_values;
+ r->out.sids->sids = sids;
+
+ return NT_STATUS_OK;
+}
/*
samr_OpenUser