Line data Source code
1 :
2 : /*
3 : Unix SMB/CIFS implementation.
4 : handle SMBsessionsetup
5 : Copyright (C) Andrew Tridgell 1998-2001
6 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005
7 : Copyright (C) Jim McDonough 2002
8 : Copyright (C) Luke Howard 2003
9 : Copyright (C) Stefan Metzmacher 2005
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "includes.h"
26 : #include <tevent.h>
27 : #include "version.h"
28 : #include "auth/gensec/gensec.h"
29 : #include "auth/auth.h"
30 : #include "smb_server/smb_server.h"
31 : #include "samba/service_stream.h"
32 : #include "param/param.h"
33 : #include "../lib/tsocket/tsocket.h"
34 : #include "lib/stream/packet.h"
35 :
36 : struct sesssetup_context {
37 : struct auth4_context *auth_context;
38 : struct smbsrv_request *req;
39 : };
40 :
41 : /*
42 : * Log the SMB authentication, as by not calling GENSEC we won't log
43 : * it during the gensec_session_info().
44 : */
45 13 : void smbsrv_not_spengo_sesssetup_authz_log(struct smbsrv_request *req,
46 : struct auth_session_info *session_info)
47 : {
48 : struct tsocket_address *local_address;
49 : struct tsocket_address *remote_address;
50 13 : TALLOC_CTX *frame = talloc_stackframe();
51 :
52 13 : remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
53 : frame);
54 13 : local_address = socket_get_local_addr(req->smb_conn->connection->socket,
55 : frame);
56 :
57 13 : log_successful_authz_event(req->smb_conn->connection->msg_ctx,
58 13 : req->smb_conn->lp_ctx,
59 : remote_address,
60 : local_address,
61 : "SMB",
62 : "bare-NTLM",
63 : AUTHZ_TRANSPORT_PROTECTION_SMB,
64 : session_info);
65 :
66 13 : talloc_free(frame);
67 13 : return;
68 : }
69 :
70 :
71 : /*
72 : setup the OS, Lanman and domain portions of a session setup reply
73 : */
74 1177 : static void sesssetup_common_strings(struct smbsrv_request *req,
75 : char **os, char **lanman, char **domain)
76 : {
77 1177 : (*os) = talloc_asprintf(req, "Unix");
78 1177 : (*lanman) = talloc_asprintf(req, "Samba %s", SAMBA_VERSION_STRING);
79 1177 : (*domain) = talloc_asprintf(req, "%s",
80 1177 : lpcfg_workgroup(req->smb_conn->lp_ctx));
81 1177 : }
82 :
83 1177 : static void smbsrv_sesssetup_backend_send(struct smbsrv_request *req,
84 : union smb_sesssetup *sess,
85 : NTSTATUS status)
86 : {
87 1177 : if (NT_STATUS_IS_OK(status)) {
88 986 : req->smb_conn->negotiate.done_sesssetup = true;
89 : /* we need to keep the session long term */
90 986 : req->session = talloc_steal(req->smb_conn, req->session);
91 : }
92 1177 : smbsrv_reply_sesssetup_send(req, sess, status);
93 1177 : }
94 :
95 4 : static void sesssetup_old_send(struct tevent_req *subreq)
96 : {
97 4 : struct sesssetup_context *state = tevent_req_callback_data(subreq, struct sesssetup_context);
98 4 : struct smbsrv_request *req = state->req;
99 :
100 4 : union smb_sesssetup *sess = talloc_get_type(req->io_ptr, union smb_sesssetup);
101 4 : struct auth_user_info_dc *user_info_dc = NULL;
102 : struct auth_session_info *session_info;
103 : struct smbsrv_session *smb_sess;
104 : NTSTATUS status;
105 4 : uint8_t authoritative = 1;
106 : uint32_t flags;
107 :
108 4 : status = auth_check_password_recv(subreq, req, &user_info_dc,
109 : &authoritative);
110 4 : TALLOC_FREE(subreq);
111 4 : if (!NT_STATUS_IS_OK(status)) goto failed;
112 :
113 0 : flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
114 0 : if (user_info_dc->info->authenticated) {
115 0 : flags |= AUTH_SESSION_INFO_AUTHENTICATED;
116 : }
117 : /* This references user_info_dc into session_info */
118 0 : status = req->smb_conn->negotiate.auth_context->generate_session_info(req->smb_conn->negotiate.auth_context,
119 : req,
120 : user_info_dc, sess->old.in.user,
121 : flags, &session_info);
122 0 : if (!NT_STATUS_IS_OK(status)) goto failed;
123 :
124 : /* allocate a new session */
125 0 : smb_sess = smbsrv_session_new(req->smb_conn, req, NULL);
126 0 : if (!smb_sess) {
127 0 : status = NT_STATUS_INSUFFICIENT_RESOURCES;
128 0 : goto failed;
129 : }
130 :
131 0 : smbsrv_not_spengo_sesssetup_authz_log(req, session_info);
132 :
133 : /* Ensure this is marked as a 'real' vuid, not one
134 : * simply valid for the session setup leg */
135 0 : status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
136 0 : if (!NT_STATUS_IS_OK(status)) goto failed;
137 :
138 : /* To correctly process any AndX packet (like a tree connect)
139 : * we need to fill in the session on the request here */
140 0 : req->session = smb_sess;
141 0 : sess->old.out.vuid = smb_sess->vuid;
142 :
143 4 : failed:
144 4 : status = nt_status_squash(status);
145 4 : smbsrv_sesssetup_backend_send(req, sess, status);
146 4 : }
147 :
148 : /*
149 : handler for old style session setup
150 : */
151 4 : static void sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *sess)
152 : {
153 4 : struct auth_usersupplied_info *user_info = NULL;
154 : struct tsocket_address *remote_address, *local_address;
155 4 : const char *remote_machine = NULL;
156 : struct tevent_req *subreq;
157 : struct sesssetup_context *state;
158 :
159 4 : sess->old.out.vuid = 0;
160 4 : sess->old.out.action = 0;
161 :
162 4 : sesssetup_common_strings(req,
163 : &sess->old.out.os,
164 : &sess->old.out.lanman,
165 : &sess->old.out.domain);
166 :
167 4 : if (!req->smb_conn->negotiate.done_sesssetup) {
168 4 : req->smb_conn->negotiate.max_send = sess->old.in.bufsize;
169 : }
170 :
171 4 : if (req->smb_conn->negotiate.calling_name) {
172 0 : remote_machine = req->smb_conn->negotiate.calling_name->name;
173 : }
174 :
175 4 : remote_address = socket_get_remote_addr(req->smb_conn->connection->socket, req);
176 4 : if (!remote_address) goto nomem;
177 :
178 4 : if (!remote_machine) {
179 4 : remote_machine = tsocket_address_inet_addr_string(remote_address, req);
180 4 : if (!remote_machine) goto nomem;
181 : }
182 :
183 4 : local_address = socket_get_local_addr(req->smb_conn->connection->socket, req);
184 4 : if (!local_address) goto nomem;
185 :
186 4 : user_info = talloc_zero(req, struct auth_usersupplied_info);
187 4 : if (!user_info) goto nomem;
188 :
189 4 : user_info->service_description = "SMB";
190 :
191 4 : user_info->logon_parameters = 0;
192 4 : user_info->flags = 0;
193 4 : user_info->client.account_name = sess->old.in.user;
194 4 : user_info->client.domain_name = sess->old.in.domain;
195 4 : user_info->workstation_name = remote_machine;
196 :
197 4 : user_info->remote_host = talloc_steal(user_info, remote_address);
198 4 : user_info->local_host = talloc_steal(user_info, local_address);
199 :
200 4 : user_info->password_state = AUTH_PASSWORD_RESPONSE;
201 4 : user_info->password.response.lanman = sess->old.in.password;
202 4 : user_info->password.response.lanman.data = talloc_steal(user_info, sess->old.in.password.data);
203 4 : user_info->password.response.nt = data_blob(NULL, 0);
204 :
205 4 : state = talloc(req, struct sesssetup_context);
206 4 : if (!state) goto nomem;
207 :
208 4 : if (req->smb_conn->negotiate.auth_context) {
209 4 : state->auth_context = req->smb_conn->negotiate.auth_context;
210 : } else {
211 : /* TODO: should we use just "anonymous" here? */
212 0 : NTSTATUS status = auth_context_create(state,
213 0 : req->smb_conn->connection->event.ctx,
214 0 : req->smb_conn->connection->msg_ctx,
215 0 : req->smb_conn->lp_ctx,
216 : &state->auth_context);
217 0 : if (!NT_STATUS_IS_OK(status)) {
218 0 : smbsrv_sesssetup_backend_send(req, sess, status);
219 0 : return;
220 : }
221 : }
222 :
223 4 : state->req = req;
224 :
225 6 : subreq = auth_check_password_send(state,
226 4 : req->smb_conn->connection->event.ctx,
227 4 : req->smb_conn->negotiate.auth_context,
228 : user_info);
229 4 : if (!subreq) goto nomem;
230 4 : tevent_req_set_callback(subreq, sesssetup_old_send, state);
231 4 : return;
232 :
233 0 : nomem:
234 0 : smbsrv_sesssetup_backend_send(req, sess, NT_STATUS_NO_MEMORY);
235 : }
236 :
237 15 : static void sesssetup_nt1_send(struct tevent_req *subreq)
238 : {
239 15 : struct sesssetup_context *state = tevent_req_callback_data(subreq, struct sesssetup_context);
240 15 : struct smbsrv_request *req = state->req;
241 15 : union smb_sesssetup *sess = talloc_get_type(req->io_ptr, union smb_sesssetup);
242 15 : struct auth_user_info_dc *user_info_dc = NULL;
243 : struct auth_session_info *session_info;
244 : struct smbsrv_session *smb_sess;
245 15 : uint8_t authoritative = 1;
246 : uint32_t flags;
247 : NTSTATUS status;
248 :
249 15 : status = auth_check_password_recv(subreq, req, &user_info_dc,
250 : &authoritative);
251 15 : TALLOC_FREE(subreq);
252 15 : if (!NT_STATUS_IS_OK(status)) goto failed;
253 :
254 13 : flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
255 13 : if (user_info_dc->info->authenticated) {
256 8 : flags |= AUTH_SESSION_INFO_AUTHENTICATED;
257 : }
258 : /* This references user_info_dc into session_info */
259 13 : status = state->auth_context->generate_session_info(state->auth_context,
260 : req,
261 : user_info_dc,
262 : sess->nt1.in.user,
263 : flags,
264 : &session_info);
265 13 : if (!NT_STATUS_IS_OK(status)) goto failed;
266 :
267 : /* allocate a new session */
268 13 : smb_sess = smbsrv_session_new(req->smb_conn, req, NULL);
269 13 : if (!smb_sess) {
270 0 : status = NT_STATUS_INSUFFICIENT_RESOURCES;
271 0 : goto failed;
272 : }
273 :
274 13 : smbsrv_not_spengo_sesssetup_authz_log(req, session_info);
275 :
276 : /* Ensure this is marked as a 'real' vuid, not one
277 : * simply valid for the session setup leg */
278 13 : status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
279 13 : if (!NT_STATUS_IS_OK(status)) goto failed;
280 :
281 : /* To correctly process any AndX packet (like a tree connect)
282 : * we need to fill in the session on the request here */
283 13 : req->session = smb_sess;
284 13 : sess->nt1.out.vuid = smb_sess->vuid;
285 :
286 13 : if (!smbsrv_setup_signing(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2)) {
287 : /* Already signing, or disabled */
288 1 : goto done;
289 : }
290 :
291 22 : done:
292 13 : status = NT_STATUS_OK;
293 15 : failed:
294 15 : status = nt_status_squash(status);
295 15 : smbsrv_sesssetup_backend_send(req, sess, status);
296 15 : }
297 :
298 : /*
299 : handler for NT1 style session setup
300 : */
301 15 : static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
302 : {
303 : NTSTATUS status;
304 15 : struct auth_usersupplied_info *user_info = NULL;
305 : struct tsocket_address *remote_address, *local_address;
306 15 : const char *remote_machine = NULL;
307 : struct tevent_req *subreq;
308 : struct sesssetup_context *state;
309 15 : bool allow_raw = lpcfg_raw_ntlmv2_auth(req->smb_conn->lp_ctx);
310 :
311 15 : sess->nt1.out.vuid = 0;
312 15 : sess->nt1.out.action = 0;
313 :
314 15 : sesssetup_common_strings(req,
315 : &sess->nt1.out.os,
316 : &sess->nt1.out.lanman,
317 : &sess->nt1.out.domain);
318 :
319 15 : if (!req->smb_conn->negotiate.done_sesssetup) {
320 14 : req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize;
321 14 : req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities;
322 : }
323 :
324 15 : state = talloc(req, struct sesssetup_context);
325 15 : if (!state) goto nomem;
326 :
327 15 : state->req = req;
328 :
329 15 : if (req->smb_conn->negotiate.oid) {
330 2 : if (sess->nt1.in.user && *sess->nt1.in.user) {
331 : /* We can't accept a normal login, because we
332 : * don't have a challenge */
333 0 : status = NT_STATUS_LOGON_FAILURE;
334 0 : goto failed;
335 : }
336 :
337 : /* TODO: should we use just "anonymous" here? */
338 8 : status = auth_context_create(state,
339 2 : req->smb_conn->connection->event.ctx,
340 2 : req->smb_conn->connection->msg_ctx,
341 2 : req->smb_conn->lp_ctx,
342 : &state->auth_context);
343 2 : if (!NT_STATUS_IS_OK(status)) goto failed;
344 13 : } else if (req->smb_conn->negotiate.auth_context) {
345 13 : state->auth_context = req->smb_conn->negotiate.auth_context;
346 : } else {
347 : /* TODO: should we use just "anonymous" here? */
348 0 : status = auth_context_create(state,
349 0 : req->smb_conn->connection->event.ctx,
350 0 : req->smb_conn->connection->msg_ctx,
351 0 : req->smb_conn->lp_ctx,
352 : &state->auth_context);
353 0 : if (!NT_STATUS_IS_OK(status)) goto failed;
354 : }
355 :
356 15 : if (req->smb_conn->negotiate.calling_name) {
357 0 : remote_machine = req->smb_conn->negotiate.calling_name->name;
358 : }
359 :
360 15 : remote_address = socket_get_remote_addr(req->smb_conn->connection->socket, req);
361 15 : if (!remote_address) goto nomem;
362 :
363 15 : if (!remote_machine) {
364 15 : remote_machine = tsocket_address_inet_addr_string(remote_address, req);
365 15 : if (!remote_machine) goto nomem;
366 : }
367 :
368 15 : local_address = socket_get_local_addr(req->smb_conn->connection->socket, req);
369 15 : if (!local_address) goto nomem;
370 :
371 15 : user_info = talloc_zero(req, struct auth_usersupplied_info);
372 15 : if (!user_info) goto nomem;
373 :
374 15 : user_info->service_description = "SMB";
375 15 : user_info->auth_description = "bare-NTLM";
376 :
377 15 : user_info->logon_parameters = 0;
378 15 : user_info->flags = 0;
379 15 : user_info->client.account_name = sess->nt1.in.user;
380 15 : user_info->client.domain_name = sess->nt1.in.domain;
381 15 : user_info->workstation_name = remote_machine;
382 15 : user_info->remote_host = talloc_steal(user_info, remote_address);
383 15 : user_info->local_host = talloc_steal(user_info, local_address);
384 :
385 15 : user_info->password_state = AUTH_PASSWORD_RESPONSE;
386 15 : user_info->password.response.lanman = sess->nt1.in.password1;
387 15 : user_info->password.response.lanman.data = talloc_steal(user_info, sess->nt1.in.password1.data);
388 15 : user_info->password.response.nt = sess->nt1.in.password2;
389 15 : user_info->password.response.nt.data = talloc_steal(user_info, sess->nt1.in.password2.data);
390 :
391 15 : if (!allow_raw && user_info->password.response.nt.length >= 48) {
392 : /*
393 : * NTLMv2_RESPONSE has at least 48 bytes
394 : * and should only be supported via NTLMSSP.
395 : */
396 0 : status = NT_STATUS_INVALID_PARAMETER;
397 0 : goto failed;
398 : }
399 :
400 27 : subreq = auth_check_password_send(state,
401 15 : req->smb_conn->connection->event.ctx,
402 : state->auth_context,
403 : user_info);
404 15 : if (!subreq) goto nomem;
405 15 : tevent_req_set_callback(subreq, sesssetup_nt1_send, state);
406 :
407 15 : return;
408 :
409 0 : nomem:
410 0 : status = NT_STATUS_NO_MEMORY;
411 0 : failed:
412 0 : status = nt_status_squash(status);
413 0 : smbsrv_sesssetup_backend_send(req, sess, status);
414 : }
415 :
416 : struct sesssetup_spnego_state {
417 : struct smbsrv_request *req;
418 : union smb_sesssetup *sess;
419 : struct smbsrv_session *smb_sess;
420 : };
421 :
422 1155 : static void sesssetup_spnego_send(struct tevent_req *subreq)
423 : {
424 1155 : struct sesssetup_spnego_state *s = tevent_req_callback_data(subreq,
425 : struct sesssetup_spnego_state);
426 1155 : struct smbsrv_request *req = s->req;
427 1155 : union smb_sesssetup *sess = s->sess;
428 1155 : struct smbsrv_session *smb_sess = s->smb_sess;
429 1155 : struct auth_session_info *session_info = NULL;
430 : NTSTATUS status;
431 : NTSTATUS skey_status;
432 : DATA_BLOB session_key;
433 :
434 1155 : status = gensec_update_recv(subreq, req, &sess->spnego.out.secblob);
435 1155 : packet_recv_enable(req->smb_conn->packet);
436 1155 : TALLOC_FREE(subreq);
437 1155 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
438 178 : goto done;
439 977 : } else if (!NT_STATUS_IS_OK(status)) {
440 4 : goto failed;
441 : }
442 :
443 973 : status = gensec_session_info(smb_sess->gensec_ctx, smb_sess, &session_info);
444 973 : if (!NT_STATUS_IS_OK(status)) goto failed;
445 :
446 : /* The session_key is only needed until the end of the smbsrv_setup_signing() call */
447 973 : skey_status = gensec_session_key(smb_sess->gensec_ctx, req, &session_key);
448 973 : if (NT_STATUS_IS_OK(skey_status)) {
449 973 : smbsrv_setup_signing(req->smb_conn, &session_key, NULL);
450 : }
451 :
452 : /* Ensure this is marked as a 'real' vuid, not one
453 : * simply valid for the session setup leg */
454 973 : status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
455 973 : if (!NT_STATUS_IS_OK(status)) goto failed;
456 :
457 973 : req->session = smb_sess;
458 :
459 1151 : done:
460 1151 : sess->spnego.out.vuid = smb_sess->vuid;
461 1155 : failed:
462 1155 : status = nt_status_squash(status);
463 1155 : smbsrv_sesssetup_backend_send(req, sess, status);
464 1293 : if (!NT_STATUS_IS_OK(status) &&
465 182 : !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
466 4 : talloc_free(smb_sess);
467 : }
468 1155 : }
469 :
470 : /*
471 : handler for SPNEGO style session setup
472 : */
473 1158 : static void sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *sess)
474 : {
475 : NTSTATUS status;
476 1158 : struct smbsrv_session *smb_sess = NULL;
477 1158 : bool is_smb_sess_new = false;
478 1158 : struct sesssetup_spnego_state *s = NULL;
479 : uint16_t vuid;
480 : struct tevent_req *subreq;
481 :
482 1158 : sess->spnego.out.vuid = 0;
483 1158 : sess->spnego.out.action = 0;
484 :
485 1158 : sesssetup_common_strings(req,
486 : &sess->spnego.out.os,
487 : &sess->spnego.out.lanman,
488 : &sess->spnego.out.workgroup);
489 :
490 1158 : if (!req->smb_conn->negotiate.done_sesssetup) {
491 1116 : req->smb_conn->negotiate.max_send = sess->spnego.in.bufsize;
492 1116 : req->smb_conn->negotiate.client_caps = sess->spnego.in.capabilities;
493 : }
494 :
495 1158 : vuid = SVAL(req->in.hdr,HDR_UID);
496 :
497 : /* lookup an existing session */
498 1158 : if (vuid == 0) {
499 : struct gensec_security *gensec_ctx;
500 : struct tsocket_address *remote_address, *local_address;
501 3776 : status = samba_server_gensec_start(req,
502 977 : req->smb_conn->connection->event.ctx,
503 977 : req->smb_conn->connection->msg_ctx,
504 977 : req->smb_conn->lp_ctx,
505 977 : req->smb_conn->negotiate.server_credentials,
506 : "cifs",
507 : &gensec_ctx);
508 977 : if (!NT_STATUS_IS_OK(status)) {
509 0 : DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
510 0 : goto failed;
511 : }
512 :
513 977 : gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
514 977 : gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SMB_TRANSPORT);
515 :
516 977 : remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
517 : req);
518 977 : if (!remote_address) {
519 0 : status = NT_STATUS_INTERNAL_ERROR;
520 0 : DBG_ERR("Failed to obtain remote address");
521 0 : goto failed;
522 : }
523 :
524 977 : status = gensec_set_remote_address(gensec_ctx,
525 : remote_address);
526 977 : if (!NT_STATUS_IS_OK(status)) {
527 0 : DBG_ERR("Failed to set remote address");
528 0 : goto failed;
529 : }
530 :
531 977 : local_address = socket_get_local_addr(req->smb_conn->connection->socket,
532 : req);
533 977 : if (!local_address) {
534 0 : status = NT_STATUS_INTERNAL_ERROR;
535 0 : DBG_ERR("Failed to obtain local address");
536 0 : goto failed;
537 : }
538 :
539 977 : status = gensec_set_local_address(gensec_ctx,
540 : local_address);
541 977 : if (!NT_STATUS_IS_OK(status)) {
542 0 : DBG_ERR("Failed to set local address");
543 0 : goto failed;
544 : }
545 :
546 977 : status = gensec_set_target_service_description(gensec_ctx,
547 : "SMB");
548 :
549 977 : if (!NT_STATUS_IS_OK(status)) {
550 0 : DBG_ERR("Failed to set service description");
551 0 : goto failed;
552 : }
553 :
554 977 : status = gensec_start_mech_by_oid(gensec_ctx, req->smb_conn->negotiate.oid);
555 977 : if (!NT_STATUS_IS_OK(status)) {
556 0 : DEBUG(1, ("Failed to start GENSEC %s server code: %s\n",
557 : gensec_get_name_by_oid(gensec_ctx, req->smb_conn->negotiate.oid), nt_errstr(status)));
558 0 : goto failed;
559 : }
560 :
561 : /* allocate a new session */
562 977 : smb_sess = smbsrv_session_new(req->smb_conn, req->smb_conn, gensec_ctx);
563 977 : if (!smb_sess) {
564 0 : status = NT_STATUS_INSUFFICIENT_RESOURCES;
565 0 : goto failed;
566 : }
567 977 : is_smb_sess_new = true;
568 : } else {
569 181 : smb_sess = smbsrv_session_find_sesssetup(req->smb_conn, vuid);
570 : }
571 :
572 1158 : if (!smb_sess) {
573 1 : status = NT_STATUS_DOS(ERRSRV, ERRbaduid);
574 1 : goto failed;
575 : }
576 :
577 1157 : if (smb_sess->session_info) {
578 2 : status = NT_STATUS_INVALID_PARAMETER;
579 2 : goto failed;
580 : }
581 :
582 1155 : if (!smb_sess->gensec_ctx) {
583 0 : status = NT_STATUS_INTERNAL_ERROR;
584 0 : DEBUG(1, ("Internal ERROR: no gensec_ctx on session: %s\n", nt_errstr(status)));
585 0 : goto failed;
586 : }
587 :
588 1155 : s = talloc(req, struct sesssetup_spnego_state);
589 1155 : if (!s) goto nomem;
590 1155 : s->req = req;
591 1155 : s->sess = sess;
592 1155 : s->smb_sess = smb_sess;
593 :
594 2223 : subreq = gensec_update_send(s,
595 1155 : req->smb_conn->connection->event.ctx,
596 : smb_sess->gensec_ctx,
597 : sess->spnego.in.secblob);
598 1155 : if (!subreq) {
599 0 : goto nomem;
600 : }
601 : /* disable receipt of more packets on this socket until we've
602 : finished with the session setup. This avoids a problem with
603 : crashes if we get EOF on the socket while processing a session
604 : setup */
605 1155 : packet_recv_disable(req->smb_conn->packet);
606 1155 : tevent_req_set_callback(subreq, sesssetup_spnego_send, s);
607 :
608 1155 : return;
609 :
610 0 : nomem:
611 0 : status = NT_STATUS_NO_MEMORY;
612 3 : failed:
613 3 : if (is_smb_sess_new) {
614 0 : talloc_free(smb_sess);
615 : }
616 3 : status = nt_status_squash(status);
617 3 : smbsrv_sesssetup_backend_send(req, sess, status);
618 : }
619 :
620 : /*
621 : backend for sessionsetup call - this takes all 3 variants of the call
622 : */
623 1177 : void smbsrv_sesssetup_backend(struct smbsrv_request *req,
624 : union smb_sesssetup *sess)
625 : {
626 1177 : switch (sess->old.level) {
627 4 : case RAW_SESSSETUP_OLD:
628 4 : sesssetup_old(req, sess);
629 94 : return;
630 :
631 15 : case RAW_SESSSETUP_NT1:
632 15 : sesssetup_nt1(req, sess);
633 15 : return;
634 :
635 1158 : case RAW_SESSSETUP_SPNEGO:
636 1158 : sesssetup_spnego(req, sess);
637 1158 : return;
638 :
639 0 : case RAW_SESSSETUP_SMB2:
640 0 : break;
641 : }
642 :
643 0 : smbsrv_sesssetup_backend_send(req, sess, NT_STATUS_INVALID_LEVEL);
644 : }
|