$self->pidl("static NTSTATUS $name\__check_register_in_endpoint(const char *name, struct dcerpc_binding *binding) {");
$self->indent();
$self->pidl("enum dcerpc_transport_t transport = dcerpc_binding_get_transport(binding);");
+ $self->pidl("NTSTATUS status;");
$self->pidl("");
$self->pidl("/* If service is disabled, do not register */");
$self->pidl("if (rpc_service_mode(name) == RPC_SERVICE_MODE_DISABLED) {");
$self->pidl("return NT_STATUS_NOT_SUPPORTED;");
$self->deindent();
$self->pidl("}");
+
+ $self->pidl("");
+ $self->pidl("/*");
+ $self->pidl(" * If rpc service is external then change the default ncalrpc endpoint,");
+ $self->pidl(" * otherwise if the rpc daemon running this service is configured in");
+ $self->pidl(" * fork mode the forked process will race with main smbd to accept the");
+ $self->pidl(" * connections in the default ncalrpc socket, and the forked process");
+ $self->pidl(" * may not have the requested interface registered.");
+ $self->pidl(" * For example, in the ad_member test environment:");
+ $self->pidl(" *");
+ $self->pidl(" * rpc_server:lsarpc = external");
+ $self->pidl(" * rpc_server:samr = external");
+ $self->pidl(" * rpc_server:netlogon = disabled");
+ $self->pidl(" * rpc_daemon:lsasd = fork");
+ $self->pidl(" *");
+ $self->pidl(" * With these settings both, the main smbd and all the preforked lsasd");
+ $self->pidl(" * processes would be listening in the default ncalrpc socket if it is");
+ $self->pidl(" * not changed. If a client connection is accepted by one of the lsasd");
+ $self->pidl(" * worker processes and the client asks for an interface not registered");
+ $self->pidl(" * in these processes (winreg for example) it will get an error.");
+ $self->pidl(" */");
+ $self->pidl("if (rpc_service_mode(name) == RPC_SERVICE_MODE_EXTERNAL && transport == NCALRPC) {");
+ $self->indent();
+ $self->pidl("status = dcerpc_binding_set_string_option(binding, \"endpoint\", \"$uname\");");
+ $self->pidl("if (!NT_STATUS_IS_OK(status)) {");
+ $self->indent();
+ $self->pidl("return status;");
+ $self->deindent();
+ $self->pidl("}");
+ $self->deindent();
+ $self->pidl("}");
+
$self->pidl("");
$self->pidl("return NT_STATUS_OK;");
$self->deindent();
$self->pidl("uint32_t i;");
$self->pidl("NTSTATUS ret;");
$self->pidl("struct dcerpc_binding *binding;");
+ $self->pidl("struct dcerpc_binding *binding2 = NULL;");
$self->pidl("");
$self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_NCACN_NP_SECONDARY_ENDPOINT");
$self->pidl("const char *ncacn_np_secondary_endpoint = DCESRV_INTERFACE_$uname\_NCACN_NP_SECONDARY_ENDPOINT;");
$self->pidl("continue;");
$self->deindent();
$self->pidl("}");
- $self->pidl("talloc_free(binding);");
$self->pidl("");
- $self->pidl("ret = dcesrv_interface_register(dce_ctx, name, ncacn_np_secondary_endpoint, &dcesrv_$name\_interface, NULL);");
+
+ $self->pidl("if (ncacn_np_secondary_endpoint != NULL) {");
+ $self->indent();
+ $self->pidl("ret = dcerpc_parse_binding(dce_ctx, ncacn_np_secondary_endpoint, &binding2);");
+ $self->pidl("if (NT_STATUS_IS_ERR(ret)) {");
+ $self->indent();
+ $self->pidl("DBG_ERR(\"Failed to parse 2nd binding string \'%s\'\\n\", ncacn_np_secondary_endpoint);");
+ $self->pidl("TALLOC_FREE(binding);");
+ $self->pidl("return ret;");
+ $self->deindent();
+ $self->pidl("}");
+ $self->deindent();
+ $self->pidl("}");
+ $self->pidl("");
+
+ $self->pidl("ret = dcesrv_interface_register_b(dce_ctx, binding, binding2, &dcesrv_$name\_interface, NULL);");
+ $self->pidl("TALLOC_FREE(binding);");
+ $self->pidl("TALLOC_FREE(binding2);");
$self->pidl("if (!NT_STATUS_IS_OK(ret)) {");
$self->indent();
$self->pidl("DBG_ERR(\"Failed to register endpoint \'%s\'\\n\",name);");
}
static NTSTATUS find_ncalrpc_default_endpoint(struct dcesrv_context *dce_ctx,
- struct dcesrv_endpoint **ep)
+ const struct ndr_interface_table *ndr_table,
+ struct dcesrv_endpoint **ep)
{
TALLOC_CTX *tmp_ctx = NULL;
struct dcerpc_binding *binding = NULL;
return NT_STATUS_NO_MEMORY;
}
+ if (rpc_service_mode(ndr_table->name) == RPC_SERVICE_MODE_EXTERNAL) {
+ ep_description = talloc_asprintf(tmp_ctx, "ncalrpc:[%s]",
+ talloc_strdup_upper(tmp_ctx, ndr_table->name));
+ if (ep_description == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+
+ status = dcerpc_parse_binding(tmp_ctx, ep_description, &binding);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ status = dcesrv_find_endpoint(dce_ctx, binding, ep);
+ if (NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+ }
+
/*
* Some services use a rpcint binding handle in their initialization,
* before the server is fully initialized. Search the NCALRPC endpoint
conn->preferred_transfer = &ndr_transfer_syntax_ndr;
conn->transport.private_data = ncacn_conn;
- status = find_ncalrpc_default_endpoint(conn->dce_ctx, &endpoint);
+ status = find_ncalrpc_default_endpoint(conn->dce_ctx, ndr_table, &endpoint);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}