build: put doserr.c into it's own subsystem, so it's no longer a duplicate
[metze/samba/wip.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 {
40         struct smbcli_socket *sock;
41
42         sock = smbcli_sock_connect_byname(server, ports, NULL,
43                                           resolve_ctx, ev_ctx,
44                       socket_options);
45
46         if (sock == NULL) return false;
47         
48         cli->transport = smbcli_transport_init(sock, cli, true, options);
49         if (!cli->transport) {
50                 return false;
51         }
52
53         return true;
54 }
55
56 /* wrapper around smbcli_transport_connect() */
57 bool smbcli_transport_establish(struct smbcli_state *cli, 
58                                 struct nbt_name *calling,
59                                 struct nbt_name *called)
60 {
61         return smbcli_transport_connect(cli->transport, calling, called);
62 }
63
64 /* wrapper around smb_raw_negotiate() */
65 NTSTATUS smbcli_negprot(struct smbcli_state *cli, bool unicode, int maxprotocol)
66 {
67         return smb_raw_negotiate(cli->transport, unicode, maxprotocol);
68 }
69
70 /* wrapper around smb_raw_sesssetup() */
71 NTSTATUS smbcli_session_setup(struct smbcli_state *cli, 
72                               struct cli_credentials *credentials,
73                               const char *workgroup,
74                               struct smbcli_session_options options,
75                               struct gensec_settings *gensec_settings)
76 {
77         struct smb_composite_sesssetup setup;
78         NTSTATUS status;
79
80         cli->session = smbcli_session_init(cli->transport, cli, true,
81                                            options);
82         if (!cli->session) return NT_STATUS_UNSUCCESSFUL;
83
84         setup.in.sesskey = cli->transport->negotiate.sesskey;
85         setup.in.capabilities = cli->transport->negotiate.capabilities;
86         setup.in.credentials = credentials;
87         setup.in.workgroup = workgroup;
88         setup.in.gensec_settings = gensec_settings;
89
90         status = smb_composite_sesssetup(cli->session, &setup);
91
92         cli->session->vuid = setup.out.vuid;
93
94         return status;
95 }
96
97 /* wrapper around smb_raw_tcon() */
98 NTSTATUS smbcli_tconX(struct smbcli_state *cli, const char *sharename, 
99                       const char *devtype, const char *password)
100 {
101         union smb_tcon tcon;
102         TALLOC_CTX *mem_ctx;
103         NTSTATUS status;
104
105         cli->tree = smbcli_tree_init(cli->session, cli, true);
106         if (!cli->tree) return NT_STATUS_UNSUCCESSFUL;
107
108         mem_ctx = talloc_init("tcon");
109         if (!mem_ctx) {
110                 return NT_STATUS_NO_MEMORY;
111         }
112
113         /* setup a tree connect */
114         tcon.generic.level = RAW_TCON_TCONX;
115         tcon.tconx.in.flags = 0;
116         if (cli->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
117                 tcon.tconx.in.password = data_blob(NULL, 0);
118         } else if (cli->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
119                 tcon.tconx.in.password = data_blob_talloc(mem_ctx, NULL, 24);
120                 if (cli->transport->negotiate.secblob.length < 8) {
121                         return NT_STATUS_INVALID_PARAMETER;
122                 }
123                 SMBencrypt(password, cli->transport->negotiate.secblob.data, tcon.tconx.in.password.data);
124         } else {
125                 tcon.tconx.in.password = data_blob_talloc(mem_ctx, password, strlen(password)+1);
126         }
127         tcon.tconx.in.path = sharename;
128         tcon.tconx.in.device = devtype;
129         
130         status = smb_raw_tcon(cli->tree, mem_ctx, &tcon);
131
132         cli->tree->tid = tcon.tconx.out.tid;
133
134         talloc_free(mem_ctx);
135
136         return status;
137 }
138
139
140 /*
141   easy way to get to a fully connected smbcli_state in one call
142 */
143 NTSTATUS smbcli_full_connection(TALLOC_CTX *parent_ctx,
144                                 struct smbcli_state **ret_cli, 
145                                 const char *host,
146                                 const char **ports,
147                                 const char *sharename,
148                                 const char *devtype,
149                                 const char *socket_options,
150                                 struct cli_credentials *credentials,
151                                 struct resolve_context *resolve_ctx,
152                                 struct tevent_context *ev,
153                                 struct smbcli_options *options,
154                                 struct smbcli_session_options *session_options,
155                                 struct gensec_settings *gensec_settings)
156 {
157         struct smbcli_tree *tree;
158         NTSTATUS status;
159
160         *ret_cli = NULL;
161
162         status = smbcli_tree_full_connection(parent_ctx,
163                                              &tree, host, ports, 
164                                              sharename, devtype,
165                                                  socket_options,
166                                              credentials, resolve_ctx, ev,
167                                              options,
168                                              session_options,
169                                                  gensec_settings);
170         if (!NT_STATUS_IS_OK(status)) {
171                 goto done;
172         }
173
174         (*ret_cli) = smbcli_state_init(parent_ctx);
175
176         (*ret_cli)->tree = tree;
177         (*ret_cli)->session = tree->session;
178         (*ret_cli)->transport = tree->session->transport;
179
180         talloc_steal(*ret_cli, tree);
181         
182 done:
183         return status;
184 }
185
186
187 /*
188   disconnect the tree
189 */
190 NTSTATUS smbcli_tdis(struct smbcli_state *cli)
191 {
192         return smb_tree_disconnect(cli->tree);
193 }
194
195 /****************************************************************************
196  Initialise a client state structure.
197 ****************************************************************************/
198 struct smbcli_state *smbcli_state_init(TALLOC_CTX *mem_ctx)
199 {
200         return talloc_zero(mem_ctx, struct smbcli_state);
201 }
202
203 /* Insert a NULL at the first separator of the given path and return a pointer
204  * to the remainder of the string.
205  */
206 static char *
207 terminate_path_at_separator(char * path)
208 {
209         char * p;
210
211         if (!path) {
212                 return NULL;
213         }
214
215         if ((p = strchr_m(path, '/'))) {
216                 *p = '\0';
217                 return p + 1;
218         }
219
220         if ((p = strchr_m(path, '\\'))) {
221                 *p = '\0';
222                 return p + 1;
223         }
224         
225         /* No separator. */
226         return NULL;
227 }
228
229 /*
230   parse a //server/share type UNC name
231 */
232 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
233                       char **hostname, char **sharename)
234 {
235         char *p;
236
237         if (strncmp(unc_name, "\\\\", 2) &&
238             strncmp(unc_name, "//", 2)) {
239                 return false;
240         }
241
242         *hostname = *sharename = NULL;
243
244         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
245         p = terminate_path_at_separator(*hostname);
246
247         if (p != NULL && *p) {
248                 *sharename = talloc_strdup(mem_ctx, p);
249                 terminate_path_at_separator(*sharename);
250         }
251
252         if (*hostname && *sharename) {
253                 return true;
254         }
255
256         talloc_free(*hostname);
257         talloc_free(*sharename);
258         *hostname = *sharename = NULL;
259         return false;
260 }
261
262
263