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 }
 |