s4:libcli: use smbcli_sock_connect() in smbcli_socket_connect()
[kai/samba.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    Copyright (C) James Peach 2005
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "libcli/libcli.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/raw/raw_proto.h"
27 #include "libcli/auth/libcli_auth.h"
28 #include "libcli/smb_composite/smb_composite.h"
29
30 /*
31   wrapper around smbcli_sock_connect()
32 */
33 bool smbcli_socket_connect(struct smbcli_state *cli, const char *server, 
34                            const char **ports, 
35                            struct tevent_context *ev_ctx,
36                            struct resolve_context *resolve_ctx,
37                            struct smbcli_options *options,
38                            const char *socket_options,
39                            struct nbt_name *calling,
40                            struct nbt_name *called)
41 {
42         struct smbcli_socket *sock;
43         uint32_t timeout_msec = options->request_timeout * 1000;
44         NTSTATUS status;
45
46         status = smbcli_sock_connect(cli,
47                                      NULL, /* host_addr */
48                                      ports,
49                                      server,
50                                      resolve_ctx,
51                                      ev_ctx,
52                                      socket_options,
53                                      &sock);
54         if (!NT_STATUS_IS_OK(status)) {
55                 return false;
56         }
57
58         status = smbcli_transport_connect(sock,
59                                           timeout_msec,
60                                           calling, called);
61         if (!NT_STATUS_IS_OK(status)) {
62                 return false;
63         }
64
65         cli->transport = smbcli_transport_init(sock, cli, true, options);
66         if (!cli->transport) {
67                 return false;
68         }
69
70         return true;
71 }
72
73 /* wrapper around smb_raw_negotiate() */
74 NTSTATUS smbcli_negprot(struct smbcli_state *cli, bool unicode, int maxprotocol)
75 {
76         return smb_raw_negotiate(cli->transport, unicode, maxprotocol);
77 }
78
79 /* wrapper around smb_raw_sesssetup() */
80 NTSTATUS smbcli_session_setup(struct smbcli_state *cli, 
81                               struct cli_credentials *credentials,
82                               const char *workgroup,
83                               struct smbcli_session_options options,
84                               struct gensec_settings *gensec_settings)
85 {
86         struct smb_composite_sesssetup setup;
87         NTSTATUS status;
88
89         cli->session = smbcli_session_init(cli->transport, cli, true,
90                                            options);
91         if (!cli->session) return NT_STATUS_UNSUCCESSFUL;
92
93         setup.in.sesskey = cli->transport->negotiate.sesskey;
94         setup.in.capabilities = cli->transport->negotiate.capabilities;
95         setup.in.credentials = credentials;
96         setup.in.workgroup = workgroup;
97         setup.in.gensec_settings = gensec_settings;
98
99         status = smb_composite_sesssetup(cli->session, &setup);
100
101         cli->session->vuid = setup.out.vuid;
102
103         return status;
104 }
105
106 /* wrapper around smb_raw_tcon() */
107 NTSTATUS smbcli_tconX(struct smbcli_state *cli, const char *sharename, 
108                       const char *devtype, const char *password)
109 {
110         union smb_tcon tcon;
111         TALLOC_CTX *mem_ctx;
112         NTSTATUS status;
113
114         cli->tree = smbcli_tree_init(cli->session, cli, true);
115         if (!cli->tree) return NT_STATUS_UNSUCCESSFUL;
116
117         mem_ctx = talloc_init("tcon");
118         if (!mem_ctx) {
119                 return NT_STATUS_NO_MEMORY;
120         }
121
122         /* setup a tree connect */
123         tcon.generic.level = RAW_TCON_TCONX;
124         tcon.tconx.in.flags = 0;
125         if (cli->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
126                 tcon.tconx.in.password = data_blob(NULL, 0);
127         } else if (cli->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
128                 tcon.tconx.in.password = data_blob_talloc(mem_ctx, NULL, 24);
129                 if (cli->transport->negotiate.secblob.length < 8) {
130                         return NT_STATUS_INVALID_PARAMETER;
131                 }
132                 SMBencrypt(password, cli->transport->negotiate.secblob.data, tcon.tconx.in.password.data);
133         } else {
134                 tcon.tconx.in.password = data_blob_talloc(mem_ctx, password, strlen(password)+1);
135         }
136         tcon.tconx.in.path = sharename;
137         tcon.tconx.in.device = devtype;
138         
139         status = smb_raw_tcon(cli->tree, mem_ctx, &tcon);
140
141         cli->tree->tid = tcon.tconx.out.tid;
142
143         talloc_free(mem_ctx);
144
145         return status;
146 }
147
148
149 /*
150   easy way to get to a fully connected smbcli_state in one call
151 */
152 NTSTATUS smbcli_full_connection(TALLOC_CTX *parent_ctx,
153                                 struct smbcli_state **ret_cli, 
154                                 const char *host,
155                                 const char **ports,
156                                 const char *sharename,
157                                 const char *devtype,
158                                 const char *socket_options,
159                                 struct cli_credentials *credentials,
160                                 struct resolve_context *resolve_ctx,
161                                 struct tevent_context *ev,
162                                 struct smbcli_options *options,
163                                 struct smbcli_session_options *session_options,
164                                 struct gensec_settings *gensec_settings)
165 {
166         struct smbcli_tree *tree;
167         NTSTATUS status;
168
169         *ret_cli = NULL;
170
171         status = smbcli_tree_full_connection(parent_ctx,
172                                              &tree, host, ports, 
173                                              sharename, devtype,
174                                                  socket_options,
175                                              credentials, resolve_ctx, ev,
176                                              options,
177                                              session_options,
178                                                  gensec_settings);
179         if (!NT_STATUS_IS_OK(status)) {
180                 goto done;
181         }
182
183         (*ret_cli) = smbcli_state_init(parent_ctx);
184
185         (*ret_cli)->tree = tree;
186         (*ret_cli)->session = tree->session;
187         (*ret_cli)->transport = tree->session->transport;
188
189         talloc_steal(*ret_cli, tree);
190         
191 done:
192         return status;
193 }
194
195
196 /*
197   disconnect the tree
198 */
199 NTSTATUS smbcli_tdis(struct smbcli_state *cli)
200 {
201         return smb_tree_disconnect(cli->tree);
202 }
203
204 /****************************************************************************
205  Initialise a client state structure.
206 ****************************************************************************/
207 struct smbcli_state *smbcli_state_init(TALLOC_CTX *mem_ctx)
208 {
209         return talloc_zero(mem_ctx, struct smbcli_state);
210 }
211
212 /* Insert a NULL at the first separator of the given path and return a pointer
213  * to the remainder of the string.
214  */
215 static char *
216 terminate_path_at_separator(char * path)
217 {
218         char * p;
219
220         if (!path) {
221                 return NULL;
222         }
223
224         if ((p = strchr_m(path, '/'))) {
225                 *p = '\0';
226                 return p + 1;
227         }
228
229         if ((p = strchr_m(path, '\\'))) {
230                 *p = '\0';
231                 return p + 1;
232         }
233         
234         /* No separator. */
235         return NULL;
236 }
237
238 /*
239   parse a //server/share type UNC name
240 */
241 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
242                       char **hostname, char **sharename)
243 {
244         char *p;
245
246         if (strncmp(unc_name, "\\\\", 2) &&
247             strncmp(unc_name, "//", 2)) {
248                 return false;
249         }
250
251         *hostname = *sharename = NULL;
252
253         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
254         p = terminate_path_at_separator(*hostname);
255
256         if (p != NULL && *p) {
257                 *sharename = talloc_strdup(mem_ctx, p);
258                 terminate_path_at_separator(*sharename);
259         }
260
261         if (*hostname && *sharename) {
262                 return true;
263         }
264
265         talloc_free(*hostname);
266         talloc_free(*sharename);
267         *hostname = *sharename = NULL;
268         return false;
269 }
270
271
272