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 "rpc_server/samr/dcesrv_samr.h"
#include "system/time.h"
#include "lib/ldb/include/ldb.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "dsdb/common/flags.h"
+#include "dsdb/samdb/samdb.h"
+#include "libcli/ldap/ldap_ndr.h"
+#include "libcli/security/security.h"
+#include "rpc_server/samr/proto.h"
+#include "util/util_ldb.h"
+#include "param/param.h"
+/* these query macros make samr_Query[User|Group]Info a bit easier to read */
+
+#define QUERY_STRING(msg, field, attr) \
+ r->out.info->field.string = samdb_result_string(msg, attr, "");
+#define QUERY_UINT(msg, field, attr) \
+ r->out.info->field = samdb_result_uint(msg, attr, 0);
+#define QUERY_RID(msg, field, attr) \
+ r->out.info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0);
+#define QUERY_UINT64(msg, field, attr) \
+ r->out.info->field = samdb_result_uint64(msg, attr, 0);
+#define QUERY_APASSC(msg, field, attr) \
+ r->out.info->field = samdb_result_allow_password_change(sam_ctx, mem_ctx, \
+ a_state->domain_state->domain_dn, msg, attr);
+#define QUERY_FPASSC(msg, field, attr) \
+ r->out.info->field = samdb_result_force_password_change(sam_ctx, mem_ctx, \
+ a_state->domain_state->domain_dn, msg);
+#define QUERY_LHOURS(msg, field, attr) \
+ r->out.info->field = samdb_result_logon_hours(mem_ctx, msg, attr);
+#define QUERY_AFLAGS(msg, field, attr) \
+ r->out.info->field = samdb_result_acct_flags(msg, attr);
+
+
+/* these are used to make the Set[User|Group]Info code easier to follow */
+
+#define SET_STRING(msg, field, attr) do { \
+ struct ldb_message_element *set_el; \
+ if (r->in.info->field.string == NULL) return NT_STATUS_INVALID_PARAMETER; \
+ if (r->in.info->field.string[0] == '\0') { \
+ if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, NULL)) { \
+ return NT_STATUS_NO_MEMORY; \
+ } \
+ } \
+ if (ldb_msg_add_string(msg, attr, r->in.info->field.string) != 0) { \
+ return NT_STATUS_NO_MEMORY; \
+ } \
+ set_el = ldb_msg_find_element(msg, attr); \
+ set_el->flags = LDB_FLAG_MOD_REPLACE; \
+} while (0)
+
+#define SET_UINT(msg, field, attr) do { \
+ struct ldb_message_element *set_el; \
+ if (samdb_msg_add_uint(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
+ return NT_STATUS_NO_MEMORY; \
+ } \
+ set_el = ldb_msg_find_element(msg, attr); \
+ set_el->flags = LDB_FLAG_MOD_REPLACE; \
+} while (0)
+
+#define SET_INT64(msg, field, attr) do { \
+ struct ldb_message_element *set_el; \
+ if (samdb_msg_add_int64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
+ return NT_STATUS_NO_MEMORY; \
+ } \
+ set_el = ldb_msg_find_element(msg, attr); \
+ set_el->flags = LDB_FLAG_MOD_REPLACE; \
+} while (0)
+
+#define SET_UINT64(msg, field, attr) do { \
+ struct ldb_message_element *set_el; \
+ if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
+ return NT_STATUS_NO_MEMORY; \
+ } \
+ set_el = ldb_msg_find_element(msg, attr); \
+ set_el->flags = LDB_FLAG_MOD_REPLACE; \
+} while (0)
+
+#define SET_AFLAGS(msg, field, attr) do { \
+ struct ldb_message_element *set_el; \
+ if (samdb_msg_add_acct_flags(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
+ return NT_STATUS_NO_MEMORY; \
+ } \
+ set_el = ldb_msg_find_element(msg, attr); \
+ set_el->flags = LDB_FLAG_MOD_REPLACE; \
+} while (0)
+
+#define SET_LHOURS(msg, field, attr) do { \
+ struct ldb_message_element *set_el; \
+ if (samdb_msg_add_logon_hours(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
+ return NT_STATUS_NO_MEMORY; \
+ } \
+ set_el = ldb_msg_find_element(msg, attr); \
+ set_el->flags = LDB_FLAG_MOD_REPLACE; \
+} while (0)
-/*
- This is a bad temporary hack until we have at least some kind of schema
- support
-*/
-static char *ldb_hexstr(TALLOC_CTX *mem_ctx, uint32 val)
-{
- return talloc_asprintf(mem_ctx, "0x%.8x", val);
-}
/*
samr_Connect
create a connection to the SAM database
*/
-static NTSTATUS samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_Connect *r)
{
struct samr_connect_state *c_state;
}
/* make sure the sam database is accessible */
- c_state->sam_ctx = samdb_connect(c_state);
+ c_state->sam_ctx = samdb_connect(c_state, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
if (c_state->sam_ctx == NULL) {
talloc_free(c_state);
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
+
handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_CONNECT);
if (!handle) {
talloc_free(c_state);
/*
samr_Close
*/
-static NTSTATUS samr_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_Close *r)
{
struct dcesrv_handle *h;
/*
samr_SetSecurity
*/
-static NTSTATUS samr_SetSecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_SetSecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_SetSecurity *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
/*
samr_QuerySecurity
*/
-static NTSTATUS samr_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QuerySecurity *r)
{
struct dcesrv_handle *h;
we refuse this operation completely. If a admin wants to shutdown samr
in Samba then they should use the samba admin tools to disable the samr pipe
*/
-static NTSTATUS samr_Shutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_Shutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_Shutdown *r)
{
return NT_STATUS_ACCESS_DENIED;
this maps from a domain name to a SID
*/
-static NTSTATUS samr_LookupDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_LookupDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_LookupDomain *r)
{
struct samr_connect_state *c_state;
struct dcesrv_handle *h;
- struct dom_sid2 *sid;
- const char *sidstr;
-
+ struct dom_sid *sid;
+ const char * const dom_attrs[] = { "objectSid", NULL};
+ const char * const ref_attrs[] = { "ncName", NULL};
+ struct ldb_message **dom_msgs;
+ struct ldb_message **ref_msgs;
+ int ret;
+ struct ldb_dn *partitions_basedn;
+
r->out.sid = NULL;
DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT);
c_state = h->data;
- if (r->in.domain->string == NULL) {
+ if (r->in.domain_name->string == NULL) {
return NT_STATUS_INVALID_PARAMETER;
}
- sidstr = samdb_search_string(c_state->sam_ctx,
- mem_ctx, NULL, "objectSid",
- "(&(name=%s)(objectclass=domain))",
- r->in.domain->string);
- if (sidstr == NULL) {
- return NT_STATUS_NO_SUCH_DOMAIN;
+ partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
+
+ if (strcasecmp(r->in.domain_name->string, "BUILTIN") == 0) {
+ ret = gendb_search(c_state->sam_ctx,
+ mem_ctx, NULL, &dom_msgs, dom_attrs,
+ "(objectClass=builtinDomain)");
+ } else {
+ ret = gendb_search(c_state->sam_ctx,
+ mem_ctx, partitions_basedn, &ref_msgs, ref_attrs,
+ "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
+ ldb_binary_encode_string(mem_ctx, r->in.domain_name->string));
+ if (ret != 1) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ ret = gendb_search_dn(c_state->sam_ctx, mem_ctx,
+ samdb_result_dn(c_state->sam_ctx, mem_ctx,
+ ref_msgs[0], "ncName", NULL),
+ &dom_msgs, dom_attrs);
}
- sid = dom_sid_parse_talloc(mem_ctx, sidstr);
+ if (ret != 1) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ sid = samdb_result_dom_sid(mem_ctx, dom_msgs[0],
+ "objectSid");
+
if (sid == NULL) {
- DEBUG(0,("samdb: Invalid sid '%s' for domain %s\n",
- sidstr, r->in.domain->string));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ return NT_STATUS_NO_SUCH_DOMAIN;
}
r->out.sid = sid;
list the domains in the SAM
*/
-static NTSTATUS samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_EnumDomains *r)
{
struct samr_connect_state *c_state;
struct dcesrv_handle *h;
struct samr_SamArray *array;
- const char **domains;
int count, i, start_i;
+ const char * const dom_attrs[] = { "cn", NULL};
+ const char * const ref_attrs[] = { "nETBIOSName", NULL};
+ struct ldb_message **dom_msgs;
+ struct ldb_message **ref_msgs;
+ struct ldb_dn *partitions_basedn;
*r->out.resume_handle = 0;
r->out.sam = NULL;
c_state = h->data;
- count = samdb_search_string_multiple(c_state->sam_ctx,
- mem_ctx, NULL, &domains,
- "name", "(objectclass=domain)");
+ partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
+
+ count = gendb_search(c_state->sam_ctx,
+ mem_ctx, NULL, &dom_msgs, dom_attrs,
+ "(objectClass=domain)");
if (count == -1) {
DEBUG(0,("samdb: no domains found in EnumDomains\n"));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
for (i=0;i<count-start_i;i++) {
+ int ret;
array->entries[i].idx = start_i + i;
- array->entries[i].name.string = domains[start_i+i];
+ /* try and find the domain */
+ ret = gendb_search(c_state->sam_ctx, mem_ctx, partitions_basedn,
+ &ref_msgs, ref_attrs,
+ "(&(objectClass=crossRef)(ncName=%s))",
+ ldb_dn_get_linearized(dom_msgs[i]->dn));
+ if (ret == 1) {
+ array->entries[i].name.string = samdb_result_string(ref_msgs[0], "nETBIOSName", NULL);
+ } else {
+ array->entries[i].name.string = samdb_result_string(dom_msgs[i], "cn", NULL);
+ }
}
r->out.sam = array;
/*
samr_OpenDomain
*/
-static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_OpenDomain *r)
{
struct dcesrv_handle *h_conn, *h_domain;
- const char *sidstr, *domain_name;
+ const char *domain_name;
struct samr_connect_state *c_state;
struct samr_domain_state *d_state;
- const char * const attrs[2] = { "name", NULL};
- struct ldb_message **msgs;
+ const char * const dom_attrs[] = { "cn", NULL};
+ const char * const ref_attrs[] = { "nETBIOSName", NULL};
+ struct ldb_message **dom_msgs;
+ struct ldb_message **ref_msgs;
int ret;
+ struct ldb_dn *partitions_basedn;
ZERO_STRUCTP(r->out.domain_handle);
return NT_STATUS_INVALID_PARAMETER;
}
- sidstr = dom_sid_string(mem_ctx, r->in.sid);
- if (sidstr == NULL) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- ret = samdb_search(c_state->sam_ctx,
- mem_ctx, NULL, &msgs, attrs,
- "(&(objectSid=%s)(objectclass=domain))",
- sidstr);
- if (ret != 1) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
+ partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
- domain_name = ldb_msg_find_string(msgs[0], "name", NULL);
- if (domain_name == NULL) {
+ ret = gendb_search(c_state->sam_ctx,
+ mem_ctx, NULL, &dom_msgs, dom_attrs,
+ "(&(objectSid=%s)(&(|(objectclass=domain)(objectClass=builtinDomain))))",
+ ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
+ if (ret == 0) {
return NT_STATUS_NO_SUCH_DOMAIN;
+ } else if (ret > 1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ } else if (ret == -1) {
+ DEBUG(1, ("Failed to open domain %s: %s\n", dom_sid_string(mem_ctx, r->in.sid), ldb_errstring(c_state->sam_ctx)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ } else {
+ ret = gendb_search(c_state->sam_ctx,
+ mem_ctx, partitions_basedn, &ref_msgs, ref_attrs,
+ "(&(&(nETBIOSName=*)(objectclass=crossRef))(ncName=%s))",
+ ldb_dn_get_linearized(dom_msgs[0]->dn));
+ if (ret == 0) {
+ domain_name = ldb_msg_find_attr_as_string(dom_msgs[0], "cn", NULL);
+ if (domain_name == NULL) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+ } else if (ret == 1) {
+
+ domain_name = ldb_msg_find_attr_as_string(ref_msgs[0], "nETBIOSName", NULL);
+ if (domain_name == NULL) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+ } else {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
}
d_state = talloc(c_state, struct samr_domain_state);
return NT_STATUS_NO_MEMORY;
}
+ d_state->role = lp_server_role(dce_call->conn->dce_ctx->lp_ctx);
d_state->connect_state = talloc_reference(d_state, c_state);
d_state->sam_ctx = c_state->sam_ctx;
- d_state->domain_sid = talloc_strdup(d_state, sidstr);
+ d_state->domain_sid = dom_sid_dup(d_state, r->in.sid);
d_state->domain_name = talloc_strdup(d_state, domain_name);
- d_state->domain_dn = talloc_strdup(d_state, msgs[0]->dn);
+ d_state->domain_dn = ldb_dn_copy(d_state, dom_msgs[0]->dn);
if (!d_state->domain_sid || !d_state->domain_name || !d_state->domain_dn) {
talloc_free(d_state);
return NT_STATUS_NO_MEMORY;
/*
return DomInfo1
*/
-static NTSTATUS samr_info_DomInfo1(struct samr_domain_state *state,
+static NTSTATUS dcesrv_samr_info_DomInfo1(struct samr_domain_state *state,
TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
struct samr_DomInfo1 *info)
{
- const char * const attrs[] = { "minPwdLength", "pwdHistoryLength",
- "pwdProperties", "maxPwdAge",
- "minPwdAge", NULL };
- int ret;
- struct ldb_message **res;
-
- ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs,
- "dn=%s", state->domain_dn);
- if (ret != 1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
info->min_password_length =
- samdb_result_uint(res[0], "minPwdLength", 0);
+ samdb_result_uint(dom_msgs[0], "minPwdLength", 0);
info->password_history_length =
- samdb_result_uint(res[0], "pwdHistoryLength", 0);
+ samdb_result_uint(dom_msgs[0], "pwdHistoryLength", 0);
info->password_properties =
- samdb_result_uint(res[0], "pwdProperties", 0);
+ samdb_result_uint(dom_msgs[0], "pwdProperties", 0);
info->max_password_age =
- samdb_result_int64(res[0], "maxPwdAge", 0);
+ samdb_result_int64(dom_msgs[0], "maxPwdAge", 0);
info->min_password_age =
- samdb_result_int64(res[0], "minPwdAge", 0);
+ samdb_result_int64(dom_msgs[0], "minPwdAge", 0);
return NT_STATUS_OK;
}
/*
return DomInfo2
*/
-static NTSTATUS samr_info_DomInfo2(struct samr_domain_state *state, TALLOC_CTX *mem_ctx,
- struct samr_DomInfo2 *info)
+static NTSTATUS dcesrv_samr_info_DomInfo2(struct samr_domain_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
+ struct samr_DomInfo2 *info)
{
- const char * const attrs[] = { "comment", "name", NULL };
- int ret;
- struct ldb_message **res;
-
- ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs,
- "dn=%s", state->domain_dn);
- if (ret != 1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ /* This pulls the NetBIOS name from the
+ cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
+ string */
+ info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx, dom_msgs[0], "fSMORoleOwner");
+
+ info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff",
+ 0x8000000000000000LL);
+
+ info->comment.string = samdb_result_string(dom_msgs[0], "comment", NULL);
+ info->domain_name.string = state->domain_name;
+
+ info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount",
+ 0);
+ switch (state->role) {
+ case ROLE_DOMAIN_CONTROLLER:
+ /* This pulls the NetBIOS name from the
+ cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
+ string */
+ if (samdb_is_pdc(state->sam_ctx)) {
+ info->role = SAMR_ROLE_DOMAIN_PDC;
+ } else {
+ info->role = SAMR_ROLE_DOMAIN_BDC;
+ }
+ break;
+ case ROLE_DOMAIN_MEMBER:
+ info->role = SAMR_ROLE_DOMAIN_MEMBER;
+ break;
+ case ROLE_STANDALONE:
+ info->role = SAMR_ROLE_STANDALONE;
+ break;
}
- /* where is this supposed to come from? is it settable? */
- info->force_logoff_time = 0x8000000000000000LL;
-
- info->comment.string = samdb_result_string(res[0], "comment", NULL);
- info->domain.string = samdb_result_string(res[0], "name", NULL);
-
- info->primary.string = lp_netbios_name();
- info->sequence_num = 0;
- info->role = ROLE_DOMAIN_PDC;
- info->num_users = samdb_search_count(state->sam_ctx, mem_ctx, NULL, "(objectClass=user)");
- info->num_groups = samdb_search_count(state->sam_ctx, mem_ctx, NULL,
+ /* No users in BUILTIN, and the LOCAL group types are only in builtin, and the global group type is never in BUILTIN */
+ info->num_users = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,
+ "(objectClass=user)");
+ info->num_groups = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,
"(&(objectClass=group)(sAMAccountType=%u))",
ATYPE_GLOBAL_GROUP);
- info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx, NULL,
+ info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,
"(&(objectClass=group)(sAMAccountType=%u))",
ATYPE_LOCAL_GROUP);
/*
return DomInfo3
*/
-static NTSTATUS samr_info_DomInfo3(struct samr_domain_state *state,
+static NTSTATUS dcesrv_samr_info_DomInfo3(struct samr_domain_state *state,
TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
struct samr_DomInfo3 *info)
{
- /* where is this supposed to come from? is it settable? */
- info->force_logoff_time = 0x8000000000000000LL;
+ info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff",
+ 0x8000000000000000LL);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ return DomInfo4
+*/
+static NTSTATUS dcesrv_samr_info_DomInfo4(struct samr_domain_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
+ struct samr_DomInfo4 *info)
+{
+ info->comment.string = samdb_result_string(dom_msgs[0], "comment", NULL);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ return DomInfo5
+*/
+static NTSTATUS dcesrv_samr_info_DomInfo5(struct samr_domain_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
+ struct samr_DomInfo5 *info)
+{
+ info->domain_name.string = state->domain_name;
+
+ return NT_STATUS_OK;
+}
+
+/*
+ return DomInfo6
+*/
+static NTSTATUS dcesrv_samr_info_DomInfo6(struct samr_domain_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
+ struct samr_DomInfo6 *info)
+{
+ /* This pulls the NetBIOS name from the
+ cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
+ string */
+ info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx,
+ dom_msgs[0], "fSMORoleOwner");
+
+ return NT_STATUS_OK;
+}
+
+/*
+ return DomInfo7
+*/
+static NTSTATUS dcesrv_samr_info_DomInfo7(struct samr_domain_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
+ struct samr_DomInfo7 *info)
+{
+
+ switch (state->role) {
+ case ROLE_DOMAIN_CONTROLLER:
+ /* This pulls the NetBIOS name from the
+ cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
+ string */
+ if (samdb_is_pdc(state->sam_ctx)) {
+ info->role = SAMR_ROLE_DOMAIN_PDC;
+ } else {
+ info->role = SAMR_ROLE_DOMAIN_BDC;
+ }
+ break;
+ case ROLE_DOMAIN_MEMBER:
+ info->role = SAMR_ROLE_DOMAIN_MEMBER;
+ break;
+ case ROLE_STANDALONE:
+ info->role = SAMR_ROLE_STANDALONE;
+ break;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*
+ return DomInfo8
+*/
+static NTSTATUS dcesrv_samr_info_DomInfo8(struct samr_domain_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
+ struct samr_DomInfo8 *info)
+{
+ info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount",
+ time(NULL));
+
+ info->domain_create_time = ldb_msg_find_attr_as_uint(dom_msgs[0], "creationTime",
+ 0x0LL);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ return DomInfo9
+*/
+static NTSTATUS dcesrv_samr_info_DomInfo9(struct samr_domain_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
+ struct samr_DomInfo9 *info)
+{
+ info->unknown = 1;
+
+ return NT_STATUS_OK;
+}
+
+/*
+ return DomInfo11
+*/
+static NTSTATUS dcesrv_samr_info_DomInfo11(struct samr_domain_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
+ struct samr_DomInfo11 *info)
+{
+ NTSTATUS status;
+ status = dcesrv_samr_info_DomInfo2(state, mem_ctx, dom_msgs, &info->info2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration",
+ -18000000000LL);
+ info->lockout_window = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockOutObservationWindow",
+ -18000000000LL);
+ info->lockout_threshold = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutThreshold", 0);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ return DomInfo12
+*/
+static NTSTATUS dcesrv_samr_info_DomInfo12(struct samr_domain_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
+ struct samr_DomInfo12 *info)
+{
+ info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration",
+ -18000000000LL);
+ info->lockout_window = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockOutObservationWindow",
+ -18000000000LL);
+ info->lockout_threshold = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutThreshold", 0);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ return DomInfo13
+*/
+static NTSTATUS dcesrv_samr_info_DomInfo13(struct samr_domain_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
+ struct samr_DomInfo13 *info)
+{
+ info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount",
+ time(NULL));
+
+ info->domain_create_time = ldb_msg_find_attr_as_uint(dom_msgs[0], "creationTime",
+ 0x0LL);
+
+ info->unknown1 = 0;
+ info->unknown2 = 0;
return NT_STATUS_OK;
}
/*
samr_QueryDomainInfo
*/
-static NTSTATUS samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QueryDomainInfo *r)
{
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
+ struct ldb_message **dom_msgs;
+ const char * const *attrs = NULL;
+
r->out.info = NULL;
DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
return NT_STATUS_NO_MEMORY;
}
+ switch (r->in.level) {
+ case 1:
+ {
+ static const char * const attrs2[] = { "minPwdLength", "pwdHistoryLength",
+ "pwdProperties", "maxPwdAge",
+ "minPwdAge", NULL };
+ attrs = attrs2;
+ break;
+ }
+ case 2:
+ {
+ static const char * const attrs2[] = {"forceLogoff",
+ "comment",
+ "modifiedCount",
+ "fSMORoleOwner",
+ NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 3:
+ {
+ static const char * const attrs2[] = {"forceLogoff",
+ NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 4:
+ {
+ static const char * const attrs2[] = {"comment",
+ NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 5:
+ {
+ attrs = NULL;
+ break;
+ }
+ case 6:
+ {
+ static const char * const attrs2[] = {"fSMORoleOwner",
+ NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 7:
+ {
+ attrs = NULL;
+ break;
+ }
+ case 8:
+ {
+ static const char * const attrs2[] = { "modifiedCount",
+ "creationTime",
+ NULL };
+ attrs = attrs2;
+ break;
+ }
+ case 9:
+ attrs = NULL;
+ break;
+ case 11:
+ {
+ static const char * const attrs2[] = { "comment", "forceLogoff",
+ "modifiedCount",
+ "lockoutDuration",
+ "lockOutObservationWindow",
+ "lockoutThreshold",
+ NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 12:
+ {
+ static const char * const attrs2[] = { "lockoutDuration",
+ "lockOutObservationWindow",
+ "lockoutThreshold",
+ NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 13:
+ {
+ static const char * const attrs2[] = { "modifiedCount",
+ "creationTime",
+ NULL };
+ attrs = attrs2;
+ break;
+ }
+ }
+
+ /* some levels don't need a search */
+ if (attrs) {
+ int ret;
+ ret = gendb_search_dn(d_state->sam_ctx, mem_ctx,
+ d_state->domain_dn, &dom_msgs, attrs);
+ if (ret != 1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ }
+
ZERO_STRUCTP(r->out.info);
switch (r->in.level) {
case 1:
- return samr_info_DomInfo1(d_state, mem_ctx,
+ return dcesrv_samr_info_DomInfo1(d_state, mem_ctx, dom_msgs,
&r->out.info->info1);
case 2:
- return samr_info_DomInfo2(d_state, mem_ctx, &r->out.info->info2);
+ return dcesrv_samr_info_DomInfo2(d_state, mem_ctx, dom_msgs,
+ &r->out.info->info2);
case 3:
- return samr_info_DomInfo3(d_state, mem_ctx,
+ return dcesrv_samr_info_DomInfo3(d_state, mem_ctx, dom_msgs,
&r->out.info->info3);
+ case 4:
+ return dcesrv_samr_info_DomInfo4(d_state, mem_ctx, dom_msgs,
+ &r->out.info->info4);
+ case 5:
+ return dcesrv_samr_info_DomInfo5(d_state, mem_ctx, dom_msgs,
+ &r->out.info->info5);
+ case 6:
+ return dcesrv_samr_info_DomInfo6(d_state, mem_ctx, dom_msgs,
+ &r->out.info->info6);
+ case 7:
+ return dcesrv_samr_info_DomInfo7(d_state, mem_ctx, dom_msgs,
+ &r->out.info->info7);
+ case 8:
+ return dcesrv_samr_info_DomInfo8(d_state, mem_ctx, dom_msgs,
+ &r->out.info->info8);
+ case 9:
+ return dcesrv_samr_info_DomInfo9(d_state, mem_ctx, dom_msgs,
+ &r->out.info->info9);
+ case 11:
+ return dcesrv_samr_info_DomInfo11(d_state, mem_ctx, dom_msgs,
+ &r->out.info->info11);
+ case 12:
+ return dcesrv_samr_info_DomInfo12(d_state, mem_ctx, dom_msgs,
+ &r->out.info->info12);
+ case 13:
+ return dcesrv_samr_info_DomInfo13(d_state, mem_ctx, dom_msgs,
+ &r->out.info->info13);
}
return NT_STATUS_INVALID_INFO_CLASS;
/*
samr_SetDomainInfo
*/
-static NTSTATUS samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_SetDomainInfo *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct dcesrv_handle *h;
+ struct samr_domain_state *d_state;
+ struct ldb_message *msg;
+ int ret;
+ struct ldb_context *sam_ctx;
+
+ DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
+
+ d_state = h->data;
+ sam_ctx = d_state->sam_ctx;
+
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ msg->dn = talloc_reference(mem_ctx, d_state->domain_dn);
+ if (!msg->dn) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ switch (r->in.level) {
+ case 1:
+ SET_UINT (msg, info1.min_password_length, "minPwdLength");
+ SET_UINT (msg, info1.password_history_length, "pwdHistoryLength");
+ SET_UINT (msg, info1.password_properties, "pwdProperties");
+ SET_INT64 (msg, info1.max_password_age, "maxPwdAge");
+ SET_INT64 (msg, info1.min_password_age, "minPwdAge");
+ break;
+ case 3:
+ SET_UINT64 (msg, info3.force_logoff_time, "forceLogoff");
+ break;
+ case 4:
+ SET_STRING(msg, info4.comment, "comment");
+ break;
+
+ case 6:
+ case 7:
+ case 9:
+ /* No op, we don't know where to set these */
+ return NT_STATUS_OK;
+
+ case 12:
+
+ SET_INT64 (msg, info12.lockout_duration, "lockoutDuration");
+ SET_INT64 (msg, info12.lockout_window, "lockOutObservationWindow");
+ SET_INT64 (msg, info12.lockout_threshold, "lockoutThreshold");
+ break;
+
+ default:
+ /* many info classes are not valid for SetDomainInfo */
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
+
+ /* modify the samdb record */
+ ret = ldb_modify(sam_ctx, msg);
+ if (ret != 0) {
+ DEBUG(1,("Failed to modify record %s: %s\n",
+ ldb_dn_get_linearized(d_state->domain_dn),
+ ldb_errstring(sam_ctx)));
+
+ /* we really need samdb.c to return NTSTATUS */
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
}
/*
samr_CreateDomainGroup
*/
-static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_CreateDomainGroup *r)
{
struct samr_domain_state *d_state;
struct dcesrv_handle *h;
const char *name;
struct ldb_message *msg;
- uint32_t rid;
- const char *groupname, *sidstr;
+ struct dom_sid *sid;
+ const char *groupname;
struct dcesrv_handle *g_handle;
int ret;
- NTSTATUS status;
ZERO_STRUCTP(r->out.group_handle);
*r->out.rid = 0;
name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
"sAMAccountName",
"(&(sAMAccountName=%s)(objectclass=group))",
- groupname);
+ ldb_binary_encode_string(mem_ctx, groupname));
if (name != NULL) {
return NT_STATUS_GROUP_EXISTS;
}
return NT_STATUS_NO_MEMORY;
}
- /* pull in all the template attributes */
- ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg,
- "(&(name=TemplateGroup)(objectclass=groupTemplate))");
- if (ret != 0) {
- DEBUG(0,("Failed to load TemplateGroup from samdb\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- /* allocate a rid */
- status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx,
- d_state->domain_dn, "nextRid", &rid);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* and the group SID */
- sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
- if (!sidstr) {
- return NT_STATUS_NO_MEMORY;
- }
-
/* add core elements to the ldb_message for the user */
- msg->dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", groupname,
- d_state->domain_dn);
+ msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
+ ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", groupname);
if (!msg->dn) {
return NT_STATUS_NO_MEMORY;
}
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "name", groupname);
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "cn", groupname);
samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", groupname);
samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group");
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectSid", sidstr);
/* create the group */
- ret = samdb_add(d_state->sam_ctx, mem_ctx, msg);
- if (ret != 0) {
- DEBUG(0,("Failed to create group record %s\n", msg->dn));
+ ret = ldb_add(d_state->sam_ctx, msg);
+ switch (ret) {
+ case LDB_SUCCESS:
+ break;
+ case LDB_ERR_ENTRY_ALREADY_EXISTS:
+ DEBUG(0,("Failed to create group record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(d_state->sam_ctx)));
+ return NT_STATUS_GROUP_EXISTS;
+ case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
+ DEBUG(0,("Failed to create group record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(d_state->sam_ctx)));
+ return NT_STATUS_ACCESS_DENIED;
+ default:
+ DEBUG(0,("Failed to create group record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(d_state->sam_ctx)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
a_state->access_mask = r->in.access_mask;
a_state->domain_state = talloc_reference(a_state, d_state);
a_state->account_dn = talloc_steal(a_state, msg->dn);
- a_state->account_sid = talloc_steal(a_state, sidstr);
+
+ /* retrieve the sid for the group just created */
+ sid = samdb_search_dom_sid(d_state->sam_ctx, a_state,
+ msg->dn, "objectSid", NULL);
+ if (sid == NULL) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
a_state->account_name = talloc_strdup(a_state, groupname);
if (!a_state->account_name) {
return NT_STATUS_NO_MEMORY;
g_handle->data = talloc_steal(g_handle, a_state);
*r->out.group_handle = g_handle->wire_handle;
- *r->out.rid = rid;
+ *r->out.rid = sid->sub_auths[sid->num_auths-1];
return NT_STATUS_OK;
}
/*
samr_EnumDomainGroups
*/
-static NTSTATUS samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_EnumDomainGroups *r)
{
struct dcesrv_handle *h;
int ldb_cnt, count, i, first;
struct samr_SamEntry *entries;
const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
- struct dom_sid *domain_sid;
*r->out.resume_handle = 0;
r->out.sam = NULL;
d_state = h->data;
- domain_sid = dom_sid_parse_talloc(mem_ctx, d_state->domain_sid);
- if (domain_sid == NULL)
- return NT_STATUS_NO_MEMORY;
-
/* search for all domain groups in this domain. This could possibly be
cached and resumed based on resume_key */
ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
d_state->domain_dn, &res, attrs,
- domain_sid,
- "(&(grouptype=%s)(objectclass=group))",
- ldb_hexstr(mem_ctx,
- GTYPE_SECURITY_GLOBAL_GROUP));
+ d_state->domain_sid,
+ "(&(grouptype=%d)(objectclass=group))",
+ GTYPE_SECURITY_GLOBAL_GROUP);
if (ldb_cnt == -1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
/*
samr_CreateUser2
- TODO: This should do some form of locking, especially around the rid allocation
+ This call uses transactions to ensure we don't get a new conflicting
+ user while we are processing this, and to ensure the user either
+ completly exists, or does not.
*/
-static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_CreateUser2 *r)
{
struct samr_domain_state *d_state;
struct dcesrv_handle *h;
const char *name;
struct ldb_message *msg;
- uint32_t rid;
- const char *account_name, *sidstr;
+ struct dom_sid *sid;
+ const char *account_name;
struct dcesrv_handle *u_handle;
int ret;
- NTSTATUS status;
- const char *container, *additional_class=NULL;
+ const char *container, *obj_class=NULL;
+ char *cn_name;
+ int cn_name_len;
+
+ const char *attrs[] = {
+ "objectSid",
+ "userAccountControl",
+ NULL
+ };
+
+ uint32_t user_account_control;
+
+ struct ldb_message **msgs;
ZERO_STRUCTP(r->out.user_handle);
*r->out.access_granted = 0;
return NT_STATUS_INVALID_PARAMETER;
}
+ ret = ldb_transaction_start(d_state->sam_ctx);
+ if (ret != 0) {
+ DEBUG(0,("Failed to start a transaction for user creation: %s\n",
+ ldb_errstring(d_state->sam_ctx)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
/* check if the user already exists */
name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
"sAMAccountName",
- "(&(sAMAccountName=%s)(objectclass=user))", account_name);
+ "(&(sAMAccountName=%s)(objectclass=user))",
+ ldb_binary_encode_string(mem_ctx, account_name));
if (name != NULL) {
+ ldb_transaction_cancel(d_state->sam_ctx);
return NT_STATUS_USER_EXISTS;
}
msg = ldb_msg_new(mem_ctx);
if (msg == NULL) {
+ ldb_transaction_cancel(d_state->sam_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ cn_name = talloc_strdup(mem_ctx, account_name);
+ if (!cn_name) {
+ ldb_transaction_cancel(d_state->sam_ctx);
return NT_STATUS_NO_MEMORY;
}
+ cn_name_len = strlen(cn_name);
+
/* This must be one of these values *only* */
if (r->in.acct_flags == ACB_NORMAL) {
- /* pull in all the template attributes */
- ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg,
- "(&(name=TemplateUser)(objectclass=userTemplate))");
- if (ret != 0) {
- DEBUG(0,("Failed to load TemplateUser from samdb\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- container = "Users";
+ container = "CN=Users";
+ obj_class = "user";
} else if (r->in.acct_flags == ACB_WSTRUST) {
- /* pull in all the template attributes */
- ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg,
- "(&(name=TemplateMemberServer)(objectclass=userTemplate))");
- if (ret != 0) {
- DEBUG(0,("Failed to load TemplateMemberServer from samdb\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ if (cn_name[cn_name_len - 1] != '$') {
+ return NT_STATUS_FOOBAR;
}
-
- container = "Computers";
- additional_class = "computer";
+ cn_name[cn_name_len - 1] = '\0';
+ container = "CN=Computers";
+ obj_class = "computer";
+ samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "primaryGroupID", DOMAIN_RID_DOMAIN_MEMBERS);
} else if (r->in.acct_flags == ACB_SVRTRUST) {
- /* pull in all the template attributes */
- ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg,
- "(&(name=TemplateDomainController)(objectclass=userTemplate))");
- if (ret != 0) {
- DEBUG(0,("Failed to load TemplateDomainController from samdb\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ if (cn_name[cn_name_len - 1] != '$') {
+ return NT_STATUS_FOOBAR;
}
-
- container = "Domain Controllers";
- additional_class = "computer";
+ cn_name[cn_name_len - 1] = '\0';
+ container = "OU=Domain Controllers";
+ obj_class = "computer";
+ samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "primaryGroupID", DOMAIN_RID_DCS);
} else if (r->in.acct_flags == ACB_DOMTRUST) {
- /* pull in all the template attributes */
- ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg,
- "(&(name=TemplateTrustingDomain)(objectclass=userTemplate))");
- if (ret != 0) {
- DEBUG(0,("Failed to load TemplateTrustingDomain from samdb\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- container = "Users";
- additional_class = "computer";
+ container = "CN=Users";
+ obj_class = "user";
} else {
+ ldb_transaction_cancel(d_state->sam_ctx);
return NT_STATUS_INVALID_PARAMETER;
}
- /* allocate a rid */
- status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx,
- d_state->domain_dn, "nextRid", &rid);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* and the users SID */
- sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
- if (!sidstr) {
- return NT_STATUS_NO_MEMORY;
- }
-
/* add core elements to the ldb_message for the user */
- msg->dn = talloc_asprintf(mem_ctx, "CN=%s,CN=%s,%s", account_name, container, d_state->domain_dn);
- if (!msg->dn) {
- return NT_STATUS_NO_MEMORY;
- }
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "name", account_name);
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "cn", account_name);
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", account_name);
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "user");
- if (additional_class) {
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", additional_class);
+ msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
+ if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s,%s", cn_name, container)) {
+ ldb_transaction_cancel(d_state->sam_ctx);
+ return NT_STATUS_FOOBAR;
}
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectSid", sidstr);
+ samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", account_name);
+ samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", obj_class);
+
+ /* Start a transaction, so we can query and do a subsequent atomic modify */
+
/* create the user */
- ret = samdb_add(d_state->sam_ctx, mem_ctx, msg);
- if (ret != 0) {
- DEBUG(0,("Failed to create user record %s\n", msg->dn));
+ ret = ldb_add(d_state->sam_ctx, msg);
+ switch (ret) {
+ case LDB_SUCCESS:
+ break;
+ case LDB_ERR_ENTRY_ALREADY_EXISTS:
+ ldb_transaction_cancel(d_state->sam_ctx);
+ DEBUG(0,("Failed to create user record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(d_state->sam_ctx)));
+ return NT_STATUS_USER_EXISTS;
+ case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
+ ldb_transaction_cancel(d_state->sam_ctx);
+ DEBUG(0,("Failed to create user record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(d_state->sam_ctx)));
+ return NT_STATUS_ACCESS_DENIED;
+ default:
+ ldb_transaction_cancel(d_state->sam_ctx);
+ DEBUG(0,("Failed to create user record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(d_state->sam_ctx)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
a_state = talloc(d_state, struct samr_account_state);
if (!a_state) {
+ ldb_transaction_cancel(d_state->sam_ctx);
return NT_STATUS_NO_MEMORY;
}
a_state->sam_ctx = d_state->sam_ctx;
a_state->access_mask = r->in.access_mask;
a_state->domain_state = talloc_reference(a_state, d_state);
a_state->account_dn = talloc_steal(a_state, msg->dn);
- a_state->account_sid = talloc_steal(a_state, sidstr);
- a_state->account_name = talloc_strdup(a_state, account_name);
+
+ /* retrieve the sid and account control bits for the user just created */
+ ret = gendb_search_dn(d_state->sam_ctx, a_state,
+ msg->dn, &msgs, attrs);
+
+ if (ret != 1) {
+ ldb_transaction_cancel(d_state->sam_ctx);
+ DEBUG(0,("Apparently we failed to create an account record, as %s now doesn't exist\n",
+ ldb_dn_get_linearized(msg->dn)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ sid = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid");
+ if (sid == NULL) {
+ ldb_transaction_cancel(d_state->sam_ctx);
+ DEBUG(0,("Apparently we failed to get the objectSid of the just created account record %s\n",
+ ldb_dn_get_linearized(msg->dn)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ /* Change the account control to be the correct account type.
+ * The default is for a workstation account */
+ user_account_control = samdb_result_uint(msgs[0], "userAccountControl", 0);
+ user_account_control = (user_account_control &
+ ~(UF_NORMAL_ACCOUNT |
+ UF_INTERDOMAIN_TRUST_ACCOUNT |
+ UF_WORKSTATION_TRUST_ACCOUNT |
+ UF_SERVER_TRUST_ACCOUNT));
+ user_account_control |= samdb_acb2uf(r->in.acct_flags);
+
+ talloc_free(msg);
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) {
+ ldb_transaction_cancel(d_state->sam_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ msg->dn = ldb_dn_copy(msg, a_state->account_dn);
+
+ if (samdb_msg_add_uint(a_state->sam_ctx, mem_ctx, msg,
+ "userAccountControl",
+ user_account_control) != 0) {
+ ldb_transaction_cancel(d_state->sam_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* modify the samdb record */
+ ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
+ if (ret != 0) {
+ DEBUG(0,("Failed to modify account record %s to set userAccountControl: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(d_state->sam_ctx)));
+ ldb_transaction_cancel(d_state->sam_ctx);
+
+ /* we really need samdb.c to return NTSTATUS */
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ret = ldb_transaction_commit(d_state->sam_ctx);
+ if (ret != 0) {
+ DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(d_state->sam_ctx)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ a_state->account_name = talloc_steal(a_state, account_name);
if (!a_state->account_name) {
return NT_STATUS_NO_MEMORY;
}
*r->out.user_handle = u_handle->wire_handle;
*r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */
- *r->out.rid = rid;
+
+ *r->out.rid = sid->sub_auths[sid->num_auths-1];
return NT_STATUS_OK;
}
/*
samr_CreateUser
*/
-static NTSTATUS samr_CreateUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_CreateUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_CreateUser *r)
{
struct samr_CreateUser2 r2;
r2.out.access_granted = &access_granted;
r2.out.rid = r->out.rid;
- return samr_CreateUser2(dce_call, mem_ctx, &r2);
+ return dcesrv_samr_CreateUser2(dce_call, mem_ctx, &r2);
}
/*
samr_EnumDomainUsers
*/
-static NTSTATUS samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_EnumDomainUsers *r)
{
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
struct ldb_message **res;
- int count, i, first;
+ int count, num_filtered_entries, i, first;
struct samr_SamEntry *entries;
- const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
+ const char * const attrs[] = { "objectSid", "sAMAccountName", "userAccountControl", NULL };
*r->out.resume_handle = 0;
r->out.sam = NULL;
/* search for all users in this domain. This could possibly be cached and
resumed based on resume_key */
- count = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
+ count = gendb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
"objectclass=user");
if (count == -1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
if (!entries) {
return NT_STATUS_NO_MEMORY;
}
+ num_filtered_entries = 0;
for (i=0;i<count;i++) {
- entries[i].idx = samdb_result_rid_from_sid(mem_ctx, res[i], "objectSid", 0);
- entries[i].name.string = samdb_result_string(res[i], "sAMAccountName", "");
+ /* Check if a mask has been requested */
+ if (r->in.acct_flags
+ && ((samdb_result_acct_flags(res[i],
+ "userAccountControl") & r->in.acct_flags) == 0)) {
+ continue;
+ }
+ entries[num_filtered_entries].idx = samdb_result_rid_from_sid(mem_ctx, res[i], "objectSid", 0);
+ entries[num_filtered_entries].name.string = samdb_result_string(res[i], "sAMAccountName", "");
+ num_filtered_entries++;
}
/* sort the results by rid */
- qsort(entries, count, sizeof(struct samr_SamEntry),
+ qsort(entries, num_filtered_entries, sizeof(struct samr_SamEntry),
(comparison_fn_t)compare_SamEntry);
/* find the first entry to return */
for (first=0;
- first<count && entries[first].idx <= *r->in.resume_handle;
+ first<num_filtered_entries && entries[first].idx <= *r->in.resume_handle;
first++) ;
- if (first == count) {
- return NT_STATUS_OK;
- }
-
/* return the rest, limit by max_size. Note that we
use the w2k3 element size value of 54 */
- r->out.num_entries = count - first;
+ r->out.num_entries = num_filtered_entries - first;
r->out.num_entries = MIN(r->out.num_entries,
1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
r->out.sam->entries = entries+first;
r->out.sam->count = r->out.num_entries;
- if (r->out.num_entries < count - first) {
+ if (first == num_filtered_entries) {
+ return NT_STATUS_OK;
+ }
+
+ if (r->out.num_entries < num_filtered_entries - first) {
*r->out.resume_handle = entries[first+r->out.num_entries-1].idx;
return STATUS_MORE_ENTRIES;
}
/*
samr_CreateDomAlias
*/
-static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_CreateDomAlias *r)
{
struct samr_domain_state *d_state;
struct samr_account_state *a_state;
struct dcesrv_handle *h;
- const char *aliasname, *name, *sidstr;
+ const char *alias_name, *name;
struct ldb_message *msg;
- uint32_t rid;
+ struct dom_sid *sid;
struct dcesrv_handle *a_handle;
int ret;
- NTSTATUS status;
ZERO_STRUCTP(r->out.alias_handle);
*r->out.rid = 0;
d_state = h->data;
- aliasname = r->in.aliasname->string;
+ alias_name = r->in.alias_name->string;
- if (aliasname == NULL) {
+ if (alias_name == NULL) {
return NT_STATUS_INVALID_PARAMETER;
}
/* Check if alias already exists */
name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
"sAMAccountName",
- "(&(sAMAccountName=%s)(objectclass=group))",
- aliasname);
+ "(sAMAccountName=%s)(objectclass=group))",
+ ldb_binary_encode_string(mem_ctx, alias_name));
if (name != NULL) {
return NT_STATUS_ALIAS_EXISTS;
return NT_STATUS_NO_MEMORY;
}
- /* pull in all the template attributes */
- ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg,
- "(&(name=TemplateAlias)"
- "(objectclass=aliasTemplate))");
- if (ret != 0) {
- DEBUG(0,("Failed to load TemplateAlias from samdb\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- /* allocate a rid */
- status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx,
- d_state->domain_dn, "nextRid", &rid);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* and the group SID */
- sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
- if (!sidstr) {
- return NT_STATUS_NO_MEMORY;
- }
-
/* 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);
+ msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
+ ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", alias_name);
if (!msg->dn) {
return NT_STATUS_NO_MEMORY;
}
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "name", aliasname);
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "cn", aliasname);
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", aliasname);
+ samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", alias_name);
samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group");
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectSid", sidstr);
+ samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "groupType", GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
/* create the alias */
- ret = samdb_add(d_state->sam_ctx, mem_ctx, msg);
- if (ret != 0) {
- DEBUG(0,("Failed to create alias record %s\n", msg->dn));
+ ret = ldb_add(d_state->sam_ctx, msg);
+ switch (ret) {
+ case LDB_SUCCESS:
+ break;
+ case LDB_ERR_ENTRY_ALREADY_EXISTS:
+ return NT_STATUS_ALIAS_EXISTS;
+ case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
+ return NT_STATUS_ACCESS_DENIED;
+ default:
+ DEBUG(0,("Failed to create alias record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(d_state->sam_ctx)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
a_state->access_mask = r->in.access_mask;
a_state->domain_state = talloc_reference(a_state, d_state);
a_state->account_dn = talloc_steal(a_state, msg->dn);
- a_state->account_sid = talloc_steal(a_state, sidstr);
- a_state->account_name = talloc_strdup(a_state, aliasname);
+
+ /* retrieve the sid for the alias just created */
+ sid = samdb_search_dom_sid(d_state->sam_ctx, a_state,
+ msg->dn, "objectSid", NULL);
+
+ a_state->account_name = talloc_strdup(a_state, alias_name);
if (!a_state->account_name) {
return NT_STATUS_NO_MEMORY;
}
a_handle->data = talloc_steal(a_handle, a_state);
*r->out.alias_handle = a_handle->wire_handle;
- *r->out.rid = rid;
+
+ *r->out.rid = sid->sub_auths[sid->num_auths-1];
return NT_STATUS_OK;
}
/*
samr_EnumDomainAliases
*/
-static NTSTATUS samr_EnumDomainAliases(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_EnumDomainAliases(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_EnumDomainAliases *r)
{
struct dcesrv_handle *h;
int ldb_cnt, count, i, first;
struct samr_SamEntry *entries;
const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
- struct dom_sid *domain_sid;
*r->out.resume_handle = 0;
r->out.sam = NULL;
d_state = h->data;
- domain_sid = dom_sid_parse_talloc(mem_ctx, d_state->domain_sid);
- if (domain_sid == NULL)
- return NT_STATUS_NO_MEMORY;
-
/* search for all domain groups in this domain. This could possibly be
cached and resumed based on resume_key */
ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
d_state->domain_dn,
- &res, attrs, domain_sid,
- "(&(|(grouptype=%s)(grouptype=%s)))"
+ &res, attrs,
+ d_state->domain_sid,
+ "(&(|(grouptype=%d)(grouptype=%d)))"
"(objectclass=group))",
- ldb_hexstr(mem_ctx,
- GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
- ldb_hexstr(mem_ctx,
- GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
+ GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
+ GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
if (ldb_cnt == -1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
/*
samr_GetAliasMembership
*/
-static NTSTATUS samr_GetAliasMembership(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_GetAliasMembership(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_GetAliasMembership *r)
{
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
struct ldb_message **res;
- struct dom_sid *domain_sid;
int i, count = 0;
DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
const char * const attrs[2] = { "objectSid", NULL };
filter = talloc_asprintf(mem_ctx,
- "(&(|(grouptype=%s)(grouptype=%s))"
+ "(&(|(grouptype=%d)(grouptype=%d))"
"(objectclass=group)(|",
- ldb_hexstr(mem_ctx,
- GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
- ldb_hexstr(mem_ctx,
- GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
+ GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
+ GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
if (filter == NULL)
return NT_STATUS_NO_MEMORY;
for (i=0; i<r->in.sids->num_sids; i++) {
- const char *sidstr, *memberdn;
+ const char *memberdn;
- sidstr = dom_sid_string(mem_ctx,
- r->in.sids->sids[i].sid);
- if (sidstr == NULL)
- return NT_STATUS_NO_MEMORY;
-
- memberdn = samdb_search_string(d_state->sam_ctx,
- mem_ctx, NULL, "dn",
- "(objectSid=%s)",
- sidstr);
+ memberdn =
+ samdb_search_string(d_state->sam_ctx,
+ mem_ctx, NULL, "distinguishedName",
+ "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx,
+ r->in.sids->sids[i].sid));
if (memberdn == NULL)
continue;
return NT_STATUS_NO_MEMORY;
}
- domain_sid = dom_sid_parse_talloc(mem_ctx,
- d_state->domain_sid);
- if (domain_sid == NULL)
- return NT_STATUS_NO_MEMORY;
-
count = samdb_search_domain(d_state->sam_ctx, mem_ctx,
d_state->domain_dn, &res, attrs,
- domain_sid, "%s))", filter);
+ d_state->domain_sid, "%s))", filter);
if (count < 0)
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
/*
samr_LookupNames
*/
-static NTSTATUS samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_LookupNames *r)
{
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
- int i;
+ int i, num_mapped;
NTSTATUS status = NT_STATUS_OK;
const char * const attrs[] = { "sAMAccountType", "objectSid", NULL };
int count;
r->out.rids.count = r->in.num_names;
r->out.types.count = r->in.num_names;
+ num_mapped = 0;
+
for (i=0;i<r->in.num_names;i++) {
struct ldb_message **res;
- struct dom_sid2 *sid;
- const char *sidstr;
+ struct dom_sid *sid;
uint32_t atype, rtype;
r->out.rids.ids[i] = 0;
r->out.types.ids[i] = SID_NAME_UNKNOWN;
- count = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
- "sAMAccountName=%s", r->in.names[i].string);
+ count = gendb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
+ "sAMAccountName=%s",
+ ldb_binary_encode_string(mem_ctx, r->in.names[i].string));
if (count != 1) {
status = STATUS_SOME_UNMAPPED;
continue;
}
- sidstr = samdb_result_string(res[0], "objectSid", NULL);
- if (sidstr == NULL) {
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
-
- sid = dom_sid_parse_talloc(mem_ctx, sidstr);
+ sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
if (sid == NULL) {
status = STATUS_SOME_UNMAPPED;
continue;
}
-
+
atype = samdb_result_uint(res[0], "sAMAccountType", 0);
if (atype == 0) {
status = STATUS_SOME_UNMAPPED;
r->out.rids.ids[i] = sid->sub_auths[sid->num_auths-1];
r->out.types.ids[i] = rtype;
+ num_mapped++;
}
-
+ if (num_mapped == 0) {
+ return NT_STATUS_NONE_MAPPED;
+ }
return status;
}
/*
samr_LookupRids
*/
-static NTSTATUS samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_LookupRids *r)
{
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
- int i;
+ int i, total;
NTSTATUS status = NT_STATUS_OK;
- struct samr_String *names;
+ struct lsa_String *names;
uint32_t *ids;
ZERO_STRUCT(r->out.names);
if (r->in.num_rids == 0)
return NT_STATUS_OK;
- names = talloc_array(mem_ctx, struct samr_String, r->in.num_rids);
+ names = talloc_array(mem_ctx, struct lsa_String, r->in.num_rids);
ids = talloc_array(mem_ctx, uint32_t, r->in.num_rids);
if ((names == NULL) || (ids == NULL))
return NT_STATUS_NO_MEMORY;
+ total = 0;
+
for (i=0; i<r->in.num_rids; i++) {
struct ldb_message **res;
int count;
const char * const attrs[] = { "sAMAccountType",
"sAMAccountName", NULL };
uint32_t atype;
+ struct dom_sid *sid;
ids[i] = SID_NAME_UNKNOWN;
- count = samdb_search(d_state->sam_ctx, mem_ctx,
+ sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rids[i]);
+ if (sid == NULL) {
+ names[i].string = NULL;
+ status = STATUS_SOME_UNMAPPED;
+ continue;
+ }
+
+ count = gendb_search(d_state->sam_ctx, mem_ctx,
d_state->domain_dn, &res, attrs,
- "(objectSid=%s-%u)", d_state->domain_sid,
- r->in.rids[i]);
+ "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx, sid));
if (count != 1) {
+ names[i].string = NULL;
status = STATUS_SOME_UNMAPPED;
continue;
}
names[i].string = samdb_result_string(res[0], "sAMAccountName",
NULL);
-
+
atype = samdb_result_uint(res[0], "sAMAccountType", 0);
if (atype == 0) {
status = STATUS_SOME_UNMAPPED;
/*
samr_OpenGroup
*/
-static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_OpenGroup *r)
{
struct samr_domain_state *d_state;
struct samr_account_state *a_state;
struct dcesrv_handle *h;
- const char *groupname, *sidstr;
+ const char *groupname;
+ struct dom_sid *sid;
struct ldb_message **msgs;
struct dcesrv_handle *g_handle;
const char * const attrs[2] = { "sAMAccountName", NULL };
d_state = h->data;
/* form the group SID */
- sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, r->in.rid);
- if (!sidstr) {
+ sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
+ if (!sid) {
return NT_STATUS_NO_MEMORY;
}
/* search for the group record */
- ret = samdb_search(d_state->sam_ctx,
+ ret = gendb_search(d_state->sam_ctx,
mem_ctx, d_state->domain_dn, &msgs, attrs,
"(&(objectSid=%s)(objectclass=group)"
- "(grouptype=%s))",
- sidstr, ldb_hexstr(mem_ctx,
- GTYPE_SECURITY_GLOBAL_GROUP));
+ "(grouptype=%d))",
+ ldap_encode_ndr_dom_sid(mem_ctx, sid),
+ GTYPE_SECURITY_GLOBAL_GROUP);
if (ret == 0) {
return NT_STATUS_NO_SUCH_GROUP;
}
if (ret != 1) {
- DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
+ DEBUG(0,("Found %d records matching sid %s\n",
+ ret, dom_sid_string(mem_ctx, sid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
groupname = samdb_result_string(msgs[0], "sAMAccountName", NULL);
if (groupname == NULL) {
- DEBUG(0,("sAMAccountName field missing for sid %s\n", sidstr));
+ DEBUG(0,("sAMAccountName field missing for sid %s\n",
+ dom_sid_string(mem_ctx, sid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
a_state = talloc(d_state, struct samr_account_state);
if (!a_state) {
- return NT_STATUS_NO_MEMORY;
- }
- a_state->sam_ctx = d_state->sam_ctx;
- a_state->access_mask = r->in.access_mask;
- a_state->domain_state = talloc_reference(a_state, d_state);
- a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
- a_state->account_sid = talloc_steal(a_state, sidstr);
- a_state->account_name = talloc_strdup(a_state, groupname);
- if (!a_state->account_name) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* create the policy handle */
- g_handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_GROUP);
- if (!g_handle) {
- return NT_STATUS_NO_MEMORY;
- }
-
- g_handle->data = talloc_steal(g_handle, a_state);
-
- *r->out.group_handle = g_handle->wire_handle;
-
- return NT_STATUS_OK;
-}
-
-/* these query macros make samr_Query[User|Group]Info a bit easier to read */
-
-#define QUERY_STRING(msg, field, attr) \
- r->out.info->field = samdb_result_string(msg, attr, "");
-#define QUERY_UINT(msg, field, attr) \
- r->out.info->field = samdb_result_uint(msg, attr, 0);
-#define QUERY_RID(msg, field, attr) \
- r->out.info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0);
-#define QUERY_NTTIME(msg, field, attr) \
- r->out.info->field = samdb_result_nttime(msg, attr, 0);
-#define QUERY_APASSC(msg, field, attr) \
- r->out.info->field = samdb_result_allow_password_change(a_state->sam_ctx, mem_ctx, \
- a_state->domain_state->domain_dn, msg, attr);
-#define QUERY_FPASSC(msg, field, attr) \
- r->out.info->field = samdb_result_force_password_change(a_state->sam_ctx, mem_ctx, \
- a_state->domain_state->domain_dn, msg, attr);
-#define QUERY_LHOURS(msg, field, attr) \
- r->out.info->field = samdb_result_logon_hours(mem_ctx, msg, attr);
-#define QUERY_AFLAGS(msg, field, attr) \
- r->out.info->field = samdb_result_acct_flags(msg, attr);
-
-
-/* these are used to make the Set[User|Group]Info code easier to follow */
+ return NT_STATUS_NO_MEMORY;
+ }
+ a_state->sam_ctx = d_state->sam_ctx;
+ a_state->access_mask = r->in.access_mask;
+ a_state->domain_state = talloc_reference(a_state, d_state);
+ a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
+ a_state->account_sid = talloc_steal(a_state, sid);
+ a_state->account_name = talloc_strdup(a_state, groupname);
+ if (!a_state->account_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
-#define SET_STRING(mod, field, attr) do { \
- if (r->in.info->field == NULL) return NT_STATUS_INVALID_PARAMETER; \
- if (samdb_msg_add_string(a_state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
- return NT_STATUS_NO_MEMORY; \
- } \
-} while (0)
+ /* create the policy handle */
+ g_handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_GROUP);
+ if (!g_handle) {
+ return NT_STATUS_NO_MEMORY;
+ }
-#define SET_UINT(mod, field, attr) do { \
- if (samdb_msg_add_uint(a_state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
- return NT_STATUS_NO_MEMORY; \
- } \
-} while (0)
+ g_handle->data = talloc_steal(g_handle, a_state);
-#define SET_AFLAGS(msg, field, attr) do { \
- if (samdb_msg_add_acct_flags(a_state->sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
- return NT_STATUS_NO_MEMORY; \
- } \
-} while (0)
+ *r->out.group_handle = g_handle->wire_handle;
-#define SET_LHOURS(msg, field, attr) do { \
- if (samdb_msg_add_logon_hours(a_state->sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
- return NT_STATUS_NO_MEMORY; \
- } \
-} while (0)
+ return NT_STATUS_OK;
+}
/*
samr_QueryGroupInfo
*/
-static NTSTATUS samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QueryGroupInfo *r)
{
struct dcesrv_handle *h;
a_state = h->data;
/* pull all the group attributes */
- ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, attrs,
- "dn=%s", a_state->account_dn);
+ ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
+ a_state->account_dn, &res, attrs);
if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
/* Fill in the level */
switch (r->in.level) {
- case GroupInfoAll:
- QUERY_STRING(msg, all.name.string, "sAMAccountName");
- r->out.info->all.attributes = 7; /* Do like w2k3 */
+ case GROUPINFOALL:
+ QUERY_STRING(msg, all.name, "sAMAccountName");
+ r->out.info->all.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */
QUERY_UINT (msg, all.num_members, "numMembers")
- QUERY_STRING(msg, all.description.string, "description");
+ QUERY_STRING(msg, all.description, "description");
+ break;
+ case GROUPINFONAME:
+ QUERY_STRING(msg, name, "sAMAccountName");
break;
- case GroupInfoName:
- QUERY_STRING(msg, name.string, "sAMAccountName");
+ case GROUPINFOATTRIBUTES:
+ r->out.info->attributes.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */
break;
- case GroupInfoX:
- r->out.info->unknown.unknown = 7;
+ case GROUPINFODESCRIPTION:
+ QUERY_STRING(msg, description, "description");
break;
- case GroupInfoDescription:
- QUERY_STRING(msg, description.string, "description");
+ case GROUPINFOALL2:
+ QUERY_STRING(msg, all2.name, "sAMAccountName");
+ r->out.info->all.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */
+ QUERY_UINT (msg, all2.num_members, "numMembers")
+ QUERY_STRING(msg, all2.description, "description");
break;
default:
r->out.info = NULL;
/*
samr_SetGroupInfo
*/
-static NTSTATUS samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_SetGroupInfo *r)
{
struct dcesrv_handle *h;
- struct samr_account_state *a_state;
+ struct samr_account_state *g_state;
struct ldb_message *msg;
+ struct ldb_context *sam_ctx;
int ret;
DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
- a_state = h->data;
+ g_state = h->data;
+ sam_ctx = g_state->sam_ctx;
msg = ldb_msg_new(mem_ctx);
if (msg == NULL) {
return NT_STATUS_NO_MEMORY;
}
- msg->dn = talloc_strdup(mem_ctx, a_state->account_dn);
+ msg->dn = ldb_dn_copy(mem_ctx, g_state->account_dn);
if (!msg->dn) {
return NT_STATUS_NO_MEMORY;
}
switch (r->in.level) {
- case GroupInfoDescription:
- SET_STRING(msg, description.string, "description");
+ case GROUPINFODESCRIPTION:
+ SET_STRING(msg, description, "description");
break;
- case GroupInfoName:
+ case GROUPINFONAME:
/* On W2k3 this does not change the name, it changes the
* sAMAccountName attribute */
- SET_STRING(msg, name.string, "sAMAccountName");
+ SET_STRING(msg, name, "sAMAccountName");
break;
- case GroupInfoX:
+ case GROUPINFOATTRIBUTES:
/* This does not do anything obviously visible in W2k3 LDAP */
- break;
+ return NT_STATUS_OK;
default:
return NT_STATUS_INVALID_INFO_CLASS;
}
/* modify the samdb record */
- ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
+ ret = ldb_modify(g_state->sam_ctx, msg);
if (ret != 0) {
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL;
/*
samr_AddGroupMember
*/
-static NTSTATUS samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_AddGroupMember *r)
{
struct dcesrv_handle *h;
struct samr_account_state *a_state;
struct samr_domain_state *d_state;
struct ldb_message *mod;
- char *membersidstr;
+ struct dom_sid *membersid;
const char *memberdn;
- struct ldb_message **msgs;
- const char * const attrs[2] = { "dn", NULL };
+ struct ldb_result *res;
+ const char * const attrs[] = { NULL };
int ret;
DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
a_state = h->data;
d_state = a_state->domain_state;
- membersidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid,
- r->in.rid);
- if (membersidstr == NULL)
+ membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
+ if (membersid == NULL)
return NT_STATUS_NO_MEMORY;
/* In native mode, AD can also nest domain groups. Not sure yet
* whether this is also available via RPC. */
- ret = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn,
- &msgs, attrs, "(&(objectSid=%s)(objectclass=user))",
- membersidstr);
+ ret = ldb_search_exp_fmt(d_state->sam_ctx, mem_ctx, &res,
+ d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
+ "(&(objectSid=%s)(objectclass=user))",
+ ldap_encode_ndr_dom_sid(mem_ctx, membersid));
- if (ret == 0)
- return NT_STATUS_NO_SUCH_USER;
+ if (ret != 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
- if (ret > 1)
+ if (res->count == 0) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ if (res->count > 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
- memberdn = samdb_result_string(msgs[0], "dn", NULL);
+ memberdn = ldb_dn_alloc_linearized(mem_ctx, res->msgs[0]->dn);
if (memberdn == NULL)
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ return NT_STATUS_NO_MEMORY;
mod = ldb_msg_new(mem_ctx);
if (mod == NULL) {
memberdn) != 0)
return NT_STATUS_UNSUCCESSFUL;
- if (samdb_modify(a_state->sam_ctx, mem_ctx, mod) != 0)
+ ret = ldb_modify(a_state->sam_ctx, mod);
+ switch (ret) {
+ case LDB_SUCCESS:
+ return NT_STATUS_OK;
+ case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
+ return NT_STATUS_MEMBER_IN_GROUP;
+ case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
+ return NT_STATUS_ACCESS_DENIED;
+ default:
return NT_STATUS_UNSUCCESSFUL;
+ }
- return NT_STATUS_OK;
}
/*
samr_DeleteDomainGroup
*/
-static NTSTATUS samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_DeleteDomainGroup *r)
{
struct dcesrv_handle *h;
a_state = h->data;
- ret = samdb_delete(a_state->sam_ctx, mem_ctx, a_state->account_dn);
+ ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
if (ret != 0) {
return NT_STATUS_UNSUCCESSFUL;
}
/*
samr_DeleteGroupMember
*/
-static NTSTATUS samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_DeleteGroupMember *r)
{
struct dcesrv_handle *h;
struct samr_account_state *a_state;
struct samr_domain_state *d_state;
struct ldb_message *mod;
- char *membersidstr;
+ struct dom_sid *membersid;
const char *memberdn;
- struct ldb_message **msgs;
- const char * const attrs[2] = { "dn", NULL };
+ struct ldb_result *res;
+ const char * const attrs[] = { NULL };
int ret;
DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
a_state = h->data;
d_state = a_state->domain_state;
- membersidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid,
- r->in.rid);
- if (membersidstr == NULL)
+ membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
+ if (membersid == NULL)
return NT_STATUS_NO_MEMORY;
/* In native mode, AD can also nest domain groups. Not sure yet
* whether this is also available via RPC. */
- ret = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn,
- &msgs, attrs, "(&(objectSid=%s)(objectclass=user))",
- membersidstr);
+ ret = ldb_search_exp_fmt(d_state->sam_ctx, mem_ctx, &res,
+ d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
+ "(&(objectSid=%s)(objectclass=user))",
+ ldap_encode_ndr_dom_sid(mem_ctx, membersid));
- if (ret == 0)
- return NT_STATUS_NO_SUCH_USER;
+ if (ret != 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
- if (ret > 1)
+ if (res->count == 0) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ if (res->count > 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
- memberdn = samdb_result_string(msgs[0], "dn", NULL);
+ memberdn = ldb_dn_alloc_linearized(mem_ctx, res->msgs[0]->dn);
if (memberdn == NULL)
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ return NT_STATUS_NO_MEMORY;
mod = ldb_msg_new(mem_ctx);
if (mod == NULL) {
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;
+ memberdn) != 0) {
+ return NT_STATUS_NO_MEMORY;
+ }
- if (samdb_modify(a_state->sam_ctx, mem_ctx, mod) != 0)
+ ret = ldb_modify(a_state->sam_ctx, mod);
+ switch (ret) {
+ case LDB_SUCCESS:
+ return NT_STATUS_OK;
+ case LDB_ERR_NO_SUCH_ATTRIBUTE:
+ return NT_STATUS_MEMBER_NOT_IN_GROUP;
+ case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
+ return NT_STATUS_ACCESS_DENIED;
+ default:
return NT_STATUS_UNSUCCESSFUL;
+ }
- return NT_STATUS_OK;
}
/*
samr_QueryGroupMember
*/
-static NTSTATUS samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct samr_QueryGroupMember *r)
+static NTSTATUS dcesrv_samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct samr_QueryGroupMember *r)
{
struct dcesrv_handle *h;
struct samr_account_state *a_state;
struct ldb_message **res;
struct ldb_message_element *el;
- struct samr_ridArray *array;
+ struct samr_RidTypeArray *array;
const char * const attrs[2] = { "member", NULL };
int ret;
a_state = h->data;
/* pull the member attribute */
- ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, attrs,
- "dn=%s", a_state->account_dn);
+ ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
+ a_state->account_dn, &res, attrs);
if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- array = talloc(mem_ctx, struct samr_ridArray);
+ array = talloc(mem_ctx, struct samr_RidTypeArray);
if (array == NULL)
return NT_STATUS_NO_MEMORY;
array->count = el->num_values;
- array->rids = talloc_array(mem_ctx, uint32,
+ array->rids = talloc_array(mem_ctx, uint32_t,
el->num_values);
if (array->rids == NULL)
return NT_STATUS_NO_MEMORY;
- array->unknown = talloc_array(mem_ctx, uint32,
- el->num_values);
- if (array->unknown == NULL)
+ array->types = talloc_array(mem_ctx, uint32_t,
+ el->num_values);
+ if (array->types == NULL)
return NT_STATUS_NO_MEMORY;
for (i=0; i<el->num_values; i++) {
struct ldb_message **res2;
const char * const attrs2[2] = { "objectSid", NULL };
- ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL,
- &res2, attrs2, "dn=%s",
- (char *)el->values[i].data);
+ ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
+ ldb_dn_new(mem_ctx, a_state->sam_ctx, (const char *)el->values[i].data),
+ &res2, attrs2);
if (ret != 1)
return NT_STATUS_INTERNAL_DB_CORRUPTION;
if (array->rids[i] == 0)
return NT_STATUS_INTERNAL_DB_CORRUPTION;
- array->unknown[i] = 7; /* Not sure what this is.. */
+ array->types[i] = 7; /* RID type of some kind, not sure what the value means. */
}
}
/*
samr_SetMemberAttributesOfGroup
*/
-static NTSTATUS samr_SetMemberAttributesOfGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_SetMemberAttributesOfGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_SetMemberAttributesOfGroup *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
/*
samr_OpenAlias
*/
-static NTSTATUS samr_OpenAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_OpenAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_OpenAlias *r)
{
struct samr_domain_state *d_state;
struct samr_account_state *a_state;
struct dcesrv_handle *h;
- const char *aliasname, *sidstr;
+ const char *alias_name;
+ struct dom_sid *sid;
struct ldb_message **msgs;
struct dcesrv_handle *g_handle;
const char * const attrs[2] = { "sAMAccountName", NULL };
d_state = h->data;
/* form the alias SID */
- sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid,
- r->in.rid);
- if (sidstr == NULL)
+ sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
+ if (sid == NULL)
return NT_STATUS_NO_MEMORY;
/* search for the group record */
- ret = samdb_search(d_state->sam_ctx,
+ ret = gendb_search(d_state->sam_ctx,
mem_ctx, d_state->domain_dn, &msgs, attrs,
"(&(objectSid=%s)(objectclass=group)"
- "(|(grouptype=%s)(grouptype=%s)))",
- sidstr,
- ldb_hexstr(mem_ctx,
- GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
- ldb_hexstr(mem_ctx,
- GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
+ "(|(grouptype=%d)(grouptype=%d)))",
+ ldap_encode_ndr_dom_sid(mem_ctx, sid),
+ GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
+ GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
if (ret == 0) {
return NT_STATUS_NO_SUCH_ALIAS;
}
if (ret != 1) {
- DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
+ DEBUG(0,("Found %d records matching sid %s\n",
+ ret, dom_sid_string(mem_ctx, sid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- aliasname = samdb_result_string(msgs[0], "sAMAccountName", NULL);
- if (aliasname == NULL) {
- DEBUG(0,("sAMAccountName field missing for sid %s\n", sidstr));
+ alias_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);
+ if (alias_name == NULL) {
+ DEBUG(0,("sAMAccountName field missing for sid %s\n",
+ dom_sid_string(mem_ctx, sid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
a_state->access_mask = r->in.access_mask;
a_state->domain_state = talloc_reference(a_state, d_state);
a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
- a_state->account_sid = talloc_steal(a_state, sidstr);
- a_state->account_name = talloc_strdup(a_state, aliasname);
+ a_state->account_sid = talloc_steal(a_state, sid);
+ a_state->account_name = talloc_strdup(a_state, alias_name);
if (!a_state->account_name) {
return NT_STATUS_NO_MEMORY;
}
/*
samr_QueryAliasInfo
*/
-static NTSTATUS samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QueryAliasInfo *r)
{
struct dcesrv_handle *h;
a_state = h->data;
/* pull all the alias attributes */
- ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, attrs,
- "dn=%s", a_state->account_dn);
+ ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
+ a_state->account_dn ,&res, attrs);
if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ZERO_STRUCTP(r->out.info);
switch(r->in.level) {
- case AliasInfoAll:
- QUERY_STRING(msg, all.name.string, "sAMAccountName");
+ case ALIASINFOALL:
+ QUERY_STRING(msg, all.name, "sAMAccountName");
QUERY_UINT (msg, all.num_members, "numMembers");
- QUERY_STRING(msg, all.description.string, "description");
+ QUERY_STRING(msg, all.description, "description");
break;
- case AliasInfoName:
- QUERY_STRING(msg, name.string, "sAMAccountName");
+ case ALIASINFONAME:
+ QUERY_STRING(msg, name, "sAMAccountName");
break;
- case AliasInfoDescription:
- QUERY_STRING(msg, description.string, "description");
+ case ALIASINFODESCRIPTION:
+ QUERY_STRING(msg, description, "description");
break;
default:
r->out.info = NULL;
/*
samr_SetAliasInfo
*/
-static NTSTATUS samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_SetAliasInfo *r)
{
struct dcesrv_handle *h;
struct samr_account_state *a_state;
struct ldb_message *msg;
+ struct ldb_context *sam_ctx;
int ret;
DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
a_state = h->data;
+ sam_ctx = a_state->sam_ctx;
msg = ldb_msg_new(mem_ctx);
if (msg == NULL) {
return NT_STATUS_NO_MEMORY;
}
- msg->dn = talloc_strdup(mem_ctx, a_state->account_dn);
+ msg->dn = ldb_dn_copy(mem_ctx, a_state->account_dn);
if (!msg->dn) {
return NT_STATUS_NO_MEMORY;
}
switch (r->in.level) {
- case AliasInfoDescription:
- SET_STRING(msg, description.string, "description");
+ case ALIASINFODESCRIPTION:
+ SET_STRING(msg, description, "description");
break;
- case AliasInfoName:
+ case ALIASINFONAME:
/* On W2k3 this does not change the name, it changes the
* sAMAccountName attribute */
- SET_STRING(msg, name.string, "sAMAccountName");
+ SET_STRING(msg, name, "sAMAccountName");
break;
default:
return NT_STATUS_INVALID_INFO_CLASS;
}
/* modify the samdb record */
- ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
+ ret = ldb_modify(a_state->sam_ctx, msg);
if (ret != 0) {
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL;
/*
samr_DeleteDomAlias
*/
-static NTSTATUS samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_DeleteDomAlias *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct dcesrv_handle *h;
+ struct samr_account_state *a_state;
+ int ret;
+
+ *r->out.alias_handle = *r->in.alias_handle;
+
+ DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
+
+ a_state = h->data;
+
+ ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
+ if (ret != 0) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ZERO_STRUCTP(r->out.alias_handle);
+
+ return NT_STATUS_OK;
}
/*
samr_AddAliasMember
*/
-static NTSTATUS samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_AddAliasMember *r)
{
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;
+ const char * const attrs[] = { NULL };
+ struct ldb_dn *memberdn = NULL;
int ret;
+ NTSTATUS status;
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);
+ ret = gendb_search(d_state->sam_ctx, mem_ctx, NULL,
+ &msgs, attrs, "(objectsid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
if (ret == 1) {
- memberdn = ldb_msg_find_string(msgs[0], "dn", NULL);
+ memberdn = msgs[0]->dn;
} else if (ret > 1) {
- DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
+ DEBUG(0,("Found %d records matching sid %s\n",
+ ret, dom_sid_string(mem_ctx, r->in.sid)));
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;
-
- msg = ldb_msg_new(mem_ctx);
- if (msg == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* 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;
+ status = samdb_create_foreign_security_principal(d_state->sam_ctx, mem_ctx,
+ r->in.sid, &memberdn);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
} else {
- DEBUG(0, ("samdb_search returned %d\n", ret));
+ DEBUG(0, ("samdb_search returned %d: %s\n", ret, ldb_errstring(d_state->sam_ctx)));
}
if (memberdn == NULL) {
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)
+ ldb_dn_alloc_linearized(mem_ctx, memberdn)) != 0)
return NT_STATUS_UNSUCCESSFUL;
- if (samdb_modify(a_state->sam_ctx, mem_ctx, mod) != 0)
+ if (ldb_modify(a_state->sam_ctx, mod) != 0)
return NT_STATUS_UNSUCCESSFUL;
return NT_STATUS_OK;
/*
samr_DeleteAliasMember
*/
-static NTSTATUS samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_DeleteAliasMember *r)
{
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;
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);
+ "distinguishedName", "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
if (memberdn == NULL)
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
memberdn) != 0)
return NT_STATUS_UNSUCCESSFUL;
- if (samdb_modify(a_state->sam_ctx, mem_ctx, mod) != 0)
+ if (ldb_modify(a_state->sam_ctx, mod) != 0)
return NT_STATUS_UNSUCCESSFUL;
return NT_STATUS_OK;
/*
samr_GetMembersInAlias
*/
-static NTSTATUS samr_GetMembersInAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_GetMembersInAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_GetMembersInAlias *r)
{
struct dcesrv_handle *h;
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);
+ ret = gendb_search_dn(d_state->sam_ctx, mem_ctx,
+ a_state->account_dn, &msgs, attrs);
if (ret != 1)
return NT_STATUS_INTERNAL_DB_CORRUPTION;
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);
+ ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
+ ldb_dn_new(mem_ctx, a_state->sam_ctx, (const char *)el->values[i].data),
+ &msgs2, attrs2);
if (ret != 1)
return NT_STATUS_INTERNAL_DB_CORRUPTION;
/*
samr_OpenUser
*/
-static NTSTATUS samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_OpenUser *r)
{
struct samr_domain_state *d_state;
struct samr_account_state *a_state;
struct dcesrv_handle *h;
- const char *account_name, *sidstr;
+ const char *account_name;
+ struct dom_sid *sid;
struct ldb_message **msgs;
struct dcesrv_handle *u_handle;
const char * const attrs[2] = { "sAMAccountName", NULL };
d_state = h->data;
/* form the users SID */
- sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, r->in.rid);
- if (!sidstr) {
+ sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
+ if (!sid) {
return NT_STATUS_NO_MEMORY;
}
/* search for the user record */
- ret = samdb_search(d_state->sam_ctx,
+ ret = gendb_search(d_state->sam_ctx,
mem_ctx, d_state->domain_dn, &msgs, attrs,
"(&(objectSid=%s)(objectclass=user))",
- sidstr);
+ ldap_encode_ndr_dom_sid(mem_ctx, sid));
if (ret == 0) {
return NT_STATUS_NO_SUCH_USER;
}
if (ret != 1) {
- DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
+ DEBUG(0,("Found %d records matching sid %s\n", ret,
+ dom_sid_string(mem_ctx, sid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
account_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);
if (account_name == NULL) {
- DEBUG(0,("sAMAccountName field missing for sid %s\n", sidstr));
+ DEBUG(0,("sAMAccountName field missing for sid %s\n",
+ dom_sid_string(mem_ctx, sid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
a_state->access_mask = r->in.access_mask;
a_state->domain_state = talloc_reference(a_state, d_state);
a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
- a_state->account_sid = talloc_steal(a_state, sidstr);
+ a_state->account_sid = talloc_steal(a_state, sid);
a_state->account_name = talloc_strdup(a_state, account_name);
if (!a_state->account_name) {
return NT_STATUS_NO_MEMORY;
/*
samr_DeleteUser
*/
-static NTSTATUS samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_DeleteUser *r)
{
struct dcesrv_handle *h;
a_state = h->data;
- ret = samdb_delete(a_state->sam_ctx, mem_ctx, a_state->account_dn);
+ ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
if (ret != 0) {
+ DEBUG(1, ("Failed to delete user: %s: %s\n",
+ ldb_dn_get_linearized(a_state->account_dn),
+ ldb_errstring(a_state->sam_ctx)));
return NT_STATUS_UNSUCCESSFUL;
}
/*
samr_QueryUserInfo
*/
-static NTSTATUS samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QueryUserInfo *r)
{
struct dcesrv_handle *h;
struct samr_account_state *a_state;
struct ldb_message *msg, **res;
int ret;
+ struct ldb_context *sam_ctx;
+
+ const char * const *attrs = NULL;
r->out.info = NULL;
DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
a_state = h->data;
+ sam_ctx = a_state->sam_ctx;
+
+ /* fill in the reply */
+ switch (r->in.level) {
+ case 1:
+ {
+ static const char * const attrs2[] = {"sAMAccountName", "displayName",
+ "primaryGroupID", "description",
+ "comment", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 2:
+ {
+ static const char * const attrs2[] = {"comment", "countryCode", "codePage", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 3:
+ {
+ static const char * const attrs2[] = {"sAMAccountName",
+ "displayName",
+ "objectSid",
+ "primaryGroupID",
+ "homeDirectory",
+ "homeDrive",
+ "scriptPath",
+ "profilePath",
+ "userWorkstations",
+ "lastLogon",
+ "lastLogoff",
+ "pwdLastSet",
+ "logonHours",
+ "badPwdCount",
+ "logonCount",
+ "userAccountControl", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 4:
+ {
+ static const char * const attrs2[] = {"logonHours", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 5:
+ {
+ static const char * const attrs2[] = {"sAMAccountName",
+ "displayName",
+ "objectSid",
+ "primaryGroupID",
+ "homeDirectory",
+ "homeDrive",
+ "scriptPath",
+ "profilePath",
+ "description",
+ "userWorkstations",
+ "lastLogon",
+ "lastLogoff",
+ "logonHours",
+ "badPwdCount",
+ "logonCount",
+ "pwdLastSet",
+ "accountExpires",
+ "userAccountControl",
+ NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 6:
+ {
+ static const char * const attrs2[] = {"sAMAccountName", "displayName", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 7:
+ {
+ static const char * const attrs2[] = {"sAMAccountName", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 8:
+ {
+ static const char * const attrs2[] = {"displayName", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 9:
+ {
+ static const char * const attrs2[] = {"primaryGroupID", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 10:
+ {
+ static const char * const attrs2[] = {"homeDirectory", "homeDrive", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 11:
+ {
+ static const char * const attrs2[] = {"scriptPath", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 12:
+ {
+ static const char * const attrs2[] = {"profilePath", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 13:
+ {
+ static const char * const attrs2[] = {"description", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 14:
+ {
+ static const char * const attrs2[] = {"userWorkstations", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 16:
+ {
+ static const char * const attrs2[] = {"userAccountControl", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 17:
+ {
+ static const char * const attrs2[] = {"accountExpires", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 20:
+ {
+ static const char * const attrs2[] = {"userParameters", NULL};
+ attrs = attrs2;
+ break;
+ }
+ case 21:
+ {
+ static const char * const attrs2[] = {"lastLogon",
+ "lastLogoff",
+ "pwdLastSet",
+ "accountExpires",
+ "sAMAccountName",
+ "displayName",
+ "homeDirectory",
+ "homeDrive",
+ "scriptPath",
+ "profilePath",
+ "description",
+ "userWorkstations",
+ "comment",
+ "userParameters",
+ "objectSid",
+ "primaryGroupID",
+ "userAccountControl",
+ "logonHours",
+ "badPwdCount",
+ "logonCount",
+ "countryCode",
+ "codePage",
+ NULL};
+ attrs = attrs2;
+ break;
+ }
+ }
/* pull all the user attributes */
- ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, NULL,
- "dn=%s", a_state->account_dn);
+ ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
+ a_state->account_dn ,&res, attrs);
if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
/* fill in the reply */
switch (r->in.level) {
case 1:
- QUERY_STRING(msg, info1.account_name.string, "sAMAccountName");
- QUERY_STRING(msg, info1.full_name.string, "displayName");
+ QUERY_STRING(msg, info1.account_name, "sAMAccountName");
+ QUERY_STRING(msg, info1.full_name, "displayName");
QUERY_UINT (msg, info1.primary_gid, "primaryGroupID");
- QUERY_STRING(msg, info1.description.string, "description");
- QUERY_STRING(msg, info1.comment.string, "comment");
+ QUERY_STRING(msg, info1.description, "description");
+ QUERY_STRING(msg, info1.comment, "comment");
break;
case 2:
- QUERY_STRING(msg, info2.comment.string, "comment");
+ QUERY_STRING(msg, info2.comment, "comment");
QUERY_UINT (msg, info2.country_code, "countryCode");
QUERY_UINT (msg, info2.code_page, "codePage");
break;
case 3:
- QUERY_STRING(msg, info3.account_name.string, "sAMAccountName");
- QUERY_STRING(msg, info3.full_name.string, "displayName");
+ QUERY_STRING(msg, info3.account_name, "sAMAccountName");
+ QUERY_STRING(msg, info3.full_name, "displayName");
QUERY_RID (msg, info3.rid, "objectSid");
QUERY_UINT (msg, info3.primary_gid, "primaryGroupID");
- QUERY_STRING(msg, info3.home_directory.string, "homeDirectory");
- QUERY_STRING(msg, info3.home_drive.string, "homeDrive");
- QUERY_STRING(msg, info3.logon_script.string, "scriptPath");
- QUERY_STRING(msg, info3.profile_path.string, "profilePath");
- QUERY_STRING(msg, info3.workstations.string, "userWorkstations");
- QUERY_NTTIME(msg, info3.last_logon, "lastLogon");
- QUERY_NTTIME(msg, info3.last_logoff, "lastLogoff");
- QUERY_NTTIME(msg, info3.last_password_change, "pwdLastSet");
+ QUERY_STRING(msg, info3.home_directory, "homeDirectory");
+ QUERY_STRING(msg, info3.home_drive, "homeDrive");
+ QUERY_STRING(msg, info3.logon_script, "scriptPath");
+ QUERY_STRING(msg, info3.profile_path, "profilePath");
+ QUERY_STRING(msg, info3.workstations, "userWorkstations");
+ QUERY_UINT64(msg, info3.last_logon, "lastLogon");
+ QUERY_UINT64(msg, info3.last_logoff, "lastLogoff");
+ QUERY_UINT64(msg, info3.last_password_change, "pwdLastSet");
QUERY_APASSC(msg, info3.allow_password_change, "pwdLastSet");
QUERY_FPASSC(msg, info3.force_password_change, "pwdLastSet");
QUERY_LHOURS(msg, info3.logon_hours, "logonHours");
break;
case 5:
- QUERY_STRING(msg, info5.account_name.string, "sAMAccountName");
- QUERY_STRING(msg, info5.full_name.string, "displayName");
+ QUERY_STRING(msg, info5.account_name, "sAMAccountName");
+ QUERY_STRING(msg, info5.full_name, "displayName");
QUERY_RID (msg, info5.rid, "objectSid");
QUERY_UINT (msg, info5.primary_gid, "primaryGroupID");
- QUERY_STRING(msg, info5.home_directory.string, "homeDirectory");
- QUERY_STRING(msg, info5.home_drive.string, "homeDrive");
- QUERY_STRING(msg, info5.logon_script.string, "scriptPath");
- QUERY_STRING(msg, info5.profile_path.string, "profilePath");
- QUERY_STRING(msg, info5.description.string, "description");
- QUERY_STRING(msg, info5.workstations.string, "userWorkstations");
- QUERY_NTTIME(msg, info5.last_logon, "lastLogon");
- QUERY_NTTIME(msg, info5.last_logoff, "lastLogoff");
+ QUERY_STRING(msg, info5.home_directory, "homeDirectory");
+ QUERY_STRING(msg, info5.home_drive, "homeDrive");
+ QUERY_STRING(msg, info5.logon_script, "scriptPath");
+ QUERY_STRING(msg, info5.profile_path, "profilePath");
+ QUERY_STRING(msg, info5.description, "description");
+ QUERY_STRING(msg, info5.workstations, "userWorkstations");
+ QUERY_UINT64(msg, info5.last_logon, "lastLogon");
+ QUERY_UINT64(msg, info5.last_logoff, "lastLogoff");
QUERY_LHOURS(msg, info5.logon_hours, "logonHours");
QUERY_UINT (msg, info5.bad_password_count, "badPwdCount");
QUERY_UINT (msg, info5.logon_count, "logonCount");
- QUERY_NTTIME(msg, info5.last_password_change, "pwdLastSet");
- QUERY_NTTIME(msg, info5.acct_expiry, "accountExpires");
+ QUERY_UINT64(msg, info5.last_password_change, "pwdLastSet");
+ QUERY_UINT64(msg, info5.acct_expiry, "accountExpires");
QUERY_AFLAGS(msg, info5.acct_flags, "userAccountControl");
break;
case 6:
- QUERY_STRING(msg, info6.account_name.string, "sAMAccountName");
- QUERY_STRING(msg, info6.full_name.string, "displayName");
+ QUERY_STRING(msg, info6.account_name, "sAMAccountName");
+ QUERY_STRING(msg, info6.full_name, "displayName");
break;
case 7:
- QUERY_STRING(msg, info7.account_name.string, "sAMAccountName");
+ QUERY_STRING(msg, info7.account_name, "sAMAccountName");
break;
case 8:
- QUERY_STRING(msg, info8.full_name.string, "displayName");
+ QUERY_STRING(msg, info8.full_name, "displayName");
break;
case 9:
- QUERY_UINT (msg, info9.primary_gid, "primaryGroupID");
+ QUERY_UINT (msg, info9.primary_gid, "primaryGroupID");
break;
case 10:
- QUERY_STRING(msg, info10.home_directory.string,"homeDirectory");
- QUERY_STRING(msg, info10.home_drive.string, "homeDrive");
+ QUERY_STRING(msg, info10.home_directory,"homeDirectory");
+ QUERY_STRING(msg, info10.home_drive, "homeDrive");
break;
case 11:
- QUERY_STRING(msg, info11.logon_script.string, "scriptPath");
+ QUERY_STRING(msg, info11.logon_script, "scriptPath");
break;
case 12:
- QUERY_STRING(msg, info12.profile_path.string, "profilePath");
+ QUERY_STRING(msg, info12.profile_path, "profilePath");
break;
case 13:
- QUERY_STRING(msg, info13.description.string, "description");
+ QUERY_STRING(msg, info13.description, "description");
break;
case 14:
- QUERY_STRING(msg, info14.workstations.string, "userWorkstations");
+ QUERY_STRING(msg, info14.workstations, "userWorkstations");
break;
case 16:
- QUERY_AFLAGS(msg, info16.acct_flags, "userAccountControl");
+ QUERY_AFLAGS(msg, info16.acct_flags, "userAccountControl");
break;
case 17:
- QUERY_NTTIME(msg, info17.acct_expiry, "accountExpires");
+ QUERY_UINT64(msg, info17.acct_expiry, "accountExpires");
+ break;
case 20:
- QUERY_STRING(msg, info20.parameters.string, "userParameters");
+ QUERY_STRING(msg, info20.parameters, "userParameters");
break;
case 21:
- QUERY_NTTIME(msg, info21.last_logon, "lastLogon");
- QUERY_NTTIME(msg, info21.last_logoff, "lastLogoff");
- QUERY_NTTIME(msg, info21.last_password_change, "pwdLastSet");
- QUERY_NTTIME(msg, info21.acct_expiry, "accountExpires");
+ QUERY_UINT64(msg, info21.last_logon, "lastLogon");
+ QUERY_UINT64(msg, info21.last_logoff, "lastLogoff");
+ QUERY_UINT64(msg, info21.last_password_change, "pwdLastSet");
+ QUERY_UINT64(msg, info21.acct_expiry, "accountExpires");
QUERY_APASSC(msg, info21.allow_password_change,"pwdLastSet");
QUERY_FPASSC(msg, info21.force_password_change,"pwdLastSet");
- QUERY_STRING(msg, info21.account_name.string, "sAMAccountName");
- QUERY_STRING(msg, info21.full_name.string, "displayName");
- QUERY_STRING(msg, info21.home_directory.string,"homeDirectory");
- QUERY_STRING(msg, info21.home_drive.string, "homeDrive");
- QUERY_STRING(msg, info21.logon_script.string, "scriptPath");
- QUERY_STRING(msg, info21.profile_path.string, "profilePath");
- QUERY_STRING(msg, info21.description.string, "description");
- QUERY_STRING(msg, info21.workstations.string, "userWorkstations");
- QUERY_STRING(msg, info21.comment.string, "comment");
- QUERY_STRING(msg, info21.parameters.string, "userParameters");
+ QUERY_STRING(msg, info21.account_name, "sAMAccountName");
+ QUERY_STRING(msg, info21.full_name, "displayName");
+ QUERY_STRING(msg, info21.home_directory, "homeDirectory");
+ QUERY_STRING(msg, info21.home_drive, "homeDrive");
+ QUERY_STRING(msg, info21.logon_script, "scriptPath");
+ QUERY_STRING(msg, info21.profile_path, "profilePath");
+ QUERY_STRING(msg, info21.description, "description");
+ QUERY_STRING(msg, info21.workstations, "userWorkstations");
+ QUERY_STRING(msg, info21.comment, "comment");
+ QUERY_STRING(msg, info21.parameters, "userParameters");
QUERY_RID (msg, info21.rid, "objectSid");
QUERY_UINT (msg, info21.primary_gid, "primaryGroupID");
QUERY_AFLAGS(msg, info21.acct_flags, "userAccountControl");
/*
samr_SetUserInfo
*/
-static NTSTATUS samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_SetUserInfo *r)
{
struct dcesrv_handle *h;
struct ldb_message *msg;
int ret;
NTSTATUS status = NT_STATUS_OK;
+ struct ldb_context *sam_ctx;
DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
a_state = h->data;
+ sam_ctx = a_state->sam_ctx;
msg = ldb_msg_new(mem_ctx);
if (msg == NULL) {
switch (r->in.level) {
case 2:
- SET_STRING(msg, info2.comment.string, "comment");
- SET_UINT (msg, info2.country_code, "countryCode");
- SET_UINT (msg, info2.code_page, "codePage");
+ SET_STRING(msg, info2.comment, "comment");
+ SET_UINT (msg, info2.country_code, "countryCode");
+ SET_UINT (msg, info2.code_page, "codePage");
break;
case 4:
- SET_LHOURS(msg, info4.logon_hours, "logonHours");
+ SET_LHOURS(msg, info4.logon_hours, "logonHours");
break;
case 6:
- SET_STRING(msg, info6.full_name.string, "displayName");
+ SET_STRING(msg, info6.full_name, "displayName");
+ break;
+
+ case 7:
+ SET_STRING(msg, info7.account_name, "samAccountName");
break;
case 8:
- SET_STRING(msg, info8.full_name.string, "displayName");
+ SET_STRING(msg, info8.full_name, "displayName");
break;
case 9:
- SET_UINT(msg, info9.primary_gid, "primaryGroupID");
+ SET_UINT(msg, info9.primary_gid, "primaryGroupID");
break;
case 10:
- SET_STRING(msg, info10.home_directory.string, "homeDirectory");
- SET_STRING(msg, info10.home_drive.string, "homeDrive");
+ SET_STRING(msg, info10.home_directory, "homeDirectory");
+ SET_STRING(msg, info10.home_drive, "homeDrive");
break;
case 11:
- SET_STRING(msg, info11.logon_script.string, "scriptPath");
+ SET_STRING(msg, info11.logon_script, "scriptPath");
break;
case 12:
- SET_STRING(msg, info12.profile_path.string, "profilePath");
+ SET_STRING(msg, info12.profile_path, "profilePath");
break;
case 13:
- SET_STRING(msg, info13.description.string, "description");
+ SET_STRING(msg, info13.description, "description");
break;
case 14:
- SET_STRING(msg, info14.workstations.string, "userWorkstations");
+ SET_STRING(msg, info14.workstations, "userWorkstations");
break;
case 16:
- SET_AFLAGS(msg, info16.acct_flags, "userAccountControl");
+ SET_AFLAGS(msg, info16.acct_flags, "userAccountControl");
+ break;
+
+ case 17:
+ SET_UINT64(msg, info17.acct_expiry, "accountExpires");
break;
case 20:
- SET_STRING(msg, info20.parameters.string, "userParameters");
+ SET_STRING(msg, info20.parameters, "userParameters");
break;
case 21:
-#define IFSET(bit) if (bit & r->in.info->info21.fields_present)
- IFSET(SAMR_FIELD_NAME)
- SET_STRING(msg, info21.full_name.string, "displayName");
- IFSET(SAMR_FIELD_DESCRIPTION)
- SET_STRING(msg, info21.description.string, "description");
- IFSET(SAMR_FIELD_COMMENT)
- SET_STRING(msg, info21.comment.string, "comment");
- IFSET(SAMR_FIELD_LOGON_SCRIPT)
- SET_STRING(msg, info21.logon_script.string, "scriptPath");
- IFSET(SAMR_FIELD_PROFILE_PATH)
- SET_STRING(msg, info21.profile_path.string, "profilePath");
- IFSET(SAMR_FIELD_WORKSTATION)
- SET_STRING(msg, info21.workstations.string, "userWorkstations");
- IFSET(SAMR_FIELD_LOGON_HOURS)
- SET_LHOURS(msg, info21.logon_hours, "logonHours");
- IFSET(SAMR_FIELD_ACCT_FLAGS)
- SET_AFLAGS(msg, info21.acct_flags, "userAccountControl");
- IFSET(SAMR_FIELD_PARAMETERS)
- SET_STRING(msg, info21.parameters.string, "userParameters");
- IFSET(SAMR_FIELD_COUNTRY_CODE)
- SET_UINT (msg, info21.country_code, "countryCode");
- IFSET(SAMR_FIELD_CODE_PAGE)
- SET_UINT (msg, info21.code_page, "codePage");
-
-
- /* Any reason the rest of these can't be set? */
+#define IFSET(bit) if (bit & r->in.info->info21.fields_present)
+ IFSET(SAMR_FIELD_ACCT_EXPIRY)
+ SET_UINT64(msg, info21.acct_expiry, "accountExpires");
+ IFSET(SAMR_FIELD_ACCOUNT_NAME)
+ SET_STRING(msg, info21.account_name, "samAccountName");
+ IFSET(SAMR_FIELD_FULL_NAME)
+ SET_STRING(msg, info21.full_name, "displayName");
+ IFSET(SAMR_FIELD_DESCRIPTION)
+ SET_STRING(msg, info21.description, "description");
+ IFSET(SAMR_FIELD_COMMENT)
+ SET_STRING(msg, info21.comment, "comment");
+ IFSET(SAMR_FIELD_LOGON_SCRIPT)
+ SET_STRING(msg, info21.logon_script, "scriptPath");
+ IFSET(SAMR_FIELD_PROFILE_PATH)
+ SET_STRING(msg, info21.profile_path, "profilePath");
+ IFSET(SAMR_FIELD_HOME_DIRECTORY)
+ SET_STRING(msg, info21.home_directory, "homeDirectory");
+ IFSET(SAMR_FIELD_HOME_DRIVE)
+ SET_STRING(msg, info21.home_drive, "homeDrive");
+ IFSET(SAMR_FIELD_WORKSTATIONS)
+ SET_STRING(msg, info21.workstations, "userWorkstations");
+ IFSET(SAMR_FIELD_LOGON_HOURS)
+ SET_LHOURS(msg, info21.logon_hours, "logonHours");
+ IFSET(SAMR_FIELD_ACCT_FLAGS)
+ SET_AFLAGS(msg, info21.acct_flags, "userAccountControl");
+ IFSET(SAMR_FIELD_PARAMETERS)
+ SET_STRING(msg, info21.parameters, "userParameters");
+ IFSET(SAMR_FIELD_COUNTRY_CODE)
+ SET_UINT (msg, info21.country_code, "countryCode");
+ IFSET(SAMR_FIELD_CODE_PAGE)
+ SET_UINT (msg, info21.code_page, "codePage");
#undef IFSET
break;
case 23:
#define IFSET(bit) if (bit & r->in.info->info23.info.fields_present)
- IFSET(SAMR_FIELD_NAME)
- SET_STRING(msg, info23.info.full_name.string, "displayName");
+ IFSET(SAMR_FIELD_ACCT_EXPIRY)
+ SET_UINT64(msg, info23.info.acct_expiry, "accountExpires");
+ IFSET(SAMR_FIELD_ACCOUNT_NAME)
+ SET_STRING(msg, info23.info.account_name, "samAccountName");
+ IFSET(SAMR_FIELD_FULL_NAME)
+ SET_STRING(msg, info23.info.full_name, "displayName");
IFSET(SAMR_FIELD_DESCRIPTION)
- SET_STRING(msg, info23.info.description.string, "description");
+ SET_STRING(msg, info23.info.description, "description");
IFSET(SAMR_FIELD_COMMENT)
- SET_STRING(msg, info23.info.comment.string, "comment");
+ SET_STRING(msg, info23.info.comment, "comment");
IFSET(SAMR_FIELD_LOGON_SCRIPT)
- SET_STRING(msg, info23.info.logon_script.string, "scriptPath");
+ SET_STRING(msg, info23.info.logon_script, "scriptPath");
IFSET(SAMR_FIELD_PROFILE_PATH)
- SET_STRING(msg, info23.info.profile_path.string, "profilePath");
- IFSET(SAMR_FIELD_WORKSTATION)
- SET_STRING(msg, info23.info.workstations.string, "userWorkstations");
+ SET_STRING(msg, info23.info.profile_path, "profilePath");
+ IFSET(SAMR_FIELD_WORKSTATIONS)
+ SET_STRING(msg, info23.info.workstations, "userWorkstations");
IFSET(SAMR_FIELD_LOGON_HOURS)
- SET_LHOURS(msg, info23.info.logon_hours, "logonHours");
+ SET_LHOURS(msg, info23.info.logon_hours, "logonHours");
IFSET(SAMR_FIELD_ACCT_FLAGS)
- SET_AFLAGS(msg, info23.info.acct_flags, "userAccountControl");
+ SET_AFLAGS(msg, info23.info.acct_flags, "userAccountControl");
IFSET(SAMR_FIELD_PARAMETERS)
- SET_STRING(msg, info23.info.parameters.string, "userParameters");
+ SET_STRING(msg, info23.info.parameters, "userParameters");
IFSET(SAMR_FIELD_COUNTRY_CODE)
- SET_UINT (msg, info23.info.country_code, "countryCode");
+ SET_UINT (msg, info23.info.country_code, "countryCode");
IFSET(SAMR_FIELD_CODE_PAGE)
- SET_UINT (msg, info23.info.code_page, "codePage");
+ SET_UINT (msg, info23.info.code_page, "codePage");
IFSET(SAMR_FIELD_PASSWORD) {
status = samr_set_password(dce_call,
a_state->sam_ctx,
case 25:
#define IFSET(bit) if (bit & r->in.info->info25.info.fields_present)
- IFSET(SAMR_FIELD_NAME)
- SET_STRING(msg, info25.info.full_name.string, "displayName");
+ IFSET(SAMR_FIELD_ACCT_EXPIRY)
+ SET_UINT64(msg, info25.info.acct_expiry, "accountExpires");
+ IFSET(SAMR_FIELD_ACCOUNT_NAME)
+ SET_STRING(msg, info25.info.account_name, "samAccountName");
+ IFSET(SAMR_FIELD_FULL_NAME)
+ SET_STRING(msg, info25.info.full_name, "displayName");
IFSET(SAMR_FIELD_DESCRIPTION)
- SET_STRING(msg, info25.info.description.string, "description");
+ SET_STRING(msg, info25.info.description, "description");
IFSET(SAMR_FIELD_COMMENT)
- SET_STRING(msg, info25.info.comment.string, "comment");
+ SET_STRING(msg, info25.info.comment, "comment");
IFSET(SAMR_FIELD_LOGON_SCRIPT)
- SET_STRING(msg, info25.info.logon_script.string, "scriptPath");
+ SET_STRING(msg, info25.info.logon_script, "scriptPath");
IFSET(SAMR_FIELD_PROFILE_PATH)
- SET_STRING(msg, info25.info.profile_path.string, "profilePath");
- IFSET(SAMR_FIELD_WORKSTATION)
- SET_STRING(msg, info25.info.workstations.string, "userWorkstations");
+ SET_STRING(msg, info25.info.profile_path, "profilePath");
+ IFSET(SAMR_FIELD_WORKSTATIONS)
+ SET_STRING(msg, info25.info.workstations, "userWorkstations");
IFSET(SAMR_FIELD_LOGON_HOURS)
- SET_LHOURS(msg, info25.info.logon_hours, "logonHours");
+ SET_LHOURS(msg, info25.info.logon_hours, "logonHours");
IFSET(SAMR_FIELD_ACCT_FLAGS)
- SET_AFLAGS(msg, info25.info.acct_flags, "userAccountControl");
+ SET_AFLAGS(msg, info25.info.acct_flags, "userAccountControl");
IFSET(SAMR_FIELD_PARAMETERS)
- SET_STRING(msg, info25.info.parameters.string, "userParameters");
+ SET_STRING(msg, info25.info.parameters, "userParameters");
IFSET(SAMR_FIELD_COUNTRY_CODE)
- SET_UINT (msg, info25.info.country_code, "countryCode");
+ SET_UINT (msg, info25.info.country_code, "countryCode");
IFSET(SAMR_FIELD_CODE_PAGE)
- SET_UINT (msg, info25.info.code_page, "codePage");
+ SET_UINT (msg, info25.info.code_page, "codePage");
IFSET(SAMR_FIELD_PASSWORD) {
status = samr_set_password_ex(dce_call,
a_state->sam_ctx,
}
/* modify the samdb record */
- ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
+ ret = ldb_modify(a_state->sam_ctx, msg);
if (ret != 0) {
+ DEBUG(1,("Failed to modify record %s: %s\n",
+ ldb_dn_get_linearized(a_state->account_dn),
+ ldb_errstring(a_state->sam_ctx)));
+
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL;
}
/*
samr_GetGroupsForUser
*/
-static NTSTATUS samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_GetGroupsForUser *r)
{
struct dcesrv_handle *h;
struct samr_account_state *a_state;
struct samr_domain_state *d_state;
struct ldb_message **res;
- struct dom_sid *domain_sid;
const char * const attrs[2] = { "objectSid", NULL };
- struct samr_RidArray *array;
+ struct samr_RidWithAttributeArray *array;
int count;
DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
a_state = h->data;
d_state = a_state->domain_state;
- domain_sid = dom_sid_parse_talloc(mem_ctx, d_state->domain_sid);
- if (domain_sid == NULL)
- return NT_STATUS_NO_MEMORY;
- count = samdb_search_domain(a_state->sam_ctx, mem_ctx, NULL, &res,
- attrs, domain_sid,
- "(&(member=%s)(grouptype=%s)(objectclass=group))",
- a_state->account_dn,
- ldb_hexstr(mem_ctx,
- GTYPE_SECURITY_GLOBAL_GROUP));
+ count = samdb_search_domain(a_state->sam_ctx, mem_ctx, d_state->domain_dn, &res,
+ attrs, d_state->domain_sid,
+ "(&(member=%s)(grouptype=%d)(objectclass=group))",
+ ldb_dn_get_linearized(a_state->account_dn),
+ GTYPE_SECURITY_GLOBAL_GROUP);
if (count < 0)
return NT_STATUS_INTERNAL_DB_CORRUPTION;
- array = talloc(mem_ctx, struct samr_RidArray);
+ array = talloc(mem_ctx, struct samr_RidWithAttributeArray);
if (array == NULL)
return NT_STATUS_NO_MEMORY;
array->count = 0;
- array->rid = NULL;
+ array->rids = NULL;
if (count > 0) {
int i;
- array->rid = talloc_array(mem_ctx, struct samr_RidType,
+ array->rids = talloc_array(mem_ctx, struct samr_RidWithAttribute,
count);
- if (array->rid == NULL)
+ if (array->rids == NULL)
return NT_STATUS_NO_MEMORY;
for (i=0; i<count; i++) {
continue;
}
- array->rid[array->count].rid =
+ array->rids[array->count].rid =
group_sid->sub_auths[group_sid->num_auths-1];
- array->rid[array->count].type = 7;
+ array->rids[array->count].attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
array->count += 1;
}
}
/*
samr_QueryDisplayInfo
*/
-static NTSTATUS samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QueryDisplayInfo *r)
{
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
struct ldb_message **res;
int ldb_cnt, count, i;
- const char * const attrs[4] = { "objectSid", "sAMAccountName",
- "description", NULL };
- struct dom_sid *domain_sid;
+ const char * const attrs[] = { "objectSid", "sAMAccountName", "displayName",
+ "description", "userAccountControl", NULL };
struct samr_DispEntryFull *entriesFull = NULL;
+ struct samr_DispEntryFullGroup *entriesFullGroup = NULL;
struct samr_DispEntryAscii *entriesAscii = NULL;
struct samr_DispEntryGeneral * entriesGeneral = NULL;
const char *filter;
case 1:
case 4:
filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)"
- "(sAMAccountType=%s))",
- ldb_hexstr(mem_ctx,
- ATYPE_NORMAL_ACCOUNT));
+ "(sAMAccountType=%u))",
+ ATYPE_NORMAL_ACCOUNT);
break;
case 2:
filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)"
- "(sAMAccountType=%s))",
- ldb_hexstr(mem_ctx,
- ATYPE_WORKSTATION_TRUST));
+ "(sAMAccountType=%u))",
+ ATYPE_WORKSTATION_TRUST);
break;
case 3:
case 5:
- filter = talloc_asprintf(mem_ctx, "(&(grouptype=%s)"
+ filter = talloc_asprintf(mem_ctx, "(&(grouptype=%d)"
"(objectclass=group))",
- ldb_hexstr(mem_ctx, GTYPE_SECURITY_GLOBAL_GROUP));
+ GTYPE_SECURITY_GLOBAL_GROUP);
break;
default:
return NT_STATUS_INVALID_INFO_CLASS;
}
- domain_sid = dom_sid_parse_talloc(mem_ctx, d_state->domain_sid);
- if (domain_sid == NULL)
- return NT_STATUS_NO_MEMORY;
-
/* search for all requested objects in this domain. This could
possibly be cached and resumed based on resume_key */
ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
d_state->domain_dn, &res, attrs,
- domain_sid, "%s", filter);
+ d_state->domain_sid, "%s", filter);
if (ldb_cnt == -1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ldb_cnt);
break;
case 2:
- case 3:
entriesFull = talloc_array(mem_ctx,
struct samr_DispEntryFull,
ldb_cnt);
break;
+ case 3:
+ entriesFullGroup = talloc_array(mem_ctx,
+ struct samr_DispEntryFullGroup,
+ ldb_cnt);
+ break;
case 4:
case 5:
entriesAscii = talloc_array(mem_ctx,
}
if ((entriesGeneral == NULL) && (entriesFull == NULL) &&
- (entriesAscii == NULL))
+ (entriesAscii == NULL) && (entriesFullGroup == NULL))
return NT_STATUS_NO_MEMORY;
count = 0;
switch(r->in.level) {
case 1:
- entriesGeneral[count].idx = count;
+ entriesGeneral[count].idx = count + 1;
entriesGeneral[count].rid =
objectsid->sub_auths[objectsid->num_auths-1];
entriesGeneral[count].acct_flags =
samdb_result_string(res[i], "description", "");
break;
case 2:
- case 3:
- entriesFull[count].idx = count;
+ entriesFull[count].idx = count + 1;
entriesFull[count].rid =
objectsid->sub_auths[objectsid->num_auths-1];
+
+ /* No idea why we need to or in ACB_NORMAL here, but this is what Win2k3 seems to do... */
entriesFull[count].acct_flags =
samdb_result_acct_flags(res[i],
- "userAccountControl");
- if (r->in.level == 3) {
- /* We get a "7" here for groups */
- entriesFull[count].acct_flags = 7;
- }
+ "userAccountControl") | ACB_NORMAL;
entriesFull[count].account_name.string =
samdb_result_string(res[i], "sAMAccountName",
"");
entriesFull[count].description.string =
samdb_result_string(res[i], "description", "");
break;
+ case 3:
+ entriesFullGroup[count].idx = count + 1;
+ entriesFullGroup[count].rid =
+ objectsid->sub_auths[objectsid->num_auths-1];
+ entriesFullGroup[count].acct_flags =
+ samdb_result_acct_flags(res[i],
+ "userAccountControl");
+ /* We get a "7" here for groups */
+ entriesFullGroup[count].acct_flags
+ = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
+ entriesFullGroup[count].account_name.string =
+ samdb_result_string(res[i], "sAMAccountName",
+ "");
+ entriesFullGroup[count].description.string =
+ samdb_result_string(res[i], "description", "");
+ break;
case 4:
case 5:
- entriesAscii[count].idx = count;
+ entriesAscii[count].idx = count + 1;
entriesAscii[count].account_name.string =
samdb_result_string(res[i], "sAMAccountName",
"");
case 3:
r->out.info.info3.count = r->out.returned_size;
r->out.info.info3.entries =
- &(entriesFull[r->in.start_idx]);
+ &(entriesFullGroup[r->in.start_idx]);
break;
case 4:
r->out.info.info4.count = r->out.returned_size;
/*
samr_GetDisplayEnumerationIndex
*/
-static NTSTATUS samr_GetDisplayEnumerationIndex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_GetDisplayEnumerationIndex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_GetDisplayEnumerationIndex *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
/*
samr_TestPrivateFunctionsDomain
*/
-static NTSTATUS samr_TestPrivateFunctionsDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_TestPrivateFunctionsDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_TestPrivateFunctionsDomain *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ return NT_STATUS_NOT_IMPLEMENTED;
}
/*
samr_TestPrivateFunctionsUser
*/
-static NTSTATUS samr_TestPrivateFunctionsUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_TestPrivateFunctionsUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_TestPrivateFunctionsUser *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ return NT_STATUS_NOT_IMPLEMENTED;
}
/*
samr_GetUserPwInfo
*/
-static NTSTATUS samr_GetUserPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_GetUserPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_GetUserPwInfo *r)
{
struct dcesrv_handle *h;
a_state = h->data;
- r->out.info.min_password_length = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, NULL, "minPwdLength",
- "dn=%s", a_state->domain_state->domain_dn);
- r->out.info.password_properties = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, NULL, "pwdProperties",
- "dn=%s", a_state->account_dn);
+ r->out.info.min_password_length = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0,
+ a_state->domain_state->domain_dn, "minPwdLength",
+ NULL);
+ r->out.info.password_properties = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0,
+ a_state->account_dn,
+ "pwdProperties", NULL);
return NT_STATUS_OK;
}
/*
samr_RemoveMemberFromForeignDomain
*/
-static NTSTATUS samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_RemoveMemberFromForeignDomain *r)
{
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
- struct dom_sid *domain_sid;
- const char *membersid, *memberdn;
+ const char *memberdn;
struct ldb_message **res;
- const char * const attrs[3] = { "dn", "objectSid", NULL };
+ const char * const attrs[3] = { "distinguishedName", "objectSid", NULL };
int i, count;
DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
d_state = h->data;
- domain_sid = dom_sid_parse_talloc(mem_ctx, d_state->domain_sid);
- membersid = dom_sid_string(mem_ctx, r->in.sid);
- if ((domain_sid == NULL) || (membersid == NULL))
- return NT_STATUS_NO_MEMORY;
-
memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
- "dn", "(objectSid=%s)", membersid);
- if (memberdn == NULL)
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ "distinguishedName", "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
+ /* Nothing to do */
+ if (memberdn == NULL) {
+ return NT_STATUS_OK;
+ }
/* TODO: Does this call only remove alias members, or does it do this
* for domain groups as well? */
count = samdb_search_domain(d_state->sam_ctx, mem_ctx,
d_state->domain_dn, &res, attrs,
- domain_sid,
+ d_state->domain_sid,
"(&(member=%s)(objectClass=group)"
- "(|(groupType=%s)(groupType=%s)))",
+ "(|(groupType=%d)(groupType=%d)))",
memberdn,
- ldb_hexstr(mem_ctx,
- GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
- ldb_hexstr(mem_ctx,
- GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
+ GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
+ GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
if (count < 0)
return NT_STATUS_INTERNAL_DB_CORRUPTION;
return NT_STATUS_NO_MEMORY;
}
- mod->dn = talloc_reference(mod,
- samdb_result_string(res[i], "dn",
- NULL));
+ mod->dn = samdb_result_dn(d_state->sam_ctx, mod, res[i], "distinguishedName", NULL);
if (mod->dn == NULL) {
talloc_free(mod);
continue;
"member", memberdn) != 0)
return NT_STATUS_NO_MEMORY;
- if (samdb_modify(d_state->sam_ctx, mem_ctx, mod) != 0)
+ if (ldb_modify(d_state->sam_ctx, mod) != 0)
return NT_STATUS_UNSUCCESSFUL;
talloc_free(mod);
/*
samr_QueryDomainInfo2
+
+ just an alias for samr_QueryDomainInfo
*/
-static NTSTATUS samr_QueryDomainInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_QueryDomainInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QueryDomainInfo2 *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct samr_QueryDomainInfo r1;
+ NTSTATUS status;
+
+ ZERO_STRUCT(r1.out);
+ r1.in.domain_handle = r->in.domain_handle;
+ r1.in.level = r->in.level;
+
+ status = dcesrv_samr_QueryDomainInfo(dce_call, mem_ctx, &r1);
+
+ r->out.info = r1.out.info;
+
+ return status;
}
just an alias for samr_QueryUserInfo
*/
-static NTSTATUS samr_QueryUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_QueryUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QueryUserInfo2 *r)
{
struct samr_QueryUserInfo r1;
r1.in.user_handle = r->in.user_handle;
r1.in.level = r->in.level;
- status = samr_QueryUserInfo(dce_call, mem_ctx, &r1);
+ status = dcesrv_samr_QueryUserInfo(dce_call, mem_ctx, &r1);
r->out.info = r1.out.info;
/*
samr_QueryDisplayInfo2
*/
-static NTSTATUS samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QueryDisplayInfo2 *r)
{
struct samr_QueryDisplayInfo q;
q.in.buf_size = r->in.buf_size;
ZERO_STRUCT(q.out);
- result = samr_QueryDisplayInfo(dce_call, mem_ctx, &q);
+ result = dcesrv_samr_QueryDisplayInfo(dce_call, mem_ctx, &q);
r->out.total_size = q.out.total_size;
r->out.returned_size = q.out.returned_size;
/*
samr_GetDisplayEnumerationIndex2
*/
-static NTSTATUS samr_GetDisplayEnumerationIndex2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_GetDisplayEnumerationIndex2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_GetDisplayEnumerationIndex2 *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
/*
samr_QueryDisplayInfo3
*/
-static NTSTATUS samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QueryDisplayInfo3 *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct samr_QueryDisplayInfo q;
+ NTSTATUS result;
+
+ q.in.domain_handle = r->in.domain_handle;
+ q.in.level = r->in.level;
+ q.in.start_idx = r->in.start_idx;
+ q.in.max_entries = r->in.max_entries;
+ q.in.buf_size = r->in.buf_size;
+ ZERO_STRUCT(q.out);
+
+ result = dcesrv_samr_QueryDisplayInfo(dce_call, mem_ctx, &q);
+
+ r->out.total_size = q.out.total_size;
+ r->out.returned_size = q.out.returned_size;
+ r->out.info = q.out.info;
+
+ return result;
}
/*
samr_AddMultipleMembersToAlias
*/
-static NTSTATUS samr_AddMultipleMembersToAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_AddMultipleMembersToAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_AddMultipleMembersToAlias *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
/*
samr_RemoveMultipleMembersFromAlias
*/
-static NTSTATUS samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_RemoveMultipleMembersFromAlias *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
note that w2k3 completely ignores the domain name in this call, and
always returns the information for the servers primary domain
*/
-static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_GetDomPwInfo *r)
{
struct ldb_message **msgs;
int ret;
const char * const attrs[] = {"minPwdLength", "pwdProperties", NULL };
- void *sam_ctx;
+ struct ldb_context *sam_ctx;
ZERO_STRUCT(r->out.info);
- sam_ctx = samdb_connect(mem_ctx);
+ sam_ctx = samdb_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
- ret = samdb_search(sam_ctx,
- mem_ctx, NULL, &msgs, attrs,
- "(&(name=%s)(objectclass=domain))",
- lp_workgroup());
+ /* The domain name in this call is ignored */
+ ret = gendb_search_dn(sam_ctx,
+ mem_ctx, NULL, &msgs, attrs);
if (ret <= 0) {
return NT_STATUS_NO_SUCH_DOMAIN;
}
if (ret > 1) {
- samdb_search_free(sam_ctx, mem_ctx, msgs);
+ talloc_free(msgs);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
r->out.info.min_password_length = samdb_result_uint(msgs[0], "minPwdLength", 0);
r->out.info.password_properties = samdb_result_uint(msgs[0], "pwdProperties", 1);
- samdb_search_free(sam_ctx, mem_ctx, msgs);
+ talloc_free(msgs);
talloc_free(sam_ctx);
return NT_STATUS_OK;
/*
samr_Connect2
*/
-static NTSTATUS samr_Connect2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_Connect2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_Connect2 *r)
{
struct samr_Connect c;
c.in.access_mask = r->in.access_mask;
c.out.connect_handle = r->out.connect_handle;
- return samr_Connect(dce_call, mem_ctx, &c);
+ return dcesrv_samr_Connect(dce_call, mem_ctx, &c);
}
just an alias for samr_SetUserInfo
*/
-static NTSTATUS samr_SetUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_SetUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_SetUserInfo2 *r)
{
struct samr_SetUserInfo r2;
r2.in.level = r->in.level;
r2.in.info = r->in.info;
- return samr_SetUserInfo(dce_call, mem_ctx, &r2);
+ return dcesrv_samr_SetUserInfo(dce_call, mem_ctx, &r2);
}
/*
samr_SetBootKeyInformation
*/
-static NTSTATUS samr_SetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_SetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_SetBootKeyInformation *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
/*
samr_GetBootKeyInformation
*/
-static NTSTATUS samr_GetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_GetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_GetBootKeyInformation *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
/*
samr_Connect3
*/
-static NTSTATUS samr_Connect3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_Connect3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_Connect3 *r)
{
struct samr_Connect c;
c.in.access_mask = r->in.access_mask;
c.out.connect_handle = r->out.connect_handle;
- return samr_Connect(dce_call, mem_ctx, &c);
+ return dcesrv_samr_Connect(dce_call, mem_ctx, &c);
}
/*
samr_Connect4
*/
-static NTSTATUS samr_Connect4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_Connect4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_Connect4 *r)
{
struct samr_Connect c;
c.in.access_mask = r->in.access_mask;
c.out.connect_handle = r->out.connect_handle;
- return samr_Connect(dce_call, mem_ctx, &c);
+ return dcesrv_samr_Connect(dce_call, mem_ctx, &c);
}
/*
samr_Connect5
*/
-static NTSTATUS samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_Connect5 *r)
{
struct samr_Connect c;
c.in.access_mask = r->in.access_mask;
c.out.connect_handle = r->out.connect_handle;
- status = samr_Connect(dce_call, mem_ctx, &c);
+ status = dcesrv_samr_Connect(dce_call, mem_ctx, &c);
r->out.info->info1.unknown1 = 3;
r->out.info->info1.unknown2 = 0;
/*
samr_RidToSid
*/
-static NTSTATUS samr_RidToSid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct samr_RidToSid *r)
+static NTSTATUS dcesrv_samr_RidToSid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct samr_RidToSid *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct samr_domain_state *d_state;
+ struct dcesrv_handle *h;
+
+ DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
+
+ d_state = h->data;
+
+ /* form the users SID */
+ r->out.sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
+ if (!r->out.sid) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
}
/*
samr_SetDsrmPassword
*/
-static NTSTATUS samr_SetDsrmPassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_SetDsrmPassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_SetDsrmPassword *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
/*
samr_ValidatePassword
*/
-static NTSTATUS samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_ValidatePassword *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);