Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header.
[samba.git] / source3 / rpc_client / cli_connect.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB client generic functions
5    Copyright (C) Andrew Tridgell              1994-2000
6    Copyright (C) Luke Kenneth Casson Leighton 1996-2000
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 "rpc_parse.h"
27
28
29 static struct cli_connection **con_list = NULL;
30 static uint32 num_cons = 0;
31
32 struct user_creds *usr_creds = NULL;
33 vuser_key *user_key = NULL;
34
35 extern pstring global_myname;
36 /*
37  * needed for the struct cli_connection
38  * none of these functions are implemented in HEAD currently
39  * rpc_client/cli_connect.c for details
40  *
41  * the 'typedef struct _cli_auth_fns cli_auth_fns;' is in 
42  * rpc_misc.h
43  */
44 struct _cli_auth_fns {
45
46         /* these three will do for now.  they *should* match with server-side */
47         BOOL (*create_bind_req) (struct cli_connection *, prs_struct *,
48                                  uint32, RPC_IFACE *, RPC_IFACE *);
49         BOOL (*decode_bind_resp) (struct cli_connection *, prs_struct *);
50         BOOL (*create_bind_cont) (struct cli_connection *, prs_struct *, uint32);
51
52         /* creates an authenticated PDU */
53         BOOL (*cli_create_pdu) (struct cli_connection *, uint8, prs_struct *,
54                                 int, int *, prs_struct *, uint8 *);
55
56         /* decodes an authenticated PDU */
57         BOOL (*cli_decode_pdu) (struct cli_connection *, prs_struct *, int, int);
58
59 };
60
61 cli_auth_fns cli_noauth_fns = 
62 {
63         NULL,
64         NULL,
65         NULL,
66         NULL,
67         NULL
68 };
69
70
71
72
73 void init_connections(void)
74 {
75         con_list = NULL;
76         num_cons = 0;
77
78         init_cli_use();
79 }
80
81 static void free_con_array(uint32 num_entries,
82                            struct cli_connection **entries)
83 {
84         void (*fn) (void *) = (void (*)(void *))&cli_connection_free;
85         free_void_array(num_entries, (void **)entries, *fn);
86 }
87
88
89 static struct cli_connection *add_con_to_array(uint32 * len,
90                                                struct cli_connection ***array,
91                                                struct cli_connection *con)
92 {
93         return (struct cli_connection *)add_item_to_array(len,
94                                                           (void ***)array,
95                                                           (void *)con);
96
97 }
98
99 void free_connections(void)
100 {
101         DEBUG(3, ("free_connections: closing all MSRPC connections\n"));
102         free_con_array(num_cons, con_list);
103         free_cli_use();
104
105         init_connections();
106 }
107
108 static struct cli_connection *cli_con_get(const char *srv_name,
109                                           char *pipe_name,
110                                           cli_auth_fns * auth,
111                                           void *auth_creds, BOOL reuse)
112 {
113         struct cli_connection *con = NULL;
114         BOOL is_new_connection = False;
115         CREDS_NT usr;
116         struct ntuser_creds *ntc = NULL;
117         struct ncacn_np *pNcacn;
118
119         /*
120          * initialization stuff
121          */
122         con = (struct cli_connection *)malloc(sizeof(*con));
123         if (con == NULL)
124         {
125                 return NULL;
126         }
127         memset(con, 0, sizeof(*con));
128
129         copy_user_creds(&con->usr_creds, NULL);
130         con->usr_creds.reuse = reuse;
131
132         if (srv_name != NULL)
133         {
134                 con->srv_name = strdup(srv_name);
135         }
136         if (pipe_name != NULL)
137         {
138                 con->pipe_name = strdup(pipe_name);
139         }
140         if (usr_creds != NULL)
141         {
142                 ntc = &usr_creds->ntc;
143         }
144
145         /* fix me XXXX **WHAT** a hack.  The cli_state* is malloc'd
146            deep within the call stack, so we can grab that pointer.
147            ncacn_np* is stored in an array which is currently handled
148            by underlying systems.   --jerry */
149         pNcacn = ncacn_np_use_add(pipe_name, user_key, srv_name,
150                                           ntc, reuse,
151                                           &is_new_connection);
152         if (pNcacn == NULL)
153                 return NULL;
154
155         con->pCli_state = pNcacn->smb;
156
157         if (con->pCli_state == NULL)
158                 return NULL;
159
160         con->pCli_state->key.pid = 0;
161         con->pCli_state->key.vuid = UID_FIELD_INVALID;
162         create_ntc_from_cli_state ( &usr, con->pCli_state );
163         copy_nt_creds(&con->usr_creds.ntc, &usr);
164
165         if (is_new_connection)
166         {
167                 con->auth_info = NULL;
168                 con->auth_creds = auth_creds;
169
170                 if (auth != NULL)
171                 {
172                         con->auth = auth;
173                 }
174                 else
175                 {
176                         con->auth = &cli_noauth_fns;
177                 }
178
179                 if (!rpc_pipe_bind(con->pCli_state, pipe_name, global_myname))
180                 {
181                         DEBUG(0, ("rpc_pipe_bind failed\n"));
182                         cli_connection_free(con);
183                         return NULL;
184                 }
185         }
186         else
187         {
188                 con->auth_info = cli_conn_get_auth_creds(con);
189                 con->auth = cli_conn_get_authfns(con);
190                 if (con->auth_info != NULL)
191                 {
192                         DEBUG(1,("cli_con_get: TODO: auth reuse\n"));
193                         cli_connection_free(con);
194                         return NULL;
195                 }
196                 else
197                 {
198                         con->auth = &cli_noauth_fns;
199                 }
200         }
201
202         add_con_to_array(&num_cons, &con_list, con);
203         return con;
204 }
205
206
207 /****************************************************************************
208 terminate client connection
209 ****************************************************************************/
210 void cli_connection_free(struct cli_connection *con)
211 {
212         BOOL closed = False;
213         struct cli_state *oldcli = NULL;
214         int i;
215
216         DEBUG(10, ("cli_connection_free: %d\n", __LINE__));
217
218         if (con->pCli_state != NULL)
219         {
220                 DEBUG(10, ("msrpc smb connection\n"));
221                 ncacn_np_use_del(con->srv_name, con->pipe_name,
222                                  &con->pCli_state->key, False, &closed);
223                 oldcli = con->pCli_state;
224                 con->pCli_state = NULL;
225         }
226
227         DEBUG(10, ("cli_connection_free: closed: %s\n", BOOLSTR(closed)));
228
229         if (closed)
230         {
231                 for (i = 0; i < num_cons; i++)
232                 {
233                         struct cli_connection *c = con_list[i];
234                         if (c != NULL && con != c && c->pCli_state == oldcli)
235                         {
236                                 /* WHOOPS! fnum already open: too bad!!!
237                                    get rid of all other connections that
238                                    were using that connection
239                                  */
240                                  c->pCli_state = NULL;
241                         }
242                 }
243         }
244
245         /* don't free the cli_state since it is being handled
246            by the *clis list in rpc_client/cli_use.c.
247            This code needs to be fixed badly.  It is **way**
248            to complicated.  --jerry */
249         /* if (oldcli != NULL)
250         {
251                 free(oldcli);
252         } */
253         
254         SAFE_FREE(con->srv_name);
255         SAFE_FREE(con->pipe_name);
256         SAFE_FREE(con->auth_info);
257         
258         memset(&con->usr_creds, 0, sizeof(con->usr_creds));
259
260         for (i = 0; i < num_cons; i++)
261         {
262                 if (con == con_list[i])
263                 {
264                         con_list[i] = NULL;
265                 }
266         }
267
268         SAFE_FREE(con);
269 }
270
271 void cli_connection_unlink(struct cli_connection *con)
272 {
273         if (con != NULL)
274         {
275                 cli_connection_free(con);
276         }
277         return;
278 }
279
280 /****************************************************************************
281 init client state
282 ****************************************************************************/
283 BOOL cli_connection_init(const char *srv_name, char *pipe_name,
284                          struct cli_connection **con)
285 {
286         return cli_connection_init_auth(srv_name, pipe_name, con, NULL, NULL);
287 }
288
289 /****************************************************************************
290 init client state
291 ****************************************************************************/
292 BOOL cli_connection_init_auth(const char *srv_name, char *pipe_name,
293                               struct cli_connection **con,
294                               cli_auth_fns * auth, void *auth_creds)
295 {
296         BOOL reuse = True;
297
298         /*
299          * allocate
300          */
301
302         DEBUG(10, ("cli_connection_init_auth: %s %s\n",
303                    srv_name != NULL ? srv_name : "<null>", pipe_name));
304
305         *con = cli_con_get(srv_name, pipe_name, auth, auth_creds, reuse);
306
307         return (*con) != NULL;
308 }
309
310 /****************************************************************************
311  get auth functions associated with an msrpc session.
312 ****************************************************************************/
313 struct _cli_auth_fns *cli_conn_get_authfns(struct cli_connection *con)
314 {
315         return con != NULL ? con->auth : NULL;
316 }
317
318
319 /****************************************************************************
320  get auth info associated with an msrpc session.
321 ****************************************************************************/
322 void *cli_conn_get_auth_creds(struct cli_connection *con)
323 {
324         return con != NULL ? con->auth_creds : NULL;
325 }
326
327
328 /****************************************************************************
329  send a request on an rpc pipe.
330  ****************************************************************************/
331 BOOL rpc_hnd_pipe_req(const POLICY_HND * hnd, uint8 op_num,
332                       prs_struct * data, prs_struct * rdata)
333 {
334         struct cli_connection *con = NULL;
335
336         /* we need this to locate the cli_connection associated
337            with the POLICY_HND */
338         if ((con=RpcHndList_get_connection(hnd)) == NULL)
339                 return False;
340
341         if (!rpc_con_ok(con)) return False;
342
343         return rpc_con_pipe_req(con, op_num, data, rdata);
344 }
345
346 /****************************************************************************
347  send a request on an rpc pipe.
348  ****************************************************************************/
349 BOOL rpc_con_pipe_req(struct cli_connection *con, uint8 op_num,
350                       prs_struct * data, prs_struct * rdata)
351 {
352         BOOL ret;
353         DEBUG(10, ("rpc_con_pipe_req: op_num %d offset %d used: %d\n",
354                    op_num, data->data_offset, data->buffer_size));
355         prs_dump("in_rpcclient", (int)op_num, data);
356
357         /* Why does this use prs->data_offset?  --jerry */
358         /* prs_realloc_data(data, data->data_offset); */
359
360         ret = rpc_api_pipe_req(con->pCli_state, op_num, data, rdata);
361         prs_dump("out_rpcclient", (int)op_num, rdata);
362         return ret;
363 }
364
365 /**************************************************************************** 
366    this allows us to detect dead servers. The cli->fd is set to -1 when
367    we get an error 
368 *****************************************************************************/
369 BOOL rpc_con_ok(struct cli_connection *con)
370 {
371         if (!con) 
372                 return False;
373
374         if (!con->pCli_state)
375                 return False;
376         if (con->pCli_state->fd == -1) 
377                 return False;
378
379         return True;
380 }