diff options
-rw-r--r-- | source4/librpc/idl/drsuapi.idl | 286 | ||||
-rw-r--r-- | source4/rpc_server/drsuapi/dcesrv_drsuapi.c | 6 | ||||
-rw-r--r-- | source4/torture/rpc/drsuapi.c | 138 |
3 files changed, 421 insertions, 9 deletions
diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl index b4784da95b..15d1ca8efc 100644 --- a/source4/librpc/idl/drsuapi.idl +++ b/source4/librpc/idl/drsuapi.idl @@ -17,8 +17,12 @@ 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 */ + /* this is a magic guid you need to pass to DsBind to make drsuapi_DsWriteAccountSpn() work + * + * maybe the bind_guid could also be the invocation_id see drsuapi_DsReplicaConnection04 + */ const string DRSUAPI_DS_BIND_GUID = "e24d201a-4fd6-11d1-a3da-0000f875ae0d"; + /* this are the bind info blobs returned (seemed to be const): w2k3 7ffbff1f81a6ff5d80139441a372e9b779d70268f801000000000000 @@ -310,8 +314,284 @@ interface drsuapi WERROR DRSUAPI_EXECUTE_KCC(); /*****************/ - /* Function 0x13 */ - WERROR DRSUAPI_GET_REPL_INFO(); + /* Function 0x13 */ + typedef enum { + DRSUAPI_DS_REPLICA_GET_INFO = 1, + DRSUAPI_DS_REPLICA_GET_INFO2 = 2 + } drsuapi_DsReplicaGetInfoLevel; + + typedef enum { + DRSUAPI_DS_REPLICA_INFO_NEIGHBORS = 0, + DRSUAPI_DS_REPLICA_INFO_CURSORS = 1, + DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA = 2, + DRSUAPI_DS_REPLICA_INFO_KCC_DSA_CONNECT_FAILURES = 3, + DRSUAPI_DS_REPLICA_INFO_KCC_DSA_LINK_FAILURES = 4, + DRSUAPI_DS_REPLICA_INFO_PENDING_OPS = 5, + DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA = 6, + DRSUAPI_DS_REPLICA_INFO_CURSORS2 = 7, + DRSUAPI_DS_REPLICA_INFO_CURSORS3 = 8, + DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA2 = 9, + DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA2 = 10, + DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02 = -2, + DRSUAPI_DS_REPLICA_INFO_CONNECTIONS04 = -4, + DRSUAPI_DS_REPLICA_INFO_CURSURS05 = -5, + DRSUAPI_DS_REPLICA_INFO_06 = -6 + } drsuapi_DsReplicaInfoType; + + typedef struct { + int32 info_type; + unistr *object_dn; + GUID guid1; + } drsuapi_DsReplicaGetInfoRequest1; + + typedef struct { + int32 info_type; + unistr *object_dn; + GUID guid1; + uint32 unknown1; + unistr *string1; + unistr *string2; + uint32 unknown2; + } drsuapi_DsReplicaGetInfoRequest2; + + typedef union { + [case(1)] drsuapi_DsReplicaGetInfoRequest1 req1; + [case(2)] drsuapi_DsReplicaGetInfoRequest2 req2; + } drsuapi_DsReplicaGetInfoRequest; + + typedef struct { + unistr *naming_context_dn; + unistr *source_dsa_obj_dn; + unistr *source_dsa_address; + unistr *transport_obj_dn; + uint32 replica_flags; + uint32 reserved; + GUID naming_context_obj_guid; + GUID source_dsa_obj_guid; + GUID source_dsa_invocation_id; + GUID transport_obj_guid; + uint64 tmp_highest_usn; + uint64 highest_usn; + NTTIME last_success; + NTTIME last_attempt; + WERROR result_last_attempt; + uint32 consecutive_sync_failures; + } drsuapi_DsReplicaNeighbour; + + typedef struct { + uint32 count; + uint32 reserved; + [size_is(count)] drsuapi_DsReplicaNeighbour array[]; + } drsuapi_DsReplicaNeighbourCtr; + + typedef struct { + GUID source_dsa_invocation_id; + uint64 highest_usn; + } drsuapi_DsReplicaCoursor; + + typedef struct { + uint32 count; + uint32 reserved; + [size_is(count)] drsuapi_DsReplicaCoursor array[]; + } drsuapi_DsReplicaCoursorCtr; + + typedef struct { + unistr *attribute_name; + uint32 version; + NTTIME originating_last_changed; + GUID originating_dsa_invocation_id; + uint64 originating_usn; + uint64 local_usn; + } drsuapi_DsReplicaObjMetaData; + + typedef struct { + uint32 count; + uint32 reserved; + [size_is(count)] drsuapi_DsReplicaObjMetaData array[]; + } drsuapi_DsReplicaObjMetaDataCtr; + + typedef struct { + unistr *dsa_obj_dn; + GUID dsa_obj_guid; + NTTIME first_failure; + uint32 num_failures; + WERROR last_result; + } drsuapi_DsReplicaKccDsaFailure; + + typedef struct { + uint32 count; + uint32 reserved; + [size_is(count)] drsuapi_DsReplicaKccDsaFailure array[]; + } drsuapi_DsReplicaKccDsaFailuresCtr; + + typedef struct { + NTTIME operation_start; + uint32 serial_num; /* unique till reboot */ + uint32 priority; + uint16 operation_type; + uint32 options_flags; + unistr *nc_dn; + unistr *remote_dsa_obj_dn; + unistr *remote_dsa_address; + GUID nc_obj_guid; + GUID remote_dsa_obj_guid; + } drsuapi_DsReplicaOp; + + typedef struct { + NTTIME time; + uint32 count; + [size_is(count)] drsuapi_DsReplicaOp array[]; + } drsuapi_DsReplicaOpCtr; + + typedef struct { + unistr *attribute_name; + unistr *object_dn; + uint32 value_length; + [size_is(value_length)] uint8 *value; + NTTIME deleted; + NTTIME created; + uint32 version; + NTTIME originating_last_changed; + GUID originating_dsa_invocation_id; + uint64 originating_usn; + uint64 local_usn; + } drsuapi_DsReplicaAttrValMetaData; + + typedef struct { + uint32 count; + int32 enumeration_context; + [size_is(count)] drsuapi_DsReplicaAttrValMetaData array[]; + } drsuapi_DsReplicaAttrValMetaDataCtr; + + typedef struct { + GUID source_dsa_invocation_id; + uint64 highest_usn; + NTTIME last_sync_success; + } drsuapi_DsReplicaCoursor2; + + typedef struct { + uint32 count; + int32 enumeration_context; + [size_is(count)] drsuapi_DsReplicaCoursor2 array[]; + } drsuapi_DsReplicaCoursor2Ctr; + + typedef struct { + GUID source_dsa_invocation_id; + uint64 highest_usn; + NTTIME last_sync_success; + unistr *source_dsa_obj_dn; + } drsuapi_DsReplicaCoursor3; + + typedef struct { + uint32 count; + int32 enumeration_context; + [size_is(count)] drsuapi_DsReplicaCoursor3 array[]; + } drsuapi_DsReplicaCoursor3Ctr; + + typedef struct { + uint32 attribute_name;/*unistr *attribute_name;*/ + uint32 version; + NTTIME originating_last_changed; + GUID originating_dsa_invocation_id; + uint64 originating_usn; + uint64 local_usn; + uint32 originating_dsa_obj_dn;/*unistr *originating_dsa_obj_dn;*/ + uint32 u1; /* in the last element this is not present; some stupid alignment? */ + } drsuapi_DsReplicaObjMetaData2; + + typedef struct { + uint32 count; + int32 enumeration_context; + [size_is(count)] drsuapi_DsReplicaObjMetaData2 array[]; + } drsuapi_DsReplicaObjMetaData2Ctr; + + typedef struct { + unistr *attribute_name; + unistr *object_dn; + uint32 value_length; + [size_is(value_length)] uint8 *value; + NTTIME deleted; + NTTIME created; + uint32 version; + NTTIME originating_last_changed; + GUID originating_dsa_invocation_id; + uint64 originating_usn; + uint64 local_usn; + unistr *originating_dsa_obj_dn; + } drsuapi_DsReplicaAttrValMetaData2; + + typedef struct { + uint32 count; + int32 enumeration_context; + [size_is(count)] drsuapi_DsReplicaAttrValMetaData2 array[]; + } drsuapi_DsReplicaAttrValMetaData2Ctr; + + typedef struct { + uint64 u1; /* session number? */ + uint32 u2; + uint32 u3; + GUID bind_guid; + NTTIME_1sec bind_time; + uint32 u4; /* flags? */ + uint32 u5; + } drsuapi_DsReplicaConnection04; + + typedef struct { + [range(0,10000)] uint32 count; + uint32 reserved; + [size_is(count)] drsuapi_DsReplicaConnection04 array[]; + } drsuapi_DsReplicaConnection04Ctr; + + typedef struct { + uint32 u1; + uint32 u2; + [range(0,0x100000)] uint32 count; + uint32 u3; + [size_is(count)] drsuapi_DsReplicaCoursor array[]; + } drsuapi_DsReplicaCoursor05Ctr; + + typedef struct { + unistr *str1; + uint32 u1; + uint32 u2; + uint32 u3; + uint32 u4; + uint32 u5; + uint64 u6; + uint32 u7; + } drsuapi_DsReplica06; + + typedef struct { + [range(0,256)] uint32 count; + uint32 reserved; + [size_is(count)] drsuapi_DsReplica06 array[]; + } drsuapi_DsReplica06Ctr; + + typedef union { + [case(0)] drsuapi_DsReplicaNeighbourCtr *neighbours; + [case(1)] drsuapi_DsReplicaCoursorCtr *coursors; + [case(2)] drsuapi_DsReplicaObjMetaDataCtr *objmetadata; + [case(3)] drsuapi_DsReplicaKccDsaFailuresCtr *connectfailures; + [case(4)] drsuapi_DsReplicaKccDsaFailuresCtr *linkfailures; + [case(5)] drsuapi_DsReplicaOpCtr *pendingops; + [case(6)] drsuapi_DsReplicaAttrValMetaDataCtr *attrvalmetadata; + [case(7)] drsuapi_DsReplicaCoursor2Ctr *coursors2; + [case(8)] drsuapi_DsReplicaCoursor3Ctr *coursors3; + [case(9)] drsuapi_DsReplicaObjMetaData2Ctr *objmetadata2; + [case(10)] drsuapi_DsReplicaAttrValMetaData2Ctr *attrvalmetadata2; + [case(-2)] drsuapi_DsReplicaNeighbourCtr *neighbours02; + [case(-4)] drsuapi_DsReplicaConnection04Ctr *connections04; + [case(-5)] drsuapi_DsReplicaCoursor05Ctr *coursors05; + [case(-6)] drsuapi_DsReplica06Ctr *i06; + } drsuapi_DsReplicaInfo; + + WERROR drsuapi_DsReplicaGetInfo( + [in,ref] policy_handle *bind_handle, + [in] int32 level, + [in,switch_is(level)] drsuapi_DsReplicaGetInfoRequest req, + [out] int32 info_type, + [out,switch_is(info_type)] drsuapi_DsReplicaInfo info + ); /*****************/ /* Function 0x14 */ diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c index f033c07ff7..a8c48d6805 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c @@ -273,10 +273,10 @@ static WERROR DRSUAPI_EXECUTE_KCC(struct dcesrv_call_state *dce_call, TALLOC_CTX /* - DRSUAPI_GET_REPL_INFO + drsuapi_DsReplicaGetInfo */ -static WERROR DRSUAPI_GET_REPL_INFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct DRSUAPI_GET_REPL_INFO *r) +static WERROR drsuapi_DsReplicaGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct drsuapi_DsReplicaGetInfo *r) { DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); } diff --git a/source4/torture/rpc/drsuapi.c b/source4/torture/rpc/drsuapi.c index b6b1ddf6dc..e5b7e2ca0c 100644 --- a/source4/torture/rpc/drsuapi.c +++ b/source4/torture/rpc/drsuapi.c @@ -27,7 +27,9 @@ struct DsPrivate { struct policy_handle bind_handle; struct GUID bind_guid; + const char *domain_obj_dn; const char *domain_guid_str; + struct GUID domain_guid; struct drsuapi_DsGetDCInfo2 dcinfo; }; @@ -71,7 +73,6 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, BOOL ret = True; const char *dns_domain; const char *nt4_domain; - const char *FQDN_1779_domain; const char *FQDN_1779_name; ZERO_STRUCT(r); @@ -133,6 +134,8 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, } priv->domain_guid_str = r.out.ctr.ctr1->array[0].result_name; + GUID_from_string(priv->domain_guid_str, &priv->domain_guid); + r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID; r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT; @@ -182,7 +185,7 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return ret; } - FQDN_1779_domain = r.out.ctr.ctr1->array[0].result_name; + priv->domain_obj_dn = 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; @@ -421,7 +424,7 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 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", + printf("testing DsCrackNames with BIND GUID '%s' desired format:%d\n", names[0].str, r.in.req.req1.format_desired); status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r); @@ -627,6 +630,131 @@ static BOOL test_DsWriteAccountSpn(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return ret; } +static BOOL test_DsReplicaGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, + struct DsPrivate *priv) +{ + NTSTATUS status; + struct drsuapi_DsReplicaGetInfo r; + BOOL ret = True; + int i; + struct { + int32 level; + int32 infotype; + const char *obj_dn; + } array[] = { + { + DRSUAPI_DS_REPLICA_GET_INFO, + DRSUAPI_DS_REPLICA_INFO_NEIGHBORS, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO, + DRSUAPI_DS_REPLICA_INFO_CURSORS, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO, + DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO, + DRSUAPI_DS_REPLICA_INFO_KCC_DSA_CONNECT_FAILURES, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO, + DRSUAPI_DS_REPLICA_INFO_KCC_DSA_LINK_FAILURES, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO, + DRSUAPI_DS_REPLICA_INFO_PENDING_OPS, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO2, + DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO2, + DRSUAPI_DS_REPLICA_INFO_CURSORS2, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO2, + DRSUAPI_DS_REPLICA_INFO_CURSORS3, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO2, + DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA2, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO2, + DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA2, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO2, + DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO2, + DRSUAPI_DS_REPLICA_INFO_CONNECTIONS04, + "__IGNORED__" + },{ + DRSUAPI_DS_REPLICA_GET_INFO2, + DRSUAPI_DS_REPLICA_INFO_CURSURS05, + NULL + },{ + DRSUAPI_DS_REPLICA_GET_INFO2, + DRSUAPI_DS_REPLICA_INFO_06, + NULL + } + }; + + r.in.bind_handle = &priv->bind_handle; + + for (i=0; i < ARRAY_SIZE(array); i++) { + const char *object_dn; + + printf("testing DsReplicaGetInfo level %d infotype %d\n", + array[i].level, array[i].infotype); + + object_dn = (array[i].obj_dn ? array[i].obj_dn : priv->domain_obj_dn); + + r.in.level = array[i].level; + switch(r.in.level) { + case DRSUAPI_DS_REPLICA_GET_INFO: + r.in.req.req1.info_type = array[i].infotype; + r.in.req.req1.object_dn = object_dn; + ZERO_STRUCT(r.in.req.req1.guid1); + break; + case DRSUAPI_DS_REPLICA_GET_INFO2: + r.in.req.req2.info_type = array[i].infotype; + r.in.req.req2.object_dn = object_dn; + ZERO_STRUCT(r.in.req.req1.guid1); + r.in.req.req2.unknown1 = 0; + r.in.req.req2.string1 = NULL; + r.in.req.req2.string2 = NULL; + r.in.req.req2.unknown2 = 0; + break; + } + + status = dcerpc_drsuapi_DsReplicaGetInfo(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); + } + if (p->last_fault_code != DCERPC_FAULT_INVALID_TAG) { + printf("dcerpc_drsuapi_DsReplicaGetInfo failed - %s\n", errstr); + ret = False; + } else { + printf("DsReplicaGetInfo level %d and/or infotype %d not supported by server\n", + array[i].level, array[i].infotype); + } + } else if (!W_ERROR_IS_OK(r.out.result)) { + printf("DsReplicaGetInfo 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) { @@ -693,6 +821,10 @@ BOOL torture_rpc_drsuapi(void) ret = False; } + if (!test_DsReplicaGetInfo(p, mem_ctx, &priv)) { + ret = False; + } + if (!test_DsUnbind(p, mem_ctx, &priv)) { ret = False; } |