Changeset 988 for vendor/current/source4/libcli/smb2
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- Location:
- vendor/current/source4/libcli/smb2
- Files:
-
- 1 deleted
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source4/libcli/smb2/cancel.c
r740 r988 21 21 22 22 #include "includes.h" 23 #include <tevent.h> 23 24 #include "libcli/raw/libcliraw.h" 24 25 #include "libcli/smb2/smb2.h" … … 30 31 NTSTATUS smb2_cancel(struct smb2_request *r) 31 32 { 32 NTSTATUS status; 33 struct smb2_request *c; 34 uint32_t old_timeout; 35 uint64_t old_seqnum; 33 bool ok; 36 34 37 /* 38 * if we don't get a pending id yet, we just 39 * mark the request for pending, so that we directly 40 * send the cancel after getting the pending id 41 */ 42 if (!r->cancel.can_cancel) { 43 r->cancel.do_cancel++; 35 if (r->subreq == NULL) { 44 36 return NT_STATUS_OK; 45 37 } 46 38 47 /* we don't want a seqmun for a SMB2 Cancel */ 48 old_seqnum = r->transport->seqnum; 49 c = smb2_request_init(r->transport, SMB2_OP_CANCEL, 0x04, false, 0); 50 r->transport->seqnum = old_seqnum; 51 NT_STATUS_HAVE_NO_MEMORY(c); 52 c->seqnum = 0; 53 54 SIVAL(c->out.hdr, SMB2_HDR_FLAGS, 0x00000002); 55 SSVAL(c->out.hdr, SMB2_HDR_CREDIT, 0x0030); 56 SBVAL(c->out.hdr, SMB2_HDR_ASYNC_ID, r->cancel.async_id); 57 SBVAL(c->out.hdr, SMB2_HDR_MESSAGE_ID, c->seqnum); 58 if (r->session) { 59 SBVAL(c->out.hdr, SMB2_HDR_SESSION_ID, r->session->uid); 39 ok = tevent_req_cancel(r->subreq); 40 if (!ok) { 41 return NT_STATUS_INTERNAL_ERROR; 60 42 } 61 43 62 SSVAL(c->out.body, 0x02, 0); 63 64 old_timeout = c->transport->options.request_timeout; 65 c->transport->options.request_timeout = 0; 66 smb2_transport_send(c); 67 c->transport->options.request_timeout = old_timeout; 68 69 if (c->state == SMB2_REQUEST_ERROR) { 70 status = c->status; 71 } else { 72 status = NT_STATUS_OK; 73 } 74 75 talloc_free(c); 76 return status; 44 return NT_STATUS_OK; 77 45 } -
vendor/current/source4/libcli/smb2/connect.c
r414 r988 21 21 22 22 #include "includes.h" 23 #include <tevent.h> 24 #include "lib/util/tevent_ntstatus.h" 23 25 #include "libcli/raw/libcliraw.h" 24 26 #include "libcli/raw/raw_proto.h" … … 28 30 #include "libcli/resolve/resolve.h" 29 31 #include "param/param.h" 32 #include "auth/credentials/credentials.h" 33 #include "../libcli/smb/smbXcli_base.h" 30 34 31 35 struct smb2_connect_state { 36 struct tevent_context *ev; 32 37 struct cli_credentials *credentials; 38 uint64_t previous_session_id; 33 39 struct resolve_context *resolve_ctx; 34 40 const char *host; 35 41 const char *share; 42 const char *unc; 36 43 const char **ports; 37 44 const char *socket_options; 45 struct nbt_name calling, called; 38 46 struct gensec_settings *gensec_settings; 39 47 struct smbcli_options options; 40 struct smb2_negprot negprot; 41 struct smb2_tree_connect tcon; 48 struct smb2_transport *transport; 42 49 struct smb2_session *session; 43 50 struct smb2_tree *tree; 44 51 }; 45 52 46 /* 47 continue after tcon reply 48 */ 49 static void continue_tcon(struct smb2_request *req) 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) 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) 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.secblob = state->negprot.out.secblob; 109 talloc_steal(transport, transport->negotiate.secblob.data); 110 transport->negotiate.system_time = state->negprot.out.system_time; 111 transport->negotiate.server_start_time = state->negprot.out.server_start_time; 112 transport->negotiate.security_mode = state->negprot.out.security_mode; 113 transport->negotiate.dialect_revision = state->negprot.out.dialect_revision; 114 115 switch (transport->options.signing) { 116 case SMB_SIGNING_OFF: 117 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) { 118 composite_error(c, NT_STATUS_ACCESS_DENIED); 119 return; 120 } 121 transport->signing_required = false; 122 break; 123 case SMB_SIGNING_SUPPORTED: 124 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) { 125 transport->signing_required = true; 126 } else { 127 transport->signing_required = false; 128 } 129 break; 130 case SMB_SIGNING_AUTO: 131 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) { 132 transport->signing_required = true; 133 } else { 134 transport->signing_required = false; 135 } 136 break; 137 case SMB_SIGNING_REQUIRED: 138 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) { 139 transport->signing_required = true; 140 } else { 141 composite_error(c, NT_STATUS_ACCESS_DENIED); 142 return; 143 } 144 break; 145 } 146 147 state->session = smb2_session_init(transport, state->gensec_settings, state, true); 148 if (composite_nomem(state->session, c)) return; 149 150 creq = smb2_session_setup_spnego_send(state->session, state->credentials); 151 152 composite_continue(c, creq, continue_session, c); 153 } 154 155 /* 156 continue after a socket connect completes 157 */ 158 static void continue_socket(struct composite_context *creq) 159 { 160 struct composite_context *c = talloc_get_type(creq->async.private_data, 161 struct composite_context); 162 struct smb2_connect_state *state = talloc_get_type(c->private_data, 163 struct smb2_connect_state); 164 struct smbcli_socket *sock; 165 struct smb2_transport *transport; 166 struct smb2_request *req; 167 uint16_t dialects[3] = { 168 SMB2_DIALECT_REVISION_000, 169 SMB2_DIALECT_REVISION_202, 170 SMB2_DIALECT_REVISION_210 171 }; 172 173 c->status = smbcli_sock_connect_recv(creq, state, &sock); 174 if (!composite_is_ok(c)) return; 175 176 transport = smb2_transport_init(sock, state, &state->options); 177 if (composite_nomem(transport, c)) return; 178 179 ZERO_STRUCT(state->negprot); 180 state->negprot.in.dialect_count = sizeof(dialects) / sizeof(dialects[0]); 181 switch (transport->options.signing) { 182 case SMB_SIGNING_OFF: 183 state->negprot.in.security_mode = 0; 184 break; 185 case SMB_SIGNING_SUPPORTED: 186 case SMB_SIGNING_AUTO: 187 state->negprot.in.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED; 188 break; 189 case SMB_SIGNING_REQUIRED: 190 state->negprot.in.security_mode = 191 SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED; 192 break; 193 } 194 state->negprot.in.capabilities = 0; 195 unix_to_nt_time(&state->negprot.in.start_time, time(NULL)); 196 state->negprot.in.dialects = dialects; 197 198 req = smb2_negprot_send(transport, &state->negprot); 199 if (composite_nomem(req, c)) return; 200 201 req->async.fn = continue_negprot; 202 req->async.private_data = c; 203 } 204 205 206 /* 207 continue after a resolve finishes 208 */ 209 static void continue_resolve(struct composite_context *creq) 210 { 211 struct composite_context *c = talloc_get_type(creq->async.private_data, 212 struct composite_context); 213 struct smb2_connect_state *state = talloc_get_type(c->private_data, 214 struct smb2_connect_state); 215 const char *addr; 216 const char **ports; 217 const char *default_ports[] = { "445", NULL }; 218 219 c->status = resolve_name_recv(creq, state, &addr); 220 if (!composite_is_ok(c)) return; 221 222 if (state->ports == NULL) { 223 ports = default_ports; 224 } else { 225 ports = state->ports; 226 } 227 228 creq = smbcli_sock_connect_send(state, addr, ports, state->host, state->resolve_ctx, c->event_ctx, state->socket_options); 229 230 composite_continue(c, creq, continue_socket, c); 231 } 53 static void smb2_connect_socket_done(struct composite_context *creq); 232 54 233 55 /* … … 235 57 a connected smb2_tree 236 58 */ 237 struct composite_context *smb2_connect_send(TALLOC_CTX *mem_ctx, 238 const char *host, 239 const char **ports, 240 const char *share, 241 struct resolve_context *resolve_ctx, 242 struct cli_credentials *credentials, 243 struct tevent_context *ev, 244 struct smbcli_options *options, 245 const char *socket_options, 246 struct gensec_settings *gensec_settings) 247 { 248 struct composite_context *c; 59 struct tevent_req *smb2_connect_send(TALLOC_CTX *mem_ctx, 60 struct tevent_context *ev, 61 const char *host, 62 const char **ports, 63 const char *share, 64 struct resolve_context *resolve_ctx, 65 struct cli_credentials *credentials, 66 uint64_t previous_session_id, 67 const struct smbcli_options *options, 68 const char *socket_options, 69 struct gensec_settings *gensec_settings) 70 { 71 struct tevent_req *req; 249 72 struct smb2_connect_state *state; 250 struct nbt_name name;251 73 struct composite_context *creq; 252 253 c = composite_create(mem_ctx, ev); 254 if (c == NULL) return NULL; 255 256 state = talloc(c, struct smb2_connect_state); 257 if (composite_nomem(state, c)) return c; 258 c->private_data = state; 259 74 static const char *default_ports[] = { "445", "139", NULL }; 75 76 req = tevent_req_create(mem_ctx, &state, 77 struct smb2_connect_state); 78 if (req == NULL) { 79 return NULL; 80 } 81 82 state->ev = ev; 260 83 state->credentials = credentials; 84 state->previous_session_id = previous_session_id; 261 85 state->options = *options; 262 state->host = talloc_strdup(c, host); 263 if (composite_nomem(state->host, c)) return c; 264 state->ports = talloc_reference(state, ports); 265 state->share = talloc_strdup(c, share); 266 if (composite_nomem(state->share, c)) return c; 267 state->resolve_ctx = talloc_reference(state, resolve_ctx); 268 state->socket_options = talloc_reference(state, socket_options); 269 state->gensec_settings = talloc_reference(state, gensec_settings); 270 271 ZERO_STRUCT(name); 272 name.name = host; 273 274 creq = resolve_name_send(resolve_ctx, state, &name, c->event_ctx); 275 composite_continue(c, creq, continue_resolve, c); 276 return c; 277 } 278 279 /* 280 receive a connect reply 281 */ 282 NTSTATUS smb2_connect_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, 86 state->host = host; 87 state->ports = ports; 88 state->share = share; 89 state->resolve_ctx = resolve_ctx; 90 state->socket_options = socket_options; 91 state->gensec_settings = gensec_settings; 92 93 if (state->ports == NULL) { 94 state->ports = default_ports; 95 } 96 97 make_nbt_name_client(&state->calling, 98 cli_credentials_get_workstation(credentials)); 99 100 nbt_choose_called_name(state, &state->called, 101 host, NBT_NAME_SERVER); 102 103 state->unc = talloc_asprintf(state, "\\\\%s\\%s", 104 state->host, state->share); 105 if (tevent_req_nomem(state->unc, req)) { 106 return tevent_req_post(req, ev); 107 } 108 109 creq = smbcli_sock_connect_send(state, NULL, state->ports, 110 state->host, state->resolve_ctx, 111 state->ev, state->socket_options, 112 &state->calling, 113 &state->called); 114 if (tevent_req_nomem(creq, req)) { 115 return tevent_req_post(req, ev); 116 } 117 creq->async.fn = smb2_connect_socket_done; 118 creq->async.private_data = req; 119 120 return req; 121 } 122 123 static void smb2_connect_negprot_done(struct tevent_req *subreq); 124 125 static void smb2_connect_socket_done(struct composite_context *creq) 126 { 127 struct tevent_req *req = 128 talloc_get_type_abort(creq->async.private_data, 129 struct tevent_req); 130 struct smb2_connect_state *state = 131 tevent_req_data(req, 132 struct smb2_connect_state); 133 struct smbcli_socket *sock; 134 struct tevent_req *subreq; 135 NTSTATUS status; 136 uint32_t timeout_msec; 137 enum protocol_types min_protocol; 138 139 status = smbcli_sock_connect_recv(creq, state, &sock); 140 if (tevent_req_nterror(req, status)) { 141 return; 142 } 143 144 state->transport = smb2_transport_init(sock, state, &state->options); 145 if (tevent_req_nomem(state->transport, req)) { 146 return; 147 } 148 149 timeout_msec = state->transport->options.request_timeout * 1000; 150 min_protocol = state->transport->options.min_protocol; 151 if (min_protocol < PROTOCOL_SMB2_02) { 152 min_protocol = PROTOCOL_SMB2_02; 153 } 154 155 subreq = smbXcli_negprot_send(state, state->ev, 156 state->transport->conn, timeout_msec, 157 min_protocol, 158 state->transport->options.max_protocol); 159 if (tevent_req_nomem(subreq, req)) { 160 return; 161 } 162 tevent_req_set_callback(subreq, smb2_connect_negprot_done, req); 163 } 164 165 static void smb2_connect_session_done(struct tevent_req *subreq); 166 167 static void smb2_connect_negprot_done(struct tevent_req *subreq) 168 { 169 struct tevent_req *req = 170 tevent_req_callback_data(subreq, 171 struct tevent_req); 172 struct smb2_connect_state *state = 173 tevent_req_data(req, 174 struct smb2_connect_state); 175 struct smb2_transport *transport = state->transport; 176 NTSTATUS status; 177 178 status = smbXcli_negprot_recv(subreq); 179 TALLOC_FREE(subreq); 180 if (tevent_req_nterror(req, status)) { 181 return; 182 } 183 184 /* This is a hack... */ 185 smb2cli_conn_set_max_credits(transport->conn, 30); 186 187 state->session = smb2_session_init(transport, state->gensec_settings, state); 188 if (tevent_req_nomem(state->session, req)) { 189 return; 190 } 191 192 subreq = smb2_session_setup_spnego_send(state, state->ev, 193 state->session, 194 state->credentials, 195 state->previous_session_id); 196 if (tevent_req_nomem(subreq, req)) { 197 return; 198 } 199 tevent_req_set_callback(subreq, smb2_connect_session_done, req); 200 } 201 202 static void smb2_connect_tcon_done(struct tevent_req *subreq); 203 204 static void smb2_connect_session_done(struct tevent_req *subreq) 205 { 206 struct tevent_req *req = 207 tevent_req_callback_data(subreq, 208 struct tevent_req); 209 struct smb2_connect_state *state = 210 tevent_req_data(req, 211 struct smb2_connect_state); 212 NTSTATUS status; 213 uint32_t timeout_msec; 214 215 status = smb2_session_setup_spnego_recv(subreq); 216 TALLOC_FREE(subreq); 217 if (tevent_req_nterror(req, status)) { 218 return; 219 } 220 221 state->tree = smb2_tree_init(state->session, state, true); 222 if (tevent_req_nomem(state->tree, req)) { 223 return; 224 } 225 226 timeout_msec = state->transport->options.request_timeout * 1000; 227 228 subreq = smb2cli_tcon_send(state, state->ev, 229 state->transport->conn, 230 timeout_msec, 231 state->session->smbXcli, 232 state->tree->smbXcli, 233 0, /* flags */ 234 state->unc); 235 if (tevent_req_nomem(subreq, req)) { 236 return; 237 } 238 tevent_req_set_callback(subreq, smb2_connect_tcon_done, req); 239 } 240 241 static void smb2_connect_tcon_done(struct tevent_req *subreq) 242 { 243 struct tevent_req *req = 244 tevent_req_callback_data(subreq, 245 struct tevent_req); 246 NTSTATUS status; 247 248 status = smb2cli_tcon_recv(subreq); 249 if (tevent_req_nterror(req, status)) { 250 return; 251 } 252 253 tevent_req_done(req); 254 } 255 256 NTSTATUS smb2_connect_recv(struct tevent_req *req, 257 TALLOC_CTX *mem_ctx, 283 258 struct smb2_tree **tree) 284 259 { 285 NTSTATUS status; 286 struct smb2_connect_state *state = talloc_get_type(c->private_data, 287 struct smb2_connect_state); 288 status = composite_wait(c); 289 if (NT_STATUS_IS_OK(status)) { 290 *tree = talloc_steal(mem_ctx, state->tree); 291 } 292 talloc_free(c); 293 return status; 260 struct smb2_connect_state *state = 261 tevent_req_data(req, 262 struct smb2_connect_state); 263 NTSTATUS status; 264 265 if (tevent_req_is_nterror(req, &status)) { 266 tevent_req_received(req); 267 return status; 268 } 269 270 *tree = talloc_move(mem_ctx, &state->tree); 271 272 tevent_req_received(req); 273 return NT_STATUS_OK; 294 274 } 295 275 … … 297 277 sync version of smb2_connect 298 278 */ 299 NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx, 300 const char *host, const char **ports, 279 NTSTATUS smb2_connect_ext(TALLOC_CTX *mem_ctx, 280 const char *host, 281 const char **ports, 301 282 const char *share, 283 struct resolve_context *resolve_ctx, 284 struct cli_credentials *credentials, 285 uint64_t previous_session_id, 286 struct smb2_tree **tree, 287 struct tevent_context *ev, 288 const struct smbcli_options *options, 289 const char *socket_options, 290 struct gensec_settings *gensec_settings) 291 { 292 struct tevent_req *subreq; 293 NTSTATUS status; 294 bool ok; 295 TALLOC_CTX *frame = talloc_stackframe(); 296 297 if (frame == NULL) { 298 return NT_STATUS_NO_MEMORY; 299 } 300 301 subreq = smb2_connect_send(frame, 302 ev, 303 host, 304 ports, 305 share, 306 resolve_ctx, 307 credentials, 308 previous_session_id, 309 options, 310 socket_options, 311 gensec_settings); 312 if (subreq == NULL) { 313 TALLOC_FREE(frame); 314 return NT_STATUS_NO_MEMORY; 315 } 316 317 ok = tevent_req_poll(subreq, ev); 318 if (!ok) { 319 status = map_nt_error_from_unix_common(errno); 320 TALLOC_FREE(frame); 321 return status; 322 } 323 324 status = smb2_connect_recv(subreq, mem_ctx, tree); 325 TALLOC_FREE(subreq); 326 if (!NT_STATUS_IS_OK(status)) { 327 TALLOC_FREE(frame); 328 return status; 329 } 330 331 TALLOC_FREE(frame); 332 return NT_STATUS_OK; 333 } 334 335 NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx, 336 const char *host, 337 const char **ports, 338 const char *share, 302 339 struct resolve_context *resolve_ctx, 303 340 struct cli_credentials *credentials, … … 305 342 struct tevent_context *ev, 306 343 struct smbcli_options *options, 307 const char *socket_options, 308 struct gensec_settings *gensec_settings) 309 { 310 struct composite_context *c = smb2_connect_send(mem_ctx, host, ports, 311 share, resolve_ctx, 312 credentials, ev, options, 313 socket_options, 314 gensec_settings); 315 return smb2_connect_recv(c, mem_ctx, tree); 316 } 344 const char *socket_options, 345 struct gensec_settings *gensec_settings) 346 { 347 NTSTATUS status; 348 349 status = smb2_connect_ext(mem_ctx, host, ports, share, resolve_ctx, 350 credentials, 351 0, /* previous_session_id */ 352 tree, ev, options, socket_options, 353 gensec_settings); 354 355 return status; 356 } -
vendor/current/source4/libcli/smb2/create.c
r740 r988 107 107 } 108 108 109 if (io->in.durable_open_v2) { 110 uint8_t data[32]; 111 uint32_t flags = 0; 112 DATA_BLOB guid_blob; 113 114 SIVAL(data, 0, io->in.timeout); 115 if (io->in.persistent_open) { 116 flags = SMB2_DHANDLE_FLAG_PERSISTENT; 117 } 118 SIVAL(data, 4, flags); 119 SBVAL(data, 8, 0x0); /* reserved */ 120 status = GUID_to_ndr_blob(&io->in.create_guid, req, /* TALLOC_CTX */ 121 &guid_blob); 122 if (!NT_STATUS_IS_OK(status)) { 123 talloc_free(req); 124 return NULL; 125 } 126 memcpy(data+16, guid_blob.data, 16); 127 128 status = smb2_create_blob_add(req, &blobs, 129 SMB2_CREATE_TAG_DH2Q, 130 data_blob_const(data, 32)); 131 if (!NT_STATUS_IS_OK(status)) { 132 talloc_free(req); 133 return NULL; 134 } 135 } 136 109 137 if (io->in.durable_handle) { 110 138 uint8_t data[16]; … … 112 140 status = smb2_create_blob_add(req, &blobs, 113 141 SMB2_CREATE_TAG_DHNC, data_blob_const(data, 16)); 142 if (!NT_STATUS_IS_OK(status)) { 143 talloc_free(req); 144 return NULL; 145 } 146 } 147 148 if (io->in.durable_handle_v2) { 149 uint8_t data[36]; 150 DATA_BLOB guid_blob; 151 uint32_t flags = 0; 152 153 smb2_push_handle(data, io->in.durable_handle_v2); 154 status = GUID_to_ndr_blob(&io->in.create_guid, req, /* TALLOC_CTX */ 155 &guid_blob); 156 if (!NT_STATUS_IS_OK(status)) { 157 talloc_free(req); 158 return NULL; 159 } 160 memcpy(data+16, guid_blob.data, 16); 161 if (io->in.persistent_open) { 162 flags = SMB2_DHANDLE_FLAG_PERSISTENT; 163 } 164 SIVAL(data, 32, flags); 165 166 status = smb2_create_blob_add(req, &blobs, 167 SMB2_CREATE_TAG_DH2C, 168 data_blob_const(data, 36)); 114 169 if (!NT_STATUS_IS_OK(status)) { 115 170 talloc_free(req); … … 158 213 uint8_t data[32]; 159 214 160 memcpy(&data[0], &io->in.lease_request->lease_key, 16); 161 SIVAL(data, 16, io->in.lease_request->lease_state); 162 SIVAL(data, 20, io->in.lease_request->lease_flags); 163 SBVAL(data, 24, io->in.lease_request->lease_duration); 164 165 status = smb2_create_blob_add(req, &blobs, 166 SMB2_CREATE_TAG_RQLS, 167 data_blob_const(data, 32)); 215 if (!smb2_lease_push(io->in.lease_request, data, 216 sizeof(data))) { 217 TALLOC_FREE(req); 218 return NULL; 219 } 220 221 status = smb2_create_blob_add( 222 req, &blobs, SMB2_CREATE_TAG_RQLS, 223 data_blob_const(data, sizeof(data))); 224 if (!NT_STATUS_IS_OK(status)) { 225 talloc_free(req); 226 return NULL; 227 } 228 } 229 230 if (io->in.lease_request_v2) { 231 uint8_t data[52]; 232 233 if (!smb2_lease_push(io->in.lease_request_v2, data, 234 sizeof(data))) { 235 TALLOC_FREE(req); 236 return NULL; 237 } 238 239 status = smb2_create_blob_add( 240 req, &blobs, SMB2_CREATE_TAG_RQLS, 241 data_blob_const(data, sizeof(data))); 242 if (!NT_STATUS_IS_OK(status)) { 243 talloc_free(req); 244 return NULL; 245 } 246 } 247 248 if (io->in.app_instance_id) { 249 uint8_t data[20]; 250 DATA_BLOB guid_blob; 251 252 SSVAL(data, 0, 20); /* structure size */ 253 SSVAL(data, 2, 0); /* reserved */ 254 255 status = GUID_to_ndr_blob(io->in.app_instance_id, 256 req, /* TALLOC_CTX */ 257 &guid_blob); 258 if (!NT_STATUS_IS_OK(status)) { 259 talloc_free(req); 260 return NULL; 261 } 262 memcpy(data+4, guid_blob.data, 16); 263 264 status = smb2_create_blob_add(req, &blobs, 265 SMB2_CREATE_TAG_APP_INSTANCE_ID, 266 data_blob_const(data, 20)); 168 267 if (!NT_STATUS_IS_OK(status)) { 169 268 talloc_free(req); … … 194 293 talloc_free(req); 195 294 return NULL; 295 } 296 297 if (((io->in.fname == NULL) || (strlen(io->in.fname) == 0)) && 298 (blob.length == 0)) { 299 struct smb2_request_buffer *buf = &req->out; 300 301 status = smb2_grow_buffer(buf, 1); 302 if (!NT_STATUS_IS_OK(status)) { 303 talloc_free(req); 304 return NULL; 305 } 306 buf->dynamic[0] = 0; 307 buf->dynamic += 1; 308 buf->body_size += 1; 309 buf->size += 1; 196 310 } 197 311 … … 263 377 } 264 378 if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_RQLS) == 0) { 379 struct smb2_lease *ls = NULL; 265 380 uint8_t *data; 266 if (io->out.blobs.blobs[i].data.length != 32) { 381 382 ZERO_STRUCT(io->out.lease_response); 383 ZERO_STRUCT(io->out.lease_response_v2); 384 385 switch (io->out.blobs.blobs[i].data.length) { 386 case 32: 387 ls = &io->out.lease_response; 388 ls->lease_version = 1; 389 break; 390 case 52: 391 ls = &io->out.lease_response_v2; 392 ls->lease_version = 2; 393 break; 394 default: 267 395 smb2_request_destroy(req); 268 396 return NT_STATUS_INVALID_NETWORK_RESPONSE; … … 270 398 271 399 data = io->out.blobs.blobs[i].data.data; 272 memcpy(&io->out.lease_response.lease_key, data, 16); 273 io->out.lease_response.lease_state = IVAL(data, 16); 274 io->out.lease_response.lease_flags = IVAL(data, 20); 275 io->out.lease_response.lease_duration = BVAL(data, 24); 400 memcpy(&ls->lease_key, data, 16); 401 ls->lease_state = IVAL(data, 16); 402 ls->lease_flags = IVAL(data, 20); 403 ls->lease_duration = BVAL(data, 24); 404 405 if (io->out.blobs.blobs[i].data.length == 52) { 406 memcpy(&ls->parent_lease_key, data+32, 16); 407 ls->lease_epoch = SVAL(data, 48); 408 } 409 } 410 if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNQ) == 0) { 411 if (io->out.blobs.blobs[i].data.length != 8) { 412 smb2_request_destroy(req); 413 return NT_STATUS_INVALID_NETWORK_RESPONSE; 414 } 415 io->out.durable_open = true; 416 } 417 if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_DH2Q) == 0) { 418 uint32_t flags; 419 uint8_t *data; 420 421 if (io->out.blobs.blobs[i].data.length != 8) { 422 smb2_request_destroy(req); 423 return NT_STATUS_INVALID_NETWORK_RESPONSE; 424 } 425 426 io->out.durable_open = false; 427 io->out.durable_open_v2 = true; 428 429 data = io->out.blobs.blobs[i].data.data; 430 io->out.timeout = IVAL(data, 0); 431 flags = IVAL(data, 4); 432 if ((flags & SMB2_DHANDLE_FLAG_PERSISTENT) != 0) { 433 io->out.persistent_open = true; 434 } 276 435 } 277 436 } -
vendor/current/source4/libcli/smb2/find.c
r740 r988 34 34 NTSTATUS status; 35 35 36 req = smb2_request_init_tree(tree, SMB2_OP_ FIND, 0x20, true, 0);36 req = smb2_request_init_tree(tree, SMB2_OP_QUERY_DIRECTORY, 0x20, true, 0); 37 37 if (req == NULL) return NULL; 38 38 -
vendor/current/source4/libcli/smb2/ioctl.c
r414 r988 23 23 #include "libcli/smb2/smb2.h" 24 24 #include "libcli/smb2/smb2_calls.h" 25 #include "librpc/gen_ndr/ioctl.h" 25 26 26 27 /* … … 62 63 } 63 64 65 /* 66 * 3.3.4.4 Sending an Error Response 67 */ 68 static bool smb2_ioctl_is_failure(uint32_t ctl_code, NTSTATUS status, 69 size_t data_size) 70 { 71 if (NT_STATUS_IS_OK(status)) { 72 return false; 73 } 74 75 if (NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW) 76 && ((ctl_code == FSCTL_PIPE_TRANSCEIVE) 77 || (ctl_code == FSCTL_PIPE_PEEK) 78 || (ctl_code == FSCTL_DFS_GET_REFERRALS))) { 79 return false; 80 } 81 82 if (((ctl_code == FSCTL_SRV_COPYCHUNK) 83 || (ctl_code == FSCTL_SRV_COPYCHUNK_WRITE)) 84 && (data_size == sizeof(struct srv_copychunk_rsp))) { 85 /* 86 * copychunk responses may come with copychunk data or error 87 * response data, independent of status. 88 */ 89 return false; 90 } 91 92 return true; 93 } 64 94 65 95 /* 66 96 recv a ioctl reply 67 97 */ 68 NTSTATUS smb2_ioctl_recv(struct smb2_request *req, 98 NTSTATUS smb2_ioctl_recv(struct smb2_request *req, 69 99 TALLOC_CTX *mem_ctx, struct smb2_ioctl *io) 70 100 { 71 101 NTSTATUS status; 72 102 73 if (!smb2_request_receive(req) || 74 smb2_request_is_error(req)) { 103 if (!smb2_request_receive(req) || 104 smb2_ioctl_is_failure(io->in.function, req->status, 105 req->in.bufinfo.data_size)) { 75 106 return smb2_request_destroy(req); 76 107 } -
vendor/current/source4/libcli/smb2/logoff.c
r414 r988 36 36 req->session = session; 37 37 38 SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, session->uid);39 40 38 SSVAL(req->out.body, 0x02, 0); 41 39 -
vendor/current/source4/libcli/smb2/read.c
r414 r988 45 45 SSVAL(req->out.body, 0x2E, io->in.channel_length); 46 46 47 req->credit_charge = (MAX(io->in.length, 1) - 1)/ 65536 + 1; 48 47 49 smb2_transport_send(req); 48 50 -
vendor/current/source4/libcli/smb2/request.c
r740 r988 43 43 } 44 44 45 46 /* destroy a request structure */47 static int smb2_request_destructor(struct smb2_request *req)48 {49 if (req->transport) {50 /* remove it from the list of pending requests (a null op if51 its not in the list) */52 DLIST_REMOVE(req->transport->pending_recv, req);53 }54 return 0;55 }56 57 45 /* 58 46 initialise a smb2 request … … 63 51 { 64 52 struct smb2_request *req; 65 uint64_t seqnum;66 53 uint32_t hdr_offset; 67 uint32_t flags = 0;68 54 bool compound = false; 69 55 … … 76 62 } 77 63 78 req = talloc (transport, struct smb2_request);64 req = talloc_zero(transport, struct smb2_request); 79 65 if (req == NULL) return NULL; 80 81 seqnum = transport->seqnum;82 if (transport->credits.charge > 0) {83 transport->seqnum += transport->credits.charge;84 } else {85 transport->seqnum += 1;86 }87 66 88 67 req->state = SMB2_REQUEST_INIT; 89 68 req->transport = transport; 90 req->session = NULL; 91 req->tree = NULL; 92 req->seqnum = seqnum; 93 req->status = NT_STATUS_OK; 94 req->async.fn = NULL; 95 req->next = req->prev = NULL; 96 97 ZERO_STRUCT(req->cancel); 98 ZERO_STRUCT(req->in); 99 100 if (transport->compound.missing > 0) { 101 compound = true; 102 transport->compound.missing -= 1; 103 req->out = transport->compound.buffer; 104 ZERO_STRUCT(transport->compound.buffer); 105 if (transport->compound.related) { 106 flags |= SMB2_HDR_FLAG_CHAINED; 107 } 108 } else { 109 ZERO_STRUCT(req->out); 110 } 111 112 if (req->out.size > 0) { 113 hdr_offset = req->out.size; 114 } else { 115 hdr_offset = NBT_HDR_SIZE; 116 } 69 70 hdr_offset = NBT_HDR_SIZE; 117 71 118 72 req->out.size = hdr_offset + SMB2_HDR_BODY + body_fixed_size; … … 134 88 SIVAL(req->out.hdr, 0, SMB2_MAGIC); 135 89 SSVAL(req->out.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); 136 SSVAL(req->out.hdr, SMB2_HDR_ EPOCH, transport->credits.charge);90 SSVAL(req->out.hdr, SMB2_HDR_CREDIT_CHARGE, 0); 137 91 SIVAL(req->out.hdr, SMB2_HDR_STATUS, 0); 138 92 SSVAL(req->out.hdr, SMB2_HDR_OPCODE, opcode); 139 SSVAL(req->out.hdr, SMB2_HDR_CREDIT, transport->credits.ask_num);140 SIVAL(req->out.hdr, SMB2_HDR_FLAGS, flags);93 SSVAL(req->out.hdr, SMB2_HDR_CREDIT, 0); 94 SIVAL(req->out.hdr, SMB2_HDR_FLAGS, 0); 141 95 SIVAL(req->out.hdr, SMB2_HDR_NEXT_COMMAND, 0); 142 SBVAL(req->out.hdr, SMB2_HDR_MESSAGE_ID, req->seqnum);96 SBVAL(req->out.hdr, SMB2_HDR_MESSAGE_ID, 0); 143 97 SIVAL(req->out.hdr, SMB2_HDR_PID, 0); 144 98 SIVAL(req->out.hdr, SMB2_HDR_TID, 0); … … 158 112 } 159 113 160 talloc_set_destructor(req, smb2_request_destructor);161 162 114 return req; 163 115 } … … 175 127 if (req == NULL) return NULL; 176 128 177 SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, tree->session->uid);178 SIVAL(req->out.hdr, SMB2_HDR_PID, tree->session->pid);179 SIVAL(req->out.hdr, SMB2_HDR_TID, tree->tid);180 129 req->session = tree->session; 181 130 req->tree = tree; … … 215 164 /* keep receiving packets until this one is replied to */ 216 165 while (req->state <= SMB2_REQUEST_RECV) { 217 if ( event_loop_once(req->transport->socket->event.ctx) != 0) {166 if (tevent_loop_once(req->transport->ev) != 0) { 218 167 return false; 219 168 } … … 687 636 NTSTATUS status; 688 637 void *vstr; 638 size_t converted_size = 0; 689 639 bool ret; 690 640 … … 706 656 707 657 ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, 708 blob.data, blob.length, &vstr, NULL, false);658 blob.data, blob.length, &vstr, &converted_size); 709 659 data_blob_free(&blob); 710 660 (*str) = (char *)vstr; … … 725 675 NTSTATUS status; 726 676 bool ret; 677 void *ptr = NULL; 727 678 728 679 if (str == NULL) { … … 737 688 738 689 ret = convert_string_talloc(buf->buffer, CH_UNIX, CH_UTF16, 739 str, strlen(str), (void **)&blob.data, &blob.length, 740 false); 690 str, strlen(str), &ptr, &blob.length); 741 691 if (!ret) { 742 692 return NT_STATUS_ILLEGAL_CHARACTER; 743 693 } 694 blob.data = (uint8_t *)ptr; 744 695 745 696 status = smb2_push_o16s16_blob(buf, ofs, blob); -
vendor/current/source4/libcli/smb2/session.c
r740 r988 21 21 22 22 #include "includes.h" 23 #include "system/network.h" 24 #include <tevent.h> 25 #include "lib/util/tevent_ntstatus.h" 23 26 #include "libcli/raw/libcliraw.h" 24 27 #include "libcli/smb2/smb2.h" 25 28 #include "libcli/smb2/smb2_calls.h" 26 #include "libcli/composite/composite.h"27 29 #include "auth/gensec/gensec.h" 28 29 #include <unistd.h>30 #include "auth/credentials/credentials.h" 31 #include "../libcli/smb/smbXcli_base.h" 30 32 31 33 /** … … 34 36 struct smb2_session *smb2_session_init(struct smb2_transport *transport, 35 37 struct gensec_settings *settings, 36 TALLOC_CTX *parent_ctx , bool primary)38 TALLOC_CTX *parent_ctx) 37 39 { 38 40 struct smb2_session *session; … … 43 45 return NULL; 44 46 } 45 if (primary) {46 session->transport = talloc_steal(session, transport); 47 } else {48 session->transport = talloc_reference(session, transport);49 }50 51 session->pid = getpid();47 session->transport = talloc_steal(session, transport); 48 49 session->smbXcli = smbXcli_session_create(session, transport->conn); 50 if (session->smbXcli == NULL) { 51 talloc_free(session); 52 return NULL; 53 } 52 54 53 55 /* prepare a gensec context for later use */ 54 status = gensec_client_start(session, &session->gensec, 55 session->transport->socket->event.ctx, 56 status = gensec_client_start(session, &session->gensec, 56 57 settings); 57 58 if (!NT_STATUS_IS_OK(status)) { … … 65 66 } 66 67 67 /** 68 send a session setup request 69 */ 70 struct smb2_request *smb2_session_setup_send(struct smb2_session *session, 71 struct smb2_session_setup *io) 72 { 73 struct smb2_request *req; 74 NTSTATUS status; 75 76 req = smb2_request_init(session->transport, SMB2_OP_SESSSETUP, 77 0x18, true, io->in.secblob.length); 78 if (req == NULL) return NULL; 79 80 SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, session->uid); 81 SCVAL(req->out.body, 0x02, io->in.vc_number); 82 SCVAL(req->out.body, 0x03, io->in.security_mode); 83 SIVAL(req->out.body, 0x04, io->in.capabilities); 84 SIVAL(req->out.body, 0x08, io->in.channel); 85 SBVAL(req->out.body, 0x10, io->in.previous_sessionid); 86 87 req->session = session; 88 89 status = smb2_push_o16s16_blob(&req->out, 0x0C, io->in.secblob); 68 /* 69 * Note: that the caller needs to keep 'transport' around as 70 * long as the returned session is active! 71 */ 72 struct smb2_session *smb2_session_channel(struct smb2_transport *transport, 73 struct gensec_settings *settings, 74 TALLOC_CTX *parent_ctx, 75 struct smb2_session *base_session) 76 { 77 struct smb2_session *session; 78 NTSTATUS status; 79 80 session = talloc_zero(parent_ctx, struct smb2_session); 81 if (!session) { 82 return NULL; 83 } 84 session->transport = transport; 85 86 status = smb2cli_session_create_channel(session, 87 base_session->smbXcli, 88 transport->conn, 89 &session->smbXcli); 90 90 if (!NT_STATUS_IS_OK(status)) { 91 talloc_free(req); 92 return NULL; 93 } 94 95 smb2_transport_send(req); 96 97 return req; 98 } 99 100 101 /** 102 recv a session setup reply 103 */ 104 NTSTATUS smb2_session_setup_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, 105 struct smb2_session_setup *io) 106 { 107 NTSTATUS status; 108 109 if (!smb2_request_receive(req) || 110 (smb2_request_is_error(req) && 111 !NT_STATUS_EQUAL(req->status, NT_STATUS_MORE_PROCESSING_REQUIRED))) { 112 return smb2_request_destroy(req); 113 } 114 115 SMB2_CHECK_PACKET_RECV(req, 0x08, true); 116 117 io->out.session_flags = SVAL(req->in.body, 0x02); 118 io->out.uid = BVAL(req->in.hdr, SMB2_HDR_SESSION_ID); 119 120 status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x04, &io->out.secblob); 91 talloc_free(session); 92 return NULL; 93 } 94 95 session->needs_bind = true; 96 97 /* prepare a gensec context for later use */ 98 status = gensec_client_start(session, &session->gensec, 99 settings); 121 100 if (!NT_STATUS_IS_OK(status)) { 122 smb2_request_destroy(req); 123 return status; 124 } 125 126 return smb2_request_destroy(req); 127 } 128 129 /* 130 sync session setup request 131 */ 132 NTSTATUS smb2_session_setup(struct smb2_session *session, 133 TALLOC_CTX *mem_ctx, struct smb2_session_setup *io) 134 { 135 struct smb2_request *req = smb2_session_setup_send(session, io); 136 return smb2_session_setup_recv(req, mem_ctx, io); 137 } 138 139 140 struct smb2_session_state { 141 struct smb2_session_setup io; 142 struct smb2_request *req; 101 talloc_free(session); 102 return NULL; 103 } 104 105 gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY); 106 107 return session; 108 } 109 110 struct smb2_session_setup_spnego_state { 111 struct tevent_context *ev; 112 struct smb2_session *session; 113 struct cli_credentials *credentials; 114 uint64_t previous_session_id; 115 bool session_bind; 116 bool reauth; 143 117 NTSTATUS gensec_status; 118 DATA_BLOB in_secblob; 119 DATA_BLOB out_secblob; 144 120 }; 145 121 146 /* 147 handle continuations of the spnego session setup 148 */ 149 static void session_request_handler(struct smb2_request *req) 150 { 151 struct composite_context *c = talloc_get_type(req->async.private_data, 152 struct composite_context); 153 struct smb2_session_state *state = talloc_get_type(c->private_data, 154 struct smb2_session_state); 155 struct smb2_session *session = req->session; 156 NTSTATUS session_key_err; 157 DATA_BLOB session_key; 158 NTSTATUS peer_status; 159 160 c->status = smb2_session_setup_recv(req, c, &state->io); 161 peer_status = c->status; 162 163 if (NT_STATUS_EQUAL(peer_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || 164 (NT_STATUS_IS_OK(peer_status) && 165 NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED))) { 166 c->status = gensec_update(session->gensec, c, 167 state->io.out.secblob, 168 &state->io.in.secblob); 169 state->gensec_status = c->status; 170 171 session->uid = state->io.out.uid; 172 } 173 174 if (!NT_STATUS_IS_OK(c->status) && 175 !NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { 176 composite_error(c, c->status); 177 return; 178 } 179 180 if (NT_STATUS_EQUAL(peer_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { 181 state->req = smb2_session_setup_send(session, &state->io); 182 if (state->req == NULL) { 183 composite_error(c, NT_STATUS_NO_MEMORY); 184 return; 185 } 186 187 state->req->async.fn = session_request_handler; 188 state->req->async.private_data = c; 189 return; 190 } 191 192 session_key_err = gensec_session_key(session->gensec, &session_key); 193 if (NT_STATUS_IS_OK(session_key_err)) { 194 session->session_key = session_key; 195 } 196 197 if (session->transport->signing_required) { 198 if (session->session_key.length == 0) { 199 DEBUG(0,("Wrong session key length %u for SMB2 signing\n", 200 (unsigned)session->session_key.length)); 201 composite_error(c, NT_STATUS_ACCESS_DENIED); 202 return; 203 } 204 session->signing_active = true; 205 } 206 207 composite_done(c); 208 } 122 static void smb2_session_setup_spnego_done(struct tevent_req *subreq); 209 123 210 124 /* 211 125 a composite function that does a full SPNEGO session setup 212 126 */ 213 struct composite_context *smb2_session_setup_spnego_send(struct smb2_session *session, 214 struct cli_credentials *credentials) 215 { 216 struct composite_context *c; 217 struct smb2_session_state *state; 127 struct tevent_req *smb2_session_setup_spnego_send( 128 TALLOC_CTX *mem_ctx, 129 struct tevent_context *ev, 130 struct smb2_session *session, 131 struct cli_credentials *credentials, 132 uint64_t previous_session_id) 133 { 134 struct tevent_req *req; 135 struct smb2_session_setup_spnego_state *state; 136 uint64_t current_session_id; 218 137 const char *chosen_oid; 219 220 c = composite_create(session, session->transport->socket->event.ctx); 221 if (c == NULL) return NULL; 222 223 state = talloc(c, struct smb2_session_state); 224 if (composite_nomem(state, c)) return c; 225 c->private_data = state; 226 227 ZERO_STRUCT(state->io); 228 state->io.in.vc_number = 0; 229 if (session->transport->signing_required) { 230 state->io.in.security_mode = 231 SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED; 232 } 233 state->io.in.capabilities = 0; 234 state->io.in.channel = 0; 235 state->io.in.previous_sessionid = 0; 236 237 c->status = gensec_set_credentials(session->gensec, credentials); 238 if (!composite_is_ok(c)) return c; 239 240 c->status = gensec_set_target_hostname(session->gensec, 241 session->transport->socket->hostname); 242 if (!composite_is_ok(c)) return c; 243 244 c->status = gensec_set_target_service(session->gensec, "cifs"); 245 if (!composite_is_ok(c)) return c; 246 247 if (session->transport->negotiate.secblob.length > 0) { 138 struct tevent_req *subreq; 139 NTSTATUS status; 140 const DATA_BLOB *server_gss_blob; 141 DATA_BLOB negprot_secblob = data_blob_null; 142 uint32_t timeout_msec; 143 uint8_t in_flags = 0; 144 145 timeout_msec = session->transport->options.request_timeout * 1000; 146 147 req = tevent_req_create(mem_ctx, &state, 148 struct smb2_session_setup_spnego_state); 149 if (req == NULL) { 150 return NULL; 151 } 152 state->ev = ev; 153 state->session = session; 154 state->credentials = credentials; 155 state->previous_session_id = previous_session_id; 156 157 current_session_id = smb2cli_session_current_id(state->session->smbXcli); 158 if (state->session->needs_bind) { 159 state->session_bind = true; 160 } else if (current_session_id != 0) { 161 state->reauth = true; 162 } 163 server_gss_blob = smbXcli_conn_server_gss_blob(session->transport->conn); 164 if (server_gss_blob) { 165 negprot_secblob = *server_gss_blob; 166 } 167 168 status = gensec_set_credentials(session->gensec, credentials); 169 if (tevent_req_nterror(req, status)) { 170 return tevent_req_post(req, ev); 171 } 172 173 status = gensec_set_target_hostname(session->gensec, 174 smbXcli_conn_remote_name(session->transport->conn)); 175 if (tevent_req_nterror(req, status)) { 176 return tevent_req_post(req, ev); 177 } 178 179 status = gensec_set_target_service(session->gensec, "cifs"); 180 if (tevent_req_nterror(req, status)) { 181 return tevent_req_post(req, ev); 182 } 183 184 if (negprot_secblob.length > 0) { 248 185 chosen_oid = GENSEC_OID_SPNEGO; 249 186 } else { … … 251 188 } 252 189 253 c->status = gensec_start_mech_by_oid(session->gensec, chosen_oid); 254 if (!composite_is_ok(c)) return c; 255 256 c->status = gensec_update(session->gensec, c, 257 session->transport->negotiate.secblob, 258 &state->io.in.secblob); 259 if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { 260 composite_error(c, c->status); 261 return c; 262 } 263 state->gensec_status = c->status; 264 265 state->req = smb2_session_setup_send(session, &state->io); 266 composite_continue_smb2(c, state->req, session_request_handler, c); 267 return c; 190 status = gensec_start_mech_by_oid(session->gensec, chosen_oid); 191 if (tevent_req_nterror(req, status)) { 192 return tevent_req_post(req, ev); 193 } 194 195 status = gensec_update_ev(session->gensec, state, 196 state->ev, 197 negprot_secblob, 198 &state->in_secblob); 199 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { 200 tevent_req_nterror(req, status); 201 return tevent_req_post(req, ev); 202 } 203 state->gensec_status = status; 204 205 if (state->session_bind) { 206 in_flags |= SMB2_SESSION_FLAG_BINDING; 207 } 208 209 subreq = smb2cli_session_setup_send(state, state->ev, 210 session->transport->conn, 211 timeout_msec, 212 session->smbXcli, 213 in_flags, 214 0, /* in_capabilities */ 215 0, /* in_channel */ 216 state->previous_session_id, 217 &state->in_secblob); 218 if (tevent_req_nomem(subreq, req)) { 219 return tevent_req_post(req, ev); 220 } 221 tevent_req_set_callback(subreq, smb2_session_setup_spnego_done, req); 222 223 return req; 224 } 225 226 /* 227 handle continuations of the spnego session setup 228 */ 229 static void smb2_session_setup_spnego_done(struct tevent_req *subreq) 230 { 231 struct tevent_req *req = 232 tevent_req_callback_data(subreq, 233 struct tevent_req); 234 struct smb2_session_setup_spnego_state *state = 235 tevent_req_data(req, 236 struct smb2_session_setup_spnego_state); 237 struct smb2_session *session = state->session; 238 NTSTATUS peer_status; 239 NTSTATUS status; 240 struct iovec *recv_iov; 241 uint32_t timeout_msec; 242 uint8_t in_flags = 0; 243 244 timeout_msec = session->transport->options.request_timeout * 1000; 245 246 status = smb2cli_session_setup_recv(subreq, state, 247 &recv_iov, 248 &state->out_secblob); 249 if (!NT_STATUS_IS_OK(status) && 250 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { 251 tevent_req_nterror(req, status); 252 return; 253 } 254 peer_status = status; 255 256 if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { 257 status = gensec_update_ev(session->gensec, state, 258 state->ev, 259 state->out_secblob, 260 &state->in_secblob); 261 state->gensec_status = status; 262 } 263 264 if (!NT_STATUS_IS_OK(status) && 265 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { 266 tevent_req_nterror(req, status); 267 return; 268 } 269 270 if (NT_STATUS_IS_OK(peer_status) && NT_STATUS_IS_OK(state->gensec_status)) { 271 DATA_BLOB session_key; 272 273 if (state->reauth) { 274 tevent_req_done(req); 275 return; 276 } 277 278 if (cli_credentials_is_anonymous(state->credentials)) { 279 /* 280 * Windows server does not set the 281 * SMB2_SESSION_FLAG_IS_GUEST nor 282 * SMB2_SESSION_FLAG_IS_NULL flag. 283 * 284 * This fix makes sure we do not try 285 * to verify a signature on the final 286 * session setup response. 287 */ 288 tevent_req_done(req); 289 return; 290 } 291 292 status = gensec_session_key(session->gensec, state, 293 &session_key); 294 if (tevent_req_nterror(req, status)) { 295 return; 296 } 297 298 if (state->session_bind) { 299 status = smb2cli_session_set_channel_key(session->smbXcli, 300 session_key, 301 recv_iov); 302 if (tevent_req_nterror(req, status)) { 303 return; 304 } 305 session->needs_bind = false; 306 } else { 307 status = smb2cli_session_set_session_key(session->smbXcli, 308 session_key, 309 recv_iov); 310 if (tevent_req_nterror(req, status)) { 311 return; 312 } 313 } 314 tevent_req_done(req); 315 return; 316 } 317 318 if (state->session_bind) { 319 in_flags |= SMB2_SESSION_FLAG_BINDING; 320 } 321 322 subreq = smb2cli_session_setup_send(state, state->ev, 323 session->transport->conn, 324 timeout_msec, 325 session->smbXcli, 326 in_flags, 327 0, /* in_capabilities */ 328 0, /* in_channel */ 329 state->previous_session_id, 330 &state->in_secblob); 331 if (tevent_req_nomem(subreq, req)) { 332 return; 333 } 334 tevent_req_set_callback(subreq, smb2_session_setup_spnego_done, req); 268 335 } 269 336 … … 271 338 receive a composite session setup reply 272 339 */ 273 NTSTATUS smb2_session_setup_spnego_recv(struct composite_context *c) 274 { 275 NTSTATUS status; 276 status = composite_wait(c); 277 talloc_free(c); 278 return status; 340 NTSTATUS smb2_session_setup_spnego_recv(struct tevent_req *req) 341 { 342 return tevent_req_simple_recv_ntstatus(req); 279 343 } 280 344 … … 283 347 */ 284 348 NTSTATUS smb2_session_setup_spnego(struct smb2_session *session, 285 struct cli_credentials *credentials) 286 { 287 struct composite_context *c = smb2_session_setup_spnego_send(session, credentials); 288 return smb2_session_setup_spnego_recv(c); 289 } 349 struct cli_credentials *credentials, 350 uint64_t previous_session_id) 351 { 352 struct tevent_req *subreq; 353 NTSTATUS status; 354 bool ok; 355 TALLOC_CTX *frame = talloc_stackframe(); 356 struct tevent_context *ev = session->transport->ev; 357 358 if (frame == NULL) { 359 return NT_STATUS_NO_MEMORY; 360 } 361 362 subreq = smb2_session_setup_spnego_send(frame, ev, 363 session, credentials, 364 previous_session_id); 365 if (subreq == NULL) { 366 TALLOC_FREE(frame); 367 return NT_STATUS_NO_MEMORY; 368 } 369 370 ok = tevent_req_poll(subreq, ev); 371 if (!ok) { 372 status = map_nt_error_from_unix_common(errno); 373 TALLOC_FREE(frame); 374 return status; 375 } 376 377 status = smb2_session_setup_spnego_recv(subreq); 378 TALLOC_FREE(subreq); 379 if (!NT_STATUS_IS_OK(status)) { 380 TALLOC_FREE(frame); 381 return status; 382 } 383 384 TALLOC_FREE(frame); 385 return NT_STATUS_OK; 386 } -
vendor/current/source4/libcli/smb2/smb2.h
r740 r988 28 28 struct smb2_handle; 29 29 struct smb2_lease_break; 30 31 /*32 information returned from the negotiate process33 */34 struct smb2_negotiate {35 DATA_BLOB secblob;36 NTTIME system_time;37 NTTIME server_start_time;38 uint16_t security_mode;39 uint16_t dialect_revision;40 };41 30 42 31 struct smb2_request_buffer { … … 71 60 /* this is the context for the smb2 transport layer */ 72 61 struct smb2_transport { 73 /* socket level info */ 74 struct smbcli_socket *socket; 75 76 struct smb2_negotiate negotiate; 77 78 /* next seqnum to allocate */ 79 uint64_t seqnum; 62 struct tevent_context *ev; /* TODO: remove this !!! */ 63 struct smbXcli_conn *conn; 80 64 81 65 /* the details for coumpounded requests */ 82 66 struct { 83 uint32_t missing;84 67 bool related; 85 struct smb2_request_buffer buffer;68 struct tevent_req **reqs; 86 69 } compound; 87 88 struct {89 uint16_t charge;90 uint16_t ask_num;91 } credits;92 93 /* a list of requests that are pending for receive on this94 connection */95 struct smb2_request *pending_recv;96 97 /* context of the stream -> packet parser */98 struct packet_context *packet;99 70 100 71 /* an idle function - if this is defined then it will be … … 105 76 void *private_data; 106 77 unsigned int period; 78 struct tevent_timer *te; 107 79 } idle; 108 80 … … 124 96 void *private_data; 125 97 } lease; 98 struct tevent_req *break_subreq; 126 99 127 100 struct smbcli_options options; 128 129 bool signing_required;130 101 }; 131 102 … … 136 107 struct smb2_tree { 137 108 struct smb2_session *session; 138 uint32_t tid;109 struct smbXcli_tcon *smbXcli; 139 110 }; 140 111 … … 145 116 struct smb2_transport *transport; 146 117 struct gensec_security *gensec; 147 uint64_t uid; 148 uint32_t pid; 149 DATA_BLOB session_key; 150 bool signing_active; 118 struct smbXcli_session *smbXcli; 119 bool needs_bind; 151 120 }; 152 121 … … 163 132 /* the context for a single SMB2 request */ 164 133 struct smb2_request { 165 /* allow a request to be part of a list of requests */166 struct smb2_request *next, *prev;167 168 134 /* each request is in one of 3 possible states */ 169 135 enum smb2_request_state state; 136 137 struct tevent_req *subreq; 170 138 171 139 struct smb2_transport *transport; … … 173 141 struct smb2_tree *tree; 174 142 175 uint64_t seqnum;176 177 143 struct { 178 bool do_cancel;179 144 bool can_cancel; 180 uint64_t async_id;181 145 } cancel; 182 146 … … 187 151 struct smb2_request_buffer in; 188 152 struct smb2_request_buffer out; 153 struct iovec *recv_iov; 154 155 uint16_t credit_charge; 189 156 190 157 /* information on what to do with a reply when it is received -
vendor/current/source4/libcli/smb2/tcon.c
r414 r988 23 23 #include "libcli/smb2/smb2.h" 24 24 #include "libcli/smb2/smb2_calls.h" 25 #include "../libcli/smb/smbXcli_base.h" 25 26 26 27 /* … … 41 42 tree->session = talloc_reference(tree, session); 42 43 } 43 return tree;44 }45 44 46 /* 47 send a tree connect 48 */ 49 struct smb2_request *smb2_tree_connect_send(struct smb2_tree *tree, 50 struct smb2_tree_connect *io) 51 { 52 struct smb2_request *req; 53 NTSTATUS status; 54 55 req = smb2_request_init(tree->session->transport, SMB2_OP_TCON, 56 0x08, true, 0); 57 if (req == NULL) return NULL; 58 59 SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, tree->session->uid); 60 req->session = tree->session; 61 62 SSVAL(req->out.body, 0x02, io->in.reserved); 63 status = smb2_push_o16s16_string(&req->out, 0x04, io->in.path); 64 if (!NT_STATUS_IS_OK(status)) { 65 talloc_free(req); 45 tree->smbXcli = smbXcli_tcon_create(tree); 46 if (tree->smbXcli == NULL) { 47 talloc_free(tree); 66 48 return NULL; 67 49 } 68 50 69 smb2_transport_send(req); 70 71 return req; 51 return tree; 72 52 } 73 74 75 /*76 recv a tree connect reply77 */78 NTSTATUS smb2_tree_connect_recv(struct smb2_request *req, struct smb2_tree_connect *io)79 {80 if (!smb2_request_receive(req) ||81 smb2_request_is_error(req)) {82 return smb2_request_destroy(req);83 }84 85 SMB2_CHECK_PACKET_RECV(req, 0x10, false);86 87 io->out.tid = IVAL(req->in.hdr, SMB2_HDR_TID);88 89 io->out.share_type = CVAL(req->in.body, 0x02);90 io->out.reserved = CVAL(req->in.body, 0x03);91 io->out.flags = IVAL(req->in.body, 0x04);92 io->out.capabilities= IVAL(req->in.body, 0x08);93 io->out.access_mask = IVAL(req->in.body, 0x0C);94 95 if (io->out.capabilities & ~SMB2_CAP_ALL) {96 DEBUG(0,("Unknown capabilities mask 0x%x\n", io->out.capabilities));97 }98 if (io->out.flags & ~SMB2_SHAREFLAG_ALL) {99 DEBUG(0,("Unknown tcon shareflag 0x%x\n", io->out.flags));100 }101 102 return smb2_request_destroy(req);103 }104 105 /*106 sync tree connect request107 */108 NTSTATUS smb2_tree_connect(struct smb2_tree *tree, struct smb2_tree_connect *io)109 {110 struct smb2_request *req = smb2_tree_connect_send(tree, io);111 return smb2_tree_connect_recv(req, io);112 } -
vendor/current/source4/libcli/smb2/transport.c
r740 r988 21 21 22 22 #include "includes.h" 23 #include "system/network.h" 23 24 #include "libcli/raw/libcliraw.h" 24 25 #include "libcli/raw/raw_proto.h" … … 27 28 #include "lib/socket/socket.h" 28 29 #include "lib/events/events.h" 29 #include "lib/stream/packet.h"30 30 #include "../lib/util/dlinklist.h" 31 32 33 /* 34 an event has happened on the socket 35 */ 36 static void smb2_transport_event_handler(struct tevent_context *ev, 37 struct tevent_fd *fde, 38 uint16_t flags, void *private_data) 39 { 40 struct smb2_transport *transport = talloc_get_type(private_data, 41 struct smb2_transport); 42 if (flags & EVENT_FD_READ) { 43 packet_recv(transport->packet); 44 return; 45 } 46 if (flags & EVENT_FD_WRITE) { 47 packet_queue_run(transport->packet); 48 } 49 } 31 #include "../libcli/smb/smbXcli_base.h" 32 #include "librpc/ndr/libndr.h" 50 33 51 34 /* … … 57 40 return 0; 58 41 } 59 60 61 /*62 handle receive errors63 */64 static void smb2_transport_error(void *private_data, NTSTATUS status)65 {66 struct smb2_transport *transport = talloc_get_type(private_data,67 struct smb2_transport);68 smb2_transport_dead(transport, status);69 }70 71 static NTSTATUS smb2_transport_finish_recv(void *private_data, DATA_BLOB blob);72 42 73 43 /* … … 83 53 if (!transport) return NULL; 84 54 85 transport-> socket = talloc_steal(transport, sock);55 transport->ev = sock->event.ctx; 86 56 transport->options = *options; 87 transport->credits.charge = 0; 88 transport->credits.ask_num = 1; 89 90 /* setup the stream -> packet parser */ 91 transport->packet = packet_init(transport); 92 if (transport->packet == NULL) { 57 58 if (transport->options.max_protocol == PROTOCOL_DEFAULT) { 59 transport->options.max_protocol = PROTOCOL_LATEST; 60 } 61 62 if (transport->options.max_protocol < PROTOCOL_SMB2_02) { 63 transport->options.max_protocol = PROTOCOL_LATEST; 64 } 65 66 TALLOC_FREE(sock->event.fde); 67 TALLOC_FREE(sock->event.te); 68 69 transport->conn = smbXcli_conn_create(transport, 70 sock->sock->fd, 71 sock->hostname, 72 options->signing, 73 0, /* smb1_capabilities */ 74 &options->client_guid, 75 options->smb2_capabilities); 76 if (transport->conn == NULL) { 93 77 talloc_free(transport); 94 78 return NULL; 95 79 } 96 packet_set_private(transport->packet, transport); 97 packet_set_socket(transport->packet, transport->socket->sock); 98 packet_set_callback(transport->packet, smb2_transport_finish_recv); 99 packet_set_full_request(transport->packet, packet_full_request_nbt); 100 packet_set_error_handler(transport->packet, smb2_transport_error); 101 packet_set_event_context(transport->packet, transport->socket->event.ctx); 102 packet_set_nofree(transport->packet); 103 104 /* take over event handling from the socket layer - it only 105 handles events up until we are connected */ 106 talloc_free(transport->socket->event.fde); 107 transport->socket->event.fde = event_add_fd(transport->socket->event.ctx, 108 transport->socket, 109 socket_get_fd(transport->socket->sock), 110 EVENT_FD_READ, 111 smb2_transport_event_handler, 112 transport); 113 114 packet_set_fde(transport->packet, transport->socket->event.fde); 115 packet_set_serialise(transport->packet); 80 sock->sock->fd = -1; 81 TALLOC_FREE(sock); 116 82 117 83 talloc_set_destructor(transport, transport_destructor); … … 125 91 void smb2_transport_dead(struct smb2_transport *transport, NTSTATUS status) 126 92 { 127 smbcli_sock_dead(transport->socket);128 129 93 if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) { 130 94 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; 131 95 } 132 133 /* kill all pending receives */ 134 while (transport->pending_recv) { 135 struct smb2_request *req = transport->pending_recv; 96 if (NT_STATUS_IS_OK(status)) { 97 status = NT_STATUS_LOCAL_DISCONNECT; 98 } 99 100 smbXcli_conn_disconnect(transport->conn, status); 101 } 102 103 static void smb2_request_done(struct tevent_req *subreq); 104 static void smb2_transport_break_handler(struct tevent_req *subreq); 105 106 /* 107 put a request into the send queue 108 */ 109 void smb2_transport_send(struct smb2_request *req) 110 { 111 NTSTATUS status; 112 struct smb2_transport *transport = req->transport; 113 struct tevent_req **reqs = transport->compound.reqs; 114 size_t num_reqs = talloc_array_length(reqs); 115 size_t i; 116 uint16_t cmd = SVAL(req->out.hdr, SMB2_HDR_OPCODE); 117 uint32_t additional_flags = IVAL(req->out.hdr, SMB2_HDR_FLAGS); 118 uint32_t clear_flags = 0; 119 struct smbXcli_tcon *tcon = NULL; 120 struct smbXcli_session *session = NULL; 121 bool need_pending_break = false; 122 size_t hdr_ofs; 123 size_t pdu_len; 124 DATA_BLOB body = data_blob_null; 125 DATA_BLOB dyn = data_blob_null; 126 uint32_t timeout_msec = transport->options.request_timeout * 1000; 127 128 if (transport->oplock.handler) { 129 need_pending_break = true; 130 } 131 132 if (transport->lease.handler) { 133 need_pending_break = true; 134 } 135 136 if (transport->break_subreq) { 137 need_pending_break = false; 138 } 139 140 if (need_pending_break) { 141 struct tevent_req *subreq; 142 143 subreq = smb2cli_req_create(transport, 144 transport->ev, 145 transport->conn, 146 SMB2_OP_BREAK, 147 0, /* additional_flags */ 148 0, /*clear_flags */ 149 0, /* timeout_msec */ 150 NULL, /* tcon */ 151 NULL, /* session */ 152 NULL, /* body */ 153 0, /* body_fixed */ 154 NULL, /* dyn */ 155 0, /* dyn_len */ 156 0); /* max_dyn_len */ 157 if (subreq != NULL) { 158 smbXcli_req_set_pending(subreq); 159 tevent_req_set_callback(subreq, 160 smb2_transport_break_handler, 161 transport); 162 transport->break_subreq = subreq; 163 } 164 } 165 166 if (req->session) { 167 session = req->session->smbXcli; 168 } 169 170 if (req->tree) { 171 tcon = req->tree->smbXcli; 172 } 173 174 if (transport->compound.related) { 175 additional_flags |= SMB2_HDR_FLAG_CHAINED; 176 } 177 178 hdr_ofs = PTR_DIFF(req->out.hdr, req->out.buffer); 179 pdu_len = req->out.size - hdr_ofs; 180 body.data = req->out.body; 181 body.length = req->out.body_fixed; 182 dyn.data = req->out.body + req->out.body_fixed; 183 dyn.length = pdu_len - (SMB2_HDR_BODY + req->out.body_fixed); 184 185 req->subreq = smb2cli_req_create(req, 186 transport->ev, 187 transport->conn, 188 cmd, 189 additional_flags, 190 clear_flags, 191 timeout_msec, 192 tcon, 193 session, 194 body.data, body.length, 195 dyn.data, dyn.length, 196 0); /* max_dyn_len */ 197 if (req->subreq == NULL) { 136 198 req->state = SMB2_REQUEST_ERROR; 199 req->status = NT_STATUS_NO_MEMORY; 200 return; 201 } 202 203 if (!tevent_req_is_in_progress(req->subreq)) { 204 req->state = SMB2_REQUEST_ERROR; 205 req->status = NT_STATUS_INTERNAL_ERROR;/* TODO */ 206 return; 207 } 208 209 tevent_req_set_callback(req->subreq, smb2_request_done, req); 210 211 smb2cli_req_set_notify_async(req->subreq); 212 if (req->credit_charge) { 213 smb2cli_req_set_credit_charge(req->subreq, req->credit_charge); 214 } 215 216 ZERO_STRUCT(req->out); 217 req->state = SMB2_REQUEST_RECV; 218 219 if (num_reqs > 0) { 220 for (i=0; i < num_reqs; i++) { 221 if (reqs[i] != NULL) { 222 continue; 223 } 224 225 reqs[i] = req->subreq; 226 i++; 227 break; 228 } 229 230 if (i < num_reqs) { 231 return; 232 } 233 } else { 234 reqs = &req->subreq; 235 num_reqs = 1; 236 } 237 status = smb2cli_req_compound_submit(reqs, num_reqs); 238 239 TALLOC_FREE(transport->compound.reqs); 240 transport->compound.related = false; 241 242 if (!NT_STATUS_IS_OK(status)) { 137 243 req->status = status; 138 DLIST_REMOVE(transport->pending_recv, req); 139 if (req->async.fn) { 140 req->async.fn(req); 141 } 142 } 143 } 144 145 static NTSTATUS smb2_handle_oplock_break(struct smb2_transport *transport, 146 const DATA_BLOB *blob) 147 { 148 uint8_t *hdr; 244 req->state = SMB2_REQUEST_ERROR; 245 smbXcli_conn_disconnect(transport->conn, status); 246 } 247 } 248 249 static void smb2_request_done(struct tevent_req *subreq) 250 { 251 struct smb2_request *req = 252 tevent_req_callback_data(subreq, 253 struct smb2_request); 254 ssize_t len; 255 size_t i; 256 257 req->recv_iov = NULL; 258 259 req->status = smb2cli_req_recv(req->subreq, req, &req->recv_iov, NULL, 0); 260 if (NT_STATUS_EQUAL(req->status, STATUS_PENDING)) { 261 req->cancel.can_cancel = true; 262 return; 263 } 264 TALLOC_FREE(req->subreq); 265 if (!NT_STATUS_IS_OK(req->status)) { 266 if (req->recv_iov == NULL) { 267 req->state = SMB2_REQUEST_ERROR; 268 if (req->async.fn) { 269 req->async.fn(req); 270 } 271 return; 272 } 273 } 274 275 len = req->recv_iov[0].iov_len; 276 for (i=1; i < 3; i++) { 277 uint8_t *p = req->recv_iov[i-1].iov_base; 278 uint8_t *c1 = req->recv_iov[i].iov_base; 279 uint8_t *c2 = p + req->recv_iov[i-1].iov_len; 280 281 len += req->recv_iov[i].iov_len; 282 283 if (req->recv_iov[i].iov_len == 0) { 284 continue; 285 } 286 287 if (c1 != c2) { 288 req->status = NT_STATUS_INTERNAL_ERROR; 289 req->state = SMB2_REQUEST_ERROR; 290 if (req->async.fn) { 291 req->async.fn(req); 292 } 293 return; 294 } 295 } 296 297 req->in.buffer = req->recv_iov[0].iov_base; 298 req->in.size = len; 299 req->in.allocated = req->in.size; 300 301 req->in.hdr = req->recv_iov[0].iov_base; 302 req->in.body = req->recv_iov[1].iov_base; 303 req->in.dynamic = req->recv_iov[2].iov_base; 304 req->in.body_fixed = req->recv_iov[1].iov_len; 305 req->in.body_size = req->in.body_fixed; 306 req->in.body_size += req->recv_iov[2].iov_len; 307 308 smb2_setup_bufinfo(req); 309 310 req->state = SMB2_REQUEST_DONE; 311 if (req->async.fn) { 312 req->async.fn(req); 313 } 314 } 315 316 static void smb2_transport_break_handler(struct tevent_req *subreq) 317 { 318 struct smb2_transport *transport = 319 tevent_req_callback_data(subreq, 320 struct smb2_transport); 321 NTSTATUS status; 149 322 uint8_t *body; 150 uint16_t len , bloblen;323 uint16_t len = 0; 151 324 bool lease; 152 153 hdr = blob->data+NBT_HDR_SIZE; 154 body = hdr+SMB2_HDR_BODY; 155 bloblen = blob->length - SMB2_HDR_BODY; 156 157 if (bloblen < 2) { 158 DEBUG(1,("Discarding smb2 oplock reply of size %u\n", 159 (unsigned)blob->length)); 160 return NT_STATUS_INVALID_NETWORK_RESPONSE; 161 } 162 163 len = CVAL(body, 0x00); 164 if (len > bloblen) { 165 DEBUG(1,("Discarding smb2 oplock reply," 166 "packet claims %u byte body, only %u bytes seen\n", 167 len, bloblen)); 168 return NT_STATUS_INVALID_NETWORK_RESPONSE; 325 struct iovec *recv_iov = NULL; 326 327 transport->break_subreq = NULL; 328 329 status = smb2cli_req_recv(subreq, transport, &recv_iov, NULL, 0); 330 TALLOC_FREE(subreq); 331 if (!NT_STATUS_IS_OK(status)) { 332 TALLOC_FREE(recv_iov); 333 smb2_transport_dead(transport, status); 334 return; 335 } 336 337 /* 338 * Setup the subreq to handle the 339 * next incoming SMB2 Break. 340 */ 341 subreq = smb2cli_req_create(transport, 342 transport->ev, 343 transport->conn, 344 SMB2_OP_BREAK, 345 0, /* additional_flags */ 346 0, /*clear_flags */ 347 0, /* timeout_msec */ 348 NULL, /* tcon */ 349 NULL, /* session */ 350 NULL, /* body */ 351 0, /* body_fixed */ 352 NULL, /* dyn */ 353 0, /* dyn_len */ 354 0); /* max_dyn_len */ 355 if (subreq != NULL) { 356 smbXcli_req_set_pending(subreq); 357 tevent_req_set_callback(subreq, 358 smb2_transport_break_handler, 359 transport); 360 transport->break_subreq = subreq; 361 } 362 363 body = recv_iov[1].iov_base; 364 365 len = recv_iov[1].iov_len; 366 if (recv_iov[1].iov_len >= 2) { 367 len = CVAL(body, 0x00); 368 if (len != recv_iov[1].iov_len) { 369 len = recv_iov[1].iov_len; 370 } 169 371 } 170 372 … … 175 377 } else { 176 378 DEBUG(1,("Discarding smb2 oplock reply of invalid size %u\n", 177 (unsigned)blob->length)); 178 return NT_STATUS_INVALID_NETWORK_RESPONSE; 379 (unsigned)len)); 380 TALLOC_FREE(recv_iov); 381 status = NT_STATUS_INVALID_NETWORK_RESPONSE; 382 smb2_transport_dead(transport, status); 383 return; 179 384 } 180 385 … … 185 390 level = CVAL(body, 0x02); 186 391 smb2_pull_handle(body+0x08, &h); 392 393 TALLOC_FREE(recv_iov); 187 394 188 395 transport->oplock.handler(transport, &h, level, … … 192 399 193 400 ZERO_STRUCT(lb); 401 lb.new_epoch = SVAL(body, 0x2); 194 402 lb.break_flags = SVAL(body, 0x4); 195 403 memcpy(&lb.current_lease.lease_key, body+0x8, … … 201 409 lb.share_mask_hint = SVAL(body, 0x28); 202 410 411 TALLOC_FREE(recv_iov); 412 203 413 transport->lease.handler(transport, &lb, 204 414 transport->lease.private_data); … … 207 417 lease ? "lease" : "oplock")); 208 418 } 209 210 return NT_STATUS_OK; 211 } 212 213 struct smb2_transport_compount_response_state { 214 struct smb2_transport *transport; 215 DATA_BLOB blob; 216 }; 217 218 static void smb2_transport_compound_response_handler(struct tevent_context *ctx, 219 struct tevent_immediate *im, 220 void *private_data) 221 { 222 struct smb2_transport_compount_response_state *state = 223 talloc_get_type_abort(private_data, 224 struct smb2_transport_compount_response_state); 225 struct smb2_transport *transport = state->transport; 226 NTSTATUS status; 227 228 status = smb2_transport_finish_recv(transport, state->blob); 229 TALLOC_FREE(state); 230 if (!NT_STATUS_IS_OK(status)) { 231 smb2_transport_error(transport, status); 232 } 233 } 234 235 /* 236 we have a full request in our receive buffer - match it to a pending request 237 and process 238 */ 239 static NTSTATUS smb2_transport_finish_recv(void *private_data, DATA_BLOB blob) 240 { 241 struct smb2_transport *transport = talloc_get_type(private_data, 242 struct smb2_transport); 243 uint8_t *buffer, *hdr; 244 int len; 245 struct smb2_request *req = NULL; 246 uint64_t seqnum; 247 uint32_t flags; 248 uint16_t buffer_code; 249 uint32_t dynamic_size; 250 uint32_t i; 251 uint16_t opcode; 252 NTSTATUS status; 253 uint32_t next_ofs; 254 255 buffer = blob.data; 256 len = blob.length; 257 258 hdr = buffer+NBT_HDR_SIZE; 259 260 if (len < SMB2_MIN_SIZE) { 261 DEBUG(1,("Discarding smb2 reply of size %d\n", len)); 262 goto error; 263 } 264 265 flags = IVAL(hdr, SMB2_HDR_FLAGS); 266 seqnum = BVAL(hdr, SMB2_HDR_MESSAGE_ID); 267 opcode = SVAL(hdr, SMB2_HDR_OPCODE); 268 269 /* see MS-SMB2 3.2.5.19 */ 270 if (seqnum == UINT64_MAX) { 271 if (opcode != SMB2_OP_BREAK) { 272 DEBUG(1,("Discarding packet with invalid seqnum, " 273 "opcode %u\n", opcode)); 274 return NT_STATUS_INVALID_NETWORK_RESPONSE; 275 } 276 277 return smb2_handle_oplock_break(transport, &blob); 278 } 279 280 /* match the incoming request against the list of pending requests */ 281 for (req=transport->pending_recv; req; req=req->next) { 282 if (req->seqnum == seqnum) break; 283 } 284 285 if (!req) { 286 DEBUG(1,("Discarding unmatched reply with seqnum 0x%llx op %d\n", 287 (long long)seqnum, SVAL(hdr, SMB2_HDR_OPCODE))); 288 goto error; 289 } 290 291 /* fill in the 'in' portion of the matching request */ 292 req->in.buffer = buffer; 293 talloc_steal(req, buffer); 294 req->in.size = len; 295 req->in.allocated = req->in.size; 296 297 req->in.hdr = hdr; 298 req->in.body = hdr+SMB2_HDR_BODY; 299 req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE); 300 req->status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS)); 301 302 if ((flags & SMB2_HDR_FLAG_ASYNC) && 303 NT_STATUS_EQUAL(req->status, STATUS_PENDING)) { 304 req->cancel.can_cancel = true; 305 req->cancel.async_id = BVAL(hdr, SMB2_HDR_ASYNC_ID); 306 for (i=0; i< req->cancel.do_cancel; i++) { 307 smb2_cancel(req); 308 } 309 talloc_free(buffer); 310 return NT_STATUS_OK; 311 } 312 313 next_ofs = IVAL(req->in.hdr, SMB2_HDR_NEXT_COMMAND); 314 if (next_ofs > 0) { 315 if (smb2_oob(&req->in, req->in.hdr + next_ofs, SMB2_HDR_BODY + 2)) { 316 DEBUG(1,("SMB2 request invalid next offset 0x%x\n", 317 next_ofs)); 318 goto error; 319 } 320 321 req->in.size = NBT_HDR_SIZE + next_ofs; 322 req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE); 323 } 324 325 if (req->session && req->session->signing_active) { 326 status = smb2_check_signature(&req->in, 327 req->session->session_key); 328 if (!NT_STATUS_IS_OK(status)) { 329 /* the spec says to ignore packets with a bad signature */ 330 talloc_free(buffer); 331 return status; 332 } 333 } 334 335 buffer_code = SVAL(req->in.body, 0); 336 req->in.body_fixed = (buffer_code & ~1); 337 req->in.dynamic = NULL; 338 dynamic_size = req->in.body_size - req->in.body_fixed; 339 if (dynamic_size != 0 && (buffer_code & 1)) { 340 req->in.dynamic = req->in.body + req->in.body_fixed; 341 if (smb2_oob(&req->in, req->in.dynamic, dynamic_size)) { 342 DEBUG(1,("SMB2 request invalid dynamic size 0x%x\n", 343 dynamic_size)); 344 goto error; 345 } 346 } 347 348 smb2_setup_bufinfo(req); 349 350 DEBUG(2, ("SMB2 RECV seqnum=0x%llx\n", (long long)req->seqnum)); 351 dump_data(5, req->in.body, req->in.body_size); 352 353 if (next_ofs > 0) { 354 struct tevent_immediate *im; 355 struct smb2_transport_compount_response_state *state; 356 357 state = talloc(transport, 358 struct smb2_transport_compount_response_state); 359 if (!state) { 360 goto error; 361 } 362 state->transport = transport; 363 364 state->blob = data_blob_talloc(state, NULL, 365 blob.length - next_ofs); 366 if (!state->blob.data) { 367 goto error; 368 } 369 im = tevent_create_immediate(state); 370 if (!im) { 371 TALLOC_FREE(state); 372 goto error; 373 } 374 _smb2_setlen(state->blob.data, state->blob.length - NBT_HDR_SIZE); 375 memcpy(state->blob.data + NBT_HDR_SIZE, 376 req->in.hdr + next_ofs, 377 req->in.allocated - req->in.size); 378 tevent_schedule_immediate(im, transport->socket->event.ctx, 379 smb2_transport_compound_response_handler, 380 state); 381 } 382 383 /* if this request has an async handler then call that to 384 notify that the reply has been received. This might destroy 385 the request so it must happen last */ 386 DLIST_REMOVE(transport->pending_recv, req); 387 req->state = SMB2_REQUEST_DONE; 388 if (req->async.fn) { 389 req->async.fn(req); 390 } 391 return NT_STATUS_OK; 392 393 error: 394 dump_data(5, buffer, len); 395 if (req) { 396 DLIST_REMOVE(transport->pending_recv, req); 397 req->state = SMB2_REQUEST_ERROR; 398 if (req->async.fn) { 399 req->async.fn(req); 400 } 401 } else { 402 talloc_free(buffer); 403 } 404 return NT_STATUS_UNSUCCESSFUL; 405 } 406 407 /* 408 handle timeouts of individual smb requests 409 */ 410 static void smb2_timeout_handler(struct tevent_context *ev, struct tevent_timer *te, 411 struct timeval t, void *private_data) 412 { 413 struct smb2_request *req = talloc_get_type(private_data, struct smb2_request); 414 415 if (req->state == SMB2_REQUEST_RECV) { 416 DLIST_REMOVE(req->transport->pending_recv, req); 417 } 418 req->status = NT_STATUS_IO_TIMEOUT; 419 req->state = SMB2_REQUEST_ERROR; 420 if (req->async.fn) { 421 req->async.fn(req); 422 } 423 } 424 425 426 /* 427 destroy a request 428 */ 429 static int smb2_request_destructor(struct smb2_request *req) 430 { 431 if (req->state == SMB2_REQUEST_RECV) { 432 DLIST_REMOVE(req->transport->pending_recv, req); 433 } 434 return 0; 435 } 436 437 static NTSTATUS smb2_transport_raw_send(struct smb2_transport *transport, 438 struct smb2_request_buffer *buffer) 439 { 440 DATA_BLOB blob; 441 NTSTATUS status; 442 443 /* check if the transport is dead */ 444 if (transport->socket->sock == NULL) { 445 return NT_STATUS_NET_WRITE_FAULT; 446 } 447 448 _smb2_setlen(buffer->buffer, buffer->size - NBT_HDR_SIZE); 449 blob = data_blob_const(buffer->buffer, buffer->size); 450 status = packet_send(transport->packet, blob); 451 if (!NT_STATUS_IS_OK(status)) { 452 return status; 453 } 454 455 return NT_STATUS_OK; 456 } 457 458 /* 459 put a request into the send queue 460 */ 461 void smb2_transport_send(struct smb2_request *req) 462 { 463 NTSTATUS status; 464 465 DEBUG(2, ("SMB2 send seqnum=0x%llx\n", (long long)req->seqnum)); 466 dump_data(5, req->out.body, req->out.body_size); 467 468 if (req->transport->compound.missing > 0) { 469 off_t next_ofs; 470 size_t pad = 0; 471 uint8_t *end; 472 473 end = req->out.buffer + req->out.size; 474 475 /* 476 * we need to set dynamic otherwise 477 * smb2_grow_buffer segfaults 478 */ 479 if (req->out.dynamic == NULL) { 480 req->out.dynamic = end; 481 } 482 483 next_ofs = end - req->out.hdr; 484 if ((next_ofs % 8) > 0) { 485 pad = 8 - (next_ofs % 8); 486 } 487 next_ofs += pad; 488 489 status = smb2_grow_buffer(&req->out, pad); 490 if (!NT_STATUS_IS_OK(status)) { 491 req->state = SMB2_REQUEST_ERROR; 492 req->status = status; 493 return; 494 } 495 req->out.size += pad; 496 497 SIVAL(req->out.hdr, SMB2_HDR_NEXT_COMMAND, next_ofs); 498 } 499 500 /* possibly sign the message */ 501 if (req->session && req->session->signing_active) { 502 status = smb2_sign_message(&req->out, req->session->session_key); 503 if (!NT_STATUS_IS_OK(status)) { 504 req->state = SMB2_REQUEST_ERROR; 505 req->status = status; 506 return; 507 } 508 } 509 510 if (req->transport->compound.missing > 0) { 511 req->transport->compound.buffer = req->out; 512 } else { 513 status = smb2_transport_raw_send(req->transport, 514 &req->out); 515 if (!NT_STATUS_IS_OK(status)) { 516 req->state = SMB2_REQUEST_ERROR; 517 req->status = status; 518 return; 519 } 520 } 521 ZERO_STRUCT(req->out); 522 523 req->state = SMB2_REQUEST_RECV; 524 DLIST_ADD(req->transport->pending_recv, req); 525 526 /* add a timeout */ 527 if (req->transport->options.request_timeout) { 528 event_add_timed(req->transport->socket->event.ctx, req, 529 timeval_current_ofs(req->transport->options.request_timeout, 0), 530 smb2_timeout_handler, req); 531 } 532 533 talloc_set_destructor(req, smb2_request_destructor); 419 TALLOC_FREE(recv_iov); 534 420 } 535 421 … … 537 423 uint32_t num) 538 424 { 425 TALLOC_FREE(transport->compound.reqs); 539 426 ZERO_STRUCT(transport->compound); 540 transport->compound.missing = num; 427 428 transport->compound.reqs = talloc_zero_array(transport, 429 struct tevent_req *, 430 num); 431 if (transport->compound.reqs == NULL) { 432 return NT_STATUS_NO_MEMORY; 433 } 434 541 435 return NT_STATUS_OK; 542 436 } … … 551 445 uint16_t ask_num) 552 446 { 553 transport->credits.ask_num = ask_num; 554 } 555 556 void smb2_transport_credits_set_charge(struct smb2_transport *transport, 557 uint16_t charge) 558 { 559 transport->credits.charge = charge; 447 smb2cli_conn_set_max_credits(transport->conn, ask_num); 560 448 } 561 449 … … 565 453 struct smb2_transport *transport = talloc_get_type(private_data, 566 454 struct smb2_transport); 567 struct timeval next = timeval_add(&t, 0, transport->idle.period); 568 transport->socket->event.te = event_add_timed(transport->socket->event.ctx, 569 transport, 570 next, 571 idle_handler, transport); 455 struct timeval next; 456 572 457 transport->idle.func(transport, transport->idle.private_data); 458 459 next = timeval_current_ofs_usec(transport->idle.period); 460 transport->idle.te = tevent_add_timer(transport->ev, 461 transport, 462 next, 463 idle_handler, 464 transport); 573 465 } 574 466 … … 582 474 void *private_data) 583 475 { 476 TALLOC_FREE(transport->idle.te); 477 584 478 transport->idle.func = idle_func; 585 479 transport->idle.private_data = private_data; 586 480 transport->idle.period = period; 587 481 588 if (transport->socket->event.te != NULL) { 589 talloc_free(transport->socket->event.te); 590 } 591 592 transport->socket->event.te = event_add_timed(transport->socket->event.ctx, 593 transport, 594 timeval_current_ofs(0, period), 595 idle_handler, transport); 596 } 482 transport->idle.te = tevent_add_timer(transport->ev, 483 transport, 484 timeval_current_ofs_usec(period), 485 idle_handler, 486 transport); 487 } -
vendor/current/source4/libcli/smb2/util.c
r740 r988 231 231 return (h1.data[0] == h2.data[0]) && (h1.data[1] == h2.data[1]); 232 232 } 233 234 bool smb2_util_handle_empty(const struct smb2_handle h) 235 { 236 struct smb2_handle empty; 237 238 ZERO_STRUCT(empty); 239 240 return smb2_util_handle_equal(h, empty); 241 } -
vendor/current/source4/libcli/smb2/write.c
r414 r988 59 59 { 60 60 if (!smb2_request_receive(req) || 61 smb2_request_is_error(req)) {61 !smb2_request_is_ok(req)) { 62 62 return smb2_request_destroy(req); 63 63 } -
vendor/current/source4/libcli/smb2/wscript_build
r740 r988 2 2 3 3 bld.SAMBA_SUBSYSTEM('LIBCLI_SMB2', 4 source='transport.c request.c negprot.csession.c tcon.c create.c close.c connect.c getinfo.c write.c read.c setinfo.c find.c ioctl.c logoff.c tdis.c flush.c lock.c notify.c cancel.c keepalive.c break.c util.c signing.c lease_break.c',4 source='transport.c request.c session.c tcon.c create.c close.c connect.c getinfo.c write.c read.c setinfo.c find.c ioctl.c logoff.c tdis.c flush.c lock.c notify.c cancel.c keepalive.c break.c util.c signing.c lease_break.c', 5 5 autoproto='smb2_proto.h', 6 public_deps='LIBCLI_RAW LIBPACKET gensec' 6 deps='tevent-util cli_smb_common', 7 public_deps='smbclient-raw gensec samba-credentials tevent', 8 private_headers='smb2.h', 7 9 ) 8 10
Note:
See TracChangeset
for help on using the changeset viewer.