1 /*
   2  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
   3  * Copyright (c) 2000, Boris Popov
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  * 1. Redistributions of source code must retain the above copyright
  10  *    notice, this list of conditions and the following disclaimer.
  11  * 2. Redistributions in binary form must reproduce the above copyright
  12  *    notice, this list of conditions and the following disclaimer in the
  13  *    documentation and/or other materials provided with the distribution.
  14  * 3. All advertising materials mentioning features or use of this software
  15  *    must display the following acknowledgement:
  16  *    This product includes software developed by Boris Popov.
  17  * 4. Neither the name of the author nor the names of any co-contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  *
  33  * $Id: rq.c,v 1.4 2004/12/13 00:25:23 lindak Exp $
  34  */
  35 
  36 #include <sys/types.h>
  37 #include <sys/param.h>
  38 #include <sys/ioctl.h>
  39 #include <sys/errno.h>
  40 #include <sys/stat.h>
  41 
  42 #include <ctype.h>
  43 #include <errno.h>
  44 #include <stdio.h>
  45 #include <unistd.h>
  46 #include <strings.h>
  47 #include <stdlib.h>
  48 #include <sysexits.h>
  49 #include <libintl.h>
  50 
  51 #include <netsmb/smb.h>
  52 #include <netsmb/smb_lib.h>
  53 #include "private.h"
  54 
  55 #define MIN_REPLY_SIZE 4096
  56 
  57 static uint32_t smb_map_doserr(uint8_t, uint16_t);
  58 
  59 /*
  60  * Create and initialize a request structure, for either an
  61  * "internal" request (one that does not use the driver) or
  62  * a regular "driver" request, that uses driver ioctls.
  63  *
  64  * The two kinds are built a little differently:
  65  * Driver requests are composed starting with the
  66  * first word of the "variable word vector" section.
  67  * The driver prepends the SMB header and word count.
  68  * The driver also needs an output buffer to receive
  69  * the response, filled in via copyout in the ioctl.
  70  *
  71  * Internal requests are composed entirely in this library.
  72  * Space for the SMB header is reserved here, and later
  73  * filled in by smb_rq_internal before the send/receive.
  74  */
  75 int
  76 smb_rq_init(struct smb_ctx *ctx, uchar_t cmd, struct smb_rq **rqpp)
  77 {
  78         struct smb_rq *rqp;
  79 
  80         rqp = malloc(sizeof (*rqp));
  81         if (rqp == NULL)
  82                 goto errout;
  83         bzero(rqp, sizeof (*rqp));
  84         rqp->rq_cmd = cmd;
  85         rqp->rq_ctx = ctx;
  86 
  87         /*
  88          * Setup the request buffer.
  89          * Do the reply buffer later.
  90          */
  91         if (mb_init(&rqp->rq_rq))
  92                 goto errout;
  93 
  94         /* Space for the SMB header. (filled in later) */
  95         mb_put_mem(&rqp->rq_rq, NULL, SMB_HDRLEN, MB_MSYSTEM);
  96 
  97         /*
  98          * Copy the ctx flags here, so the caller can
  99          * update the req flags before the OTW call.
 100          */
 101         rqp->rq_hflags = ctx->ct_hflags;
 102         rqp->rq_hflags2 = ctx->ct_hflags2;
 103 
 104         *rqpp = rqp;
 105         return (0);
 106 
 107 errout:
 108         if (rqp) {
 109                 smb_rq_done(rqp);
 110                 free(rqp);
 111         }
 112         return (ENOMEM);
 113 }
 114 
 115 void
 116 smb_rq_done(struct smb_rq *rqp)
 117 {
 118         mb_done(&rqp->rq_rp);
 119         mb_done(&rqp->rq_rq);
 120         free(rqp);
 121 }
 122 
 123 /*
 124  * Reserve space for the word count, which is filled in later by
 125  * smb_rq_wend().  Also initialize the counter that it uses
 126  * to figure out what value to fill in.
 127  *
 128  * Note that the word count happens to be 8-bits,
 129  * which can lead to confusion.
 130  */
 131 void
 132 smb_rq_wstart(struct smb_rq *rqp)
 133 {
 134         struct mbdata *mbp = &rqp->rq_rq;
 135 
 136         (void) mb_fit(mbp, 1, &rqp->rq_wcntp);
 137         rqp->rq_wcbase = mbp->mb_count;
 138 }
 139 
 140 /*
 141  * Fill in the word count, in the space reserved by
 142  * smb_rq_wstart().
 143  */
 144 void
 145 smb_rq_wend(struct smb_rq *rqp)
 146 {
 147         struct mbdata *mbp = &rqp->rq_rq;
 148         int wcnt;
 149 
 150         if (rqp->rq_wcntp == NULL) {
 151                 DPRINT("no wcount ptr\n");
 152                 return;
 153         }
 154         wcnt = mbp->mb_count - rqp->rq_wcbase;
 155         if (wcnt > 0x1ff)
 156                 DPRINT("word count too large (%d)\n", wcnt);
 157         if (wcnt & 1)
 158                 DPRINT("odd word count\n");
 159         wcnt >>= 1;
 160 
 161         /*
 162          * Fill in the word count (8-bits).
 163          * Also store it in the rq, in case
 164          * we're using the ioctl path.
 165          */
 166         *rqp->rq_wcntp = (char)wcnt;
 167 }
 168 
 169 /*
 170  * Reserve space for the byte count, which is filled in later by
 171  * smb_rq_bend().  Also initialize the counter that it uses
 172  * to figure out what value to fill in.
 173  *
 174  * Note that the byte count happens to be 16-bits,
 175  * which can lead to confusion.
 176  */
 177 void
 178 smb_rq_bstart(struct smb_rq *rqp)
 179 {
 180         struct mbdata *mbp = &rqp->rq_rq;
 181 
 182         (void) mb_fit(mbp, 2, &rqp->rq_bcntp);
 183         rqp->rq_bcbase = mbp->mb_count;
 184 }
 185 
 186 /*
 187  * Fill in the byte count, in the space reserved by
 188  * smb_rq_bstart().
 189  */
 190 void
 191 smb_rq_bend(struct smb_rq *rqp)
 192 {
 193         struct mbdata *mbp = &rqp->rq_rq;
 194         int bcnt;
 195 
 196         if (rqp->rq_bcntp == NULL) {
 197                 DPRINT("no bcount ptr\n");
 198                 return;
 199         }
 200         bcnt = mbp->mb_count - rqp->rq_bcbase;
 201         if (bcnt > 0xffff)
 202                 DPRINT("byte count too large (%d)\n", bcnt);
 203         /*
 204          * Fill in the byte count (16-bits).
 205          * Also store it in the rq, in case
 206          * we're using the ioctl path.
 207          *
 208          * The pointer is char * type due to
 209          * typical off-by-one alignment.
 210          */
 211         rqp->rq_bcntp[0] = bcnt & 0xFF;
 212         rqp->rq_bcntp[1] = (bcnt >> 8);
 213 }
 214 
 215 int
 216 smb_rq_simple(struct smb_rq *rqp)
 217 {
 218         struct smbioc_rq krq;
 219         struct mbdata *mbp;
 220         mbuf_t *m;
 221         char *data;
 222         uint32_t len;
 223         size_t rpbufsz;
 224         int error;
 225 
 226         bzero(&krq, sizeof (krq));
 227         krq.ioc_cmd = rqp->rq_cmd;
 228 
 229         /*
 230          * Make the SMB request body contiguous,
 231          * and fill in the ioctl request.
 232          */
 233         mbp = smb_rq_getrequest(rqp);
 234         error = m_lineup(mbp->mb_top, &mbp->mb_top);
 235         if (error)
 236                 return (error);
 237 
 238         data = mtod(mbp->mb_top, char *);
 239         len = m_totlen(mbp->mb_top);
 240 
 241         /*
 242          * _rq_init left space for the SMB header,
 243          * which makes mb_count the offset from
 244          * the beginning of the header (useful).
 245          * However, in this code path the driver
 246          * prepends the header, so we skip it.
 247          */
 248         krq.ioc_tbufsz = len - SMB_HDRLEN;
 249         krq.ioc_tbuf  = data + SMB_HDRLEN;
 250 
 251         /*
 252          * Setup a buffer to hold the reply,
 253          * at least MIN_REPLY_SIZE, or larger
 254          * if the caller increased rq_rpbufsz.
 255          */
 256         mbp = smb_rq_getreply(rqp);
 257         rpbufsz = rqp->rq_rpbufsz;
 258         if (rpbufsz < MIN_REPLY_SIZE)
 259                 rpbufsz = MIN_REPLY_SIZE;
 260         if ((error = m_get(rpbufsz, &m)) != 0)
 261                 return (error);
 262         mb_initm(mbp, m);
 263         krq.ioc_rbufsz = rpbufsz;
 264         krq.ioc_rbuf = mtod(m, char *);
 265 
 266         /*
 267          * Call the driver
 268          */
 269         if (ioctl(rqp->rq_ctx->ct_dev_fd, SMBIOC_REQUEST, &krq) == -1)
 270                 return (errno);
 271 
 272         /*
 273          * Initialize returned mbdata.
 274          * SMB header already parsed.
 275          */
 276         m->m_len = krq.ioc_rbufsz;
 277 
 278         return (0);
 279 }
 280 
 281 
 282 int
 283 smb_t2_request(int dev_fd, int setupcount, uint16_t *setup,
 284         const char *name,
 285         int tparamcnt, void *tparam,
 286         int tdatacnt, void *tdata,
 287         int *rparamcnt, void *rparam,
 288         int *rdatacnt, void *rdata,
 289         int *buffer_oflow)
 290 {
 291         smbioc_t2rq_t *krq;
 292         int i;
 293 
 294         krq = (smbioc_t2rq_t *)malloc(sizeof (smbioc_t2rq_t));
 295         bzero(krq, sizeof (*krq));
 296 
 297         if (setupcount < 0 || setupcount >= SMBIOC_T2RQ_MAXSETUP) {
 298                 /* Bogus setup count, or too many setup words */
 299                 return (EINVAL);
 300         }
 301         for (i = 0; i < setupcount; i++)
 302                 krq->ioc_setup[i] = setup[i];
 303         krq->ioc_setupcnt = setupcount;
 304         strcpy(krq->ioc_name, name);
 305         krq->ioc_tparamcnt = tparamcnt;
 306         krq->ioc_tparam = tparam;
 307         krq->ioc_tdatacnt = tdatacnt;
 308         krq->ioc_tdata = tdata;
 309 
 310         krq->ioc_rparamcnt = *rparamcnt;
 311         krq->ioc_rdatacnt = *rdatacnt;
 312         krq->ioc_rparam = rparam;
 313         krq->ioc_rdata  = rdata;
 314 
 315         if (ioctl(dev_fd, SMBIOC_T2RQ, krq) == -1) {
 316                 return (errno);
 317         }
 318 
 319         *rparamcnt = krq->ioc_rparamcnt;
 320         *rdatacnt = krq->ioc_rdatacnt;
 321         *buffer_oflow = (krq->ioc_rpflags2 & SMB_FLAGS2_ERR_STATUS) &&
 322             (krq->ioc_error == NT_STATUS_BUFFER_OVERFLOW);
 323         free(krq);
 324 
 325         return (0);
 326 }
 327 
 328 
 329 /*
 330  * Do an over-the-wire call without using the nsmb driver.
 331  * This is all "internal" to this library, and used only
 332  * for connection setup (negotiate protocol, etc.)
 333  */
 334 int
 335 smb_rq_internal(struct smb_ctx *ctx, struct smb_rq *rqp)
 336 {
 337         static const uint8_t ffsmb[4] = SMB_SIGNATURE;
 338         struct smb_iods *is = &ctx->ct_iods;
 339         uint32_t sigbuf[2];
 340         struct mbdata mbtmp, *mbp;
 341         int err, save_mlen;
 342         uint8_t ctmp;
 343 
 344         rqp->rq_uid = is->is_smbuid;
 345         rqp->rq_tid = SMB_TID_UNKNOWN;
 346         rqp->rq_mid = is->is_next_mid++;
 347 
 348         /*
 349          * Fill in the NBT and SMB headers
 350          * Using mbtmp so we can rewind without
 351          * affecting the passed request mbdata.
 352          */
 353         bcopy(&rqp->rq_rq, &mbtmp, sizeof (mbtmp));
 354         mbp = &mbtmp;
 355         mbp->mb_cur = mbp->mb_top;
 356         mbp->mb_pos = mbp->mb_cur->m_data;
 357         mbp->mb_count = 0;
 358         /* Have to save and restore m_len */
 359         save_mlen = mbp->mb_cur->m_len;
 360         mbp->mb_cur->m_len = 0;
 361 
 362         /*
 363          * rewind done; fill it in
 364          */
 365         mb_put_mem(mbp, ffsmb, SMB_SIGLEN, MB_MSYSTEM);
 366         mb_put_uint8(mbp, rqp->rq_cmd);
 367         mb_put_uint32le(mbp, 0);        /* status */
 368         mb_put_uint8(mbp, rqp->rq_hflags);
 369         mb_put_uint16le(mbp, rqp->rq_hflags2);
 370         /* pid_hi(2), signature(8), reserved(2) */
 371         mb_put_mem(mbp, NULL, 12, MB_MZERO);
 372         mb_put_uint16le(mbp, rqp->rq_tid);
 373         mb_put_uint16le(mbp, 0);        /* pid_lo */
 374         mb_put_uint16le(mbp, rqp->rq_uid);
 375         mb_put_uint16le(mbp, rqp->rq_mid);
 376 
 377         /* Restore original m_len */
 378         mbp->mb_cur->m_len = save_mlen;
 379 
 380         /*
 381          * Sign the message, if flags2 indicates.
 382          */
 383         if (rqp->rq_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
 384                 smb_rq_sign(rqp);
 385         }
 386 
 387         /*
 388          * Send it, wait for the reply.
 389          */
 390         if ((err = smb_ssn_send(ctx, &rqp->rq_rq)) != 0)
 391                 return (err);
 392 
 393         if ((err = smb_ssn_recv(ctx, &rqp->rq_rp)) != 0)
 394                 return (err);
 395 
 396         /*
 397          * Should have an SMB header, at least.
 398          */
 399         mbp = &rqp->rq_rp;
 400         if (mbp->mb_cur->m_len < SMB_HDRLEN) {
 401                 DPRINT("len < 32");
 402                 return (EBADRPC);
 403         }
 404 
 405         /*
 406          * If the request was signed, validate the
 407          * signature on the response.
 408          */
 409         if (rqp->rq_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
 410                 err = smb_rq_verify(rqp);
 411                 if (err) {
 412                         DPRINT("bad signature");
 413                         return (err);
 414                 }
 415         }
 416 
 417         /*
 418          * Decode the SMB header.
 419          */
 420         md_get_mem(mbp, (char *)sigbuf, 4, MB_MSYSTEM);
 421         if (0 != bcmp(sigbuf, ffsmb, 4)) {
 422                 DPRINT("not SMB");
 423                 return (EBADRPC);
 424         }
 425         md_get_uint8(mbp, &ctmp);   /* SMB cmd */
 426         md_get_uint32le(mbp, &rqp->rq_status);
 427         md_get_uint8(mbp, &rqp->rq_hflags);
 428         md_get_uint16le(mbp, &rqp->rq_hflags2);
 429         /* pid_hi(2), signature(8), reserved(2) */
 430         md_get_mem(mbp, NULL, 12, MB_MSYSTEM);
 431         md_get_uint16le(mbp, &rqp->rq_tid);
 432         md_get_uint16le(mbp, NULL);     /* pid_lo */
 433         md_get_uint16le(mbp, &rqp->rq_uid);
 434         md_get_uint16le(mbp, &rqp->rq_mid);
 435 
 436         /*
 437          * Figure out the status return.
 438          * Caller looks at rq_status.
 439          */
 440         if ((rqp->rq_hflags2 & SMB_FLAGS2_ERR_STATUS) == 0) {
 441                 uint16_t        serr;
 442                 uint8_t         class;
 443 
 444                 class = rqp->rq_status & 0xff;
 445                 serr  = rqp->rq_status >> 16;
 446                 rqp->rq_status = smb_map_doserr(class, serr);
 447         }
 448 
 449         return (0);
 450 }
 451 
 452 /*
 453  * Map old DOS errors (etc.) to NT status codes.
 454  * We probably don't need this anymore, since
 455  * the oldest server we talk to is NT.  But if
 456  * later find we do need this, add support here
 457  * for the DOS errors we care about.
 458  */
 459 static uint32_t
 460 smb_map_doserr(uint8_t class, uint16_t serr)
 461 {
 462         if (class == 0 && serr == 0)
 463                 return (0);
 464 
 465         DPRINT("class 0x%x serr 0x%x", (int)class, (int)serr);
 466         return (NT_STATUS_UNSUCCESSFUL);
 467 }