merge from HEAD
[Samba.git] / source / rpc_client / cli_connect.c
blob0146c790da41ac6909ff0e8e1d69d36a94a79161
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"
29 struct user_creds *usr_creds = NULL;
30 vuser_key *user_key = NULL;
32 extern int DEBUGLEVEL;
34 enum
35 { MSRPC_NONE, MSRPC_LOCAL, MSRPC_SMB };
37 struct cli_connection
39 char *srv_name;
40 char *pipe_name;
41 struct user_creds usr_creds;
43 int type;
45 union
47 struct ncacn_np *smb;
48 struct msrpc_local *local;
49 void *cli;
51 msrpc;
53 cli_auth_fns *auth;
54 void *auth_info;
55 void *auth_creds;
58 static struct cli_connection **con_list = NULL;
59 static uint32 num_cons = 0;
61 void init_connections(void)
63 con_list = NULL;
64 num_cons = 0;
66 init_cli_use();
69 static void free_con_array(uint32 num_entries,
70 struct cli_connection **entries)
72 void (*fn) (void *) = (void (*)(void *))&cli_connection_free;
73 free_void_array(num_entries, (void **)entries, *fn);
76 static struct cli_connection *add_con_to_array(uint32 * len,
77 struct cli_connection ***array,
78 struct cli_connection *con)
80 return (struct cli_connection *)add_item_to_array(len,
81 (void ***)array,
82 (void *)con);
85 void free_connections(void)
87 DEBUG(3, ("free_connections: closing all MSRPC connections\n"));
88 free_con_array(num_cons, con_list);
89 free_cli_use();
91 init_connections();
94 static struct cli_connection *cli_con_get(const char *srv_name,
95 const char *pipe_name,
96 cli_auth_fns * auth,
97 void *auth_creds, BOOL reuse)
99 struct cli_connection *con = NULL;
100 BOOL is_new_connection = False;
102 vuser_key key;
104 con = (struct cli_connection *)malloc(sizeof(*con));
106 if (con == NULL)
108 return NULL;
111 memset(con, 0, sizeof(*con));
112 con->type = MSRPC_NONE;
114 copy_user_creds(&con->usr_creds, NULL);
115 con->usr_creds.reuse = reuse;
117 if (srv_name != NULL)
119 con->srv_name = strdup(srv_name);
121 if (pipe_name != NULL)
123 con->pipe_name = strdup(pipe_name);
126 if (strequal(srv_name, "\\\\."))
128 con->type = MSRPC_LOCAL;
129 become_root(False);
130 con->msrpc.local = ncalrpc_l_use_add(pipe_name, user_key,
131 reuse,
132 &is_new_connection);
134 * XXX - this rebinds on the same pipe,
135 * only necessary, when the loopback connection
136 * was first iniated as a forward
138 is_new_connection = True;
139 unbecome_root(False);
141 else
143 struct ntuser_creds *ntc = NULL;
144 if (usr_creds != NULL)
146 ntc = &usr_creds->ntc;
148 con->type = MSRPC_SMB;
149 con->msrpc.smb =
150 ncacn_np_use_add(pipe_name, user_key, srv_name,
151 ntc, reuse,
152 &is_new_connection);
154 if (con->msrpc.smb == NULL)
156 cli_connection_free(con);
157 return NULL;
160 key = con->msrpc.smb->smb->nt.key;
161 con->msrpc.smb->smb->nt.key.pid = 0;
162 con->msrpc.smb->smb->nt.key.vuid = UID_FIELD_INVALID;
163 copy_nt_creds(&con->usr_creds.ntc,
164 &con->msrpc.smb->smb->usr);
167 if (con->msrpc.cli != NULL)
169 if (is_new_connection)
171 RPC_IFACE abstract;
172 RPC_IFACE transfer;
174 con->auth_info = NULL;
175 con->auth_creds = auth_creds;
177 if (auth != NULL)
179 con->auth = auth;
181 else
183 extern cli_auth_fns cli_noauth_fns;
184 con->auth = &cli_noauth_fns;
187 if (!rpc_pipe_bind(con, pipe_name, &abstract,
188 &transfer))
190 DEBUG(0, ("rpc_pipe_bind failed\n"));
191 cli_connection_free(con);
192 return NULL;
195 else
197 con->auth_info = cli_conn_get_auth_creds(con);
198 con->auth = cli_conn_get_authfns(con);
199 if (con->auth_info != NULL)
201 DEBUG(1,("cli_con_get: TODO: auth reuse\n"));
202 cli_connection_free(con);
203 return NULL;
205 else
207 extern cli_auth_fns cli_noauth_fns;
208 con->auth = &cli_noauth_fns;
213 if (con->msrpc.cli == NULL)
215 cli_connection_free(con);
216 return NULL;
219 if (con->type == MSRPC_SMB)
221 con->msrpc.smb->smb->nt.key = key;
223 add_con_to_array(&num_cons, &con_list, con);
224 return con;
227 /****************************************************************************
228 terminate client connection
229 ****************************************************************************/
230 void cli_connection_free(struct cli_connection *con)
232 BOOL closed = False;
233 int i;
235 DEBUG(10, ("cli_connection_free: %d\n", __LINE__));
237 if (con->msrpc.cli != NULL)
239 switch (con->type)
241 case MSRPC_LOCAL:
243 DEBUG(10, ("msrpc local connection\n"));
244 ncalrpc_l_use_del(con->pipe_name,
245 &con->msrpc.local->nt.key,
246 False, &closed);
247 con->msrpc.local = NULL;
248 break;
250 case MSRPC_SMB:
252 DEBUG(10, ("msrpc smb connection\n"));
253 ncacn_np_use_del(con->srv_name,
254 con->pipe_name,
255 &con->msrpc.smb->smb->nt.key,
256 False, &closed);
257 con->msrpc.smb = NULL;
258 break;
263 DEBUG(10, ("cli_connection_free: closed: %s\n", BOOLSTR(closed)));
265 if (con->msrpc.cli != NULL)
267 free(con->msrpc.cli);
269 con->msrpc.cli = NULL;
271 if (con->srv_name != NULL)
273 free(con->srv_name);
274 con->srv_name = NULL;
276 if (con->pipe_name != NULL)
278 free(con->pipe_name);
279 con->pipe_name = NULL;
282 if (con->auth_info != NULL)
284 free(con->auth_info);
285 con->auth_info = NULL;
288 memset(&con->usr_creds, 0, sizeof(con->usr_creds));
290 for (i = 0; i < num_cons; i++)
292 if (con == con_list[i])
294 con_list[i] = NULL;
298 free(con);
301 /****************************************************************************
302 terminate client state
303 ****************************************************************************/
304 void cli_connection_unlink(struct cli_connection *con)
306 if (con != NULL)
308 cli_connection_free(con);
310 return;
313 /****************************************************************************
314 init client state
315 ****************************************************************************/
316 BOOL cli_connection_init(const char *srv_name, const char *pipe_name,
317 struct cli_connection **con)
319 return cli_connection_init_auth(srv_name, pipe_name, con, NULL, NULL);
322 /****************************************************************************
323 init client state
324 ****************************************************************************/
325 BOOL cli_connection_init_auth(const char *srv_name, const char *pipe_name,
326 struct cli_connection **con,
327 cli_auth_fns * auth, void *auth_creds)
329 BOOL reuse = True;
332 * allocate
335 DEBUG(10, ("cli_connection_init_auth: %s %s\n",
336 srv_name != NULL ? srv_name : "<null>", pipe_name));
338 *con = cli_con_get(srv_name, pipe_name, auth, auth_creds, reuse);
340 return (*con) != NULL;
343 /****************************************************************************
344 obtain client state
345 ****************************************************************************/
346 BOOL cli_connection_getsrv(const char *srv_name, const char *pipe_name,
347 struct cli_connection **con)
349 int i;
350 struct cli_connection *auth_con = NULL;
352 if (con_list == NULL || num_cons == 0)
354 return False;
357 (*con) = NULL;
359 for (i = 0; i < num_cons; i++)
361 if (con_list[i] != NULL &&
362 strequal(con_list[i]->srv_name, srv_name) &&
363 strequal(con_list[i]->pipe_name, pipe_name))
365 extern cli_auth_fns cli_noauth_fns;
366 (*con) = con_list[i];
367 /* authenticated connections take priority. HACK! */
368 if ((*con)->auth != &cli_noauth_fns)
370 auth_con = (*con);
375 if (auth_con != NULL)
377 (*con) = auth_con;
380 return (*con) != NULL;
383 /****************************************************************************
384 obtain client state
385 ****************************************************************************/
386 BOOL cli_connection_get(const POLICY_HND * pol, struct cli_connection **con)
388 return get_policy_con(get_global_hnd_cache(), pol, con);
391 /****************************************************************************
392 link a child policy handle to a parent one
393 ****************************************************************************/
394 BOOL cli_pol_link(POLICY_HND * to, const POLICY_HND * from)
396 struct cli_connection *con = NULL;
398 if (!cli_connection_get(from, &con))
400 DEBUG(0, ("cli_pol_link: no connection\n"));
401 return False;
404 /* fix this when access masks are actually working! */
405 DEBUG(10, ("cli_pol_link: lkclXXXX - MAXIMUM_ALLOWED access_mask\n"));
407 return dup_policy_hnd(get_global_hnd_cache(), to, from) &&
408 set_policy_con(get_global_hnd_cache(), to, con, NULL);
411 /****************************************************************************
412 set a user session key associated with a connection
413 ****************************************************************************/
414 BOOL cli_get_usr_sesskey(const POLICY_HND * pol, uchar usr_sess_key[16])
416 struct ntdom_info *nt;
417 struct cli_connection *con;
418 if (!cli_connection_get(pol, &con))
420 return False;
422 if (con == NULL)
424 DEBUG(0, ("cli_get_usr_sesskey: no connection\n"));
425 return False;
427 nt = cli_conn_get_ntinfo(con);
428 if (nt == NULL)
430 DEBUG(0, ("cli_get_usr_sesskey: no ntdom_info\n"));
431 return False;
434 memcpy(usr_sess_key, nt->usr_sess_key, sizeof(nt->usr_sess_key));
436 return True;
439 /****************************************************************************
440 set a user session key associated with a connection
441 ****************************************************************************/
442 BOOL cli_set_con_usr_sesskey(struct cli_connection *con,
443 const uchar usr_sess_key[16])
445 struct ntdom_info *nt;
446 if (con == NULL)
448 return False;
450 nt = cli_conn_get_ntinfo(con);
451 if (nt != NULL)
453 memcpy(nt->usr_sess_key, usr_sess_key,
454 sizeof(nt->usr_sess_key));
458 return True;
461 /****************************************************************************
462 get auth functions associated with an msrpc session.
463 ****************************************************************************/
464 const vuser_key *cli_con_sec_ctx(struct cli_connection *con)
466 struct ntdom_info *nt;
467 if (con == NULL)
469 return False;
471 nt = cli_conn_get_ntinfo(con);
472 if (nt != NULL && nt->key.vuid != UID_FIELD_INVALID)
474 return &nt->key;
476 return NULL;
479 /****************************************************************************
480 get auth functions associated with an msrpc session.
481 ****************************************************************************/
482 struct cli_auth_fns *cli_conn_get_authfns(struct cli_connection *con)
484 return con != NULL ? con->auth : NULL;
487 /****************************************************************************
488 get auth info associated with an msrpc session.
489 ****************************************************************************/
490 void *cli_conn_get_auth_creds(struct cli_connection *con)
492 return con != NULL ? con->auth_creds : NULL;
495 /****************************************************************************
496 get auth info associated with an msrpc session.
497 ****************************************************************************/
498 void *cli_conn_get_auth_info(struct cli_connection *con)
500 return con != NULL ? con->auth_info : NULL;
503 /****************************************************************************
504 set auth info associated with an msrpc session.
505 ****************************************************************************/
506 BOOL cli_conn_set_auth_info(struct cli_connection *con, void *auth_info)
508 con->auth_info = auth_info;
509 return auth_info != NULL;
512 /****************************************************************************
513 get nt creds (HACK ALERT!) associated with an msrpc session.
514 ****************************************************************************/
515 struct ntdom_info *cli_conn_get_ntinfo(struct cli_connection *con)
517 if (con == NULL)
519 return NULL;
521 if (con->msrpc.cli == NULL)
523 DEBUG(1, ("cli_conn_get_ntinfo: NULL msrpc (closed)\n"));
524 return NULL;
527 switch (con->type)
529 case MSRPC_LOCAL:
531 return &con->msrpc.local->nt;
533 case MSRPC_SMB:
535 return &con->msrpc.smb->smb->nt;
538 return NULL;
541 /****************************************************************************
542 get a user session key associated with a connection associated with a
543 policy handle.
544 ****************************************************************************/
545 BOOL cli_get_con_sesskey(struct cli_connection *con, uchar sess_key[16])
547 struct ntdom_info *nt;
548 if (con == NULL)
550 return False;
552 nt = cli_conn_get_ntinfo(con);
553 memcpy(sess_key, nt->sess_key, sizeof(nt->sess_key));
555 dump_data_pw("sess_key:", sess_key, 16);
557 return True;
560 /****************************************************************************
561 get a server name associated with a connection associated with a
562 policy handle.
563 ****************************************************************************/
564 BOOL cli_con_get_srvname(struct cli_connection *con, char *srv_name)
566 char *desthost = NULL;
568 if (con == NULL)
570 return False;
573 switch (con->type)
575 case MSRPC_SMB:
577 desthost = con->msrpc.smb->smb->desthost;
578 break;
580 case MSRPC_LOCAL:
582 desthost = con->srv_name;
583 break;
587 if (strnequal("\\\\", desthost, 2))
589 fstrcpy(srv_name, desthost);
591 else
593 fstrcpy(srv_name, "\\\\");
594 fstrcat(srv_name, desthost);
597 return True;
600 /****************************************************************************
601 get a user session key associated with a connection associated with a
602 policy handle.
603 ****************************************************************************/
604 BOOL cli_get_sesskey(const POLICY_HND * pol, uchar sess_key[16])
606 struct cli_connection *con = NULL;
608 if (!cli_connection_get(pol, &con))
610 return False;
613 return cli_get_con_sesskey(con, sess_key);
616 /****************************************************************************
617 get a user session key associated with a connection associated with a
618 policy handle.
619 ****************************************************************************/
620 BOOL cli_get_sesskey_srv(const char *srv_name, uchar sess_key[16])
622 struct cli_connection *con = NULL;
624 if (!cli_connection_getsrv(srv_name, PIPE_NETLOGON, &con))
626 return False;
629 return cli_get_con_sesskey(con, sess_key);
632 /****************************************************************************
633 get a user session key associated with a connection associated with a
634 policy handle.
635 ****************************************************************************/
636 void cli_con_gen_next_creds(struct cli_connection *con,
637 DOM_CRED * new_clnt_cred)
639 struct ntdom_info *nt = cli_conn_get_ntinfo(con);
640 gen_next_creds(nt, new_clnt_cred);
643 /****************************************************************************
644 get a user session key associated with a connection associated with a
645 policy handle.
646 ****************************************************************************/
647 void cli_con_get_cli_cred(struct cli_connection *con, DOM_CRED * clnt_cred)
649 struct ntdom_info *nt = cli_conn_get_ntinfo(con);
650 memcpy(clnt_cred, &nt->clnt_cred, sizeof(*clnt_cred));
653 /****************************************************************************
654 get a user session key associated with a connection associated with a
655 policy handle.
656 ****************************************************************************/
657 BOOL cli_con_deal_with_creds(struct cli_connection *con,
658 DOM_CRED * rcv_srv_cred)
660 struct ntdom_info *nt = cli_conn_get_ntinfo(con);
661 return clnt_deal_with_creds(nt->sess_key, &nt->clnt_cred,
662 rcv_srv_cred);
665 /****************************************************************************
666 get a user session key associated with a connection associated with a
667 policy handle.
668 ****************************************************************************/
669 BOOL cli_con_set_creds(const char *srv_name, const uchar sess_key[16],
670 DOM_CRED * cred)
672 struct cli_connection *con = NULL;
673 struct ntdom_info *nt;
675 if (!cli_connection_getsrv(srv_name, PIPE_NETLOGON, &con))
677 return False;
680 nt = cli_conn_get_ntinfo(con);
682 memcpy(nt->sess_key, sess_key, 16);
683 memcpy(&nt->clnt_cred, cred, sizeof(*cred));
685 return True;
688 /****************************************************************************
689 send a request on an rpc pipe.
690 ****************************************************************************/
691 BOOL rpc_hnd_ok(const POLICY_HND *hnd)
693 struct cli_connection *con = NULL;
695 return cli_connection_get(hnd, &con) && rpc_con_ok(con);
698 /****************************************************************************
699 send a request on an rpc pipe.
700 ****************************************************************************/
701 BOOL rpc_hnd_pipe_req(const POLICY_HND * hnd, uint8 op_num,
702 prs_struct * data, prs_struct * rdata)
704 struct cli_connection *con = NULL;
706 if (!cli_connection_get(hnd, &con))
708 return False;
711 if (!rpc_con_ok(con)) return False;
713 return rpc_con_pipe_req(con, op_num, data, rdata);
716 /****************************************************************************
717 send a request on an rpc pipe.
718 ****************************************************************************/
719 BOOL rpc_con_pipe_req(struct cli_connection *con, uint8 op_num,
720 prs_struct * data, prs_struct * rdata)
722 BOOL ret;
723 DEBUG(10, ("rpc_con_pipe_req: op_num %d offset %d used: %d\n",
724 op_num, prs_offset(data), prs_data_size(data)));
725 prs_dump("in_rpcclient", (int)op_num, data);
726 prs_realloc_data(data, data->offset);
727 ret = rpc_api_pipe_req(con, op_num, data, rdata);
728 prs_dump("out_rpcclient", (int)op_num, rdata);
729 return ret;
732 /****************************************************************************
733 write to a pipe
734 ****************************************************************************/
735 BOOL rpc_api_write(struct cli_connection *con, prs_struct * data)
737 switch (con->type)
739 case MSRPC_SMB:
741 struct cli_state *cli = con->msrpc.smb->smb;
742 int fnum = con->msrpc.smb->fnum;
743 return cli_write(cli, fnum, 0x0008,
744 data->data, 0,
745 prs_data_size(data),
746 prs_data_size(data)) > 0;
748 case MSRPC_LOCAL:
750 data->offset = prs_data_size(data);
751 prs_link(NULL, data, NULL);
752 return msrpc_send(con->msrpc.local->fd, data);
755 return False;
758 BOOL rpc_api_rcv_pdu(struct cli_connection *con, prs_struct * rdata)
760 switch (con->type)
762 case MSRPC_SMB:
764 struct cli_state *cli = con->msrpc.smb->smb;
765 int fnum = con->msrpc.smb->fnum;
766 return cli_rcv_pdu(con, cli, fnum, rdata);
768 case MSRPC_LOCAL:
770 BOOL ret;
771 ret = msrpc_send(con->msrpc.local->fd, NULL);
772 ret = msrpc_receive(con->msrpc.local->fd, rdata);
773 rdata->io = True;
774 rdata->offset = 0;
775 rdata->start = 0;
776 rdata->end = prs_data_size(rdata);
777 return ret;
780 return False;
783 /* this allows us to detect dead servers. The cli->fd is set to -1 when
784 we get an error */
785 BOOL rpc_con_ok(struct cli_connection *con)
787 if (!con) return False;
789 switch (con->type)
791 case MSRPC_SMB:
793 struct cli_state *cli;
794 if (!con->msrpc.smb) return False;
795 cli = con->msrpc.smb->smb;
796 if (cli->fd == -1) return False;
797 return True;
799 break;
801 case MSRPC_LOCAL:
802 return True;
804 return False;
808 BOOL rpc_api_send_rcv_pdu(struct cli_connection *con, prs_struct * data,
809 prs_struct * rdata)
811 switch (con->type)
813 case MSRPC_SMB:
815 struct ntdom_info *nt = cli_conn_get_ntinfo(con);
816 struct cli_state *cli = con->msrpc.smb->smb;
817 int fnum = con->msrpc.smb->fnum;
818 if (cli->fd == -1) return False;
819 return cli_send_and_rcv_pdu(con, cli, fnum, data,
820 rdata, nt->max_xmit_frag);
822 case MSRPC_LOCAL:
824 BOOL ret;
825 data->offset = prs_data_size(data);
826 prs_link(NULL, data, NULL);
827 ret = msrpc_send(con->msrpc.local->fd, data) &&
828 msrpc_receive(con->msrpc.local->fd, rdata);
829 rdata->io = True;
830 rdata->offset = 0;
831 rdata->start = 0;
832 rdata->end = prs_data_size(rdata);
833 return ret;
836 return False;
839 /* connection policy state-info */
841 struct con_info
843 struct cli_connection *con;
844 void (*free_con) (struct cli_connection *);
847 static void free_policy_con(void *dev)
849 struct con_info *con = (struct con_info *)dev;
850 DEBUG(10, ("free policy connection\n"));
851 if (con->free_con != NULL)
853 con->free_con(con->con);
855 free(dev);
858 /****************************************************************************
859 set con state
860 ****************************************************************************/
861 BOOL set_policy_con(struct policy_cache *cache, POLICY_HND * hnd,
862 struct cli_connection *con,
863 void (*free_fn) (struct cli_connection *))
865 struct con_info *dev = (struct con_info *)malloc(sizeof(*dev));
867 if (dev != NULL)
869 dev->con = con;
870 dev->free_con = free_fn;
871 if (set_policy_state(cache, hnd,
872 free_policy_con, (void *)dev))
874 DEBUG(5, ("setting policy con\n"));
875 return True;
877 free(dev);
880 DEBUG(3, ("Error setting policy con state\n"));
881 return False;
884 /****************************************************************************
885 get con state
886 ****************************************************************************/
887 BOOL get_policy_con(struct policy_cache *cache, const POLICY_HND * hnd,
888 struct cli_connection **con)
890 struct con_info *dev;
891 dev = (struct con_info *)get_policy_state_info(cache, hnd);
893 if (dev != NULL)
895 DEBUG(5, ("Getting policy con state\n"));
896 (*con) = dev->con;
897 return True;
900 DEBUG(3, ("Error getting policy con state\n"));
901 return False;