Merge branch 'v4-0-test' of git://git.samba.org/samba into 4-0-local
[jelmer/samba4-debian.git] / source / libcli / smb2 / connect.c
index 18f28539ea09f1649e18e4c13427dc3448591a2f..85ddafc031fcdab08fa114804ec1ecb030f1046e 100644 (file)
@@ -7,7 +7,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "libcli/smb2/smb2.h"
 #include "libcli/smb2/smb2_calls.h"
 #include "libcli/composite/composite.h"
+#include "libcli/resolve/resolve.h"
+#include "param/param.h"
 
 struct smb2_connect_state {
-       struct smb2_request *req;
-       struct composite_context *creq;
        struct cli_credentials *credentials;
+       struct resolve_context *resolve_ctx;
        const char *host;
        const char *share;
        struct smb2_negprot negprot;
@@ -49,10 +49,7 @@ static void continue_tcon(struct smb2_request *req)
                                                           struct smb2_connect_state);
 
        c->status = smb2_tree_connect_recv(req, &state->tcon);
-       if (!NT_STATUS_IS_OK(c->status)) {
-               composite_error(c, c->status);
-               return;
-       }
+       if (!composite_is_ok(c)) return;
        
        state->tree->tid = state->tcon.out.tid;
 
@@ -68,35 +65,24 @@ static void continue_session(struct composite_context *creq)
                                                      struct composite_context);
        struct smb2_connect_state *state = talloc_get_type(c->private_data, 
                                                           struct smb2_connect_state);
+       struct smb2_request *req;
 
        c->status = smb2_session_setup_spnego_recv(creq);
-       if (!NT_STATUS_IS_OK(c->status)) {
-               composite_error(c, c->status);
-               return;
-       }
+       if (!composite_is_ok(c)) return;
 
-       state->tree = smb2_tree_init(state->session, state, True);
-       if (state->tree == NULL) {
-               composite_error(c, NT_STATUS_NO_MEMORY);
-               return;
-       }
+       state->tree = smb2_tree_init(state->session, state, true);
+       if (composite_nomem(state->tree, c)) return;
 
-       state->tcon.in.unknown1 = 0x09;
+       state->tcon.in.reserved = 0;
        state->tcon.in.path     = talloc_asprintf(state, "\\\\%s\\%s", 
                                                  state->host, state->share);
-       if (state->tcon.in.path == NULL) {
-               composite_error(c, NT_STATUS_NO_MEMORY);
-               return;
-       }
+       if (composite_nomem(state->tcon.in.path, c)) return;
        
-       state->req = smb2_tree_connect_send(state->tree, &state->tcon);
-       if (state->req == NULL) {
-               composite_error(c, NT_STATUS_NO_MEMORY);
-               return;
-       }
+       req = smb2_tree_connect_send(state->tree, &state->tcon);
+       if (composite_nomem(req, c)) return;
 
-       state->req->async.fn = continue_tcon;
-       state->req->async.private = c;  
+       req->async.fn = continue_tcon;
+       req->async.private = c; 
 }
 
 /*
@@ -109,27 +95,17 @@ static void continue_negprot(struct smb2_request *req)
        struct smb2_connect_state *state = talloc_get_type(c->private_data, 
                                                           struct smb2_connect_state);
        struct smb2_transport *transport = req->transport;
+       struct composite_context *creq;
 
        c->status = smb2_negprot_recv(req, c, &state->negprot);
-       if (!NT_STATUS_IS_OK(c->status)) {
-               composite_error(c, c->status);
-               return;
-       }
+       if (!composite_is_ok(c)) return;
 
-       state->session = smb2_session_init(transport, state, True);
-       if (state->session == NULL) {
-               composite_error(c, NT_STATUS_NO_MEMORY);
-               return;
-       }
+       state->session = smb2_session_init(transport, global_loadparm, state, true);
+       if (composite_nomem(state->session, c)) return;
 
-       state->creq = smb2_session_setup_spnego_send(state->session, state->credentials);
-       if (state->creq == NULL) {
-               composite_error(c, NT_STATUS_NO_MEMORY);
-               return;
-       }
+       creq = smb2_session_setup_spnego_send(state->session, state->credentials);
 
-       state->creq->async.fn = continue_session;
-       state->creq->async.private_data = c;
+       composite_continue(c, creq, continue_session, c);
 }
 
 /*
@@ -143,30 +119,28 @@ static void continue_socket(struct composite_context *creq)
                                                           struct smb2_connect_state);
        struct smbcli_socket *sock;
        struct smb2_transport *transport;
+       struct smb2_request *req;
+       uint16_t dialects[1];
 
        c->status = smbcli_sock_connect_recv(creq, state, &sock);
-       if (!NT_STATUS_IS_OK(c->status)) {
-               composite_error(c, c->status);
-               return;
-       }
+       if (!composite_is_ok(c)) return;
 
        transport = smb2_transport_init(sock, state);
-       if (transport == NULL) {
-               composite_error(c, NT_STATUS_NO_MEMORY);
-               return;
-       }
+       if (composite_nomem(transport, c)) return;
 
        ZERO_STRUCT(state->negprot);
-       state->negprot.in.unknown1 = 0x010024;
-       
-       state->req = smb2_negprot_send(transport, &state->negprot);
-       if (state->req == NULL) {
-               composite_error(c, NT_STATUS_NO_MEMORY);
-               return;
-       }
-
-       state->req->async.fn = continue_negprot;
-       state->req->async.private = c;
+       state->negprot.in.dialect_count = 1;
+       state->negprot.in.security_mode = 0;
+       state->negprot.in.capabilities  = 0;
+       unix_to_nt_time(&state->negprot.in.start_time, time(NULL));
+       dialects[0] = SMB2_DIALECT_REVISION;
+       state->negprot.in.dialects = dialects;
+
+       req = smb2_negprot_send(transport, &state->negprot);
+       if (composite_nomem(req, c)) return;
+
+       req->async.fn = continue_negprot;
+       req->async.private = c;
 }
 
 
@@ -180,21 +154,14 @@ static void continue_resolve(struct composite_context *creq)
        struct smb2_connect_state *state = talloc_get_type(c->private_data, 
                                                           struct smb2_connect_state);
        const char *addr;
-       
+       const char *ports[2] = { "445", NULL };
+
        c->status = resolve_name_recv(creq, state, &addr);
-       if (!NT_STATUS_IS_OK(c->status)) {
-               composite_error(c, c->status);
-               return;
-       }
+       if (!composite_is_ok(c)) return;
 
-       state->creq = smbcli_sock_connect_send(state, addr, 445, state->host, c->event_ctx);
-       if (state->creq == NULL) {
-               composite_error(c, NT_STATUS_NO_MEMORY);
-               return;
-       }
+       creq = smbcli_sock_connect_send(state, addr, ports, state->host, state->resolve_ctx, c->event_ctx);
 
-       state->creq->async.private_data = c;
-       state->creq->async.fn = continue_socket;
+       composite_continue(c, creq, continue_socket, c);
 }
 
 /*
@@ -204,47 +171,34 @@ static void continue_resolve(struct composite_context *creq)
 struct composite_context *smb2_connect_send(TALLOC_CTX *mem_ctx,
                                            const char *host,
                                            const char *share,
+                                           struct resolve_context *resolve_ctx,
                                            struct cli_credentials *credentials,
                                            struct event_context *ev)
 {
        struct composite_context *c;
        struct smb2_connect_state *state;
        struct nbt_name name;
+       struct composite_context *creq;
 
-       c = talloc_zero(mem_ctx, struct composite_context);
+       c = composite_create(mem_ctx, ev);
        if (c == NULL) return NULL;
 
        state = talloc(c, struct smb2_connect_state);
-       if (state == NULL) {
-               c->status = NT_STATUS_NO_MEMORY;
-               goto failed;
-       }
-
-       c->state = COMPOSITE_STATE_IN_PROGRESS;
+       if (composite_nomem(state, c)) return c;
        c->private_data = state;
-       c->event_ctx = ev;
 
        state->credentials = credentials;
        state->host = talloc_strdup(c, host);
+       if (composite_nomem(state->host, c)) return c;
        state->share = talloc_strdup(c, share);
-       if (state->host == NULL || state->share == NULL) {
-               c->status = NT_STATUS_NO_MEMORY;
-               goto failed;
-       }
+       if (composite_nomem(state->share, c)) return c;
+       state->resolve_ctx = talloc_reference(state, resolve_ctx);
 
        ZERO_STRUCT(name);
        name.name = host;
 
-       state->creq = resolve_name_send(&name, c->event_ctx, lp_name_resolve_order());
-       if (state->creq == NULL) goto failed;
-
-       state->creq->async.private_data = c;
-       state->creq->async.fn = continue_resolve;
-
-       return c;
-
-failed:
-       composite_trigger_error(c);
+       creq = resolve_name_send(resolve_ctx, &name, c->event_ctx);
+       composite_continue(c, creq, continue_resolve, c);
        return c;
 }
 
@@ -270,11 +224,13 @@ NTSTATUS smb2_connect_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
 */
 NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx, 
                      const char *host, const char *share,
+                     struct resolve_context *resolve_ctx,
                      struct cli_credentials *credentials,
                      struct smb2_tree **tree,
                      struct event_context *ev)
 {
        struct composite_context *c = smb2_connect_send(mem_ctx, host, share, 
+                                                       resolve_ctx,
                                                        credentials, ev);
        return smb2_connect_recv(c, mem_ctx, tree);
 }