diff options
-rw-r--r-- | source3/rpc_parse/parse_epmapper.c | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/source3/rpc_parse/parse_epmapper.c b/source3/rpc_parse/parse_epmapper.c new file mode 100644 index 0000000000..9e21da04dd --- /dev/null +++ b/source3/rpc_parse/parse_epmapper.c @@ -0,0 +1,406 @@ +/* + Unix SMB/CIFS implementation. + Samba end point mapper functions + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + + 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" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_PARSE + +/******************************************************************* + Reads or writes a handle. +********************************************************************/ +BOOL epm_io_handle(const char *desc, EPM_HANDLE *handle, prs_struct *ps, + int depth) +{ + + if (!prs_uint8s(False, "data", ps, depth, handle->data, + sizeof(handle->data))) + return False; + + return True; +} + +/******************************************************************* + inits an EPM_FLOOR structure. +********************************************************************/ +NTSTATUS init_epm_floor(EPM_FLOOR *floor, uint8 protocol) +{ + /* handle lhs */ + floor->lhs.protocol = protocol; + floor->lhs.length = sizeof(floor->lhs.protocol); + + switch(floor->lhs.protocol) { + case EPM_FLOOR_UUID: + floor->lhs.length += sizeof(floor->lhs.uuid.uuid); + floor->lhs.length += sizeof(floor->lhs.uuid.version); + break; + default: + break; + } + + /* handle rhs */ + switch(floor->lhs.protocol) { + case EPM_FLOOR_RPC: + case EPM_FLOOR_UUID: + floor->rhs.length = sizeof(floor->rhs.unknown); + break; + case EPM_FLOOR_TCP: + floor->rhs.length = sizeof(floor->rhs.tcp.port); + break; + case EPM_FLOOR_IP: + floor->rhs.length = sizeof(floor->rhs.ip.addr); + break; + default: + break; + } + + return NT_STATUS_OK; +} + +/******************************************************************* + inits an EPM_FLOOR structure with a UUID +********************************************************************/ +NTSTATUS init_epm_floor_uuid(EPM_FLOOR *floor, + const RPC_UUID *uuid, uint16 version) +{ + memcpy(&floor->lhs.uuid.uuid, uuid, sizeof(*uuid)); + floor->lhs.uuid.version = version; + floor->rhs.unknown = 0; + return init_epm_floor(floor, EPM_FLOOR_UUID); +} + +/******************************************************************* + inits an EPM_FLOOR structure for RPC +********************************************************************/ +NTSTATUS init_epm_floor_rpc(EPM_FLOOR *floor) +{ + floor->rhs.unknown = 0; + return init_epm_floor(floor, EPM_FLOOR_RPC); +} + +/******************************************************************* + inits an EPM_FLOOR structure for TCP +********************************************************************/ +NTSTATUS init_epm_floor_tcp(EPM_FLOOR *floor, uint16 port) +{ + floor->rhs.tcp.port = htons(port); + return init_epm_floor(floor, EPM_FLOOR_TCP); +} + +/******************************************************************* + inits an EPM_FLOOR structure for IP +********************************************************************/ +NTSTATUS init_epm_floor_ip(EPM_FLOOR *floor, uint8 addr[4]) +{ + memcpy(&floor->rhs.ip.addr, addr, sizeof(addr)); + return init_epm_floor(floor, EPM_FLOOR_IP); +} + +/******************************************************************* + reads and writes EPM_FLOOR. +********************************************************************/ +BOOL epm_io_floor(const char *desc, EPM_FLOOR *floor, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "epm_io_floor"); + depth++; + + if (!prs_uint16("lhs_length", ps, depth, &floor->lhs.length)) + return False; + if (!prs_uint8("protocol", ps, depth, &floor->lhs.protocol)) + return False; + + switch (floor->lhs.protocol) { + case EPM_FLOOR_UUID: + if (!smb_io_rpc_uuid("uuid", &floor->lhs.uuid.uuid, ps, depth)) + return False; + if (!prs_uint16("version", ps, depth, + &floor->lhs.uuid.version)) + return False; + break; + } + + if (!prs_uint16("rhs_length", ps, depth, &floor->rhs.length)) + return False; + + switch (floor->lhs.protocol) { + case EPM_FLOOR_UUID: + case EPM_FLOOR_RPC: + if (!prs_uint16("unknown", ps, depth, &floor->rhs.unknown)) + return False; + break; + case EPM_FLOOR_TCP: + if (!prs_uint16("tcp_port", ps, depth, &floor->rhs.tcp.port)) + return False; + break; + case EPM_FLOOR_IP: + if (!prs_uint8s(False, "ip_addr", ps, depth, + floor->rhs.ip.addr, + sizeof(floor->rhs.ip.addr))) + return False; + break; + default: + break; + } + + return True; +} + +/******************************************************************* + Inits a EPM_TOWER structure. +********************************************************************/ +NTSTATUS init_epm_tower(TALLOC_CTX *ctx, EPM_TOWER *tower, + const EPM_FLOOR *floors, int num_floors) +{ + static uint32 internal_referent_id = 0; + int size = 0; + int i; + + DEBUG(5, ("init_epm_tower\n")); + + for (i = 0; i < num_floors; i++) { + size += (sizeof(uint32) * 2); + size += floors[i].lhs.length; + size += floors[i].rhs.length; + } + size += sizeof(uint8); /* this could be aligning... */ + + tower->referent_id = ++internal_referent_id; + tower->max_length = tower->length = size; + tower->num_floors = num_floors; + tower->floors = talloc(ctx, sizeof(EPM_FLOOR) * num_floors); + if (!tower->floors) { + return NT_STATUS_NO_MEMORY; + } + memcpy(tower->floors, floors, sizeof(EPM_FLOOR) * num_floors); + tower->unknown = 0x7e; + + return NT_STATUS_OK; +} + +/******************************************************************* + Reads or writes an EPM_TOWER structure. +********************************************************************/ +BOOL epm_io_tower(const char *desc, EPM_TOWER *tower, + prs_struct *ps, int depth) +{ + int i; + + prs_debug(ps, depth, desc, "epm_io_tower"); + depth++; + + if (!prs_uint32("referent_id", ps, depth, &tower->referent_id)) + return False; + if (!prs_uint32("max_length", ps, depth, &tower->max_length)) + return False; + if (!prs_uint32("length", ps, depth, &tower->length)) + return False; + if (!prs_uint16("num_floors", ps, depth, &tower->num_floors)) + return False; + + if (UNMARSHALLING(ps)) { + tower->floors = talloc(ps->mem_ctx, + sizeof(EPM_FLOOR) * tower->num_floors); + if (!tower->floors) + return False; + } + + for (i = 0; i < tower->num_floors; i++) { + if (!epm_io_floor("floor", tower->floors + i, ps, depth)) + return False; + } + + if (!prs_uint8("unknown", ps, depth, &tower->unknown)) + return False; + + return True; +} + +/******************************************************************* + Initialize an EPM_TOWER_ARRAY structure +********************************************************************/ +NTSTATUS init_epm_tower_array(TALLOC_CTX *ctx, EPM_TOWER_ARRAY *array, + const EPM_TOWER *towers, int num_towers) +{ + array->max_count = num_towers; + array->offset = 0; + array->count = num_towers; + array->towers = talloc(ctx, sizeof(EPM_TOWER) * num_towers); + if (!array->towers) { + return NT_STATUS_NO_MEMORY; + } + memcpy(array->towers, towers, sizeof(EPM_TOWER) * num_towers); + + return NT_STATUS_OK; +} + +/******************************************************************* + Reads or writes an EPM_TOWER_ARRAY structure. +********************************************************************/ +BOOL epm_io_tower_array(const char *desc, EPM_TOWER_ARRAY *array, + prs_struct *ps, int depth) +{ + int i; + + prs_debug(ps, depth, desc, "epm_io_tower_array"); + depth++; + + if (!prs_uint32("max_count", ps, depth, &array->max_count)) + return False; + if (!prs_uint32("offset", ps, depth, &array->offset)) + return False; + if (!prs_uint32("count", ps, depth, &array->count)) + return False; + + if (!prs_set_offset(ps, prs_offset(ps) + array->offset)) + return False; + + if (UNMARSHALLING(ps)) { + array->towers = talloc(ps->mem_ctx, + sizeof(EPM_TOWER) * array->count); + if (!array->towers) { + return False; + } + } + + for (i = 0; i < array->count; i++) { + if (!epm_io_tower("tower", array->towers + 1, ps, depth)) + return False; + } + + return True; +} + +/******************************************************************* + Initialize EPM_R_MAP structure +******************************************************************/ +NTSTATUS init_epm_r_map(TALLOC_CTX *ctx, EPM_R_MAP *r_map, + const EPM_HANDLE *handle, const EPM_TOWER_ARRAY *array, + int num_elements, uint32 status) +{ + memcpy(&r_map->handle, handle, sizeof(*handle)); + r_map->num_results = num_elements; + r_map->results = talloc(ctx, sizeof(EPM_TOWER_ARRAY) * num_elements); + if (!r_map->results) { + return NT_STATUS_NO_MEMORY; + } + memcpy(r_map->results, array, sizeof(EPM_TOWER_ARRAY) * num_elements); + r_map->status = status; + return NT_STATUS_OK; +} + +/************************************************************************* + Inits a EPM_Q_MAP structure. +************************************************************************** +* We attempt to hide the ugliness of the wire format by taking a EPM_TOWER +* array with a defined size +**************************************************************************/ +NTSTATUS init_epm_q_map(TALLOC_CTX *ctx, EPM_Q_MAP *q_map, + const EPM_TOWER *towers, int num_towers) +{ + static uint32 handle = 1; + + ZERO_STRUCTP(q_map); + + DEBUG(5, ("init_epm_q_map\n")); + q_map->handle.data[0] = (handle >> 0) & 0xFF; + q_map->handle.data[1] = (handle >> 8) & 0xFF; + q_map->handle.data[2] = (handle >> 16) & 0xFF; + q_map->handle.data[3] = (handle >> 24) & 0xFF; + + q_map->tower = talloc(ctx, sizeof(EPM_TOWER) * (num_towers + 1)); + if (!q_map->tower) { + return NT_STATUS_NO_MEMORY; + } + + memcpy(q_map->tower, towers, sizeof(EPM_TOWER) * num_towers); + + ZERO_STRUCT(q_map->tower[num_towers]); + + /* For now let's not take more than 4 towers per result */ + q_map->max_towers = num_towers * 4; + + handle++; + + return NT_STATUS_OK; +} + +/***************************************************************** + epm_io_q_map - read or write EPM_Q_MAP structure +******************************************************************/ +BOOL epm_io_q_map(char *desc, EPM_Q_MAP *io_map, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "epm_io_q_map"); + depth++; + + if (!epm_io_handle("handle", &io_map->handle, ps, depth)) + return False; + + /* HACK: We need a more elegant way of doing this */ + if (UNMARSHALLING(ps)) { + io_map->tower = talloc(ps->mem_ctx, sizeof(EPM_TOWER)); + if (!io_map->tower) + return False; + } + if (!epm_io_tower("tower", io_map->tower, ps, depth)) + return False; + if (!epm_io_handle("term_handle", &io_map->term_handle, ps, depth)) + return False; + + if (!prs_uint32("max_towers", ps, 0, &io_map->max_towers)) + return False; + + return True; +} + +/******************************************************************* + epm_io_r_map - Read/Write EPM_R_MAP structure +******************************************************************/ +BOOL epm_io_r_map(char *desc, EPM_R_MAP *io_map, + prs_struct *ps, int depth) +{ + int i; + + prs_debug(ps, depth, desc, "epm_io_r_map"); + depth++; + + if (!epm_io_handle("handle", &io_map->handle, ps, depth)) + return False; + if (!prs_uint32("num_results", ps, depth, &io_map->num_results)) + return False; + + if (UNMARSHALLING(ps)) { + io_map->results = talloc(ps->mem_ctx, + sizeof(EPM_TOWER_ARRAY) * + io_map->num_results); + if (!io_map->results) + return False; + } + for (i = 0; i < io_map->num_results; i++) { + if (!epm_io_tower_array("results", io_map->results + i, + ps, depth)) + return False; + } + + if (!prs_uint32("status", ps, depth, &io_map->status)) + return False; + + return True; +} |