s4-test: added test suite for common.py code
[tridge/samba.git] / source3 / libsmb / smb2cli_negprot.c
1 /*
2    Unix SMB/CIFS implementation.
3    smb2 lib
4    Copyright (C) Volker Lendecke 2011
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "client.h"
22 #include "async_smb.h"
23 #include "smb2cli_base.h"
24 #include "smb2cli.h"
25 #include "libsmb/proto.h"
26 #include "librpc/ndr/libndr.h"
27 #include "lib/util/tevent_ntstatus.h"
28
29 struct smb2cli_negprot_state {
30         struct cli_state *cli;
31         uint8_t fixed[36];
32         uint8_t dyn[4];
33 };
34
35 static void smb2cli_negprot_done(struct tevent_req *subreq);
36
37 struct tevent_req *smb2cli_negprot_send(TALLOC_CTX *mem_ctx,
38                                         struct tevent_context *ev,
39                                         struct cli_state *cli)
40 {
41         struct tevent_req *req, *subreq;
42         struct smb2cli_negprot_state *state;
43         uint8_t *buf;
44
45         req = tevent_req_create(mem_ctx, &state,
46                                 struct smb2cli_negprot_state);
47         if (req == NULL) {
48                 return NULL;
49         }
50         state->cli = cli;
51
52         buf = state->fixed;
53         SSVAL(buf, 0, 36);
54         SSVAL(buf, 2, 2);       /* DialectCount */
55         if (client_is_signing_mandatory(cli)) {
56                 SSVAL(buf, 4, SMB2_NEGOTIATE_SIGNING_REQUIRED);
57         } else {
58                 SSVAL(buf, 4, SMB2_NEGOTIATE_SIGNING_ENABLED);
59         }
60         SSVAL(buf, 6, 0);       /* Reserved */
61         SSVAL(buf, 8, 0);       /* Capabilities */
62         memset(buf+12, 0, 16);  /* ClientGuid */
63         SBVAL(buf, 28, 0);      /* ClientStartTime */
64
65         buf = state->dyn;
66         SSVAL(buf, 0, 0x202);   /* SMB2.002 */
67         SSVAL(buf, 2, 0x210);   /* SMB2.1 */
68
69         subreq = smb2cli_req_send(state, ev, cli, SMB2_OP_NEGPROT,
70                                   0, 0, /* flags */
71                                   cli->timeout,
72                                   cli->smb2.pid,
73                                   0, 0, /* tid, uid */
74                                   state->fixed, sizeof(state->fixed),
75                                   state->dyn, sizeof(state->dyn));
76         if (tevent_req_nomem(subreq, req)) {
77                 return tevent_req_post(req, ev);
78         }
79         tevent_req_set_callback(subreq, smb2cli_negprot_done, req);
80         return req;
81 }
82
83 static void smb2cli_negprot_done(struct tevent_req *subreq)
84 {
85         struct tevent_req *req =
86                 tevent_req_callback_data(subreq,
87                 struct tevent_req);
88         struct smb2cli_negprot_state *state =
89                 tevent_req_data(req,
90                 struct smb2cli_negprot_state);
91         struct cli_state *cli = state->cli;
92         size_t security_offset, security_length;
93         DATA_BLOB blob;
94         NTSTATUS status;
95         struct iovec *iov;
96         uint8_t *body;
97         static const struct smb2cli_req_expected_response expected[] = {
98         {
99                 .status = NT_STATUS_OK,
100                 .body_size = 0x41
101         }
102         };
103
104         status = smb2cli_req_recv(subreq, talloc_tos(), &iov,
105                                   expected, ARRAY_SIZE(expected));
106         if (!NT_STATUS_IS_OK(status)) {
107                 TALLOC_FREE(subreq);
108                 tevent_req_nterror(req, status);
109                 return;
110         }
111         body = (uint8_t *)iov[1].iov_base;
112
113         cli->smb2.security_mode         = SVAL(body, 2);
114         cli->smb2.dialect_revision      = SVAL(body, 4);
115
116         blob = data_blob_const(body + 8, 16);
117         GUID_from_data_blob(&blob, &cli->smb2.server_guid);
118
119         cli->smb2.server_capabilities   = IVAL(body, 24);
120         cli->smb2.max_transact_size     = IVAL(body, 28);
121         cli->smb2.max_read_size         = IVAL(body, 32);
122         cli->smb2.max_write_size        = IVAL(body, 36);
123         cli->smb2.system_time           = interpret_long_date((char *)body + 40);
124         cli->smb2.server_start_time     = interpret_long_date((char *)body + 48);
125
126         security_offset         = SVAL(body, 56);
127         security_length         = SVAL(body, 58);
128
129         if ((security_offset != SMB2_HDR_BODY + iov[1].iov_len) ||
130             (security_length > iov[2].iov_len)) {
131                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
132                 return;
133         }
134         cli->smb2.gss_blob = data_blob(iov[1].iov_base, security_length);
135
136         tevent_req_done(req);
137 }
138
139 NTSTATUS smb2cli_negprot_recv(struct tevent_req *req)
140 {
141         return tevent_req_simple_recv_ntstatus(req);
142 }
143
144 NTSTATUS smb2cli_negprot(struct cli_state *cli)
145 {
146         TALLOC_CTX *frame = talloc_stackframe();
147         struct event_context *ev;
148         struct tevent_req *req;
149         NTSTATUS status = NT_STATUS_NO_MEMORY;
150
151         if (cli_has_async_calls(cli)) {
152                 /*
153                  * Can't use sync call while an async call is in flight
154                  */
155                 status = NT_STATUS_INVALID_PARAMETER;
156                 goto fail;
157         }
158         ev = event_context_init(frame);
159         if (ev == NULL) {
160                 goto fail;
161         }
162         req = smb2cli_negprot_send(frame, ev, cli);
163         if (req == NULL) {
164                 goto fail;
165         }
166         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
167                 goto fail;
168         }
169         status = smb2cli_negprot_recv(req);
170  fail:
171         TALLOC_FREE(frame);
172         return status;
173 }
174