Convert all uses of uint32/16/8 to _t in source3/rpc_server.
[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 #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 {
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                           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 *create_rpc_handle_internal(struct pipes_struct *p,
253                                 struct policy_handle *hnd, void *data_ptr)
254 {
255         struct dcesrv_handle *rpc_hnd;
256         static uint32_t pol_hnd_low  = 0;
257         static uint32_t pol_hnd_high = 0;
258         time_t t = time(NULL);
259
260         if (p->pipe_handles->count > MAX_OPEN_POLS) {
261                 DEBUG(0,("create_policy_hnd: ERROR: too many handles (%d) on this pipe.\n",
262                                 (int)p->pipe_handles->count));
263                 return NULL;
264         }
265
266         rpc_hnd = talloc_zero(p->pipe_handles, struct dcesrv_handle);
267         if (!rpc_hnd) {
268                 DEBUG(0,("create_policy_hnd: ERROR: out of memory!\n"));
269                 return NULL;
270         }
271
272         if (data_ptr != NULL) {
273                 rpc_hnd->data = talloc_move(rpc_hnd, &data_ptr);
274         }
275
276         pol_hnd_low++;
277         if (pol_hnd_low == 0) {
278                 pol_hnd_high++;
279         }
280
281         /* first bit must be null */
282         SIVAL(&rpc_hnd->wire_handle.handle_type, 0 , 0);
283
284         /* second bit is incrementing */
285         SIVAL(&rpc_hnd->wire_handle.uuid.time_low, 0 , pol_hnd_low);
286         SSVAL(&rpc_hnd->wire_handle.uuid.time_mid, 0 , pol_hnd_high);
287         SSVAL(&rpc_hnd->wire_handle.uuid.time_hi_and_version, 0, (pol_hnd_high >> 16));
288
289         /* split the current time into two 16 bit values */
290
291         /* something random */
292         SSVAL(rpc_hnd->wire_handle.uuid.clock_seq, 0, (t >> 16));
293         /* something random */
294         SSVAL(rpc_hnd->wire_handle.uuid.node, 0, t);
295         /* something more random */
296         SIVAL(rpc_hnd->wire_handle.uuid.node, 2, getpid());
297
298         DLIST_ADD(p->pipe_handles->handles, rpc_hnd);
299         p->pipe_handles->count++;
300
301         *hnd = rpc_hnd->wire_handle;
302
303         DEBUG(6, ("Opened policy hnd[%d] ", (int)p->pipe_handles->count));
304         dump_data(6, (uint8_t *)hnd, sizeof(*hnd));
305
306         return rpc_hnd;
307 }
308
309 bool create_policy_hnd(struct pipes_struct *p, struct policy_handle *hnd,
310                        void *data_ptr)
311 {
312         struct dcesrv_handle *rpc_hnd;
313
314         rpc_hnd = create_rpc_handle_internal(p, hnd, data_ptr);
315         if (rpc_hnd == NULL) {
316                 return false;
317         }
318         return true;
319 }
320
321 /****************************************************************************
322   find policy by handle - internal version.
323 ****************************************************************************/
324
325 static struct dcesrv_handle *find_policy_by_hnd_internal(struct pipes_struct *p,
326                                 const struct policy_handle *hnd, void **data_p)
327 {
328         struct dcesrv_handle *h;
329         unsigned int count;
330
331         if (data_p) {
332                 *data_p = NULL;
333         }
334
335         count = 0;
336         for (h = p->pipe_handles->handles; h != NULL; h = h->next) {
337                 if (memcmp(&h->wire_handle, hnd, sizeof(*hnd)) == 0) {
338                         DEBUG(6,("Found policy hnd[%u] ", count));
339                         dump_data(6, (const uint8_t *)hnd, sizeof(*hnd));
340                         if (data_p) {
341                                 *data_p = h->data;
342                         }
343                         return h;
344                 }
345                 count++;
346         }
347
348         DEBUG(4,("Policy not found: "));
349         dump_data(4, (const uint8_t *)hnd, sizeof(*hnd));
350
351         p->fault_state = DCERPC_FAULT_CONTEXT_MISMATCH;
352
353         return NULL;
354 }
355
356 /****************************************************************************
357   find policy by handle
358 ****************************************************************************/
359
360 bool find_policy_by_hnd(struct pipes_struct *p, const struct policy_handle *hnd,
361                         void **data_p)
362 {
363         struct dcesrv_handle *rpc_hnd;
364
365         rpc_hnd = find_policy_by_hnd_internal(p, hnd, data_p);
366         if (rpc_hnd == NULL) {
367                 return false;
368         }
369         return true;
370 }
371
372 /****************************************************************************
373   Close a policy.
374 ****************************************************************************/
375
376 bool close_policy_hnd(struct pipes_struct *p, struct policy_handle *hnd)
377 {
378         struct dcesrv_handle *rpc_hnd;
379
380         rpc_hnd = find_policy_by_hnd_internal(p, hnd, NULL);
381
382         if (rpc_hnd == NULL) {
383                 DEBUG(3, ("Error closing policy (policy not found)\n"));
384                 return false;
385         }
386
387         DEBUG(6,("Closed policy\n"));
388
389         p->pipe_handles->count--;
390
391         DLIST_REMOVE(p->pipe_handles->handles, rpc_hnd);
392         TALLOC_FREE(rpc_hnd);
393
394         return true;
395 }
396
397 /****************************************************************************
398  Close a pipe - free the handle set if it was the last pipe reference.
399 ****************************************************************************/
400
401 void close_policy_by_pipe(struct pipes_struct *p)
402 {
403         if (p->pipe_handles == NULL) {
404                 return;
405         }
406
407         p->pipe_handles->pipe_ref_count--;
408
409         if (p->pipe_handles->pipe_ref_count == 0) {
410                 /*
411                  * Last pipe open on this list - free the list.
412                  */
413                 TALLOC_FREE(p->pipe_handles);
414
415                 DEBUG(10,("Deleted handle list for RPC connection %s\n",
416                           ndr_interface_name(&p->contexts->syntax.uuid,
417                                              p->contexts->syntax.if_version)));
418         }
419 }
420
421 /*******************************************************************
422 Shall we allow access to this rpc?  Currently this function
423 implements the 'restrict anonymous' setting by denying access to
424 anonymous users if the restrict anonymous level is > 0.  Further work
425 will be checking a security descriptor to determine whether a user
426 token has enough access to access the pipe.
427 ********************************************************************/
428
429 bool pipe_access_check(struct pipes_struct *p)
430 {
431         /* Don't let anonymous users access this RPC if restrict
432            anonymous > 0 */
433
434         if (lp_restrict_anonymous() > 0) {
435
436                 /* schannel, so we must be ok */
437                 if (p->pipe_bound &&
438                     (p->auth.auth_type == DCERPC_AUTH_TYPE_SCHANNEL)) {
439                         return True;
440                 }
441
442                 if (security_session_user_level(p->session_info, NULL) < SECURITY_USER) {
443                         return False;
444                 }
445         }
446
447         return True;
448 }
449
450 void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd,
451                             uint32_t access_granted, size_t data_size,
452                             const char *type, NTSTATUS *pstatus)
453 {
454         struct dcesrv_handle *rpc_hnd;
455         void *data;
456
457         if (p->pipe_handles->count > MAX_OPEN_POLS) {
458                 DEBUG(0, ("ERROR: Too many handles (%d) for RPC connection %s\n",
459                           (int) p->pipe_handles->count,
460                           ndr_interface_name(&p->contexts->syntax.uuid,
461                                              p->contexts->syntax.if_version)));
462
463                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
464                 return NULL;
465         }
466
467         data = talloc_size(talloc_tos(), data_size);
468         if (data == NULL) {
469                 *pstatus = NT_STATUS_NO_MEMORY;
470                 return NULL;
471         }
472         talloc_set_name_const(data, type);
473
474         rpc_hnd = create_rpc_handle_internal(p, hnd, data);
475         if (rpc_hnd == NULL) {
476                 TALLOC_FREE(data);
477                 *pstatus = NT_STATUS_NO_MEMORY;
478                 return NULL;
479         }
480         rpc_hnd->access_granted = access_granted;
481         *pstatus = NT_STATUS_OK;
482         return data;
483 }
484
485 void *_policy_handle_find(struct pipes_struct *p,
486                           const struct policy_handle *hnd,
487                           uint32_t access_required,
488                           uint32_t *paccess_granted,
489                           const char *name, const char *location,
490                           NTSTATUS *pstatus)
491 {
492         struct dcesrv_handle *rpc_hnd;
493         void *data;
494
495         rpc_hnd = find_policy_by_hnd_internal(p, hnd, &data);
496         if (rpc_hnd == NULL) {
497                 *pstatus = NT_STATUS_INVALID_HANDLE;
498                 return NULL;
499         }
500         if (strcmp(name, talloc_get_name(data)) != 0) {
501                 DEBUG(10, ("expected %s, got %s\n", name,
502                            talloc_get_name(data)));
503                 *pstatus = NT_STATUS_INVALID_HANDLE;
504                 return NULL;
505         }
506         if ((access_required & rpc_hnd->access_granted) != access_required) {
507                 if (root_mode()) {
508                         DEBUG(4, ("%s: ACCESS should be DENIED (granted: "
509                                   "%#010x; required: %#010x)\n", location,
510                                   rpc_hnd->access_granted, access_required));
511                         DEBUGADD(4,("but overwritten by euid == 0\n"));
512                         goto okay;
513                 }
514                 DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: "
515                          "%#010x)\n", location, rpc_hnd->access_granted,
516                          access_required));
517                 *pstatus = NT_STATUS_ACCESS_DENIED;
518                 return NULL;
519         }
520
521  okay:
522         DEBUG(10, ("found handle of type %s\n", talloc_get_name(data)));
523         if (paccess_granted != NULL) {
524                 *paccess_granted = rpc_hnd->access_granted;
525         }
526         *pstatus = NT_STATUS_OK;
527         return data;
528 }