3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 #include <smbsrv/smb_kproto.h>
27 #include <smbsrv/smb_share.h>
28
29 static void
30 smb_tcon_puterror(smb_request_t *sr, uint32_t status)
31 {
32
33 switch (status) {
34
35 case NT_STATUS_BAD_NETWORK_NAME:
36 /* Intentional status=0 */
37 smbsr_error(sr, 0, ERRSRV, ERRinvnetname);
38 break;
39
40 case NT_STATUS_ACCESS_DENIED:
41 smbsr_error(sr, status, ERRSRV, ERRaccess);
42 break;
43
83 * message that the server can handle. The client should not generate
84 * messages, nor expect to receive responses, larger than this. This
85 * must be constant for a given server. For newer dialects, this field
86 * is ignored.
87 */
88 smb_sdrc_t
89 smb_pre_tree_connect(smb_request_t *sr)
90 {
91 smb_arg_tcon_t *tcon = &sr->sr_tcon;
92 int rc;
93
94 /*
95 * Perhaps this should be "%A.sA" now that unicode is enabled.
96 */
97 rc = smbsr_decode_data(sr, "%AAA", sr, &tcon->path,
98 &tcon->password, &tcon->service);
99
100 tcon->flags = 0;
101 tcon->optional_support = 0;
102
103 DTRACE_SMB_2(op__TreeConnect__start, smb_request_t *, sr,
104 smb_arg_tcon_t *, tcon);
105
106 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
107 }
108
109 void
110 smb_post_tree_connect(smb_request_t *sr)
111 {
112 DTRACE_SMB_1(op__TreeConnect__done, smb_request_t *, sr);
113 }
114
115 smb_sdrc_t
116 smb_com_tree_connect(smb_request_t *sr)
117 {
118 uint32_t status;
119 int rc;
120
121 status = smb_tree_connect(sr);
122 if (status) {
123 smb_tcon_puterror(sr, status);
124 return (SDRC_ERROR);
125 }
126
127 rc = smbsr_encode_result(sr, 2, 0, "bwww",
128 2, /* wct */
129 (WORD)smb_maxbufsize, /* MaxBufferSize */
130 sr->smb_tid, /* TID */
131 0); /* bcc */
132
274 smb_arg_tcon_t *tcon = &sr->sr_tcon;
275 uint8_t *pwbuf = NULL;
276 uint16_t pwlen = 0;
277 int rc;
278
279 rc = smbsr_decode_vwv(sr, "b.www", &sr->andx_com, &sr->andx_off,
280 &tcon->flags, &pwlen);
281 if (rc == 0) {
282 if (pwlen != 0)
283 pwbuf = smb_srm_zalloc(sr, pwlen);
284
285 rc = smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf,
286 &tcon->path, &tcon->service);
287
288 tcon->pwdlen = pwlen;
289 tcon->password = (char *)pwbuf;
290 }
291
292 tcon->optional_support = 0;
293
294 DTRACE_SMB_2(op__TreeConnectX__start, smb_request_t *, sr,
295 smb_arg_tcon_t *, tcon);
296
297 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
298 }
299
300 void
301 smb_post_tree_connect_andx(smb_request_t *sr)
302 {
303 DTRACE_SMB_1(op__TreeConnectX__done, smb_request_t *, sr);
304 }
305
306 smb_sdrc_t
307 smb_com_tree_connect_andx(smb_request_t *sr)
308 {
309 smb_arg_tcon_t *tcon = &sr->sr_tcon;
310 char *service;
311 uint32_t status;
312 int rc;
313
314 status = smb_tree_connect(sr);
315 if (status) {
316 smb_tcon_puterror(sr, status);
317 return (SDRC_ERROR);
318 }
319
320 switch (sr->tid_tree->t_res_type & STYPE_MASK) {
321 case STYPE_IPC:
322 service = "IPC";
323 break;
324 case STYPE_PRINTQ:
325 service = "LPT1:";
326 break;
327 case STYPE_DISKTREE:
328 default:
329 service = "A:";
330 }
331
332 if (sr->session->dialect < NT_LM_0_12) {
333 rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.wwss",
334 (char)2, /* wct */
335 sr->andx_com,
336 VAR_BCC,
337 VAR_BCC,
338 service,
339 sr->tid_tree->t_typename);
340 } else {
341 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.wwws%u",
342 (char)3, /* wct */
343 sr->andx_com,
344 (short)64,
345 tcon->optional_support,
346 VAR_BCC,
347 service,
348 sr,
349 sr->tid_tree->t_typename);
350 }
351
352 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
353 }
354
355 /*
356 * SmbTreeDisconnect: Disconnect a tree.
357 *
358 * Note: SDDF_SUPPRESS_UID is set for this operation, which means the sr
359 * uid_user field will not be valid on entry to these functions. Do not
360 * use it until it is set up in smb_com_tree_disconnect() or the system
361 * will panic.
362 *
363 * Note: there are scenarios in which the client does not send a tree
364 * disconnect request, for example, when ERRbaduid is returned from
365 * SmbReadX after a user has logged off. Any open files will remain
366 * around until the session is destroyed.
367 *
368 * Client Request Description
369 * ================================== =================================
375 * logically disconnected from the server. Tid is invalidated; it will not
376 * be recognized if used by the client for subsequent requests. All locks,
377 * open files, etc. created on behalf of Tid are released.
378 *
379 * Server Response Description
380 * ================================== =================================
381 *
382 * UCHAR WordCount; Count of parameter words = 0
383 * USHORT ByteCount; Count of data bytes = 0
384 *
385 * Errors:
386 * ERRSRV/ERRinvnid
387 * ERRSRV/ERRbaduid
388 */
389 smb_sdrc_t
390 smb_pre_tree_disconnect(smb_request_t *sr)
391 {
392 sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid);
393 sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
394
395 DTRACE_SMB_1(op__TreeDisconnect__start, smb_request_t *, sr);
396 return (SDRC_SUCCESS);
397 }
398
399 void
400 smb_post_tree_disconnect(smb_request_t *sr)
401 {
402 DTRACE_SMB_1(op__TreeDisconnect__done, smb_request_t *, sr);
403 }
404
405 /*
406 * SmbTreeDisconnect requires a valid UID as well as a valid TID. Some
407 * clients logoff a user and then try to disconnect the trees connected
408 * by the user who has just been logged off, which would normally fail
409 * in the dispatch code with ERRbaduid but, unfortunately, ERRbaduid
410 * causes a problem for some of those clients. Windows returns ERRinvnid.
411 *
412 * To prevent ERRbaduid being returned, the UID and TID are looked up here
413 * rather than prior to dispatching SmbTreeDisconnect requests. If either
414 * the UID or the TID is invalid, ERRinvnid is returned.
415 */
416 smb_sdrc_t
417 smb_com_tree_disconnect(smb_request_t *sr)
418 {
419 if (sr->uid_user == NULL || sr->tid_tree == NULL) {
420 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid);
421 return (SDRC_ERROR);
422 }
423
424 sr->user_cr = smb_user_getcred(sr->uid_user);
425
426 smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
427 smb_tree_disconnect(sr->tid_tree, B_TRUE);
428
429 if (smbsr_encode_empty_result(sr))
430 return (SDRC_ERROR);
431
432 return (SDRC_SUCCESS);
433 }
|
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 #include <smbsrv/smb_kproto.h>
27 #include <smbsrv/smb_share.h>
28
29 static void
30 smb_tcon_puterror(smb_request_t *sr, uint32_t status)
31 {
32
33 switch (status) {
34
35 case NT_STATUS_BAD_NETWORK_NAME:
36 /* Intentional status=0 */
37 smbsr_error(sr, 0, ERRSRV, ERRinvnetname);
38 break;
39
40 case NT_STATUS_ACCESS_DENIED:
41 smbsr_error(sr, status, ERRSRV, ERRaccess);
42 break;
43
83 * message that the server can handle. The client should not generate
84 * messages, nor expect to receive responses, larger than this. This
85 * must be constant for a given server. For newer dialects, this field
86 * is ignored.
87 */
88 smb_sdrc_t
89 smb_pre_tree_connect(smb_request_t *sr)
90 {
91 smb_arg_tcon_t *tcon = &sr->sr_tcon;
92 int rc;
93
94 /*
95 * Perhaps this should be "%A.sA" now that unicode is enabled.
96 */
97 rc = smbsr_decode_data(sr, "%AAA", sr, &tcon->path,
98 &tcon->password, &tcon->service);
99
100 tcon->flags = 0;
101 tcon->optional_support = 0;
102
103 DTRACE_SMB_START(op__TreeConnect, smb_request_t *, sr);
104
105 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
106 }
107
108 void
109 smb_post_tree_connect(smb_request_t *sr)
110 {
111 DTRACE_SMB_DONE(op__TreeConnect, smb_request_t *, sr);
112 }
113
114 smb_sdrc_t
115 smb_com_tree_connect(smb_request_t *sr)
116 {
117 uint32_t status;
118 int rc;
119
120 status = smb_tree_connect(sr);
121 if (status) {
122 smb_tcon_puterror(sr, status);
123 return (SDRC_ERROR);
124 }
125
126 rc = smbsr_encode_result(sr, 2, 0, "bwww",
127 2, /* wct */
128 (WORD)smb_maxbufsize, /* MaxBufferSize */
129 sr->smb_tid, /* TID */
130 0); /* bcc */
131
273 smb_arg_tcon_t *tcon = &sr->sr_tcon;
274 uint8_t *pwbuf = NULL;
275 uint16_t pwlen = 0;
276 int rc;
277
278 rc = smbsr_decode_vwv(sr, "b.www", &sr->andx_com, &sr->andx_off,
279 &tcon->flags, &pwlen);
280 if (rc == 0) {
281 if (pwlen != 0)
282 pwbuf = smb_srm_zalloc(sr, pwlen);
283
284 rc = smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf,
285 &tcon->path, &tcon->service);
286
287 tcon->pwdlen = pwlen;
288 tcon->password = (char *)pwbuf;
289 }
290
291 tcon->optional_support = 0;
292
293 DTRACE_SMB_START(op__TreeConnectX, smb_request_t *, sr);
294
295 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
296 }
297
298 void
299 smb_post_tree_connect_andx(smb_request_t *sr)
300 {
301 DTRACE_SMB_DONE(op__TreeConnectX, smb_request_t *, sr);
302 }
303
304 smb_sdrc_t
305 smb_com_tree_connect_andx(smb_request_t *sr)
306 {
307 smb_arg_tcon_t *tcon = &sr->sr_tcon;
308 smb_tree_t *tree;
309 char *service;
310 uint32_t status;
311 int rc;
312
313 if (tcon->flags & SMB_TCONX_DISCONECT_TID) {
314 tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
315 if (tree != NULL) {
316 smb_tree_disconnect(tree, B_TRUE);
317 smb_session_cancel_requests(sr->session, tree, sr);
318 }
319 }
320
321 status = smb_tree_connect(sr);
322 if (status) {
323 smb_tcon_puterror(sr, status);
324 return (SDRC_ERROR);
325 }
326 tree = sr->tid_tree;
327
328 switch (tree->t_res_type & STYPE_MASK) {
329 case STYPE_IPC:
330 service = "IPC";
331 break;
332 case STYPE_PRINTQ:
333 service = "LPT1:";
334 break;
335 case STYPE_DISKTREE:
336 default:
337 service = "A:";
338 }
339
340 if (sr->session->dialect < NT_LM_0_12) {
341 rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.ww%ss",
342 (char)2, /* wct */
343 sr->andx_com,
344 VAR_BCC,
345 VAR_BCC,
346 sr,
347 service,
348 tree->t_typename);
349 } else if ((tcon->flags & SMB_TCONX_EXTENDED_RESPONSE) == 0) {
350 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%su",
351 (char)3, /* wct */
352 sr->andx_com,
353 (short)64,
354 tcon->optional_support,
355 VAR_BCC,
356 sr,
357 service,
358 tree->t_typename);
359
360 } else {
361 rc = smbsr_encode_result(sr, 7, VAR_BCC, "bb.wwllw%su",
362 (char)7, /* wct (b) */
363 sr->andx_com, /* AndXcmd (b) */
364 (short)72, /* AndXoff (w) */
365 tcon->optional_support, /* (w) */
366 tree->t_access, /* (l) */
367 0, /* guest_access (l) */
368 VAR_BCC, /* (w) */
369 sr, /* (%) */
370 service, /* (s) */
371 tree->t_typename); /* (u) */
372 }
373
374 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
375 }
376
377 /*
378 * SmbTreeDisconnect: Disconnect a tree.
379 *
380 * Note: SDDF_SUPPRESS_UID is set for this operation, which means the sr
381 * uid_user field will not be valid on entry to these functions. Do not
382 * use it until it is set up in smb_com_tree_disconnect() or the system
383 * will panic.
384 *
385 * Note: there are scenarios in which the client does not send a tree
386 * disconnect request, for example, when ERRbaduid is returned from
387 * SmbReadX after a user has logged off. Any open files will remain
388 * around until the session is destroyed.
389 *
390 * Client Request Description
391 * ================================== =================================
397 * logically disconnected from the server. Tid is invalidated; it will not
398 * be recognized if used by the client for subsequent requests. All locks,
399 * open files, etc. created on behalf of Tid are released.
400 *
401 * Server Response Description
402 * ================================== =================================
403 *
404 * UCHAR WordCount; Count of parameter words = 0
405 * USHORT ByteCount; Count of data bytes = 0
406 *
407 * Errors:
408 * ERRSRV/ERRinvnid
409 * ERRSRV/ERRbaduid
410 */
411 smb_sdrc_t
412 smb_pre_tree_disconnect(smb_request_t *sr)
413 {
414 sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid);
415 sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
416
417 DTRACE_SMB_START(op__TreeDisconnect, smb_request_t *, sr);
418 return (SDRC_SUCCESS);
419 }
420
421 void
422 smb_post_tree_disconnect(smb_request_t *sr)
423 {
424 DTRACE_SMB_DONE(op__TreeDisconnect, smb_request_t *, sr);
425 }
426
427 /*
428 * SmbTreeDisconnect requires a valid UID as well as a valid TID. Some
429 * clients logoff a user and then try to disconnect the trees connected
430 * by the user who has just been logged off, which would normally fail
431 * in the dispatch code with ERRbaduid but, unfortunately, ERRbaduid
432 * causes a problem for some of those clients. Windows returns ERRinvnid.
433 *
434 * To prevent ERRbaduid being returned, the UID and TID are looked up here
435 * rather than prior to dispatching SmbTreeDisconnect requests. If either
436 * the UID or the TID is invalid, ERRinvnid is returned.
437 */
438 smb_sdrc_t
439 smb_com_tree_disconnect(smb_request_t *sr)
440 {
441 if (sr->uid_user == NULL || sr->tid_tree == NULL) {
442 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid);
443 return (SDRC_ERROR);
444 }
445
446 sr->user_cr = smb_user_getcred(sr->uid_user);
447
448 smb_tree_disconnect(sr->tid_tree, B_TRUE);
449 smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
450
451 if (smbsr_encode_empty_result(sr))
452 return (SDRC_ERROR);
453
454 return (SDRC_SUCCESS);
455 }
|