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*/ 33bool 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 struct smb_iconv_convenience *iconv_convenience, 39 const char *socket_options) 40{ 41 struct smbcli_socket *sock; 42 43 sock = smbcli_sock_connect_byname(server, ports, NULL, 44 resolve_ctx, ev_ctx, 45 socket_options); 46 47 if (sock == NULL) return false; 48 49 cli->transport = smbcli_transport_init(sock, cli, true, options, 50 iconv_convenience); 51 if (!cli->transport) { 52 return false; 53 } 54 55 return true; 56} 57 58/* wrapper around smbcli_transport_connect() */ 59bool smbcli_transport_establish(struct smbcli_state *cli, 60 struct nbt_name *calling, 61 struct nbt_name *called) 62{ 63 return smbcli_transport_connect(cli->transport, calling, called); 64} 65 66/* wrapper around smb_raw_negotiate() */ 67NTSTATUS smbcli_negprot(struct smbcli_state *cli, bool unicode, int maxprotocol) 68{ 69 return smb_raw_negotiate(cli->transport, unicode, maxprotocol); 70} 71 72/* wrapper around smb_raw_sesssetup() */ 73NTSTATUS smbcli_session_setup(struct smbcli_state *cli, 74 struct cli_credentials *credentials, 75 const char *workgroup, 76 struct smbcli_session_options options, 77 struct gensec_settings *gensec_settings) 78{ 79 struct smb_composite_sesssetup setup; 80 NTSTATUS status; 81 82 cli->session = smbcli_session_init(cli->transport, cli, true, 83 options); 84 if (!cli->session) return NT_STATUS_UNSUCCESSFUL; 85 86 setup.in.sesskey = cli->transport->negotiate.sesskey; 87 setup.in.capabilities = cli->transport->negotiate.capabilities; 88 setup.in.credentials = credentials; 89 setup.in.workgroup = workgroup; 90 setup.in.gensec_settings = gensec_settings; 91 92 status = smb_composite_sesssetup(cli->session, &setup); 93 94 cli->session->vuid = setup.out.vuid; 95 96 return status; 97} 98 99/* wrapper around smb_raw_tcon() */ 100NTSTATUS smbcli_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_raw_tcon(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*/ 145NTSTATUS smbcli_full_connection(TALLOC_CTX *parent_ctx, 146 struct smbcli_state **ret_cli, 147 const char *host, 148 const char **ports, 149 const char *sharename, 150 const char *devtype, 151 const char *socket_options, 152 struct cli_credentials *credentials, 153 struct resolve_context *resolve_ctx, 154 struct tevent_context *ev, 155 struct smbcli_options *options, 156 struct smbcli_session_options *session_options, 157 struct smb_iconv_convenience *iconv_convenience, 158 struct gensec_settings *gensec_settings) 159{ 160 struct smbcli_tree *tree; 161 NTSTATUS status; 162 163 *ret_cli = NULL; 164 165 status = smbcli_tree_full_connection(parent_ctx, 166 &tree, host, ports, 167 sharename, devtype, 168 socket_options, 169 credentials, resolve_ctx, ev, 170 options, 171 session_options, 172 iconv_convenience, 173 gensec_settings); 174 if (!NT_STATUS_IS_OK(status)) { 175 goto done; 176 } 177 178 (*ret_cli) = smbcli_state_init(parent_ctx); 179 180 (*ret_cli)->tree = tree; 181 (*ret_cli)->session = tree->session; 182 (*ret_cli)->transport = tree->session->transport; 183 184 talloc_steal(*ret_cli, tree); 185 186done: 187 return status; 188} 189 190 191/* 192 disconnect the tree 193*/ 194NTSTATUS smbcli_tdis(struct smbcli_state *cli) 195{ 196 return smb_tree_disconnect(cli->tree); 197} 198 199/**************************************************************************** 200 Initialise a client state structure. 201****************************************************************************/ 202struct smbcli_state *smbcli_state_init(TALLOC_CTX *mem_ctx) 203{ 204 return talloc_zero(mem_ctx, struct smbcli_state); 205} 206 207/* Insert a NULL at the first separator of the given path and return a pointer 208 * to the remainder of the string. 209 */ 210static char * 211terminate_path_at_separator(char * path) 212{ 213 char * p; 214 215 if (!path) { 216 return NULL; 217 } 218 219 if ((p = strchr_m(path, '/'))) { 220 *p = '\0'; 221 return p + 1; 222 } 223 224 if ((p = strchr_m(path, '\\'))) { 225 *p = '\0'; 226 return p + 1; 227 } 228 229 /* No separator. */ 230 return NULL; 231} 232 233/* 234 parse a //server/share type UNC name 235*/ 236bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx, 237 char **hostname, char **sharename) 238{ 239 char *p; 240 241 *hostname = *sharename = NULL; 242 243 if (strncmp(unc_name, "\\\\", 2) && 244 strncmp(unc_name, "//", 2)) { 245 return false; 246 } 247 248 *hostname = talloc_strdup(mem_ctx, &unc_name[2]); 249 p = terminate_path_at_separator(*hostname); 250 251 if (p != NULL && *p) { 252 *sharename = talloc_strdup(mem_ctx, p); 253 terminate_path_at_separator(*sharename); 254 } 255 256 if (*hostname && *sharename) { 257 return true; 258 } 259 260 talloc_free(*hostname); 261 talloc_free(*sharename); 262 *hostname = *sharename = NULL; 263 return false; 264} 265 266 267 268