diff --git a/selftest/knownfail.d/source3-epmapper b/selftest/knownfail.d/source3-epmapper new file mode 100644 index 00000000000..0a731eca7a3 --- /dev/null +++ b/selftest/knownfail.d/source3-epmapper @@ -0,0 +1,2 @@ +^samba3.rpc.epmapper\ over\ ncalrpc.epmapper.Map_full\(nt4_dc:local\) +^samba3.rpc.epmapper\ over\ ncalrpc.epmapper.Insert_noreplace\(nt4_dc:local\) diff --git a/source3/rpc_server/epmapper/srv_epmapper.c b/source3/rpc_server/epmapper/srv_epmapper.c index e7f71e0ade4..7b3a3051d0a 100644 --- a/source3/rpc_server/epmapper/srv_epmapper.c +++ b/source3/rpc_server/epmapper/srv_epmapper.c @@ -23,13 +23,17 @@ #include "ntdomain.h" #include "../libcli/security/security.h" #include "../lib/tsocket/tsocket.h" -#include "srv_epmapper.h" #include "auth.h" #include "librpc/rpc/dcesrv_core.h" #include "librpc/gen_ndr/ndr_epmapper.h" #include "librpc/gen_ndr/ndr_epmapper_scompat.h" #include "rpc_server/rpc_server.h" +#include "lib/tdb_wrap/tdb_wrap.h" +#include "lib/util/util_tdb.h" +#include "lib/util/strv.h" + +static struct tdb_wrap *epmdb = NULL; /* handle types for this module */ enum handle_types {HTYPE_LOOKUP}; @@ -80,283 +84,181 @@ struct rpc_eps { uint32_t count; }; -static struct dcesrv_epm_endpoint *endpoint_table = NULL; +struct build_ep_list_state { + const struct GUID *uuid; + const char *srv_addr; + TALLOC_CTX *mem_ctx; + struct dcesrv_ep_iface *ifaces; +}; -/* - * 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) +static bool build_ep_list_fill_iface( + TALLOC_CTX *mem_ctx, + const struct ndr_syntax_id *syntax_id, + const char *endpoint, + const char *name, + const char *srv_addr, + struct dcesrv_ep_iface *dst) { - return GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid); -} + struct dcesrv_ep_iface iface = { + .syntax_id = *syntax_id, + }; + struct dcerpc_binding *binding = NULL; + enum dcerpc_transport_t transport; + char *name_dup = NULL; + const char *host_addr = NULL; + NTSTATUS status; -/* - * Find the interface operations on an endpoint. - */ -static const struct dcesrv_iface *find_interface(const struct dcesrv_epm_endpoint *endpoint, - const struct dcesrv_iface *iface) -{ - struct dcesrv_iface_list *iflist; + /* copy without const for error path TALLOC_FREE */ + name_dup = talloc_strdup(mem_ctx, name); + if (name_dup == NULL) { + goto fail; + } + iface.name = name_dup; - for (iflist = endpoint->iface_list; iflist; iflist = iflist->next) { - if (interface_match(iflist->iface, iface)) { - return iflist->iface; + status = dcerpc_parse_binding(mem_ctx, endpoint, &binding); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_parse_binding failed: %s\n", + nt_errstr(status)); + goto fail; + } + + status = dcerpc_binding_set_abstract_syntax(binding, syntax_id); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n", + nt_errstr(status)); + goto fail; + } + + transport = dcerpc_binding_get_transport(binding); + if (transport == NCACN_IP_TCP) { + const char *host = NULL; + + host = dcerpc_binding_get_string_option(binding, "host"); + if (host == NULL) { + host_addr = srv_addr; + } else if (!is_ipaddress_v4(host)) { + host_addr = srv_addr; + } else if (strcmp(host, "0.0.0.0") == 0) { + host_addr = srv_addr; } } - return NULL; -} - -#if 0 -/* - * See if a uuid and if_version match to an interface - */ -static bool interface_match_by_uuid(const struct dcesrv_iface *iface, - const struct GUID *uuid) -{ - return GUID_equal(&iface->syntax_id.uuid, uuid); -} -#endif - -static struct dcesrv_iface_list *find_interface_list(const struct dcesrv_epm_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; + if (host_addr != NULL) { + status = dcerpc_binding_set_string_option( + binding, "host", host_addr); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_binding_set_string_option " + "failed: %s\n", + nt_errstr(status)); + goto fail; } } - return NULL; -} - -/* - * Check if two endpoints match. - */ -static bool endpoints_match(const struct dcerpc_binding *b1, - const struct dcerpc_binding *b2) -{ - enum dcerpc_transport_t t1; - const char *ep1; - const char *h1; - enum dcerpc_transport_t t2; - const char *ep2; - const char *h2; - - t1 = dcerpc_binding_get_transport(b1); - ep1 = dcerpc_binding_get_string_option(b1, "endpoint"); - h1 = dcerpc_binding_get_string_option(b1, "host"); - - t2 = dcerpc_binding_get_transport(b2); - ep2 = dcerpc_binding_get_string_option(b2, "endpoint"); - h2 = dcerpc_binding_get_string_option(b2, "host"); - - if (t1 != t2) { - return false; - } - - if ((ep1 != NULL) || (ep2 != NULL)) { - if (!strequal(ep1, ep2)) { - return false; - } - } - - if ((h1 != NULL) || (h2 != NULL)) { - if (!strequal(h1, h2)) { - return false; - } + status = dcerpc_binding_build_tower(mem_ctx, binding, &iface.ep); + TALLOC_FREE(binding); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n", + nt_errstr(status)); + goto fail; } + *dst = iface; return true; + +fail: + TALLOC_FREE(binding); + TALLOC_FREE(name_dup); + TALLOC_FREE(iface.ep.floors); + return false; } -static struct dcesrv_epm_endpoint *find_endpoint(struct dcesrv_epm_endpoint *endpoint_list, - struct dcerpc_binding *ep_description) { - struct dcesrv_epm_endpoint *ep = NULL; +static int build_ep_list_fn( + struct tdb_context *tdb, + TDB_DATA key, + TDB_DATA value, + void *private_data) +{ + struct build_ep_list_state *state = private_data; + struct ndr_syntax_id syntax_id = { .if_version = 0 }; + const char *name = NULL; + char *endpoints = NULL; + const char *endpoint = NULL; + bool ok; - for (ep = endpoint_list; ep != NULL; ep = ep->next) { - if (endpoints_match(ep->ep_description, ep_description)) { - return ep; + if ((key.dsize == 0) || (key.dptr[key.dsize-1] != '\0') || + (value.dsize == 0) || (value.dptr[value.dsize-1] != '\0')) { + DBG_DEBUG("Invalid record\n"); + return 0; + } + + ok = ndr_syntax_id_from_string((char *)key.dptr, &syntax_id); + if (!ok) { + DBG_DEBUG("Invalid interface: %s\n", (char *)key.dptr); + return 0; + } + + endpoints = (char *)value.dptr; + endpoint = endpoints; + name = endpoints; + + while ((endpoint = strv_len_next(endpoints, value.dsize, endpoint))) { + size_t num_ifaces = talloc_array_length(state->ifaces); + struct dcesrv_ep_iface *tmp = NULL; + + if (num_ifaces+1 < num_ifaces) { + return 1; + } + + tmp = talloc_realloc( + state->mem_ctx, + state->ifaces, + struct dcesrv_ep_iface, + num_ifaces+1); + if (tmp == NULL) { + return 1; + } + state->ifaces = tmp; + + ok = build_ep_list_fill_iface( + state->ifaces, + &syntax_id, + endpoint, + name, + state->srv_addr, + &state->ifaces[num_ifaces]); + if (!ok) { + state->ifaces = talloc_realloc( + state->mem_ctx, + state->ifaces, + struct dcesrv_ep_iface, + num_ifaces); } } - return NULL; + return 0; } /* * Build a list of all interfaces handled by all endpoint servers. */ static uint32_t build_ep_list(TALLOC_CTX *mem_ctx, - struct dcesrv_epm_endpoint *endpoint_list, const struct GUID *uuid, const char *srv_addr, struct dcesrv_ep_iface **peps) { - struct dcesrv_ep_iface *eps = NULL; - struct dcesrv_epm_endpoint *d = NULL; - uint32_t total = 0; - NTSTATUS status; + struct build_ep_list_state state = { + .mem_ctx = mem_ctx, .uuid = uuid, .srv_addr = srv_addr, + }; + int ret; - *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) { - enum dcerpc_transport_t transport; - const char *host = NULL; - const char *host_addr = NULL; - -#if 0 - /* - * Windows ignores the object uuid by default. There is - * one corner case. It is checked for the mgmt - * interface, which we do not implement here yet. - */ - if (uuid && !interface_match_by_uuid(iface->iface, uuid)) { - continue; - } -#endif - - eps = talloc_realloc(mem_ctx, - eps, - struct dcesrv_ep_iface, - total + 1); - if (eps == NULL) { - return 0; - } - eps[total].name = talloc_strdup(eps, - iface->iface->name); - if (eps[total].name == NULL) { - return 0; - } - eps[total].syntax_id = iface->iface->syntax_id; - - description = dcerpc_binding_dup(mem_ctx, d->ep_description); - if (description == NULL) { - return 0; - } - - status = dcerpc_binding_set_abstract_syntax(description, - &iface->iface->syntax_id); - if (!NT_STATUS_IS_OK(status)) { - return 0; - } - - transport = dcerpc_binding_get_transport(description); - host = dcerpc_binding_get_string_option(description, "host"); - - if (transport == NCACN_IP_TCP) { - if (host == NULL) { - host_addr = srv_addr; - } else if (!is_ipaddress_v4(host)) { - host_addr = srv_addr; - } else if (strcmp(host, "0.0.0.0") == 0) { - host_addr = srv_addr; - } - } - - if (host_addr != NULL) { - status = dcerpc_binding_set_string_option(description, - "host", - host_addr); - if (!NT_STATUS_IS_OK(status)) { - return 0; - } - } - - status = dcerpc_binding_build_tower(eps, - description, - &eps[total].ep); - TALLOC_FREE(description); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Unable to build tower for %s\n", - iface->iface->name)); - continue; - } - total++; - } + ret = tdb_traverse_read(epmdb->tdb, build_ep_list_fn, &state); + if (ret == -1) { + DBG_DEBUG("tdb_traverse_read failed\n"); + return 0; } - *peps = eps; - - return total; -} - -static bool is_privileged_pipe(struct auth_session_info *info) { - /* If the user is not root, or has the system token, fail */ - if ((info->unix_token->uid != sec_initial_uid()) && - !security_token_is_system(info->security_token)) { - return false; - } - - return true; -} - -void srv_epmapper_delete_endpoints(struct dcesrv_connection *conn, - void *private_data) -{ - struct pipes_struct *p = dcesrv_get_pipes_struct(conn); - struct dcesrv_auth *auth = NULL; - struct epm_Delete r; - struct dcesrv_ep_entry_list *el = p->ep_entries; - error_status_t result; - - /* We have to set p->session_info to check if the connection is - * privileged and delete the endpoints registered by this connection. - * Set the default session info created at connection time as a - * fallback. - */ - p->session_info = conn->default_auth_state->session_info; - - /* Due to security context multiplexing we can have several states - * in the connection. Search the one of type NCALRPC_AS_SYSTEM to - * replace the default. - */ - for (auth = conn->auth_states; auth != NULL; auth = auth->next) { - if (auth->auth_type == DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM) { - p->session_info = auth->session_info; - } - } - - while (el) { - struct dcesrv_ep_entry_list *next = el->next; - - r.in.num_ents = el->num_ents; - r.in.entries = el->entries; - - DEBUG(10, ("Delete_endpoints for: %s\n", - el->entries[0].annotation)); - - result = _epm_Delete(p, &r); - if (result != EPMAPPER_STATUS_OK) { - DBG_ERR("Failed to delete endpoint maps\n"); - return; - } - - DLIST_REMOVE(p->ep_entries, el); - TALLOC_FREE(el); - - el = next; - } -} - -void srv_epmapper_cleanup(void) -{ - struct dcesrv_epm_endpoint *ep = endpoint_table; - - while (ep) { - struct dcesrv_epm_endpoint *next = ep->next; - - DLIST_REMOVE(endpoint_table, ep); - TALLOC_FREE(ep); - - ep = next; - } + *peps = state.ifaces; + return talloc_array_length(*peps); } /* @@ -367,135 +269,10 @@ void srv_epmapper_cleanup(void) error_status_t _epm_Insert(struct pipes_struct *p, struct epm_Insert *r) { - TALLOC_CTX *tmp_ctx; - error_status_t rc; - NTSTATUS status; - uint32_t i; - struct dcerpc_binding *b; - struct dcesrv_epm_endpoint *ep = NULL; - struct dcesrv_iface_list *iflist; - struct dcesrv_iface *iface; - bool add_ep; - - /* If this is not a privileged users, return */ - if (p->transport != NCALRPC || - !is_privileged_pipe(p->session_info)) { - p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; - return EPMAPPER_STATUS_CANT_PERFORM_OP; - } - - tmp_ctx = talloc_stackframe(); - if (tmp_ctx == NULL) { - return EPMAPPER_STATUS_NO_MEMORY; - } - - DBG_NOTICE("Trying to add %"PRIu32" new entries.\n", - r->in.num_ents); - - for (i = 0; i < r->in.num_ents; i++) { - enum dcerpc_transport_t transport; - add_ep = false; - b = NULL; - - status = dcerpc_binding_from_tower(tmp_ctx, - &r->in.entries[i].tower->tower, - &b); - if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) { - rc = EPMAPPER_STATUS_NO_MEMORY; - goto done; - } - if (!NT_STATUS_IS_OK(status)) { - rc = EPMAPPER_STATUS_CANT_PERFORM_OP; - goto done; - } - - transport = dcerpc_binding_get_transport(b); - DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n", - derpc_transport_string_by_transport(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_epm_endpoint); - if (ep == NULL) { - rc = EPMAPPER_STATUS_NO_MEMORY; - 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 = dcerpc_binding_get_abstract_syntax(b); - - /* - * Check if the rpc service is already registered on the - * endpoint. - */ - if (find_interface(ep, iface) != NULL) { - DBG_INFO("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); - } - } - - if (r->in.num_ents > 0) { - struct dcesrv_ep_entry_list *el; - - el = talloc_zero(p, struct dcesrv_ep_entry_list); - if (el == NULL) { - rc = EPMAPPER_STATUS_NO_MEMORY; - goto done; - } - el->num_ents = r->in.num_ents; - el->entries = talloc_move(el, &r->in.entries); - - DLIST_ADD(p->ep_entries, el); - } - - rc = EPMAPPER_STATUS_OK; -done: - talloc_free(tmp_ctx); - - return rc; + p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; + return EPMAPPER_STATUS_CANT_PERFORM_OP; } - /* * epm_Delete * @@ -504,88 +281,10 @@ done: error_status_t _epm_Delete(struct pipes_struct *p, struct epm_Delete *r) { - TALLOC_CTX *tmp_ctx; - error_status_t rc; - NTSTATUS status; - uint32_t i; - struct dcerpc_binding *b; - struct dcesrv_epm_endpoint *ep = NULL; - struct dcesrv_iface iface; - struct dcesrv_iface_list *iflist; - - DEBUG(3, ("_epm_Delete: Trying to delete %u entries.\n", - r->in.num_ents)); - - /* If this is not a privileged users, return */ - if (p->transport != NCALRPC || - !is_privileged_pipe(p->session_info)) { - p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; - return EPMAPPER_STATUS_CANT_PERFORM_OP; - } - - tmp_ctx = talloc_stackframe(); - if (tmp_ctx == NULL) { - return EPMAPPER_STATUS_NO_MEMORY; - } - - for (i = 0; i < r->in.num_ents; i++) { - enum dcerpc_transport_t transport; - - b = NULL; - - 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; - } - - transport = dcerpc_binding_get_transport(b); - DEBUG(3, ("_epm_Delete: Deleting transport '%s' for '%s'\n", - derpc_transport_string_by_transport(transport), - r->in.entries[i].annotation)); - - ep = find_endpoint(endpoint_table, b); - if (ep == NULL) { - rc = EPMAPPER_STATUS_OK; - goto done; - } - - iface.name = r->in.entries[i].annotation; - iface.syntax_id = dcerpc_binding_get_abstract_syntax(b); - - iflist = find_interface_list(ep, &iface); - if (iflist == NULL) { - DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n")); - DLIST_REMOVE(endpoint_table, ep); - talloc_free(ep); - - rc = EPMAPPER_STATUS_OK; - goto done; - } - - DLIST_REMOVE(ep->iface_list, iflist); - - if (ep->iface_list == NULL) { - DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n")); - DLIST_REMOVE(endpoint_table, ep); - talloc_free(ep); - - rc = EPMAPPER_STATUS_OK; - goto done; - } - - } - - rc = EPMAPPER_STATUS_OK; -done: - talloc_free(tmp_ctx); - - return rc; + p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; + return EPMAPPER_STATUS_CANT_PERFORM_OP; } - /* * epm_Lookup * @@ -643,7 +342,6 @@ error_status_t _epm_Lookup(struct pipes_struct *p, * be ignored. */ eps->count = build_ep_list(eps, - endpoint_table, NULL, srv_addr, &eps->e); @@ -666,7 +364,6 @@ error_status_t _epm_Lookup(struct pipes_struct *p, * interface_id, vers_option, and object. */ eps->count = build_ep_list(eps, - endpoint_table, &r->in.interface_id->uuid, srv_addr, &eps->e); @@ -677,7 +374,6 @@ error_status_t _epm_Lookup(struct pipes_struct *p, * UUID specified by object. */ eps->count = build_ep_list(eps, - endpoint_table, r->in.object, srv_addr, &eps->e); @@ -922,6 +618,126 @@ done: return rc; } +static struct rpc_eps *epm_map_get_towers( + TALLOC_CTX *mem_ctx, + const struct ndr_syntax_id *iface, + enum dcerpc_transport_t transport, + const char *local_address) +{ + struct ndr_syntax_id_buf idbuf; + char *iface_string = ndr_syntax_id_buf_string(iface, &idbuf); + struct rpc_eps *eps = NULL; + uint8_t *buf = NULL; + size_t buflen; + char *bindings = NULL; + char *binding = NULL; + char *name = NULL; + NTSTATUS status; + int ret; + + DBG_DEBUG("Mapping interface %s\n", iface_string); + + eps = talloc_zero(mem_ctx, struct rpc_eps); + if (eps == NULL) { + goto fail; + } + + ret = tdb_fetch_talloc( + epmdb->tdb, string_term_tdb_data(iface_string), eps, &buf); + if (ret != 0) { + DBG_DEBUG("Could not find epm entry for %s: %s\n", + iface_string, + strerror(ret)); + goto fail; + } + buflen = talloc_array_length(buf); + + if ((buflen < 1) || (buf[buflen-1] != '\0')) { + DBG_DEBUG("epm entry for %s invalid\n", iface_string); + goto fail; + } + bindings = (char *)buf; + + name = bindings; /* name comes first */ + binding = name; /* strv_next will skip name */ + + while ((binding = strv_next(bindings, binding)) != NULL) { + struct dcerpc_binding *b = NULL; + enum dcerpc_transport_t found_transport; + struct dcesrv_ep_iface *tmp = NULL, *new_ep = NULL; + + DBG_DEBUG("Found %s for %s\n", binding, name); + + status = dcerpc_parse_binding(mem_ctx, binding, &b); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_parse_binding() for %s failed: %s\n", + binding, + nt_errstr(status)); + goto fail; + } + + found_transport = dcerpc_binding_get_transport(b); + if (found_transport != transport) { + DBG_DEBUG("Transport %d does not match %d\n", + (int)found_transport, + (int)transport); + TALLOC_FREE(b); + continue; + } + + if (found_transport == NCACN_IP_TCP) { + status = dcerpc_binding_set_string_option( + b, "host", local_address); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("Could not set host: %s\n", + nt_errstr(status)); + goto fail; + } + } + + status = dcerpc_binding_set_abstract_syntax(b, iface); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("Could not set abstract syntax: %s\n", + nt_errstr(status)); + goto fail; + } + + tmp = talloc_realloc( + eps, + eps->e, + struct dcesrv_ep_iface, + eps->count+1); + if (tmp == NULL) { + goto fail; + } + eps->e = tmp; + + new_ep = &eps->e[eps->count]; + + new_ep->name = talloc_strdup(eps->e, name); + if (new_ep->name == NULL) { + goto fail; + } + new_ep->syntax_id = *iface; + + status = dcerpc_binding_build_tower(eps->e, b, &new_ep->ep); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n", + nt_errstr(status)); + goto fail; + } + + eps->count += 1; + + TALLOC_FREE(b); + } + return eps; + +fail: + TALLOC_FREE(eps); + return NULL; +} + /* * epm_Map * @@ -980,7 +796,13 @@ error_status_t _epm_Map(struct pipes_struct *p, floors = r->in.map_tower->tower.floors; /* We accept NDR as the transfer syntax */ - dcerpc_floor_get_lhs_data(&floors[1], &ifid); + status = dcerpc_floor_get_lhs_data(&floors[1], &ifid); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_floor_get_lhs_data() failed: %s\n", + nt_errstr(status)); + rc = EPMAPPER_STATUS_NO_MORE_ENTRIES; + goto done; + } if (floors[1].lhs.protocol != EPM_PROTOCOL_UUID || !ndr_syntax_id_equal(&ifid, &ndr_transfer_syntax_ndr)) { @@ -1003,91 +825,42 @@ error_status_t _epm_Map(struct pipes_struct *p, if (r->in.entry_handle == NULL || ndr_policy_handle_empty(r->in.entry_handle)) { - struct GUID *obj; - char *srv_addr = NULL; + char *local_address = NULL; + struct ndr_syntax_id_buf buf; + char *if_string = NULL; DEBUG(7, ("_epm_Map: No entry_handle found, creating it.\n")); - eps = talloc_zero(tmp_ctx, struct rpc_eps); - if (eps == NULL) { - rc = EPMAPPER_STATUS_NO_MEMORY; - goto done; - } - - /* - * *** ATTENTION *** - * CDE 1.1 states: - * - * ept_map() - * Apply some algorithm (using the fields in the map_tower) - * to an endpoint map to produce a list of protocol towers. - * - * The following code is the mysterious "some algorithm"! - */ - - /* Filter by object id if one was given. */ - if (r->in.object == NULL || GUID_all_zero(r->in.object)) { - obj = NULL; - } else { - obj = r->in.object; - } - - if (p->local_address != NULL && - tsocket_address_is_inet(p->local_address, "ipv4")) - { - srv_addr = tsocket_address_inet_addr_string(p->local_address, - tmp_ctx); - } - - eps->count = build_ep_list(eps, - endpoint_table, - obj, - srv_addr, - &eps->e); - if (eps->count == 0) { + status = dcerpc_floor_get_lhs_data(&floors[0], &ifid); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("dcerpc_floor_get_lhs_data() failed: %s\n", + nt_errstr(status)); rc = EPMAPPER_STATUS_NO_MORE_ENTRIES; goto done; } - /* Filter out endpoints which match the interface. */ - { - struct rpc_eps *teps; - uint32_t total = 0; + if_string = ndr_syntax_id_buf_string(&ifid, &buf); - teps = talloc_zero(tmp_ctx, struct rpc_eps); - if (teps == NULL) { - rc = EPMAPPER_STATUS_NO_MEMORY; - goto done; - } + DBG_INFO("Mapping interface %s\n", if_string); - for (i = 0; i < eps->count; i++) { - if (data_blob_cmp(&r->in.map_tower->tower.floors[0].lhs.lhs_data, - &eps->e[i].ep.floors[0].lhs.lhs_data) != 0 || - transport != dcerpc_transport_by_tower(&eps->e[i].ep)) { - continue; - } - - teps->e = talloc_realloc(tmp_ctx, - teps->e, - struct dcesrv_ep_iface, - total + 1); - if (teps->e == NULL) { - return 0; - } - - teps->e[total].ep.floors = talloc_move(teps, &eps->e[i].ep.floors); - teps->e[total].ep.num_floors = eps->e[i].ep.num_floors; - teps->e[total].name = talloc_move(teps, &eps->e[i].name); - teps->e[total].syntax_id = eps->e[i].syntax_id; - - total++; - } - - teps->count = total; - talloc_free(eps); - eps = teps; + if ((transport == NCACN_IP_TCP) && + tsocket_address_is_inet(p->local_address, "ip")) { + /* + * We don't have the host ip in the epm + * database. For NCACN_IP_TCP, add the IP that + * the client connected to. + */ + local_address = tsocket_address_inet_addr_string( + p->local_address, tmp_ctx); + } + + eps = epm_map_get_towers( + tmp_ctx, &ifid, transport, local_address); + if (eps == NULL) { + DBG_DEBUG("No bindings found\n"); + rc = EPMAPPER_STATUS_NO_MORE_ENTRIES; + goto done; } - /* end of "some algorithm" */ ok = create_policy_hnd(p, r->out.entry_handle, HTYPE_LOOKUP, eps); if (!ok) { @@ -1245,11 +1018,44 @@ static NTSTATUS epmapper__op_shutdown_server(struct dcesrv_context *dce_ctx, static NTSTATUS epmapper_shutdown_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server) { - srv_epmapper_cleanup(); - return epmapper__op_shutdown_server(dce_ctx, ep_server); } +static NTSTATUS epmapper__op_init_server( + struct dcesrv_context *dce_ctx, + const struct dcesrv_endpoint_server *ep_server); + +static NTSTATUS epmapper_init_server( + struct dcesrv_context *dce_ctx, + const struct dcesrv_endpoint_server *ep_server) +{ + char *epmdb_path = NULL; + NTSTATUS status; + + epmdb_path = lock_path(dce_ctx, "epmdb.tdb"); + if (epmdb_path == NULL) { + return NT_STATUS_NO_MEMORY; + } + + epmdb = tdb_wrap_open( + dce_ctx, + epmdb_path, + 0, + TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, + O_RDONLY, + 0644); + if (epmdb == NULL) { + DBG_DEBUG("Could not open epmdb.tdb: %s\n", strerror(errno)); + return map_nt_error_from_unix(errno); + } + TALLOC_FREE(epmdb_path); + + status = epmapper__op_init_server(dce_ctx, ep_server); + return status; +} + +#define DCESRV_INTERFACE_EPMAPPER_INIT_SERVER epmapper_init_server + /* include the generated boilerplate */ #include "librpc/gen_ndr/ndr_epmapper_scompat.c" diff --git a/source3/rpc_server/epmapper/srv_epmapper.h b/source3/rpc_server/epmapper/srv_epmapper.h deleted file mode 100644 index 7ec35ace666..00000000000 --- a/source3/rpc_server/epmapper/srv_epmapper.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * - * Endpoint server for the epmapper pipe - * - * Copyright (C) 2010-2011 Andreas Schneider - * - * 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 3 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, see . - */ - -#ifndef _SRV_EPMAPPER_H_ -#define _SRV_EPMAPPER_H_ - -struct dcesrv_connection; - -/** - * @brief Cleanup memory and other stuff. - */ -void srv_epmapper_cleanup(void); - -/** - * @brief Cleanup function used to delete endpoints when a ncalrpc connection - * from an external daemon is lost - */ -void srv_epmapper_delete_endpoints(struct dcesrv_connection *conn, - void *private_data); - -#endif /*_SRV_EPMAPPER_H_ */ - -/* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */ diff --git a/source3/rpc_server/epmd.c b/source3/rpc_server/epmd.c index f1178f67aa3..f9b80a03510 100644 --- a/source3/rpc_server/epmd.c +++ b/source3/rpc_server/epmd.c @@ -32,7 +32,6 @@ #include "rpc_server/rpc_server.h" #include "rpc_server/rpc_service_setup.h" #include "rpc_server/rpc_sock_helper.h" -#include "rpc_server/epmapper/srv_epmapper.h" #include "rpc_server/epmd.h" #undef DBGC_CLASS @@ -216,10 +215,6 @@ void start_epmd(struct tevent_context *ev_ctx, continue; } - if (transport == NCALRPC) { - term_fn = srv_epmapper_delete_endpoints; - } - status = dcesrv_setup_endpoint_sockets(ev_ctx, msg_ctx, dce_ctx, diff --git a/source3/rpc_server/rpc_service_setup.c b/source3/rpc_server/rpc_service_setup.c index 4d4af724126..2d585af6f47 100644 --- a/source3/rpc_server/rpc_service_setup.c +++ b/source3/rpc_server/rpc_service_setup.c @@ -52,7 +52,6 @@ #include "rpc_server/rpc_server.h" #include "rpc_server/rpc_config.h" #include "rpc_server/rpc_modules.h" -#include "rpc_server/epmapper/srv_epmapper.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV diff --git a/source3/rpc_server/rpcd_classic.c b/source3/rpc_server/rpcd_classic.c new file mode 100644 index 00000000000..d3607d2e19c --- /dev/null +++ b/source3/rpc_server/rpcd_classic.c @@ -0,0 +1,99 @@ +/* + * Unix SMB/CIFS implementation. + * + * 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 3 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, see . + */ + +#include "includes.h" +#include "rpc_worker.h" +#include "librpc/gen_ndr/ndr_srvsvc.h" +#include "librpc/gen_ndr/ndr_srvsvc_scompat.h" +#include "librpc/gen_ndr/ndr_dfs.h" +#include "librpc/gen_ndr/ndr_dfs_scompat.h" +#include "librpc/gen_ndr/ndr_wkssvc.h" +#include "librpc/gen_ndr/ndr_wkssvc_scompat.h" +#include "librpc/gen_ndr/ndr_svcctl.h" +#include "librpc/gen_ndr/ndr_svcctl_scompat.h" +#include "librpc/gen_ndr/ndr_ntsvcs.h" +#include "librpc/gen_ndr/ndr_ntsvcs_scompat.h" +#include "librpc/gen_ndr/ndr_eventlog.h" +#include "librpc/gen_ndr/ndr_eventlog_scompat.h" +#include "librpc/gen_ndr/ndr_initshutdown.h" +#include "librpc/gen_ndr/ndr_initshutdown_scompat.h" +#include "source3/include/secrets.h" +#include "locking/share_mode_lock.h" + +static size_t classic_interfaces( + const struct ndr_interface_table ***pifaces, + void *private_data) +{ + static const struct ndr_interface_table *ifaces[] = { + &ndr_table_srvsvc, + &ndr_table_netdfs, + &ndr_table_wkssvc, + &ndr_table_svcctl, + &ndr_table_ntsvcs, + &ndr_table_eventlog, + &ndr_table_initshutdown, + }; + *pifaces = ifaces; + return ARRAY_SIZE(ifaces); +} + +static size_t classic_servers( + struct dcesrv_context *dce_ctx, + const struct dcesrv_endpoint_server ***_ep_servers, + void *private_data) +{ + static const struct dcesrv_endpoint_server *ep_servers[7] = { NULL }; + bool ok; + + ep_servers[0] = srvsvc_get_ep_server(); + ep_servers[1] = netdfs_get_ep_server(); + ep_servers[2] = wkssvc_get_ep_server(); + ep_servers[3] = svcctl_get_ep_server(); + ep_servers[4] = ntsvcs_get_ep_server(); + ep_servers[5] = eventlog_get_ep_server(); + ep_servers[6] = initshutdown_get_ep_server(); + + ok = secrets_init(); + if (!ok) { + DBG_ERR("secrets_init() failed\n"); + exit(1); + } + + ok = locking_init(); + if (!ok) { + DBG_ERR("locking_init() failed\n"); + exit(1); + } + + lp_load_with_shares(get_dyn_CONFIGFILE()); + + *_ep_servers = ep_servers; + return ARRAY_SIZE(ep_servers); +} + +int main(int argc, const char *argv[]) +{ + return rpc_worker_main( + argc, + argv, + "rpcd_classic", + 5, + 60, + classic_interfaces, + classic_servers, + NULL); +} diff --git a/source3/rpc_server/rpcd_epmapper.c b/source3/rpc_server/rpcd_epmapper.c new file mode 100644 index 00000000000..950ba7ec12a --- /dev/null +++ b/source3/rpc_server/rpcd_epmapper.c @@ -0,0 +1,58 @@ +/* + * Unix SMB/CIFS implementation. + * + * 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 3 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, see . + */ + +#include "replace.h" +#include "rpc_worker.h" +#include "librpc/gen_ndr/ndr_epmapper.h" +#include "librpc/gen_ndr/ndr_epmapper_scompat.h" + +static size_t epmapper_interfaces( + const struct ndr_interface_table ***pifaces, + void *private_data) +{ + static const struct ndr_interface_table *ifaces[] = { + &ndr_table_epmapper, + }; + *pifaces = ifaces; + return ARRAY_SIZE(ifaces); +} + +static size_t epmapper_servers( + struct dcesrv_context *dce_ctx, + const struct dcesrv_endpoint_server ***_ep_servers, + void *private_data) +{ + static const struct dcesrv_endpoint_server *ep_servers[] = { NULL }; + + ep_servers[0] = epmapper_get_ep_server(); + + *_ep_servers = ep_servers; + return ARRAY_SIZE(ep_servers); +} + +int main(int argc, const char *argv[]) +{ + return rpc_worker_main( + argc, + argv, + "rpcd_epmapper", + 1, + 10, + epmapper_interfaces, + epmapper_servers, + NULL); +} diff --git a/source3/rpc_server/rpcd_fsrvp.c b/source3/rpc_server/rpcd_fsrvp.c new file mode 100644 index 00000000000..3325bbbc16b --- /dev/null +++ b/source3/rpc_server/rpcd_fsrvp.c @@ -0,0 +1,79 @@ +/* + * Unix SMB/CIFS implementation. + * + * 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 3 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, see . + */ + +#include "includes.h" +#include "rpc_worker.h" +#include "librpc/gen_ndr/ndr_fsrvp.h" +#include "librpc/gen_ndr/ndr_fsrvp_scompat.h" + +static size_t fsrvp_interfaces( + const struct ndr_interface_table ***pifaces, + void *private_data) +{ + static const struct ndr_interface_table *ifaces[] = { + &ndr_table_FileServerVssAgent, + }; + + if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) { + /* + * For now, don't do shadow copies on the AD DC. This + * might change in the future, but there's a + * recommendation to split DCs from file servers. + * + * But then we need to put the snap logic into the ad + * dc testenv's smb.conf. + */ + *pifaces = NULL; + return 0; + } + + *pifaces = ifaces; + return ARRAY_SIZE(ifaces); +} + +static size_t fsrvp_servers( + struct dcesrv_context *dce_ctx, + const struct dcesrv_endpoint_server ***_ep_servers, + void *private_data) +{ + static const struct dcesrv_endpoint_server *ep_servers[1] = { NULL }; + + if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) { + *_ep_servers = NULL; + return 0; + } + + lp_load_with_shares(get_dyn_CONFIGFILE()); + + ep_servers[0] = FileServerVssAgent_get_ep_server(); + + *_ep_servers = ep_servers; + return ARRAY_SIZE(ep_servers); +} + +int main(int argc, const char *argv[]) +{ + return rpc_worker_main( + argc, + argv, + "rpcd_fsrvp", + 5, + 60, + fsrvp_interfaces, + fsrvp_servers, + NULL); +} diff --git a/source3/rpc_server/rpcd_lsad.c b/source3/rpc_server/rpcd_lsad.c new file mode 100644 index 00000000000..3ca0ed43fdd --- /dev/null +++ b/source3/rpc_server/rpcd_lsad.c @@ -0,0 +1,102 @@ +/* + * Unix SMB/CIFS implementation. + * + * 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 3 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, see . + */ + +#include "includes.h" +#include "rpc_worker.h" +#include "librpc/gen_ndr/ndr_lsa.h" +#include "librpc/gen_ndr/ndr_lsa_scompat.h" +#include "librpc/gen_ndr/ndr_samr.h" +#include "librpc/gen_ndr/ndr_samr_scompat.h" +#include "librpc/gen_ndr/ndr_netlogon.h" +#include "librpc/gen_ndr/ndr_netlogon_scompat.h" +#include "librpc/gen_ndr/ndr_dssetup.h" +#include "librpc/gen_ndr/ndr_dssetup_scompat.h" +#include "source3/include/auth.h" +#include "source3/include/secrets.h" + +static size_t lsad_interfaces( + const struct ndr_interface_table ***pifaces, + void *private_data) +{ + static const struct ndr_interface_table *ifaces[] = { + &ndr_table_lsarpc, + &ndr_table_samr, + &ndr_table_dssetup, + &ndr_table_netlogon, + }; + size_t num_ifaces = ARRAY_SIZE(ifaces); + + switch(lp_server_role()) { + case ROLE_STANDALONE: + case ROLE_DOMAIN_MEMBER: + /* no netlogon for non-dc */ + num_ifaces -= 1; + break; + default: + break; + } + + *pifaces = ifaces; + return num_ifaces; +} + +static size_t lsad_servers( + struct dcesrv_context *dce_ctx, + const struct dcesrv_endpoint_server ***_ep_servers, + void *private_data) +{ + static const struct dcesrv_endpoint_server *ep_servers[4] = { NULL, }; + size_t num_servers = ARRAY_SIZE(ep_servers); + bool ok; + + ep_servers[0] = lsarpc_get_ep_server(); + ep_servers[1] = samr_get_ep_server(); + ep_servers[2] = dssetup_get_ep_server(); + ep_servers[3] = netlogon_get_ep_server(); + + ok = secrets_init(); + if (!ok) { + DBG_ERR("secrets_init() failed\n"); + exit(1); + } + + switch(lp_server_role()) { + case ROLE_STANDALONE: + case ROLE_DOMAIN_MEMBER: + /* no netlogon for non-dc */ + num_servers -= 1; + break; + default: + break; + } + + *_ep_servers = ep_servers; + return num_servers; +} + +int main(int argc, const char *argv[]) +{ + return rpc_worker_main( + argc, + argv, + "rpcd_lsad", + 5, + 60, + lsad_interfaces, + lsad_servers, + NULL); +} diff --git a/source3/rpc_server/rpcd_mdssvc.c b/source3/rpc_server/rpcd_mdssvc.c new file mode 100644 index 00000000000..c5b632099fa --- /dev/null +++ b/source3/rpc_server/rpcd_mdssvc.c @@ -0,0 +1,61 @@ +/* + * Unix SMB/CIFS implementation. + * + * 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 3 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, see . + */ + +#include "includes.h" +#include "rpc_worker.h" +#include "librpc/gen_ndr/ndr_mdssvc.h" +#include "librpc/gen_ndr/ndr_mdssvc_scompat.h" + +static size_t mdssvc_interfaces( + const struct ndr_interface_table ***pifaces, + void *private_data) +{ + static const struct ndr_interface_table *ifaces[] = { + &ndr_table_mdssvc, + }; + + *pifaces = ifaces; + return ARRAY_SIZE(ifaces); +} + +static size_t mdssvc_servers( + struct dcesrv_context *dce_ctx, + const struct dcesrv_endpoint_server ***_ep_servers, + void *private_data) +{ + static const struct dcesrv_endpoint_server *ep_servers[1] = { NULL }; + + lp_load_with_shares(get_dyn_CONFIGFILE()); + + ep_servers[0] = mdssvc_get_ep_server(); + + *_ep_servers = ep_servers; + return ARRAY_SIZE(ep_servers); +} + +int main(int argc, const char *argv[]) +{ + return rpc_worker_main( + argc, + argv, + "rpcd_mdssvc", + 5, + 60, + mdssvc_interfaces, + mdssvc_servers, + NULL); +} diff --git a/source3/rpc_server/rpcd_rpcecho.c b/source3/rpc_server/rpcd_rpcecho.c new file mode 100644 index 00000000000..9176039819f --- /dev/null +++ b/source3/rpc_server/rpcd_rpcecho.c @@ -0,0 +1,58 @@ +/* + * Unix SMB/CIFS implementation. + * + * 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 3 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, see . + */ + +#include "replace.h" +#include "rpc_worker.h" +#include "librpc/gen_ndr/ndr_echo.h" +#include "librpc/gen_ndr/ndr_echo_scompat.h" + +static size_t rpcecho_interfaces( + const struct ndr_interface_table ***pifaces, + void *private_data) +{ + static const struct ndr_interface_table *ifaces[] = { + &ndr_table_rpcecho, + }; + *pifaces = ifaces; + return ARRAY_SIZE(ifaces); +} + +static size_t rpcecho_servers( + struct dcesrv_context *dce_ctx, + const struct dcesrv_endpoint_server ***_ep_servers, + void *private_data) +{ + static const struct dcesrv_endpoint_server *ep_servers[1] = { NULL }; + + ep_servers[0] = rpcecho_get_ep_server(); + + *_ep_servers = ep_servers; + return ARRAY_SIZE(ep_servers); +} + +int main(int argc, const char *argv[]) +{ + return rpc_worker_main( + argc, + argv, + "rpcd_rpcecho", + 1, + 1, + rpcecho_interfaces, + rpcecho_servers, + NULL); +} diff --git a/source3/rpc_server/rpcd_spoolss.c b/source3/rpc_server/rpcd_spoolss.c new file mode 100644 index 00000000000..de54619e327 --- /dev/null +++ b/source3/rpc_server/rpcd_spoolss.c @@ -0,0 +1,86 @@ +/* + * Unix SMB/CIFS implementation. + * + * 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 3 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, see . + */ + +#include "includes.h" +#include "rpc_worker.h" +#include "lib/global_contexts.h" +#include "librpc/gen_ndr/ndr_spoolss.h" +#include "librpc/gen_ndr/ndr_spoolss_scompat.h" +#include "source3/locking/share_mode_lock.h" +#include "source3/printing/queue_process.h" +#include "source3/include/messages.h" +#include "source3/include/secrets.h" + +static size_t spoolss_interfaces( + const struct ndr_interface_table ***pifaces, + void *private_data) +{ + static const struct ndr_interface_table *ifaces[] = { + &ndr_table_spoolss, + }; + *pifaces = ifaces; + return ARRAY_SIZE(ifaces); +} + +static size_t spoolss_servers( + struct dcesrv_context *dce_ctx, + const struct dcesrv_endpoint_server ***_ep_servers, + void *private_data) +{ + static const struct dcesrv_endpoint_server *ep_servers[1] = { NULL }; + struct messaging_context *msg_ctx = global_messaging_context(); + struct tevent_context *ev_ctx = messaging_tevent_context(msg_ctx); + bool ok; + + ep_servers[0] = spoolss_get_ep_server(); + + ok = secrets_init(); + if (!ok) { + DBG_ERR("secrets_init() failed\n"); + exit(1); + } + + ok = locking_init(); + if (!ok) { + DBG_ERR("locking_init() failed\n"); + exit(1); + } + + lp_load_with_shares(get_dyn_CONFIGFILE()); + + ok = printing_subsystem_init(ev_ctx, msg_ctx, dce_ctx, false, false); + if (!ok) { + DBG_WARNING("printing_subsystem_init() failed\n"); + return 1; + } + + *_ep_servers = ep_servers; + return ARRAY_SIZE(ep_servers); +} + +int main(int argc, const char *argv[]) +{ + return rpc_worker_main( + argc, + argv, + "rpcd_spoolss", + 5, + 60, + spoolss_interfaces, + spoolss_servers, + NULL); +} diff --git a/source3/rpc_server/rpcd_winreg.c b/source3/rpc_server/rpcd_winreg.c new file mode 100644 index 00000000000..4f92fd76617 --- /dev/null +++ b/source3/rpc_server/rpcd_winreg.c @@ -0,0 +1,69 @@ +/* + * Unix SMB/CIFS implementation. + * + * 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 3 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, see . + */ + +#include "includes.h" +#include "rpc_worker.h" +#include "librpc/gen_ndr/ndr_winreg.h" +#include "librpc/gen_ndr/ndr_winreg_scompat.h" +#include "source3/registry/reg_init_full.h" + +static size_t winreg_interfaces( + const struct ndr_interface_table ***pifaces, + void *private_data) +{ + static const struct ndr_interface_table *ifaces[] = { + &ndr_table_winreg, + }; + *pifaces = ifaces; + return ARRAY_SIZE(ifaces); +} + +static size_t winreg_servers( + struct dcesrv_context *dce_ctx, + const struct dcesrv_endpoint_server ***_ep_servers, + void *private_data) +{ + static const struct dcesrv_endpoint_server *ep_servers[1] = { NULL }; + WERROR werr; + + ep_servers[0] = winreg_get_ep_server(); + + werr = registry_init_full(); + if (!W_ERROR_IS_OK(werr)) { + DBG_ERR("registry_init_full() failed: %s\n", + win_errstr(werr)); + exit(1); + } + + lp_load_with_shares(get_dyn_CONFIGFILE()); + + *_ep_servers = ep_servers; + return ARRAY_SIZE(ep_servers); +} + +int main(int argc, const char *argv[]) +{ + return rpc_worker_main( + argc, + argv, + "rpcd_winreg", + 5, + 60, + winreg_interfaces, + winreg_servers, + NULL); +} diff --git a/source3/rpc_server/wscript_build b/source3/rpc_server/wscript_build index 98b0c24a2d6..0caa3b64745 100644 --- a/source3/rpc_server/wscript_build +++ b/source3/rpc_server/wscript_build @@ -33,6 +33,79 @@ bld.SAMBA_LIBRARY('RPC_WORKER', npa_tstream ''') +bld.SAMBA3_BINARY('rpcd_rpcecho', + source='rpcd_rpcecho.c', + deps=''' + RPC_WORKER + RPC_RPCECHO + ''', + install_path='${SAMBA_LIBEXECDIR}') + +bld.SAMBA3_BINARY('rpcd_classic', + source='rpcd_classic.c', + deps=''' + CMDLINE_S3 + RPC_WORKER + RPC_SERVICE + RPC_SOCK_HELPER + smbd_base + ''', + install_path='${SAMBA_LIBEXECDIR}') + +bld.SAMBA3_BINARY('rpcd_lsad', + source='rpcd_lsad.c', + deps=''' + CMDLINE_S3 + RPC_WORKER + RPC_LSARPC + RPC_SAMR + RPC_DSSETUP + RPC_NETLOGON + RPC_SOCK_HELPER + smbd_base + ''', + install_path='${SAMBA_LIBEXECDIR}') + +bld.SAMBA3_BINARY('rpcd_winreg', + source='rpcd_winreg.c', + deps=''' + CMDLINE_S3 + RPC_WORKER + RPC_WINREG + smbd_base + ''', + install_path='${SAMBA_LIBEXECDIR}') + +bld.SAMBA3_BINARY('rpcd_spoolss', + source='rpcd_spoolss.c', + deps=''' + CMDLINE_S3 + RPC_WORKER + RPC_SPOOLSS + smbd_base + ''', + install_path='${SAMBA_LIBEXECDIR}') + +bld.SAMBA3_BINARY('rpcd_epmapper', + source='rpcd_epmapper.c', + deps=''' + CMDLINE_S3 + RPC_WORKER + RPC_EPMAPPER + smbd_base + ''', + install_path='${SAMBA_LIBEXECDIR}') + +bld.SAMBA3_BINARY('rpcd_fsrvp', + source='rpcd_fsrvp.c', + deps=''' + CMDLINE_S3 + RPC_WORKER + RPC_FSS_AGENT + smbd_base + ''', + install_path='${SAMBA_LIBEXECDIR}') + bld.SAMBA3_SUBSYSTEM('RPC_CONFIG', source='rpc_config.c', deps='talloc') @@ -186,6 +259,15 @@ bld.SAMBA3_MODULE('rpc_mdssvc_module', internal_module=bld.SAMBA3_IS_STATIC_MODULE('rpc_mdssvc_module'), enabled=bld.SAMBA3_IS_ENABLED_MODULE('rpc_mdssvc_module')) +bld.SAMBA3_BINARY('rpcd_mdssvc', + source='rpcd_mdssvc.c ' + rpc_mdssvc_sources, + deps=''' + CMDLINE_S3 + RPC_WORKER + smbd_base + ''' + rpc_mdssvc_deps, + install_path='${SAMBA_LIBEXECDIR}') + # RPC_SERVICE bld.SAMBA3_SUBSYSTEM('RPC_SERVER_REGISTER', source='rpc_ep_register.c ../librpc/rpc/dcerpc_ep.c',