s3:utils: Fix 'Usage:' for 'net ads enctypes'
[samba4-gss.git] / source3 / rpc_server / rpc_server.c
blob73fafa635cd268421d86100d28f4a0c48866555e
1 /*
2 Unix SMB/Netbios implementation.
3 Generic infrstructure for RPC Daemons
4 Copyright (C) Simo Sorce 2010
5 Copyright (C) Andrew Bartlett 2011
6 Copyright (C) Andreas Schneider 2011
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "librpc/rpc/dcesrv_core.h"
24 #include "rpc_server/rpc_pipes.h"
25 #include "rpc_server/rpc_server.h"
26 #include "rpc_server/rpc_config.h"
27 #include "rpc_dce.h"
28 #include "librpc/gen_ndr/netlogon.h"
29 #include "librpc/gen_ndr/auth.h"
30 #include "lib/tsocket/tsocket.h"
31 #include "libcli/named_pipe_auth/npa_tstream.h"
32 #include "../auth/auth_sam_reply.h"
33 #include "auth.h"
34 #include "rpc_server/rpc_ncacn_np.h"
35 #include "rpc_server/srv_pipe_hnd.h"
36 #include "lib/util/idtree_random.h"
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_RPC_SRV
41 /* Start listening on the appropriate unix socket and setup all is needed to
42 * dispatch requests to the pipes rpc implementation */
44 struct dcerpc_ncacn_listen_state {
45 int fd;
47 struct tevent_context *ev_ctx;
48 struct messaging_context *msg_ctx;
49 struct dcesrv_context *dce_ctx;
50 struct dcesrv_endpoint *endpoint;
51 dcerpc_ncacn_termination_fn termination_fn;
52 void *termination_data;
55 static void ncacn_terminate_connection(struct dcerpc_ncacn_conn *conn,
56 const char *reason);
58 NTSTATUS dcesrv_auth_gensec_prepare(
59 TALLOC_CTX *mem_ctx,
60 struct dcesrv_call_state *call,
61 struct gensec_security **out,
62 void *private_data)
64 struct gensec_security *gensec = NULL;
65 NTSTATUS status;
67 if (out == NULL) {
68 return NT_STATUS_INVALID_PARAMETER;
71 status = auth_generic_prepare(mem_ctx,
72 call->conn->remote_address,
73 call->conn->local_address,
74 "DCE/RPC",
75 &gensec);
76 if (!NT_STATUS_IS_OK(status)) {
77 DBG_ERR("Failed to prepare gensec: %s\n", nt_errstr(status));
78 return status;
81 *out = gensec;
83 return NT_STATUS_OK;
86 void dcesrv_log_successful_authz(
87 struct dcesrv_call_state *call,
88 void *private_data)
90 TALLOC_CTX *frame = talloc_stackframe();
91 struct auth4_context *auth4_context = NULL;
92 struct dcesrv_auth *auth = call->auth_state;
93 enum dcerpc_transport_t transport = dcerpc_binding_get_transport(
94 call->conn->endpoint->ep_description);
95 const char *auth_type = derpc_transport_string_by_transport(transport);
96 const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
97 NTSTATUS status;
99 if (frame == NULL) {
100 DBG_ERR("No memory\n");
101 return;
104 if (transport == NCACN_NP) {
105 transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
108 become_root();
109 status = make_auth4_context(frame, &auth4_context);
110 unbecome_root();
111 if (!NT_STATUS_IS_OK(status)) {
112 DBG_ERR("Unable to make auth context for authz log.\n");
113 TALLOC_FREE(frame);
114 return;
118 * Log the authorization to this RPC interface. This
119 * covered ncacn_np pass-through auth, and anonymous
120 * DCE/RPC (eg epmapper, netlogon etc)
122 log_successful_authz_event(auth4_context->msg_ctx,
123 auth4_context->lp_ctx,
124 call->conn->remote_address,
125 call->conn->local_address,
126 "DCE/RPC",
127 auth_type,
128 transport_protection,
129 auth->session_info,
130 NULL /* client_audit_info */,
131 NULL /* server_audit_info */);
133 auth->auth_audited = true;
135 TALLOC_FREE(frame);
138 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
140 int ret;
142 dcesrv_assoc_group_common_destructor(assoc_group);
144 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr,
145 assoc_group->id);
146 if (ret != 0) {
147 DBG_ERR("Failed to remove assoc_group 0x%08x\n",
148 assoc_group->id);
150 return 0;
153 static NTSTATUS dcesrv_assoc_group_new(struct dcesrv_call_state *call)
155 struct dcesrv_connection *conn = call->conn;
156 struct dcesrv_context *dce_ctx = conn->dce_ctx;
157 const struct dcesrv_endpoint *endpoint = conn->endpoint;
158 enum dcerpc_transport_t transport =
159 dcerpc_binding_get_transport(endpoint->ep_description);
160 struct dcesrv_assoc_group *assoc_group = NULL;
161 int id;
163 assoc_group = talloc_zero(conn, struct dcesrv_assoc_group);
164 if (assoc_group == NULL) {
165 return NT_STATUS_NO_MEMORY;
168 id = idr_get_new_random(dce_ctx->assoc_groups_idr,
169 assoc_group,
171 UINT16_MAX);
172 if (id == -1) {
173 TALLOC_FREE(assoc_group);
174 DBG_ERR("Out of association groups!\n");
175 return NT_STATUS_RPC_OUT_OF_RESOURCES;
178 assoc_group->transport = transport;
179 assoc_group->id = id;
180 assoc_group->dce_ctx = dce_ctx;
182 call->conn->assoc_group = assoc_group;
184 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
186 return NT_STATUS_OK;
189 static NTSTATUS dcesrv_assoc_group_reference(struct dcesrv_call_state *call,
190 uint32_t assoc_group_id)
192 struct dcesrv_connection *conn = call->conn;
193 const struct dcesrv_endpoint *endpoint = conn->endpoint;
194 enum dcerpc_transport_t transport =
195 dcerpc_binding_get_transport(endpoint->ep_description);
196 struct dcesrv_assoc_group *assoc_group = NULL;
197 void *id_ptr = NULL;
199 /* find an association group given a assoc_group_id */
200 id_ptr = idr_find(conn->dce_ctx->assoc_groups_idr, assoc_group_id);
201 if (id_ptr == NULL) {
203 * FIXME If the association group is not found it has
204 * been created in other process (preforking daemons).
205 * Until this is properly fixed we just create a new
206 * association group in this process
208 DBG_NOTICE("Failed to find assoc_group 0x%08x in this "
209 "server process, creating a new one\n",
210 assoc_group_id);
211 return dcesrv_assoc_group_new(call);
213 assoc_group = talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
215 if (assoc_group->transport != transport) {
216 const char *at =
217 derpc_transport_string_by_transport(
218 assoc_group->transport);
219 const char *ct =
220 derpc_transport_string_by_transport(
221 transport);
223 DBG_NOTICE("assoc_group 0x%08x (transport %s) "
224 "is not available on transport %s\n",
225 assoc_group_id, at, ct);
226 return NT_STATUS_UNSUCCESSFUL;
229 conn->assoc_group = talloc_reference(conn, assoc_group);
230 return NT_STATUS_OK;
233 NTSTATUS dcesrv_assoc_group_find(
234 struct dcesrv_call_state *call,
235 void *private_data)
237 uint32_t assoc_group_id = call->pkt.u.bind.assoc_group_id;
239 if (assoc_group_id != 0) {
240 return dcesrv_assoc_group_reference(call, assoc_group_id);
243 /* If not requested by client create a new association group */
244 return dcesrv_assoc_group_new(call);
247 void dcesrv_transport_terminate_connection(struct dcesrv_connection *dce_conn,
248 const char *reason)
250 struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
251 dce_conn->transport.private_data,
252 struct dcerpc_ncacn_conn);
254 ncacn_terminate_connection(ncacn_conn, reason);
257 static void ncacn_terminate_connection(struct dcerpc_ncacn_conn *conn,
258 const char *reason)
260 if (reason == NULL) {
261 reason = "Unknown reason";
264 DBG_NOTICE("Terminating connection - '%s'\n", reason);
266 talloc_free(conn);
269 NTSTATUS dcesrv_endpoint_by_ncacn_np_name(struct dcesrv_context *dce_ctx,
270 const char *pipe_name,
271 struct dcesrv_endpoint **out)
273 struct dcesrv_endpoint *e = NULL;
275 for (e = dce_ctx->endpoint_list; e; e = e->next) {
276 enum dcerpc_transport_t transport =
277 dcerpc_binding_get_transport(e->ep_description);
278 const char *endpoint = NULL;
280 if (transport != NCACN_NP) {
281 continue;
284 endpoint = dcerpc_binding_get_string_option(e->ep_description,
285 "endpoint");
286 if (endpoint == NULL) {
287 continue;
290 if (strncmp(endpoint, "\\pipe\\", 6) == 0) {
291 endpoint += 6;
294 if (strequal(endpoint, pipe_name)) {
295 *out = e;
296 return NT_STATUS_OK;
300 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
303 struct pipes_struct *dcesrv_get_pipes_struct(struct dcesrv_connection *conn)
305 struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
306 conn->transport.private_data,
307 struct dcerpc_ncacn_conn);
309 return &ncacn_conn->p;
312 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */