#include <commonp.h>
#include <com.h>
#include <dce/ep.h>
#include <rpcdp.h>
#include <rpcdepdb.h>
#ifdef RPC_LLB
#include <dce/glb.h>
#include <rpcdlbdb.h>
#endif
#include <twrp.h>
GLOBAL ept_v3_0_epv_t ept_v3_0_mgr_epv =
{
ept_insert,
ept_delete,
ept_lookup,
ept_map,
ept_lookup_handle_free,
ept_inq_object,
ept_mgmt_delete
};
#ifndef REMOTE_ENDPOINT_ACCESS
INTERNAL int is_unpriv_handle( handle_t h, error_status_t *st )
{
error_status_t status,status1;
rpc_binding_vector_p_t bv;
handle_t binding;
unsigned_char_p_t stb,our_netaddr,client_netaddr;
unsigned32 i;
static unsigned_char_p_t *local_netaddr = NULL;
static unsigned32 addr_count = 0;
unsigned32 prot_seq = 0;
rpc_transport_info_handle_t info;
unsigned32 uid = (unsigned32) -1;
unsigned32 gid = (unsigned32) -1;
rpc_binding_inq_prot_seq(h, &prot_seq, &status);
if (! STATUS_OK(&status))
{
*st = status;
return(1);
}
if (prot_seq == rpc_c_protseq_id_ncalrpc)
{
rpc_binding_inq_transport_info(h, &info, &status);
if (! STATUS_OK(&status))
{
*st = status;
return(1);
}
rpc_lrpc_transport_info_inq_peer_eid(info, &uid, &gid);
*st = rpc_s_ok;
return (uid != 0);
}
rpc_binding_server_from_client(h,&binding,&status);
if (! STATUS_OK(&status))
{
*st = status;
return(1);
}
rpc_binding_to_string_binding(binding,&stb,&status);
if (! STATUS_OK(&status))
{
rpc_binding_free(&binding,&status1);
*st = status;
return(1);
}
rpc_binding_free(&binding,&status1);
rpc_string_binding_parse(stb,NULL,NULL,&client_netaddr,NULL,NULL,&status);
if (! STATUS_OK(&status))
{
rpc_string_free(&stb,&status1);
*st = status;
return(1);
}
rpc_string_free(&stb,&status1);
if (addr_count == 0)
{
rpc_server_inq_bindings(&bv,&status);
if (! STATUS_OK(&status))
{
rpc_string_free(&client_netaddr,&status1);
*st = status;
return(1);
}
addr_count = bv->count;
local_netaddr = (unsigned_char_p_t *) malloc(
(size_t) (addr_count * sizeof(unsigned_char_p_t)));
if (local_netaddr == NULL)
{
rpc_string_free(&client_netaddr,&status1);
rpc_binding_vector_free(&bv,&status1);
*st = ept_s_no_memory;
return(1);
}
for ( i=0; i < bv->count; i++ )
{
rpc_binding_to_string_binding(bv->binding_h[i],&stb,&status);
if (! STATUS_OK(&status))
{
rpc_binding_vector_free(&bv,&status1);
rpc_string_free(&client_netaddr,&status1);
*st = status;
return(1);
}
rpc_string_binding_parse(stb,NULL,NULL,
&our_netaddr,NULL,NULL,&status);
if (! STATUS_OK(&status))
{
rpc_binding_vector_free(&bv,&status1);
rpc_string_free(&stb,&status1);
rpc_string_free(&client_netaddr,&status1);
*st = status;
return(1);
}
local_netaddr[i] = our_netaddr;
rpc_string_free(&stb,&status1);
}
rpc_binding_vector_free(&bv,&status1);
}
*st = rpc_s_ok;
for ( i=0; i < addr_count; i++ )
{
if(strcmp((char*) client_netaddr, (char*) local_netaddr[i]) == 0)
{
rpc_string_free(&client_netaddr,&status1);
return(0);
}
}
rpc_string_free(&client_netaddr,&status1);
return(1);
}
#endif
PRIVATE boolean ept__is_ncacn_np(
ept_entry_p_t entry)
{
unsigned16 floor_count, count;
byte_p_t tower = entry->tower->tower_octet_string;
if (entry->tower->tower_length < TWR_C_TOWER_FLR_COUNT_SIZE)
{
return false;
}
memcpy((char *)&floor_count, tower, TWR_C_TOWER_FLR_COUNT_SIZE);
RPC_RESOLVE_ENDIAN_INT16 (floor_count);
tower += TWR_C_TOWER_FLR_COUNT_SIZE;
for ( count = 0; count < floor_count; count++ )
{
unsigned16 id_size, addr_size;
unsigned8 id;
if (TWR_C_TOWER_FLR_LHS_COUNT_SIZE >
entry->tower->tower_length - (tower - entry->tower->tower_octet_string))
{
return false;
}
memcpy ((char *)&id_size, tower, TWR_C_TOWER_FLR_LHS_COUNT_SIZE);
RPC_RESOLVE_ENDIAN_INT16 (id_size);
if (id_size == TWR_C_TOWER_PROT_ID_SIZE)
{
if ((unsigned) (TWR_C_TOWER_FLR_LHS_COUNT_SIZE + TWR_C_TOWER_PROT_ID_SIZE) >
entry->tower->tower_length - (tower - entry->tower->tower_octet_string))
{
return false;
}
memcpy ((char *)&id, (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE),
TWR_C_TOWER_PROT_ID_SIZE);
if (id == TWR_C_FLR_PROT_ID_NP)
{
return true;
}
}
if ((unsigned) (TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size + TWR_C_TOWER_FLR_RHS_COUNT_SIZE) >
entry->tower->tower_length - (tower - entry->tower->tower_octet_string))
{
return false;
}
memcpy ((char *)&addr_size, (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE +
id_size), TWR_C_TOWER_FLR_RHS_COUNT_SIZE);
RPC_RESOLVE_ENDIAN_INT16 (addr_size);
if ((unsigned) ((TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size +
TWR_C_TOWER_FLR_RHS_COUNT_SIZE + addr_size)) >
(entry->tower->tower_length - (tower - entry->tower->tower_octet_string)))
{
return false;
}
tower += TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size +
TWR_C_TOWER_FLR_RHS_COUNT_SIZE + addr_size;
}
return false;
}
PRIVATE void ept_insert(
handle_t h,
unsigned32 num_ents,
ept_entry_t entries[],
boolean32 replace,
error_status_t *status)
{
epdb_handle_t epdb;
ept_entry_t *entp;
unsigned32 i;
error_status_t tmp_st;
epdb_handle_from_ohandle(h, &epdb, status);
if (! STATUS_OK(status))
return;
#ifndef REMOTE_ENDPOINT_ACCESS
if ( is_unpriv_handle(h,&tmp_st) )
{
assert(status != NULL);
*status = ept_s_cant_perform_op;
return;
}
#endif
for (i = 0, entp = &entries[0]; i < num_ents; i++, entp++)
{
if (ept__is_ncacn_np(entp))
{
continue;
}
epdb_insert(epdb, entp, replace, status);
if (! STATUS_OK(status))
{
if (dflag)
show_st("ept_insert Unable to update endpoint database", status);
ept_delete(h, i, entries, &tmp_st);
return;
}
}
}
PRIVATE void ept_delete(
handle_t h,
unsigned32 num_ents,
ept_entry_t entries[],
error_status_t *status)
{
epdb_handle_t epdb;
ept_entry_t *entp;
unsigned32 i;
error_status_t tmp_st;
epdb_handle_from_ohandle(h, &epdb, status);
if (! STATUS_OK(status))
return;
#ifndef REMOTE_ENDPOINT_ACCESS
if ( is_unpriv_handle(h,&tmp_st) )
{
assert(status != NULL);
*status = ept_s_cant_perform_op;
return;
}
#endif
for (i = 0, entp = &entries[0]; i < num_ents; i++, entp++)
{
epdb_delete(epdb, entp, status);
if (! STATUS_OK(status))
{
if (dflag)
show_st("ept_delete Unable to update endpoint database", status);
return;
}
}
}
PRIVATE void ept_lookup(
handle_t h,
unsigned32 inquiry_type,
uuid_p_t object,
rpc_if_id_p_t interface,
unsigned32 vers_option,
ept_lookup_handle_t *entry_handle,
unsigned32 max_ents,
unsigned32 *num_ents,
ept_entry_t entries[],
error_status_t *status)
{
epdb_handle_t epdb;
*num_ents = 0;
epdb_handle_from_ohandle(h, &epdb, status);
if (! STATUS_OK(status))
return;
epdb_lookup(epdb, inquiry_type, object, interface, vers_option, entry_handle,
max_ents, num_ents, entries, status);
if (dflag)
printf("ept_lookup entry_handle %p *entry_handle %p *num_ents %lu\n",
entry_handle, *entry_handle, (unsigned long) *num_ents);
}
PRIVATE void ept_map(
handle_t h,
uuid_p_t object,
twr_p_t map_tower,
ept_lookup_handle_t *entry_handle,
unsigned32 max_towers,
unsigned32 *num_towers,
twr_t *towers[],
error_status_t *status)
{
epdb_handle_t epdb;
*num_towers = 0;
epdb_handle_from_ohandle(h, &epdb, status);
if (! STATUS_OK(status))
return;
epdb_map(epdb, object, map_tower, entry_handle,
max_towers, num_towers, towers, status);
#ifdef RPC_LLB
if ((*status == ept_s_not_registered) ||
(*status == ept_s_invalid_context) ||
((*status == rpc_s_ok) &&
((*num_towers < max_towers) ||
((entry_handle != NULL) && (*entry_handle == NULL)) )) )
{
h = lbdb_inq_handle();
lbdb_map(h, object, map_tower, entry_handle,
max_towers, num_towers, towers, status);
}
#endif
if (dflag)
printf("ept_map entry_handle %p *entry_handle %p *num_towers %lu\n",
entry_handle, *entry_handle, (unsigned long) *num_towers);
}
PRIVATE void ept_lookup_handle_free(
handle_t h ATTRIBUTE_UNUSED,
ept_lookup_handle_t *entry_handle,
error_status_t *status)
{
epdb_handle_t epdb;
epdb = epdb_inq_handle();
epdb_delete_lookup_handle(epdb, entry_handle);
SET_STATUS_OK(status);
}
PRIVATE void ept_inq_object(
handle_t h,
idl_uuid_t *object,
error_status_t *status)
{
epdb_handle_t epdb;
epdb_handle_from_ohandle(h, &epdb, status);
if (! STATUS_OK(status))
return;
epdb_inq_object(epdb, object, status);
}
PRIVATE void ept_mgmt_delete(
handle_t h,
boolean32 object_speced,
uuid_p_t object,
twr_p_t tower,
error_status_t *status)
{
epdb_handle_t epdb;
error_status_t tmp_st;
epdb_handle_from_ohandle(h, &epdb, status);
if (! STATUS_OK(status))
return;
#ifndef REMOTE_ENDPOINT_ACCESS
if ( is_unpriv_handle(h,&tmp_st) )
{
assert(status != NULL);
*status = ept_s_cant_perform_op;
return;
}
#endif
epdb_mgmt_delete(epdb, object_speced, object, tower, status);
}
PRIVATE void ept_lookup_handle_t_rundown(
ept_lookup_handle_t entry_handle)
{
epdb_handle_t epdb;
epdb = epdb_inq_handle();
epdb_delete_lookup_handle(epdb, &entry_handle);
}