d547f18dc1e5ccb053b7570198f235d89ee60d3e
[kai/samba.git] / source3 / rpc_server / rpc_handles.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-1997,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
6  *  Copyright (C) Jeremy Allison                           2001.
7  *  
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.
12  *  
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.
17  *  
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/>.
20  */
21
22 #include "includes.h"
23 #include "system/passwd.h" /* uid_wrapper */
24 #include "../librpc/gen_ndr/ndr_lsa.h"
25 #include "../librpc/gen_ndr/ndr_samr.h"
26 #include "auth.h"
27 #include "rpc_server/rpc_pipes.h"
28 #include "../libcli/security/security.h"
29 #include "lib/tsocket/tsocket.h"
30
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_RPC_SRV
33
34 static struct pipes_struct *InternalPipes;
35
36 /* TODO
37  * the following prototypes are declared here to avoid
38  * code being moved about too much for a patch to be
39  * disrupted / less obvious.
40  *
41  * these functions, and associated functions that they
42  * call, should be moved behind a .so module-loading
43  * system _anyway_.  so that's the next step...
44  */
45
46 int make_base_pipes_struct(TALLOC_CTX *mem_ctx,
47                            struct messaging_context *msg_ctx,
48                            const char *pipe_name,
49                            enum dcerpc_transport_t transport,
50                            bool endian, bool ncalrpc_as_system,
51                            const struct tsocket_address *remote_address,
52                            const struct tsocket_address *local_address,
53                            struct pipes_struct **_p)
54 {
55         struct pipes_struct *p;
56
57         p = talloc_zero(mem_ctx, struct pipes_struct);
58         if (!p) {
59                 return ENOMEM;
60         }
61
62         p->mem_ctx = talloc_named(p, 0, "pipe %s %p", pipe_name, p);
63         if (!p->mem_ctx) {
64                 talloc_free(p);
65                 return ENOMEM;
66         }
67
68         p->msg_ctx = msg_ctx;
69         p->transport = transport;
70         p->endian = endian;
71         p->ncalrpc_as_system = ncalrpc_as_system;
72
73         p->remote_address = tsocket_address_copy(remote_address, p);
74         if (p->remote_address == NULL) {
75                 talloc_free(p);
76                 return ENOMEM;
77         }
78
79         if (local_address) {
80                 p->local_address = tsocket_address_copy(local_address, p);
81                 if (p->local_address == NULL) {
82                         talloc_free(p);
83                         return ENOMEM;
84                 }
85         }
86
87         DLIST_ADD(InternalPipes, p);
88         talloc_set_destructor(p, close_internal_rpc_pipe_hnd);
89
90         *_p = p;
91         return 0;
92 }
93
94
95 bool check_open_pipes(void)
96 {
97         struct pipes_struct *p;
98
99         for (p = InternalPipes; p != NULL; p = p->next) {
100                 if (num_pipe_handles(p) != 0) {
101                         return true;
102                 }
103         }
104         return false;
105 }
106
107 /****************************************************************************
108  Close an rpc pipe.
109 ****************************************************************************/
110
111 int close_internal_rpc_pipe_hnd(struct pipes_struct *p)
112 {
113         if (!p) {
114                 DEBUG(0,("Invalid pipe in close_internal_rpc_pipe_hnd\n"));
115                 return False;
116         }
117
118         /* Free the handles database. */
119         close_policy_by_pipe(p);
120
121         DLIST_REMOVE(InternalPipes, p);
122
123         return 0;
124 }
125
126 /*
127  * Handle database - stored per pipe.
128  */
129
130 struct dcesrv_handle {
131         struct dcesrv_handle *prev, *next;
132         struct policy_handle wire_handle;
133         uint32_t access_granted;
134         void *data;
135 };
136
137 struct handle_list {
138         struct dcesrv_handle *handles;  /* List of pipe handles. */
139         size_t count;                   /* Current number of handles. */
140         size_t pipe_ref_count;          /* Number of pipe handles referring
141                                          * to this tree. */
142 };
143
144 /* This is the max handles across all instances of a pipe name. */
145 #ifndef MAX_OPEN_POLS
146 #define MAX_OPEN_POLS 2048
147 #endif
148
149 /****************************************************************************
150  Hack as handles need to be persisant over lsa pipe closes so long as a samr
151  pipe is open. JRA.
152 ****************************************************************************/
153
154 static bool is_samr_lsa_pipe(const struct ndr_syntax_id *syntax)
155 {
156         return (ndr_syntax_id_equal(syntax, &ndr_table_samr.syntax_id)
157                 || ndr_syntax_id_equal(syntax, &ndr_table_lsarpc.syntax_id));
158 }
159
160 size_t num_pipe_handles(struct pipes_struct *p)
161 {
162         if (p->pipe_handles == NULL) {
163                 return 0;
164         }
165         return p->pipe_handles->count;
166 }
167
168 /****************************************************************************
169  Initialise a policy handle list on a pipe. Handle list is shared between all
170  pipes of the same name.
171 ****************************************************************************/
172
173 bool init_pipe_handles(struct pipes_struct *p, const struct ndr_syntax_id *syntax)
174 {
175         struct pipes_struct *plist;
176         struct handle_list *hl;
177
178         for (plist = InternalPipes; plist; plist = plist->next) {
179                 struct pipe_rpc_fns *p_ctx;
180                 bool stop = false;
181
182                 for (p_ctx = plist->contexts;
183                      p_ctx != NULL;
184                      p_ctx = p_ctx->next) {
185                         if (ndr_syntax_id_equal(syntax, &p_ctx->syntax)) {
186                                 stop = true;
187                                 break;
188                         }
189                         if (is_samr_lsa_pipe(&p_ctx->syntax)
190                             && is_samr_lsa_pipe(syntax)) {
191                                 /*
192                                  * samr and lsa share a handle space (same process
193                                  * under Windows?)
194                                  */
195                                 stop = true;
196                                 break;
197                         }
198                 }
199
200                 if (stop) {
201                         break;
202                 }
203         }
204
205         if (plist != NULL) {
206                 hl = plist->pipe_handles;
207                 if (hl == NULL) {
208                         return false;
209                 }
210         } else {
211                 /*
212                  * First open, we have to create the handle list
213                  */
214                 hl = talloc_zero(NULL, struct handle_list);
215                 if (hl == NULL) {
216                         return false;
217                 }
218
219                 DEBUG(10,("init_pipe_handle_list: created handle list for "
220                           "pipe %s\n",
221                           get_pipe_name_from_syntax(talloc_tos(), syntax)));
222         }
223
224         /*
225          * One more pipe is using this list.
226          */
227
228         hl->pipe_ref_count++;
229
230         /*
231          * Point this pipe at this list.
232          */
233
234         p->pipe_handles = hl;
235
236         DEBUG(10,("init_pipe_handle_list: pipe_handles ref count = %lu for "
237                   "pipe %s\n", (unsigned long)p->pipe_handles->pipe_ref_count,
238                   get_pipe_name_from_syntax(talloc_tos(), syntax)));
239
240         return True;
241 }
242
243 /****************************************************************************
244   find first available policy slot.  creates a policy handle for you.
245
246   If "data_ptr" is given, this must be a talloc'ed object, create_policy_hnd
247   talloc_moves this into the handle. If the policy_hnd is closed,
248   data_ptr is TALLOC_FREE()'ed
249 ****************************************************************************/
250
251 static struct dcesrv_handle *create_rpc_handle_internal(struct pipes_struct *p,
252                                 struct policy_handle *hnd, void *data_ptr)
253 {
254         struct dcesrv_handle *rpc_hnd;
255         static uint32 pol_hnd_low  = 0;
256         static uint32 pol_hnd_high = 0;
257         time_t t = time(NULL);
258
259         if (p->pipe_handles->count > MAX_OPEN_POLS) {
260                 DEBUG(0,("create_policy_hnd: ERROR: too many handles (%d) on this pipe.\n",
261                                 (int)p->pipe_handles->count));
262                 return NULL;
263         }
264
265         rpc_hnd = talloc_zero(p->pipe_handles, struct dcesrv_handle);
266         if (!rpc_hnd) {
267                 DEBUG(0,("create_policy_hnd: ERROR: out of memory!\n"));
268                 return NULL;
269         }
270
271         if (data_ptr != NULL) {
272                 rpc_hnd->data = talloc_move(rpc_hnd, &data_ptr);
273         }
274
275         pol_hnd_low++;
276         if (pol_hnd_low == 0) {
277                 pol_hnd_high++;
278         }
279
280         /* first bit must be null */
281         SIVAL(&rpc_hnd->wire_handle.handle_type, 0 , 0);
282
283         /* second bit is incrementing */
284         SIVAL(&rpc_hnd->wire_handle.uuid.time_low, 0 , pol_hnd_low);
285         SSVAL(&rpc_hnd->wire_handle.uuid.time_mid, 0 , pol_hnd_high);
286         SSVAL(&rpc_hnd->wire_handle.uuid.time_hi_and_version, 0, (pol_hnd_high >> 16));
287
288         /* split the current time into two 16 bit values */
289
290         /* something random */
291         SSVAL(rpc_hnd->wire_handle.uuid.clock_seq, 0, (t >> 16));
292         /* something random */
293         SSVAL(rpc_hnd->wire_handle.uuid.node, 0, t);
294         /* something more random */
295         SIVAL(rpc_hnd->wire_handle.uuid.node, 2, sys_getpid());
296
297         DLIST_ADD(p->pipe_handles->handles, rpc_hnd);
298         p->pipe_handles->count++;
299
300         *hnd = rpc_hnd->wire_handle;
301
302         DEBUG(4, ("Opened policy hnd[%d] ", (int)p->pipe_handles->count));
303         dump_data(4, (uint8_t *)hnd, sizeof(*hnd));
304
305         return rpc_hnd;
306 }
307
308 bool create_policy_hnd(struct pipes_struct *p, struct policy_handle *hnd,
309                        void *data_ptr)
310 {
311         struct dcesrv_handle *rpc_hnd;
312
313         rpc_hnd = create_rpc_handle_internal(p, hnd, data_ptr);
314         if (rpc_hnd == NULL) {
315                 return false;
316         }
317         return true;
318 }
319
320 /****************************************************************************
321   find policy by handle - internal version.
322 ****************************************************************************/
323
324 static struct dcesrv_handle *find_policy_by_hnd_internal(struct pipes_struct *p,
325                                 const struct policy_handle *hnd, void **data_p)
326 {
327         struct dcesrv_handle *h;
328         unsigned int count;
329
330         if (data_p) {
331                 *data_p = NULL;
332         }
333
334         count = 0;
335         for (h = p->pipe_handles->handles; h != NULL; h = h->next) {
336                 if (memcmp(&h->wire_handle, hnd, sizeof(*hnd)) == 0) {
337                         DEBUG(4,("Found policy hnd[%u] ", count));
338                         dump_data(4, (const uint8 *)hnd, sizeof(*hnd));
339                         if (data_p) {
340                                 *data_p = h->data;
341                         }
342                         return h;
343                 }
344                 count++;
345         }
346
347         DEBUG(4,("Policy not found: "));
348         dump_data(4, (const uint8_t *)hnd, sizeof(*hnd));
349
350         p->bad_handle_fault_state = true;
351
352         return NULL;
353 }
354
355 /****************************************************************************
356   find policy by handle
357 ****************************************************************************/
358
359 bool find_policy_by_hnd(struct pipes_struct *p, const struct policy_handle *hnd,
360                         void **data_p)
361 {
362         struct dcesrv_handle *rpc_hnd;
363
364         rpc_hnd = find_policy_by_hnd_internal(p, hnd, data_p);
365         if (rpc_hnd == NULL) {
366                 return false;
367         }
368         return true;
369 }
370
371 /****************************************************************************
372   Close a policy.
373 ****************************************************************************/
374
375 bool close_policy_hnd(struct pipes_struct *p, struct policy_handle *hnd)
376 {
377         struct dcesrv_handle *rpc_hnd;
378
379         rpc_hnd = find_policy_by_hnd_internal(p, hnd, NULL);
380
381         if (rpc_hnd == NULL) {
382                 DEBUG(3, ("Error closing policy (policy not found)\n"));
383                 return false;
384         }
385
386         DEBUG(3,("Closed policy\n"));
387
388         p->pipe_handles->count--;
389
390         DLIST_REMOVE(p->pipe_handles->handles, rpc_hnd);
391         TALLOC_FREE(rpc_hnd);
392
393         return true;
394 }
395
396 /****************************************************************************
397  Close a pipe - free the handle set if it was the last pipe reference.
398 ****************************************************************************/
399
400 void close_policy_by_pipe(struct pipes_struct *p)
401 {
402         if (p->pipe_handles == NULL) {
403                 return;
404         }
405
406         p->pipe_handles->pipe_ref_count--;
407
408         if (p->pipe_handles->pipe_ref_count == 0) {
409                 /*
410                  * Last pipe open on this list - free the list.
411                  */
412                 TALLOC_FREE(p->pipe_handles);
413
414                 DEBUG(10,("Deleted handle list for RPC connection %s\n",
415                           get_pipe_name_from_syntax(talloc_tos(),
416                                                     &p->contexts->syntax)));
417         }
418 }
419
420 /*******************************************************************
421 Shall we allow access to this rpc?  Currently this function
422 implements the 'restrict anonymous' setting by denying access to
423 anonymous users if the restrict anonymous level is > 0.  Further work
424 will be checking a security descriptor to determine whether a user
425 token has enough access to access the pipe.
426 ********************************************************************/
427
428 bool pipe_access_check(struct pipes_struct *p)
429 {
430         /* Don't let anonymous users access this RPC if restrict
431            anonymous > 0 */
432
433         if (lp_restrict_anonymous() > 0) {
434
435                 /* schannel, so we must be ok */
436                 if (p->pipe_bound &&
437                     (p->auth.auth_type == DCERPC_AUTH_TYPE_SCHANNEL)) {
438                         return True;
439                 }
440
441                 if (security_session_user_level(p->session_info, NULL) < SECURITY_USER) {
442                         return False;
443                 }
444         }
445
446         return True;
447 }
448
449 void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd,
450                             uint32_t access_granted, size_t data_size,
451                             const char *type, NTSTATUS *pstatus)
452 {
453         struct dcesrv_handle *rpc_hnd;
454         void *data;
455
456         if (p->pipe_handles->count > MAX_OPEN_POLS) {
457                 DEBUG(0, ("ERROR: Too many handles (%d) for RPC connection %s\n",
458                           (int) p->pipe_handles->count,
459                           get_pipe_name_from_syntax(talloc_tos(),
460                                                     &p->contexts->syntax)));
461                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
462                 return NULL;
463         }
464
465         data = talloc_size(talloc_tos(), data_size);
466         if (data == NULL) {
467                 *pstatus = NT_STATUS_NO_MEMORY;
468                 return NULL;
469         }
470         talloc_set_name_const(data, type);
471
472         rpc_hnd = create_rpc_handle_internal(p, hnd, data);
473         if (rpc_hnd == NULL) {
474                 TALLOC_FREE(data);
475                 *pstatus = NT_STATUS_NO_MEMORY;
476                 return NULL;
477         }
478         rpc_hnd->access_granted = access_granted;
479         *pstatus = NT_STATUS_OK;
480         return data;
481 }
482
483 void *_policy_handle_find(struct pipes_struct *p,
484                           const struct policy_handle *hnd,
485                           uint32_t access_required,
486                           uint32_t *paccess_granted,
487                           const char *name, const char *location,
488                           NTSTATUS *pstatus)
489 {
490         struct dcesrv_handle *rpc_hnd;
491         void *data;
492
493         rpc_hnd = find_policy_by_hnd_internal(p, hnd, &data);
494         if (rpc_hnd == NULL) {
495                 *pstatus = NT_STATUS_INVALID_HANDLE;
496                 return NULL;
497         }
498         if (strcmp(name, talloc_get_name(data)) != 0) {
499                 DEBUG(10, ("expected %s, got %s\n", name,
500                            talloc_get_name(data)));
501                 *pstatus = NT_STATUS_INVALID_HANDLE;
502                 return NULL;
503         }
504         if ((access_required & rpc_hnd->access_granted) != access_required) {
505                 if (geteuid() == sec_initial_uid()) {
506                         DEBUG(4, ("%s: ACCESS should be DENIED (granted: "
507                                   "%#010x; required: %#010x)\n", location,
508                                   rpc_hnd->access_granted, access_required));
509                         DEBUGADD(4,("but overwritten by euid == 0\n"));
510                         goto okay;
511                 }
512                 DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: "
513                          "%#010x)\n", location, rpc_hnd->access_granted,
514                          access_required));
515                 *pstatus = NT_STATUS_ACCESS_DENIED;
516                 return NULL;
517         }
518
519  okay:
520         DEBUG(10, ("found handle of type %s\n", talloc_get_name(data)));
521         if (paccess_granted != NULL) {
522                 *paccess_granted = rpc_hnd->access_granted;
523         }
524         *pstatus = NT_STATUS_OK;
525         return data;
526 }