deal with allocation size of 0 in prs_unistr when UNMARSHALLING
[Samba.git] / source / rpc_client / cli_connect.c
blob0eceda4c4cff224d30faa225bb47d75201709be0
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
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.
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.
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.
23 #define NO_SYSLOG
25 #include "includes.h"
26 #include "rpc_parse.h"
27 #include "rpc_client.h"
30 static struct cli_connection **con_list = NULL;
31 static uint32 num_cons = 0;
33 struct user_creds *usr_creds = NULL;
34 vuser_key *user_key = NULL;
36 extern int DEBUGLEVEL;
37 extern pstring global_myname;
39 * needed for the struct cli_connection
40 * none of these functions are implemented in HEAD currently
41 * rpc_client/cli_connect.c for details
43 * the 'typedef struct _cli_auth_fns cli_auth_fns;' is in
44 * rpc_misc.h
46 struct _cli_auth_fns {
48 /* these three will do for now. they *should* match with server-side */
49 BOOL (*create_bind_req) (struct cli_connection *, prs_struct *,
50 uint32, RPC_IFACE *, RPC_IFACE *);
51 BOOL (*decode_bind_resp) (struct cli_connection *, prs_struct *);
52 BOOL (*create_bind_cont) (struct cli_connection *, prs_struct *, uint32);
54 /* creates an authenticated PDU */
55 BOOL (*cli_create_pdu) (struct cli_connection *, uint8, prs_struct *,
56 int, int *, prs_struct *, uint8 *);
58 /* decodes an authenticated PDU */
59 BOOL (*cli_decode_pdu) (struct cli_connection *, prs_struct *, int, int);
63 cli_auth_fns cli_noauth_fns =
65 NULL,
66 NULL,
67 NULL,
68 NULL,
69 NULL
75 void init_connections(void)
77 con_list = NULL;
78 num_cons = 0;
80 init_cli_use();
83 static void free_con_array(uint32 num_entries,
84 struct cli_connection **entries)
86 void (*fn) (void *) = (void (*)(void *))&cli_connection_free;
87 free_void_array(num_entries, (void **)entries, *fn);
91 static struct cli_connection *add_con_to_array(uint32 * len,
92 struct cli_connection ***array,
93 struct cli_connection *con)
95 return (struct cli_connection *)add_item_to_array(len,
96 (void ***)array,
97 (void *)con);
101 void free_connections(void)
103 DEBUG(3, ("free_connections: closing all MSRPC connections\n"));
104 free_con_array(num_cons, con_list);
105 free_cli_use();
107 init_connections();
110 static struct cli_connection *cli_con_get(const char *srv_name,
111 char *pipe_name,
112 cli_auth_fns * auth,
113 void *auth_creds, BOOL reuse)
115 struct cli_connection *con = NULL;
116 BOOL is_new_connection = False;
117 CREDS_NT usr;
118 struct ntuser_creds *ntc = NULL;
119 struct ncacn_np *pNcacn;
122 * initialization stuff
124 con = (struct cli_connection *)malloc(sizeof(*con));
125 if (con == NULL)
127 return NULL;
129 memset(con, 0, sizeof(*con));
131 copy_user_creds(&con->usr_creds, NULL);
132 con->usr_creds.reuse = reuse;
134 if (srv_name != NULL)
136 con->srv_name = strdup(srv_name);
138 if (pipe_name != NULL)
140 con->pipe_name = strdup(pipe_name);
142 if (usr_creds != NULL)
144 ntc = &usr_creds->ntc;
147 /* fix me XXXX **WHAT** a hack. The cli_state* is malloc'd
148 deep within the call stack, so we can grab that pointer.
149 ncacn_np* is stored in an array which is currently handled
150 by underlying systems. --jerry */
151 pNcacn = ncacn_np_use_add(pipe_name, user_key, srv_name,
152 ntc, reuse,
153 &is_new_connection);
154 if (pNcacn == NULL)
155 return NULL;
157 con->pCli_state = pNcacn->smb;
159 if (con->pCli_state == NULL)
160 return NULL;
162 con->pCli_state->key.pid = 0;
163 con->pCli_state->key.vuid = UID_FIELD_INVALID;
164 create_ntc_from_cli_state ( &usr, con->pCli_state );
165 copy_nt_creds(&con->usr_creds.ntc, &usr);
167 if (is_new_connection)
169 con->auth_info = NULL;
170 con->auth_creds = auth_creds;
172 if (auth != NULL)
174 con->auth = auth;
176 else
178 con->auth = &cli_noauth_fns;
181 if (!rpc_pipe_bind(con->pCli_state, pipe_name, global_myname))
183 DEBUG(0, ("rpc_pipe_bind failed\n"));
184 cli_connection_free(con);
185 return NULL;
188 else
190 con->auth_info = cli_conn_get_auth_creds(con);
191 con->auth = cli_conn_get_authfns(con);
192 if (con->auth_info != NULL)
194 DEBUG(1,("cli_con_get: TODO: auth reuse\n"));
195 cli_connection_free(con);
196 return NULL;
198 else
200 con->auth = &cli_noauth_fns;
204 add_con_to_array(&num_cons, &con_list, con);
205 return con;
209 /****************************************************************************
210 terminate client connection
211 ****************************************************************************/
212 void cli_connection_free(struct cli_connection *con)
214 BOOL closed = False;
215 struct cli_state *oldcli = NULL;
216 int i;
218 DEBUG(10, ("cli_connection_free: %d\n", __LINE__));
220 if (con->pCli_state != NULL)
222 DEBUG(10, ("msrpc smb connection\n"));
223 ncacn_np_use_del(con->srv_name, con->pipe_name,
224 &con->pCli_state->key, False, &closed);
225 oldcli = con->pCli_state;
226 con->pCli_state = NULL;
229 DEBUG(10, ("cli_connection_free: closed: %s\n", BOOLSTR(closed)));
231 if (closed)
233 for (i = 0; i < num_cons; i++)
235 struct cli_connection *c = con_list[i];
236 if (c != NULL && con != c && c->pCli_state == oldcli)
238 /* WHOOPS! fnum already open: too bad!!!
239 get rid of all other connections that
240 were using that connection
242 c->pCli_state = NULL;
247 /* don't free the cli_state since it is being handled
248 by the *clis list in rpc_client/cli_use.c.
249 This code needs to be fixed badly. It is **way**
250 to complicated. --jerry */
251 /* if (oldcli != NULL)
253 free(oldcli);
254 } */
256 if (con->srv_name != NULL)
258 free(con->srv_name);
259 con->srv_name = NULL;
261 if (con->pipe_name != NULL)
263 free(con->pipe_name);
264 con->pipe_name = NULL;
267 if (con->auth_info != NULL)
269 free(con->auth_info);
270 con->auth_info = NULL;
273 memset(&con->usr_creds, 0, sizeof(con->usr_creds));
275 for (i = 0; i < num_cons; i++)
277 if (con == con_list[i])
279 con_list[i] = NULL;
283 free(con);
286 void cli_connection_unlink(struct cli_connection *con)
288 if (con != NULL)
290 cli_connection_free(con);
292 return;
295 /****************************************************************************
296 init client state
297 ****************************************************************************/
298 BOOL cli_connection_init(const char *srv_name, char *pipe_name,
299 struct cli_connection **con)
301 return cli_connection_init_auth(srv_name, pipe_name, con, NULL, NULL);
304 /****************************************************************************
305 init client state
306 ****************************************************************************/
307 BOOL cli_connection_init_auth(const char *srv_name, char *pipe_name,
308 struct cli_connection **con,
309 cli_auth_fns * auth, void *auth_creds)
311 BOOL reuse = True;
314 * allocate
317 DEBUG(10, ("cli_connection_init_auth: %s %s\n",
318 srv_name != NULL ? srv_name : "<null>", pipe_name));
320 *con = cli_con_get(srv_name, pipe_name, auth, auth_creds, reuse);
322 return (*con) != NULL;
325 /****************************************************************************
326 get auth functions associated with an msrpc session.
327 ****************************************************************************/
328 struct _cli_auth_fns *cli_conn_get_authfns(struct cli_connection *con)
330 return con != NULL ? con->auth : NULL;
334 /****************************************************************************
335 get auth info associated with an msrpc session.
336 ****************************************************************************/
337 void *cli_conn_get_auth_creds(struct cli_connection *con)
339 return con != NULL ? con->auth_creds : NULL;
343 /****************************************************************************
344 send a request on an rpc pipe.
345 ****************************************************************************/
346 BOOL rpc_hnd_pipe_req(const POLICY_HND * hnd, uint8 op_num,
347 prs_struct * data, prs_struct * rdata)
349 struct cli_connection *con = NULL;
351 /* we need this to locate the cli_connection associated
352 with the POLICY_HND */
353 if ((con=RpcHndList_get_connection(hnd)) == NULL)
354 return False;
356 if (!rpc_con_ok(con)) return False;
358 return rpc_con_pipe_req(con, op_num, data, rdata);
361 /****************************************************************************
362 send a request on an rpc pipe.
363 ****************************************************************************/
364 BOOL rpc_con_pipe_req(struct cli_connection *con, uint8 op_num,
365 prs_struct * data, prs_struct * rdata)
367 BOOL ret;
368 DEBUG(10, ("rpc_con_pipe_req: op_num %d offset %d used: %d\n",
369 op_num, data->data_offset, data->buffer_size));
370 prs_dump("in_rpcclient", (int)op_num, data);
372 /* Why does this use prs->data_offset? --jerry */
373 /* prs_realloc_data(data, data->data_offset); */
375 ret = rpc_api_pipe_req(con->pCli_state, op_num, data, rdata);
376 prs_dump("out_rpcclient", (int)op_num, rdata);
377 return ret;
380 /****************************************************************************
381 this allows us to detect dead servers. The cli->fd is set to -1 when
382 we get an error
383 *****************************************************************************/
384 BOOL rpc_con_ok(struct cli_connection *con)
386 if (!con)
387 return False;
389 if (!con->pCli_state)
390 return False;
391 if (con->pCli_state->fd == -1)
392 return False;
394 return True;