This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.
[samba.git] / source / rpc_server / srv_lsa_hnd.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 2 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, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "includes.h"
24
25 /* This is the max handles across all instances of a pipe name. */
26 #ifndef MAX_OPEN_POLS
27 #define MAX_OPEN_POLS 1024
28 #endif
29
30 /****************************************************************************
31  Hack as handles need to be persisant over lsa pipe closes so long as a samr
32  pipe is open. JRA.
33 ****************************************************************************/
34
35 static BOOL is_samr_lsa_pipe(const char *pipe_name)
36 {
37         return (strstr(pipe_name, "samr") || strstr(pipe_name, "lsa"));
38 }
39
40 /****************************************************************************
41  Initialise a policy handle list on a pipe. Handle list is shared between all
42  pipes of the same name.
43 ****************************************************************************/
44
45 BOOL init_pipe_handle_list(pipes_struct *p, char *pipe_name)
46 {
47         pipes_struct *plist = get_first_internal_pipe();
48         struct handle_list *hl = NULL;
49
50         for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist)) {
51                 if (strequal( plist->name, pipe_name) ||
52                                 (is_samr_lsa_pipe(plist->name) && is_samr_lsa_pipe(pipe_name))) {
53                         if (!plist->pipe_handles) {
54                                 pstring msg;
55                                 slprintf(msg, sizeof(msg)-1, "init_pipe_handles: NULL pipe_handle pointer in pipe %s",
56                                                 pipe_name );
57                                 smb_panic(msg);
58                         }
59                         hl = plist->pipe_handles;
60                         break;
61                 }
62         }
63
64         if (!hl) {
65                 /*
66                  * No handle list for this pipe (first open of pipe).
67                  * Create list.
68                  */
69
70                 if ((hl = (struct handle_list *)malloc(sizeof(struct handle_list))) == NULL)
71                         return False;
72                 ZERO_STRUCTP(hl);
73
74                 DEBUG(10,("init_pipe_handles: created handle list for pipe %s\n", pipe_name ));
75         }
76
77         /*
78          * One more pipe is using this list.
79          */
80
81         hl->pipe_ref_count++;
82
83         /*
84          * Point this pipe at this list.
85          */
86
87         p->pipe_handles = hl;
88
89         DEBUG(10,("init_pipe_handles: pipe_handles ref count = %u for pipe %s\n",
90                         p->pipe_handles->pipe_ref_count, pipe_name ));
91
92         return True;
93 }
94
95 /****************************************************************************
96   find first available policy slot.  creates a policy handle for you.
97 ****************************************************************************/
98
99 BOOL create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void (*free_fn)(void *), void *data_ptr)
100 {
101         static uint32 pol_hnd_low  = 0;
102         static uint32 pol_hnd_high = 0;
103
104         struct policy *pol;
105
106         if (p->pipe_handles->count > MAX_OPEN_POLS) {
107                 DEBUG(0,("create_policy_hnd: ERROR: too many handles (%d) on this pipe.\n",
108                                 (int)p->pipe_handles->count));
109                 return False;
110         }
111
112         pol = (struct policy *)malloc(sizeof(*p));
113         if (!pol) {
114                 DEBUG(0,("create_policy_hnd: ERROR: out of memory!\n"));
115                 return False;
116         }
117
118         ZERO_STRUCTP(pol);
119
120         pol->data_ptr = data_ptr;
121         pol->free_fn = free_fn;
122
123         pol_hnd_low++;
124         if (pol_hnd_low == 0)
125                 (pol_hnd_high)++;
126
127         SIVAL(&pol->pol_hnd.data1, 0 , 0);  /* first bit must be null */
128         SIVAL(&pol->pol_hnd.data2, 0 , pol_hnd_low ); /* second bit is incrementing */
129         SSVAL(&pol->pol_hnd.data3, 0 , pol_hnd_high); /* second bit is incrementing */
130         SSVAL(&pol->pol_hnd.data4, 0 , (pol_hnd_high>>16)); /* second bit is incrementing */
131         SIVAL(pol->pol_hnd.data5, 0, time(NULL)); /* something random */
132         SIVAL(pol->pol_hnd.data5, 4, sys_getpid()); /* something more random */
133
134         DLIST_ADD(p->pipe_handles->Policy, pol);
135         p->pipe_handles->count++;
136
137         *hnd = pol->pol_hnd;
138         
139         DEBUG(4,("Opened policy hnd[%d] ", (int)p->pipe_handles->count));
140         dump_data(4, (char *)hnd, sizeof(*hnd));
141
142         return True;
143 }
144
145 /****************************************************************************
146   find policy by handle - internal version.
147 ****************************************************************************/
148
149 static struct policy *find_policy_by_hnd_internal(pipes_struct *p, POLICY_HND *hnd, void **data_p)
150 {
151         struct policy *pol;
152         size_t i;
153
154         if (data_p)
155                 *data_p = NULL;
156
157         for (i = 0, pol=p->pipe_handles->Policy;pol;pol=pol->next, i++) {
158                 if (memcmp(&pol->pol_hnd, hnd, sizeof(*hnd)) == 0) {
159                         DEBUG(4,("Found policy hnd[%d] ", (int)i));
160                         dump_data(4, (char *)hnd, sizeof(*hnd));
161                         if (data_p)
162                                 *data_p = pol->data_ptr;
163                         return pol;
164                 }
165         }
166
167         DEBUG(4,("Policy not found: "));
168         dump_data(4, (char *)hnd, sizeof(*hnd));
169
170         p->bad_handle_fault_state = True;
171
172         return NULL;
173 }
174
175 /****************************************************************************
176   find policy by handle
177 ****************************************************************************/
178
179 BOOL find_policy_by_hnd(pipes_struct *p, POLICY_HND *hnd, void **data_p)
180 {
181         return find_policy_by_hnd_internal(p, hnd, data_p) == NULL ? False : True;
182 }
183
184 /****************************************************************************
185   Close a policy.
186 ****************************************************************************/
187
188 BOOL close_policy_hnd(pipes_struct *p, POLICY_HND *hnd)
189 {
190         struct policy *pol = find_policy_by_hnd_internal(p, hnd, NULL);
191
192         if (!pol) {
193                 DEBUG(3,("Error closing policy\n"));
194                 return False;
195         }
196
197         DEBUG(3,("Closed policy\n"));
198
199         if (pol->free_fn && pol->data_ptr)
200                 (*pol->free_fn)(pol->data_ptr);
201
202         p->pipe_handles->count--;
203
204         DLIST_REMOVE(p->pipe_handles->Policy, pol);
205
206         ZERO_STRUCTP(pol);
207
208         SAFE_FREE(pol);
209
210         return True;
211 }
212
213 /****************************************************************************
214  Close a pipe - free the handle list if it was the last pipe reference.
215 ****************************************************************************/
216
217 void close_policy_by_pipe(pipes_struct *p)
218 {
219         p->pipe_handles->pipe_ref_count--;
220
221         if (p->pipe_handles->pipe_ref_count == 0) {
222                 /*
223                  * Last pipe open on this list - free the list.
224                  */
225                 while (p->pipe_handles->Policy)
226                         close_policy_hnd(p, &p->pipe_handles->Policy->pol_hnd);
227
228                 p->pipe_handles->Policy = NULL;
229                 p->pipe_handles->count = 0;
230
231                 SAFE_FREE(p->pipe_handles);
232                 DEBUG(10,("close_policy_by_pipe: deleted handle list for pipe %s\n", p->name ));
233         }
234 }