diff options
-rw-r--r-- | source4/librpc/idl/drsuapi.idl | 137 | ||||
-rw-r--r-- | source4/rpc_server/drsuapi/dcesrv_drsuapi.c | 18 | ||||
-rw-r--r-- | source4/torture/rpc/drsuapi.c | 70 |
3 files changed, 201 insertions, 24 deletions
diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl index 759599e707..8a6a96dcac 100644 --- a/source4/librpc/idl/drsuapi.idl +++ b/source4/librpc/idl/drsuapi.idl @@ -4,6 +4,7 @@ uuid("e3514235-4b06-11d1-ab04-00c04fc2dcd2"), version(4.0), endpoint("ncacn_np:[\\pipe\\lsass]","ncacn_np:[\\pipe\\protected_storage]", "ncacn_ip_tcp:", "ncalrpc:"), + authservice("ldap"), helpstring("Active Directory Replication"), pointer_default(unique) ] @@ -112,19 +113,46 @@ interface drsuapi /*****************/ /* Function 0x02 */ - typedef [flag(NDR_PAHEX)] struct { + typedef [gensize,flag(NDR_PAHEX)] struct { + [value(ndr_size_drsuapi_DsReplicaSyncRequest1Info(r, ndr->flags)-4)] uint32 __ndr_size; uint32 unknown1; - uint32 unknown2; GUID guid1; - uint8 unknown3[28]; + uint8 byte_array[28]; [flag(STR_SIZE4|STR_CHARLEN|STR_CONFORMANT)] string nc_dn; } drsuapi_DsReplicaSyncRequest1Info; + typedef bitmap { + DRSUAPI_DS_REPLICA_SYNC_ASYNCHRONOUS_OPERATION = 0x00000001, + DRSUAPI_DS_REPLICA_SYNC_WRITEABLE = 0x00000002, + DRSUAPI_DS_REPLICA_SYNC_PERIODIC = 0x00000004, + DRSUAPI_DS_REPLICA_SYNC_INTERSITE_MESSAGING = 0x00000008, + DRSUAPI_DS_REPLICA_SYNC_ALL_SOURCES = 0x00000010, + DRSUAPI_DS_REPLICA_SYNC_FULL = 0x00000020, + DRSUAPI_DS_REPLICA_SYNC_URGENT = 0x00000040, + DRSUAPI_DS_REPLICA_SYNC_NO_DISCARD = 0x00000080, + DRSUAPI_DS_REPLICA_SYNC_FORCE = 0x00000100, + DRSUAPI_DS_REPLICA_SYNC_ADD_REFERENCE = 0x00000200, + DRSUAPI_DS_REPLICA_SYNC_NEVER_COMPLETED = 0x00000400, + DRSUAPI_DS_REPLICA_SYNC_TWO_WAY = 0x00000800, + DRSUAPI_DS_REPLICA_SYNC_NEVER_NOTIFY = 0x00001000, + DRSUAPI_DS_REPLICA_SYNC_INITIAL = 0x00002000, + DRSUAPI_DS_REPLICA_SYNC_USE_COMPRESSION = 0x00004000, + DRSUAPI_DS_REPLICA_SYNC_ABANDONED = 0x00008000, + DRSUAPI_DS_REPLICA_SYNC_INITIAL_IN_PROGRESS = 0x00010000, + DRSUAPI_DS_REPLICA_SYNC_PARTIAL_ATTRIBUTE_SET = 0x00020000, + DRSUAPI_DS_REPLICA_SYNC_REQUEUE = 0x00040000, + DRSUAPI_DS_REPLICA_SYNC_NOTIFICATION = 0x00080000, + DRSUAPI_DS_REPLICA_SYNC_ASYNCHRONOUS_REPLICA = 0x00100000, + DRSUAPI_DS_REPLICA_SYNC_CRITICAL = 0x00200000, + DRSUAPI_DS_REPLICA_SYNC_FULL_IN_PROGRESS = 0x00400000, + DRSUAPI_DS_REPLICA_SYNC_PREEMPTED = 0x00800000 + } drsuapi_DsReplicaSyncOptions; + typedef struct { drsuapi_DsReplicaSyncRequest1Info *info; GUID guid1; astring *string1; - uint32 unknown1; + drsuapi_DsReplicaSyncOptions options; } drsuapi_DsReplicaSyncRequest1; typedef [switch_type(int32)] union { @@ -138,23 +166,95 @@ interface drsuapi ); /*****************/ - /* Function 0x03 */ - WERROR DRSUAPI_GET_NC_CHANGES(); + /* Function 0x03 */ + typedef struct { + hyper usn1; + hyper usn2; + hyper usn3; + } drsuapi_DsGetNCChangesUsnTriple; + + typedef struct { + GUID guid1; + GUID guid2; + uint32 unknown1[20]; + drsuapi_DsReplicaSyncRequest1Info sync_req_info1; + drsuapi_DsGetNCChangesUsnTriple usn; + } drsuapi_DsGetNCChangesRequest8; + + typedef [switch_type(int32)] union { + [case(8)] drsuapi_DsGetNCChangesRequest8 req8; + } drsuapi_DsGetNCChangesRequest; + + typedef struct { + } drsuapi_DsGetNCChangesCtr7; + + typedef [switch_type(int32)] union { + [case(7)] drsuapi_DsGetNCChangesCtr7 ctr7; + } drsuapi_DsGetNCChangesCtr; + + WERROR drsuapi_DsGetNCChanges( + [in,ref] policy_handle *bind_handle, + [in,out] int32 level, + [in,switch_is(level)] drsuapi_DsGetNCChangesRequest req, + [out,switch_is(level)] drsuapi_DsGetNCChangesCtr ctr + ); /*****************/ /* Function 0x04 */ - WERROR DRSUAPI_UPDATE_REFS(); + typedef bitmap { + DRSUAPI_DS_REPLICA_UPDATE_ASYNCHRONOUS_OPERATION = 0x00000001, + DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE = 0x00000002, + DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE = 0x00000004, + DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE = 0x00000008, + DRSUAPI_DS_REPLICA_UPDATE_0x00000010 = 0x00000010 + } drsuapi_DsReplicaUpdateRefsOptions; + + typedef struct { + uint32 unknown1; + uint32 unknown2; + GUID dest_dsa_guid; + drsuapi_DsReplicaUpdateRefsOptions options; + drsuapi_DsReplicaSyncRequest1Info sync_req_info1; + ascstr dest_dsa_dns_name; + } drsuapi_DsReplicaUpdateRefsRequest1; + + typedef [switch_type(int32)] union { + [case(1)] drsuapi_DsReplicaUpdateRefsRequest1 req1; + } drsuapi_DsReplicaUpdateRefsRequest; + + WERROR drsuapi_DsReplicaUpdateRefs( + [in,ref] policy_handle *bind_handle, + [in] int32 level, + [in,switch_is(level)] drsuapi_DsReplicaUpdateRefsRequest req + ); /*****************/ /* Function 0x05 */ + typedef bitmap { + DRSUAPI_DS_REPLICA_ADD_ASYNCHRONOUS_OPERATION = 0x00000001, + DRSUAPI_DS_REPLICA_ADD_WRITEABLE = 0x00000002 + /* TODO ... */ + } drsuapi_DsReplicaAddOptions; + WERROR DRSUAPI_REPLICA_ADD(); /*****************/ /* Function 0x06 */ + typedef bitmap { + DRSUAPI_DS_REPLICA_DELETE_ASYNCHRONOUS_OPERATION = 0x00000001, + DRSUAPI_DS_REPLICA_DELETE_WRITEABLE = 0x00000002 + /* TODO ... */ + } drsuapi_DsReplicaDeleteOptions; + WERROR DRSUAPI_REPLICA_DEL(); /*****************/ /* Function 0x07 */ + typedef bitmap { + DRSUAPI_DS_REPLICA_MODIFY_ASYNCHRONOUS_OPERATION = 0x00000001, + DRSUAPI_DS_REPLICA_MODIFY_WRITEABLE = 0x00000002 + } drsuapi_DsReplicaModifyOptions; + WERROR DRSUAPI_REPLICA_MODIFY(); /*****************/ @@ -369,7 +469,7 @@ interface drsuapi /*****************/ /* Function 0x11 */ - WERROR DRSUAPI_ADD_ENTRY(); + WERROR drsuapi_DsAddEntry(); /*****************/ /* Function 0x12 */ @@ -486,12 +586,29 @@ interface drsuapi [size_is(count)] drsuapi_DsReplicaKccDsaFailure array[]; } drsuapi_DsReplicaKccDsaFailuresCtr; + typedef enum { + DRSUAPI_DS_REPLICA_OP_TYPE_SYNC = 0, + DRSUAPI_DS_REPLICA_OP_TYPE_ADD = 1, + DRSUAPI_DS_REPLICA_OP_TYPE_DELETE = 2, + DRSUAPI_DS_REPLICA_OP_TYPE_MODIFY = 3, + DRSUAPI_DS_REPLICA_OP_TYPE_UPDATE_REFS = 4 + } drsuapi_DsReplicaOpType; + + typedef [switch_type(drsuapi_DsReplicaOpType)] union { + [case(DRSUAPI_DS_REPLICA_OP_TYPE_SYNC)] drsuapi_DsReplicaSyncOptions sync; + [case(DRSUAPI_DS_REPLICA_OP_TYPE_ADD)] drsuapi_DsReplicaAddOptions add; + [case(DRSUAPI_DS_REPLICA_OP_TYPE_DELETE)] drsuapi_DsReplicaDeleteOptions delete; + [case(DRSUAPI_DS_REPLICA_OP_TYPE_MODIFY)] drsuapi_DsReplicaModifyOptions modify; + [case(DRSUAPI_DS_REPLICA_OP_TYPE_UPDATE_REFS)] drsuapi_DsReplicaUpdateRefsOptions update_refs; + [default] uint32 unknown; + } drsuapi_DsRplicaOpOptions; + typedef struct { NTTIME operation_start; uint32 serial_num; /* unique till reboot */ uint32 priority; - uint16 operation_type; - uint32 options_flags; + drsuapi_DsReplicaOpType operation_type; + [switch_is(operation_type)] drsuapi_DsRplicaOpOptions options; unistr *nc_dn; unistr *remote_dsa_obj_dn; unistr *remote_dsa_address; diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c index 6a1ccb00d5..13058296a5 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c @@ -110,20 +110,20 @@ static WERROR drsuapi_DsReplicaSync(struct dcesrv_call_state *dce_call, TALLOC_C /* - DRSUAPI_GET_NC_CHANGES + drsuapi_DsGetNCChanges */ -static WERROR DRSUAPI_GET_NC_CHANGES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct DRSUAPI_GET_NC_CHANGES *r) +static WERROR drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct drsuapi_DsGetNCChanges *r) { DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); } /* - DRSUAPI_UPDATE_REFS + drsuapi_DsReplicaUpdateRefs */ -static WERROR DRSUAPI_UPDATE_REFS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct DRSUAPI_UPDATE_REFS *r) +static WERROR drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct drsuapi_DsReplicaUpdateRefs *r) { DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); } @@ -246,10 +246,10 @@ static WERROR drsuapi_DsGetDomainControllerInfo(struct dcesrv_call_state *dce_ca /* - DRSUAPI_ADD_ENTRY + drsuapi_DsAddEntry */ -static WERROR DRSUAPI_ADD_ENTRY(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct DRSUAPI_ADD_ENTRY *r) +static WERROR drsuapi_DsAddEntry(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct drsuapi_DsAddEntry *r) { DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); } diff --git a/source4/torture/rpc/drsuapi.c b/source4/torture/rpc/drsuapi.c index e10c088e36..a6c0f5b9c6 100644 --- a/source4/torture/rpc/drsuapi.c +++ b/source4/torture/rpc/drsuapi.c @@ -29,6 +29,7 @@ struct DsPrivate { struct GUID bind_guid; const char *domain_obj_dn; const char *domain_guid_str; + const char *domain_dns_name; struct GUID domain_guid; struct drsuapi_DsGetDCInfo2 dcinfo; }; @@ -133,6 +134,7 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return ret; } + priv->domain_dns_name = r.out.ctr.ctr1->array[0].dns_domain_name; priv->domain_guid_str = r.out.ctr.ctr1->array[0].result_name; GUID_from_string(priv->domain_guid_str, &priv->domain_guid); @@ -780,21 +782,20 @@ static BOOL test_DsReplicaSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.bind_handle = &priv->bind_handle; for (i=0; i < ARRAY_SIZE(array); i++) { - printf("testing DsReplicaGetInfo level %d\n", + printf("testing DsReplicaSync level %d\n", array[i].level); r.in.level = array[i].level; switch(r.in.level) { case 1: r.in.req.req1.info = &info1; - r.in.req.req1.info->unknown1 = 32; - r.in.req.req1.info->unknown2 = 120; + r.in.req.req1.info->unknown1 = 0; ZERO_STRUCT(r.in.req.req1.info->guid1); - ZERO_STRUCT(r.in.req.req1.info->unknown3); + ZERO_STRUCT(r.in.req.req1.info->byte_array); r.in.req.req1.info->nc_dn = priv->domain_obj_dn?priv->domain_obj_dn:""; r.in.req.req1.guid1 = priv->dcinfo.ntds_guid; r.in.req.req1.string1 = NULL; - r.in.req.req1.unknown1 = 16; + r.in.req.req1.options = 16; break; } @@ -815,6 +816,63 @@ static BOOL test_DsReplicaSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return ret; } +static BOOL test_DsReplicaUpdateRefs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, + struct DsPrivate *priv) +{ + NTSTATUS status; + BOOL ret = True; + int i; + struct drsuapi_DsReplicaUpdateRefs r; + struct GUID null_guid; + struct { + int32_t level; + } array[] = { + { + 1 + } + }; + + ZERO_STRUCT(null_guid); + + r.in.bind_handle = &priv->bind_handle; + + for (i=0; i < ARRAY_SIZE(array); i++) { + printf("testing DsReplicaUpdateRefs level %d\n", + array[i].level); + + r.in.level = array[i].level; + switch(r.in.level) { + case 1: + r.in.req.req1.unknown1 = 0; + r.in.req.req1.unknown2 = 0; + r.in.req.req1.dest_dsa_guid = null_guid; + r.in.req.req1.options = 0; + r.in.req.req1.sync_req_info1.unknown1 = 0; + r.in.req.req1.sync_req_info1.guid1 = null_guid; + ZERO_STRUCT(r.in.req.req1.sync_req_info1.byte_array); + r.in.req.req1.sync_req_info1.nc_dn = priv->domain_obj_dn?priv->domain_obj_dn:""; + r.in.req.req1.dest_dsa_dns_name = talloc_asprintf(mem_ctx, "__some_dest_dsa_guid_string._msdn.%s", + priv->domain_dns_name); + break; + } + + status = dcerpc_drsuapi_DsReplicaUpdateRefs(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_DsReplicaUpdateRefs failed - %s\n", errstr); + ret = False; + } else if (!W_ERROR_IS_OK(r.out.result)) { + printf("DsReplicaUpdateRefs 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) { @@ -877,6 +935,8 @@ BOOL torture_rpc_drsuapi(void) ret &= test_DsReplicaSync(p, mem_ctx, &priv); + ret &= test_DsReplicaUpdateRefs(p, mem_ctx, &priv); + ret &= test_DsUnbind(p, mem_ctx, &priv); talloc_free(mem_ctx); |