summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/librpc/idl/drsuapi.idl40
-rw-r--r--source4/rpc_server/drsuapi/dcesrv_drsuapi.c6
-rw-r--r--source4/torture/rpc/drsuapi.c90
3 files changed, 129 insertions, 7 deletions
diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl
index 17e84fffab..481c1a1de1 100644
--- a/source4/librpc/idl/drsuapi.idl
+++ b/source4/librpc/idl/drsuapi.idl
@@ -17,8 +17,11 @@ interface drsuapi
[size_is(length)] uint8 data[];
} drsuapi_DsBindInfo;
+ /* this is a magic guid you need to pass to DsBind to make drsuapi_DsWriteAccountSpn() work */
+ const string DRSUAPI_DS_BIND_GUID = "e24d201a-4fd6-11d1-a3da-0000f875ae0d";
+
WERROR drsuapi_DsBind(
- [in] GUID *server_guid,
+ [in] GUID *bind_guid,
[in,out] drsuapi_DsBindInfo *bind_info,
[out,ref] policy_handle *bind_handle
);
@@ -145,8 +148,39 @@ interface drsuapi
);
/*****************/
- /* Function 0x0d */
- WERROR DRSUAPI_WRITE_SPN();
+ /* Function 0x0d */
+ typedef enum {
+ DRSUAPI_DS_SPN_OPERATION_ADD = 0,
+ DRSUAPI_DS_SPN_OPERATION_REPLACE= 1,
+ DRSUAPI_DS_SPN_OPERATION_DELETE = 2
+ } drsuapi_DsSpnOperation;
+
+ typedef struct {
+ int32 operation;
+ int32 unknown1;
+ unistr *object_dn;
+ [range(0,10000)] uint32 count;
+ [size_is(count)] drsuapi_DsNameString *spn_names;
+ } drsuapi_DsWriteAccountSpnRequest1;
+
+ typedef union {
+ [case(1)] drsuapi_DsWriteAccountSpnRequest1 req1;
+ } drsuapi_DsWriteAccountSpnRequest;
+
+ typedef struct {
+ WERROR status;
+ } drsuapi_DsWriteAccountSpnResult1;
+
+ typedef union {
+ [case(1)] drsuapi_DsWriteAccountSpnResult1 res1;
+ } drsuapi_DsWriteAccountSpnResult;
+
+ WERROR drsuapi_DsWriteAccountSpn(
+ [in,ref] policy_handle *bind_handle,
+ [in, out] uint32 level,
+ [in,switch_is(level)] drsuapi_DsWriteAccountSpnRequest req,
+ [out,switch_is(level)] drsuapi_DsWriteAccountSpnResult res
+ );
/*****************/
/* Function 0x0e */
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
index 617bc02742..eb38a22f43 100644
--- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
+++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
@@ -200,10 +200,10 @@ static WERROR (*drsuapi_DsCrackNames)(struct dcesrv_call_state *dce_call, TALLOC
struct drsuapi_DsCrackNames *r) = dcesrv_drsuapi_DsCrackNames;
/*
- DRSUAPI_WRITE_SPN
+ drsuapi_DsWriteAccountSpn
*/
-static WERROR DRSUAPI_WRITE_SPN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct DRSUAPI_WRITE_SPN *r)
+static WERROR drsuapi_DsWriteAccountSpn(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsWriteAccountSpn *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
diff --git a/source4/torture/rpc/drsuapi.c b/source4/torture/rpc/drsuapi.c
index 6696d12136..b6b1ddf6dc 100644
--- a/source4/torture/rpc/drsuapi.c
+++ b/source4/torture/rpc/drsuapi.c
@@ -26,6 +26,7 @@
struct DsPrivate {
struct policy_handle bind_handle;
+ struct GUID bind_guid;
const char *domain_guid_str;
struct drsuapi_DsGetDCInfo2 dcinfo;
};
@@ -37,7 +38,9 @@ static BOOL test_DsBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
struct drsuapi_DsBind r;
BOOL ret = True;
- r.in.server_guid = NULL;
+ GUID_from_string(DRSUAPI_DS_BIND_GUID, &priv->bind_guid);
+
+ r.in.bind_guid = &priv->bind_guid;
r.in.bind_info = NULL;
r.out.bind_handle = &priv->bind_handle;
@@ -366,6 +369,8 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return ret;
}
+ r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID;
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
names[0].str = GUID_string2(mem_ctx, &priv->dcinfo.server_guid);
printf("testing DsCrackNames with Server GUID '%s' desired format:%d\n",
@@ -388,6 +393,8 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return ret;
}
+ r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID;
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
names[0].str = GUID_string2(mem_ctx, &priv->dcinfo.ntds_guid);
printf("testing DsCrackNames with NTDS GUID '%s' desired format:%d\n",
@@ -410,6 +417,30 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return ret;
}
+ r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID;
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
+ names[0].str = GUID_string2(mem_ctx, &priv->bind_guid);
+
+ printf("testing DsCrackNames with NTDS GUID '%s' desired format:%d\n",
+ names[0].str, r.in.req.req1.format_desired);
+
+ 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("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
+ ret = False;
+ } else if (!W_ERROR_IS_OK(r.out.result)) {
+ printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
+ ret = False;
+ }
+
+ if (!ret) {
+ return ret;
+ }
+
return ret;
}
@@ -543,6 +574,59 @@ static BOOL test_DsGetDCInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return ret;
}
+static BOOL test_DsWriteAccountSpn(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ struct DsPrivate *priv)
+{
+ NTSTATUS status;
+ struct drsuapi_DsWriteAccountSpn r;
+ struct drsuapi_DsNameString names[2];
+ BOOL ret = True;
+
+ r.in.bind_handle = &priv->bind_handle;
+ r.in.level = 1;
+
+ printf("testing DsWriteAccountSpn\n");
+
+ r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_ADD;
+ r.in.req.req1.unknown1 = 0;
+ r.in.req.req1.object_dn = priv->dcinfo.computer_dn;
+ r.in.req.req1.count = 2;
+ r.in.req.req1.spn_names = names;
+ names[0].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.netbios_name);
+ names[1].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.dns_name);
+
+ status = dcerpc_drsuapi_DsWriteAccountSpn(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("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
+ ret = False;
+ } else if (!W_ERROR_IS_OK(r.out.result)) {
+ printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
+ ret = False;
+ }
+
+ r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_DELETE;
+ r.in.req.req1.unknown1 = 0;
+
+ status = dcerpc_drsuapi_DsWriteAccountSpn(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("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
+ ret = False;
+ } else if (!W_ERROR_IS_OK(r.out.result)) {
+ printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
+ ret = False;
+ }
+
+ return ret;
+}
+
static BOOL test_DsUnbind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
struct DsPrivate *priv)
{
@@ -605,6 +689,10 @@ BOOL torture_rpc_drsuapi(void)
ret = False;
}
+ if (!test_DsWriteAccountSpn(p, mem_ctx, &priv)) {
+ ret = False;
+ }
+
if (!test_DsUnbind(p, mem_ctx, &priv)) {
ret = False;
}