r5941: Commit this patch much earlier than I would normally prefer, but metze needs...
[gd/samba-autobuild/.git] / source4 / libcli / cliconnect.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    client connect/disconnect routines
5
6    Copyright (C) Andrew Tridgell 2003-2005
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 #include "includes.h"
24 #include "libcli/raw/libcliraw.h"
25 #include "libcli/composite/composite.h"
26
27 /*
28   wrapper around smbcli_sock_connect()
29 */
30 BOOL smbcli_socket_connect(struct smbcli_state *cli, const char *server)
31 {
32         struct smbcli_socket *sock;
33
34         sock = smbcli_sock_init(cli, NULL);
35         if (!sock) return False;
36
37         if (!smbcli_sock_connect_byname(sock, server, 0)) {
38                 talloc_free(sock);
39                 return False;
40         }
41         
42         cli->transport = smbcli_transport_init(sock, cli, True);
43         if (!cli->transport) {
44                 return False;
45         }
46
47         return True;
48 }
49
50 /* wrapper around smbcli_transport_connect() */
51 BOOL smbcli_transport_establish(struct smbcli_state *cli, 
52                                 struct nbt_name *calling,
53                                 struct nbt_name *called)
54 {
55         return smbcli_transport_connect(cli->transport, calling, called);
56 }
57
58 /* wrapper around smb_raw_negotiate() */
59 NTSTATUS smbcli_negprot(struct smbcli_state *cli)
60 {
61         return smb_raw_negotiate(cli->transport, lp_maxprotocol());
62 }
63
64 /* wrapper around smb_raw_session_setup() */
65 NTSTATUS smbcli_session_setup(struct smbcli_state *cli, 
66                                                           struct cli_credentials *credentials)
67 {
68         struct smb_composite_sesssetup setup;
69         NTSTATUS status;
70         TALLOC_CTX *mem_ctx;
71
72         cli->session = smbcli_session_init(cli->transport, cli, True);
73         if (!cli->session) return NT_STATUS_UNSUCCESSFUL;
74
75         mem_ctx = talloc_init("smbcli_session_setup");
76         if (!mem_ctx) return NT_STATUS_NO_MEMORY;
77
78         setup.in.sesskey = cli->transport->negotiate.sesskey;
79         setup.in.capabilities = cli->transport->negotiate.capabilities;
80         if (cli_credentials_is_anonymous(credentials)) {
81                 if (cli->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
82                         setup.in.password = cli_credentials_get_password(credentials);
83                 } else {
84                         setup.in.password = NULL;
85                 }
86                 setup.in.user = cli_credentials_get_username(credentials);
87                 setup.in.domain = cli_credentials_get_domain(credentials);
88         }
89
90         status = smb_composite_sesssetup(cli->session, &setup);
91
92         cli->session->vuid = setup.out.vuid;
93
94         talloc_free(mem_ctx);
95
96         return status;
97 }
98
99 /* wrapper around smb_tree_connect() */
100 NTSTATUS smbcli_send_tconX(struct smbcli_state *cli, const char *sharename, 
101                            const char *devtype, const char *password)
102 {
103         union smb_tcon tcon;
104         TALLOC_CTX *mem_ctx;
105         NTSTATUS status;
106
107         cli->tree = smbcli_tree_init(cli->session, cli, True);
108         if (!cli->tree) return NT_STATUS_UNSUCCESSFUL;
109
110         mem_ctx = talloc_init("tcon");
111         if (!mem_ctx) {
112                 return NT_STATUS_NO_MEMORY;
113         }
114
115         /* setup a tree connect */
116         tcon.generic.level = RAW_TCON_TCONX;
117         tcon.tconx.in.flags = 0;
118         if (cli->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
119                 tcon.tconx.in.password = data_blob(NULL, 0);
120         } else if (cli->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
121                 tcon.tconx.in.password = data_blob_talloc(mem_ctx, NULL, 24);
122                 if (cli->transport->negotiate.secblob.length < 8) {
123                         return NT_STATUS_INVALID_PARAMETER;
124                 }
125                 SMBencrypt(password, cli->transport->negotiate.secblob.data, tcon.tconx.in.password.data);
126         } else {
127                 tcon.tconx.in.password = data_blob_talloc(mem_ctx, password, strlen(password)+1);
128         }
129         tcon.tconx.in.path = sharename;
130         tcon.tconx.in.device = devtype;
131         
132         status = smb_tree_connect(cli->tree, mem_ctx, &tcon);
133
134         cli->tree->tid = tcon.tconx.out.tid;
135
136         talloc_free(mem_ctx);
137
138         return status;
139 }
140
141
142 /*
143   easy way to get to a fully connected smbcli_state in one call
144 */
145 NTSTATUS smbcli_full_connection(TALLOC_CTX *parent_ctx,
146                                 struct smbcli_state **ret_cli, 
147                                 const char *myname,
148                                 const char *host,
149                                 const char *sharename,
150                                 const char *devtype,
151                                 struct cli_credentials *credentials)
152 {
153         struct smbcli_tree *tree;
154         NTSTATUS status;
155         TALLOC_CTX *mem_ctx;
156
157         mem_ctx = talloc_init("smbcli_full_connection");
158
159         *ret_cli = NULL;
160
161         status = smbcli_tree_full_connection(parent_ctx,
162                                              &tree, myname, host, 0, sharename, devtype,
163                                              credentials);
164         if (!NT_STATUS_IS_OK(status)) {
165                 goto done;
166         }
167
168         (*ret_cli) = smbcli_state_init(parent_ctx);
169
170         (*ret_cli)->tree = tree;
171         (*ret_cli)->session = tree->session;
172         (*ret_cli)->transport = tree->session->transport;
173         
174 done:
175         talloc_free(mem_ctx);
176
177         return status;
178 }
179
180
181 /*
182   disconnect the tree
183 */
184 NTSTATUS smbcli_tdis(struct smbcli_state *cli)
185 {
186         return smb_tree_disconnect(cli->tree);
187 }
188
189 /****************************************************************************
190  Initialise a client state structure.
191 ****************************************************************************/
192 struct smbcli_state *smbcli_state_init(TALLOC_CTX *mem_ctx)
193 {
194         struct smbcli_state *cli;
195
196         cli = talloc_zero(mem_ctx, struct smbcli_state);
197         if (cli) {
198                 ZERO_STRUCTP(cli);
199         }
200
201         return cli;
202 }
203
204 /****************************************************************************
205  Shutdown a client structure.
206 ****************************************************************************/
207 void smbcli_shutdown(struct smbcli_state *cli)
208 {
209         talloc_free(cli);
210 }
211
212 /*
213   parse a //server/share type UNC name
214 */
215 BOOL smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
216                       const char **hostname, const char **sharename)
217 {
218         char *p;
219
220         if (strncmp(unc_name, "\\\\", 2) &&
221             strncmp(unc_name, "//", 2)) {
222                 return False;
223         }
224
225         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
226         p = strchr_m(&(*hostname)[2],'/');
227         if (!p) {
228                 p = strchr_m(&(*hostname)[2],'\\');
229                 if (!p) return False;
230         }
231         *p = 0;
232         *sharename = talloc_strdup(mem_ctx, p+1);
233
234         return True;
235 }
236
237
238