s3/lib: add parent_smb_fname()
[vlendec/samba-autobuild/.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 #include "librpc/ndr/ndr_table.h"
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
34
35 static struct pipes_struct *InternalPipes;
36
37 /* TODO
38  * the following prototypes are declared here to avoid
39  * code being moved about too much for a patch to be
40  * disrupted / less obvious.
41  *
42  * these functions, and associated functions that they
43  * call, should be moved behind a .so module-loading
44  * system _anyway_.  so that's the next step...
45  */
46
47 int make_base_pipes_struct(TALLOC_CTX *mem_ctx,
48                            struct messaging_context *msg_ctx,
49                            const char *pipe_name,
50                            enum dcerpc_transport_t transport,
51                            bool endian,
52                            const struct tsocket_address *remote_address,
53                            const struct tsocket_address *local_address,
54                            struct pipes_struct **_p)
55 {
56         struct pipes_struct *p;
57
58         p = talloc_zero(mem_ctx, struct pipes_struct);
59         if (!p) {
60                 return ENOMEM;
61         }
62
63         p->mem_ctx = talloc_named(p, 0, "pipe %s %p", pipe_name, p);
64         if (!p->mem_ctx) {
65                 talloc_free(p);
66                 return ENOMEM;
67         }
68
69         p->msg_ctx = msg_ctx;
70         p->transport = transport;
71         p->endian = endian;
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_old {
131         struct dcesrv_handle_old *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_old *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 persistent 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                           ndr_interface_name(&syntax->uuid,
222                                              syntax->if_version)));
223         }
224
225         /*
226          * One more pipe is using this list.
227          */
228
229         hl->pipe_ref_count++;
230
231         /*
232          * Point this pipe at this list.
233          */
234
235         p->pipe_handles = hl;
236
237         DEBUG(10,("init_pipe_handle_list: pipe_handles ref count = %lu for "
238                   "pipe %s\n", (unsigned long)p->pipe_handles->pipe_ref_count,
239                   ndr_interface_name(&syntax->uuid, syntax->if_version)));
240
241         return True;
242 }
243
244 /****************************************************************************
245   find first available policy slot.  creates a policy handle for you.
246
247   If "data_ptr" is given, this must be a talloc'ed object, create_policy_hnd
248   talloc_moves this into the handle. If the policy_hnd is closed,
249   data_ptr is TALLOC_FREE()'ed
250 ****************************************************************************/
251
252 static struct dcesrv_handle_old *create_rpc_handle_internal(
253                                 struct pipes_struct *p,
254                                 struct policy_handle *hnd,
255                                 uint8_t handle_type,
256                                 void *data_ptr)
257 {
258         struct dcesrv_handle_old *rpc_hnd = NULL;
259         static uint32_t pol_hnd_low  = 0;
260         static uint32_t pol_hnd_high = 0;
261         time_t t = time(NULL);
262
263         if (p->pipe_handles->count > MAX_OPEN_POLS) {
264                 DEBUG(0,("create_policy_hnd: ERROR: too many handles (%d) on this pipe.\n",
265                                 (int)p->pipe_handles->count));
266                 return NULL;
267         }
268
269         rpc_hnd = talloc_zero(p->pipe_handles, struct dcesrv_handle_old);
270         if (!rpc_hnd) {
271                 DEBUG(0,("create_policy_hnd: ERROR: out of memory!\n"));
272                 return NULL;
273         }
274
275         if (data_ptr != NULL) {
276                 rpc_hnd->data = talloc_move(rpc_hnd, &data_ptr);
277         }
278
279         pol_hnd_low++;
280         if (pol_hnd_low == 0) {
281                 pol_hnd_high++;
282         }
283
284         SIVAL(&rpc_hnd->wire_handle.handle_type, 0 , handle_type);
285
286         /* second bit is incrementing */
287         SIVAL(&rpc_hnd->wire_handle.uuid.time_low, 0 , pol_hnd_low);
288         SSVAL(&rpc_hnd->wire_handle.uuid.time_mid, 0 , pol_hnd_high);
289         SSVAL(&rpc_hnd->wire_handle.uuid.time_hi_and_version, 0, (pol_hnd_high >> 16));
290
291         /* split the current time into two 16 bit values */
292
293         /* something random */
294         SSVAL(rpc_hnd->wire_handle.uuid.clock_seq, 0, (t >> 16));
295         /* something random */
296         SSVAL(rpc_hnd->wire_handle.uuid.node, 0, t);
297         /* something more random */
298         SIVAL(rpc_hnd->wire_handle.uuid.node, 2, getpid());
299
300         DLIST_ADD(p->pipe_handles->handles, rpc_hnd);
301         p->pipe_handles->count++;
302
303         *hnd = rpc_hnd->wire_handle;
304
305         DEBUG(6, ("Opened policy hnd[%d] ", (int)p->pipe_handles->count));
306         dump_data(6, (uint8_t *)hnd, sizeof(*hnd));
307
308         return rpc_hnd;
309 }
310
311 bool create_policy_hnd(struct pipes_struct *p,
312                         struct policy_handle *hnd,
313                         uint8_t handle_type,
314                         void *data_ptr)
315 {
316         struct dcesrv_handle_old *rpc_hnd = NULL;
317
318         rpc_hnd = create_rpc_handle_internal(p, hnd, handle_type, data_ptr);
319         if (rpc_hnd == NULL) {
320                 return false;
321         }
322         return true;
323 }
324
325 /****************************************************************************
326   find policy by handle - internal version.
327 ****************************************************************************/
328
329 static struct dcesrv_handle_old *find_policy_by_hnd_internal(struct pipes_struct *p,
330                                 const struct policy_handle *hnd, void **data_p)
331 {
332         struct dcesrv_handle_old *h = NULL;
333         unsigned int count;
334
335         if (data_p) {
336                 *data_p = NULL;
337         }
338
339         count = 0;
340         for (h = p->pipe_handles->handles; h != NULL; h = h->next) {
341                 if (memcmp(&h->wire_handle, hnd, sizeof(*hnd)) == 0) {
342                         DEBUG(6,("Found policy hnd[%u] ", count));
343                         dump_data(6, (const uint8_t *)hnd, sizeof(*hnd));
344                         if (data_p) {
345                                 *data_p = h->data;
346                         }
347                         return h;
348                 }
349                 count++;
350         }
351
352         DEBUG(4,("Policy not found: "));
353         dump_data(4, (const uint8_t *)hnd, sizeof(*hnd));
354
355         p->fault_state = DCERPC_FAULT_CONTEXT_MISMATCH;
356
357         return NULL;
358 }
359
360 /****************************************************************************
361   find policy by handle
362 ****************************************************************************/
363
364 bool find_policy_by_hnd(struct pipes_struct *p, const struct policy_handle *hnd,
365                         void **data_p)
366 {
367         struct dcesrv_handle_old *rpc_hnd = NULL;
368
369         rpc_hnd = find_policy_by_hnd_internal(p, hnd, data_p);
370         if (rpc_hnd == NULL) {
371                 return false;
372         }
373         return true;
374 }
375
376 /****************************************************************************
377   Close a policy.
378 ****************************************************************************/
379
380 bool close_policy_hnd(struct pipes_struct *p, struct policy_handle *hnd)
381 {
382         struct dcesrv_handle_old *rpc_hnd = NULL;
383
384         rpc_hnd = find_policy_by_hnd_internal(p, hnd, NULL);
385
386         if (rpc_hnd == NULL) {
387                 DEBUG(3, ("Error closing policy (policy not found)\n"));
388                 return false;
389         }
390
391         DEBUG(6,("Closed policy\n"));
392
393         p->pipe_handles->count--;
394
395         DLIST_REMOVE(p->pipe_handles->handles, rpc_hnd);
396         TALLOC_FREE(rpc_hnd);
397
398         return true;
399 }
400
401 /****************************************************************************
402  Close a pipe - free the handle set if it was the last pipe reference.
403 ****************************************************************************/
404
405 void close_policy_by_pipe(struct pipes_struct *p)
406 {
407         if (p->pipe_handles == NULL) {
408                 return;
409         }
410
411         p->pipe_handles->pipe_ref_count--;
412
413         if (p->pipe_handles->pipe_ref_count == 0) {
414                 /*
415                  * Last pipe open on this list - free the list.
416                  */
417                 TALLOC_FREE(p->pipe_handles);
418
419                 DBG_DEBUG("Deleted handle list for RPC connection %s\n",
420                                 p->contexts ?
421                                 ndr_interface_name(&p->contexts->syntax.uuid,
422                                         p->contexts->syntax.if_version) :
423                                 "Unknown");
424         }
425 }
426
427 /*******************************************************************
428 Shall we allow access to this rpc?  Currently this function
429 implements the 'restrict anonymous' setting by denying access to
430 anonymous users if the restrict anonymous level is > 0.  Further work
431 will be checking a security descriptor to determine whether a user
432 token has enough access to access the pipe.
433 ********************************************************************/
434
435 bool pipe_access_check(struct pipes_struct *p)
436 {
437         /* Don't let anonymous users access this RPC if restrict
438            anonymous > 0 */
439
440         if (lp_restrict_anonymous() > 0) {
441
442                 /* schannel, so we must be ok */
443                 if (p->pipe_bound &&
444                     (p->auth.auth_type == DCERPC_AUTH_TYPE_SCHANNEL)) {
445                         return True;
446                 }
447
448                 if (security_session_user_level(p->session_info, NULL) < SECURITY_USER) {
449                         return False;
450                 }
451         }
452
453         return True;
454 }
455
456 void *_policy_handle_create(struct pipes_struct *p,
457                         struct policy_handle *hnd,
458                         uint8_t handle_type,
459                         uint32_t access_granted,
460                         size_t data_size,
461                         const char *type,
462                         NTSTATUS *pstatus)
463 {
464         struct dcesrv_handle_old *rpc_hnd = NULL;
465         void *data;
466
467         if (p->pipe_handles->count > MAX_OPEN_POLS) {
468                 DEBUG(0, ("ERROR: Too many handles (%d) for RPC connection %s\n",
469                           (int) p->pipe_handles->count,
470                           ndr_interface_name(&p->contexts->syntax.uuid,
471                                              p->contexts->syntax.if_version)));
472
473                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
474                 return NULL;
475         }
476
477         data = talloc_size(talloc_tos(), data_size);
478         if (data == NULL) {
479                 *pstatus = NT_STATUS_NO_MEMORY;
480                 return NULL;
481         }
482         talloc_set_name_const(data, type);
483
484         rpc_hnd = create_rpc_handle_internal(p, hnd, handle_type, data);
485         if (rpc_hnd == NULL) {
486                 TALLOC_FREE(data);
487                 *pstatus = NT_STATUS_NO_MEMORY;
488                 return NULL;
489         }
490         rpc_hnd->access_granted = access_granted;
491         *pstatus = NT_STATUS_OK;
492         return data;
493 }
494
495 void *_policy_handle_find(struct pipes_struct *p,
496                           const struct policy_handle *hnd,
497                           uint32_t access_required,
498                           uint32_t *paccess_granted,
499                           const char *name, const char *location,
500                           NTSTATUS *pstatus)
501 {
502         struct dcesrv_handle_old *rpc_hnd = NULL;
503         void *data;
504
505         rpc_hnd = find_policy_by_hnd_internal(p, hnd, &data);
506         if (rpc_hnd == NULL) {
507                 *pstatus = NT_STATUS_INVALID_HANDLE;
508                 return NULL;
509         }
510         if (strcmp(name, talloc_get_name(data)) != 0) {
511                 DEBUG(10, ("expected %s, got %s\n", name,
512                            talloc_get_name(data)));
513                 *pstatus = NT_STATUS_INVALID_HANDLE;
514                 return NULL;
515         }
516         if ((access_required & rpc_hnd->access_granted) != access_required) {
517                 if (root_mode()) {
518                         DEBUG(4, ("%s: ACCESS should be DENIED (granted: "
519                                   "%#010x; required: %#010x)\n", location,
520                                   rpc_hnd->access_granted, access_required));
521                         DEBUGADD(4,("but overwritten by euid == 0\n"));
522                         goto okay;
523                 }
524                 DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: "
525                          "%#010x)\n", location, rpc_hnd->access_granted,
526                          access_required));
527                 *pstatus = NT_STATUS_ACCESS_DENIED;
528                 return NULL;
529         }
530
531  okay:
532         DEBUG(10, ("found handle of type %s\n", talloc_get_name(data)));
533         if (paccess_granted != NULL) {
534                 *paccess_granted = rpc_hnd->access_granted;
535         }
536         *pstatus = NT_STATUS_OK;
537         return data;
538 }