mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
s3-epmapper: Added epm_Insert function.
This commit is contained in:
parent
84995397a7
commit
c31ee9a152
@ -25,22 +25,248 @@
|
||||
|
||||
typedef uint32_t error_status_t;
|
||||
|
||||
/* A rpc service interface like samr, lsarpc or netlogon */
|
||||
struct dcesrv_iface {
|
||||
const char *name;
|
||||
struct ndr_syntax_id syntax_id;
|
||||
};
|
||||
|
||||
struct dcesrv_iface_list {
|
||||
struct dcesrv_iface_list *next, *prev;
|
||||
struct dcesrv_iface *iface;
|
||||
};
|
||||
|
||||
/*
|
||||
epm_Insert
|
||||
*/
|
||||
* An endpoint can serve multiple rpc services interfaces.
|
||||
* For example \\pipe\netlogon can be used by lsarpc and netlogon.
|
||||
*/
|
||||
struct dcesrv_endpoint {
|
||||
struct dcesrv_endpoint *next, *prev;
|
||||
|
||||
/* The type and the location of the endpoint */
|
||||
struct dcerpc_binding *ep_description;
|
||||
|
||||
/* A list of rpc services able to connect to the endpoint */
|
||||
struct dcesrv_iface_list *iface_list;
|
||||
};
|
||||
|
||||
struct dcesrv_endpoint *endpoint_table;
|
||||
|
||||
/*
|
||||
* Check if the UUID and if_version match to an interface.
|
||||
*/
|
||||
static bool interface_match(const struct dcesrv_iface *if1,
|
||||
const struct dcesrv_iface *if2)
|
||||
{
|
||||
return GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the interface operations on an endpoint.
|
||||
*/
|
||||
static const struct dcesrv_iface *find_interface(const struct dcesrv_endpoint *endpoint,
|
||||
const struct dcesrv_iface *iface)
|
||||
{
|
||||
struct dcesrv_iface_list *iflist;
|
||||
|
||||
for (iflist = endpoint->iface_list; iflist; iflist = iflist->next) {
|
||||
if (interface_match(iflist->iface, iface)) {
|
||||
return iflist->iface;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if two endpoints match.
|
||||
*/
|
||||
static bool endpoints_match(const struct dcerpc_binding *ep1,
|
||||
const struct dcerpc_binding *ep2)
|
||||
{
|
||||
if (ep1->transport != ep2->transport) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ep1->endpoint || !ep2->endpoint) {
|
||||
return ep1->endpoint == ep2->endpoint;
|
||||
}
|
||||
|
||||
if (!strequal(ep1->endpoint, ep2->endpoint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct dcesrv_endpoint *find_endpoint(struct dcesrv_endpoint *endpoint_list,
|
||||
struct dcerpc_binding *ep_description) {
|
||||
struct dcesrv_endpoint *ep;
|
||||
|
||||
for (ep = endpoint_list; ep != NULL; ep = ep->next) {
|
||||
if (endpoints_match(ep->ep_description, ep_description)) {
|
||||
return ep;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a list of all interfaces handled by all endpoint servers.
|
||||
*/
|
||||
static uint32_t build_ep_list(TALLOC_CTX *mem_ctx,
|
||||
struct dcesrv_endpoint *endpoint_list,
|
||||
struct dcesrv_ep_iface **peps)
|
||||
{
|
||||
struct dcesrv_ep_iface *eps;
|
||||
struct dcesrv_endpoint *d;
|
||||
uint32_t total = 0;
|
||||
NTSTATUS status;
|
||||
|
||||
*peps = NULL;
|
||||
|
||||
for (d = endpoint_list; d != NULL; d = d->next) {
|
||||
struct dcesrv_iface_list *iface;
|
||||
struct dcerpc_binding *description;
|
||||
|
||||
for (iface = d->iface_list; iface != NULL; iface = iface->next) {
|
||||
eps = talloc_realloc(mem_ctx,
|
||||
eps,
|
||||
struct dcesrv_ep_iface,
|
||||
total + 1);
|
||||
if (eps == NULL) {
|
||||
return 0;
|
||||
}
|
||||
eps[total].name = iface->iface->name;
|
||||
|
||||
description = d->ep_description;
|
||||
description->object = iface->iface->syntax_id;
|
||||
|
||||
status = dcerpc_binding_build_tower(eps,
|
||||
description,
|
||||
&eps[total].ep);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
DEBUG(1, ("Unable to build tower for %s\n",
|
||||
iface->iface->name));
|
||||
continue;
|
||||
}
|
||||
total++;
|
||||
}
|
||||
}
|
||||
|
||||
*peps = eps;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/*
|
||||
* epm_Insert
|
||||
*
|
||||
* Add the specified entries to an endpoint map.
|
||||
*/
|
||||
error_status_t _epm_Insert(struct pipes_struct *p,
|
||||
struct epm_Insert *r)
|
||||
{
|
||||
/* Check if we have a priviledged pipe/handle */
|
||||
TALLOC_CTX *tmp_ctx;
|
||||
error_status_t rc;
|
||||
NTSTATUS status;
|
||||
uint32_t i;
|
||||
|
||||
/* Check if the entry already exits */
|
||||
tmp_ctx = talloc_stackframe();
|
||||
if (tmp_ctx == NULL) {
|
||||
return EPMAPPER_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Replace the entry if flag is set */
|
||||
DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
|
||||
r->in.num_ents));
|
||||
|
||||
/* Create new entry */
|
||||
/* TODO Check if we have a priviledged pipe/handle */
|
||||
|
||||
p->rng_fault_state = true;
|
||||
return EPMAPPER_STATUS_CANT_PERFORM_OP;
|
||||
for (i = 0; i < r->in.num_ents; i++) {
|
||||
struct dcerpc_binding *b = NULL;
|
||||
struct dcesrv_endpoint *ep;
|
||||
struct dcesrv_iface_list *iflist;
|
||||
struct dcesrv_iface *iface;
|
||||
bool add_ep = false;
|
||||
|
||||
status = dcerpc_binding_from_tower(tmp_ctx,
|
||||
&r->in.entries[i].tower->tower,
|
||||
&b);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
rc = EPMAPPER_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
|
||||
derpc_transport_string_by_transport(b->transport),
|
||||
r->in.entries[i].annotation));
|
||||
|
||||
/* Check if the entry already exits */
|
||||
ep = find_endpoint(endpoint_table, b);
|
||||
if (ep == NULL) {
|
||||
/* No entry found, create it */
|
||||
ep = talloc_zero(NULL, struct dcesrv_endpoint);
|
||||
if (ep == NULL) {
|
||||
rc = EPMAPPER_STATUS_CANT_PERFORM_OP;
|
||||
goto done;
|
||||
}
|
||||
add_ep = true;
|
||||
|
||||
ep->ep_description = talloc_steal(ep, b);
|
||||
}
|
||||
|
||||
/* TODO Replace the entry if the replace flag is set */
|
||||
|
||||
/* Create an interface */
|
||||
iface = talloc(tmp_ctx, struct dcesrv_iface);
|
||||
if (iface == NULL) {
|
||||
rc = EPMAPPER_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
iface->name = talloc_strdup(iface, r->in.entries[i].annotation);
|
||||
if (iface->name == NULL) {
|
||||
rc = EPMAPPER_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
iface->syntax_id = b->object;
|
||||
|
||||
/*
|
||||
* Check if the rpc service is alrady registered on the
|
||||
* endpoint.
|
||||
*/
|
||||
if (find_interface(ep, iface) != NULL) {
|
||||
DEBUG(0, ("dcesrv_interface_register: interface '%s' "
|
||||
"already registered on endpoint\n",
|
||||
iface->name));
|
||||
/* FIXME wrong error code? */
|
||||
rc = EPMAPPER_STATUS_OK;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Create an entry for the interface */
|
||||
iflist = talloc(ep, struct dcesrv_iface_list);
|
||||
if (iflist == NULL) {
|
||||
rc = EPMAPPER_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
iflist->iface = talloc_move(iflist, &iface);
|
||||
|
||||
/* Finally add the interface on the endpoint */
|
||||
DLIST_ADD(ep->iface_list, iflist);
|
||||
|
||||
/* If it's a new endpoint add it to the endpoint_table */
|
||||
if (add_ep) {
|
||||
DLIST_ADD(endpoint_table, ep);
|
||||
}
|
||||
}
|
||||
|
||||
rc = EPMAPPER_STATUS_OK;
|
||||
done:
|
||||
talloc_free(tmp_ctx);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user