1 /*
2 * Copyright (c) 2011 - 2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/kmem.h>
31 #include <sys/proc.h>
32 #include <sys/lock.h>
33 #include <sys/socket.h>
34 #include <sys/uio.h>
35 #include <sys/random.h>
36 #include <sys/note.h>
37 #include <sys/errno.h>
38 #include <sys/cmn_err.h>
39
40 #include <smb/ntaccess.h>
41 #include <smb/winioctl.h>
42
43 #include <netsmb/smb_osdep.h>
44
45 #include <netsmb/smb.h>
46 #include <netsmb/smb2.h>
47 #include <netsmb/smb_conn.h>
48 #include <netsmb/smb_subr.h>
49 #include <netsmb/smb_tran.h>
50 #include <netsmb/smb_rq.h>
51 #include <netsmb/smb2_rq.h>
52
53 #define NDIALECTS 1
54 static const uint16_t smb2_dialects[1] = {
55 SMB2_DIALECT_0210
56 };
57
58 /* Optional capabilities we advertise (none yet). */
59 uint32_t smb2_clnt_caps = 0;
60
61 /* How many credits to ask for during ssn. setup. */
62 uint16_t smb2_ss_req_credits = 64;
63
64 /*
65 * Default timeout values, all in seconds.
66 * Make these tunable (only via mdb for now).
67 */
68 int smb2_timo_notice = 15;
69 int smb2_timo_default = 30;
70 int smb2_timo_logon = 45;
71 int smb2_timo_open = 45;
72 int smb2_timo_read = 45;
73 int smb2_timo_write = 60;
74 int smb2_timo_append = 90;
75
76 /*
77 * This is a special handler for the odd SMB1-to-SMB2 negotiate
78 * response, where an SMB1 request gets an SMB2 response.
79 *
80 * Unlike most parse functions here, this needs to parse both
81 * the SMB2 header and the nego. response body. Note that
82 * the only "SMB2" dialect our SMB1 negotiate offered was
83 * { SMB_DIALECT_SMB2_FF, "SMB 2.???"} so the only valid
84 * SMB2 dialect we should get is: SMB2_DIALECT_02ff
85 */
86 int
87 smb2_parse_smb1nego_resp(struct smb_rq *rqp)
88 {
89 struct smb_vc *vcp = rqp->sr_vc;
90 struct smb_sopt *sp = &vcp->vc_sopt;
91 struct mdchain *mdp;
92 uint16_t length = 0;
93 int error;
94
95 /* Get pointer to response data */
96 smb_rq_getreply(rqp, &mdp);
97
98 error = smb2_rq_parsehdr(rqp);
99 if (error != 0)
100 return (error);
101
102 /*
103 * Parse SMB 2/3 Negotiate Response
104 * We are already pointing to begining of Response data
105 */
106
107 /* Check structure size is 65 */
108 md_get_uint16le(mdp, &length);
109 if (length != 65)
110 return (EBADRPC);
111
112 /* Get Security Mode */
113 md_get_uint16le(mdp, &sp->sv2_security_mode);
114
115 /* Get Dialect. */
116 error = md_get_uint16le(mdp, &sp->sv2_dialect);
117 if (error != 0)
118 return (error);
119
120 /* What dialect did we get? */
121 if (sp->sv2_dialect != SMB2_DIALECT_02ff) {
122 SMBERROR("Unknown dialect 0x%x\n", sp->sv2_dialect);
123 return (EINVAL);
124 }
125 /* Set our (internal) SMB1 dialect also. */
126 sp->sv_proto = SMB_DIALECT_SMB2_FF;
127
128 /*
129 * This request did not go through smb2_iod_addrq and
130 * smb2_iod_process() so the SMB2 message ID state is
131 * behind what we need it to be. Fix that.
132 */
133 vcp->vc2_next_message_id = 1;
134 vcp->vc2_limit_message_id = 2;
135
136 /*
137 * Skip parsing the rest. We'll get a normal
138 * SMB2 negotiate next and do negotiate then.
139 */
140 return (0);
141 }
142
143 int
144 smb2_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
145 {
146 smb_sopt_t *sp = &vcp->vc_sopt;
147 smbioc_ssn_work_t *wk = &vcp->vc_work;
148 struct smb_rq *rqp = NULL;
149 struct mbchain *mbp = NULL;
150 struct mdchain *mdp = NULL;
151 uint16_t ndialects = NDIALECTS;
152 boolean_t will_sign = B_FALSE;
153 uint16_t length = 0;
154 uint16_t security_mode;
155 uint16_t sec_buf_off;
156 uint16_t sec_buf_len;
157 int err, i;
158
159 /*
160 * Compute security mode
161 */
162 if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) {
163 security_mode = SMB2_NEGOTIATE_SIGNING_REQUIRED;
164 } else {
165 security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
166 }
167
168 err = smb_rq_alloc(VCTOCP(vcp), SMB2_NEGOTIATE, scred, &rqp);
169 if (err)
170 return (err);
171
172 /*
173 * Build the SMB2 negotiate request.
174 */
175 smb_rq_getrequest(rqp, &mbp);
176 mb_put_uint16le(mbp, 36); /* Struct Size */
177 mb_put_uint16le(mbp, ndialects); /* Dialect Count */
178 mb_put_uint16le(mbp, security_mode);
179 mb_put_uint16le(mbp, 0); /* Reserved */
180 mb_put_uint32le(mbp, smb2_clnt_caps);
181 mb_put_mem(mbp, vcp->vc_cl_guid, 16, MB_MSYSTEM);
182 mb_put_uint64le(mbp, 0); /* Start Time */
183 for (i = 0; i < ndialects; i++) { /* Dialects */
184 mb_put_uint16le(mbp, smb2_dialects[i]);
185 }
186
187 /*
188 * Do the OTW call.
189 */
190 err = smb2_rq_internal(rqp, smb2_timo_default);
191 if (err) {
192 goto errout;
193 }
194 /* Should only get status success. */
195 if (rqp->sr_error != NT_STATUS_SUCCESS) {
196 err = ENOTSUP;
197 goto errout;
198 }
199
200 /*
201 * Decode the negotiate response
202 */
203 smb_rq_getreply(rqp, &mdp);
204
205 md_get_uint16le(mdp, &length); /* Struct size */
206 if (length != 65) {
207 err = EBADRPC;
208 goto errout;
209 }
210
211 md_get_uint16le(mdp, &sp->sv2_security_mode);
212 md_get_uint16le(mdp, &sp->sv2_dialect);
213 md_get_uint16le(mdp, NULL); /* reserved */
214 md_get_mem(mdp, sp->sv2_guid, 16, MB_MSYSTEM);
215 md_get_uint32le(mdp, &sp->sv2_capabilities);
216 md_get_uint32le(mdp, &sp->sv2_maxtransact);
217 md_get_uint32le(mdp, &sp->sv2_maxread);
218 md_get_uint32le(mdp, &sp->sv2_maxwrite);
219 md_get_uint64le(mdp, NULL); /* curr_time */
220 md_get_uint64le(mdp, NULL); /* boot_time */
221
222 /* Get Security Blob offset and length */
223 md_get_uint16le(mdp, &sec_buf_off);
224 err = md_get_uint16le(mdp, &sec_buf_len);
225 if (err != 0)
226 goto errout;
227 md_get_uint32le(mdp, NULL); /* reserved */
228
229 /*
230 * Security buffer offset is from the beginning of SMB 2 Header
231 * Calculate how much further we have to go to get to it.
232 * Current offset is: SMB2_HDRLEN + 64
233 */
234 if (sec_buf_len != 0) {
235 int skip = (int)sec_buf_off - (SMB2_HDRLEN + 64);
236 if (skip < 0) {
237 err = EBADRPC;
238 goto errout;
239 }
240 if (skip > 0) {
241 md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
242 }
243
244 /*
245 * Copy the security blob out to user space.
246 * Buffer addr,size in vc_auth_rbuf,rlen
247 */
248 if (wk->wk_u_auth_rlen < sec_buf_len) {
249 SMBSDEBUG("vc_auth_rbuf too small");
250 /* Give caller required size. */
251 wk->wk_u_auth_rlen = sec_buf_len;
252 err = EMSGSIZE;
253 goto errout;
254 }
255 wk->wk_u_auth_rlen = sec_buf_len;
256 err = md_get_mem(mdp, wk->wk_u_auth_rbuf.lp_ptr,
257 sec_buf_len, MB_MUSER);
258 if (err) {
259 goto errout;
260 }
261 }
262
263 /*
264 * Decoded everything. Now decisions.
265 */
266
267 /*
268 * Turn on signing if either Server or client requires it,
269 * except: anonymous sessions can't sign.
270 */
271 if ((sp->sv2_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
272 (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED))
273 will_sign = B_TRUE;
274 if (vcp->vc_vopt & SMBVOPT_ANONYMOUS)
275 will_sign = B_FALSE;
276 SMBSDEBUG("Security signatures: %d", (int)will_sign);
277 if (will_sign)
278 vcp->vc_flags |= SMBV_SIGNING;
279
280 /*
281 * ToDo - too many places are looking at sv_caps, so for now
282 * set the SMB1 capabilities too. Later we should use the
283 * sv2_capabilities for SMB 2+.
284 */
285 sp->sv_caps = (SMB_CAP_UNICODE |
286 SMB_CAP_LARGE_FILES |
287 SMB_CAP_STATUS32 |
288 SMB_CAP_LARGE_READX |
289 SMB_CAP_LARGE_WRITEX |
290 SMB_CAP_EXT_SECURITY);
291 if (sp->sv2_capabilities & SMB2_CAP_DFS)
292 sp->sv_caps |= SMB_CAP_DFS;
293
294 /*
295 * A few sanity checks on what we received,
296 * becuse we will send these in ssnsetup.
297 *
298 * Maximum outstanding requests (we care),
299 * and Max. VCs (we only use one). Also,
300 * MaxBufferSize lower limit per spec.
301 */
302 if (sp->sv2_maxread < 0x8000) {
303 SMBSDEBUG("maxread too small\n");
304 err = ENOTSUP;
305 goto errout;
306 }
307 if (sp->sv2_maxwrite < 0x8000) {
308 SMBSDEBUG("maxwrite too small\n");
309 err = ENOTSUP;
310 goto errout;
311 }
312 if (sp->sv2_maxtransact < 0x4000) {
313 SMBSDEBUG("maxtransact too small\n");
314 err = ENOTSUP;
315 goto errout;
316 }
317
318 /* Here too, fill SMB1 fields */
319 vcp->vc_rxmax = sp->sv2_maxread;
320 vcp->vc_wxmax = sp->sv2_maxwrite;
321 vcp->vc_txmax = sp->sv2_maxtransact;
322
323 smb_rq_done(rqp);
324 return (0);
325
326 errout:
327 smb_rq_done(rqp);
328 if (err == 0)
329 err = EBADRPC;
330 return (err);
331 }
332
333 int
334 smb2_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred)
335 {
336 // smb_sopt_t *sv = &vcp->vc_sopt;
337 smbioc_ssn_work_t *wk = &vcp->vc_work;
338 struct smb_rq *rqp = NULL;
339 struct mbchain *mbp = NULL;
340 struct mdchain *mdp = NULL;
341 char *sb;
342 int err, ret;
343 uint16_t sblen;
344 uint16_t length = 0;
345 uint16_t session_flags;
346 uint16_t sec_buf_off;
347 uint16_t sec_buf_len;
348 uint8_t security_mode;
349
350 /*
351 * Compute security mode
352 */
353 if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) {
354 security_mode = SMB2_NEGOTIATE_SIGNING_REQUIRED;
355 } else {
356 security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
357 }
358
359 sb = wk->wk_u_auth_wbuf.lp_ptr;
360 sblen = (uint16_t)wk->wk_u_auth_wlen;
361
362 err = smb_rq_alloc(VCTOCP(vcp), SMB2_SESSION_SETUP, scred, &rqp);
363 if (err != 0) {
364 ret = err;
365 goto out;
366 }
367
368 /*
369 * Always ask for some credits. The server usually will
370 * only grant these credits once we've authenticated.
371 */
372 rqp->sr2_creditsrequested = smb2_ss_req_credits;
373
374 /*
375 * Build the SMB Session Setup request.
376 */
377 smb_rq_getrequest(rqp, &mbp);
378
379 mb_put_uint16le(mbp, 25); /* Struct size */
380 mb_put_uint8(mbp, 0); /* VcNumber */
381 mb_put_uint8(mbp, security_mode);
382 mb_put_uint32le(mbp, smb2_clnt_caps); /* Capabilities */
383 mb_put_uint32le(mbp, 0); /* Channel - always 0 */
384
385 /*
386 * Security buffer offset and length. Normally would use
387 * ptr = mb_reserve() and fill in later, but since only a
388 * small amount of fixed-size stuff follows (12 bytes)
389 * we can just compute the offset now.
390 */
391 mb_put_uint16le(mbp, mbp->mb_count + 12);
392 mb_put_uint16le(mbp, sblen);
393 mb_put_uint64le(mbp, vcp->vc2_prev_session_id);
394 err = mb_put_mem(mbp, sb, sblen, MB_MUSER);
395 if (err != 0) {
396 ret = err;
397 goto out;
398 }
399
400 /*
401 * Run the request. The return value here should be the
402 * return from this function, unless we fail decoding.
403 * Note: NT_STATUS_MORE_PROCESSING_REQUIRED is OK, and
404 * the caller expects EINPROGRESS for that case.
405 */
406 ret = smb2_rq_internal(rqp, smb2_timo_logon);
407 if (ret != 0)
408 goto out;
409 switch (rqp->sr_error) {
410 case NT_STATUS_SUCCESS:
411 break;
412 case NT_STATUS_MORE_PROCESSING_REQUIRED:
413 /* Keep going, but return... */
414 ret = EINPROGRESS;
415 break;
416 default:
417 ret = EAUTH;
418 goto out;
419 }
420
421 /*
422 * After the first Session Setup Response,
423 * save the session ID.
424 */
425 if (vcp->vc2_session_id == 0)
426 vcp->vc2_session_id = rqp->sr2_rspsessionid;
427
428 /*
429 * Decode the session setup response
430 */
431 smb_rq_getreply(rqp, &mdp);
432
433 md_get_uint16le(mdp, &length); /* Struct size */
434 if (length != 9) {
435 ret = EBADRPC;
436 goto out;
437 }
438
439 md_get_uint16le(mdp, &session_flags);
440 md_get_uint16le(mdp, &sec_buf_off);
441 err = md_get_uint16le(mdp, &sec_buf_len);
442 if (err != 0) {
443 ret = err;
444 goto out;
445 }
446
447 /*
448 * Security buffer offset is from the beginning of SMB 2 Header
449 * Calculate how much further we have to go to get to it.
450 * Current offset is: SMB2_HDRLEN + 8
451 */
452 if (sec_buf_len != 0) {
453 int skip = (int)sec_buf_off - (SMB2_HDRLEN + 8);
454 if (skip < 0) {
455 ret = EBADRPC;
456 goto out;
457 }
458 if (skip > 0) {
459 md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
460 }
461
462 /*
463 * Copy the security blob out to user space.
464 * Buffer addr,size in vc_auth_rbuf,rlen
465 */
466 if (wk->wk_u_auth_rlen < sec_buf_len) {
467 SMBSDEBUG("vc_auth_rbuf too small");
468 /* Give caller required size. */
469 wk->wk_u_auth_rlen = sec_buf_len;
470 ret = EMSGSIZE;
471 goto out;
472 }
473 wk->wk_u_auth_rlen = sec_buf_len;
474 err = md_get_mem(mdp, wk->wk_u_auth_rbuf.lp_ptr,
475 sec_buf_len, MB_MUSER);
476 if (err != 0) {
477 ret = err;
478 goto out;
479 }
480 }
481
482 out:
483 if (err != 0 && err != EINPROGRESS) {
484 /* Session ID no longer valid. */
485 vcp->vc2_session_id = 0;
486 }
487 if (rqp)
488 smb_rq_done(rqp);
489
490 return (ret);
491 }
492
493 int
494 smb2_smb_logoff(struct smb_vc *vcp, struct smb_cred *scred)
495 {
496 struct smb_rq *rqp;
497 struct mbchain *mbp;
498 int error;
499
500 if (vcp->vc2_session_id == 0)
501 return (0);
502
503 error = smb_rq_alloc(VCTOCP(vcp), SMB2_LOGOFF, scred, &rqp);
504 if (error)
505 return (error);
506
507 /*
508 * Fill in Logoff part
509 */
510 smb_rq_getrequest(rqp, &mbp);
511 mb_put_uint16le(mbp, 4); /* Struct size */
512 mb_put_uint16le(mbp, 0); /* Reserved */
513
514 /*
515 * Run this with a relatively short timeout. (5 sec.)
516 * We don't really care about the result here.
517 * Also, don't reconnect for this, of course!
518 */
519 rqp->sr_flags |= SMBR_NORECONNECT;
520 error = smb2_rq_internal(rqp, 5);
521 smb_rq_done(rqp);
522 return (error);
523 }
524
525 int
526 smb2_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred)
527 {
528 struct smb_vc *vcp;
529 struct smb_rq *rqp = NULL;
530 struct mbchain *mbp;
531 struct mdchain *mdp;
532 char *unc_name = NULL;
533 int error, unc_len;
534 uint16_t plen, *plenp;
535 uint16_t options = 0;
536 uint_t cnt0;
537 uint32_t net_stype;
538 uint16_t structure_size = 0;
539 uint8_t smb2stype;
540
541 vcp = SSTOVC(ssp);
542
543 /*
544 * Make this a "VC-level" request, so it will have
545 * rqp->sr_share == NULL, and smb_iod_sendrq()
546 * will send it with TID = SMB_TID_UNKNOWN
547 *
548 * This also serves to bypass the wait for
549 * share state changes, which this call is
550 * trying to carry out.
551 */
552 error = smb_rq_alloc(VCTOCP(vcp), SMB2_TREE_CONNECT, scred, &rqp);
553 if (error)
554 return (error);
555
556 /*
557 * Build the UNC name, i.e. "//server/share"
558 * but with backslashes of course.
559 * size math: three slashes, one null.
560 */
561 unc_len = 4 + strlen(vcp->vc_srvname) + strlen(ssp->ss_name);
562 unc_name = kmem_alloc(unc_len, KM_SLEEP);
563 (void) snprintf(unc_name, unc_len, "\\\\%s\\%s",
564 vcp->vc_srvname, ssp->ss_name);
565 SMBSDEBUG("unc_name: \"%s\"", unc_name);
566
567 /*
568 * Build the request.
569 */
570 mbp = &rqp->sr_rq;
571
572 mb_put_uint16le(mbp, 9); /* Struct size */
573 mb_put_uint16le(mbp, 0); /* Reserved */
574 mb_put_uint16le(mbp, 72); /* Path Offset */
575
576 /*
577 * Fill in path length after we put the string, so we know
578 * the length after conversion from UTF-8 to UCS-2.
579 */
580 plenp = mb_reserve(mbp, 2);
581 cnt0 = mbp->mb_count;
582
583 /* UNC resource name (without the null) */
584 error = smb_put_dmem(mbp, vcp, unc_name, unc_len - 1,
585 SMB_CS_NONE, NULL);
586 if (error)
587 goto out;
588
589 /* Now go back and fill in the path length. */
590 plen = (uint16_t)(mbp->mb_count - cnt0);
591 *plenp = htoles(plen);
592
593 /*
594 * Run the request.
595 *
596 * Using NOINTR_RECV because we don't want to risk
597 * missing a successful tree connect response,
598 * which would "leak" Tree IDs.
599 */
600 rqp->sr_flags |= SMBR_NOINTR_RECV;
601 error = smb2_rq_simple(rqp);
602 SMBSDEBUG("%d\n", error);
603 if (error) {
604 /*
605 * If we get the server name wrong, i.e. due to
606 * mis-configured name services, this will be
607 * NT_STATUS_DUPLICATE_NAME. Log this error.
608 */
609 SMBERROR("(%s) failed, status=0x%x",
610 unc_name, rqp->sr_error);
611 goto out;
612 }
613
614 /*
615 * Parse the tree connect response
616 */
617 smb_rq_getreply(rqp, &mdp);
618
619 /* Check structure size is 16 */
620 md_get_uint16le(mdp, &structure_size);
621 if (structure_size != 16) {
622 error = EBADRPC;
623 goto out;
624 }
625
626 md_get_uint8(mdp, &smb2stype);
627 md_get_uint8(mdp, NULL); /* reserved */
628 md_get_uint32le(mdp, &ssp->ss2_share_flags);
629 md_get_uint32le(mdp, &ssp->ss2_share_caps);
630 error = md_get_uint32le(mdp, NULL); /* maxAccessRights */
631 if (error)
632 goto out;
633
634 /*
635 * Convert SMB2 share type to NetShareEnum share type
636 */
637 switch (smb2stype) {
638 case SMB2_SHARE_TYPE_DISK:
639 net_stype = STYPE_DISKTREE;
640 break;
641 case SMB2_SHARE_TYPE_PIPE:
642 net_stype = STYPE_IPC;
643 break;
644 case SMB2_SHARE_TYPE_PRINT:
645 net_stype = STYPE_PRINTQ;
646 break;
647 default:
648 net_stype = STYPE_UNKNOWN;
649 break;
650 }
651 ssp->ss_type = net_stype;
652
653 /*
654 * Map SMB 2/3 capabilities to SMB 1 options,
655 * for common code that looks there.
656 */
657 if (ssp->ss2_share_caps & SMB2_SHARE_CAP_DFS)
658 options |= SMB_SHARE_IS_IN_DFS;
659
660 /* Update share state */
661 SMB_SS_LOCK(ssp);
662 ssp->ss2_tree_id = rqp->sr2_rsptreeid;
663 ssp->ss_vcgenid = vcp->vc_genid;
664 ssp->ss_options = options;
665 ssp->ss_flags |= SMBS_CONNECTED;
666 SMB_SS_UNLOCK(ssp);
667
668 out:
669 if (unc_name)
670 kmem_free(unc_name, unc_len);
671 smb_rq_done(rqp);
672 return (error);
673 }
674
675 int
676 smb2_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred)
677 {
678 struct smb_vc *vcp;
679 struct smb_rq *rqp;
680 struct mbchain *mbp;
681 int error;
682
683 if (ssp->ss2_tree_id == SMB2_TID_UNKNOWN)
684 return (0);
685
686 /*
687 * Build this as a "VC-level" request, so it will
688 * avoid testing the _GONE flag on the share,
689 * which has already been set at this point.
690 * Add the share pointer "by hand" below, so
691 * smb_iod_sendrq will plug in the TID.
692 */
693 vcp = SSTOVC(ssp);
694 error = smb_rq_alloc(VCTOCP(vcp), SMB2_TREE_DISCONNECT, scred, &rqp);
695 if (error)
696 return (error);
697 rqp->sr_share = ssp; /* See "by hand" above. */
698
699 /*
700 * Fill in SMB2 Tree Disconnect part
701 */
702 smb_rq_getrequest(rqp, &mbp);
703 mb_put_uint16le(mbp, 4); /* Struct size */
704 mb_put_uint16le(mbp, 0); /* Reserved */
705
706 /*
707 * Run this with a relatively short timeout. (5 sec.)
708 * We don't really care about the result here, but we
709 * do need to make sure we send this out, or we could
710 * "leak" active tree IDs on interrupt or timeout.
711 * The NOINTR_SEND flag makes this request immune to
712 * interrupt or timeout until the send is done.
713 * Also, don't reconnect for this, of course!
714 */
715 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
716 error = smb2_rq_simple_timed(rqp, 5);
717
718 smb_rq_done(rqp);
719
720 /* Whether we get an error or not... */
721 ssp->ss2_tree_id = SMB2_TID_UNKNOWN;
722
723 return (error);
724 }
725
726 /*
727 * Put the name, first skipping a leading slash.
728 */
729 static int
730 put_name_skip_slash(struct mbchain *mbp, struct mbchain *name_mbp)
731 {
732 mblk_t *m;
733
734 if (name_mbp == NULL)
735 return (0);
736 m = name_mbp->mb_top;
737 if (m == NULL)
738 return (0);
739
740 /* Use a dup of the message to leave the passed one untouched. */
741 m = dupmsg(m);
742 if (m == NULL)
743 return (ENOSR);
744
745 if (MBLKL(m) >= 2 &&
746 m->b_rptr[0] == '\\' &&
747 m->b_rptr[1] == '\0')
748 m->b_rptr += 2;
749
750 return (mb_put_mbuf(mbp, m));
751 }
752
753 /*
754 * Modern create/open of file or directory.
755 *
756 * The passed name is a full path relative to the share root.
757 * Callers prepare paths with a leading slash (backslash)
758 * because that's what SMB1 expected. SMB2 does not allow the
759 * leading slash here. To make life simpler for callers skip a
760 * leading slash here. That allows callers use use common logic
761 * for building paths without needing to know if the connection
762 * is using SMB1 or SMB2 (just build paths with a leading slash).
763 */
764 int
765 smb2_smb_ntcreate(
766 struct smb_share *ssp,
767 struct mbchain *name_mb,
768 struct mbchain *cctx_in,
769 struct mdchain *cctx_out,
770 uint32_t cr_flags, /* create flags */
771 uint32_t req_acc, /* requested access */
772 uint32_t efa, /* ext. file attrs (DOS attr +) */
773 uint32_t share_acc,
774 uint32_t open_disp, /* open disposition */
775 uint32_t createopt, /* NTCREATEX_OPTIONS_ */
776 uint32_t impersonate, /* NTCREATEX_IMPERSONATION_... */
777 struct smb_cred *scrp,
778 smb2fid_t *fidp, /* returned FID */
779 uint32_t *cr_act_p, /* optional create action */
780 struct smbfattr *fap) /* optional attributes */
781 {
782 struct smbfattr fa;
783 struct smb_rq *rqp;
784 struct mbchain *mbp;
785 struct mdchain *mdp;
786 uint16_t *name_offp;
787 uint16_t *name_lenp;
788 uint32_t *cctx_offp;
789 uint32_t *cctx_lenp;
790 uint32_t rcc_off, rcc_len;
791 smb2fid_t smb2_fid;
792 uint64_t llongint;
793 uint32_t longint, createact;
794 uint_t off, len;
795 int error;
796 uint16_t StructSize = 57; // [MS-SMB2]
797
798 bzero(&fa, sizeof (fa));
799
800 error = smb_rq_alloc(SSTOCP(ssp), SMB2_CREATE, scrp, &rqp);
801 if (error)
802 return (error);
803
804 /*
805 * Todo: Assemble creat contexts (if needed)
806 * into an mbchain.
807 */
808
809 /*
810 * Build the SMB 2/3 Create Request
811 */
812 smb_rq_getrequest(rqp, &mbp);
813 mb_put_uint16le(mbp, StructSize);
814 mb_put_uint8(mbp, 0); /* Security flags */
815 mb_put_uint8(mbp, SMB2_OPLOCK_LEVEL_NONE); /* Oplock level */
816 mb_put_uint32le(mbp, impersonate); /* Impersonation Level */
817 mb_put_uint64le(mbp, cr_flags);
818 mb_put_uint64le(mbp, 0); /* Reserved */
819 mb_put_uint32le(mbp, req_acc);
820 mb_put_uint32le(mbp, efa); /* File attributes */
821 mb_put_uint32le(mbp, share_acc); /* Share access */
822 mb_put_uint32le(mbp, open_disp); /* Create disposition */
823 mb_put_uint32le(mbp, createopt); /* Create options */
824
825 name_offp = mb_reserve(mbp, 2); /* Name offset */
826 name_lenp = mb_reserve(mbp, 2); /* Name len */
827
828 cctx_offp = mb_reserve(mbp, 4); /* Context offset */
829 cctx_lenp = mb_reserve(mbp, 4); /* Context len */
830
831 /*
832 * Put the file name, which is provided in an mbchain.
833 * If there's a leading slash, skip it (see above).
834 */
835 off = mbp->mb_count;
836 *name_offp = htoles((uint16_t)off);
837 error = put_name_skip_slash(mbp, name_mb);
838 if (error)
839 goto out;
840 len = mbp->mb_count - off;
841 *name_lenp = htoles((uint16_t)len);
842
843 /*
844 * Now the create contexts (if provided)
845 */
846 if (cctx_in != NULL) {
847 off = mbp->mb_count;
848 *cctx_offp = htolel((uint32_t)off);
849 mb_put_mbchain(mbp, cctx_in);
850 len = mbp->mb_count - off;
851 *cctx_lenp = htolel((uint32_t)len);
852 } else {
853 *cctx_offp = 0;
854 *cctx_lenp = 0;
855 }
856
857 /*
858 * If we didn't put any variable-sized data, we'll have
859 * put exactly 56 bytes of data, and we need to pad out
860 * this request to the 57 bytes StructSize indicated.
861 */
862 if (mbp->mb_count < (StructSize + SMB2_HDRLEN))
863 mb_put_uint8(mbp, 0);
864
865 /*
866 * Don't want to risk missing a successful
867 * open response, or we could "leak" FIDs.
868 */
869 rqp->sr_flags |= SMBR_NOINTR_RECV;
870 error = smb2_rq_simple_timed(rqp, smb2_timo_open);
871 if (error)
872 goto out;
873
874 /*
875 * Parse SMB 2/3 Create Response
876 */
877 smb_rq_getreply(rqp, &mdp);
878
879 /* Check structure size is 89 */
880 error = md_get_uint16le(mdp, &StructSize);
881 if (StructSize != 89) {
882 error = EBADRPC;
883 goto out;
884 }
885
886 md_get_uint8(mdp, NULL); /* oplock lvl granted */
887 md_get_uint8(mdp, NULL); /* mbz */
888 md_get_uint32le(mdp, &createact); /* create_action */
889 md_get_uint64le(mdp, &llongint); /* creation time */
890 smb_time_NT2local(llongint, &fa.fa_createtime);
891 md_get_uint64le(mdp, &llongint); /* access time */
892 smb_time_NT2local(llongint, &fa.fa_atime);
893 md_get_uint64le(mdp, &llongint); /* write time */
894 smb_time_NT2local(llongint, &fa.fa_mtime);
895 md_get_uint64le(mdp, &llongint); /* change time */
896 smb_time_NT2local(llongint, &fa.fa_ctime);
897 md_get_uint64le(mdp, &llongint); /* allocation size */
898 fa.fa_allocsz = llongint;
899 md_get_uint64le(mdp, &llongint); /* EOF position */
900 fa.fa_size = llongint;
901 md_get_uint32le(mdp, &longint); /* attributes */
902 fa.fa_attr = longint;
903 md_get_uint32le(mdp, NULL); /* reserved */
904
905 /* Get SMB 2/3 File ID and create user fid to return */
906 md_get_uint64le(mdp, &smb2_fid.fid_persistent);
907 error = md_get_uint64le(mdp, &smb2_fid.fid_volatile);
908 if (error)
909 goto out;
910
911 /* Get Context Offset */
912 error = md_get_uint32le(mdp, &rcc_off);
913 if (error)
914 goto out;
915 /* Get Context Length */
916 error = md_get_uint32le(mdp, &rcc_len);
917 if (error)
918 goto out;
919
920 /*
921 * If the caller wants the returned create contexts, parse.
922 * Context offset is from the beginning of SMB 2/3 Header
923 * Calculate how much further we have to go to get to it.
924 * Current offset is: SMB2_HDRLEN + 88
925 */
926 if (rcc_len != 0) {
927 int skip = (int)rcc_off - (SMB2_HDRLEN + 88);
928 if (skip < 0) {
929 error = EBADRPC;
930 goto out;
931 }
932 if (skip > 0) {
933 md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
934 }
935 if (cctx_out != NULL) {
936 mblk_t *m = NULL;
937 error = md_get_mbuf(mdp, rcc_len, &m);
938 if (error)
939 goto out;
940 md_initm(cctx_out, m);
941 }
942 }
943
944 out:
945 smb_rq_done(rqp);
946 if (error)
947 return (error);
948
949 *fidp = smb2_fid;
950 if (cr_act_p)
951 *cr_act_p = createact;
952 if (fap)
953 *fap = fa; /* struct copy */
954
955 return (0);
956 }
957
958 int
959 smb2_smb_close(struct smb_share *ssp, smb2fid_t *fid, struct smb_cred *scrp)
960 {
961 struct smb_rq *rqp;
962 struct mbchain *mbp;
963 int error;
964
965 error = smb_rq_alloc(SSTOCP(ssp), SMB2_CLOSE, scrp, &rqp);
966 if (error)
967 return (error);
968
969 /*
970 * Build the SMB 2/3 Close Request
971 */
972 smb_rq_getrequest(rqp, &mbp);
973 mb_put_uint16le(mbp, 24); /* Struct size */
974 mb_put_uint16le(mbp, 0); /* Flags */
975 mb_put_uint32le(mbp, 0); /* Reserved */
976
977 mb_put_uint64le(mbp, fid->fid_persistent);
978 mb_put_uint64le(mbp, fid->fid_volatile);
979
980 /* Make sure we send, but only if already connected */
981 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
982 error = smb2_rq_simple(rqp);
983 smb_rq_done(rqp);
984 return (error);
985 }
986
987 int
988 smb2_smb_ioctl(
989 struct smb_share *ssp,
990 smb2fid_t *fid,
991 struct mbchain *data_in,
992 struct mdchain *data_out,
993 uint32_t *data_out_sz, /* max / returned */
994 uint32_t ctl_code,
995 struct smb_cred *scrp)
996 {
997 struct smb_rq *rqp;
998 struct mbchain *mbp;
999 struct mdchain *mdp;
1000 uint32_t *data_in_offp;
1001 uint32_t *data_in_lenp;
1002 uint32_t data_out_off;
1003 uint32_t data_out_len;
1004 uint16_t length = 0;
1005 uint_t off, len;
1006 int error;
1007
1008 error = smb_rq_alloc(SSTOCP(ssp), SMB2_IOCTL, scrp, &rqp);
1009 if (error)
1010 return (error);
1011
1012 /*
1013 * Build the SMB 2 IOCTL Request
1014 */
1015 smb_rq_getrequest(rqp, &mbp);
1016 mb_put_uint16le(mbp, 57); /* Struct size */
1017 mb_put_uint16le(mbp, 0); /* Reserved */
1018 mb_put_uint32le(mbp, ctl_code);
1019
1020 mb_put_uint64le(mbp, fid->fid_persistent);
1021 mb_put_uint64le(mbp, fid->fid_volatile);
1022
1023 data_in_offp = mb_reserve(mbp, 4);
1024 data_in_lenp = mb_reserve(mbp, 4);
1025 mb_put_uint32le(mbp, 0); /* Max input resp */
1026
1027 mb_put_uint32le(mbp, 0); /* Output offset */
1028 mb_put_uint32le(mbp, 0); /* Output count */
1029 mb_put_uint32le(mbp, *data_out_sz);
1030
1031 mb_put_uint32le(mbp, SMB2_IOCTL_IS_FSCTL); /* Flags */
1032 mb_put_uint32le(mbp, 0); /* Reserved2 */
1033
1034 /*
1035 * Now data_in (if provided)
1036 */
1037 if (data_in != NULL) {
1038 off = mbp->mb_count;
1039 *data_in_offp = htolel((uint32_t)off);
1040 mb_put_mbchain(mbp, data_in);
1041 len = mbp->mb_count - off;
1042 *data_in_lenp = htolel((uint32_t)len);
1043 } else {
1044 *data_in_offp = 0;
1045 *data_in_lenp = 0;
1046 }
1047
1048 /*
1049 * Run the request
1050 */
1051 error = smb2_rq_simple_timed(rqp, smb2_timo_default);
1052 if (error)
1053 goto out;
1054
1055 /*
1056 * Parse SMB 2 Ioctl Response
1057 */
1058 smb_rq_getreply(rqp, &mdp);
1059
1060 /* Check structure size is 49 */
1061 md_get_uint16le(mdp, &length);
1062 if (length != 49) {
1063 error = EBADRPC;
1064 goto out;
1065 }
1066 md_get_uint16le(mdp, NULL); /* reserved */
1067 md_get_uint32le(mdp, NULL); /* Get CtlCode */
1068 md_get_uint64le(mdp, NULL); /* fid_persistent */
1069 md_get_uint64le(mdp, NULL); /* fid_volatile */
1070 md_get_uint32le(mdp, NULL); /* Get Input offset */
1071 md_get_uint32le(mdp, NULL); /* Get Input count */
1072
1073 error = md_get_uint32le(mdp, &data_out_off);
1074 if (error)
1075 goto out;
1076 error = md_get_uint32le(mdp, &data_out_len);
1077 if (error)
1078 goto out;
1079
1080 md_get_uint32le(mdp, NULL); /* Flags */
1081 md_get_uint32le(mdp, NULL); /* reserved */
1082
1083 /*
1084 * If the caller wants the ioctl output data, parse.
1085 * Current offset is: SMB2_HDRLEN + 48
1086 * Always return the received length.
1087 */
1088 *data_out_sz = data_out_len;
1089 if (data_out_len != 0) {
1090 int skip = (int)data_out_off - (SMB2_HDRLEN + 48);
1091 if (skip < 0) {
1092 error = EBADRPC;
1093 goto out;
1094 }
1095 if (skip > 0) {
1096 md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
1097 }
1098 if (data_out != NULL) {
1099 mblk_t *m = NULL;
1100 error = md_get_mbuf(mdp, data_out_len, &m);
1101 if (error)
1102 goto out;
1103 md_initm(data_out, m);
1104 }
1105 }
1106
1107 out:
1108 smb_rq_done(rqp);
1109
1110 return (error);
1111 }
1112
1113 int
1114 smb2_smb_read(smb_fh_t *fhp, uint32_t *lenp,
1115 uio_t *uiop, smb_cred_t *scred, int timo)
1116 {
1117 struct smb_share *ssp = FHTOSS(fhp);
1118 struct smb_rq *rqp;
1119 struct mbchain *mbp;
1120 struct mdchain *mdp;
1121 int error;
1122 uint64_t off64 = uiop->uio_loffset;
1123 uint32_t rlen;
1124 uint16_t length = 0;
1125 uint8_t data_offset;
1126
1127 error = smb_rq_alloc(SSTOCP(ssp), SMB2_READ, scred, &rqp);
1128 if (error)
1129 return (error);
1130
1131 /*
1132 * Build the SMB 2 Read Request
1133 */
1134 smb_rq_getrequest(rqp, &mbp);
1135 mb_put_uint16le(mbp, 49); /* Struct size */
1136 mb_put_uint16le(mbp, 0); /* Padding and Reserved */
1137
1138 mb_put_uint32le(mbp, *lenp); /* Length of read */
1139 mb_put_uint64le(mbp, off64); /* Offset */
1140
1141 mb_put_uint64le(mbp, fhp->fh_fid2.fid_persistent);
1142 mb_put_uint64le(mbp, fhp->fh_fid2.fid_volatile);
1143
1144 mb_put_uint32le(mbp, 1); /* MinCount */
1145 /* (only indicates blocking) */
1146
1147 mb_put_uint32le(mbp, 0); /* Channel */
1148 mb_put_uint32le(mbp, 0); /* Remaining */
1149 mb_put_uint32le(mbp, 0); /* Channel offset/len */
1150 mb_put_uint8(mbp, 0); /* data "blob" (pad) */
1151
1152 if (timo == 0)
1153 timo = smb2_timo_read;
1154 error = smb2_rq_simple_timed(rqp, timo);
1155 if (error)
1156 goto out;
1157
1158 /*
1159 * Parse SMB 2 Read Response
1160 */
1161 smb_rq_getreply(rqp, &mdp);
1162
1163 /* Check structure size is 17 */
1164 md_get_uint16le(mdp, &length);
1165 if (length != 17) {
1166 error = EBADRPC;
1167 goto out;
1168 }
1169 md_get_uint8(mdp, &data_offset);
1170 md_get_uint8(mdp, NULL); /* reserved */
1171
1172 /* Get Data Length read */
1173 error = md_get_uint32le(mdp, &rlen);
1174 if (error)
1175 goto out;
1176
1177 md_get_uint32le(mdp, NULL); /* Data Remaining (always 0) */
1178 md_get_uint32le(mdp, NULL); /* Get Reserved2 (always 0) */
1179
1180 /*
1181 * Data offset is from the beginning of SMB 2/3 Header
1182 * Calculate how much further we have to go to get to it.
1183 */
1184 if (data_offset < (SMB2_HDRLEN + 16)) {
1185 error = EBADRPC;
1186 goto out;
1187 }
1188 if (data_offset > (SMB2_HDRLEN + 16)) {
1189 int skip = data_offset - (SMB2_HDRLEN + 16);
1190 md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
1191 }
1192
1193 /*
1194 * Get the data
1195 */
1196 if (rlen == 0) {
1197 *lenp = rlen;
1198 goto out;
1199 }
1200 /* paranoid */
1201 if (rlen > *lenp) {
1202 SMBSDEBUG("bad server! rlen %d, len %d\n",
1203 rlen, *lenp);
1204 rlen = *lenp;
1205 }
1206
1207 error = md_get_uio(mdp, uiop, rlen);
1208 if (error)
1209 goto out;
1210
1211 /* Success */
1212 *lenp = rlen;
1213
1214 out:
1215 smb_rq_done(rqp);
1216 return (error);
1217 }
1218
1219 int
1220 smb2_smb_write(smb_fh_t *fhp, uint32_t *lenp,
1221 uio_t *uiop, smb_cred_t *scred, int timo)
1222 {
1223 struct smb_share *ssp = FHTOSS(fhp);
1224 struct smb_rq *rqp;
1225 struct mbchain *mbp;
1226 struct mdchain *mdp;
1227 int error;
1228 uint64_t off64 = uiop->uio_loffset;
1229 uint32_t rlen;
1230 uint16_t data_offset;
1231 uint16_t length = 0;
1232
1233 error = smb_rq_alloc(SSTOCP(ssp), SMB2_WRITE, scred, &rqp);
1234 if (error)
1235 return (error);
1236
1237 /*
1238 * Build the SMB 2 Write Request
1239 */
1240 smb_rq_getrequest(rqp, &mbp);
1241 mb_put_uint16le(mbp, 49); /* Struct size */
1242 data_offset = SMB2_HDRLEN + 48;
1243 mb_put_uint16le(mbp, data_offset); /* Data Offset */
1244 mb_put_uint32le(mbp, *lenp); /* Length of write */
1245 mb_put_uint64le(mbp, off64); /* Offset */
1246
1247 mb_put_uint64le(mbp, fhp->fh_fid2.fid_persistent);
1248 mb_put_uint64le(mbp, fhp->fh_fid2.fid_volatile);
1249
1250 mb_put_uint32le(mbp, 0); /* Channel */
1251 mb_put_uint32le(mbp, 0); /* Remaining */
1252 mb_put_uint32le(mbp, 0); /* Channel offset/len */
1253 mb_put_uint32le(mbp, 0); /* Write flags */
1254
1255 error = mb_put_uio(mbp, uiop, *lenp);
1256 if (error)
1257 goto out;
1258
1259 if (timo == 0)
1260 timo = smb2_timo_write;
1261 error = smb2_rq_simple_timed(rqp, timo);
1262 if (error)
1263 goto out;
1264
1265 /*
1266 * Parse SMB 2/3 Write Response
1267 */
1268 smb_rq_getreply(rqp, &mdp);
1269
1270 /* Check structure size is 17 */
1271 md_get_uint16le(mdp, &length);
1272 if (length != 17) {
1273 error = EBADRPC;
1274 goto out;
1275 }
1276
1277 md_get_uint16le(mdp, NULL); /* Get Reserved */
1278
1279 /* Get Data Length written */
1280 error = md_get_uint32le(mdp, &rlen);
1281 if (error)
1282 goto out;
1283
1284 /* Get Data Remaining (always 0) */
1285 md_get_uint32le(mdp, NULL);
1286
1287 /* Get Reserved2 (always 0) */
1288 md_get_uint32le(mdp, NULL);
1289
1290 /* Success */
1291 *lenp = rlen;
1292
1293 out:
1294 smb_rq_done(rqp);
1295 return (error);
1296 }
1297
1298 /*
1299 * Note: the IOD calls this, so this request must not wait for
1300 * connection state changes, etc. (uses smb2_rq_internal)
1301 */
1302 int
1303 smb2_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo)
1304 {
1305 struct smb_rq *rqp;
1306 struct mbchain *mbp;
1307 int error;
1308
1309 error = smb_rq_alloc(VCTOCP(vcp), SMB2_ECHO, scred, &rqp);
1310 if (error)
1311 return (error);
1312
1313 /*
1314 * Build the SMB 2 Echo Request
1315 */
1316 smb_rq_getrequest(rqp, &mbp);
1317 mb_put_uint16le(mbp, 4); /* Struct size */
1318 mb_put_uint16le(mbp, 0); /* Reserved */
1319
1320 rqp->sr_flags |= SMBR_NORECONNECT;
1321 error = smb2_rq_internal(rqp, timo);
1322
1323 smb_rq_done(rqp);
1324 return (error);
1325 }