The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netsmb/smb_smb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000-2001 Boris Popov
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *    This product includes software developed by Boris Popov.
   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 
   33 /*
   34  * various SMB requests. Most of the routines merely packs data into mbufs.
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD: releng/5.2/sys/netsmb/smb_smb.c 116189 2003-06-11 05:37:42Z obrien $");
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/kernel.h>
   43 #include <sys/malloc.h>
   44 #include <sys/proc.h>
   45 #include <sys/lock.h>
   46 #include <sys/sysctl.h>
   47 #include <sys/socket.h>
   48 #include <sys/uio.h>
   49 
   50 #include <sys/iconv.h>
   51 
   52 #include <netsmb/smb.h>
   53 #include <netsmb/smb_subr.h>
   54 #include <netsmb/smb_rq.h>
   55 #include <netsmb/smb_conn.h>
   56 #include <netsmb/smb_tran.h>
   57 
   58 struct smb_dialect {
   59         int             d_id;
   60         const char *    d_name;
   61 };
   62 
   63 static struct smb_dialect smb_dialects[] = {
   64         {SMB_DIALECT_CORE,      "PC NETWORK PROGRAM 1.0"},
   65         {SMB_DIALECT_COREPLUS,  "MICROSOFT NETWORKS 1.03"},
   66         {SMB_DIALECT_LANMAN1_0, "MICROSOFT NETWORKS 3.0"},
   67         {SMB_DIALECT_LANMAN1_0, "LANMAN1.0"},
   68         {SMB_DIALECT_LANMAN2_0, "LM1.2X002"},
   69         {SMB_DIALECT_LANMAN2_0, "Samba"},
   70         {SMB_DIALECT_NTLM0_12,  "NT LANMAN 1.0"},
   71         {SMB_DIALECT_NTLM0_12,  "NT LM 0.12"},
   72         {-1,                    NULL}
   73 };
   74 
   75 #define SMB_DIALECT_MAX (sizeof(smb_dialects) / sizeof(struct smb_dialect) - 2)
   76 
   77 static u_int32_t
   78 smb_vc_maxread(struct smb_vc *vcp)
   79 {
   80         /*
   81          * Specs say up to 64k data bytes, but Windows traffic
   82          * uses 60k... no doubt for some good reason.
   83          */
   84         if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX)
   85                 return (60*1024);
   86         else
   87                 return (vcp->vc_sopt.sv_maxtx);
   88 }
   89 
   90 static u_int32_t
   91 smb_vc_maxwrite(struct smb_vc *vcp)
   92 {
   93         /*
   94          * Specs say up to 64k data bytes, but Windows traffic
   95          * uses 60k... probably for some good reason.
   96          */
   97         if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX)
   98                 return (60*1024);
   99         else
  100                 return (vcp->vc_sopt.sv_maxtx);
  101 }
  102 
  103 static int
  104 smb_smb_nomux(struct smb_vc *vcp, struct smb_cred *scred, const char *name)
  105 {
  106         if (scred->scr_td->td_proc == vcp->vc_iod->iod_p)
  107                 return 0;
  108         SMBERROR("wrong function called(%s)\n", name);
  109         return EINVAL;
  110 }
  111 
  112 int
  113 smb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
  114 {
  115         struct smb_dialect *dp;
  116         struct smb_sopt *sp = NULL;
  117         struct smb_rq *rqp;
  118         struct mbchain *mbp;
  119         struct mdchain *mdp;
  120         u_int8_t wc, stime[8], sblen;
  121         u_int16_t dindex, tw, tw1, swlen, bc;
  122         int error, maxqsz;
  123 
  124         if (smb_smb_nomux(vcp, scred, __func__) != 0)
  125                 return EINVAL;
  126         vcp->vc_hflags = 0;
  127         vcp->vc_hflags2 = 0;
  128         vcp->obj.co_flags &= ~(SMBV_ENCRYPT);
  129         sp = &vcp->vc_sopt;
  130         bzero(sp, sizeof(struct smb_sopt));
  131         error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_NEGOTIATE, scred, &rqp);
  132         if (error)
  133                 return error;
  134         smb_rq_getrequest(rqp, &mbp);
  135         smb_rq_wstart(rqp);
  136         smb_rq_wend(rqp);
  137         smb_rq_bstart(rqp);
  138         for(dp = smb_dialects; dp->d_id != -1; dp++) {
  139                 mb_put_uint8(mbp, SMB_DT_DIALECT);
  140                 smb_put_dstring(mbp, vcp, dp->d_name, SMB_CS_NONE);
  141         }
  142         smb_rq_bend(rqp);
  143         error = smb_rq_simple(rqp);
  144         SMBSDEBUG("%d\n", error);
  145         if (error)
  146                 goto bad;
  147         smb_rq_getreply(rqp, &mdp);
  148         do {
  149                 error = md_get_uint8(mdp, &wc);
  150                 if (error)
  151                         break;
  152                 error = md_get_uint16le(mdp, &dindex);
  153                 if (error)
  154                         break;
  155                 if (dindex > 7) {
  156                         SMBERROR("Don't know how to talk with server %s (%d)\n", "xxx", dindex);
  157                         error = EBADRPC;
  158                         break;
  159                 }
  160                 dp = smb_dialects + dindex;
  161                 sp->sv_proto = dp->d_id;
  162                 SMBSDEBUG("Dialect %s (%d, %d)\n", dp->d_name, dindex, wc);
  163                 error = EBADRPC;
  164                 if (dp->d_id >= SMB_DIALECT_NTLM0_12) {
  165                         if (wc != 17)
  166                                 break;
  167                         md_get_uint8(mdp, &sp->sv_sm);
  168                         md_get_uint16le(mdp, &sp->sv_maxmux);
  169                         md_get_uint16le(mdp, &sp->sv_maxvcs);
  170                         md_get_uint32le(mdp, &sp->sv_maxtx);
  171                         md_get_uint32le(mdp, &sp->sv_maxraw);
  172                         md_get_uint32le(mdp, &sp->sv_skey);
  173                         md_get_uint32le(mdp, &sp->sv_caps);
  174                         md_get_mem(mdp, stime, 8, MB_MSYSTEM);
  175                         md_get_uint16le(mdp, (u_int16_t*)&sp->sv_tz);
  176                         md_get_uint8(mdp, &sblen);
  177                         if (sblen && (sp->sv_sm & SMB_SM_ENCRYPT)) {
  178                                 if (sblen != SMB_MAXCHALLENGELEN) {
  179                                         SMBERROR("Unexpected length of security blob (%d)\n", sblen);
  180                                         break;
  181                                 }
  182                                 error = md_get_uint16(mdp, &bc);
  183                                 if (error)
  184                                         break;
  185                                 if (sp->sv_caps & SMB_CAP_EXT_SECURITY)
  186                                         md_get_mem(mdp, NULL, 16, MB_MSYSTEM);
  187                                 error = md_get_mem(mdp, vcp->vc_ch, sblen, MB_MSYSTEM);
  188                                 if (error)
  189                                         break;
  190                                 vcp->vc_chlen = sblen;
  191                                 vcp->obj.co_flags |= SMBV_ENCRYPT;
  192                         }
  193                         vcp->vc_hflags2 |= SMB_FLAGS2_KNOWS_LONG_NAMES;
  194                         if (dp->d_id == SMB_DIALECT_NTLM0_12 &&
  195                             sp->sv_maxtx < 4096 &&
  196                             (sp->sv_caps & SMB_CAP_NT_SMBS) == 0) {
  197                                 vcp->obj.co_flags |= SMBV_WIN95;
  198                                 SMBSDEBUG("Win95 detected\n");
  199                         }
  200                 } else if (dp->d_id > SMB_DIALECT_CORE) {
  201                         md_get_uint16le(mdp, &tw);
  202                         sp->sv_sm = tw;
  203                         md_get_uint16le(mdp, &tw);
  204                         sp->sv_maxtx = tw;
  205                         md_get_uint16le(mdp, &sp->sv_maxmux);
  206                         md_get_uint16le(mdp, &sp->sv_maxvcs);
  207                         md_get_uint16le(mdp, &tw);      /* rawmode */
  208                         md_get_uint32le(mdp, &sp->sv_skey);
  209                         if (wc == 13) {         /* >= LANMAN1 */
  210                                 md_get_uint16(mdp, &tw);                /* time */
  211                                 md_get_uint16(mdp, &tw1);               /* date */
  212                                 md_get_uint16le(mdp, (u_int16_t*)&sp->sv_tz);
  213                                 md_get_uint16le(mdp, &swlen);
  214                                 if (swlen > SMB_MAXCHALLENGELEN)
  215                                         break;
  216                                 md_get_uint16(mdp, NULL);       /* mbz */
  217                                 if (md_get_uint16(mdp, &bc) != 0)
  218                                         break;
  219                                 if (bc < swlen)
  220                                         break;
  221                                 if (swlen && (sp->sv_sm & SMB_SM_ENCRYPT)) {
  222                                         error = md_get_mem(mdp, vcp->vc_ch, swlen, MB_MSYSTEM);
  223                                         if (error)
  224                                                 break;
  225                                         vcp->vc_chlen = swlen;
  226                                         vcp->obj.co_flags |= SMBV_ENCRYPT;
  227                                 }
  228                         }
  229                         vcp->vc_hflags2 |= SMB_FLAGS2_KNOWS_LONG_NAMES;
  230                 } else {        /* an old CORE protocol */
  231                         sp->sv_maxmux = 1;
  232                 }
  233                 error = 0;
  234         } while (0);
  235         if (error == 0) {
  236                 vcp->vc_maxvcs = sp->sv_maxvcs;
  237                 if (vcp->vc_maxvcs <= 1) {
  238                         if (vcp->vc_maxvcs == 0)
  239                                 vcp->vc_maxvcs = 1;
  240                 }
  241                 if (sp->sv_maxtx <= 0 || sp->sv_maxtx > 0xffff)
  242                         sp->sv_maxtx = 1024;
  243                 else
  244                         sp->sv_maxtx = min(sp->sv_maxtx,
  245                                            63*1024 + SMB_HDRLEN + 16);
  246                 SMB_TRAN_GETPARAM(vcp, SMBTP_RCVSZ, &maxqsz);
  247                 vcp->vc_rxmax = min(smb_vc_maxread(vcp), maxqsz - 1024);
  248                 SMB_TRAN_GETPARAM(vcp, SMBTP_SNDSZ, &maxqsz);
  249                 vcp->vc_wxmax = min(smb_vc_maxwrite(vcp), maxqsz - 1024);
  250                 vcp->vc_txmax = min(sp->sv_maxtx, maxqsz);
  251                 SMBSDEBUG("TZ = %d\n", sp->sv_tz);
  252                 SMBSDEBUG("CAPS = %x\n", sp->sv_caps);
  253                 SMBSDEBUG("MAXMUX = %d\n", sp->sv_maxmux);
  254                 SMBSDEBUG("MAXVCS = %d\n", sp->sv_maxvcs);
  255                 SMBSDEBUG("MAXRAW = %d\n", sp->sv_maxraw);
  256                 SMBSDEBUG("MAXTX = %d\n", sp->sv_maxtx);
  257         }
  258 bad:
  259         smb_rq_done(rqp);
  260         return error;
  261 }
  262 
  263 int
  264 smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred)
  265 {
  266         struct smb_rq *rqp;
  267         struct mbchain *mbp;
  268 /*      u_int8_t wc;
  269         u_int16_t tw, tw1;*/
  270         smb_uniptr unipp, ntencpass = NULL;
  271         char *pp, *up, *pbuf, *encpass;
  272         int error, plen, uniplen, ulen, upper;
  273 
  274         upper = 0;
  275 
  276 again:
  277 
  278         vcp->vc_smbuid = SMB_UID_UNKNOWN;
  279 
  280         if (smb_smb_nomux(vcp, scred, __func__) != 0)
  281                 return EINVAL;
  282 
  283         error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX, scred, &rqp);
  284         if (error)
  285                 return error;
  286         pbuf = malloc(SMB_MAXPASSWORDLEN + 1, M_SMBTEMP, M_WAITOK);
  287         encpass = malloc(24, M_SMBTEMP, M_WAITOK);
  288         if (vcp->vc_sopt.sv_sm & SMB_SM_USER) {
  289                 /*
  290                  * We try w/o uppercasing first so Samba mixed case
  291                  * passwords work.  If that fails we come back and try
  292                  * uppercasing to satisfy OS/2 and Windows for Workgroups.
  293                  */
  294                 if (upper++) {
  295                         iconv_convstr(vcp->vc_toupper, pbuf,
  296                                       smb_vc_getpass(vcp)/*, SMB_MAXPASSWORDLEN*/);
  297                 } else {
  298                         strncpy(pbuf, smb_vc_getpass(vcp), SMB_MAXPASSWORDLEN);
  299                         pbuf[SMB_MAXPASSWORDLEN] = '\0';
  300                 }
  301                 if (!SMB_UNICODE_STRINGS(vcp))
  302                         iconv_convstr(vcp->vc_toserver, pbuf, pbuf/*,
  303                                       SMB_MAXPASSWORDLEN*/);
  304 
  305                 if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
  306                         uniplen = plen = 24;
  307                         smb_encrypt(pbuf, vcp->vc_ch, encpass);
  308                         ntencpass = malloc(uniplen, M_SMBTEMP, M_WAITOK);
  309                         if (SMB_UNICODE_STRINGS(vcp)) {
  310                                 strncpy(pbuf, smb_vc_getpass(vcp),
  311                                         SMB_MAXPASSWORDLEN);
  312                                 pbuf[SMB_MAXPASSWORDLEN] = '\0';
  313                         } else
  314                                 iconv_convstr(vcp->vc_toserver, pbuf,
  315                                               smb_vc_getpass(vcp)/*,
  316                                               SMB_MAXPASSWORDLEN*/);
  317                         smb_ntencrypt(pbuf, vcp->vc_ch, (u_char*)ntencpass);
  318                         pp = encpass;
  319                         unipp = ntencpass;
  320                 } else {
  321                         plen = strlen(pbuf) + 1;
  322                         pp = pbuf;
  323                         uniplen = plen * 2;
  324                         ntencpass = malloc(uniplen, M_SMBTEMP, M_WAITOK);
  325                         smb_strtouni(ntencpass, smb_vc_getpass(vcp));
  326                         plen--;
  327 
  328                         /*
  329                          * The uniplen is zeroed because Samba cannot deal
  330                          * with this 2nd cleartext password.  This Samba
  331                          * "bug" is actually a workaround for problems in
  332                          * Microsoft clients.
  333                          */
  334                         uniplen = 0/*-= 2*/;
  335                         unipp = ntencpass;
  336                 }
  337         } else {
  338                 /*
  339                  * In the share security mode password will be used
  340                  * only in the tree authentication
  341                  */
  342                  pp = "";
  343                  plen = 1;
  344                  unipp = &smb_unieol;
  345                  uniplen = 0 /* sizeof(smb_unieol) */;
  346         }
  347         smb_rq_wstart(rqp);
  348         mbp = &rqp->sr_rq;
  349         up = vcp->vc_username;
  350         ulen = strlen(up) + 1;
  351         /*
  352          * If userid is null we are attempting anonymous browse login
  353          * so passwords must be zero length.
  354          */
  355         if (ulen == 1)
  356                 plen = uniplen = 0;
  357         mb_put_uint8(mbp, 0xff);
  358         mb_put_uint8(mbp, 0);
  359         mb_put_uint16le(mbp, 0);
  360         mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxtx);
  361         mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxmux);
  362         mb_put_uint16le(mbp, vcp->vc_number);
  363         mb_put_uint32le(mbp, vcp->vc_sopt.sv_skey);
  364         mb_put_uint16le(mbp, plen);
  365         if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) {
  366                 mb_put_uint32le(mbp, 0);
  367                 smb_rq_wend(rqp);
  368                 smb_rq_bstart(rqp);
  369                 mb_put_mem(mbp, pp, plen, MB_MSYSTEM);
  370                 smb_put_dstring(mbp, vcp, up, SMB_CS_NONE);
  371         } else {
  372                 mb_put_uint16le(mbp, uniplen);
  373                 mb_put_uint32le(mbp, 0);                /* reserved */
  374                 mb_put_uint32le(mbp, vcp->obj.co_flags & SMBV_UNICODE ?
  375                                      SMB_CAP_UNICODE : 0);
  376                 smb_rq_wend(rqp);
  377                 smb_rq_bstart(rqp);
  378                 mb_put_mem(mbp, pp, plen, MB_MSYSTEM);
  379                 mb_put_mem(mbp, (caddr_t)unipp, uniplen, MB_MSYSTEM);
  380                 smb_put_dstring(mbp, vcp, up, SMB_CS_NONE);             /* AccountName */
  381                 smb_put_dstring(mbp, vcp, vcp->vc_domain, SMB_CS_NONE); /* PrimaryDomain */
  382                 smb_put_dstring(mbp, vcp, "FreeBSD", SMB_CS_NONE);      /* Client's OS */
  383                 smb_put_dstring(mbp, vcp, "NETSMB", SMB_CS_NONE);               /* Client name */
  384         }
  385         smb_rq_bend(rqp);
  386         if (ntencpass)
  387                 free(ntencpass, M_SMBTEMP);
  388         error = smb_rq_simple(rqp);
  389         SMBSDEBUG("%d\n", error);
  390         if (error) {
  391                 if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnoaccess)
  392                         error = EAUTH;
  393                 goto bad;
  394         }
  395         vcp->vc_smbuid = rqp->sr_rpuid;
  396 bad:
  397         free(encpass, M_SMBTEMP);
  398         free(pbuf, M_SMBTEMP);
  399         smb_rq_done(rqp);
  400         if (error && upper == 1 && vcp->vc_sopt.sv_sm & SMB_SM_USER)
  401                 goto again;
  402         return error;
  403 }
  404 
  405 int
  406 smb_smb_ssnclose(struct smb_vc *vcp, struct smb_cred *scred)
  407 {
  408         struct smb_rq *rqp;
  409         struct mbchain *mbp;
  410         int error;
  411 
  412         if (vcp->vc_smbuid == SMB_UID_UNKNOWN)
  413                 return 0;
  414 
  415         if (smb_smb_nomux(vcp, scred, __func__) != 0)
  416                 return EINVAL;
  417 
  418         error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_LOGOFF_ANDX, scred, &rqp);
  419         if (error)
  420                 return error;
  421         mbp = &rqp->sr_rq;
  422         smb_rq_wstart(rqp);
  423         mb_put_uint8(mbp, 0xff);
  424         mb_put_uint8(mbp, 0);
  425         mb_put_uint16le(mbp, 0);
  426         smb_rq_wend(rqp);
  427         smb_rq_bstart(rqp);
  428         smb_rq_bend(rqp);
  429         error = smb_rq_simple(rqp);
  430         SMBSDEBUG("%d\n", error);
  431         smb_rq_done(rqp);
  432         return error;
  433 }
  434 
  435 static char smb_any_share[] = "?????";
  436 
  437 static char *
  438 smb_share_typename(int stype)
  439 {
  440         char *pp;
  441 
  442         switch (stype) {
  443             case SMB_ST_DISK:
  444                 pp = "A:";
  445                 break;
  446             case SMB_ST_PRINTER:
  447                 pp = smb_any_share;             /* can't use LPT: here... */
  448                 break;
  449             case SMB_ST_PIPE:
  450                 pp = "IPC";
  451                 break;
  452             case SMB_ST_COMM:
  453                 pp = "COMM";
  454                 break;
  455             case SMB_ST_ANY:
  456             default:
  457                 pp = smb_any_share;
  458                 break;
  459         }
  460         return pp;
  461 }
  462 
  463 int
  464 smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred)
  465 {
  466         struct smb_vc *vcp;
  467         struct smb_rq rq, *rqp = &rq;
  468         struct mbchain *mbp;
  469         char *pp, *pbuf, *encpass;
  470         int error, plen, caseopt, upper;
  471 
  472         upper = 0;
  473 
  474 again:
  475 
  476 #if 0
  477         /* Disable Unicode for SMB_COM_TREE_CONNECT_ANDX requests */
  478         if (SSTOVC(ssp)->vc_hflags2 & SMB_FLAGS2_UNICODE) {
  479                 vcp = SSTOVC(ssp);
  480                 if (vcp->vc_toserver) {
  481                         iconv_close(vcp->vc_toserver);
  482                         /* Use NULL until UTF-8 -> ASCII works */
  483                         vcp->vc_toserver = NULL;
  484                 }
  485                 if (vcp->vc_tolocal) {
  486                         iconv_close(vcp->vc_tolocal);
  487                         /* Use NULL until ASCII -> UTF-8 works*/
  488                         vcp->vc_tolocal = NULL;
  489                 }
  490                 vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE;
  491         }
  492 #endif
  493 
  494         ssp->ss_tid = SMB_TID_UNKNOWN;
  495         error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_TREE_CONNECT_ANDX, scred, &rqp);
  496         if (error)
  497                 return error;
  498         vcp = rqp->sr_vc;
  499         caseopt = SMB_CS_NONE;
  500         if (vcp->vc_sopt.sv_sm & SMB_SM_USER) {
  501                 plen = 1;
  502                 pp = "";
  503                 pbuf = NULL;
  504                 encpass = NULL;
  505         } else {
  506                 pbuf = malloc(SMB_MAXPASSWORDLEN + 1, M_SMBTEMP, M_WAITOK);
  507                 encpass = malloc(24, M_SMBTEMP, M_WAITOK);
  508                 /*
  509                  * We try w/o uppercasing first so Samba mixed case
  510                  * passwords work.  If that fails we come back and try
  511                  * uppercasing to satisfy OS/2 and Windows for Workgroups.
  512                  */
  513                 if (upper++) {
  514                         iconv_convstr(vcp->vc_toupper, pbuf,
  515                                       smb_share_getpass(ssp)/*,
  516                                       SMB_MAXPASSWORDLEN*/);
  517                 } else {
  518                         strncpy(pbuf, smb_share_getpass(ssp),
  519                                 SMB_MAXPASSWORDLEN);
  520                         pbuf[SMB_MAXPASSWORDLEN] = '\0';
  521                 }
  522                 if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
  523                         plen = 24;
  524                         smb_encrypt(pbuf, vcp->vc_ch, encpass);
  525                         pp = encpass;
  526                 } else {
  527                         plen = strlen(pbuf) + 1;
  528                         pp = pbuf;
  529                 }
  530         }
  531         mbp = &rqp->sr_rq;
  532         smb_rq_wstart(rqp);
  533         mb_put_uint8(mbp, 0xff);
  534         mb_put_uint8(mbp, 0);
  535         mb_put_uint16le(mbp, 0);
  536         mb_put_uint16le(mbp, 0);                /* Flags */
  537         mb_put_uint16le(mbp, plen);
  538         smb_rq_wend(rqp);
  539         smb_rq_bstart(rqp);
  540         mb_put_mem(mbp, pp, plen, MB_MSYSTEM);
  541         smb_put_dmem(mbp, vcp, "\\\\", 2, caseopt);
  542         pp = vcp->vc_srvname;
  543         smb_put_dmem(mbp, vcp, pp, strlen(pp), caseopt);
  544         smb_put_dmem(mbp, vcp, "\\", 1, caseopt);
  545         pp = ssp->ss_name;
  546         smb_put_dstring(mbp, vcp, pp, caseopt);
  547         pp = smb_share_typename(ssp->ss_type);
  548         smb_put_dstring(mbp, vcp, pp, caseopt);
  549         smb_rq_bend(rqp);
  550         error = smb_rq_simple(rqp);
  551         SMBSDEBUG("%d\n", error);
  552         if (error)
  553                 goto bad;
  554         ssp->ss_tid = rqp->sr_rptid;
  555         ssp->ss_vcgenid = vcp->vc_genid;
  556         ssp->ss_flags |= SMBS_CONNECTED;
  557 bad:
  558         if (encpass)
  559                 free(encpass, M_SMBTEMP);
  560         if (pbuf)
  561                 free(pbuf, M_SMBTEMP);
  562         smb_rq_done(rqp);
  563         if (error && upper == 1)
  564                 goto again;
  565         return error;
  566 }
  567 
  568 int
  569 smb_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred)
  570 {
  571         struct smb_rq *rqp;
  572         struct mbchain *mbp;
  573         int error;
  574 
  575         if (ssp->ss_tid == SMB_TID_UNKNOWN)
  576                 return 0;
  577         error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_TREE_DISCONNECT, scred, &rqp);
  578         if (error)
  579                 return error;
  580         mbp = &rqp->sr_rq;
  581         smb_rq_wstart(rqp);
  582         smb_rq_wend(rqp);
  583         smb_rq_bstart(rqp);
  584         smb_rq_bend(rqp);
  585         error = smb_rq_simple(rqp);
  586         SMBSDEBUG("%d\n", error);
  587         smb_rq_done(rqp);
  588         ssp->ss_tid = SMB_TID_UNKNOWN;
  589         return error;
  590 }
  591 
  592 static __inline int
  593 smb_smb_readx(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
  594               struct uio *uio, struct smb_cred *scred)
  595 {
  596         struct smb_rq *rqp;
  597         struct mbchain *mbp;
  598         struct mdchain *mdp;
  599         u_int8_t wc;
  600         int error;
  601         u_int16_t residhi, residlo, off, doff;
  602         u_int32_t resid;
  603 
  604         error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp);
  605         if (error)
  606                 return error;
  607         smb_rq_getrequest(rqp, &mbp);
  608         smb_rq_wstart(rqp);
  609         mb_put_uint8(mbp, 0xff);        /* no secondary command */
  610         mb_put_uint8(mbp, 0);           /* MBZ */
  611         mb_put_uint16le(mbp, 0);        /* offset to secondary */
  612         mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM);
  613         mb_put_uint32le(mbp, uio->uio_offset);
  614         *len = min(SSTOVC(ssp)->vc_rxmax, *len);
  615         mb_put_uint16le(mbp, *len);     /* MaxCount */
  616         mb_put_uint16le(mbp, *len);     /* MinCount (only indicates blocking) */
  617         mb_put_uint32le(mbp, (unsigned)*len >> 16);     /* MaxCountHigh */
  618         mb_put_uint16le(mbp, *len);     /* Remaining ("obsolete") */
  619         mb_put_uint32le(mbp, uio->uio_offset >> 32);    /* OffsetHigh */
  620         smb_rq_wend(rqp);
  621         smb_rq_bstart(rqp);
  622         smb_rq_bend(rqp);
  623         do {
  624                 error = smb_rq_simple(rqp);
  625                 if (error)
  626                         break;
  627                 smb_rq_getreply(rqp, &mdp);
  628                 off = SMB_HDRLEN;
  629                 md_get_uint8(mdp, &wc);
  630                 off++;
  631                 if (wc != 12) {
  632                         error = EBADRPC;
  633                         break;
  634                 }
  635                 md_get_uint8(mdp, NULL);
  636                 off++;
  637                 md_get_uint8(mdp, NULL);
  638                 off++;
  639                 md_get_uint16le(mdp, NULL);
  640                 off += 2;
  641                 md_get_uint16le(mdp, NULL);
  642                 off += 2;
  643                 md_get_uint16le(mdp, NULL);     /* data compaction mode */
  644                 off += 2;
  645                 md_get_uint16le(mdp, NULL);
  646                 off += 2;
  647                 md_get_uint16le(mdp, &residlo);
  648                 off += 2;
  649                 md_get_uint16le(mdp, &doff);    /* data offset */
  650                 off += 2;
  651                 md_get_uint16le(mdp, &residhi);
  652                 off += 2;
  653                 resid = (residhi << 16) | residlo;
  654                 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);
  655                 off += 4*2;
  656                 md_get_uint16le(mdp, NULL);     /* ByteCount */
  657                 off += 2;
  658                 if (doff > off) /* pad byte(s)? */
  659                         md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM);
  660                 if (resid == 0) {
  661                         *rresid = resid;
  662                         break;
  663                 }
  664                 error = md_get_uio(mdp, uio, resid);
  665                 if (error)
  666                         break;
  667                 *rresid = resid;
  668         } while(0);
  669         smb_rq_done(rqp);
  670         return (error);
  671 }
  672 
  673 static __inline int
  674 smb_smb_writex(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
  675         struct uio *uio, struct smb_cred *scred)
  676 {
  677         struct smb_rq *rqp;
  678         struct mbchain *mbp;
  679         struct mdchain *mdp;
  680         int error;
  681         u_int8_t wc;
  682         u_int16_t resid;
  683 
  684         error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp);
  685         if (error)
  686                 return (error);
  687         smb_rq_getrequest(rqp, &mbp);
  688         smb_rq_wstart(rqp);
  689         mb_put_uint8(mbp, 0xff);        /* no secondary command */
  690         mb_put_uint8(mbp, 0);           /* MBZ */
  691         mb_put_uint16le(mbp, 0);        /* offset to secondary */
  692         mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM);
  693         mb_put_uint32le(mbp, uio->uio_offset);
  694         mb_put_uint32le(mbp, 0);        /* MBZ (timeout) */
  695         mb_put_uint16le(mbp, 0);        /* !write-thru */
  696         mb_put_uint16le(mbp, 0);
  697         *len = min(SSTOVC(ssp)->vc_wxmax, *len);
  698         mb_put_uint16le(mbp, (unsigned)*len >> 16);
  699         mb_put_uint16le(mbp, *len);
  700         mb_put_uint16le(mbp, 64);       /* data offset from header start */
  701         mb_put_uint32le(mbp, uio->uio_offset >> 32);    /* OffsetHigh */
  702         smb_rq_wend(rqp);
  703         smb_rq_bstart(rqp);
  704         do {
  705                 mb_put_uint8(mbp, 0xee);        /* mimic xp pad byte! */
  706                 error = mb_put_uio(mbp, uio, *len);
  707                 if (error)
  708                         break;
  709                 smb_rq_bend(rqp);
  710                 error = smb_rq_simple(rqp);
  711                 if (error)
  712                         break;
  713                 smb_rq_getreply(rqp, &mdp);
  714                 md_get_uint8(mdp, &wc);
  715                 if (wc != 6) {
  716                         error = EBADRPC;
  717                         break;
  718                 }
  719                 md_get_uint8(mdp, NULL);
  720                 md_get_uint8(mdp, NULL);
  721                 md_get_uint16le(mdp, NULL);
  722                 md_get_uint16le(mdp, &resid);
  723                 *rresid = resid;
  724         } while(0);
  725 
  726         smb_rq_done(rqp);
  727         return (error);
  728 }
  729 
  730 static __inline int
  731 smb_smb_read(struct smb_share *ssp, u_int16_t fid,
  732         int *len, int *rresid, struct uio *uio, struct smb_cred *scred)
  733 {
  734         struct smb_rq *rqp;
  735         struct mbchain *mbp;
  736         struct mdchain *mdp;
  737         u_int16_t resid, bc;
  738         u_int8_t wc;
  739         int error, rlen, blksz;
  740 
  741         if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_READX)
  742                 return (smb_smb_readx(ssp, fid, len, rresid, uio, scred));
  743 
  744         error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp);
  745         if (error)
  746                 return error;
  747 
  748         blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 16;
  749         rlen = *len = min(blksz, *len);
  750 
  751         smb_rq_getrequest(rqp, &mbp);
  752         smb_rq_wstart(rqp);
  753         mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM);
  754         mb_put_uint16le(mbp, rlen);
  755         mb_put_uint32le(mbp, uio->uio_offset);
  756         mb_put_uint16le(mbp, min(uio->uio_resid, 0xffff));
  757         smb_rq_wend(rqp);
  758         smb_rq_bstart(rqp);
  759         smb_rq_bend(rqp);
  760         do {
  761                 error = smb_rq_simple(rqp);
  762                 if (error)
  763                         break;
  764                 smb_rq_getreply(rqp, &mdp);
  765                 md_get_uint8(mdp, &wc);
  766                 if (wc != 5) {
  767                         error = EBADRPC;
  768                         break;
  769                 }
  770                 md_get_uint16le(mdp, &resid);
  771                 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);
  772                 md_get_uint16le(mdp, &bc);
  773                 md_get_uint8(mdp, NULL);                /* ignore buffer type */
  774                 md_get_uint16le(mdp, &resid);
  775                 if (resid == 0) {
  776                         *rresid = resid;
  777                         break;
  778                 }
  779                 error = md_get_uio(mdp, uio, resid);
  780                 if (error)
  781                         break;
  782                 *rresid = resid;
  783         } while(0);
  784         smb_rq_done(rqp);
  785         return error;
  786 }
  787 
  788 int
  789 smb_read(struct smb_share *ssp, u_int16_t fid, struct uio *uio,
  790         struct smb_cred *scred)
  791 {
  792         int tsize, len, resid;
  793         int error = 0;
  794 
  795         tsize = uio->uio_resid;
  796         while (tsize > 0) {
  797                 len = tsize;
  798                 error = smb_smb_read(ssp, fid, &len, &resid, uio, scred);
  799                 if (error)
  800                         break;
  801                 tsize -= resid;
  802                 if (resid < len)
  803                         break;
  804         }
  805         return error;
  806 }
  807 
  808 static __inline int
  809 smb_smb_write(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
  810         struct uio *uio, struct smb_cred *scred)
  811 {
  812         struct smb_rq *rqp;
  813         struct mbchain *mbp;
  814         struct mdchain *mdp;
  815         u_int16_t resid;
  816         u_int8_t wc;
  817         int error, blksz;
  818 
  819         if (*len && SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX)
  820                 return (smb_smb_writex(ssp, fid, len, rresid, uio, scred));
  821  
  822         blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 16;
  823         if (blksz > 0xffff)
  824                 blksz = 0xffff;
  825 
  826         resid = *len = min(blksz, *len);
  827 
  828         error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp);
  829         if (error)
  830                 return error;
  831         smb_rq_getrequest(rqp, &mbp);
  832         smb_rq_wstart(rqp);
  833         mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM);
  834         mb_put_uint16le(mbp, resid);
  835         mb_put_uint32le(mbp, uio->uio_offset);
  836         mb_put_uint16le(mbp, min(uio->uio_resid, 0xffff));
  837         smb_rq_wend(rqp);
  838         smb_rq_bstart(rqp);
  839         mb_put_uint8(mbp, SMB_DT_DATA);
  840         mb_put_uint16le(mbp, resid);
  841         do {
  842                 error = mb_put_uio(mbp, uio, resid);
  843                 if (error)
  844                         break;
  845                 smb_rq_bend(rqp);
  846                 error = smb_rq_simple(rqp);
  847                 if (error)
  848                         break;
  849                 smb_rq_getreply(rqp, &mdp);
  850                 md_get_uint8(mdp, &wc);
  851                 if (wc != 1) {
  852                         error = EBADRPC;
  853                         break;
  854                 }
  855                 md_get_uint16le(mdp, &resid);
  856                 *rresid = resid;
  857         } while(0);
  858         smb_rq_done(rqp);
  859         return error;
  860 }
  861 
  862 int
  863 smb_write(struct smb_share *ssp, u_int16_t fid, struct uio *uio,
  864         struct smb_cred *scred)
  865 {
  866         int error = 0, len, tsize, resid;
  867         struct uio olduio;
  868 
  869         tsize = uio->uio_resid;
  870         olduio = *uio;
  871         while (tsize > 0) {
  872                 len = tsize;
  873                 error = smb_smb_write(ssp, fid, &len, &resid, uio, scred);
  874                 if (error)
  875                         break;
  876                 if (resid < len) {
  877                         error = EIO;
  878                         break;
  879                 }
  880                 tsize -= resid;
  881         }
  882         if (error) {
  883                 /*
  884                  * Errors can happen on the copyin, the rpc, etc.  So they
  885                  * imply resid is unreliable.  The only safe thing is
  886                  * to pretend zero bytes made it.  We needn't restore the
  887                  * iovs because callers don't depend on them in error
  888                  * paths - uio_resid and uio_offset are what matter.
  889                  */
  890                 *uio = olduio;
  891         }
  892         return error;
  893 }
  894 
  895 int
  896 smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred)
  897 {
  898         struct smb_rq *rqp;
  899         struct mbchain *mbp;
  900         int error;
  901 
  902         error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp);
  903         if (error)
  904                 return error;
  905         mbp = &rqp->sr_rq;
  906         smb_rq_wstart(rqp);
  907         mb_put_uint16le(mbp, 1);
  908         smb_rq_wend(rqp);
  909         smb_rq_bstart(rqp);
  910         mb_put_uint32le(mbp, 0);
  911         smb_rq_bend(rqp);
  912         error = smb_rq_simple(rqp);
  913         SMBSDEBUG("%d\n", error);
  914         smb_rq_done(rqp);
  915         return error;
  916 }

Cache object: de146d4f354cfb94e93732c1c85f1408


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.