16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: smb_smb.c,v 1.35.100.2 2005/06/02 00:55:39 lindak Exp $
33 */
34
35 /*
36 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
37 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
38 */
39
40 /*
41 * various SMB requests. Most of the routines merely packs data into mbufs.
42 */
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kmem.h>
46 #include <sys/proc.h>
47 #include <sys/lock.h>
48 #include <sys/socket.h>
49 #include <sys/uio.h>
50 #include <sys/random.h>
51 #include <sys/note.h>
52 #include <sys/cmn_err.h>
53
54 #include <netsmb/smb_osdep.h>
55
56 #include <netsmb/smb.h>
57 #include <netsmb/smb_conn.h>
58 #include <netsmb/smb_rq.h>
59 #include <netsmb/smb_subr.h>
60 #include <netsmb/smb_tran.h>
61
62 #define STYPE_LEN 8 /* share type strings */
63
64 /*
65 * Largest size to use with LARGE_READ/LARGE_WRITE.
66 * Specs say up to 64k data bytes, but Windows traffic
67 * uses 60k... no doubt for some good reason.
68 * (Probably to keep 4k block alignment.)
69 * XXX: Move to smb.h maybe?
70 */
71 #define SMB_MAX_LARGE_RW_SIZE (60*1024)
72
73 /*
74 * Default timeout values, all in seconds.
75 * Make these tunable (only via mdb for now).
76 */
77 int smb_timo_notice = 15;
78 int smb_timo_default = 30; /* was SMB_DEFRQTIMO */
79 int smb_timo_open = 45;
80 int smb_timo_read = 45;
81 int smb_timo_write = 60; /* was SMBWRTTIMO */
82 int smb_timo_append = 90;
83
84 static int smb_smb_read(struct smb_share *ssp, uint16_t fid,
85 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
86 static int smb_smb_write(struct smb_share *ssp, uint16_t fid,
87 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
88
89 static int smb_smb_readx(struct smb_share *ssp, uint16_t fid,
90 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
91 static int smb_smb_writex(struct smb_share *ssp, uint16_t fid,
92 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
93
94 /*
95 * Get the string representation of a share "use" type,
96 * as needed for the "service" in tree connect.
97 */
98 static const char *
99 smb_share_typename(uint32_t stype)
100 {
101 const char *p;
102
103 switch (stype) {
104 case STYPE_DISKTREE:
105 p = "A:";
106 break;
107 case STYPE_PRINTQ:
108 p = "LPT1:";
109 break;
110 case STYPE_DEVICE:
111 p = "COMM";
112 break;
113 case STYPE_IPC:
335 * Run this with a relatively short timeout. (5 sec.)
336 * We don't really care about the result here, but we
337 * do need to make sure we send this out, or we could
338 * "leak" active tree IDs on interrupt or timeout.
339 * The NOINTR_SEND flag makes this request immune to
340 * interrupt or timeout until the send is done.
341 * Also, don't reconnect for this, of course!
342 */
343 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
344 error = smb_rq_simple_timed(rqp, 5);
345 SMBSDEBUG("%d\n", error);
346 smb_rq_done(rqp);
347 ssp->ss_tid = SMB_TID_UNKNOWN;
348 return (error);
349 }
350
351 /*
352 * Modern create/open of file or directory.
353 */
354 int
355 smb_smb_ntcreate(
356 struct smb_share *ssp,
357 struct mbchain *name_mb,
358 uint32_t cr_flags, /* create flags */
359 uint32_t req_acc, /* requested access */
360 uint32_t efa, /* ext. file attrs (DOS attr +) */
361 uint32_t share_acc,
362 uint32_t open_disp, /* open disposition */
363 uint32_t createopt, /* NTCREATEX_OPTIONS_ */
364 uint32_t impersonate, /* NTCREATEX_IMPERSONATION_... */
365 struct smb_cred *scrp,
366 uint16_t *fidp, /* returned FID */
367 uint32_t *cr_act_p, /* optional create action */
368 struct smbfattr *fap) /* optional attributes */
369 {
370 struct smb_rq rq, *rqp = &rq;
371 struct smb_vc *vcp = SSTOVC(ssp);
372 struct mbchain *mbp;
373 struct mdchain *mdp;
374 struct smbfattr fa;
375 uint64_t llongint;
458 fa.fa_size = llongint;
459
460 error = md_get_uint16le(mdp, NULL); /* file type */
461 /* other stuff we don't care about */
462
463 done:
464 smb_rq_done(rqp);
465 if (error)
466 return (error);
467
468 *fidp = fid;
469 if (cr_act_p)
470 *cr_act_p = createact;
471 if (fap)
472 *fap = fa; /* struct copy */
473
474 return (0);
475 }
476
477 int
478 smb_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
479 struct smb_cred *scrp)
480 {
481 struct smb_rq rq, *rqp = &rq;
482 struct mbchain *mbp;
483 long time;
484 int error;
485
486 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp);
487 if (error)
488 return (error);
489 smb_rq_getrequest(rqp, &mbp);
490 smb_rq_wstart(rqp);
491 mb_put_uint16le(mbp, fid);
492 if (mtime) {
493 int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz;
494 smb_time_local2server(mtime, sv_tz, &time);
495 } else {
496 time = 0;
497 }
498 mb_put_uint32le(mbp, time);
583 int error;
584
585 error = smb_rq_init(rqp, SSTOCP(ssp),
586 SMB_COM_CLOSE_PRINT_FILE, scrp);
587 if (error)
588 return (error);
589 smb_rq_getrequest(rqp, &mbp);
590 smb_rq_wstart(rqp);
591 mb_put_uint16le(mbp, fid);
592 smb_rq_wend(rqp);
593 smb_rq_bstart(rqp);
594 smb_rq_bend(rqp);
595
596 /* Make sure we send but only if already connected */
597 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
598 error = smb_rq_simple(rqp);
599 smb_rq_done(rqp);
600 return (error);
601 }
602
603 /*
604 * Common function for read/write with UIO.
605 * Called by netsmb smb_usr_rw,
606 * smbfs_readvnode, smbfs_writevnode
607 */
608 int
609 smb_rwuio(struct smb_share *ssp, uint16_t fid, uio_rw_t rw,
610 uio_t *uiop, smb_cred_t *scred, int timo)
611 {
612 struct smb_vc *vcp = SSTOVC(ssp);
613 ssize_t save_resid;
614 uint32_t len, rlen, maxlen;
615 int error = 0;
616 int (*iofun)(struct smb_share *, uint16_t, uint32_t *,
617 uio_t *, smb_cred_t *, int);
618
619 /*
620 * Determine which function to use,
621 * and the transfer size per call.
622 */
623 if (SMB_DIALECT(vcp) >= SMB_DIALECT_NTLM0_12) {
624 /*
625 * Using NT LM 0.12, so readx, writex.
626 * Make sure we can represent the offset.
627 */
628 if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0 &&
629 (uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX)
630 return (EFBIG);
631
632 if (rw == UIO_READ) {
633 iofun = smb_smb_readx;
634 if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX)
635 maxlen = SMB_MAX_LARGE_RW_SIZE;
636 else
637 maxlen = vcp->vc_rxmax;
638 } else { /* UIO_WRITE */
639 iofun = smb_smb_writex;
640 if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX)
641 maxlen = SMB_MAX_LARGE_RW_SIZE;
642 else
643 maxlen = vcp->vc_wxmax;
644 }
645 } else {
646 /*
647 * Using the old SMB_READ and SMB_WRITE so
648 * we're limited to 32-bit offsets, etc.
649 * XXX: Someday, punt the old dialects.
650 */
651 if ((uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX)
652 return (EFBIG);
653
654 if (rw == UIO_READ) {
655 iofun = smb_smb_read;
656 maxlen = vcp->vc_rxmax;
657 } else { /* UIO_WRITE */
658 iofun = smb_smb_write;
659 maxlen = vcp->vc_wxmax;
660 }
661 }
662
663 save_resid = uiop->uio_resid;
664 while (uiop->uio_resid > 0) {
665 /* Lint: uio_resid may be 64-bits */
666 rlen = len = (uint32_t)min(maxlen, uiop->uio_resid);
667 error = (*iofun)(ssp, fid, &rlen, uiop, scred, timo);
668
669 /*
670 * Note: the iofun called uio_update, so
671 * not doing that here as one might expect.
672 *
673 * Quit the loop either on error, or if we
674 * transferred less then requested.
675 */
676 if (error || (rlen < len))
677 break;
678
679 timo = 0; /* only first I/O should wait */
680 }
681 if (error && (save_resid != uiop->uio_resid)) {
682 /*
683 * Stopped on an error after having
684 * successfully transferred data.
685 * Suppress this error.
686 */
687 SMBSDEBUG("error %d suppressed\n", error);
688 error = 0;
689 }
690
691 return (error);
692 }
693
694 static int
695 smb_smb_readx(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
696 uio_t *uiop, smb_cred_t *scred, int timo)
697 {
698 struct smb_rq *rqp;
699 struct mbchain *mbp;
700 struct mdchain *mdp;
701 int error;
702 uint32_t offlo, offhi, rlen;
703 uint16_t lenhi, lenlo, off, doff;
704 uint8_t wc;
705
706 lenhi = (uint16_t)(*lenp >> 16);
707 lenlo = (uint16_t)*lenp;
708 offhi = (uint32_t)(uiop->uio_loffset >> 32);
709 offlo = (uint32_t)uiop->uio_loffset;
710
711 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp);
712 if (error)
713 return (error);
714 smb_rq_getrequest(rqp, &mbp);
715 smb_rq_wstart(rqp);
716 mb_put_uint8(mbp, 0xff); /* no secondary command */
717 mb_put_uint8(mbp, 0); /* MBZ */
718 mb_put_uint16le(mbp, 0); /* offset to secondary */
719 mb_put_uint16le(mbp, fid);
720 mb_put_uint32le(mbp, offlo); /* offset (low part) */
721 mb_put_uint16le(mbp, lenlo); /* MaxCount */
722 mb_put_uint16le(mbp, 1); /* MinCount */
723 /* (only indicates blocking) */
724 mb_put_uint32le(mbp, lenhi); /* MaxCountHigh */
725 mb_put_uint16le(mbp, lenlo); /* Remaining ("obsolete") */
726 mb_put_uint32le(mbp, offhi); /* offset (high part) */
727 smb_rq_wend(rqp);
728 smb_rq_bstart(rqp);
729 smb_rq_bend(rqp);
730
731 if (timo == 0)
732 timo = smb_timo_read;
733 error = smb_rq_simple_timed(rqp, timo);
734 if (error)
735 goto out;
736
737 smb_rq_getreply(rqp, &mdp);
738 error = md_get_uint8(mdp, &wc);
739 if (error)
769 goto out;
770 }
771 /* paranoid */
772 if (rlen > *lenp) {
773 SMBSDEBUG("bad server! rlen %d, len %d\n",
774 rlen, *lenp);
775 rlen = *lenp;
776 }
777 error = md_get_uio(mdp, uiop, rlen);
778 if (error)
779 goto out;
780
781 /* Success */
782 *lenp = rlen;
783
784 out:
785 smb_rq_done(rqp);
786 return (error);
787 }
788
789 static int
790 smb_smb_writex(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
791 uio_t *uiop, smb_cred_t *scred, int timo)
792 {
793 struct smb_rq *rqp;
794 struct mbchain *mbp;
795 struct mdchain *mdp;
796 int error;
797 uint32_t offlo, offhi, rlen;
798 uint16_t lenhi, lenlo;
799 uint8_t wc;
800
801 lenhi = (uint16_t)(*lenp >> 16);
802 lenlo = (uint16_t)*lenp;
803 offhi = (uint32_t)(uiop->uio_loffset >> 32);
804 offlo = (uint32_t)uiop->uio_loffset;
805
806 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp);
807 if (error)
808 return (error);
809 smb_rq_getrequest(rqp, &mbp);
810 smb_rq_wstart(rqp);
811 mb_put_uint8(mbp, 0xff); /* no secondary command */
812 mb_put_uint8(mbp, 0); /* MBZ */
813 mb_put_uint16le(mbp, 0); /* offset to secondary */
814 mb_put_uint16le(mbp, fid);
815 mb_put_uint32le(mbp, offlo); /* offset (low part) */
816 mb_put_uint32le(mbp, 0); /* MBZ (timeout) */
817 mb_put_uint16le(mbp, 0); /* !write-thru */
818 mb_put_uint16le(mbp, 0);
819 mb_put_uint16le(mbp, lenhi);
820 mb_put_uint16le(mbp, lenlo);
821 mb_put_uint16le(mbp, 64); /* data offset from header start */
822 mb_put_uint32le(mbp, offhi); /* offset (high part) */
823 smb_rq_wend(rqp);
824 smb_rq_bstart(rqp);
825
826 mb_put_uint8(mbp, 0); /* pad byte */
827 error = mb_put_uio(mbp, uiop, *lenp);
828 if (error)
829 goto out;
830 smb_rq_bend(rqp);
831 if (timo == 0)
832 timo = smb_timo_write;
833 error = smb_rq_simple_timed(rqp, timo);
834 if (error)
842 goto out;
843 }
844 md_get_uint8(mdp, NULL); /* andx cmd */
845 md_get_uint8(mdp, NULL); /* reserved */
846 md_get_uint16le(mdp, NULL); /* andx offset */
847 md_get_uint16le(mdp, &lenlo); /* data len ret. */
848 md_get_uint16le(mdp, NULL); /* remaining */
849 error = md_get_uint16le(mdp, &lenhi);
850 if (error)
851 goto out;
852
853 /* Success */
854 rlen = (lenhi << 16) | lenlo;
855 *lenp = rlen;
856
857 out:
858 smb_rq_done(rqp);
859 return (error);
860 }
861
862 static int
863 smb_smb_read(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
864 uio_t *uiop, smb_cred_t *scred, int timo)
865 {
866 struct smb_rq *rqp;
867 struct mbchain *mbp;
868 struct mdchain *mdp;
869 int error;
870 uint32_t off32;
871 uint16_t bc, cnt, dlen, rcnt, todo;
872 uint8_t wc;
873
874 ASSERT(uiop->uio_loffset <= UINT32_MAX);
875 off32 = (uint32_t)uiop->uio_loffset;
876 ASSERT(*lenp <= UINT16_MAX);
877 cnt = (uint16_t)*lenp;
878 /* This next is an "estimate" of planned reads. */
879 todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX);
880
881 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp);
882 if (error)
883 return (error);
884 smb_rq_getrequest(rqp, &mbp);
885 smb_rq_wstart(rqp);
886 mb_put_uint16le(mbp, fid);
887 mb_put_uint16le(mbp, cnt);
888 mb_put_uint32le(mbp, off32);
889 mb_put_uint16le(mbp, todo);
890 smb_rq_wend(rqp);
891 smb_rq_bstart(rqp);
892 smb_rq_bend(rqp);
893
894 if (timo == 0)
895 timo = smb_timo_read;
896 error = smb_rq_simple_timed(rqp, timo);
897 if (error)
898 goto out;
899 smb_rq_getreply(rqp, &mdp);
900 error = md_get_uint8(mdp, &wc);
901 if (error)
902 goto out;
903 if (wc != 5) {
904 error = EBADRPC;
905 goto out;
906 }
907 md_get_uint16le(mdp, &rcnt); /* ret. count */
908 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); /* res. */
909 md_get_uint16le(mdp, &bc); /* byte count */
910 md_get_uint8(mdp, NULL); /* buffer format */
911 error = md_get_uint16le(mdp, &dlen); /* data len */
912 if (error)
913 goto out;
914 if (dlen < rcnt) {
915 SMBSDEBUG("oops: dlen=%d rcnt=%d\n",
916 (int)dlen, (int)rcnt);
917 rcnt = dlen;
918 }
919 if (rcnt == 0) {
920 *lenp = 0;
921 goto out;
922 }
923 /* paranoid */
924 if (rcnt > cnt) {
925 SMBSDEBUG("bad server! rcnt %d, cnt %d\n",
926 (int)rcnt, (int)cnt);
927 rcnt = cnt;
928 }
929 error = md_get_uio(mdp, uiop, (int)rcnt);
930 if (error)
931 goto out;
932
933 /* success */
934 *lenp = (int)rcnt;
935
936 out:
937 smb_rq_done(rqp);
938 return (error);
939 }
940
941 static int
942 smb_smb_write(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
943 uio_t *uiop, smb_cred_t *scred, int timo)
944 {
945 struct smb_rq *rqp;
946 struct mbchain *mbp;
947 struct mdchain *mdp;
948 int error;
949 uint32_t off32;
950 uint16_t cnt, rcnt, todo;
951 uint8_t wc;
952
953 ASSERT(uiop->uio_loffset <= UINT32_MAX);
954 off32 = (uint32_t)uiop->uio_loffset;
955 ASSERT(*lenp <= UINT16_MAX);
956 cnt = (uint16_t)*lenp;
957 /* This next is an "estimate" of planned writes. */
958 todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX);
959
960 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp);
961 if (error)
962 return (error);
963 smb_rq_getrequest(rqp, &mbp);
964 smb_rq_wstart(rqp);
965 mb_put_uint16le(mbp, fid);
966 mb_put_uint16le(mbp, cnt);
967 mb_put_uint32le(mbp, off32);
968 mb_put_uint16le(mbp, todo);
969 smb_rq_wend(rqp);
970 smb_rq_bstart(rqp);
971 mb_put_uint8(mbp, SMB_DT_DATA);
972 mb_put_uint16le(mbp, cnt);
973
974 error = mb_put_uio(mbp, uiop, *lenp);
975 if (error)
976 goto out;
977 smb_rq_bend(rqp);
978 if (timo == 0)
979 timo = smb_timo_write;
980 error = smb_rq_simple_timed(rqp, timo);
981 if (error)
982 goto out;
983 smb_rq_getreply(rqp, &mdp);
984 error = md_get_uint8(mdp, &wc);
985 if (error)
986 goto out;
987 if (wc != 1) {
988 error = EBADRPC;
989 goto out;
990 }
991 error = md_get_uint16le(mdp, &rcnt);
992 if (error)
993 goto out;
994 *lenp = rcnt;
995
996 out:
997 smb_rq_done(rqp);
998 return (error);
999 }
1000
1001
1002 static u_int32_t smbechoes = 0;
1003
1004 int
1005 smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo)
1006 {
1007 struct smb_rq *rqp;
1008 struct mbchain *mbp;
1009 int error;
1010
1011 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp);
1012 if (error)
1013 return (error);
1014 mbp = &rqp->sr_rq;
1015 smb_rq_wstart(rqp);
1016 mb_put_uint16le(mbp, 1); /* echo count */
1017 smb_rq_wend(rqp);
1018 smb_rq_bstart(rqp);
1019 mb_put_uint32le(mbp, atomic_inc_32_nv(&smbechoes));
1020 smb_rq_bend(rqp);
1021 /*
1022 * Note: the IOD calls this, so
1023 * this request must not wait for
1024 * connection state changes, etc.
1025 */
1026 rqp->sr_flags |= SMBR_NORECONNECT;
1027 error = smb_rq_simple_timed(rqp, timo);
1028 SMBSDEBUG("%d\n", error);
1029 smb_rq_done(rqp);
1030 return (error);
1031 }
|
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: smb_smb.c,v 1.35.100.2 2005/06/02 00:55:39 lindak Exp $
33 */
34
35 /*
36 * Portions Copyright (C) 2001 - 2014 Apple Inc. All rights reserved.
37 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
38 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
39 */
40
41 /*
42 * various SMB requests. Most of the routines merely packs data into mbufs.
43 */
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kmem.h>
47 #include <sys/proc.h>
48 #include <sys/lock.h>
49 #include <sys/socket.h>
50 #include <sys/uio.h>
51 #include <sys/random.h>
52 #include <sys/note.h>
53 #include <sys/errno.h>
54 #include <sys/cmn_err.h>
55
56 #include <netsmb/smb_osdep.h>
57
58 #include <netsmb/smb.h>
59 #include <netsmb/smb_conn.h>
60 #include <netsmb/smb_rq.h>
61 #include <netsmb/smb_subr.h>
62 #include <netsmb/smb_tran.h>
63
64 #define STYPE_LEN 8 /* share type strings */
65
66 struct smb_dialect {
67 int d_id;
68 const char *d_name;
69 };
70
71 static struct smb_dialect smb_dialects[3] = {
72 {SMB_DIALECT_NTLM0_12, "NT LANMAN 1.0"},
73 {SMB_DIALECT_NTLM0_12, "NT LM 0.12"},
74 #define NDIALECT_SMB1 2
75 {SMB_DIALECT_SMB2_FF, "SMB 2.???"},
76 #define NDIALECT_SMB2 3
77 };
78
79 static const uint32_t smb_clnt_caps_mask =
80 SMB_CAP_UNICODE |
81 SMB_CAP_LARGE_FILES |
82 SMB_CAP_NT_SMBS |
83 SMB_CAP_STATUS32 |
84 SMB_CAP_EXT_SECURITY;
85
86 /*
87 * Default timeout values, all in seconds.
88 * Make these tunable (only via mdb for now).
89 */
90 int smb_timo_notice = 15;
91 int smb_timo_default = 30; /* was SMB_DEFRQTIMO */
92 int smb_timo_logon = 45;
93 int smb_timo_open = 45;
94 int smb_timo_read = 45;
95 int smb_timo_write = 60; /* was SMBWRTTIMO */
96 int smb_timo_append = 90;
97
98 int
99 smb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
100 {
101 smb_sopt_t *sv = &vcp->vc_sopt;
102 smbioc_ssn_work_t *wk = &vcp->vc_work;
103 struct smb_rq *rqp = NULL;
104 struct mbchain *mbp = NULL;
105 struct mdchain *mdp = NULL;
106 struct smb_dialect *dp;
107 int err, sblen, tlen;
108 uint8_t wc, eklen;
109 uint16_t dindex, bc;
110 uint16_t ndialects;
111 boolean_t will_sign = B_FALSE;
112
113 /*
114 * Initialize: vc_hflags and vc_hflags2.
115 * Note: vcp->vc_hflags* are copied into the
116 * (per request) rqp->rq_hflags* by smb_rq_init.
117 *
118 * Like Windows, set FLAGS2_UNICODE in our first request,
119 * even though technically we don't yet know whether the
120 * server supports Unicode. Will clear this flag below
121 * if we find out it doesn't. Need to do this because
122 * some servers reject all non-Unicode requests.
123 */
124 vcp->vc_hflags =
125 SMB_FLAGS_CASELESS |
126 SMB_FLAGS_CANONICAL_PATHNAMES;
127 vcp->vc_hflags2 =
128 SMB_FLAGS2_KNOWS_LONG_NAMES |
129 SMB_FLAGS2_KNOWS_EAS |
130 SMB_FLAGS2_IS_LONG_NAME |
131 SMB_FLAGS2_EXT_SEC |
132 SMB_FLAGS2_ERR_STATUS |
133 SMB_FLAGS2_UNICODE;
134
135 /*
136 * The initial UID needs to be zero,
137 */
138 vcp->vc_smbuid = 0;
139
140 /*
141 * (Re)init negotiated values
142 */
143 bzero(sv, sizeof (*sv));
144 sv->sv_maxmux = 1;
145 sv->sv_maxvcs = 1;
146 sv->sv_maxtx = 1024;
147
148 /*
149 * Should we offer the magic SMB2 dialect?
150 */
151 if (vcp->vc_ssn.ssn_maxver >= SMB2_DIALECT_BASE)
152 ndialects = NDIALECT_SMB2;
153 else
154 ndialects = NDIALECT_SMB1;
155
156 err = smb_rq_alloc(VCTOCP(vcp), SMB_COM_NEGOTIATE, scred, &rqp);
157 if (err)
158 return (err);
159
160 /*
161 * Build the SMB request.
162 */
163 smb_rq_getrequest(rqp, &mbp);
164 smb_rq_wstart(rqp);
165 smb_rq_wend(rqp);
166 smb_rq_bstart(rqp);
167 for (dindex = 0; dindex < ndialects; dindex++) {
168 dp = &smb_dialects[dindex];
169 mb_put_uint8(mbp, SMB_DT_DIALECT);
170 tlen = strlen(dp->d_name) + 1;
171 mb_put_mem(mbp, dp->d_name, tlen, MB_MSYSTEM);
172 }
173 smb_rq_bend(rqp);
174
175 /*
176 * Do the OTW call.
177 */
178 err = smb_rq_internal(rqp, smb_timo_default);
179 /*
180 * If it's an SMB1-to-SMB2 negotiate response,
181 * call the special handler and then skip the
182 * whole rest of this function.
183 */
184 if (err == EPROTO) {
185 err = smb2_parse_smb1nego_resp(rqp);
186 smb_rq_done(rqp);
187 return (err);
188 }
189 if (err) {
190 SMBSDEBUG("smb_rq_internal, err %d", err);
191 goto errout;
192 }
193 /* Should only get status success. */
194 if (rqp->sr_error != NT_STATUS_SUCCESS) {
195 err = ENOTSUP;
196 goto errout;
197 }
198
199 /*
200 * Decode the response
201 *
202 * Comments to right show names as described in
203 * The Microsoft SMB Protocol spec. [MS-SMB]
204 * section 2.2.3
205 */
206 smb_rq_getreply(rqp, &mdp);
207 (void) md_get_uint8(mdp, &wc);
208 err = md_get_uint16le(mdp, &dindex);
209 if (err != 0)
210 goto errout;
211 if (dindex >= ndialects) {
212 SMBERROR("Invalid dialect index from server: %s\n",
213 vcp->vc_srvname);
214 err = EBADRPC;
215 goto errout;
216 }
217 dp = smb_dialects + dindex;
218 sv->sv_proto = dp->d_id;
219 SMBSDEBUG("Dialect %s", dp->d_name);
220 if (dp->d_id < SMB_DIALECT_NTLM0_12) {
221 SMBSDEBUG("old dialect %s", dp->d_name);
222 goto errout;
223 }
224 if (wc != 17) {
225 SMBSDEBUG("bad wc %d", (int)wc);
226 goto errout;
227 }
228 md_get_uint8(mdp, &sv->sv_sm); /* SecurityMode */
229 md_get_uint16le(mdp, &sv->sv_maxmux); /* MaxMpxCount */
230 md_get_uint16le(mdp, &sv->sv_maxvcs); /* MaxCountVCs */
231 md_get_uint32le(mdp, &sv->sv_maxtx); /* MaxBufferSize */
232 md_get_uint32le(mdp, &sv->sv_maxraw); /* MaxRawSize */
233 md_get_uint32le(mdp, &sv->sv_skey); /* SessionKey */
234 md_get_uint32le(mdp, &sv->sv_caps); /* Capabilities */
235 md_get_mem(mdp, NULL, 8, MB_MSYSTEM); /* SystemTime(s) */
236 md_get_uint16le(mdp, (uint16_t *)&sv->sv_tz);
237 md_get_uint8(mdp, &eklen); /* EncryptionKeyLength */
238 err = md_get_uint16le(mdp, &bc); /* ByteCount */
239 if (err)
240 goto errout;
241
242 /* BEGIN CSTYLED */
243 /*
244 * Will we do SMB signing? Or block the connection?
245 * The table below describes this logic. References:
246 * [Windows Server Protocols: MS-SMB, sec. 3.2.4.2.3]
247 * http://msdn.microsoft.com/en-us/library/cc212511.aspx
248 * http://msdn.microsoft.com/en-us/library/cc212929.aspx
249 *
250 * Srv/Cli | Required | Enabled | If Required | Disabled
251 * ------------+----------+------------+-------------+-----------
252 * Required | Signed | Signed | Signed | Blocked [1]
253 * ------------+----------+------------+-------------+-----------
254 * Enabled | Signed | Signed | Not Signed | Not Signed
255 * ------------+----------+------------+-------------+-----------
256 * If Required | Signed | Not Signed | Not Signed | Not Signed
257 * ------------+----------+------------+-------------+-----------
258 * Disabled | Blocked | Not Signed | Not Signed | Not Signed
259 *
260 * [1] Like Windows 2003 and later, we don't really implement
261 * the "Disabled" setting. Instead we implement "If Required",
262 * so we always sign if the server requires signing.
263 */
264 /* END CSTYLED */
265
266 if (sv->sv_sm & SMB_SM_SIGS_REQUIRE) {
267 /*
268 * Server requires signing. We will sign,
269 * even if local setting is "disabled".
270 */
271 will_sign = B_TRUE;
272 } else if (sv->sv_sm & SMB_SM_SIGS) {
273 /*
274 * Server enables signing (client's option).
275 * If enabled locally, do signing.
276 */
277 if (vcp->vc_vopt & SMBVOPT_SIGNING_ENABLED)
278 will_sign = B_TRUE;
279 /* else not signing. */
280 } else {
281 /*
282 * Server does not support signing.
283 * If we "require" it, bail now.
284 */
285 if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) {
286 SMBERROR("Client requires signing "
287 "but server has it disabled.");
288 err = EBADRPC;
289 goto errout;
290 }
291 }
292
293 /*
294 * Anonymous sessions can't sign.
295 */
296 if (vcp->vc_vopt & SMBVOPT_ANONYMOUS) {
297 will_sign = B_FALSE;
298 }
299
300 SMBSDEBUG("Security signatures: %d", (int)will_sign);
301 if (will_sign) {
302 vcp->vc_flags |= SMBV_SIGNING;
303 vcp->vc_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
304
305 /*
306 * MS-SMB 2.2.4.5 says that when SMB signing is enabled,
307 * we should NOT use "large read/write" even though the
308 * server might offer those capabilities.
309 */
310 sv->sv_caps &= ~(SMB_CAP_LARGE_READX | SMB_CAP_LARGE_WRITEX);
311 }
312
313 /* See comment above re. FLAGS2_UNICODE */
314 if ((sv->sv_caps & SMB_CAP_UNICODE) != 0)
315 vcp->vc_flags |= SMBV_UNICODE;
316 else
317 vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE;
318
319 if ((sv->sv_caps & SMB_CAP_STATUS32) == 0) {
320 /* They don't do NT error codes. */
321 vcp->vc_hflags2 &= ~SMB_FLAGS2_ERR_STATUS;
322 }
323
324 /*
325 * Warn if they don't support SMB_CAP_NT_SMBS
326 * (We'll try to use NtCreate anyway)
327 */
328 if ((sv->sv_caps & SMB_CAP_NT_SMBS) == 0) {
329 cmn_err(CE_NOTE, "%s does not support SMB_CAP_NT_SMBS",
330 vcp->vc_srvname);
331 }
332
333 /*
334 * The rest of the message varies depending on
335 * whether we've negotiated "extended security".
336 *
337 * With extended security, we have:
338 * Server_GUID (length 16)
339 * Security_BLOB
340 * Otherwise we have:
341 * EncryptionKey (length is eklen)
342 * PrimaryDomain
343 */
344 if (sv->sv_caps & SMB_CAP_EXT_SECURITY) {
345 SMBSDEBUG("Ext.Security: yes");
346
347 /*
348 * Skip the server GUID.
349 */
350 err = md_get_mem(mdp, NULL, SMB_GUIDLEN, MB_MSYSTEM);
351 if (err)
352 goto errout;
353 /*
354 * Remainder is the security blob.
355 * Note: eklen "must be ignored" [MS-SMB]
356 */
357 sblen = (int)bc - SMB_GUIDLEN;
358 if (sblen < 0)
359 goto errout;
360 /* Security blob (hint) is next */
361 } else {
362 SMBSDEBUG("Ext.Security: no");
363 err = ENOTSUP;
364 goto errout;
365 }
366
367 /*
368 * Copy the security blob out to user space.
369 * Buffer addr,size in vc_auth_rbuf,rlen
370 */
371 if (wk->wk_u_auth_rlen < sblen) {
372 SMBSDEBUG("vc_auth_rbuf too small");
373 /* Give caller required size. */
374 wk->wk_u_auth_rlen = sblen;
375 err = EMSGSIZE;
376 goto errout;
377 }
378 wk->wk_u_auth_rlen = sblen;
379 err = md_get_mem(mdp, wk->wk_u_auth_rbuf.lp_ptr, sblen, MB_MUSER);
380 if (err)
381 goto errout;
382
383 /*
384 * A few sanity checks on what we received,
385 * becuse we will send these in ssnsetup.
386 *
387 * Maximum outstanding requests (we care),
388 * and Max. VCs (we only use one). Also,
389 * MaxBufferSize lower limit per spec.
390 */
391 if (sv->sv_maxmux < 1)
392 sv->sv_maxmux = 1;
393 if (sv->sv_maxvcs < 1)
394 sv->sv_maxvcs = 1;
395 if (sv->sv_maxtx < 1024)
396 sv->sv_maxtx = 1024;
397
398 /*
399 * Maximum transfer size.
400 * Sanity checks:
401 *
402 * Let's be conservative about an upper limit here.
403 * Win2k uses 16644 (and others) so 32k should be a
404 * reasonable sanity limit for this value.
405 *
406 * Note that this limit does NOT affect READX/WRITEX
407 * with CAP_LARGE_..., which we nearly always use.
408 */
409 vcp->vc_txmax = sv->sv_maxtx;
410 if (vcp->vc_txmax > 0x8000)
411 vcp->vc_txmax = 0x8000;
412
413 /*
414 * Max read/write sizes, WITHOUT overhead.
415 * This is just the payload size, so we must
416 * leave room for the SMB headers, etc.
417 * This is just the ct_txmax value, but
418 * reduced and rounded down. Tricky bit:
419 *
420 * Servers typically give us a value that's
421 * some nice "round" number, i.e 0x4000 plus
422 * some overhead, i.e. Win2k: 16644==0x4104
423 * Subtract for the SMB header (32) and the
424 * SMB command word and byte vectors (34?),
425 * then round down to a 512 byte multiple.
426 */
427 tlen = vcp->vc_txmax - 68;
428 tlen &= 0xFE00;
429
430 vcp->vc_rwmax = tlen;
431 vcp->vc_rxmax = tlen;
432 vcp->vc_wxmax = tlen;
433
434 /*
435 * Most of the "capability" bits we offer in session setup
436 * are just copied from those offered by the server.
437 */
438 sv->sv_caps &= smb_clnt_caps_mask;
439
440 smb_rq_done(rqp);
441 return (0);
442
443 errout:
444 smb_rq_done(rqp);
445 if (err == 0)
446 err = EBADRPC;
447 return (err);
448 }
449
450 static const char NativeOS[] = "illumos";
451 static const char LanMan[] = "NETSMB";
452
453 int
454 smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred)
455 {
456 smb_sopt_t *sv = &vcp->vc_sopt;
457 smbioc_ssn_work_t *wk = &vcp->vc_work;
458 struct smb_rq *rqp = NULL;
459 struct mbchain *mbp = NULL;
460 struct mdchain *mdp = NULL;
461 char *sb;
462 int err, ret;
463 uint32_t caps;
464 uint16_t action, bc, sblen;
465 uint8_t wc;
466
467 caps = sv->sv_caps;
468 sb = wk->wk_u_auth_wbuf.lp_ptr;
469 sblen = (uint16_t)wk->wk_u_auth_wlen;
470
471 err = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX,
472 scred, &rqp);
473 if (err != 0) {
474 ret = err;
475 goto out;
476 }
477
478 /*
479 * Build the SMB Session Setup request.
480 * Always extended security form.
481 */
482 mbp = &rqp->sr_rq;
483 smb_rq_wstart(rqp);
484 mb_put_uint16le(mbp, 0xff); /* 0: AndXCommand */
485 mb_put_uint16le(mbp, 0); /* 1: AndXOffset */
486 mb_put_uint16le(mbp, sv->sv_maxtx); /* 2: MaxBufferSize */
487 mb_put_uint16le(mbp, sv->sv_maxmux); /* 3: MaxMpxCount */
488 mb_put_uint16le(mbp, 1); /* 4: VcNumber */
489 mb_put_uint32le(mbp, sv->sv_skey); /* 5,6: Session Key */
490 mb_put_uint16le(mbp, sblen); /* 7: Sec. Blob Len */
491 mb_put_uint32le(mbp, 0); /* 8,9: reserved */
492 mb_put_uint32le(mbp, caps); /* 10,11: Capabilities */
493 smb_rq_wend(rqp); /* 12: Byte Count */
494 smb_rq_bstart(rqp);
495 err = mb_put_mem(mbp, sb, sblen, MB_MUSER);
496 if (err != 0) {
497 ret = err;
498 goto out;
499 }
500 (void) smb_put_dstring(mbp, vcp, NativeOS, SMB_CS_NONE);
501 (void) smb_put_dstring(mbp, vcp, LanMan, SMB_CS_NONE);
502 smb_rq_bend(rqp);
503
504 /*
505 * Run the request. The return value here should be the
506 * return from this function, unless we fail decoding.
507 * Note: NT_STATUS_MORE_PROCESSING_REQUIRED is OK, and
508 * the caller expects EINPROGRESS for that case.
509 */
510 ret = smb_rq_internal(rqp, smb_timo_logon);
511 if (ret != 0)
512 goto out;
513 switch (rqp->sr_error) {
514 case NT_STATUS_SUCCESS:
515 break;
516 case NT_STATUS_MORE_PROCESSING_REQUIRED:
517 /* Keep going, but return... */
518 ret = EINPROGRESS;
519 break;
520 default:
521 ret = EAUTH;
522 goto out;
523 }
524
525 if (vcp->vc_smbuid == 0)
526 vcp->vc_smbuid = rqp->sr_rpuid;
527
528 /*
529 * Parse the reply
530 */
531 smb_rq_getreply(rqp, &mdp);
532
533 err = md_get_uint8(mdp, &wc);
534 if (err != 0)
535 wc = 0;
536 if (wc != 4) {
537 ret = EBADRPC;
538 goto out;
539 }
540 md_get_uint16le(mdp, NULL); /* secondary cmd */
541 md_get_uint16le(mdp, NULL); /* andxoffset */
542 md_get_uint16le(mdp, &action); /* action XXX */
543 md_get_uint16le(mdp, &sblen); /* sec. blob len */
544 md_get_uint16le(mdp, &bc); /* byte count */
545 /*
546 * Get the security blob, after
547 * sanity-checking the length.
548 */
549 if (sblen == 0 || sblen > bc) {
550 ret = EBADRPC;
551 goto out;
552 }
553 if (sblen > wk->wk_u_auth_rlen) {
554 ret = EBADRPC;
555 goto out;
556 }
557 sb = wk->wk_u_auth_rbuf.lp_ptr;
558 err = md_get_mem(mdp, sb, sblen, MB_MUSER);
559 if (err) {
560 ret = EBADRPC;
561 goto out;
562 }
563
564 /*
565 * Native OS, LANMGR, & Domain follow here.
566 * We don't need them and don't parse them.
567 */
568
569 out:
570 if (err != 0 && err != EINPROGRESS) {
571 /* UID no longer valid. */
572 vcp->vc_smbuid = 0;
573 }
574 if (rqp)
575 smb_rq_done(rqp);
576
577 return (ret);
578 }
579
580 int
581 smb_smb_logoff(struct smb_vc *vcp, struct smb_cred *scred)
582 {
583 struct smb_rq *rqp;
584 struct mbchain *mbp;
585 int error;
586
587 if (vcp->vc_smbuid == SMB_UID_UNKNOWN)
588 return (0);
589
590 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_LOGOFF_ANDX, scred, &rqp);
591 if (error)
592 return (error);
593 mbp = &rqp->sr_rq;
594 smb_rq_wstart(rqp);
595 mb_put_uint8(mbp, 0xff);
596 mb_put_uint8(mbp, 0);
597 mb_put_uint16le(mbp, 0);
598 smb_rq_wend(rqp);
599 smb_rq_bstart(rqp);
600 smb_rq_bend(rqp);
601
602 /*
603 * Run this with a relatively short timeout. (5 sec.)
604 * We don't really care about the result here.
605 * Also, don't reconnect for this, of course!
606 */
607 rqp->sr_flags |= SMBR_NORECONNECT;
608 error = smb_rq_internal(rqp, 5);
609 smb_rq_done(rqp);
610 return (error);
611 }
612
613 /*
614 * Get the string representation of a share "use" type,
615 * as needed for the "service" in tree connect.
616 */
617 static const char *
618 smb_share_typename(uint32_t stype)
619 {
620 const char *p;
621
622 switch (stype) {
623 case STYPE_DISKTREE:
624 p = "A:";
625 break;
626 case STYPE_PRINTQ:
627 p = "LPT1:";
628 break;
629 case STYPE_DEVICE:
630 p = "COMM";
631 break;
632 case STYPE_IPC:
854 * Run this with a relatively short timeout. (5 sec.)
855 * We don't really care about the result here, but we
856 * do need to make sure we send this out, or we could
857 * "leak" active tree IDs on interrupt or timeout.
858 * The NOINTR_SEND flag makes this request immune to
859 * interrupt or timeout until the send is done.
860 * Also, don't reconnect for this, of course!
861 */
862 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
863 error = smb_rq_simple_timed(rqp, 5);
864 SMBSDEBUG("%d\n", error);
865 smb_rq_done(rqp);
866 ssp->ss_tid = SMB_TID_UNKNOWN;
867 return (error);
868 }
869
870 /*
871 * Modern create/open of file or directory.
872 */
873 int
874 smb1_smb_ntcreate(
875 struct smb_share *ssp,
876 struct mbchain *name_mb,
877 uint32_t cr_flags, /* create flags */
878 uint32_t req_acc, /* requested access */
879 uint32_t efa, /* ext. file attrs (DOS attr +) */
880 uint32_t share_acc,
881 uint32_t open_disp, /* open disposition */
882 uint32_t createopt, /* NTCREATEX_OPTIONS_ */
883 uint32_t impersonate, /* NTCREATEX_IMPERSONATION_... */
884 struct smb_cred *scrp,
885 uint16_t *fidp, /* returned FID */
886 uint32_t *cr_act_p, /* optional create action */
887 struct smbfattr *fap) /* optional attributes */
888 {
889 struct smb_rq rq, *rqp = &rq;
890 struct smb_vc *vcp = SSTOVC(ssp);
891 struct mbchain *mbp;
892 struct mdchain *mdp;
893 struct smbfattr fa;
894 uint64_t llongint;
977 fa.fa_size = llongint;
978
979 error = md_get_uint16le(mdp, NULL); /* file type */
980 /* other stuff we don't care about */
981
982 done:
983 smb_rq_done(rqp);
984 if (error)
985 return (error);
986
987 *fidp = fid;
988 if (cr_act_p)
989 *cr_act_p = createact;
990 if (fap)
991 *fap = fa; /* struct copy */
992
993 return (0);
994 }
995
996 int
997 smb1_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
998 struct smb_cred *scrp)
999 {
1000 struct smb_rq rq, *rqp = &rq;
1001 struct mbchain *mbp;
1002 long time;
1003 int error;
1004
1005 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp);
1006 if (error)
1007 return (error);
1008 smb_rq_getrequest(rqp, &mbp);
1009 smb_rq_wstart(rqp);
1010 mb_put_uint16le(mbp, fid);
1011 if (mtime) {
1012 int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz;
1013 smb_time_local2server(mtime, sv_tz, &time);
1014 } else {
1015 time = 0;
1016 }
1017 mb_put_uint32le(mbp, time);
1102 int error;
1103
1104 error = smb_rq_init(rqp, SSTOCP(ssp),
1105 SMB_COM_CLOSE_PRINT_FILE, scrp);
1106 if (error)
1107 return (error);
1108 smb_rq_getrequest(rqp, &mbp);
1109 smb_rq_wstart(rqp);
1110 mb_put_uint16le(mbp, fid);
1111 smb_rq_wend(rqp);
1112 smb_rq_bstart(rqp);
1113 smb_rq_bend(rqp);
1114
1115 /* Make sure we send but only if already connected */
1116 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
1117 error = smb_rq_simple(rqp);
1118 smb_rq_done(rqp);
1119 return (error);
1120 }
1121
1122 int
1123 smb_smb_readx(smb_fh_t *fhp, uint32_t *lenp,
1124 uio_t *uiop, smb_cred_t *scred, int timo)
1125 {
1126 struct smb_share *ssp = FHTOSS(fhp);
1127 struct smb_rq *rqp;
1128 struct mbchain *mbp;
1129 struct mdchain *mdp;
1130 int error;
1131 uint32_t offlo, offhi, rlen;
1132 uint16_t lenhi, lenlo, off, doff;
1133 uint8_t wc;
1134
1135 lenhi = (uint16_t)(*lenp >> 16);
1136 lenlo = (uint16_t)*lenp;
1137 offhi = (uint32_t)(uiop->uio_loffset >> 32);
1138 offlo = (uint32_t)uiop->uio_loffset;
1139
1140 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp);
1141 if (error)
1142 return (error);
1143 smb_rq_getrequest(rqp, &mbp);
1144 smb_rq_wstart(rqp);
1145 mb_put_uint8(mbp, 0xff); /* no secondary command */
1146 mb_put_uint8(mbp, 0); /* MBZ */
1147 mb_put_uint16le(mbp, 0); /* offset to secondary */
1148 mb_put_uint16le(mbp, fhp->fh_fid1);
1149 mb_put_uint32le(mbp, offlo); /* offset (low part) */
1150 mb_put_uint16le(mbp, lenlo); /* MaxCount */
1151 mb_put_uint16le(mbp, 1); /* MinCount */
1152 /* (only indicates blocking) */
1153 mb_put_uint32le(mbp, lenhi); /* MaxCountHigh */
1154 mb_put_uint16le(mbp, lenlo); /* Remaining ("obsolete") */
1155 mb_put_uint32le(mbp, offhi); /* offset (high part) */
1156 smb_rq_wend(rqp);
1157 smb_rq_bstart(rqp);
1158 smb_rq_bend(rqp);
1159
1160 if (timo == 0)
1161 timo = smb_timo_read;
1162 error = smb_rq_simple_timed(rqp, timo);
1163 if (error)
1164 goto out;
1165
1166 smb_rq_getreply(rqp, &mdp);
1167 error = md_get_uint8(mdp, &wc);
1168 if (error)
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 error = md_get_uio(mdp, uiop, rlen);
1207 if (error)
1208 goto out;
1209
1210 /* Success */
1211 *lenp = rlen;
1212
1213 out:
1214 smb_rq_done(rqp);
1215 return (error);
1216 }
1217
1218 int
1219 smb_smb_writex(smb_fh_t *fhp, uint32_t *lenp,
1220 uio_t *uiop, smb_cred_t *scred, int timo)
1221 {
1222 struct smb_share *ssp = FHTOSS(fhp);
1223 struct smb_rq *rqp;
1224 struct mbchain *mbp;
1225 struct mdchain *mdp;
1226 int error;
1227 uint32_t offlo, offhi, rlen;
1228 uint16_t lenhi, lenlo;
1229 uint8_t wc;
1230
1231 lenhi = (uint16_t)(*lenp >> 16);
1232 lenlo = (uint16_t)*lenp;
1233 offhi = (uint32_t)(uiop->uio_loffset >> 32);
1234 offlo = (uint32_t)uiop->uio_loffset;
1235
1236 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp);
1237 if (error)
1238 return (error);
1239 smb_rq_getrequest(rqp, &mbp);
1240 smb_rq_wstart(rqp);
1241 mb_put_uint8(mbp, 0xff); /* no secondary command */
1242 mb_put_uint8(mbp, 0); /* MBZ */
1243 mb_put_uint16le(mbp, 0); /* offset to secondary */
1244 mb_put_uint16le(mbp, fhp->fh_fid1);
1245 mb_put_uint32le(mbp, offlo); /* offset (low part) */
1246 mb_put_uint32le(mbp, 0); /* MBZ (timeout) */
1247 mb_put_uint16le(mbp, 0); /* !write-thru */
1248 mb_put_uint16le(mbp, 0);
1249 mb_put_uint16le(mbp, lenhi);
1250 mb_put_uint16le(mbp, lenlo);
1251 mb_put_uint16le(mbp, 64); /* data offset from header start */
1252 mb_put_uint32le(mbp, offhi); /* offset (high part) */
1253 smb_rq_wend(rqp);
1254 smb_rq_bstart(rqp);
1255
1256 mb_put_uint8(mbp, 0); /* pad byte */
1257 error = mb_put_uio(mbp, uiop, *lenp);
1258 if (error)
1259 goto out;
1260 smb_rq_bend(rqp);
1261 if (timo == 0)
1262 timo = smb_timo_write;
1263 error = smb_rq_simple_timed(rqp, timo);
1264 if (error)
1272 goto out;
1273 }
1274 md_get_uint8(mdp, NULL); /* andx cmd */
1275 md_get_uint8(mdp, NULL); /* reserved */
1276 md_get_uint16le(mdp, NULL); /* andx offset */
1277 md_get_uint16le(mdp, &lenlo); /* data len ret. */
1278 md_get_uint16le(mdp, NULL); /* remaining */
1279 error = md_get_uint16le(mdp, &lenhi);
1280 if (error)
1281 goto out;
1282
1283 /* Success */
1284 rlen = (lenhi << 16) | lenlo;
1285 *lenp = rlen;
1286
1287 out:
1288 smb_rq_done(rqp);
1289 return (error);
1290 }
1291
1292
1293 static u_int32_t smbechoes = 0;
1294
1295 /*
1296 * Note: the IOD calls this, so this request must not wait for
1297 * connection state changes, etc. (uses smb_rq_internal)
1298 */
1299 int
1300 smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo)
1301 {
1302 struct smb_rq *rqp;
1303 struct mbchain *mbp;
1304 int error;
1305
1306 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp);
1307 if (error)
1308 return (error);
1309 mbp = &rqp->sr_rq;
1310 smb_rq_wstart(rqp);
1311 mb_put_uint16le(mbp, 1); /* echo count */
1312 smb_rq_wend(rqp);
1313 smb_rq_bstart(rqp);
1314 mb_put_uint32le(mbp, atomic_inc_32_nv(&smbechoes));
1315 smb_rq_bend(rqp);
1316 rqp->sr_flags |= SMBR_NORECONNECT;
1317 error = smb_rq_internal(rqp, timo);
1318 SMBSDEBUG("%d\n", error);
1319 smb_rq_done(rqp);
1320 return (error);
1321 }
|