s3:libsmb: split cli->secblob into cli->conn.smb1.server.{guid,gss_blob,challenge...
authorStefan Metzmacher <metze@samba.org>
Tue, 13 Sep 2011 19:34:35 +0000 (21:34 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 15 Sep 2011 10:12:28 +0000 (12:12 +0200)
metze

source3/include/client.h
source3/libsmb/cliconnect.c
source3/libsmb/clientgen.c

index 4179ae0f52fc75f1fe914e0a133aabe12b694396..cdf8069dfb911caed8364a41f16b55bb122cd284 100644 (file)
@@ -62,7 +62,6 @@ struct cli_state {
        char *share;
        char *dev;
 
-       DATA_BLOB secblob; /* cryptkey or negTokenInit */
        int serverzone;
        uint32 servertime;
        int timeout; /* in milliseconds. */
@@ -137,6 +136,10 @@ struct cli_state {
                                bool lockread;
                                bool writeunlock;
                                uint32_t session_key;
+                               struct GUID guid;
+                               DATA_BLOB gss_blob;
+                               uint8_t challenge[8];
+                               const char *workgroup;
                        } server;
 
                        uint32_t capabilities;
index 4963332c0dcc85448077981aedad9237256fdb2f..a02e7dd7d3c3be1a9763807fd74ab8c1808a307f 100644 (file)
@@ -33,6 +33,7 @@
 #include "async_smb.h"
 #include "libsmb/nmblib.h"
 #include "read_smb.h"
+#include "librpc/ndr/libndr.h"
 
 static const struct {
        int prot;
@@ -2622,8 +2623,14 @@ static void cli_negprot_done(struct tevent_req *subreq)
        bool server_writebraw = false;
        bool server_lockread = false;
        bool server_writeunlock = false;
+       struct GUID server_guid = GUID_zero();
+       DATA_BLOB server_gss_blob = data_blob_null;
+       uint8_t server_challenge[8];
+       char *server_workgroup = NULL;
        enum protocol_types protocol;
 
+       ZERO_STRUCT(server_challenge);
+
        status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
                              &num_bytes, &bytes);
        TALLOC_FREE(subreq);
@@ -2663,6 +2670,7 @@ static void cli_negprot_done(struct tevent_req *subreq)
                bool server_allowed;
                const char *server_signing = NULL;
                bool ok;
+               uint16_t key_len;
 
                if (wct != 0x11) {
                        tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
@@ -2680,6 +2688,9 @@ static void cli_negprot_done(struct tevent_req *subreq)
                ts = interpret_long_date(((char *)(vwv+11))+1);
                cli->servertime = ts.tv_sec;
                server_capabilities = IVAL(vwv + 9, 1);
+
+               key_len = CVAL(vwv + 16, 1);
+
                if (server_capabilities & CAP_RAW_MODE) {
                        server_readbraw = true;
                        server_writebraw = true;
@@ -2687,22 +2698,53 @@ static void cli_negprot_done(struct tevent_req *subreq)
                if (server_capabilities & CAP_LOCK_AND_READ) {
                        server_lockread = true;
                }
+
                if (server_capabilities & CAP_EXTENDED_SECURITY) {
+                       DATA_BLOB blob1, blob2;
+
                        if (num_bytes < 16) {
-                               tevent_req_nterror(req,
-                                       NT_STATUS_INVALID_NETWORK_RESPONSE);
+                               tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
                                return;
                        }
-                       cli->secblob = data_blob(bytes+16, num_bytes-16);
+
+                       blob1 = data_blob_const(bytes, 16);
+                       GUID_from_data_blob(&blob1, &server_guid);
+
+                       blob1 = data_blob_const(bytes+16, num_bytes-16);
+                       blob2 = data_blob_dup_talloc(state, &blob1);
+                       if (blob1.length > 0 &&
+                           tevent_req_nomem(blob2.data, req)) {
+                               return;
+                       }
+                       server_gss_blob = blob2;
                } else {
-                       cli->secblob = data_blob(bytes, MIN(num_bytes, 8));
-                       /* work out if they sent us a workgroup */
-                       if (num_bytes > 8) {
-                               ssize_t ret;
-                               status = smb_bytes_talloc_string(
-                                       cli, (char *)inbuf, &cli->server_domain,
-                                       bytes + 8, num_bytes - 8, &ret);
-                               if (tevent_req_nterror(req, status)) {
+                       DATA_BLOB blob1;
+                       ssize_t ret;
+
+                       if (num_bytes < key_len) {
+                               tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+                               return;
+                       }
+
+                       if (key_len != 0 && key_len != 8) {
+                               tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+                               return;
+                       }
+
+                       if (key_len == 8) {
+                               memcpy(server_challenge, bytes, 8);
+                       }
+
+                       blob1 = data_blob_const(bytes+key_len, num_bytes-key_len);
+                       if (blob1.length > 0) {
+                               ret = pull_string_talloc(state,
+                                                        (char *)inbuf,
+                                                        SVAL(inbuf, smb_flg2),
+                                                        &server_workgroup,
+                                                        blob1.data, blob1.length,
+                                                        STR_TERMINATE);
+                               if (ret == -1) {
+                                       tevent_req_oom(req);
                                        return;
                                }
                        }
@@ -2754,7 +2796,15 @@ static void cli_negprot_done(struct tevent_req *subreq)
                        (char *)(vwv + 8), cli->serverzone);
                server_readbraw = ((SVAL(vwv + 5, 0) & 0x1) != 0);
                server_writebraw = ((SVAL(vwv + 5, 0) & 0x2) != 0);
-               cli->secblob = data_blob(bytes, MIN(num_bytes, 8));
+
+               if (num_bytes != 0 && num_bytes != 8) {
+                       tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+                       return;
+               }
+
+               if (num_bytes == 8) {
+                       memcpy(server_challenge, bytes, 8);
+               }
        } else {
                /* the old core protocol */
                cli->serverzone = get_time_zone(time(NULL));
@@ -2787,6 +2837,13 @@ static void cli_negprot_done(struct tevent_req *subreq)
 
        max_xmit = MIN(client_max_xmit, server_max_xmit);
 
+       if (server_workgroup) {
+               cli->server_domain = talloc_strdup(cli, server_workgroup);
+               if (tevent_req_nomem(cli->server_domain, req)) {
+                       return;
+               }
+       }
+
        cli->conn.protocol = protocol;
 
        cli->conn.smb1.server.capabilities = server_capabilities;
@@ -2806,6 +2863,12 @@ static void cli_negprot_done(struct tevent_req *subreq)
 
        cli->conn.smb1.server.session_key = server_session_key;
 
+       talloc_steal(cli, server_gss_blob.data);
+       cli->conn.smb1.server.gss_blob = server_gss_blob;
+       cli->conn.smb1.server.guid = server_guid;
+       memcpy(cli->conn.smb1.server.challenge, server_challenge, 8);
+       cli->conn.smb1.server.workgroup = talloc_move(cli, &server_workgroup);
+
        tevent_req_done(req);
 }
 
index 80d99a7b66a5e79712216f109aa47cb5c7705230..05cbb9c80cad76179cf1e1c7a8b3906b4ea1faa2 100644 (file)
@@ -399,7 +399,6 @@ static void _cli_shutdown(struct cli_state *cli)
                cli_tdis(cli);
        }
         
-       data_blob_free(&cli->secblob);
        data_blob_free(&cli->user_session_key);
 
        cli_state_disconnect(cli);
@@ -568,18 +567,12 @@ uint16_t cli_state_max_requests(struct cli_state *cli)
 
 const uint8_t *cli_state_server_challenge(struct cli_state *cli)
 {
-       static const uint8_t zero;
-
-       if (cli->secblob.length == 8)
-               return cli->secblob.data;
-       }
-
-       return zero;
+       return cli->conn.smb1.server.challenge;
 }
 
 const DATA_BLOB *cli_state_server_gss_blob(struct cli_state *cli)
 {
-       return &cli->secblob;
+       return &cli->conn.smb1.server.gss_blob;
 }
 
 uint16_t cli_state_security_mode(struct cli_state *cli)