summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/librpc/idl/drsuapi.idl73
-rw-r--r--source4/rpc_server/config.mk2
-rw-r--r--source4/rpc_server/drsuapi/dcesrv_drsuapi.c50
-rw-r--r--source4/rpc_server/drsuapi/drsuapi_cracknames.c128
-rw-r--r--source4/torture/rpc/drsuapi.c155
5 files changed, 330 insertions, 78 deletions
diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl
index fc9aee6b7f..d49f3d294a 100644
--- a/source4/librpc/idl/drsuapi.idl
+++ b/source4/librpc/idl/drsuapi.idl
@@ -72,44 +72,77 @@ interface drsuapi
/*****************/
/* Function 0x0c */
+ typedef enum {
+ DRSUAPI_DS_NAME_STATUS_OK = 0,
+ DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR = 1,
+ DRSUAPI_DS_NAME_STATUS_NOT_FOUND = 2,
+ DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE = 3,
+ DRSUAPI_DS_NAME_STATUS_NO_MAPPING = 4,
+ DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY = 5,
+ DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING = 6,
+ DRSUAPI_DS_NAME_STATUS_TRUST_REFERRAL = 7
+ } drsuapi_DsNameStatus;
+
+ typedef enum {
+ DRSUAPI_DS_NAME_FLAG_NO_FLAGS = 0x0,
+ DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY = 0x1,
+ DRSUAPI_DS_NAME_FLAG_EVAL_AT_DC = 0x2,
+ DRSUAPI_DS_NAME_FLAG_GCVERIFY = 0x4,
+ DRSUAPI_DS_NAME_FLAG_TRUST_REFERRAL = 0x8
+ } drsuapi_DsNameFlags;
+
+ typedef enum {
+ DRSUAPI_DS_NAME_FORMAT_UKNOWN = 0,
+ DRSUAPI_DS_NAME_FORMAT_FQDN_1779 = 1,
+ DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT = 2,
+ DRSUAPI_DS_NAME_FORMAT_DISPLAY = 3,
+ DRSUAPI_DS_NAME_FORMAT_GUID = 6,
+ DRSUAPI_DS_NAME_FORMAT_CANONICAL = 7,
+ DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL = 8,
+ DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX = 9,
+ DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL = 10,
+ DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY = 11,
+ DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN = 12
+ } drsuapi_DsNameFormat;
+
typedef struct {
unistr *str;
- } drsuapi_DsCrackNamesInInfo1Names;
+ } drsuapi_DsNameString;
typedef struct {
- uint32 unknown1;
- uint32 unknown2;
- uint32 unknown3;
- uint32 unknown4;
- uint32 unknown5;
+ uint32 unknown1; /* 0x000004e4 */
+ uint32 unknown2; /* 0x00000407 */
+ uint32 format_flags;
+ uint32 format_offered;
+ uint32 format_desired;
[range(1,10000)] uint32 count;
- [size_is(count)] drsuapi_DsCrackNamesInInfo1Names *names;
- } drsuapi_DsCrackNamesInInfo1;
+ [size_is(count)] drsuapi_DsNameString *names;
+ } drsuapi_DsNameRequest1;
typedef union {
- [case(1)] drsuapi_DsCrackNamesInInfo1 info1;
- } drsuapi_DsCrackNamesInInfo;
+ [case(1)] drsuapi_DsNameRequest1 req1;
+ } drsuapi_DsNameRequest;
typedef struct {
- uint32 unknown1;
- unistr *name1;
- unistr *name2;
- } drsuapi_DsCrackNamesOutInfo1Names;
+ uint32 status;
+ unistr *dns_domain_name;
+ unistr *result_name;
+ } drsuapi_DsNameInfo1;
typedef struct {
uint32 count;
- [size_is(count)] drsuapi_DsCrackNamesOutInfo1Names *names;
- } drsuapi_DsCrackNamesOutInfo1;
+ [size_is(count)] drsuapi_DsNameInfo1 *array;
+ } drsuapi_DsNameCtr1;
typedef union {
- [case(1)] drsuapi_DsCrackNamesOutInfo1 *info1;
- } drsuapi_DsCrackNamesOutInfo;
+ [case(1)] drsuapi_DsNameCtr1 *ctr1;
+ } drsuapi_DsNameCtr;
NTSTATUS drsuapi_DsCrackNames(
[in,ref] policy_handle *bind_handle,
[in, out] uint32 level,
- [in,switch_is(level)] drsuapi_DsCrackNamesInInfo in,
- [out,switch_is(level)] drsuapi_DsCrackNamesOutInfo out
+ [in,switch_is(level)] drsuapi_DsNameRequest req,
+ [out,switch_is(level)] drsuapi_DsNameCtr ctr
);
/*****************/
diff --git a/source4/rpc_server/config.mk b/source4/rpc_server/config.mk
index 350803afd9..9c0751a1b9 100644
--- a/source4/rpc_server/config.mk
+++ b/source4/rpc_server/config.mk
@@ -153,6 +153,8 @@ REQUIRED_SUBSYSTEMS = \
[MODULE::dcerpc_drsuapi]
INIT_OBJ_FILES = \
rpc_server/drsuapi/dcesrv_drsuapi.o
+ADD_OBJ_FILES = \
+ rpc_server/drsuapi/drsuapi_cracknames.o
REQUIRED_SUBSYSTEMS = \
SAMDB \
DCERPC_COMMON
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
index 06fa1bba95..503a54b6b3 100644
--- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
+++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
@@ -190,54 +190,10 @@ static NTSTATUS DRSUAPI_GET_NT4_CHANGELOG(struct dcesrv_call_state *dce_call, TA
/*
- drsuapi_DsCrackNames
+ drsuapi_DsCrackNames => drsuapip_cracknames.c
*/
-static NTSTATUS drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct drsuapi_DsCrackNames *r)
-{
- struct dcesrv_handle *h;
-
- r->out.level = r->in.level;
- ZERO_STRUCT(r->out.out);
-
- DCESRV_PULL_HANDLE(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
-
- switch (r->in.level) {
- case 1: {
- int i;
-
- r->out.out.info1 = talloc_p(mem_ctx, struct drsuapi_DsCrackNamesOutInfo1);
- NTSTATUS_TALLOC_CHECK(r->out.out.info1);
-
- r->out.out.info1->names = talloc_array_p(mem_ctx,
- struct drsuapi_DsCrackNamesOutInfo1Names,
- r->in.in.info1.count);
- NTSTATUS_TALLOC_CHECK(r->out.out.info1->names);
-
- r->out.out.info1->count = r->in.in.info1.count;
-
- for (i=0; i < r->out.out.info1->count; i++) {
- const char *name;
- r->out.out.info1->names[i].unknown1 = 2;
- r->out.out.info1->names[i].name1 = NULL;
- r->out.out.info1->names[i].name2 = NULL;
-
- /* TODO: fill crack the right names! */
- name = talloc_asprintf(mem_ctx, "%s/", lp_realm());
- if (strcmp(name, r->in.in.info1.names[i].str) != 0) {
- continue;
- }
- r->out.out.info1->names[i].unknown1 = 0;
- r->out.out.info1->names[i].name1 = talloc_asprintf(mem_ctx, "%s", lp_realm());
- r->out.out.info1->names[i].name2 = talloc_asprintf(mem_ctx, "%s\\", lp_workgroup());
- }
- return NT_STATUS_OK;
- }
- }
-
- return NT_STATUS_INVALID_LEVEL;
-}
-
+static NTSTATUS (*drsuapi_DsCrackNames)(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsCrackNames *r) = dcesrv_drsuapi_DsCrackNames;
/*
DRSUAPI_WRITE_SPN
diff --git a/source4/rpc_server/drsuapi/drsuapi_cracknames.c b/source4/rpc_server/drsuapi/drsuapi_cracknames.c
new file mode 100644
index 0000000000..1a31d541ba
--- /dev/null
+++ b/source4/rpc_server/drsuapi/drsuapi_cracknames.c
@@ -0,0 +1,128 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ endpoint server for the drsuapi pipe
+ DsCrackNames()
+
+ Copyright (C) Stefan Metzmacher 2004
+
+ 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
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+*/
+
+#include "includes.h"
+#include "rpc_server/common/common.h"
+#include "rpc_server/drsuapi/dcesrv_drsuapi.h"
+
+
+static NTSTATUS DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
+ uint32 format_offered, uint32 format_desired, const char *name,
+ struct drsuapi_DsNameInfo1 *info1)
+{
+ info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
+ info1->dns_domain_name = NULL;
+ info1->result_name = NULL;
+
+ /* TODO: fill crack the correct names in all cases! */
+ switch (format_offered) {
+ case DRSUAPI_DS_NAME_FORMAT_CANONICAL: {
+ int ret;
+ char *str;
+
+ str = talloc_asprintf(mem_ctx, "%s/", lp_realm());
+ NTSTATUS_TALLOC_CHECK(str);
+
+ ret = strcasecmp(str, name);
+ talloc_free(str);
+ if (ret != 0) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return NT_STATUS_OK;
+ }
+
+ info1->status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
+ info1->dns_domain_name = talloc_asprintf(mem_ctx, "%s", lp_realm());
+ NTSTATUS_TALLOC_CHECK(info1->dns_domain_name);
+ switch (format_desired) {
+ case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT:
+ info1->status = DRSUAPI_DS_NAME_STATUS_OK;
+ info1->result_name = talloc_asprintf(mem_ctx, "%s\\",
+ lp_workgroup());
+ NTSTATUS_TALLOC_CHECK(info1->result_name);
+ return NT_STATUS_OK;
+ default:
+ return NT_STATUS_OK;
+ }
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ default: {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return NT_STATUS_OK;
+ }
+ }
+
+ return NT_STATUS_INVALID_PARAMETER;
+}
+
+/*
+ drsuapi_DsCrackNames
+*/
+NTSTATUS dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsCrackNames *r)
+{
+ NTSTATUS status;
+ struct drsuapi_bind_state *b_state;
+ struct dcesrv_handle *h;
+
+ r->out.level = r->in.level;
+ ZERO_STRUCT(r->out.ctr);
+
+ DCESRV_PULL_HANDLE(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
+ b_state = h->data;
+
+ switch (r->in.level) {
+ case 1: {
+ struct drsuapi_DsNameInfo1 *names;
+ int count;
+ int i;
+
+ r->out.ctr.ctr1 = talloc_p(mem_ctx, struct drsuapi_DsNameCtr1);
+ NTSTATUS_TALLOC_CHECK(r->out.ctr.ctr1);
+
+ r->out.ctr.ctr1->count = 0;
+ r->out.ctr.ctr1->array = NULL;
+
+ count = r->in.req.req1.count;
+ names = talloc_array_p(mem_ctx, struct drsuapi_DsNameInfo1, count);
+ NTSTATUS_TALLOC_CHECK(names);
+
+ for (i=0; i < count; i++) {
+ status = DsCrackNameOneName(b_state, mem_ctx,
+ r->in.req.req1.format_offered,
+ r->in.req.req1.format_desired,
+ r->in.req.req1.names[i].str,
+ &names[i]);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+
+ r->out.ctr.ctr1->count = count;
+ r->out.ctr.ctr1->array = names;
+
+ return NT_STATUS_OK;
+ }
+ }
+
+ return NT_STATUS_INVALID_LEVEL;
+}
diff --git a/source4/torture/rpc/drsuapi.c b/source4/torture/rpc/drsuapi.c
index aed7f884d2..562291c6de 100644
--- a/source4/torture/rpc/drsuapi.c
+++ b/source4/torture/rpc/drsuapi.c
@@ -53,20 +53,24 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
{
NTSTATUS status;
struct drsuapi_DsCrackNames r;
- struct drsuapi_DsCrackNamesInInfo1Names names[1];
+ struct drsuapi_DsNameString names[1];
BOOL ret = True;
+ const char *dns_domain;
+ const char *nt4_domain;
+ const char *FQDN_1779_domain;
+ const char *FQDN_1779_name;
ZERO_STRUCT(r);
- r.in.bind_handle = bind_handle;
- r.in.level = 1;
- r.in.in.info1.unknown1 = 0x000004e4;
- r.in.in.info1.unknown2 = 0x00000407;
- r.in.in.info1.unknown3 = 0x00000000;
- r.in.in.info1.unknown4 = 0x00000007;
- r.in.in.info1.unknown5 = 0x00000002;
- r.in.in.info1.count = 1;
- r.in.in.info1.names = names;
-
+ r.in.bind_handle = bind_handle;
+ r.in.level = 1;
+ r.in.req.req1.unknown1 = 0x000004e4;
+ r.in.req.req1.unknown2 = 0x00000407;
+ r.in.req.req1.count = 1;
+ r.in.req.req1.names = names;
+ r.in.req.req1.format_flags = DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
+
+ r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_CANONICAL;
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
names[0].str = talloc_asprintf(mem_ctx, "%s/", lp_realm());
status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
@@ -79,6 +83,135 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
ret = False;
}
+ if (!ret) {
+ return ret;
+ }
+
+ dns_domain = r.out.ctr.ctr1->array[0].dns_domain_name;
+ nt4_domain = r.out.ctr.ctr1->array[0].result_name;
+
+ r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
+ names[0].str = nt4_domain;
+
+ status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+ }
+ printf("drsuapi_DsCrackNames failed - %s\n", errstr);
+ ret = False;
+ }
+
+ if (!ret) {
+ return ret;
+ }
+
+ FQDN_1779_domain = r.out.ctr.ctr1->array[0].result_name;
+
+ r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
+ names[0].str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, dcerpc_server_name(p));
+
+ status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+ }
+ printf("drsuapi_DsCrackNames failed - %s\n", errstr);
+ ret = False;
+ }
+
+ if (!ret) {
+ return ret;
+ }
+
+ FQDN_1779_name = r.out.ctr.ctr1->array[0].result_name;
+
+ r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL;
+ names[0].str = FQDN_1779_name;
+
+ status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+ }
+ printf("drsuapi_DsCrackNames failed - %s\n", errstr);
+ ret = False;
+ }
+
+ if (!ret) {
+ return ret;
+ }
+
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_DISPLAY;
+
+ status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+ }
+ printf("drsuapi_DsCrackNames failed - %s\n", errstr);
+ ret = False;
+ }
+
+ if (!ret) {
+ return ret;
+ }
+
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_GUID;
+
+ status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+ }
+ printf("drsuapi_DsCrackNames failed - %s\n", errstr);
+ ret = False;
+ }
+
+ if (!ret) {
+ return ret;
+ }
+
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL;
+
+ status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+ }
+ printf("drsuapi_DsCrackNames failed - %s\n", errstr);
+ ret = False;
+ }
+
+ if (!ret) {
+ return ret;
+ }
+
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL;
+
+ status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+ }
+ printf("drsuapi_DsCrackNames failed - %s\n", errstr);
+ ret = False;
+ }
+
+ if (!ret) {
+ return ret;
+ }
+
return ret;
}