first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[kai/samba.git] / source3 / lib / msrpc_use.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB client generic functions
5    Copyright (C) Andrew Tridgell 1994-1999
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
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 #define NO_SYSLOG
24
25 #include "includes.h"
26 #include "trans2.h"
27
28 extern int DEBUGLEVEL;
29 extern pstring scope;
30 extern pstring global_myname;
31
32 struct msrpc_use
33 {
34         struct msrpc_state *cli;
35         uint32 num_users;
36 };
37
38 static struct msrpc_use **msrpcs = NULL;
39 uint32 num_msrpcs = 0;
40
41 /****************************************************************************
42 terminate client connection
43 ****************************************************************************/
44 static void msrpc_use_free(struct msrpc_use *cli)
45 {
46         if (cli->cli != NULL)
47         {
48                 if (cli->cli->initialised)
49                 {
50                         msrpc_shutdown(cli->cli);
51                 }
52                 free(cli->cli);
53         }
54
55         free(cli);
56 }
57
58 /****************************************************************************
59 free a client array
60 ****************************************************************************/
61 static void free_msrpc_array(uint32 num_entries, struct msrpc_use **entries)
62 {
63         void(*fn)(void*) = (void(*)(void*))&msrpc_use_free;
64         free_void_array(num_entries, (void**)entries, *fn);
65 }
66
67 /****************************************************************************
68 add a client state to the array
69 ****************************************************************************/
70 static struct msrpc_use* add_msrpc_to_array(uint32 *len,
71                                 struct msrpc_use ***array,
72                                 struct msrpc_use *cli)
73 {
74         int i;
75         for (i = 0; i < num_msrpcs; i++)
76         {
77                 if (msrpcs[i] == NULL)
78                 {
79                         msrpcs[i] = cli;
80                         return cli;
81                 }
82         }
83
84         return (struct msrpc_use*)add_item_to_array(len,
85                              (void***)array, (void*)cli);
86                                 
87 }
88
89 /****************************************************************************
90 initiate client array
91 ****************************************************************************/
92 void init_msrpc_use(void)
93 {
94         msrpcs = NULL;
95         num_msrpcs = 0;
96 }
97
98 /****************************************************************************
99 terminate client array
100 ****************************************************************************/
101 void free_msrpc_use(void)
102 {
103         free_msrpc_array(num_msrpcs, msrpcs);
104         init_msrpc_use();
105 }
106
107 /****************************************************************************
108 find client state.  server name, user name, domain name and password must all
109 match.
110 ****************************************************************************/
111 static struct msrpc_use *msrpc_find(const char* pipe_name,
112                                 const struct user_creds *usr_creds)
113 {
114         int i;
115         struct user_creds null_usr;
116
117         copy_user_creds(&null_usr, usr_creds);
118         usr_creds = &null_usr;
119                 
120         DEBUG(10,("msrpc_find: %s %s %s\n",
121                         pipe_name,
122                         usr_creds->ntc.user_name,
123                         usr_creds->ntc.domain));
124
125         for (i = 0; i < num_msrpcs; i++)
126         {
127                 char *msrpc_name = NULL;
128                 struct msrpc_use *c = msrpcs[i];
129
130                 if (c == NULL) continue;
131
132                 msrpc_name = c->cli->pipe_name;
133
134                 DEBUG(10,("msrpc_find[%d]: %s %s %s\n",
135                                 i, msrpc_name,
136                                 c->cli->usr.ntc.user_name,
137                                 c->cli->usr.ntc.domain));
138                                 
139                 if (!strequal(msrpc_name, pipe_name))
140                 {
141                         continue;
142                 }
143                 if (!strequal(usr_creds->ntc.user_name, c->cli->usr.ntc.user_name))
144                 {
145                         continue;
146                 }
147                 if (!usr_creds->reuse &&
148                     !pwd_compare(&usr_creds->ntc.pwd, &c->cli->usr.ntc.pwd))
149                 {
150                         DEBUG(100,("password doesn't match\n"));
151                         continue;
152                 }
153                 if (usr_creds->ntc.domain[0] == 0)
154                 {
155                         return c;
156                 }
157                 if (strequal(usr_creds->ntc.domain, c->cli->usr.ntc.domain))
158                 {
159                         return c;
160                 }
161         }
162
163         return NULL;
164 }
165
166 /****************************************************************************
167 create a new client state from user credentials
168 ****************************************************************************/
169 static struct msrpc_use *msrpc_use_get(const char* pipe_name,
170                                 const struct user_creds *usr_creds)
171 {
172         struct msrpc_use *cli = (struct msrpc_use*)malloc(sizeof(*cli));
173
174         if (cli == NULL)
175         {
176                 return NULL;
177         }
178
179         memset(cli, 0, sizeof(*cli));
180
181         cli->cli = msrpc_initialise(NULL);
182
183         if (cli->cli == NULL)
184         {
185                 return NULL;
186         }
187
188         msrpc_init_creds(cli->cli, usr_creds);
189
190         return cli;
191 }
192
193 /****************************************************************************
194 init client state
195 ****************************************************************************/
196 struct msrpc_state *msrpc_use_add(const char* pipe_name,
197                                 const struct user_creds *usr_creds,
198                                 BOOL redir)
199 {
200         struct msrpc_use *cli = msrpc_find(pipe_name, usr_creds); 
201
202         if (cli != NULL)
203         {
204                 cli->num_users++;
205                 return cli->cli;
206         }
207
208         /* reuse an existing connection requested, and one was not found */
209         if (usr_creds != NULL && usr_creds->reuse && !redir)
210         {
211                 return False;
212         }
213
214         /*
215          * allocate
216          */
217
218         cli = msrpc_use_get(pipe_name, usr_creds);
219         cli->cli->redirect = redir;
220
221         if (!msrpc_establish_connection(cli->cli, pipe_name))
222         {
223                 DEBUG(0,("msrpc_net_use_add: connection failed\n"));
224                 cli->cli = NULL;
225                 msrpc_use_free(cli);
226                 return NULL;
227         }
228
229         add_msrpc_to_array(&num_msrpcs, &msrpcs, cli);
230         cli->num_users++;
231
232         return cli->cli;
233 }
234
235 /****************************************************************************
236 delete a client state
237 ****************************************************************************/
238 BOOL msrpc_use_del(const char* pipe_name,
239                                 const struct user_creds *usr_creds,
240                                 BOOL force_close,
241                                 BOOL *connection_closed)
242 {
243         int i;
244
245         DEBUG(10,("msrpc_net_use_del: %s. force close: %s\n",
246                    pipe_name, BOOLSTR(force_close)));
247
248         if (connection_closed != NULL)
249         {
250                 *connection_closed = False;
251         }
252
253         for (i = 0; i < num_msrpcs; i++)
254         {
255                 char *msrpc_name = NULL;
256
257                 if (msrpcs[i] == NULL) continue;
258                 if (msrpcs[i]->cli == NULL) continue;
259
260                 msrpc_name = msrpcs[i]->cli->pipe_name;
261
262                 if (!strequal(msrpc_name, pipe_name)) continue;
263
264                 if (strequal(usr_creds->ntc.user_name,
265                              msrpcs[i]->cli->usr.ntc.user_name) &&
266                     strequal(usr_creds->ntc.domain,
267                              msrpcs[i]->cli->usr.ntc.domain))
268                 {
269                         /* decrement number of users */
270                         msrpcs[i]->num_users--;
271
272                         DEBUG(10,("idx: %i num_users now: %d\n",
273                                    i, msrpcs[i]->num_users));
274
275                         if (force_close || msrpcs[i]->num_users == 0)
276                         {
277                                 msrpc_use_free(msrpcs[i]);
278                                 msrpcs[i] = NULL;
279                                 if (connection_closed != NULL)
280                                 {
281                                         *connection_closed = True;
282                                 }
283                         }
284                         return True;
285                 }
286         }
287
288         return False;
289 }
290
291 /****************************************************************************
292 enumerate client states
293 ****************************************************************************/
294 void msrpc_net_use_enum(uint32 *num_cons, struct use_info ***use)
295 {
296         int i;
297
298         *num_cons = 0;
299         *use = NULL;
300
301         for (i = 0; i < num_msrpcs; i++)
302         {
303                 struct use_info item;
304
305                 ZERO_STRUCT(item);
306
307                 if (msrpcs[i] == NULL) continue;
308
309                 item.connected = msrpcs[i]->cli != NULL ? True : False;
310         
311                 if (item.connected)
312                 {
313                         item.srv_name  = msrpcs[i]->cli->pipe_name;
314                         item.user_name = msrpcs[i]->cli->usr.ntc.user_name;
315                         item.domain    = msrpcs[i]->cli->usr.ntc.domain;
316                 }
317
318                 add_use_info_to_array(num_cons, use, &item);
319         }
320 }
321