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