2 Unix SMB/Netbios implementation.
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.
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
;
35 { MSRPC_NONE
, MSRPC_LOCAL
, MSRPC_SMB
};
41 struct user_creds usr_creds
;
48 struct msrpc_local
*local
;
58 static struct cli_connection
**con_list
= NULL
;
59 static uint32 num_cons
= 0;
61 void init_connections(void)
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
,
85 void free_connections(void)
87 DEBUG(3, ("free_connections: closing all MSRPC connections\n"));
88 free_con_array(num_cons
, con_list
);
94 static struct cli_connection
*cli_con_get(const char *srv_name
,
95 const char *pipe_name
,
97 void *auth_creds
, BOOL reuse
)
99 struct cli_connection
*con
= NULL
;
100 BOOL is_new_connection
= False
;
104 con
= (struct cli_connection
*)malloc(sizeof(*con
));
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
;
130 con
->msrpc
.local
= ncalrpc_l_use_add(pipe_name
, user_key
,
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
);
143 struct ntuser_creds
*ntc
= NULL
;
144 if (usr_creds
!= NULL
)
146 ntc
= &usr_creds
->ntc
;
148 con
->type
= MSRPC_SMB
;
150 ncacn_np_use_add(pipe_name
, user_key
, srv_name
,
154 if (con
->msrpc
.smb
== NULL
)
156 cli_connection_free(con
);
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
)
174 con
->auth_info
= NULL
;
175 con
->auth_creds
= auth_creds
;
183 extern cli_auth_fns cli_noauth_fns
;
184 con
->auth
= &cli_noauth_fns
;
187 if (!rpc_pipe_bind(con
, pipe_name
, &abstract
,
190 DEBUG(0, ("rpc_pipe_bind failed\n"));
191 cli_connection_free(con
);
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
);
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
);
219 if (con
->type
== MSRPC_SMB
)
221 con
->msrpc
.smb
->smb
->nt
.key
= key
;
223 add_con_to_array(&num_cons
, &con_list
, con
);
227 /****************************************************************************
228 terminate client connection
229 ****************************************************************************/
230 void cli_connection_free(struct cli_connection
*con
)
235 DEBUG(10, ("cli_connection_free: %d\n", __LINE__
));
237 if (con
->msrpc
.cli
!= NULL
)
243 DEBUG(10, ("msrpc local connection\n"));
244 ncalrpc_l_use_del(con
->pipe_name
,
245 &con
->msrpc
.local
->nt
.key
,
247 con
->msrpc
.local
= NULL
;
252 DEBUG(10, ("msrpc smb connection\n"));
253 ncacn_np_use_del(con
->srv_name
,
255 &con
->msrpc
.smb
->smb
->nt
.key
,
257 con
->msrpc
.smb
= NULL
;
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
)
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
])
301 /****************************************************************************
302 terminate client state
303 ****************************************************************************/
304 void cli_connection_unlink(struct cli_connection
*con
)
308 cli_connection_free(con
);
313 /****************************************************************************
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 /****************************************************************************
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
)
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 /****************************************************************************
345 ****************************************************************************/
346 BOOL
cli_connection_getsrv(const char *srv_name
, const char *pipe_name
,
347 struct cli_connection
**con
)
350 struct cli_connection
*auth_con
= NULL
;
352 if (con_list
== NULL
|| num_cons
== 0)
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
)
375 if (auth_con
!= NULL
)
380 return (*con
) != NULL
;
383 /****************************************************************************
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"));
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
))
424 DEBUG(0, ("cli_get_usr_sesskey: no connection\n"));
427 nt
= cli_conn_get_ntinfo(con
);
430 DEBUG(0, ("cli_get_usr_sesskey: no ntdom_info\n"));
434 memcpy(usr_sess_key
, nt
->usr_sess_key
, sizeof(nt
->usr_sess_key
));
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
;
450 nt
= cli_conn_get_ntinfo(con
);
453 memcpy(nt
->usr_sess_key
, usr_sess_key
,
454 sizeof(nt
->usr_sess_key
));
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
;
471 nt
= cli_conn_get_ntinfo(con
);
472 if (nt
!= NULL
&& nt
->key
.vuid
!= UID_FIELD_INVALID
)
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
)
521 if (con
->msrpc
.cli
== NULL
)
523 DEBUG(1, ("cli_conn_get_ntinfo: NULL msrpc (closed)\n"));
531 return &con
->msrpc
.local
->nt
;
535 return &con
->msrpc
.smb
->smb
->nt
;
541 /****************************************************************************
542 get a user session key associated with a connection associated with a
544 ****************************************************************************/
545 BOOL
cli_get_con_sesskey(struct cli_connection
*con
, uchar sess_key
[16])
547 struct ntdom_info
*nt
;
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);
560 /****************************************************************************
561 get a server name associated with a connection associated with a
563 ****************************************************************************/
564 BOOL
cli_con_get_srvname(struct cli_connection
*con
, char *srv_name
)
566 char *desthost
= NULL
;
577 desthost
= con
->msrpc
.smb
->smb
->desthost
;
582 desthost
= con
->srv_name
;
587 if (strnequal("\\\\", desthost
, 2))
589 fstrcpy(srv_name
, desthost
);
593 fstrcpy(srv_name
, "\\\\");
594 fstrcat(srv_name
, desthost
);
600 /****************************************************************************
601 get a user session key associated with a connection associated with a
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
))
613 return cli_get_con_sesskey(con
, sess_key
);
616 /****************************************************************************
617 get a user session key associated with a connection associated with a
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
))
629 return cli_get_con_sesskey(con
, sess_key
);
632 /****************************************************************************
633 get a user session key associated with a connection associated with a
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
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
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
,
665 /****************************************************************************
666 get a user session key associated with a connection associated with a
668 ****************************************************************************/
669 BOOL
cli_con_set_creds(const char *srv_name
, const uchar sess_key
[16],
672 struct cli_connection
*con
= NULL
;
673 struct ntdom_info
*nt
;
675 if (!cli_connection_getsrv(srv_name
, PIPE_NETLOGON
, &con
))
680 nt
= cli_conn_get_ntinfo(con
);
682 memcpy(nt
->sess_key
, sess_key
, 16);
683 memcpy(&nt
->clnt_cred
, cred
, sizeof(*cred
));
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
))
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
)
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
);
732 /****************************************************************************
734 ****************************************************************************/
735 BOOL
rpc_api_write(struct cli_connection
*con
, prs_struct
* data
)
741 struct cli_state
*cli
= con
->msrpc
.smb
->smb
;
742 int fnum
= con
->msrpc
.smb
->fnum
;
743 return cli_write(cli
, fnum
, 0x0008,
746 prs_data_size(data
)) > 0;
750 data
->offset
= prs_data_size(data
);
751 prs_link(NULL
, data
, NULL
);
752 return msrpc_send(con
->msrpc
.local
->fd
, data
);
758 BOOL
rpc_api_rcv_pdu(struct cli_connection
*con
, prs_struct
* rdata
)
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
);
771 ret
= msrpc_send(con
->msrpc
.local
->fd
, NULL
);
772 ret
= msrpc_receive(con
->msrpc
.local
->fd
, rdata
);
776 rdata
->end
= prs_data_size(rdata
);
783 /* this allows us to detect dead servers. The cli->fd is set to -1 when
785 BOOL
rpc_con_ok(struct cli_connection
*con
)
787 if (!con
) return False
;
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
;
808 BOOL
rpc_api_send_rcv_pdu(struct cli_connection
*con
, prs_struct
* data
,
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
);
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
);
832 rdata
->end
= prs_data_size(rdata
);
839 /* connection policy state-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
);
858 /****************************************************************************
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
));
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"));
880 DEBUG(3, ("Error setting policy con state\n"));
884 /****************************************************************************
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
);
895 DEBUG(5, ("Getting policy con state\n"));
900 DEBUG(3, ("Error getting policy con state\n"));