return blob;
}
-static bool dcerpc_floor_pack_rhs_if_version_data(
- TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax,
- DATA_BLOB *pblob)
+static DATA_BLOB dcerpc_floor_pack_rhs_data(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax)
{
DATA_BLOB blob;
- struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx);
enum ndr_err_code ndr_err;
+ struct ndr_push *ndr;
+ ndr = ndr_push_init_ctx(mem_ctx);
if (ndr == NULL) {
- return false;
+ return data_blob_null;
}
ndr->flags |= LIBNDR_FLAG_NOALIGN;
ndr_err = ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version >> 16);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return false;
+ return data_blob_null;
}
blob = ndr_push_blob(ndr);
talloc_steal(mem_ctx, blob.data);
talloc_free(ndr);
- *pblob = blob;
- return true;
+ return blob;
}
char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
tower->num_floors = 2 + num_protocols;
tower->floors = talloc_array(mem_ctx, struct epm_floor, tower->num_floors);
-
+ if (
/* Floor 0 */
tower->floors[0].lhs.protocol = EPM_PROTOCOL_UUID;
return NT_STATUS_OK;
}
+
+_PUBLIC_ NTSTATUS dcerpc_build_epm_tower_floors(TALLOC_CTX *mem_ctx,
+ const struct dcerpc_binding *binding,
+ const struct ndr_syntax_id *abstract,
+ const struct ndr_syntax_id *transfer,
+ uint16_t *_num_floors,
+ struct epm_floor *_floors);
+{
+ uint16_t *num_floors;
+ struct epm_floor *floors;
+ const enum epm_protocol *protseq = NULL;
+ int num_protocols = -1, i;
+ NTSTATUS status;
+
+ /* Find transport */
+ for (i=0;i<ARRAY_SIZE(transports);i++) {
+ if (transports[i].transport == binding->transport) {
+ protseq = transports[i].protseq;
+ num_protocols = transports[i].num_protocols;
+ break;
+ }
+ }
+
+ if (num_protocols == -1) {
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ }
+
+ num_floors = 2 + num_protocols;
+ floors = talloc_array(mem_ctx, struct epm_floor, num_floors);
+ if (floors == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Floor 0 */
+ floors[0].lhs.protocol = EPM_PROTOCOL_UUID;
+
+ floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors, abstract);
+
+ ok = dcerpc_floor_pack_rhs_if_version_data(ower->floors, abstract,
+ &tower->floors[0].rhs.uuid.unknown);
+ if (!ok) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Floor 1 */
+ tower->floors[1].lhs.protocol = EPM_PROTOCOL_UUID;
+
+ tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors,
+ &ndr_transfer_syntax_ndr);
+
+ tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(tower->floors, 2);
+
+ /* Floor 2 to num_protocols */
+ for (i = 0; i < num_protocols; i++) {
+ tower->floors[2 + i].lhs.protocol = protseq[i];
+ tower->floors[2 + i].lhs.lhs_data = data_blob_talloc(tower->floors, NULL, 0);
+ ZERO_STRUCT(tower->floors[2 + i].rhs);
+ dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[2 + i], "");
+ }
+
+ /* The 4th floor contains the endpoint */
+ if (num_protocols >= 2 && binding->endpoint) {
+ status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[3], binding->endpoint);
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+ }
+
+ /* The 5th contains the network address */
+ if (num_protocols >= 3 && binding->host) {
+ if (is_ipaddress(binding->host) ||
+ (binding->host[0] == '\\' && binding->host[1] == '\\')) {
+ status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[4],
+ binding->host);
+ } else {
+ /* note that we don't attempt to resolve the
+ name here - when we get a hostname here we
+ are in the client code, and want to put in
+ a wildcard all-zeros IP for the server to
+ fill in */
+ status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[4],
+ "0.0.0.0");
+ }
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+ }
+
+ return NT_STATUS_OK;
+}