summaryrefslogtreecommitdiff
path: root/source4/rpc_server
diff options
context:
space:
mode:
Diffstat (limited to 'source4/rpc_server')
-rw-r--r--source4/rpc_server/common/server_info.c2
-rw-r--r--source4/rpc_server/common/share_info.c2
-rw-r--r--source4/rpc_server/config.mk2
-rw-r--r--source4/rpc_server/dcerpc_server.c10
-rw-r--r--source4/rpc_server/dcerpc_server.h2
-rw-r--r--source4/rpc_server/dcesrv_auth.c14
-rw-r--r--source4/rpc_server/drsuapi/dcesrv_drsuapi.c65
-rw-r--r--source4/rpc_server/handles.c3
-rw-r--r--source4/rpc_server/lsa/dcesrv_lsa.c194
-rw-r--r--source4/rpc_server/lsa/lsa.h2
-rw-r--r--source4/rpc_server/lsa/lsa_init.c17
-rw-r--r--source4/rpc_server/lsa/lsa_lookup.c109
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c121
-rw-r--r--source4/rpc_server/remote/dcesrv_remote.c2
-rw-r--r--source4/rpc_server/samr/dcesrv_samr.c16
-rw-r--r--source4/rpc_server/samr/samr_password.c105
-rw-r--r--source4/rpc_server/service_rpc.c40
-rw-r--r--source4/rpc_server/winreg/rpc_winreg.c15
18 files changed, 522 insertions, 199 deletions
diff --git a/source4/rpc_server/common/server_info.c b/source4/rpc_server/common/server_info.c
index da034e85ea..ab04b3af1f 100644
--- a/source4/rpc_server/common/server_info.c
+++ b/source4/rpc_server/common/server_info.c
@@ -26,6 +26,8 @@
#include "dsdb/samdb/samdb.h"
#include "auth/auth.h"
#include "param/param.h"
+#include "rpc_server/common/common.h"
+#include "rpc_server/common/proto.h"
/*
Here are common server info functions used by some dcerpc server interfaces
diff --git a/source4/rpc_server/common/share_info.c b/source4/rpc_server/common/share_info.c
index b27dc37949..130babd175 100644
--- a/source4/rpc_server/common/share_info.c
+++ b/source4/rpc_server/common/share_info.c
@@ -23,6 +23,8 @@
#include "param/share.h"
#include "librpc/gen_ndr/srvsvc.h"
#include "rpc_server/dcerpc_server.h"
+#include "rpc_server/common/common.h"
+#include "rpc_server/common/proto.h"
/*
Here are common server info functions used by some dcerpc server interfaces
diff --git a/source4/rpc_server/config.mk b/source4/rpc_server/config.mk
index 6b1813544e..fb697d0c0f 100644
--- a/source4/rpc_server/config.mk
+++ b/source4/rpc_server/config.mk
@@ -206,7 +206,7 @@ PUBLIC_HEADERS += $(rpc_serversrcdir)/dcerpc_server.h
[MODULE::DCESRV]
INIT_FUNCTION = server_service_rpc_init
-SUBSYSTEM = smbd
+SUBSYSTEM = samba
PRIVATE_DEPENDENCIES = dcerpc_server
DCESRV_OBJ_FILES = $(rpc_serversrcdir)/service_rpc.o
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index e5f59d0cf9..1d1efa7480 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -24,7 +24,7 @@
#include "librpc/gen_ndr/ndr_dcerpc.h"
#include "auth/auth.h"
#include "auth/gensec/gensec.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
#include "rpc_server/dcerpc_server.h"
#include "rpc_server/dcerpc_server_proto.h"
#include "librpc/rpc/dcerpc_proto.h"
@@ -870,10 +870,6 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
call->context = context;
call->ndr_pull = pull;
- if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
- pull->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
- }
-
if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
pull->flags |= LIBNDR_FLAG_BIGENDIAN;
}
@@ -1112,6 +1108,10 @@ NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
}
+ if (CVAL(blob.data, DCERPC_PFC_OFFSET) & DCERPC_PFC_FLAG_OBJECT_UUID) {
+ ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
+ }
+
ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, &call->pkt);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(dce_conn->partial_input.data);
diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h
index b5672b41ac..59a4bab083 100644
--- a/source4/rpc_server/dcerpc_server.h
+++ b/source4/rpc_server/dcerpc_server.h
@@ -23,7 +23,7 @@
#ifndef SAMBA_DCERPC_SERVER_H
#define SAMBA_DCERPC_SERVER_H
-#include "librpc/gen_ndr/misc.h"
+#include "librpc/gen_ndr/security.h"
#include "librpc/rpc/dcerpc.h"
#include "librpc/ndr/libndr.h"
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 16bf4eb7ed..bef7e4be78 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -95,6 +95,10 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
return false;
}
+ if (call->conn->state_flags & DCESRV_CALL_STATE_FLAG_HEADER_SIGNING) {
+ gensec_want_feature(auth->gensec_security, GENSEC_FEATURE_SIGN_PKT_HEADER);
+ }
+
return true;
}
@@ -287,6 +291,7 @@ bool dcesrv_auth_request(struct dcesrv_call_state *call, DATA_BLOB *full_packet)
struct ndr_pull *ndr;
NTSTATUS status;
enum ndr_err_code ndr_err;
+ size_t hdr_size = DCERPC_REQUEST_LENGTH;
if (!dce_conn->auth_state.auth_info ||
!dce_conn->auth_state.gensec_security) {
@@ -335,6 +340,11 @@ bool dcesrv_auth_request(struct dcesrv_call_state *call, DATA_BLOB *full_packet)
ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
}
+ if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
+ ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
+ hdr_size += 16;
+ }
+
ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(ndr);
@@ -346,13 +356,13 @@ bool dcesrv_auth_request(struct dcesrv_call_state *call, DATA_BLOB *full_packet)
case DCERPC_AUTH_LEVEL_PRIVACY:
status = gensec_unseal_packet(dce_conn->auth_state.gensec_security,
call,
- full_packet->data + DCERPC_REQUEST_LENGTH,
+ full_packet->data + hdr_size,
pkt->u.request.stub_and_verifier.length,
full_packet->data,
full_packet->length-auth.credentials.length,
&auth.credentials);
memcpy(pkt->u.request.stub_and_verifier.data,
- full_packet->data + DCERPC_REQUEST_LENGTH,
+ full_packet->data + hdr_size,
pkt->u.request.stub_and_verifier.length);
break;
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
index bbb78cb778..6af8ea50b5 100644
--- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
+++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
@@ -69,7 +69,7 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C
server_site_dn = samdb_server_site_dn(b_state->sam_ctx, mem_ctx);
W_ERROR_HAVE_NO_MEMORY(server_site_dn);
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &site_res,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &site_res,
server_site_dn, LDB_SCOPE_BASE, site_attrs,
"(objectClass=*)");
if (ret != LDB_SUCCESS) {
@@ -86,7 +86,7 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C
ntds_dn = samdb_ntds_settings_dn(b_state->sam_ctx);
W_ERROR_HAVE_NO_MEMORY(ntds_dn);
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &ntds_res,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &ntds_res,
ntds_dn, LDB_SCOPE_BASE, ntds_attrs,
"(objectClass=*)");
if (ret != LDB_SUCCESS) {
@@ -330,19 +330,21 @@ static WERROR dcesrv_drsuapi_DsGetNT4ChangeLog(struct dcesrv_call_state *dce_cal
/*
drsuapi_DsCrackNames
*/
-WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct drsuapi_DsCrackNames *r)
{
WERROR status;
struct drsuapi_bind_state *b_state;
struct dcesrv_handle *h;
- r->out.level = r->in.level;
- ZERO_STRUCT(r->out.ctr);
+ *r->out.level_out = r->in.level;
DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
b_state = h->data;
+ r->out.ctr = talloc_zero(mem_ctx, union drsuapi_DsNameCtr);
+ W_ERROR_HAVE_NO_MEMORY(r->out.ctr);
+
switch (r->in.level) {
case 1: {
struct drsuapi_DsNameCtr1 *ctr1;
@@ -353,16 +355,16 @@ WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CT
ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
W_ERROR_HAVE_NO_MEMORY(ctr1);
- count = r->in.req.req1.count;
+ count = r->in.req->req1.count;
names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
W_ERROR_HAVE_NO_MEMORY(names);
for (i=0; i < count; i++) {
status = DsCrackNameOneName(b_state->sam_ctx, mem_ctx,
- r->in.req.req1.format_flags,
- r->in.req.req1.format_offered,
- r->in.req.req1.format_desired,
- r->in.req.req1.names[i].str,
+ r->in.req->req1.format_flags,
+ r->in.req->req1.format_offered,
+ r->in.req->req1.format_desired,
+ r->in.req->req1.names[i].str,
&names[i]);
if (!W_ERROR_IS_OK(status)) {
return status;
@@ -371,7 +373,7 @@ WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CT
ctr1->count = count;
ctr1->array = names;
- r->out.ctr.ctr1 = ctr1;
+ r->out.ctr->ctr1 = ctr1;
return WERR_OK;
}
@@ -389,17 +391,20 @@ static WERROR dcesrv_drsuapi_DsWriteAccountSpn(struct dcesrv_call_state *dce_cal
struct drsuapi_bind_state *b_state;
struct dcesrv_handle *h;
- r->out.level = r->in.level;
+ *r->out.level_out = r->in.level;
DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
b_state = h->data;
+ r->out.res = talloc(mem_ctx, union drsuapi_DsWriteAccountSpnResult);
+ W_ERROR_HAVE_NO_MEMORY(r->out.res);
+
switch (r->in.level) {
case 1: {
struct drsuapi_DsWriteAccountSpnRequest1 *req;
struct ldb_message *msg;
int count, i, ret;
- req = &r->in.req.req1;
+ req = &r->in.req->req1;
count = req->count;
msg = ldb_msg_new(mem_ctx);
@@ -409,7 +414,7 @@ static WERROR dcesrv_drsuapi_DsWriteAccountSpn(struct dcesrv_call_state *dce_cal
msg->dn = ldb_dn_new(msg, b_state->sam_ctx, req->object_dn);
if ( ! ldb_dn_validate(msg->dn)) {
- r->out.res.res1.status = WERR_OK;
+ r->out.res->res1.status = WERR_OK;
return WERR_OK;
}
@@ -440,9 +445,9 @@ static WERROR dcesrv_drsuapi_DsWriteAccountSpn(struct dcesrv_call_state *dce_cal
DEBUG(0,("Failed to modify SPNs on %s: %s\n",
ldb_dn_get_linearized(msg->dn),
ldb_errstring(b_state->sam_ctx)));
- r->out.res.res1.status = WERR_ACCESS_DENIED;
+ r->out.res->res1.status = WERR_ACCESS_DENIED;
} else {
- r->out.res.res1.status = WERR_OK;
+ r->out.res->res1.status = WERR_OK;
}
return WERR_OK;
@@ -473,7 +478,7 @@ static WERROR dcesrv_DRSUAPI_REMOVE_DS_DOMAIN(struct dcesrv_call_state *dce_call
}
/* Obtain the site name from a server DN */
-const char *result_site_name(struct ldb_dn *site_dn)
+static const char *result_site_name(struct ldb_dn *site_dn)
{
/* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
const struct ldb_val *val = ldb_dn_get_component_val(site_dn, 2);
@@ -519,14 +524,16 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta
int ret, i;
- r->out.level_out = r->in.req.req1.level;
+ *r->out.level_out = r->in.req->req1.level;
+ r->out.ctr = talloc(mem_ctx, union drsuapi_DsGetDCInfoCtr);
+ W_ERROR_HAVE_NO_MEMORY(r->out.ctr);
sites_dn = samdb_sites_dn(b_state->sam_ctx, mem_ctx);
if (!sites_dn) {
return WERR_DS_OBJ_NOT_FOUND;
}
- switch (r->out.level_out) {
+ switch (*r->out.level_out) {
case -1:
/* this level is not like the others */
return WERR_UNKNOWN_LEVEL;
@@ -540,7 +547,7 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta
return WERR_UNKNOWN_LEVEL;
}
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE, attrs,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE, attrs,
"objectClass=server");
if (ret) {
@@ -549,9 +556,9 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta
return WERR_GENERAL_FAILURE;
}
- switch (r->out.level_out) {
+ switch (*r->out.level_out) {
case 1:
- ctr1 = &r->out.ctr.ctr1;
+ ctr1 = &r->out.ctr->ctr1;
ctr1->count = res->count;
ctr1->array = talloc_zero_array(mem_ctx,
struct drsuapi_DsGetDCInfo1,
@@ -571,7 +578,7 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta
return WERR_NOMEM;
}
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
LDB_SCOPE_BASE, attrs_account_1, "objectClass=computer");
if (ret == LDB_SUCCESS && res_account->count == 1) {
const char *errstr;
@@ -588,7 +595,7 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta
&domain_dn, &errstr);
if (ret == LDB_SUCCESS) {
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
ldb_dn_get_linearized(ntds_dn));
if (ret) {
@@ -614,7 +621,7 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta
}
break;
case 2:
- ctr2 = &r->out.ctr.ctr2;
+ ctr2 = &r->out.ctr->ctr2;
ctr2->count = res->count;
ctr2->array = talloc_zero_array(mem_ctx,
struct drsuapi_DsGetDCInfo2,
@@ -641,7 +648,7 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta
return WERR_NOMEM;
}
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_ntds, ntds_dn,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_ntds, ntds_dn,
LDB_SCOPE_BASE, attrs_ntds, "objectClass=nTDSDSA");
if (ret == LDB_SUCCESS && res_ntds->count == 1) {
ctr2->array[i].is_gc
@@ -655,7 +662,7 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta
ldb_dn_get_linearized(ntds_dn), ldb_errstring(b_state->sam_ctx)));
}
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_site, site_dn,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_site, site_dn,
LDB_SCOPE_BASE, attrs_site, "objectClass=site");
if (ret == LDB_SUCCESS && res_site->count == 1) {
ctr2->array[i].site_guid
@@ -667,7 +674,7 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta
ldb_dn_get_linearized(site_dn), ldb_errstring(b_state->sam_ctx)));
}
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
LDB_SCOPE_BASE, attrs_account_2, "objectClass=computer");
if (ret == LDB_SUCCESS && res_account->count == 1) {
const char *errstr;
@@ -685,7 +692,7 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta
&domain_dn, &errstr);
if (ret == LDB_SUCCESS) {
- ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
+ ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
ldb_dn_get_linearized(ntds_dn));
if (ret == LDB_SUCCESS && res_domain->count == 1) {
diff --git a/source4/rpc_server/handles.c b/source4/rpc_server/handles.c
index 47174b6eeb..284354feb4 100644
--- a/source4/rpc_server/handles.c
+++ b/source4/rpc_server/handles.c
@@ -20,7 +20,7 @@
*/
#include "includes.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
#include "rpc_server/dcerpc_server.h"
/*
@@ -29,7 +29,6 @@
static int dcesrv_handle_destructor(struct dcesrv_handle *h)
{
DLIST_REMOVE(h->context->handles, h);
- talloc_free(h);
return 0;
}
diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index a1ca3b4a46..b009d2f2f8 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -1,3 +1,5 @@
+/* need access mask/acl implementation */
+
/*
Unix SMB/CIFS implementation.
@@ -21,13 +23,13 @@
*/
#include "rpc_server/lsa/lsa.h"
-#include "util/util_ldb.h"
+#include "../lib/util/util_ldb.h"
#include "libcli/ldap/ldap_ndr.h"
#include "system/kerberos.h"
#include "auth/kerberos/kerberos.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "librpc/gen_ndr/ndr_lsa.h"
-#include "lib/crypto/crypto.h"
+#include "../lib/crypto/crypto.h"
/*
this type allows us to distinguish handle types
@@ -141,7 +143,8 @@ static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALL
return NT_STATUS_OK;
} else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
- struct lsa_trusted_domain_state *trusted_domain_state = h->data;
+ struct lsa_trusted_domain_state *trusted_domain_state =
+ talloc_get_type(h->data, struct lsa_trusted_domain_state);
ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
if (ret != 0) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
@@ -187,6 +190,9 @@ static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALL
r2.in.sid = astate->account_sid;
r2.out.rights = rights;
+ /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
+ but we have a LSA_HANDLE_ACCOUNT here, so this call
+ will always fail */
status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
return NT_STATUS_OK;
@@ -393,7 +399,6 @@ static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_cal
return WERR_INVALID_PARAM;
}
-
/*
fill in the AccountDomain info
*/
@@ -444,18 +449,52 @@ static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call,
ZERO_STRUCTP(r->out.info);
switch (r->in.level) {
+ case LSA_POLICY_INFO_AUDIT_LOG:
+ /* we don't need to fill in any of this */
+ ZERO_STRUCT(r->out.info->audit_log);
+ return NT_STATUS_OK;
+ case LSA_POLICY_INFO_AUDIT_EVENTS:
+ /* we don't need to fill in any of this */
+ ZERO_STRUCT(r->out.info->audit_events);
+ return NT_STATUS_OK;
+ case LSA_POLICY_INFO_PD:
+ /* we don't need to fill in any of this */
+ ZERO_STRUCT(r->out.info->pd);
+ return NT_STATUS_OK;
+
case LSA_POLICY_INFO_DOMAIN:
+ return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->domain);
case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->account_domain);
+ case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
+ return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->l_account_domain);
+
+
+ case LSA_POLICY_INFO_ROLE:
+ r->out.info->role.role = LSA_ROLE_PRIMARY;
+ return NT_STATUS_OK;
case LSA_POLICY_INFO_DNS:
+ case LSA_POLICY_INFO_DNS_INT:
return dcesrv_lsa_info_DNS(state, mem_ctx, &r->out.info->dns);
- case LSA_POLICY_INFO_DB:
+
+ case LSA_POLICY_INFO_REPLICA:
+ ZERO_STRUCT(r->out.info->replica);
+ return NT_STATUS_OK;
+
+ case LSA_POLICY_INFO_QUOTA:
+ ZERO_STRUCT(r->out.info->quota);
+ return NT_STATUS_OK;
+
+ case LSA_POLICY_INFO_MOD:
case LSA_POLICY_INFO_AUDIT_FULL_SET:
case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
+ /* windows gives INVALID_PARAMETER */
+ r->out.info = NULL;
return NT_STATUS_INVALID_PARAMETER;
}
+ r->out.info = NULL;
return NT_STATUS_INVALID_INFO_CLASS;
}
@@ -468,6 +507,8 @@ static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, T
struct lsa_QueryInfoPolicy2 r2;
NTSTATUS status;
+ ZERO_STRUCT(r2);
+
r2.in.handle = r->in.handle;
r2.in.level = r->in.level;
@@ -484,6 +525,7 @@ static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, T
static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct lsa_SetInfoPolicy *r)
{
+ /* need to support this */
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
@@ -502,6 +544,13 @@ static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TAL
lsa_CreateAccount
This call does not seem to have any long-term effects, hence no database operations
+
+ we need to talk to the MS product group to find out what this account database means!
+
+ answer is that the lsa database is totally separate from the SAM and
+ ldap databases. We are going to need a separate ldb to store these
+ accounts. The SIDs on this account bear no relation to the SIDs in
+ AD
*/
static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct lsa_CreateAccount *r)
@@ -626,7 +675,7 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
const char *name;
DATA_BLOB session_key = data_blob(NULL, 0);
DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
- struct trustAuthInAndOutBlob auth_struct;
+ struct trustDomainPasswords auth_struct;
int ret;
NTSTATUS nt_status;
enum ndr_err_code ndr_err;
@@ -648,7 +697,7 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
dns_name = r->in.info->domain_name.string;
- trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
+ trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
if (!trusted_domain_state) {
return NT_STATUS_NO_MEMORY;
}
@@ -679,16 +728,49 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
ndr_err = ndr_pull_struct_blob(&auth_blob, mem_ctx,
lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
&auth_struct,
- (ndr_pull_flags_fn_t)ndr_pull_trustAuthInAndOutBlob);
+ (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return NT_STATUS_INVALID_PARAMETER;
}
+
+ if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
+ if (auth_struct.incoming.count > 1) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
}
if (auth_struct.incoming.count) {
+ int i;
+ struct trustAuthInOutBlob incoming;
+
+ incoming.count = auth_struct.incoming.count;
+ incoming.current = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!incoming.current) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ incoming.current->array = *auth_struct.incoming.current;
+ if (!incoming.current->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ incoming.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!incoming.previous) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ incoming.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, incoming.count);
+ if (!incoming.previous->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; i < incoming.count; i++) {
+ incoming.previous->array[i].LastUpdateTime = 0;
+ incoming.previous->array[i].AuthType = 0;
+ }
ndr_err = ndr_push_struct_blob(&trustAuthIncoming, mem_ctx,
lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
- &auth_struct.incoming,
+ &incoming,
(ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return NT_STATUS_INVALID_PARAMETER;
@@ -698,9 +780,36 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
}
if (auth_struct.outgoing.count) {
+ int i;
+ struct trustAuthInOutBlob outgoing;
+
+ outgoing.count = auth_struct.outgoing.count;
+ outgoing.current = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!outgoing.current) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ outgoing.current->array = *auth_struct.outgoing.current;
+ if (!outgoing.current->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ outgoing.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!outgoing.previous) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ outgoing.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, outgoing.count);
+ if (!outgoing.previous->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; i < outgoing.count; i++) {
+ outgoing.previous->array[i].LastUpdateTime = 0;
+ outgoing.previous->array[i].AuthType = 0;
+ }
ndr_err = ndr_push_struct_blob(&trustAuthOutgoing, mem_ctx,
lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
- &auth_struct.outgoing,
+ &outgoing,
(ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return NT_STATUS_INVALID_PARAMETER;
@@ -859,24 +968,19 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
if (auth_struct.incoming.count) {
int i;
for (i=0; i < auth_struct.incoming.count; i++ ) {
- if (auth_struct.incoming.current->array[i].AuthType == TRUST_AUTH_TYPE_NT4OWF) {
+ if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_NT4OWF) {
samdb_msg_add_hash(trusted_domain_state->policy->sam_ldb,
mem_ctx, msg_user, "unicodePwd",
- &auth_struct.incoming.current->array[i].AuthInfo.nt4owf.password);
- } else if (auth_struct.incoming.current->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
- struct samr_Password hash;
-/*
- . We cannot do this, as windows chooses to send in random passwords here, that won't convert to UTF8
- samdb_msg_add_string(trusted_domain_state->policy->sam_ldb,
- mem_ctx, msg_user, "userPassword",
- auth_struct.incoming.current->array[i].AuthInfo.clear.password);
-*/
- mdfour(hash.hash, auth_struct.incoming.current->array[i].AuthInfo.clear.password,
- auth_struct.incoming.current->array[i].AuthInfo.clear.size);
- samdb_msg_add_hash(trusted_domain_state->policy->sam_ldb,
- mem_ctx, msg_user, "unicodePwd",
- &hash);
- }
+ &auth_struct.incoming.current[i]->AuthInfo.nt4owf.password);
+ } else if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_CLEAR) {
+ DATA_BLOB new_password = data_blob_const(auth_struct.incoming.current[i]->AuthInfo.clear.password,
+ auth_struct.incoming.current[i]->AuthInfo.clear.size);
+ ret = ldb_msg_add_value(msg_user, "clearTextPassword", &new_password, NULL);
+ if (ret != LDB_SUCCESS) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
}
}
@@ -1004,7 +1108,7 @@ static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call,
ZERO_STRUCTP(r->out.trustdom_handle);
policy_state = policy_handle->data;
- trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
+ trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
if (!trusted_domain_state) {
return NT_STATUS_NO_MEMORY;
}
@@ -1088,7 +1192,7 @@ static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce
return NT_STATUS_INVALID_PARAMETER;
}
- trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
+ trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
if (!trusted_domain_state) {
return NT_STATUS_NO_MEMORY;
}
@@ -1228,7 +1332,7 @@ static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_
DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
- trusted_domain_state = h->data;
+ trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
/* pull all the user attributes */
ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
@@ -1951,7 +2055,36 @@ static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_cal
static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct lsa_GetSystemAccessAccount *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ int i;
+ NTSTATUS status;
+ struct lsa_EnumPrivsAccount enumPrivs;
+
+ enumPrivs.in.handle = r->in.handle;
+
+ status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ *(r->out.access_mask) = 0x00000000;
+
+ for (i = 0; i < enumPrivs.out.privs->count; i++) {
+ int priv = enumPrivs.out.privs->set[i].luid.low;
+
+ switch (priv) {
+ case SEC_PRIV_INTERACTIVE_LOGON:
+ *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
+ break;
+ case SEC_PRIV_NETWORK_LOGON:
+ *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
+ break;
+ case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
+ *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
+ break;
+ }
+ }
+
+ return NT_STATUS_OK;
}
@@ -2786,6 +2919,7 @@ static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
TALLOC_CTX *mem_ctx,
struct lsa_SetInfoPolicy2 *r)
{
+ /* need to support these */
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
diff --git a/source4/rpc_server/lsa/lsa.h b/source4/rpc_server/lsa/lsa.h
index b7c41486a2..ffdf96d091 100644
--- a/source4/rpc_server/lsa/lsa.h
+++ b/source4/rpc_server/lsa/lsa.h
@@ -30,7 +30,7 @@
#include "libcli/security/security.h"
#include "libcli/auth/libcli_auth.h"
#include "param/secrets.h"
-#include "util/util_ldb.h"
+#include "../lib/util/util_ldb.h"
#include "librpc/gen_ndr/ndr_dssetup.h"
#include "param/param.h"
diff --git a/source4/rpc_server/lsa/lsa_init.c b/source4/rpc_server/lsa/lsa_init.c
index 0dc21fd9c5..8d8417109f 100644
--- a/source4/rpc_server/lsa/lsa_init.c
+++ b/source4/rpc_server/lsa/lsa_init.c
@@ -71,12 +71,11 @@ NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
return NT_STATUS_NO_MEMORY;
}
- ret = ldb_search(state->sam_ldb, state->domain_dn, LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res);
-
+ ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
+ state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
if (ret != LDB_SUCCESS) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
- talloc_steal(mem_ctx, dom_res);
if (dom_res->count != 1) {
return NT_STATUS_NO_SUCH_DOMAIN;
}
@@ -95,7 +94,7 @@ NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
talloc_free(dom_res);
- ret = ldb_search_exp_fmt(state->sam_ldb, state, &ref_res,
+ ret = ldb_search(state->sam_ldb, state, &ref_res,
partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
"(&(objectclass=crossRef)(ncName=%s))",
ldb_dn_get_linearized(state->domain_dn));
@@ -125,7 +124,7 @@ NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
talloc_free(ref_res);
- ret = ldb_search_exp_fmt(state->sam_ldb, state, &forest_ref_res,
+ ret = ldb_search(state->sam_ldb, state, &forest_ref_res,
partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
"(&(objectclass=crossRef)(ncName=%s))",
ldb_dn_get_linearized(state->forest_dn));
@@ -200,6 +199,12 @@ NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *
ZERO_STRUCTP(r->out.handle);
+ if (r->in.attr != NULL &&
+ r->in.attr->root_dir != NULL) {
+ /* MS-LSAD 3.1.4.4.1 */
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -212,6 +217,8 @@ NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *
handle->data = talloc_steal(handle, state);
+ /* need to check the access mask against - need ACLs - fails
+ WSPP test */
state->access_mask = r->in.access_mask;
state->handle = handle;
*r->out.handle = handle->wire_handle;
diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c
index 30bceb8139..2375a6d27a 100644
--- a/source4/rpc_server/lsa/lsa_lookup.c
+++ b/source4/rpc_server/lsa/lsa_lookup.c
@@ -44,6 +44,11 @@ static const struct {
.rtype = SID_NAME_WKN_GRP,
},
{
+ .name = "Owner Rights",
+ .sid = SID_OWNER_RIGHTS,
+ .rtype = SID_NAME_WKN_GRP,
+ },
+ {
.domain = "NT AUTHORITY",
.name = "Dialup",
.sid = SID_NT_DIALUP,
@@ -111,7 +116,7 @@ static const struct {
},
{
.domain = "NT AUTHORITY",
- .name = "Termainal Server User",
+ .name = "Terminal Server User",
.sid = SID_NT_TERMINAL_SERVER_USERS,
.rtype = SID_NAME_WKN_GRP,
},
@@ -146,6 +151,42 @@ static const struct {
.rtype = SID_NAME_WKN_GRP,
},
{
+ .domain = "NT AUTHORITY",
+ .name = "Digest Authentication",
+ .sid = SID_NT_DIGEST_AUTHENTICATION,
+ .rtype = SID_NAME_WKN_GRP,
+ },
+ {
+ .domain = "NT AUTHORITY",
+ .name = "Enterprise Domain Controllers",
+ .sid = SID_NT_ENTERPRISE_DCS,
+ .rtype = SID_NAME_WKN_GRP,
+ },
+ {
+ .domain = "NT AUTHORITY",
+ .name = "NTLM Authentication",
+ .sid = SID_NT_NTLM_AUTHENTICATION,
+ .rtype = SID_NAME_WKN_GRP,
+ },
+ {
+ .domain = "NT AUTHORITY",
+ .name = "Other Organization",
+ .sid = SID_NT_OTHER_ORGANISATION,
+ .rtype = SID_NAME_WKN_GRP,
+ },
+ {
+ .domain = "NT AUTHORITY",
+ .name = "SChannel Authentication",
+ .sid = SID_NT_SCHANNEL_AUTHENTICATION,
+ .rtype = SID_NAME_WKN_GRP,
+ },
+ {
+ .domain = "NT AUTHORITY",
+ .name = "IUSR",
+ .sid = SID_NT_IUSR,
+ .rtype = SID_NAME_WKN_GRP,
+ },
+ {
.sid = NULL,
}
};
@@ -484,8 +525,19 @@ NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
int i;
NTSTATUS status = NT_STATUS_OK;
+ if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
+ r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
r->out.domains = NULL;
+ /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
+ and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as
+ an unknown SID. We could add a SID validator here. (tridge)
+ MS-DTYP 2.4.2
+ */
+
status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -542,7 +594,7 @@ NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
authority_name, sid,
r->out.domains, &sid_index);
if (!NT_STATUS_IS_OK(status2)) {
- return status2;
+ continue;
}
r->out.names->names[i].sid_type = rtype;
@@ -579,6 +631,8 @@ NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
NTSTATUS status;
struct dcesrv_handle *h;
+ ZERO_STRUCT(r2);
+
/* No policy handle on the wire, so make one up here */
r2.in.handle = talloc(mem_ctx, struct policy_handle);
if (!r2.in.handle) {
@@ -608,9 +662,6 @@ NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
r2.out.names = r->out.names;
status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
- if (dce_call->fault_code != 0) {
- return status;
- }
r->out.domains = r2.out.domains;
r->out.names = r2.out.names;
@@ -630,6 +681,8 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
NTSTATUS status;
int i;
+ ZERO_STRUCT(r2);
+
r2.in.handle = r->in.handle;
r2.in.sids = r->in.sids;
r2.in.names = NULL;
@@ -641,9 +694,8 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
r2.out.names = NULL;
status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
- if (dce_call->fault_code != 0) {
- return status;
- }
+ /* we deliberately don't check for error from the above,
+ as even on error we are supposed to return the names */
r->out.domains = r2.out.domains;
if (!r2.out.names) {
@@ -685,6 +737,11 @@ NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
+ if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
+ r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
policy_state = policy_handle->data;
r->out.domains = NULL;
@@ -720,7 +777,7 @@ NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
r->out.sids->sids[i].sid = NULL;
r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
- r->out.sids->sids[i].unknown = 0;
+ r->out.sids->sids[i].flags = 0;
status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name, &authority_name, &sid, &rtype);
if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
@@ -730,13 +787,13 @@ NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name,
sid, r->out.domains, &sid_index);
if (!NT_STATUS_IS_OK(status2)) {
- return status2;
+ continue;
}
r->out.sids->sids[i].sid_type = rtype;
r->out.sids->sids[i].sid = sid;
r->out.sids->sids[i].sid_index = sid_index;
- r->out.sids->sids[i].unknown = 0;
+ r->out.sids->sids[i].flags = 0;
(*r->out.count)++;
}
@@ -765,6 +822,8 @@ NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX
NTSTATUS status;
struct dcesrv_handle *h;
+ ZERO_STRUCT(r2);
+
/* No policy handle on the wire, so make one up here */
r2.in.handle = talloc(mem_ctx, struct policy_handle);
if (!r2.in.handle) {
@@ -786,18 +845,16 @@ NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX
r2.in.num_names = r->in.num_names;
r2.in.names = r->in.names;
+ r2.in.level = r->in.level;
r2.in.sids = r->in.sids;
r2.in.count = r->in.count;
- r2.in.unknown1 = r->in.unknown1;
- r2.in.unknown2 = r->in.unknown2;
+ r2.in.lookup_options = r->in.lookup_options;
+ r2.in.client_revision = r->in.client_revision;
r2.out.domains = r->out.domains;
r2.out.sids = r->out.sids;
r2.out.count = r->out.count;
status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
- if (dce_call->fault_code != 0) {
- return status;
- }
r->out.domains = r2.out.domains;
r->out.sids = r2.out.sids;
@@ -821,6 +878,11 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+ if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
+ r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
state = h->data;
r->out.domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
@@ -851,7 +913,10 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
r->out.sids->count++;
r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
- r->out.sids->sids[i].rid = 0xFFFFFFFF;
+ /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
+ to sid NULL - so we should return 0 rid for
+ unmapped entries */
+ r->out.sids->sids[i].rid = 0;
r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
r->out.sids->sids[i].unknown = 0;
@@ -864,7 +929,7 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name,
sid, r->out.domains, &sid_index);
if (!NT_STATUS_IS_OK(status2)) {
- return status2;
+ continue;
}
r->out.sids->sids[i].sid_type = rtype;
@@ -895,18 +960,20 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *
NTSTATUS status;
int i;
+ ZERO_STRUCT(r2);
+
r2.in.handle = r->in.handle;
r2.in.num_names = r->in.num_names;
r2.in.names = r->in.names;
r2.in.sids = NULL;
r2.in.level = r->in.level;
r2.in.count = r->in.count;
- r2.in.unknown1 = 0;
- r2.in.unknown2 = 0;
+ r2.in.lookup_options = 0;
+ r2.in.client_revision = 0;
r2.out.count = r->out.count;
status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
- if (dce_call->fault_code != 0) {
+ if (r2.out.sids == NULL) {
return status;
}
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 6f4287f9d8..9d4c897892 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -29,13 +29,14 @@
#include "dsdb/samdb/samdb.h"
#include "dsdb/common/flags.h"
#include "rpc_server/samr/proto.h"
-#include "util/util_ldb.h"
+#include "../lib/util/util_ldb.h"
#include "libcli/auth/libcli_auth.h"
#include "auth/gensec/schannel_state.h"
#include "libcli/security/security.h"
#include "param/param.h"
#include "lib/messaging/irpc.h"
#include "librpc/gen_ndr/ndr_irpc.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
struct server_pipe_state {
struct netr_Credential client_challenge;
@@ -86,6 +87,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
const char *attrs[] = {"unicodePwd", "userAccountControl",
"objectSid", NULL};
+ const char *trust_dom_attrs[] = {"flatname", NULL};
+ const char *account_name;
+
ZERO_STRUCTP(r->out.credentials);
*r->out.rid = 0;
*r->out.negotiate_flags = *r->in.negotiate_flags;
@@ -100,10 +104,54 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
+
+ if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
+ char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
+ const char *flatname;
+ if (!encoded_account) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Kill the trailing dot */
+ if (encoded_account[strlen(encoded_account)-1] == '.') {
+ encoded_account[strlen(encoded_account)-1] = '\0';
+ }
+
+ /* pull the user attributes */
+ num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, trust_dom_attrs,
+ "(&(trustPartner=%s)(objectclass=trustedDomain))",
+ encoded_account);
+
+ if (num_records == 0) {
+ DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
+ encoded_account));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (num_records > 1) {
+ DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
+ if (!flatname) {
+ /* No flatname for this trust - we can't proceed */
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
+
+ if (!account_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ } else {
+ account_name = r->in.account_name;
+ }
+
/* pull the user attributes */
num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
"(&(sAMAccountName=%s)(objectclass=user))",
- r->in.account_name);
+ ldb_binary_encode_string(mem_ctx, account_name));
if (num_records == 0) {
DEBUG(3,("Couldn't find user [%s] in samdb.\n",
@@ -129,7 +177,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
return NT_STATUS_ACCESS_DENIED;
}
- } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN) {
+ } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
+ r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
@@ -321,7 +370,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call
creds->sid,
NULL, /* Don't have plaintext */
NULL, &r->in.new_password,
- false, /* This is not considered a password change */
+ true, /* Password change */
NULL, NULL);
return nt_status;
}
@@ -336,16 +385,14 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
struct creds_CredentialState *creds;
struct ldb_context *sam_ctx;
NTSTATUS nt_status;
- char new_pass[512];
- uint32_t new_pass_len;
- bool ret;
+ DATA_BLOB new_password;
struct samr_CryptPassword password_buf;
nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
r->in.computer_name, mem_ctx,
- &r->in.credential, &r->out.return_authenticator,
- &creds);
+ &r->in.credential, &r->out.return_authenticator,
+ &creds);
NT_STATUS_NOT_OK_RETURN(nt_status);
sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
@@ -354,22 +401,20 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
}
memcpy(password_buf.data, r->in.new_password.data, 512);
- SIVAL(password_buf.data,512,r->in.new_password.length);
+ SIVAL(password_buf.data, 512, r->in.new_password.length);
creds_arcfour_crypt(creds, password_buf.data, 516);
- ret = decode_pw_buffer(password_buf.data, new_pass, sizeof(new_pass),
- &new_pass_len, STR_UNICODE);
- if (!ret) {
- DEBUG(3,("netr_ServerPasswordSet2: failed to decode password buffer\n"));
- return NT_STATUS_ACCESS_DENIED;
+ if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
+ DEBUG(3,("samr: failed to decode password buffer\n"));
+ return NT_STATUS_WRONG_PASSWORD;
}
-
+
/* Using the sid for the account as the key, set the password */
nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
creds->sid,
- new_pass, /* we have plaintext */
+ &new_password, /* we have plaintext */
NULL, NULL,
- false, /* This is not considered a password change */
+ true, /* Password change */
NULL, NULL);
return nt_status;
}
@@ -899,20 +944,37 @@ static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx,
struct ldb_message *res,
struct ldb_message *ref_res,
struct netr_DomainTrustInfo *info,
- bool is_local)
+ bool is_local, bool is_trust_list)
{
ZERO_STRUCTP(info);
+ info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
+ info->trust_extension.length = 16;
+ info->trust_extension.info->flags =
+ NETR_TRUST_FLAG_TREEROOT |
+ NETR_TRUST_FLAG_IN_FOREST |
+ NETR_TRUST_FLAG_PRIMARY;
+ info->trust_extension.info->parent_index = 0; /* should be index into array
+ of parent */
+ info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
+ info->trust_extension.info->trust_attributes = LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE; /* needs to be based on ldb search */
+
+ if (is_trust_list) {
+ /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
+ info->forest.string = NULL;
+ } else {
+ /* TODO: we need a common function for pulling the forest */
+ info->forest.string = samdb_result_string(ref_res, "dnsRoot", NULL);
+ }
+
if (is_local) {
info->domainname.string = samdb_result_string(ref_res, "nETBIOSName", NULL);
info->fulldomainname.string = samdb_result_string(ref_res, "dnsRoot", NULL);
- info->forest.string = NULL;
info->guid = samdb_result_guid(res, "objectGUID");
info->sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
} else {
info->domainname.string = samdb_result_string(res, "flatName", NULL);
info->fulldomainname.string = samdb_result_string(res, "trustPartner", NULL);
- info->forest.string = NULL;
info->guid = samdb_result_guid(res, "objectGUID");
info->sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
}
@@ -948,6 +1010,9 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
r->in.credential,
r->out.return_authenticator,
NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,(__location__ " Bad credentials - error\n"));
+ }
NT_STATUS_NOT_OK_RETURN(status);
sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
@@ -993,17 +1058,25 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
info1->num_trusts);
NT_STATUS_HAVE_NO_MEMORY(info1->trusts);
- status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->domaininfo, true);
+ status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->domaininfo,
+ true, false);
NT_STATUS_NOT_OK_RETURN(status);
for (i=0;i<ret2;i++) {
- status = fill_domain_trust_info(mem_ctx, res2[i], NULL, &info1->trusts[i], false);
+ status = fill_domain_trust_info(mem_ctx, res2[i], NULL, &info1->trusts[i],
+ false, true);
NT_STATUS_NOT_OK_RETURN(status);
}
- status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->trusts[i], true);
+ status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->trusts[i],
+ true, true);
NT_STATUS_NOT_OK_RETURN(status);
+ info1->dns_hostname.string = samdb_result_string(ref_res[0], "dnsRoot", NULL);
+ info1->workstation_flags =
+ NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS | NETR_WS_FLAG_HANDLES_SPN_UPDATE;
+ info1->supported_enc_types = 0; /* w2008 gives this 0 */
+
r->out.info.info1 = info1;
return NT_STATUS_OK;
diff --git a/source4/rpc_server/remote/dcesrv_remote.c b/source4/rpc_server/remote/dcesrv_remote.c
index cd32160d88..3cf8fbe8fb 100644
--- a/source4/rpc_server/remote/dcesrv_remote.c
+++ b/source4/rpc_server/remote/dcesrv_remote.c
@@ -225,7 +225,7 @@ static NTSTATUS remote_register_one_iface(struct dcesrv_context *dce_ctx, const
static NTSTATUS remote_op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
{
int i;
- const char **ifaces = str_list_make(dce_ctx, lp_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_remote", "interfaces"),NULL);
+ const char **ifaces = (const char **)str_list_make(dce_ctx, lp_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_remote", "interfaces"),NULL);
if (!ifaces) {
DEBUG(3,("remote_op_init_server: no interfaces configured\n"));
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index e54d518f76..22d201e58e 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -34,7 +34,7 @@
#include "libcli/ldap/ldap_ndr.h"
#include "libcli/security/security.h"
#include "rpc_server/samr/proto.h"
-#include "util/util_ldb.h"
+#include "../lib/util/util_ldb.h"
#include "param/param.h"
/* these query macros make samr_Query[User|Group]Info a bit easier to read */
@@ -341,7 +341,7 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL
partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
- ret = ldb_search_exp_fmt(c_state->sam_ctx, mem_ctx, &dom_res, ldb_get_default_basedn(c_state->sam_ctx),
+ ret = ldb_search(c_state->sam_ctx, mem_ctx, &dom_res, ldb_get_default_basedn(c_state->sam_ctx),
LDB_SCOPE_SUBTREE, dom_attrs, "(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain))");
if (ret != LDB_SUCCESS) {
DEBUG(0,("samdb: unable to find domains: %s\n", ldb_errstring(c_state->sam_ctx)));
@@ -373,7 +373,7 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL
for (i=0;i<dom_res->count-start_i;i++) {
array->entries[i].idx = start_i + i;
/* try and find the domain */
- ret = ldb_search_exp_fmt(c_state->sam_ctx, mem_ctx, &ref_res, partitions_basedn,
+ ret = ldb_search(c_state->sam_ctx, mem_ctx, &ref_res, partitions_basedn,
LDB_SCOPE_SUBTREE, ref_attrs, "(&(objectClass=crossRef)(ncName=%s))",
ldb_dn_get_linearized(dom_res->msgs[i]->dn));
@@ -1502,7 +1502,7 @@ static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call,
d_state = h->data;
/* don't have to worry about users in the builtin domain, as there are none */
- ret = ldb_search_exp_fmt(d_state->sam_ctx, mem_ctx, &res, d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=user");
+ ret = ldb_search(d_state->sam_ctx, mem_ctx, &res, d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=user");
if (ret != LDB_SUCCESS) {
DEBUG(3, ("Failed to search for Domain Users in %s: %s\n",
@@ -2110,7 +2110,7 @@ static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, T
a_state = h->data;
- ret = ldb_search_exp_fmt(a_state->sam_ctx, mem_ctx, &res, a_state->account_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=*");
+ ret = ldb_search(a_state->sam_ctx, mem_ctx, &res, a_state->account_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=*");
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
return NT_STATUS_NO_SUCH_GROUP;
@@ -2246,7 +2246,7 @@ static NTSTATUS dcesrv_samr_AddGroupMember(struct dcesrv_call_state *dce_call, T
/* In native mode, AD can also nest domain groups. Not sure yet
* whether this is also available via RPC. */
- ret = ldb_search_exp_fmt(d_state->sam_ctx, mem_ctx, &res,
+ ret = ldb_search(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));
@@ -2348,7 +2348,7 @@ static NTSTATUS dcesrv_samr_DeleteGroupMember(struct dcesrv_call_state *dce_call
/* In native mode, AD can also nest domain groups. Not sure yet
* whether this is also available via RPC. */
- ret = ldb_search_exp_fmt(d_state->sam_ctx, mem_ctx, &res,
+ ret = ldb_search(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));
@@ -4262,7 +4262,7 @@ static NTSTATUS dcesrv_samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_
status = dcesrv_samr_Connect(dce_call, mem_ctx, &c);
- r->out.info->info1.unknown1 = 3;
+ r->out.info->info1.client_version = SAMR_CONNECT_AFTER_W2K;
r->out.info->info1.unknown2 = 0;
r->out.level = r->in.level;
diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c
index b78a9ceaa7..859fd03801 100644
--- a/source4/rpc_server/samr/samr_password.c
+++ b/source4/rpc_server/samr/samr_password.c
@@ -25,14 +25,14 @@
#include "rpc_server/common/common.h"
#include "rpc_server/samr/dcesrv_samr.h"
#include "system/time.h"
-#include "lib/crypto/crypto.h"
+#include "../lib/crypto/crypto.h"
#include "dsdb/common/flags.h"
#include "libcli/ldap/ldap.h"
#include "dsdb/samdb/samdb.h"
#include "auth/auth.h"
#include "rpc_server/samr/proto.h"
#include "libcli/auth/libcli_auth.h"
-#include "util/util_ldb.h"
+#include "../lib/util/util_ldb.h"
#include "param/param.h"
/*
@@ -86,7 +86,8 @@ NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call,
}
msg = res[0];
- status = samdb_result_passwords(mem_ctx, msg, &lm_pwd, &nt_pwd);
+ status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
+ msg, &lm_pwd, &nt_pwd);
if (!NT_STATUS_IS_OK(status) || !lm_pwd || !nt_pwd) {
ldb_transaction_cancel(sam_ctx);
return NT_STATUS_WRONG_PASSWORD;
@@ -183,8 +184,8 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
struct samr_OemChangePasswordUser2 *r)
{
NTSTATUS status;
- char new_pass[512];
- uint32_t new_pass_len;
+ DATA_BLOB new_password, new_unicode_password;
+ char *new_pass;
struct samr_CryptPassword *pwbuf = r->in.password;
struct ldb_context *sam_ctx;
struct ldb_dn *user_dn;
@@ -195,6 +196,7 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
DATA_BLOB lm_pwd_blob;
uint8_t new_lm_hash[16];
struct samr_Password lm_verifier;
+ ssize_t unicode_pw_len;
if (pwbuf == NULL) {
return NT_STATUS_INVALID_PARAMETER;
@@ -231,7 +233,8 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
user_dn = res[0]->dn;
- status = samdb_result_passwords(mem_ctx, res[0], &lm_pwd, NULL);
+ status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
+ res[0], &lm_pwd, NULL);
if (!NT_STATUS_IS_OK(status) || !lm_pwd) {
ldb_transaction_cancel(sam_ctx);
return NT_STATUS_WRONG_PASSWORD;
@@ -242,18 +245,33 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob);
data_blob_free(&lm_pwd_blob);
- if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),
- &new_pass_len, STR_ASCII)) {
+ if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
ldb_transaction_cancel(sam_ctx);
DEBUG(3,("samr: failed to decode password buffer\n"));
return NT_STATUS_WRONG_PASSWORD;
}
+
+ if (convert_string_talloc(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
+ CH_DOS, CH_UNIX,
+ (const char *)new_password.data,
+ new_password.length,
+ (void **)&new_pass) == -1) {
+ DEBUG(3,("samr: failed to convert incoming password buffer to unix charset\n"));
+ ldb_transaction_cancel(sam_ctx);
+ return NT_STATUS_WRONG_PASSWORD;
+ }
- /* check LM verifier */
- if (lm_pwd == NULL) {
+ unicode_pw_len = convert_string_talloc(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
+ CH_DOS, CH_UTF16,
+ (const char *)new_password.data,
+ new_password.length,
+ (void **)&new_unicode_password.data);
+ if (unicode_pw_len == -1) {
+ DEBUG(3,("samr: failed to convert incoming password buffer to UTF16 charset\n"));
ldb_transaction_cancel(sam_ctx);
return NT_STATUS_WRONG_PASSWORD;
}
+ new_unicode_password.length = unicode_pw_len;
E_deshash(new_pass, new_lm_hash);
E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash);
@@ -278,7 +296,7 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
* due to password policies */
status = samdb_set_password(sam_ctx, mem_ctx,
user_dn, NULL,
- mod, new_pass,
+ mod, &new_unicode_password,
NULL, NULL,
true, /* this is a user password change */
NULL,
@@ -320,8 +338,7 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
struct samr_ChangePasswordUser3 *r)
{
NTSTATUS status;
- char new_pass[512];
- uint32_t new_pass_len;
+ DATA_BLOB new_password;
struct ldb_context *sam_ctx = NULL;
struct ldb_dn *user_dn;
int ret;
@@ -370,7 +387,8 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
user_dn = res[0]->dn;
- status = samdb_result_passwords(mem_ctx, res[0], &lm_pwd, &nt_pwd);
+ status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
+ res[0], &lm_pwd, &nt_pwd);
if (!NT_STATUS_IS_OK(status) ) {
goto failed;
}
@@ -385,40 +403,49 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob);
data_blob_free(&nt_pwd_blob);
- if (!decode_pw_buffer(r->in.nt_password->data, new_pass, sizeof(new_pass),
- &new_pass_len, STR_UNICODE)) {
+ if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) {
+ ldb_transaction_cancel(sam_ctx);
DEBUG(3,("samr: failed to decode password buffer\n"));
- status = NT_STATUS_WRONG_PASSWORD;
- goto failed;
+ return NT_STATUS_WRONG_PASSWORD;
}
-
+
if (r->in.nt_verifier == NULL) {
status = NT_STATUS_WRONG_PASSWORD;
goto failed;
}
/* check NT verifier */
- E_md4hash(new_pass, new_nt_hash);
+ mdfour(new_nt_hash, new_password.data, new_password.length);
+
E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash);
if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) {
status = NT_STATUS_WRONG_PASSWORD;
goto failed;
}
- /* check LM verifier */
+ /* check LM verifier (really not needed as we just checked the
+ * much stronger NT hash, but the RPC-SAMR test checks for
+ * this) */
if (lm_pwd && r->in.lm_verifier != NULL) {
- E_deshash(new_pass, new_lm_hash);
- E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);
- if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {
- status = NT_STATUS_WRONG_PASSWORD;
- goto failed;
+ char *new_pass;
+ if (convert_string_talloc(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
+ CH_UTF16, CH_UNIX,
+ (const char *)new_password.data,
+ new_password.length,
+ (void **)&new_pass) != -1) {
+ E_deshash(new_pass, new_lm_hash);
+ E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);
+ if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {
+ status = NT_STATUS_WRONG_PASSWORD;
+ goto failed;
+ }
}
}
-
mod = ldb_msg_new(mem_ctx);
if (mod == NULL) {
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto failed;
}
mod->dn = ldb_dn_copy(mod, user_dn);
@@ -431,7 +458,7 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
* due to password policies */
status = samdb_set_password(sam_ctx, mem_ctx,
user_dn, NULL,
- mod, new_pass,
+ mod, &new_password,
NULL, NULL,
true, /* this is a user password change */
&reason,
@@ -518,8 +545,7 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
struct samr_CryptPassword *pwbuf)
{
NTSTATUS nt_status;
- char new_pass[512];
- uint32_t new_pass_len;
+ DATA_BLOB new_password;
DATA_BLOB session_key = data_blob(NULL, 0);
nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
@@ -529,17 +555,16 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
arcfour_crypt_blob(pwbuf->data, 516, &session_key);
- if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),
- &new_pass_len, STR_UNICODE)) {
+ if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
DEBUG(3,("samr: failed to decode password buffer\n"));
return NT_STATUS_WRONG_PASSWORD;
}
-
+
/* set the password - samdb needs to know both the domain and user DNs,
so the domain password policy can be used */
return samdb_set_password(sam_ctx, mem_ctx,
account_dn, domain_dn,
- msg, new_pass,
+ msg, &new_password,
NULL, NULL,
false, /* This is a password set, not change */
NULL, NULL);
@@ -559,8 +584,7 @@ NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
struct samr_CryptPasswordEx *pwbuf)
{
NTSTATUS nt_status;
- char new_pass[512];
- uint32_t new_pass_len;
+ DATA_BLOB new_password;
DATA_BLOB co_session_key;
DATA_BLOB session_key = data_blob(NULL, 0);
struct MD5Context ctx;
@@ -582,17 +606,16 @@ NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
arcfour_crypt_blob(pwbuf->data, 516, &co_session_key);
- if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),
- &new_pass_len, STR_UNICODE)) {
+ if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
DEBUG(3,("samr: failed to decode password buffer\n"));
return NT_STATUS_WRONG_PASSWORD;
}
-
+
/* set the password - samdb needs to know both the domain and user DNs,
so the domain password policy can be used */
return samdb_set_password(sam_ctx, mem_ctx,
account_dn, domain_dn,
- msg, new_pass,
+ msg, &new_password,
NULL, NULL,
false, /* This is a password set, not change */
NULL, NULL);
diff --git a/source4/rpc_server/service_rpc.c b/source4/rpc_server/service_rpc.c
index b68cec4c7d..f168614ad5 100644
--- a/source4/rpc_server/service_rpc.c
+++ b/source4/rpc_server/service_rpc.c
@@ -25,7 +25,7 @@
#include "librpc/gen_ndr/ndr_dcerpc.h"
#include "auth/auth.h"
#include "auth/gensec/gensec.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
#include "rpc_server/dcerpc_server.h"
#include "lib/events/events.h"
#include "smbd/service_task.h"
@@ -436,6 +436,25 @@ static void dcesrv_task_init(struct task_server *task)
NTSTATUS status;
struct dcesrv_context *dce_ctx;
struct dcesrv_endpoint *e;
+ extern NTSTATUS dcerpc_server_wkssvc_init(void);
+ extern NTSTATUS dcerpc_server_drsuapi_init(void);
+ extern NTSTATUS dcerpc_server_winreg_init(void);
+ extern NTSTATUS dcerpc_server_spoolss_init(void);
+ extern NTSTATUS dcerpc_server_epmapper_init(void);
+ extern NTSTATUS dcerpc_server_srvsvc_init(void);
+ extern NTSTATUS dcerpc_server_netlogon_init(void);
+ extern NTSTATUS dcerpc_server_rpcecho_init(void);
+ extern NTSTATUS dcerpc_server_unixinfo_init(void);
+ extern NTSTATUS dcerpc_server_samr_init(void);
+ extern NTSTATUS dcerpc_server_remote_init(void);
+ extern NTSTATUS dcerpc_server_lsa_init(void);
+ init_module_fn static_init[] = { STATIC_DCESRV_MODULES };
+ init_module_fn *shared_init = load_samba_modules(NULL, task->lp_ctx, "dcerpc_server");
+
+ run_init_functions(static_init);
+ run_init_functions(shared_init);
+
+ talloc_free(shared_init);
task_server_set_title(task, "task[dcesrv]");
@@ -462,25 +481,6 @@ failed:
NTSTATUS server_service_rpc_init(void)
{
- extern NTSTATUS dcerpc_server_wkssvc_init(void);
- extern NTSTATUS dcerpc_server_drsuapi_init(void);
- extern NTSTATUS dcerpc_server_winreg_init(void);
- extern NTSTATUS dcerpc_server_spoolss_init(void);
- extern NTSTATUS dcerpc_server_epmapper_init(void);
- extern NTSTATUS dcerpc_server_srvsvc_init(void);
- extern NTSTATUS dcerpc_server_netlogon_init(void);
- extern NTSTATUS dcerpc_server_rpcecho_init(void);
- extern NTSTATUS dcerpc_server_unixinfo_init(void);
- extern NTSTATUS dcerpc_server_samr_init(void);
- extern NTSTATUS dcerpc_server_remote_init(void);
- extern NTSTATUS dcerpc_server_lsa_init(void);
- init_module_fn static_init[] = { STATIC_DCESRV_MODULES };
- init_module_fn *shared_init = load_samba_modules(NULL, global_loadparm, "dcerpc_server");
- run_init_functions(static_init);
- run_init_functions(shared_init);
-
- talloc_free(shared_init);
-
return register_server_service("rpc", dcesrv_task_init);
}
diff --git a/source4/rpc_server/winreg/rpc_winreg.c b/source4/rpc_server/winreg/rpc_winreg.c
index 430982b9f8..db11958026 100644
--- a/source4/rpc_server/winreg/rpc_winreg.c
+++ b/source4/rpc_server/winreg/rpc_winreg.c
@@ -489,8 +489,8 @@ static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call,
case SECURITY_SYSTEM:
case SECURITY_ADMINISTRATOR:
case SECURITY_USER:
- result = reg_key_get_value_by_name(mem_ctx, key,
- r->in.value_name.name, &value_type, &value_data);
+ result = reg_key_get_value_by_name(mem_ctx, key,
+ r->in.value_name->name, &value_type, &value_data);
if (!W_ERROR_IS_OK(result)) {
/* if the lookup wasn't successful, send client query back */
@@ -504,17 +504,16 @@ static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call,
return WERR_NOMEM;
}
*r->out.type = value_type;
- r->out.length = talloc(mem_ctx, uint32_t);
- if (!r->out.length) {
+ r->out.data_length = talloc(mem_ctx, uint32_t);
+ if (!r->out.data_length) {
return WERR_NOMEM;
}
*r->out.length = value_data.length;
- r->out.size = talloc(mem_ctx, uint32_t);
- if (!r->out.size) {
+ r->out.data_size = talloc(mem_ctx, uint32_t);
+ if (!r->out.data_size) {
return WERR_NOMEM;
}
- *r->out.size = value_data.length;
-
+ *r->out.data_size = value_data.length;
r->out.data = value_data.data;
return result;