root/source4/libcli/smb2/connect.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. continue_tcon
  2. continue_session
  3. continue_negprot
  4. continue_socket
  5. continue_resolve
  6. smb2_connect_send
  7. smb2_connect_recv
  8. smb2_connect

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    SMB2 composite connection setup
   5 
   6    Copyright (C) Andrew Tridgell 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 3 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, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "libcli/raw/libcliraw.h"
  24 #include "libcli/raw/raw_proto.h"
  25 #include "libcli/smb2/smb2.h"
  26 #include "libcli/smb2/smb2_calls.h"
  27 #include "libcli/composite/composite.h"
  28 #include "libcli/resolve/resolve.h"
  29 #include "param/param.h"
  30 
  31 struct smb2_connect_state {
  32         struct cli_credentials *credentials;
  33         struct resolve_context *resolve_ctx;
  34         const char *host;
  35         const char *share;
  36         const char **ports;
  37         const char *socket_options;
  38         struct gensec_settings *gensec_settings;
  39         struct smbcli_options options;
  40         struct smb2_negprot negprot;
  41         struct smb2_tree_connect tcon;
  42         struct smb2_session *session;
  43         struct smb2_tree *tree;
  44 };
  45 
  46 /*
  47   continue after tcon reply
  48 */
  49 static void continue_tcon(struct smb2_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
  50 {
  51         struct composite_context *c = talloc_get_type(req->async.private_data, 
  52                                                       struct composite_context);
  53         struct smb2_connect_state *state = talloc_get_type(c->private_data, 
  54                                                            struct smb2_connect_state);
  55 
  56         c->status = smb2_tree_connect_recv(req, &state->tcon);
  57         if (!composite_is_ok(c)) return;
  58         
  59         state->tree->tid = state->tcon.out.tid;
  60 
  61         composite_done(c);
  62 }
  63 
  64 /*
  65   continue after a session setup
  66 */
  67 static void continue_session(struct composite_context *creq)
     /* [<][>][^][v][top][bottom][index][help] */
  68 {
  69         struct composite_context *c = talloc_get_type(creq->async.private_data, 
  70                                                       struct composite_context);
  71         struct smb2_connect_state *state = talloc_get_type(c->private_data, 
  72                                                            struct smb2_connect_state);
  73         struct smb2_request *req;
  74 
  75         c->status = smb2_session_setup_spnego_recv(creq);
  76         if (!composite_is_ok(c)) return;
  77 
  78         state->tree = smb2_tree_init(state->session, state, true);
  79         if (composite_nomem(state->tree, c)) return;
  80 
  81         state->tcon.in.reserved = 0;
  82         state->tcon.in.path     = talloc_asprintf(state, "\\\\%s\\%s", 
  83                                                   state->host, state->share);
  84         if (composite_nomem(state->tcon.in.path, c)) return;
  85         
  86         req = smb2_tree_connect_send(state->tree, &state->tcon);
  87         if (composite_nomem(req, c)) return;
  88 
  89         req->async.fn = continue_tcon;
  90         req->async.private_data = c;    
  91 }
  92 
  93 /*
  94   continue after negprot reply
  95 */
  96 static void continue_negprot(struct smb2_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
  97 {
  98         struct composite_context *c = talloc_get_type(req->async.private_data, 
  99                                                       struct composite_context);
 100         struct smb2_connect_state *state = talloc_get_type(c->private_data, 
 101                                                            struct smb2_connect_state);
 102         struct smb2_transport *transport = req->transport;
 103         struct composite_context *creq;
 104 
 105         c->status = smb2_negprot_recv(req, c, &state->negprot);
 106         if (!composite_is_ok(c)) return;
 107 
 108         transport->negotiate.system_time = state->negprot.out.system_time;
 109         transport->negotiate.server_start_time = state->negprot.out.server_start_time;
 110         transport->negotiate.security_mode = state->negprot.out.security_mode;
 111 
 112         switch (transport->options.signing) {
 113         case SMB_SIGNING_OFF:
 114                 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
 115                         composite_error(c, NT_STATUS_ACCESS_DENIED);
 116                         return;
 117                 }
 118                 transport->signing_required = false;
 119                 break;
 120         case SMB_SIGNING_SUPPORTED:
 121                 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
 122                         transport->signing_required = true;
 123                 } else {
 124                         transport->signing_required = false;
 125                 }
 126                 break;
 127         case SMB_SIGNING_AUTO:
 128                 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) {
 129                         transport->signing_required = true;
 130                 } else {
 131                         transport->signing_required = false;
 132                 }
 133                 break;
 134         case SMB_SIGNING_REQUIRED:
 135                 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) {
 136                         transport->signing_required = true;
 137                 } else {
 138                         composite_error(c, NT_STATUS_ACCESS_DENIED);
 139                         return;
 140                 }
 141                 break;
 142         }
 143 
 144         state->session = smb2_session_init(transport, state->gensec_settings, state, true);
 145         if (composite_nomem(state->session, c)) return;
 146 
 147         creq = smb2_session_setup_spnego_send(state->session, state->credentials);
 148 
 149         composite_continue(c, creq, continue_session, c);
 150 }
 151 
 152 /*
 153   continue after a socket connect completes
 154 */
 155 static void continue_socket(struct composite_context *creq)
     /* [<][>][^][v][top][bottom][index][help] */
 156 {
 157         struct composite_context *c = talloc_get_type(creq->async.private_data, 
 158                                                       struct composite_context);
 159         struct smb2_connect_state *state = talloc_get_type(c->private_data, 
 160                                                            struct smb2_connect_state);
 161         struct smbcli_socket *sock;
 162         struct smb2_transport *transport;
 163         struct smb2_request *req;
 164         uint16_t dialects[2];
 165 
 166         c->status = smbcli_sock_connect_recv(creq, state, &sock);
 167         if (!composite_is_ok(c)) return;
 168 
 169         transport = smb2_transport_init(sock, state, &state->options);
 170         if (composite_nomem(transport, c)) return;
 171 
 172         ZERO_STRUCT(state->negprot);
 173         state->negprot.in.dialect_count = 2;
 174         switch (transport->options.signing) {
 175         case SMB_SIGNING_OFF:
 176                 state->negprot.in.security_mode = 0;
 177                 break;
 178         case SMB_SIGNING_SUPPORTED:
 179         case SMB_SIGNING_AUTO:
 180                 state->negprot.in.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
 181                 break;
 182         case SMB_SIGNING_REQUIRED:
 183                 state->negprot.in.security_mode = 
 184                         SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED;
 185                 break;
 186         }
 187         state->negprot.in.capabilities  = 0;
 188         unix_to_nt_time(&state->negprot.in.start_time, time(NULL));
 189         dialects[0] = SMB2_DIALECT_REVISION;
 190         dialects[1] = 0;
 191         state->negprot.in.dialects = dialects;
 192 
 193         req = smb2_negprot_send(transport, &state->negprot);
 194         if (composite_nomem(req, c)) return;
 195 
 196         req->async.fn = continue_negprot;
 197         req->async.private_data = c;
 198 }
 199 
 200 
 201 /*
 202   continue after a resolve finishes
 203 */
 204 static void continue_resolve(struct composite_context *creq)
     /* [<][>][^][v][top][bottom][index][help] */
 205 {
 206         struct composite_context *c = talloc_get_type(creq->async.private_data, 
 207                                                       struct composite_context);
 208         struct smb2_connect_state *state = talloc_get_type(c->private_data, 
 209                                                            struct smb2_connect_state);
 210         const char *addr;
 211         const char **ports;
 212         const char *default_ports[] = { "445", NULL };
 213 
 214         c->status = resolve_name_recv(creq, state, &addr);
 215         if (!composite_is_ok(c)) return;
 216 
 217         if (state->ports == NULL) {
 218                 ports = default_ports;
 219         } else {
 220                 ports = state->ports;
 221         }
 222 
 223         creq = smbcli_sock_connect_send(state, addr, ports, state->host, state->resolve_ctx, c->event_ctx, state->socket_options);
 224 
 225         composite_continue(c, creq, continue_socket, c);
 226 }
 227 
 228 /*
 229   a composite function that does a full negprot/sesssetup/tcon, returning
 230   a connected smb2_tree
 231  */
 232 struct composite_context *smb2_connect_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 233                                             const char *host,
 234                                                 const char **ports,
 235                                             const char *share,
 236                                             struct resolve_context *resolve_ctx,
 237                                             struct cli_credentials *credentials,
 238                                             struct tevent_context *ev,
 239                                             struct smbcli_options *options,
 240                                                 const char *socket_options,
 241                                                 struct gensec_settings *gensec_settings)
 242 {
 243         struct composite_context *c;
 244         struct smb2_connect_state *state;
 245         struct nbt_name name;
 246         struct composite_context *creq;
 247 
 248         c = composite_create(mem_ctx, ev);
 249         if (c == NULL) return NULL;
 250 
 251         state = talloc(c, struct smb2_connect_state);
 252         if (composite_nomem(state, c)) return c;
 253         c->private_data = state;
 254 
 255         state->credentials = credentials;
 256         state->options = *options;
 257         state->host = talloc_strdup(c, host);
 258         if (composite_nomem(state->host, c)) return c;
 259         state->ports = talloc_reference(state, ports);
 260         state->share = talloc_strdup(c, share);
 261         if (composite_nomem(state->share, c)) return c;
 262         state->resolve_ctx = talloc_reference(state, resolve_ctx);
 263         state->socket_options = talloc_reference(state, socket_options);
 264         state->gensec_settings = talloc_reference(state, gensec_settings);
 265 
 266         ZERO_STRUCT(name);
 267         name.name = host;
 268 
 269         creq = resolve_name_send(resolve_ctx, &name, c->event_ctx);
 270         composite_continue(c, creq, continue_resolve, c);
 271         return c;
 272 }
 273 
 274 /*
 275   receive a connect reply
 276 */
 277 NTSTATUS smb2_connect_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 278                            struct smb2_tree **tree)
 279 {
 280         NTSTATUS status;
 281         struct smb2_connect_state *state = talloc_get_type(c->private_data, 
 282                                                            struct smb2_connect_state);
 283         status = composite_wait(c);
 284         if (NT_STATUS_IS_OK(status)) {
 285                 *tree = talloc_steal(mem_ctx, state->tree);
 286         }
 287         talloc_free(c);
 288         return status;
 289 }
 290 
 291 /*
 292   sync version of smb2_connect
 293 */
 294 NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 295                       const char *host, const char **ports, 
 296                           const char *share,
 297                       struct resolve_context *resolve_ctx,
 298                       struct cli_credentials *credentials,
 299                       struct smb2_tree **tree,
 300                       struct tevent_context *ev,
 301                       struct smbcli_options *options,
 302                           const char *socket_options,
 303                           struct gensec_settings *gensec_settings)
 304 {
 305         struct composite_context *c = smb2_connect_send(mem_ctx, host, ports, 
 306                                                                                                         share, resolve_ctx, 
 307                                                                                                         credentials, ev, options,
 308                                                                                                         socket_options,
 309                                                                                                         gensec_settings);
 310         return smb2_connect_recv(c, mem_ctx, tree);
 311 }

/* [<][>][^][v][top][bottom][index][help] */