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 19 : 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 19 : TALLOC_CTX *frame = talloc_stackframe();
51 :
52 19 : remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
53 : frame);
54 19 : local_address = socket_get_local_addr(req->smb_conn->connection->socket,
55 : frame);
56 :
57 19 : log_successful_authz_event(req->smb_conn->connection->msg_ctx,
58 19 : 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 19 : talloc_free(frame);
67 19 : return;
68 : }
69 :
70 :
71 : /*
72 : setup the OS, Lanman and domain portions of a session setup reply
73 : */
74 1196 : static void sesssetup_common_strings(struct smbsrv_request *req,
75 : char **os, char **lanman, char **domain)
76 : {
77 1196 : (*os) = talloc_asprintf(req, "Unix");
78 1196 : (*lanman) = talloc_asprintf(req, "Samba %s", SAMBA_VERSION_STRING);
79 1196 : (*domain) = talloc_asprintf(req, "%s",
80 1196 : lpcfg_workgroup(req->smb_conn->lp_ctx));
81 1196 : }
82 :
83 1196 : static void smbsrv_sesssetup_backend_send(struct smbsrv_request *req,
84 : union smb_sesssetup *sess,
85 : NTSTATUS status)
86 : {
87 1196 : if (NT_STATUS_IS_OK(status)) {
88 1002 : req->smb_conn->negotiate.done_sesssetup = true;
89 : /* we need to keep the session long term */
90 1002 : req->session = talloc_steal(req->smb_conn, req->session);
91 : }
92 1196 : smbsrv_reply_sesssetup_send(req, sess, status);
93 1196 : }
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 = 0;
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 4 : flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
114 4 : if (user_info_dc->info->authenticated) {
115 4 : flags |= AUTH_SESSION_INFO_AUTHENTICATED;
116 : }
117 : /* This references user_info_dc into session_info */
118 4 : 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 4 : if (!NT_STATUS_IS_OK(status)) goto failed;
123 :
124 : /* allocate a new session */
125 4 : smb_sess = smbsrv_session_new(req->smb_conn, req, NULL);
126 4 : if (!smb_sess) {
127 0 : status = NT_STATUS_INSUFFICIENT_RESOURCES;
128 0 : goto failed;
129 : }
130 :
131 4 : 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 4 : status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
136 4 : 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 4 : req->session = smb_sess;
141 4 : 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->mapped_state = false;
192 4 : user_info->logon_parameters = 0;
193 4 : user_info->flags = 0;
194 4 : user_info->client.account_name = sess->old.in.user;
195 4 : user_info->client.domain_name = sess->old.in.domain;
196 4 : user_info->workstation_name = remote_machine;
197 :
198 4 : user_info->remote_host = talloc_steal(user_info, remote_address);
199 4 : user_info->local_host = talloc_steal(user_info, local_address);
200 :
201 4 : user_info->password_state = AUTH_PASSWORD_RESPONSE;
202 4 : user_info->password.response.lanman = sess->old.in.password;
203 4 : user_info->password.response.lanman.data = talloc_steal(user_info, sess->old.in.password.data);
204 4 : user_info->password.response.nt = data_blob(NULL, 0);
205 :
206 4 : state = talloc(req, struct sesssetup_context);
207 4 : if (!state) goto nomem;
208 :
209 4 : if (req->smb_conn->negotiate.auth_context) {
210 4 : state->auth_context = req->smb_conn->negotiate.auth_context;
211 : } else {
212 : /* TODO: should we use just "anonymous" here? */
213 0 : NTSTATUS status = auth_context_create(state,
214 0 : req->smb_conn->connection->event.ctx,
215 0 : req->smb_conn->connection->msg_ctx,
216 0 : req->smb_conn->lp_ctx,
217 : &state->auth_context);
218 0 : if (!NT_STATUS_IS_OK(status)) {
219 0 : smbsrv_sesssetup_backend_send(req, sess, status);
220 0 : return;
221 : }
222 : }
223 :
224 4 : state->req = req;
225 :
226 6 : subreq = auth_check_password_send(state,
227 4 : req->smb_conn->connection->event.ctx,
228 4 : req->smb_conn->negotiate.auth_context,
229 : user_info);
230 4 : if (!subreq) goto nomem;
231 4 : tevent_req_set_callback(subreq, sesssetup_old_send, state);
232 4 : return;
233 :
234 0 : nomem:
235 0 : smbsrv_sesssetup_backend_send(req, sess, NT_STATUS_NO_MEMORY);
236 : }
237 :
238 17 : static void sesssetup_nt1_send(struct tevent_req *subreq)
239 : {
240 17 : struct sesssetup_context *state = tevent_req_callback_data(subreq, struct sesssetup_context);
241 17 : struct smbsrv_request *req = state->req;
242 17 : union smb_sesssetup *sess = talloc_get_type(req->io_ptr, union smb_sesssetup);
243 17 : struct auth_user_info_dc *user_info_dc = NULL;
244 : struct auth_session_info *session_info;
245 : struct smbsrv_session *smb_sess;
246 17 : uint8_t authoritative = 0;
247 : uint32_t flags;
248 : NTSTATUS status;
249 :
250 17 : status = auth_check_password_recv(subreq, req, &user_info_dc,
251 : &authoritative);
252 17 : TALLOC_FREE(subreq);
253 17 : if (!NT_STATUS_IS_OK(status)) goto failed;
254 :
255 15 : flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
256 15 : if (user_info_dc->info->authenticated) {
257 10 : flags |= AUTH_SESSION_INFO_AUTHENTICATED;
258 : }
259 : /* This references user_info_dc into session_info */
260 15 : status = state->auth_context->generate_session_info(state->auth_context,
261 : req,
262 : user_info_dc,
263 : sess->nt1.in.user,
264 : flags,
265 : &session_info);
266 15 : if (!NT_STATUS_IS_OK(status)) goto failed;
267 :
268 : /* allocate a new session */
269 15 : smb_sess = smbsrv_session_new(req->smb_conn, req, NULL);
270 15 : if (!smb_sess) {
271 0 : status = NT_STATUS_INSUFFICIENT_RESOURCES;
272 0 : goto failed;
273 : }
274 :
275 15 : smbsrv_not_spengo_sesssetup_authz_log(req, session_info);
276 :
277 : /* Ensure this is marked as a 'real' vuid, not one
278 : * simply valid for the session setup leg */
279 15 : status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
280 15 : if (!NT_STATUS_IS_OK(status)) goto failed;
281 :
282 : /* To correctly process any AndX packet (like a tree connect)
283 : * we need to fill in the session on the request here */
284 15 : req->session = smb_sess;
285 15 : sess->nt1.out.vuid = smb_sess->vuid;
286 :
287 15 : if (!smbsrv_setup_signing(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2)) {
288 : /* Already signing, or disabled */
289 1 : goto done;
290 : }
291 :
292 25 : done:
293 15 : status = NT_STATUS_OK;
294 17 : failed:
295 17 : status = nt_status_squash(status);
296 17 : smbsrv_sesssetup_backend_send(req, sess, status);
297 17 : }
298 :
299 : /*
300 : handler for NT1 style session setup
301 : */
302 17 : static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
303 : {
304 : NTSTATUS status;
305 17 : struct auth_usersupplied_info *user_info = NULL;
306 : struct tsocket_address *remote_address, *local_address;
307 17 : const char *remote_machine = NULL;
308 : struct tevent_req *subreq;
309 : struct sesssetup_context *state;
310 17 : bool allow_raw = lpcfg_raw_ntlmv2_auth(req->smb_conn->lp_ctx);
311 :
312 17 : sess->nt1.out.vuid = 0;
313 17 : sess->nt1.out.action = 0;
314 :
315 17 : sesssetup_common_strings(req,
316 : &sess->nt1.out.os,
317 : &sess->nt1.out.lanman,
318 : &sess->nt1.out.domain);
319 :
320 17 : if (!req->smb_conn->negotiate.done_sesssetup) {
321 16 : req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize;
322 16 : req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities;
323 : }
324 :
325 17 : state = talloc(req, struct sesssetup_context);
326 17 : if (!state) goto nomem;
327 :
328 17 : state->req = req;
329 :
330 17 : if (req->smb_conn->negotiate.oid) {
331 2 : if (sess->nt1.in.user && *sess->nt1.in.user) {
332 : /* We can't accept a normal login, because we
333 : * don't have a challenge */
334 0 : status = NT_STATUS_LOGON_FAILURE;
335 0 : goto failed;
336 : }
337 :
338 : /* TODO: should we use just "anonymous" here? */
339 8 : status = auth_context_create(state,
340 2 : req->smb_conn->connection->event.ctx,
341 2 : req->smb_conn->connection->msg_ctx,
342 2 : req->smb_conn->lp_ctx,
343 : &state->auth_context);
344 2 : if (!NT_STATUS_IS_OK(status)) goto failed;
345 15 : } else if (req->smb_conn->negotiate.auth_context) {
346 15 : state->auth_context = req->smb_conn->negotiate.auth_context;
347 : } else {
348 : /* TODO: should we use just "anonymous" here? */
349 0 : status = auth_context_create(state,
350 0 : req->smb_conn->connection->event.ctx,
351 0 : req->smb_conn->connection->msg_ctx,
352 0 : req->smb_conn->lp_ctx,
353 : &state->auth_context);
354 0 : if (!NT_STATUS_IS_OK(status)) goto failed;
355 : }
356 :
357 17 : if (req->smb_conn->negotiate.calling_name) {
358 0 : remote_machine = req->smb_conn->negotiate.calling_name->name;
359 : }
360 :
361 17 : remote_address = socket_get_remote_addr(req->smb_conn->connection->socket, req);
362 17 : if (!remote_address) goto nomem;
363 :
364 17 : if (!remote_machine) {
365 17 : remote_machine = tsocket_address_inet_addr_string(remote_address, req);
366 17 : if (!remote_machine) goto nomem;
367 : }
368 :
369 17 : local_address = socket_get_local_addr(req->smb_conn->connection->socket, req);
370 17 : if (!local_address) goto nomem;
371 :
372 17 : user_info = talloc_zero(req, struct auth_usersupplied_info);
373 17 : if (!user_info) goto nomem;
374 :
375 17 : user_info->service_description = "SMB";
376 17 : user_info->auth_description = "bare-NTLM";
377 :
378 17 : user_info->mapped_state = false;
379 17 : user_info->logon_parameters = 0;
380 17 : user_info->flags = 0;
381 17 : user_info->client.account_name = sess->nt1.in.user;
382 17 : user_info->client.domain_name = sess->nt1.in.domain;
383 17 : user_info->workstation_name = remote_machine;
384 17 : user_info->remote_host = talloc_steal(user_info, remote_address);
385 17 : user_info->local_host = talloc_steal(user_info, local_address);
386 :
387 17 : user_info->password_state = AUTH_PASSWORD_RESPONSE;
388 17 : user_info->password.response.lanman = sess->nt1.in.password1;
389 17 : user_info->password.response.lanman.data = talloc_steal(user_info, sess->nt1.in.password1.data);
390 17 : user_info->password.response.nt = sess->nt1.in.password2;
391 17 : user_info->password.response.nt.data = talloc_steal(user_info, sess->nt1.in.password2.data);
392 :
393 17 : if (!allow_raw && user_info->password.response.nt.length >= 48) {
394 : /*
395 : * NTLMv2_RESPONSE has at least 48 bytes
396 : * and should only be supported via NTLMSSP.
397 : */
398 0 : status = NT_STATUS_INVALID_PARAMETER;
399 0 : goto failed;
400 : }
401 :
402 30 : subreq = auth_check_password_send(state,
403 17 : req->smb_conn->connection->event.ctx,
404 : state->auth_context,
405 : user_info);
406 17 : if (!subreq) goto nomem;
407 17 : tevent_req_set_callback(subreq, sesssetup_nt1_send, state);
408 :
409 17 : return;
410 :
411 0 : nomem:
412 0 : status = NT_STATUS_NO_MEMORY;
413 0 : failed:
414 0 : status = nt_status_squash(status);
415 0 : smbsrv_sesssetup_backend_send(req, sess, status);
416 : }
417 :
418 : struct sesssetup_spnego_state {
419 : struct smbsrv_request *req;
420 : union smb_sesssetup *sess;
421 : struct smbsrv_session *smb_sess;
422 : };
423 :
424 1172 : static void sesssetup_spnego_send(struct tevent_req *subreq)
425 : {
426 1172 : struct sesssetup_spnego_state *s = tevent_req_callback_data(subreq,
427 : struct sesssetup_spnego_state);
428 1172 : struct smbsrv_request *req = s->req;
429 1172 : union smb_sesssetup *sess = s->sess;
430 1172 : struct smbsrv_session *smb_sess = s->smb_sess;
431 1172 : struct auth_session_info *session_info = NULL;
432 : NTSTATUS status;
433 : NTSTATUS skey_status;
434 : DATA_BLOB session_key;
435 :
436 1172 : status = gensec_update_recv(subreq, req, &sess->spnego.out.secblob);
437 1172 : packet_recv_enable(req->smb_conn->packet);
438 1172 : TALLOC_FREE(subreq);
439 1172 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
440 185 : goto done;
441 987 : } else if (!NT_STATUS_IS_OK(status)) {
442 4 : goto failed;
443 : }
444 :
445 983 : status = gensec_session_info(smb_sess->gensec_ctx, smb_sess, &session_info);
446 983 : if (!NT_STATUS_IS_OK(status)) goto failed;
447 :
448 : /* The session_key is only needed until the end of the smbsrv_setup_signing() call */
449 983 : skey_status = gensec_session_key(smb_sess->gensec_ctx, req, &session_key);
450 983 : if (NT_STATUS_IS_OK(skey_status)) {
451 983 : smbsrv_setup_signing(req->smb_conn, &session_key, NULL);
452 : }
453 :
454 : /* Ensure this is marked as a 'real' vuid, not one
455 : * simply valid for the session setup leg */
456 983 : status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
457 983 : if (!NT_STATUS_IS_OK(status)) goto failed;
458 :
459 983 : req->session = smb_sess;
460 :
461 1168 : done:
462 1168 : sess->spnego.out.vuid = smb_sess->vuid;
463 1172 : failed:
464 1172 : status = nt_status_squash(status);
465 1172 : smbsrv_sesssetup_backend_send(req, sess, status);
466 1314 : if (!NT_STATUS_IS_OK(status) &&
467 189 : !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
468 4 : talloc_free(smb_sess);
469 : }
470 1172 : }
471 :
472 : /*
473 : handler for SPNEGO style session setup
474 : */
475 1175 : static void sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *sess)
476 : {
477 : NTSTATUS status;
478 1175 : struct smbsrv_session *smb_sess = NULL;
479 1175 : bool is_smb_sess_new = false;
480 1175 : struct sesssetup_spnego_state *s = NULL;
481 : uint16_t vuid;
482 : struct tevent_req *subreq;
483 :
484 1175 : sess->spnego.out.vuid = 0;
485 1175 : sess->spnego.out.action = 0;
486 :
487 1175 : sesssetup_common_strings(req,
488 : &sess->spnego.out.os,
489 : &sess->spnego.out.lanman,
490 : &sess->spnego.out.workgroup);
491 :
492 1175 : if (!req->smb_conn->negotiate.done_sesssetup) {
493 1133 : req->smb_conn->negotiate.max_send = sess->spnego.in.bufsize;
494 1133 : req->smb_conn->negotiate.client_caps = sess->spnego.in.capabilities;
495 : }
496 :
497 1175 : vuid = SVAL(req->in.hdr,HDR_UID);
498 :
499 : /* lookup an existing session */
500 1175 : if (vuid == 0) {
501 : struct gensec_security *gensec_ctx;
502 : struct tsocket_address *remote_address, *local_address;
503 3801 : status = samba_server_gensec_start(req,
504 987 : req->smb_conn->connection->event.ctx,
505 987 : req->smb_conn->connection->msg_ctx,
506 987 : req->smb_conn->lp_ctx,
507 987 : req->smb_conn->negotiate.server_credentials,
508 : "cifs",
509 : &gensec_ctx);
510 987 : if (!NT_STATUS_IS_OK(status)) {
511 0 : DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
512 0 : goto failed;
513 : }
514 :
515 987 : gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
516 987 : gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SMB_TRANSPORT);
517 :
518 987 : remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
519 : req);
520 987 : if (!remote_address) {
521 0 : status = NT_STATUS_INTERNAL_ERROR;
522 0 : DBG_ERR("Failed to obtain remote address");
523 0 : goto failed;
524 : }
525 :
526 987 : status = gensec_set_remote_address(gensec_ctx,
527 : remote_address);
528 987 : if (!NT_STATUS_IS_OK(status)) {
529 0 : DBG_ERR("Failed to set remote address");
530 0 : goto failed;
531 : }
532 :
533 987 : local_address = socket_get_local_addr(req->smb_conn->connection->socket,
534 : req);
535 987 : if (!local_address) {
536 0 : status = NT_STATUS_INTERNAL_ERROR;
537 0 : DBG_ERR("Failed to obtain local address");
538 0 : goto failed;
539 : }
540 :
541 987 : status = gensec_set_local_address(gensec_ctx,
542 : local_address);
543 987 : if (!NT_STATUS_IS_OK(status)) {
544 0 : DBG_ERR("Failed to set local address");
545 0 : goto failed;
546 : }
547 :
548 987 : status = gensec_set_target_service_description(gensec_ctx,
549 : "SMB");
550 :
551 987 : if (!NT_STATUS_IS_OK(status)) {
552 0 : DBG_ERR("Failed to set service description");
553 0 : goto failed;
554 : }
555 :
556 987 : status = gensec_start_mech_by_oid(gensec_ctx, req->smb_conn->negotiate.oid);
557 987 : if (!NT_STATUS_IS_OK(status)) {
558 0 : DEBUG(1, ("Failed to start GENSEC %s server code: %s\n",
559 : gensec_get_name_by_oid(gensec_ctx, req->smb_conn->negotiate.oid), nt_errstr(status)));
560 0 : goto failed;
561 : }
562 :
563 : /* allocate a new session */
564 987 : smb_sess = smbsrv_session_new(req->smb_conn, req->smb_conn, gensec_ctx);
565 987 : if (!smb_sess) {
566 0 : status = NT_STATUS_INSUFFICIENT_RESOURCES;
567 0 : goto failed;
568 : }
569 987 : is_smb_sess_new = true;
570 : } else {
571 188 : smb_sess = smbsrv_session_find_sesssetup(req->smb_conn, vuid);
572 : }
573 :
574 1175 : if (!smb_sess) {
575 1 : status = NT_STATUS_DOS(ERRSRV, ERRbaduid);
576 1 : goto failed;
577 : }
578 :
579 1174 : if (smb_sess->session_info) {
580 2 : status = NT_STATUS_INVALID_PARAMETER;
581 2 : goto failed;
582 : }
583 :
584 1172 : if (!smb_sess->gensec_ctx) {
585 0 : status = NT_STATUS_INTERNAL_ERROR;
586 0 : DEBUG(1, ("Internal ERROR: no gensec_ctx on session: %s\n", nt_errstr(status)));
587 0 : goto failed;
588 : }
589 :
590 1172 : s = talloc(req, struct sesssetup_spnego_state);
591 1172 : if (!s) goto nomem;
592 1172 : s->req = req;
593 1172 : s->sess = sess;
594 1172 : s->smb_sess = smb_sess;
595 :
596 2249 : subreq = gensec_update_send(s,
597 1172 : req->smb_conn->connection->event.ctx,
598 : smb_sess->gensec_ctx,
599 : sess->spnego.in.secblob);
600 1172 : if (!subreq) {
601 0 : goto nomem;
602 : }
603 : /* disable receipt of more packets on this socket until we've
604 : finished with the session setup. This avoids a problem with
605 : crashes if we get EOF on the socket while processing a session
606 : setup */
607 1172 : packet_recv_disable(req->smb_conn->packet);
608 1172 : tevent_req_set_callback(subreq, sesssetup_spnego_send, s);
609 :
610 1172 : return;
611 :
612 0 : nomem:
613 0 : status = NT_STATUS_NO_MEMORY;
614 3 : failed:
615 3 : if (is_smb_sess_new) {
616 0 : talloc_free(smb_sess);
617 : }
618 3 : status = nt_status_squash(status);
619 3 : smbsrv_sesssetup_backend_send(req, sess, status);
620 : }
621 :
622 : /*
623 : backend for sessionsetup call - this takes all 3 variants of the call
624 : */
625 1196 : void smbsrv_sesssetup_backend(struct smbsrv_request *req,
626 : union smb_sesssetup *sess)
627 : {
628 1196 : switch (sess->old.level) {
629 4 : case RAW_SESSSETUP_OLD:
630 4 : sesssetup_old(req, sess);
631 103 : return;
632 :
633 17 : case RAW_SESSSETUP_NT1:
634 17 : sesssetup_nt1(req, sess);
635 17 : return;
636 :
637 1175 : case RAW_SESSSETUP_SPNEGO:
638 1175 : sesssetup_spnego(req, sess);
639 1175 : return;
640 :
641 0 : case RAW_SESSSETUP_SMB2:
642 0 : break;
643 : }
644 :
645 0 : smbsrv_sesssetup_backend_send(req, sess, NT_STATUS_INVALID_LEVEL);
646 : }
|