s3-smbldap: move ldap_open_with_timeout out of smb_ldap.h to ads where it lives.
[Samba/gebeck_regimport.git] / source3 / libsmb / smb2cli_negprot.c
blobdec6c4c99807d661c46e199333a2f386e0b9f3ad
1 /*
2 Unix SMB/CIFS implementation.
3 smb2 lib
4 Copyright (C) Volker Lendecke 2011
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.
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.
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/>.
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"
29 struct smb2cli_negprot_state {
30 struct cli_state *cli;
31 uint8_t fixed[36];
32 uint8_t dyn[4];
35 static void smb2cli_negprot_done(struct tevent_req *subreq);
37 struct tevent_req *smb2cli_negprot_send(TALLOC_CTX *mem_ctx,
38 struct tevent_context *ev,
39 struct cli_state *cli)
41 struct tevent_req *req, *subreq;
42 struct smb2cli_negprot_state *state;
43 uint8_t *buf;
45 req = tevent_req_create(mem_ctx, &state,
46 struct smb2cli_negprot_state);
47 if (req == NULL) {
48 return NULL;
50 state->cli = cli;
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);
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 */
65 buf = state->dyn;
66 SSVAL(buf, 0, 0x202); /* SMB2.002 */
67 SSVAL(buf, 2, 0x210); /* SMB2.1 */
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);
79 tevent_req_set_callback(subreq, smb2cli_negprot_done, req);
80 return req;
83 static void smb2cli_negprot_done(struct tevent_req *subreq)
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[] = {
99 .status = NT_STATUS_OK,
100 .body_size = 0x41
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;
111 body = (uint8_t *)iov[1].iov_base;
113 cli->smb2.security_mode = SVAL(body, 2);
114 cli->smb2.dialect_revision = SVAL(body, 4);
116 blob = data_blob_const(body + 8, 16);
117 GUID_from_data_blob(&blob, &cli->smb2.server_guid);
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);
126 security_offset = SVAL(body, 56);
127 security_length = SVAL(body, 58);
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;
134 cli->smb2.gss_blob = data_blob(iov[1].iov_base, security_length);
136 tevent_req_done(req);
139 NTSTATUS smb2cli_negprot_recv(struct tevent_req *req)
141 return tevent_req_simple_recv_ntstatus(req);
144 NTSTATUS smb2cli_negprot(struct cli_state *cli)
146 TALLOC_CTX *frame = talloc_stackframe();
147 struct event_context *ev;
148 struct tevent_req *req;
149 NTSTATUS status = NT_STATUS_NO_MEMORY;
151 if (cli_has_async_calls(cli)) {
153 * Can't use sync call while an async call is in flight
155 status = NT_STATUS_INVALID_PARAMETER;
156 goto fail;
158 ev = event_context_init(frame);
159 if (ev == NULL) {
160 goto fail;
162 req = smb2cli_negprot_send(frame, ev, cli);
163 if (req == NULL) {
164 goto fail;
166 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
167 goto fail;
169 status = smb2cli_negprot_recv(req);
170 fail:
171 TALLOC_FREE(frame);
172 return status;