14bff34e3Sthurlow /* 24bff34e3Sthurlow * Copyright (c) 2000, Boris Popov 34bff34e3Sthurlow * All rights reserved. 44bff34e3Sthurlow * 54bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 64bff34e3Sthurlow * modification, are permitted provided that the following conditions 74bff34e3Sthurlow * are met: 84bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 94bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 104bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 114bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 124bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 134bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 144bff34e3Sthurlow * must display the following acknowledgement: 154bff34e3Sthurlow * This product includes software developed by Boris Popov. 164bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 174bff34e3Sthurlow * may be used to endorse or promote products derived from this software 184bff34e3Sthurlow * without specific prior written permission. 194bff34e3Sthurlow * 204bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 214bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 224bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 234bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 244bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 254bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 264bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 274bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 284bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 294bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 304bff34e3Sthurlow * SUCH DAMAGE. 314bff34e3Sthurlow * 324bff34e3Sthurlow * $Id: rq.c,v 1.4 2004/12/13 00:25:23 lindak Exp $ 334bff34e3Sthurlow */ 344bff34e3Sthurlow 354bff34e3Sthurlow #include <sys/types.h> 364bff34e3Sthurlow #include <sys/param.h> 374bff34e3Sthurlow #include <sys/ioctl.h> 384bff34e3Sthurlow #include <sys/errno.h> 394bff34e3Sthurlow #include <sys/stat.h> 404bff34e3Sthurlow 414bff34e3Sthurlow #include <ctype.h> 424bff34e3Sthurlow #include <errno.h> 434bff34e3Sthurlow #include <stdio.h> 444bff34e3Sthurlow #include <unistd.h> 454bff34e3Sthurlow #include <strings.h> 464bff34e3Sthurlow #include <stdlib.h> 474bff34e3Sthurlow #include <sysexits.h> 484bff34e3Sthurlow #include <libintl.h> 494bff34e3Sthurlow 50*613a2f6bSGordon Ross #include <netsmb/smb.h> 514bff34e3Sthurlow #include <netsmb/smb_lib.h> 529c9af259SGordon Ross #include "private.h" 534bff34e3Sthurlow 54*613a2f6bSGordon Ross static uint32_t smb_map_doserr(uint8_t, uint16_t); 554bff34e3Sthurlow 56*613a2f6bSGordon Ross /* 57*613a2f6bSGordon Ross * Create and initialize a request structure, for either an 58*613a2f6bSGordon Ross * "internal" request (one that does not use the driver) or 59*613a2f6bSGordon Ross * a regular "driver" request, that uses driver ioctls. 60*613a2f6bSGordon Ross * 61*613a2f6bSGordon Ross * The two kinds are built a little differently: 62*613a2f6bSGordon Ross * Driver requests are composed starting with the 63*613a2f6bSGordon Ross * first word of the "variable word vector" section. 64*613a2f6bSGordon Ross * The driver prepends the SMB header and word count. 65*613a2f6bSGordon Ross * The driver also needs an output buffer to receive 66*613a2f6bSGordon Ross * the response, filled in via copyout in the ioctl. 67*613a2f6bSGordon Ross * 68*613a2f6bSGordon Ross * Internal requests are composed entirely in this library. 69*613a2f6bSGordon Ross * Space for the SMB header is reserved here, and later 70*613a2f6bSGordon Ross * filled in by smb_rq_internal before the send/receive. 71*613a2f6bSGordon Ross */ 724bff34e3Sthurlow int 73*613a2f6bSGordon Ross smb_rq_init(struct smb_ctx *ctx, uchar_t cmd, struct smb_rq **rqpp) 744bff34e3Sthurlow { 754bff34e3Sthurlow struct smb_rq *rqp; 764bff34e3Sthurlow 774bff34e3Sthurlow rqp = malloc(sizeof (*rqp)); 784bff34e3Sthurlow if (rqp == NULL) 79*613a2f6bSGordon Ross goto errout; 804bff34e3Sthurlow bzero(rqp, sizeof (*rqp)); 814bff34e3Sthurlow rqp->rq_cmd = cmd; 824bff34e3Sthurlow rqp->rq_ctx = ctx; 83*613a2f6bSGordon Ross 84*613a2f6bSGordon Ross /* 85*613a2f6bSGordon Ross * Setup the request buffer. 86*613a2f6bSGordon Ross * Do the reply buffer later. 87*613a2f6bSGordon Ross */ 88*613a2f6bSGordon Ross if (mb_init(&rqp->rq_rq, M_MINSIZE)) 89*613a2f6bSGordon Ross goto errout; 90*613a2f6bSGordon Ross 91*613a2f6bSGordon Ross /* Space for the SMB header. (filled in later) */ 92*613a2f6bSGordon Ross mb_put_mem(&rqp->rq_rq, NULL, SMB_HDRLEN); 93*613a2f6bSGordon Ross 94*613a2f6bSGordon Ross /* 95*613a2f6bSGordon Ross * Copy the ctx flags here, so the caller can 96*613a2f6bSGordon Ross * update the req flags before the OTW call. 97*613a2f6bSGordon Ross */ 98*613a2f6bSGordon Ross rqp->rq_hflags = ctx->ct_hflags; 99*613a2f6bSGordon Ross rqp->rq_hflags2 = ctx->ct_hflags2; 100*613a2f6bSGordon Ross 1014bff34e3Sthurlow *rqpp = rqp; 1024bff34e3Sthurlow return (0); 103*613a2f6bSGordon Ross 104*613a2f6bSGordon Ross errout: 105*613a2f6bSGordon Ross if (rqp) { 106*613a2f6bSGordon Ross smb_rq_done(rqp); 107*613a2f6bSGordon Ross free(rqp); 108*613a2f6bSGordon Ross } 109*613a2f6bSGordon Ross return (ENOMEM); 1104bff34e3Sthurlow } 1114bff34e3Sthurlow 1124bff34e3Sthurlow void 1134bff34e3Sthurlow smb_rq_done(struct smb_rq *rqp) 1144bff34e3Sthurlow { 1154bff34e3Sthurlow mb_done(&rqp->rq_rp); 1164bff34e3Sthurlow mb_done(&rqp->rq_rq); 1174bff34e3Sthurlow free(rqp); 1184bff34e3Sthurlow } 1194bff34e3Sthurlow 120*613a2f6bSGordon Ross /* 121*613a2f6bSGordon Ross * Reserve space for the word count, which is filled in later by 122*613a2f6bSGordon Ross * smb_rq_wend(). Also initialize the counter that it uses 123*613a2f6bSGordon Ross * to figure out what value to fill in. 124*613a2f6bSGordon Ross * 125*613a2f6bSGordon Ross * Note that the word count happens to be 8-bits, 126*613a2f6bSGordon Ross * which can lead to confusion. 127*613a2f6bSGordon Ross */ 128*613a2f6bSGordon Ross void 129*613a2f6bSGordon Ross smb_rq_wstart(struct smb_rq *rqp) 130*613a2f6bSGordon Ross { 131*613a2f6bSGordon Ross struct mbdata *mbp = &rqp->rq_rq; 132*613a2f6bSGordon Ross 133*613a2f6bSGordon Ross mb_fit(mbp, 1, &rqp->rq_wcntp); 134*613a2f6bSGordon Ross rqp->rq_wcbase = mbp->mb_count; 135*613a2f6bSGordon Ross } 136*613a2f6bSGordon Ross 137*613a2f6bSGordon Ross /* 138*613a2f6bSGordon Ross * Fill in the word count, in the space reserved by 139*613a2f6bSGordon Ross * smb_rq_wstart(). 140*613a2f6bSGordon Ross */ 1414bff34e3Sthurlow void 1424bff34e3Sthurlow smb_rq_wend(struct smb_rq *rqp) 1434bff34e3Sthurlow { 144*613a2f6bSGordon Ross struct mbdata *mbp = &rqp->rq_rq; 145*613a2f6bSGordon Ross int wcnt; 146*613a2f6bSGordon Ross 147*613a2f6bSGordon Ross if (rqp->rq_wcntp == NULL) { 148*613a2f6bSGordon Ross DPRINT("no wcount ptr\n"); 149*613a2f6bSGordon Ross return; 150*613a2f6bSGordon Ross } 151*613a2f6bSGordon Ross wcnt = mbp->mb_count - rqp->rq_wcbase; 152*613a2f6bSGordon Ross if (wcnt > 0x1ff) 153*613a2f6bSGordon Ross DPRINT("word count too large (%d)\n", wcnt); 154*613a2f6bSGordon Ross if (wcnt & 1) 155*613a2f6bSGordon Ross DPRINT("odd word count\n"); 156*613a2f6bSGordon Ross wcnt >>= 1; 157*613a2f6bSGordon Ross 158*613a2f6bSGordon Ross /* 159*613a2f6bSGordon Ross * Fill in the word count (8-bits). 160*613a2f6bSGordon Ross * Also store it in the rq, in case 161*613a2f6bSGordon Ross * we're using the ioctl path. 162*613a2f6bSGordon Ross */ 163*613a2f6bSGordon Ross *rqp->rq_wcntp = (char)wcnt; 1644bff34e3Sthurlow } 1654bff34e3Sthurlow 166*613a2f6bSGordon Ross /* 167*613a2f6bSGordon Ross * Reserve space for the byte count, which is filled in later by 168*613a2f6bSGordon Ross * smb_rq_bend(). Also initialize the counter that it uses 169*613a2f6bSGordon Ross * to figure out what value to fill in. 170*613a2f6bSGordon Ross * 171*613a2f6bSGordon Ross * Note that the byte count happens to be 16-bits, 172*613a2f6bSGordon Ross * which can lead to confusion. 173*613a2f6bSGordon Ross */ 174*613a2f6bSGordon Ross void 175*613a2f6bSGordon Ross smb_rq_bstart(struct smb_rq *rqp) 1764bff34e3Sthurlow { 177*613a2f6bSGordon Ross struct mbdata *mbp = &rqp->rq_rq; 1784bff34e3Sthurlow 179*613a2f6bSGordon Ross mb_fit(mbp, 2, &rqp->rq_bcntp); 180*613a2f6bSGordon Ross rqp->rq_bcbase = mbp->mb_count; 1814bff34e3Sthurlow } 1824bff34e3Sthurlow 183*613a2f6bSGordon Ross /* 184*613a2f6bSGordon Ross * Fill in the byte count, in the space reserved by 185*613a2f6bSGordon Ross * smb_rq_bstart(). 186*613a2f6bSGordon Ross */ 187*613a2f6bSGordon Ross void 188*613a2f6bSGordon Ross smb_rq_bend(struct smb_rq *rqp) 1894bff34e3Sthurlow { 190*613a2f6bSGordon Ross struct mbdata *mbp = &rqp->rq_rq; 191*613a2f6bSGordon Ross int bcnt; 192*613a2f6bSGordon Ross 193*613a2f6bSGordon Ross if (rqp->rq_bcntp == NULL) { 194*613a2f6bSGordon Ross DPRINT("no bcount ptr\n"); 195*613a2f6bSGordon Ross return; 1964bff34e3Sthurlow } 197*613a2f6bSGordon Ross bcnt = mbp->mb_count - rqp->rq_bcbase; 198*613a2f6bSGordon Ross if (bcnt > 0xffff) 199*613a2f6bSGordon Ross DPRINT("byte count too large (%d)\n", bcnt); 200*613a2f6bSGordon Ross /* 201*613a2f6bSGordon Ross * Fill in the byte count (16-bits). 202*613a2f6bSGordon Ross * Also store it in the rq, in case 203*613a2f6bSGordon Ross * we're using the ioctl path. 204*613a2f6bSGordon Ross * 205*613a2f6bSGordon Ross * The pointer is char * type due to 206*613a2f6bSGordon Ross * typical off-by-one alignment. 207*613a2f6bSGordon Ross */ 208*613a2f6bSGordon Ross rqp->rq_bcntp[0] = bcnt & 0xFF; 209*613a2f6bSGordon Ross rqp->rq_bcntp[1] = (bcnt >> 8); 210*613a2f6bSGordon Ross } 211*613a2f6bSGordon Ross 212*613a2f6bSGordon Ross /* 213*613a2f6bSGordon Ross * Removed: smb_rq_dmem 214*613a2f6bSGordon Ross * which was mostly like: mb_put_mem 215*613a2f6bSGordon Ross */ 2164bff34e3Sthurlow 2174bff34e3Sthurlow int 2184bff34e3Sthurlow smb_rq_simple(struct smb_rq *rqp) 2194bff34e3Sthurlow { 2204bff34e3Sthurlow struct smbioc_rq krq; 2214bff34e3Sthurlow struct mbdata *mbp; 2224bff34e3Sthurlow char *data; 223*613a2f6bSGordon Ross uint32_t len; 224*613a2f6bSGordon Ross size_t rpbufsz; 2254bff34e3Sthurlow 226*613a2f6bSGordon Ross bzero(&krq, sizeof (krq)); 227*613a2f6bSGordon Ross krq.ioc_cmd = rqp->rq_cmd; 228*613a2f6bSGordon Ross 229*613a2f6bSGordon Ross /* 230*613a2f6bSGordon Ross * Make the SMB request body contiguous, 231*613a2f6bSGordon Ross * and fill in the ioctl request. 232*613a2f6bSGordon Ross */ 2334bff34e3Sthurlow mbp = smb_rq_getrequest(rqp); 2344bff34e3Sthurlow m_lineup(mbp->mb_top, &mbp->mb_top); 2354bff34e3Sthurlow data = mtod(mbp->mb_top, char *); 236*613a2f6bSGordon Ross len = m_totlen(mbp->mb_top); 2374bff34e3Sthurlow 238*613a2f6bSGordon Ross /* 239*613a2f6bSGordon Ross * _rq_init left space for the SMB header, 240*613a2f6bSGordon Ross * which makes mb_count the offset from 241*613a2f6bSGordon Ross * the beginning of the header (useful). 242*613a2f6bSGordon Ross * However, in this code path the driver 243*613a2f6bSGordon Ross * prepends the header, so we skip it. 244*613a2f6bSGordon Ross */ 245*613a2f6bSGordon Ross krq.ioc_tbufsz = len - SMB_HDRLEN; 246*613a2f6bSGordon Ross krq.ioc_tbuf = data + SMB_HDRLEN; 247*613a2f6bSGordon Ross 248*613a2f6bSGordon Ross /* 249*613a2f6bSGordon Ross * Setup a buffer to hold the reply. 250*613a2f6bSGordon Ross * 251*613a2f6bSGordon Ross * Default size is M_MINSIZE, but the 252*613a2f6bSGordon Ross * caller may increase rq_rpbufsz 253*613a2f6bSGordon Ross * before calling this. 254*613a2f6bSGordon Ross */ 2554bff34e3Sthurlow mbp = smb_rq_getreply(rqp); 256*613a2f6bSGordon Ross rpbufsz = rqp->rq_rpbufsz; 257*613a2f6bSGordon Ross if (rpbufsz < M_MINSIZE) 258*613a2f6bSGordon Ross rpbufsz = M_MINSIZE; 259*613a2f6bSGordon Ross if (mb_init(mbp, rpbufsz)) 260*613a2f6bSGordon Ross return (ENOMEM); 261*613a2f6bSGordon Ross krq.ioc_rbufsz = rpbufsz; 262*613a2f6bSGordon Ross krq.ioc_rbuf = mtod(mbp->mb_top, char *); 263*613a2f6bSGordon Ross 264*613a2f6bSGordon Ross /* 265*613a2f6bSGordon Ross * Call the driver 266*613a2f6bSGordon Ross */ 267*613a2f6bSGordon Ross if (ioctl(rqp->rq_ctx->ct_dev_fd, SMBIOC_REQUEST, &krq) == -1) 2684bff34e3Sthurlow return (errno); 269*613a2f6bSGordon Ross 270*613a2f6bSGordon Ross /* 271*613a2f6bSGordon Ross * Initialize returned mbdata. 272*613a2f6bSGordon Ross * SMB header already parsed. 273*613a2f6bSGordon Ross */ 274*613a2f6bSGordon Ross mbp->mb_top->m_len = krq.ioc_rbufsz; 275*613a2f6bSGordon Ross 2764bff34e3Sthurlow return (0); 2774bff34e3Sthurlow } 2784bff34e3Sthurlow 2794bff34e3Sthurlow 2804bff34e3Sthurlow int 2814bff34e3Sthurlow smb_t2_request(struct smb_ctx *ctx, int setupcount, uint16_t *setup, 2824bff34e3Sthurlow const char *name, 2834bff34e3Sthurlow int tparamcnt, void *tparam, 2844bff34e3Sthurlow int tdatacnt, void *tdata, 2854bff34e3Sthurlow int *rparamcnt, void *rparam, 2864bff34e3Sthurlow int *rdatacnt, void *rdata, 2874bff34e3Sthurlow int *buffer_oflow) 2884bff34e3Sthurlow { 2894bff34e3Sthurlow smbioc_t2rq_t *krq; 2904bff34e3Sthurlow int i; 2914bff34e3Sthurlow 2924bff34e3Sthurlow krq = (smbioc_t2rq_t *)malloc(sizeof (smbioc_t2rq_t)); 2934bff34e3Sthurlow bzero(krq, sizeof (*krq)); 2944bff34e3Sthurlow 295*613a2f6bSGordon Ross if (setupcount < 0 || setupcount >= SMBIOC_T2RQ_MAXSETUP) { 2964bff34e3Sthurlow /* Bogus setup count, or too many setup words */ 2974bff34e3Sthurlow return (EINVAL); 2984bff34e3Sthurlow } 2994bff34e3Sthurlow for (i = 0; i < setupcount; i++) 3004bff34e3Sthurlow krq->ioc_setup[i] = setup[i]; 3014bff34e3Sthurlow krq->ioc_setupcnt = setupcount; 3024bff34e3Sthurlow strcpy(krq->ioc_name, name); 3034bff34e3Sthurlow krq->ioc_tparamcnt = tparamcnt; 3044bff34e3Sthurlow krq->ioc_tparam = tparam; 3054bff34e3Sthurlow krq->ioc_tdatacnt = tdatacnt; 3064bff34e3Sthurlow krq->ioc_tdata = tdata; 3074bff34e3Sthurlow 3084bff34e3Sthurlow krq->ioc_rparamcnt = *rparamcnt; 3094bff34e3Sthurlow krq->ioc_rdatacnt = *rdatacnt; 3104bff34e3Sthurlow krq->ioc_rparam = rparam; 3114bff34e3Sthurlow krq->ioc_rdata = rdata; 3124bff34e3Sthurlow 313*613a2f6bSGordon Ross if (ioctl(ctx->ct_dev_fd, SMBIOC_T2RQ, krq) == -1) { 3144bff34e3Sthurlow return (errno); 3154bff34e3Sthurlow } 3164bff34e3Sthurlow 3174bff34e3Sthurlow *rparamcnt = krq->ioc_rparamcnt; 3184bff34e3Sthurlow *rdatacnt = krq->ioc_rdatacnt; 3194bff34e3Sthurlow *buffer_oflow = (krq->ioc_rpflags2 & SMB_FLAGS2_ERR_STATUS) && 3204bff34e3Sthurlow (krq->ioc_error == NT_STATUS_BUFFER_OVERFLOW); 3214bff34e3Sthurlow free(krq); 322*613a2f6bSGordon Ross 3234bff34e3Sthurlow return (0); 3244bff34e3Sthurlow } 325*613a2f6bSGordon Ross 326*613a2f6bSGordon Ross 327*613a2f6bSGordon Ross /* 328*613a2f6bSGordon Ross * Do an over-the-wire call without using the nsmb driver. 329*613a2f6bSGordon Ross * This is all "internal" to this library, and used only 330*613a2f6bSGordon Ross * for connection setup (negotiate protocol, etc.) 331*613a2f6bSGordon Ross */ 332*613a2f6bSGordon Ross int 333*613a2f6bSGordon Ross smb_rq_internal(struct smb_ctx *ctx, struct smb_rq *rqp) 334*613a2f6bSGordon Ross { 335*613a2f6bSGordon Ross static const uint8_t ffsmb[4] = SMB_SIGNATURE; 336*613a2f6bSGordon Ross struct smb_iods *is = &ctx->ct_iods; 337*613a2f6bSGordon Ross uint32_t sigbuf[2]; 338*613a2f6bSGordon Ross struct mbdata mbtmp, *mbp; 339*613a2f6bSGordon Ross int err, save_mlen; 340*613a2f6bSGordon Ross uint8_t ctmp; 341*613a2f6bSGordon Ross 342*613a2f6bSGordon Ross rqp->rq_uid = is->is_smbuid; 343*613a2f6bSGordon Ross rqp->rq_tid = SMB_TID_UNKNOWN; 344*613a2f6bSGordon Ross rqp->rq_mid = is->is_next_mid++; 345*613a2f6bSGordon Ross 346*613a2f6bSGordon Ross /* 347*613a2f6bSGordon Ross * Fill in the NBT and SMB headers 348*613a2f6bSGordon Ross * Using mbtmp so we can rewind without 349*613a2f6bSGordon Ross * affecting the passed request mbdata. 350*613a2f6bSGordon Ross */ 351*613a2f6bSGordon Ross bcopy(&rqp->rq_rq, &mbtmp, sizeof (mbtmp)); 352*613a2f6bSGordon Ross mbp = &mbtmp; 353*613a2f6bSGordon Ross mbp->mb_cur = mbp->mb_top; 354*613a2f6bSGordon Ross mbp->mb_pos = mbp->mb_cur->m_data; 355*613a2f6bSGordon Ross mbp->mb_count = 0; 356*613a2f6bSGordon Ross /* Have to save and restore m_len */ 357*613a2f6bSGordon Ross save_mlen = mbp->mb_cur->m_len; 358*613a2f6bSGordon Ross mbp->mb_cur->m_len = 0; 359*613a2f6bSGordon Ross 360*613a2f6bSGordon Ross /* 361*613a2f6bSGordon Ross * rewind done; fill it in 362*613a2f6bSGordon Ross */ 363*613a2f6bSGordon Ross mb_put_mem(mbp, (char *)SMB_SIGNATURE, SMB_SIGLEN); 364*613a2f6bSGordon Ross mb_put_uint8(mbp, rqp->rq_cmd); 365*613a2f6bSGordon Ross mb_put_mem(mbp, NULL, 4); /* status */ 366*613a2f6bSGordon Ross mb_put_uint8(mbp, rqp->rq_hflags); 367*613a2f6bSGordon Ross mb_put_uint16le(mbp, rqp->rq_hflags2); 368*613a2f6bSGordon Ross mb_put_uint16le(mbp, 0); /* pid_hi */ 369*613a2f6bSGordon Ross mb_put_mem(mbp, NULL, 8); /* signature */ 370*613a2f6bSGordon Ross mb_put_uint16le(mbp, 0); /* reserved */ 371*613a2f6bSGordon Ross mb_put_uint16le(mbp, rqp->rq_tid); 372*613a2f6bSGordon Ross mb_put_uint16le(mbp, 0); /* pid_lo */ 373*613a2f6bSGordon Ross mb_put_uint16le(mbp, rqp->rq_uid); 374*613a2f6bSGordon Ross mb_put_uint16le(mbp, rqp->rq_mid); 375*613a2f6bSGordon Ross 376*613a2f6bSGordon Ross /* Restore original m_len */ 377*613a2f6bSGordon Ross mbp->mb_cur->m_len = save_mlen; 378*613a2f6bSGordon Ross 379*613a2f6bSGordon Ross /* 380*613a2f6bSGordon Ross * Sign the message, if flags2 indicates. 381*613a2f6bSGordon Ross */ 382*613a2f6bSGordon Ross if (rqp->rq_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) { 383*613a2f6bSGordon Ross smb_rq_sign(rqp); 384*613a2f6bSGordon Ross } 385*613a2f6bSGordon Ross 386*613a2f6bSGordon Ross /* 387*613a2f6bSGordon Ross * Send it, wait for the reply. 388*613a2f6bSGordon Ross */ 389*613a2f6bSGordon Ross if ((err = smb_ssn_send(ctx, &rqp->rq_rq)) != 0) 390*613a2f6bSGordon Ross return (err); 391*613a2f6bSGordon Ross 392*613a2f6bSGordon Ross if ((err = smb_ssn_recv(ctx, &rqp->rq_rp)) != 0) 393*613a2f6bSGordon Ross return (err); 394*613a2f6bSGordon Ross 395*613a2f6bSGordon Ross /* 396*613a2f6bSGordon Ross * Should have an SMB header, at least. 397*613a2f6bSGordon Ross */ 398*613a2f6bSGordon Ross mbp = &rqp->rq_rp; 399*613a2f6bSGordon Ross if (mbp->mb_cur->m_len < SMB_HDRLEN) { 400*613a2f6bSGordon Ross DPRINT("len < 32"); 401*613a2f6bSGordon Ross return (EBADRPC); 402*613a2f6bSGordon Ross } 403*613a2f6bSGordon Ross 404*613a2f6bSGordon Ross /* 405*613a2f6bSGordon Ross * If the request was signed, validate the 406*613a2f6bSGordon Ross * signature on the response. 407*613a2f6bSGordon Ross */ 408*613a2f6bSGordon Ross if (rqp->rq_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) { 409*613a2f6bSGordon Ross err = smb_rq_verify(rqp); 410*613a2f6bSGordon Ross if (err) { 411*613a2f6bSGordon Ross DPRINT("bad signature"); 412*613a2f6bSGordon Ross return (err); 413*613a2f6bSGordon Ross } 414*613a2f6bSGordon Ross } 415*613a2f6bSGordon Ross 416*613a2f6bSGordon Ross /* 417*613a2f6bSGordon Ross * Decode the SMB header. 418*613a2f6bSGordon Ross */ 419*613a2f6bSGordon Ross mb_get_mem(mbp, (char *)sigbuf, 4); 420*613a2f6bSGordon Ross if (0 != bcmp(sigbuf, ffsmb, 4)) { 421*613a2f6bSGordon Ross DPRINT("not SMB"); 422*613a2f6bSGordon Ross return (EBADRPC); 423*613a2f6bSGordon Ross } 424*613a2f6bSGordon Ross mb_get_uint8(mbp, &ctmp); /* SMB cmd */ 425*613a2f6bSGordon Ross mb_get_uint32le(mbp, &rqp->rq_status); 426*613a2f6bSGordon Ross mb_get_uint8(mbp, &rqp->rq_hflags); 427*613a2f6bSGordon Ross mb_get_uint16le(mbp, &rqp->rq_hflags2); 428*613a2f6bSGordon Ross mb_get_uint16le(mbp, NULL); /* pid_hi */ 429*613a2f6bSGordon Ross mb_get_mem(mbp, NULL, 8); /* signature */ 430*613a2f6bSGordon Ross mb_get_uint16le(mbp, NULL); /* reserved */ 431*613a2f6bSGordon Ross mb_get_uint16le(mbp, &rqp->rq_tid); 432*613a2f6bSGordon Ross mb_get_uint16le(mbp, NULL); /* pid_lo */ 433*613a2f6bSGordon Ross mb_get_uint16le(mbp, &rqp->rq_uid); 434*613a2f6bSGordon Ross mb_get_uint16le(mbp, &rqp->rq_mid); 435*613a2f6bSGordon Ross 436*613a2f6bSGordon Ross /* 437*613a2f6bSGordon Ross * Figure out the status return. 438*613a2f6bSGordon Ross * Caller looks at rq_status. 439*613a2f6bSGordon Ross */ 440*613a2f6bSGordon Ross if ((rqp->rq_hflags2 & SMB_FLAGS2_ERR_STATUS) == 0) { 441*613a2f6bSGordon Ross uint16_t serr; 442*613a2f6bSGordon Ross uint8_t class; 443*613a2f6bSGordon Ross 444*613a2f6bSGordon Ross class = rqp->rq_status & 0xff; 445*613a2f6bSGordon Ross serr = rqp->rq_status >> 16; 446*613a2f6bSGordon Ross rqp->rq_status = smb_map_doserr(class, serr); 447*613a2f6bSGordon Ross } 448*613a2f6bSGordon Ross 449*613a2f6bSGordon Ross return (0); 450*613a2f6bSGordon Ross } 451*613a2f6bSGordon Ross 452*613a2f6bSGordon Ross /* 453*613a2f6bSGordon Ross * Map old DOS errors (etc.) to NT status codes. 454*613a2f6bSGordon Ross * We probably don't need this anymore, since 455*613a2f6bSGordon Ross * the oldest server we talk to is NT. But if 456*613a2f6bSGordon Ross * later find we do need this, add support here 457*613a2f6bSGordon Ross * for the DOS errors we care about. 458*613a2f6bSGordon Ross */ 459*613a2f6bSGordon Ross static uint32_t 460*613a2f6bSGordon Ross smb_map_doserr(uint8_t class, uint16_t serr) 461*613a2f6bSGordon Ross { 462*613a2f6bSGordon Ross if (class == 0 && serr == 0) 463*613a2f6bSGordon Ross return (0); 464*613a2f6bSGordon Ross 465*613a2f6bSGordon Ross DPRINT("class 0x%x serr 0x%x", (int)class, (int)serr); 466*613a2f6bSGordon Ross return (NT_STATUS_UNSUCCESSFUL); 467*613a2f6bSGordon Ross } 468