smb_smb.c revision 4bff34e37def8a90f9194d81bc345c52ba20086a
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Copyright (c) 2000-2001 Boris Popov
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * All rights reserved.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Redistribution and use in source and binary forms, with or without
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * modification, are permitted provided that the following conditions
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * are met:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 1. Redistributions of source code must retain the above copyright
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * notice, this list of conditions and the following disclaimer.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 2. Redistributions in binary form must reproduce the above copyright
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * notice, this list of conditions and the following disclaimer in the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * documentation and/or other materials provided with the distribution.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 3. All advertising materials mentioning features or use of this software
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * must display the following acknowledgement:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This product includes software developed by Boris Popov.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 4. Neither the name of the author nor the names of any co-contributors
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * may be used to endorse or promote products derived from this software
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * without specific prior written permission.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * SUCH DAMAGE.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * $Id: smb_smb.c,v 1.35.100.2 2005/06/02 00:55:39 lindak Exp $
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Use is subject to license terms.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#pragma ident "%Z%%M% %I% %E% SMI"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * various SMB requests. Most of the routines merely packs data into mbufs.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/param.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/systm.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/kmem.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/proc.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/lock.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/socket.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/uio.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/random.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/note.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/cmn_err.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef APPLE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/smb_apple.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/utfconv.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_osdep.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_conn.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_rq.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_subr.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_tran.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Largest size to use with LARGE_READ/LARGE_WRITE.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Specs say up to 64k data bytes, but Windows traffic
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * uses 60k... no doubt for some good reason.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (Probably to keep 4k block alignment.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX: Move to smb.h maybe?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#define SMB_MAX_LARGE_RW_SIZE (60*1024)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Default timeout values, all in seconds.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Make these tunable (only via mdb for now).
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_notice = 15;
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_default = 30; /* was SMB_DEFRQTIMO */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_open = 45;
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_read = 45;
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_write = 60; /* was SMBWRTTIMO */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_append = 90;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int smb_smb_read(struct smb_share *ssp, u_int16_t fid,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int *len, int *rresid, uio_t *uiop, struct smb_cred *scred, int timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int smb_smb_write(struct smb_share *ssp, u_int16_t fid,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int *len, int *rresid, uio_t *uiop, struct smb_cred *scred, int timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstruct smb_dialect {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int d_id;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *d_name;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow};
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_unichar smb_unieol = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic struct smb_dialect smb_dialects[] = {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {SMB_DIALECT_CORE, "PC NETWORK PROGRAM 1.0"},
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {SMB_DIALECT_LANMAN1_0, "LANMAN1.0"},
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {SMB_DIALECT_LANMAN2_0, "LM1.2X002"},
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {SMB_DIALECT_LANMAN2_1, "LANMAN2.1"},
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {SMB_DIALECT_NTLM0_12, "NT LM 0.12"},
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {-1, NULL}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow};
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#define SMB_DIALECT_MAX \
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (sizeof (smb_dialects) / sizeof (struct smb_dialect) - 2)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Number of seconds between 1970 and 1601 year
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowconst u_int64_t DIFF1970TO1601 = 11644473600ULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_time_local2server(struct timespec *tsp, int tzoff, long *seconds)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX - what if we connected to the server when it was in
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * daylight savings/summer time and we've subsequently switched
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * to standard time, or vice versa, so that the time zone
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * offset we got from the server is now wrong?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *seconds = tsp->tv_sec - tzoff * 60;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* - tz.tz_minuteswest * 60 - (wall_cmos_clock ? adjkerntz : 0) */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_time_server2local(ulong_t seconds, int tzoff, struct timespec *tsp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX - what if we connected to the server when it was in
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * daylight savings/summer time and we've subsequently switched
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * to standard time, or vice versa, so that the time zone
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * offset we got from the server is now wrong?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tsp->tv_sec = seconds + tzoff * 60;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* + tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tsp->tv_nsec = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Time from server comes as UTC, so no need to use tz
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_time_NT2local(u_int64_t nsec, int tzoff, struct timespec *tsp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_time_local2NT(struct timespec *tsp, int tzoff, u_int64_t *nsec)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow long seconds;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_time_local2server(tsp, 0, &seconds);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *nsec = (((u_int64_t)(seconds) & ~1) + DIFF1970TO1601) *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (u_int64_t)10000000;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#if defined(NOICONVSUPPORT) || defined(lint)
4bff34e37def8a90f9194d81bc345c52ba20086athurlowextern int iconv_open(const char *to, const char *from, void **handle);
4bff34e37def8a90f9194d81bc345c52ba20086athurlowextern int iconv_close(void *handle);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_dialect *dp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_sopt *sp = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int8_t wc, stime[8], sblen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t dindex, tw, tw1, swlen, bc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int unicode = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *servercs;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow void *servercshandle = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow void *localcshandle = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t toklen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags = SMB_FLAGS_CASELESS; /* XXX on Unix? */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Make sure SMB_FLAGS2_UNICODE is "off" so mb_put_dstring
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * marshalls the dialect strings in plain ascii.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 |= SMB_FLAGS2_ERR_STATUS;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_flags &= ~(SMBV_ENCRYPT);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp = &vcp->vc_sopt;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow bzero(sp, sizeof (struct smb_sopt));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_NEGOTIATE, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow for (dp = smb_dialects; dp->d_id != -1; dp++) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, SMB_DT_DIALECT);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, dp->d_name, SMB_CS_NONE);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This request should not wait for
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * connection state changes, etc.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_INTERNAL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_uint8(mdp, &wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_uint16le(mdp, &dindex);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dindex > SMB_DIALECT_MAX) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBERROR(
4bff34e37def8a90f9194d81bc345c52ba20086athurlow "Don't know how to talk with server %s (%d)\n",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_srvname, dindex);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow dp = smb_dialects + dindex;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dindex < SMB_DIALECT_MAX) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBERROR(
4bff34e37def8a90f9194d81bc345c52ba20086athurlow "Server %s negotiated old dialect (%s)\n",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_srvname, dp->d_name);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_proto = dp->d_id;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("Dialect %s (%d, %d)\n", dp->d_name, dindex, wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dp->d_id >= SMB_DIALECT_NTLM0_12) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc != 17)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &sp->sv_sm);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &sp->sv_maxmux);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &sp->sv_maxvcs);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint32le(mdp, &sp->sv_maxtx);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint32le(mdp, &sp->sv_maxraw);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint32le(mdp, &sp->sv_skey);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint32le(mdp, &sp->sv_caps);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_mem(mdp, (char *)stime, 8, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, (u_int16_t *)&sp->sv_tz);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &sblen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_uint16le(mdp, &bc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (sp->sv_sm & SMB_SM_SIGS_REQUIRE)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBERROR("server configuration requires "
4bff34e37def8a90f9194d81bc345c52ba20086athurlow "packet signing, which we dont support: "
4bff34e37def8a90f9194d81bc345c52ba20086athurlow "sp->sv_sm %d\n", sp->sv_sm);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (sp->sv_caps & SMB_CAP_UNICODE) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_flags |= SMBV_UNICODE;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow unicode = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!(sp->sv_caps & SMB_CAP_STATUS32)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * They don't do NT error codes.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If we send requests with
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * SMB_FLAGS2_ERR_STATUS set in
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Flags2, Windows 98, at least,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * appears to send replies with that
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * bit set even though it sends back
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * DOS error codes. (They probably
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * just use the request header as
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * a template for the reply header,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * and don't bother clearing that bit.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Therefore, we clear that bit in
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * our vc_hflags2 field.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 &= ~SMB_FLAGS2_ERR_STATUS;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dp->d_id == SMB_DIALECT_NTLM0_12 &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_maxtx < 4096 &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (sp->sv_caps & SMB_CAP_NT_SMBS) == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_flags |= SMBV_WIN95;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("Win95 detected\n");
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 3 cases here:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 1) Extended security.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Read bc bytes below for security blob.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note that we DON'T put the Caps flag in outtok.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * outtoklen = bc
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 2) No extended security, have challenge data and
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * possibly a domain name (which might be zero
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * bytes long, meaning "missing").
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Copy challenge stuff to vcp->vc_ch (sblen bytes),
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * then copy Cap flags and domain name (bc-sblen
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * bytes) to outtok.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * outtoklen = bc-sblen+4, where the 4 is for the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Caps flag.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 3) No extended security, no challenge data, just
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * possibly a domain name.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Copy Capsflags and domain name (bc) to outtok.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * outtoklen = bc+4, where 4 is for the Caps flag
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Sanity check: make sure the challenge length
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * isn't bigger than the byte count.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (sblen > bc) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow toklen = bc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (sblen && sblen <= SMB_MAXCHALLENGELEN &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_sm & SMB_SM_ENCRYPT) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_mem(mdp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (char *)vcp->vc_challenge,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sblen, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_chlen = sblen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow toklen -= sblen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_flags |= SMBV_ENCRYPT;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * For servers that don't support unicode
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * there are 2 things we could do:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 1) Pass the server Caps flags up to the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * user level so the logic up there will
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * know whether the domain name is unicode
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (this is what I did).
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 2) Try to convert the non-unicode string
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * to unicode. This doubles the length of
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the outtok buffer and would be guessing that
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the string was single-byte ascii, and that
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * might be wrong. Why ask for trouble?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Warning: NetApp may omit the GUID */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!(sp->sv_caps & SMB_CAP_EXT_SECURITY)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * No extended security.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Stick domain name, if present,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * and caps in outtok.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow toklen = toklen + 4; /* space for Caps flags */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtoklen = toklen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtok = kmem_alloc(toklen, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* first store server capability bits */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(vcp->vc_outtok ==
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (caddr_t)(((u_int32_t *)vcp->vc_outtok)));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *(u_int32_t *)(vcp->vc_outtok) = sp->sv_caps;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Then store the domain name if present;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * be sure to subtract 4 from the length
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * for the Caps flag.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (toklen > 4) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_mem(mdp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtok+4, toklen-4,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Extended security.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Stick the rest of the buffer in outtok.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtoklen = toklen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtok = kmem_alloc(toklen, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_mem(mdp, vcp->vc_outtok, toklen,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 &= ~(SMB_FLAGS2_EXT_SEC|SMB_FLAGS2_DFS|
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_FLAGS2_ERR_STATUS|SMB_FLAGS2_UNICODE);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dp->d_id > SMB_DIALECT_CORE) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &tw);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_sm = (uchar_t)tw;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &tw);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_maxtx = tw;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &sp->sv_maxmux);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &sp->sv_maxvcs);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &tw); /* rawmode */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint32le(mdp, &sp->sv_skey);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc == 13) { /* >= LANMAN1 */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16(mdp, &tw); /* time */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16(mdp, &tw1); /* date */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, (u_int16_t *)&sp->sv_tz);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &swlen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (swlen > SMB_MAXCHALLENGELEN)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16(mdp, NULL); /* mbz */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (md_get_uint16le(mdp, &bc) != 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (bc < swlen)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (swlen && (sp->sv_sm & SMB_SM_ENCRYPT)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_mem(mdp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (char *)vcp->vc_challenge,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow swlen, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_chlen = swlen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_flags |= SMBV_ENCRYPT;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else { /* an old CORE protocol */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 &= ~SMB_FLAGS2_KNOWS_LONG_NAMES;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_maxmux = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uint32_t x;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Maximum outstanding requests.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_maxmux < 1)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_maxmux = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Max VCs between server and client.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We only use one.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_maxvcs = sp->sv_maxvcs;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_maxvcs < 1)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_maxvcs = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Maximum transfer size.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Sanity checks:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Spec. says lower limit is 1024. OK.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Let's be conservative about an upper limit here.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Win2k uses 16644 (and others) so 32k should be a
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * reasonable sanity limit for this value.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note that this limit does NOT affect READX/WRITEX
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * with CAP_LARGE_xxx, which we nearly always use.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_txmax = sp->sv_maxtx;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_txmax < 1024)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_txmax = 1024;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_txmax > 0x8000)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_txmax = 0x8000;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Max read/write sizes, WITHOUT overhead.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This is just the payload size, so we must
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * leave room for the SMB headers, etc.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * With CAP_LARGE_xxx, always use 60k.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Otherwise use the vc_txmax value, but
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * reduced and rounded down. Tricky bit:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Servers typically give us a value that's
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * some nice "round" number, i.e 0x4000 plus
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * some overhead, i.e. Win2k: 16644==0x4104
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Subtract for the SMB header (32) and the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * SMB command word and byte vectors (34?),
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * then round down to a 512 byte multiple.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow x = (vcp->vc_txmax - 68) & 0xFE00;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (sp->sv_caps & SMB_CAP_LARGE_READX)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_rxmax = SMB_MAX_LARGE_RW_SIZE;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_rxmax = x;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (sp->sv_caps & SMB_CAP_LARGE_WRITEX)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_wxmax = SMB_MAX_LARGE_RW_SIZE;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_wxmax = x;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("TZ = %d\n", sp->sv_tz);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("CAPS = %x\n", sp->sv_caps);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("maxmux = %d\n", vcp->vc_maxmux);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("maxvcs = %d\n", vcp->vc_maxvcs);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("txmax = %d\n", vcp->vc_txmax);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("rxmax = %d\n", vcp->vc_rxmax);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("wxmax = %d\n", vcp->vc_wxmax);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If the server supports Unicode, set up to use Unicode
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * when talking to them. Othewise, use code page 437.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (unicode)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow servercs = "ucs-2";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * todo: if we can't determine the server's encoding, we
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * need to try a best-guess here.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow servercs = "cp437";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#if defined(NOICONVSUPPORT) || defined(lint)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * REVISIT
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = iconv_open(servercs, "utf-8", &servercshandle);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error != 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = iconv_open("utf-8", servercs, &localcshandle);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error != 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow iconv_close(servercshandle);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_toserver)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow iconv_close(vcp->vc_toserver);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_tolocal)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow iconv_close(vcp->vc_tolocal);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_toserver = servercshandle;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_tolocal = localcshandle;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (unicode)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 |= SMB_FLAGS2_UNICODE;
4bff34e37def8a90f9194d81bc345c52ba20086athurlowbad:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic void
4bff34e37def8a90f9194d81bc345c52ba20086athurlowget_ascii_password(struct smb_vc *vcp, int upper, char *pbuf)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *pw = smb_vc_getpass(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (upper)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_toupper(pw, pbuf, SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow strncpy(pbuf, pw, SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf[SMB_MAXPASSWORDLEN] = '\0';
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef APPLE
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic void
4bff34e37def8a90f9194d81bc345c52ba20086athurlowget_unicode_password(struct smb_vc *vcp, char *pbuf)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow strncpy(pbuf, smb_vc_getpass(vcp), SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf[SMB_MAXPASSWORDLEN] = '\0';
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic uchar_t *
4bff34e37def8a90f9194d81bc345c52ba20086athurlowadd_name_to_blob(uchar_t *blobnames, struct smb_vc *vcp, const uchar_t *name,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t namelen, int nametype, int uppercase)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct ntlmv2_namehdr namehdr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *namebuf;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t *uninamebuf;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t uninamelen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (name != NULL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uninamebuf = kmem_alloc(2 * namelen, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (uppercase) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow namebuf = kmem_alloc(namelen + 1, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_toupper((const char *)name, namebuf, namelen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow namebuf[namelen] = '\0';
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uninamelen = smb_strtouni(uninamebuf, namebuf, namelen,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow UCONV_IGNORE_NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(namebuf, namelen + 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uninamelen = smb_strtouni(uninamebuf, (char *)name,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow namelen, UCONV_IGNORE_NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uninamelen = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uninamebuf = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow namehdr.type = htoles(nametype);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow namehdr.len = htoles(uninamelen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow bcopy(&namehdr, blobnames, sizeof (namehdr));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames += sizeof (namehdr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (uninamebuf != NULL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow bcopy(uninamebuf, blobnames, uninamelen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames += uninamelen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(uninamebuf, namelen * 2);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (blobnames);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic uchar_t *
4bff34e37def8a90f9194d81bc345c52ba20086athurlowmake_ntlmv2_blob(struct smb_vc *vcp, u_int64_t client_nonce, size_t *bloblen)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uchar_t *blob;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t blobsize;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t domainlen, srvlen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct ntlmv2_blobhdr *blobhdr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct timespec now;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int64_t timestamp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uchar_t *blobnames;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ptrdiff_t diff;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX - the information at
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * http://davenport.sourceforge.net/ntlm.html#theNtlmv2Response
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * says that the "target information" comes from the Type 2 message,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * but, as we're not doing NTLMSSP, we don't have that.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Should we use the names from the NegProt response? Can we trust
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the NegProt response? (I've seen captures where the primary
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * domain name has an extra byte in front of it.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * For now, we don't trust it - we use vcp->vc_domain and
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * vcp->vc_srvname, instead. We upper-case them and convert
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * them to Unicode, as that's what's supposed to be in the blob.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow domainlen = strlen(vcp->vc_domain);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow srvlen = strlen(vcp->vc_srvname);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobsize = sizeof (struct ntlmv2_blobhdr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow + 3*sizeof (struct ntlmv2_namehdr) + 4 + 2*domainlen + 2*srvlen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blob = kmem_zalloc(blobsize, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(blob == (uchar_t *)((struct ntlmv2_blobhdr *)blob));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobhdr = (struct ntlmv2_blobhdr *)blob;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobhdr->header = htolel(0x00000101);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow gethrestime(&now);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_time_local2NT(&now, 0, &timestamp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobhdr->timestamp = htoleq(timestamp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobhdr->client_nonce = client_nonce;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames = blob + sizeof (struct ntlmv2_blobhdr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames = add_name_to_blob(blobnames, vcp, (uchar_t *)vcp->vc_domain,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow domainlen, NAMETYPE_DOMAIN_NB, 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames = add_name_to_blob(blobnames, vcp, (uchar_t *)vcp->vc_srvname,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow srvlen, NAMETYPE_MACHINE_NB, 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames = add_name_to_blob(blobnames, vcp, NULL, 0, NAMETYPE_EOL, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow diff = (intptr_t)blobnames - (intptr_t)blob;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(diff == (ptrdiff_t)((size_t)diff));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *bloblen = (size_t)diff;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (blob);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * See radar 4134676. This define helps us avoid how a certain old server
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * grants limited Guest access when we try NTLMv2, but works fine with NTLM.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The fingerprint we are looking for here is DOS error codes and no-Unicode.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note XP grants Guest access but uses Unicode and NT error codes.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#define smb_antique(rqp) (!((rqp)->sr_rpflags2 & SMB_FLAGS2_ERR_STATUS) && \
4bff34e37def8a90f9194d81bc345c52ba20086athurlow !((rqp)->sr_rpflags2 & SMB_FLAGS2_UNICODE))
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * When not doing Kerberos, we can try, in order:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * NTLMv2
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * NTLM with the ASCII password not upper-cased
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * NTLM with the ASCII password upper-cased
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * if the server supports encrypted passwords, or
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * plain-text with the ASCII password not upper-cased
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * plain-text with the ASCII password upper-cased
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * if it doesn't.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#define STATE_NTLMV2 0
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#define STATE_NOUCPW 1
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#define STATE_UCPW 2
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int8_t wc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int minauth;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_uniptr unipp = NULL, ntencpass = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *pp = NULL, *up = NULL, *ucup = NULL, *ucdp = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *pbuf = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *encpass = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t plen = 0, uniplen = 0, uniplen2 = 0, tmplen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t ucup_sl = 0, ucdp_sl = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int state;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t ntlmv2_bloblen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uchar_t *ntlmv2_blob;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int64_t client_nonce;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int32_t caps;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t bl; /* BLOB length */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t saveflags2 = vcp->vc_hflags2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow void * savetoserver = vcp->vc_toserver;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t action;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int declinedguest = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow static const char NativeOS[] = "Solaris";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow static const char LanMan[] = "NETSMB";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Most of the "capability" bits we offer should be copied
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * from those offered by the server, with a mask applied.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This is the mask of capabilies copied from the server.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Some others get special handling below.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow static const uint32_t caps_mask =
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_CAP_UNICODE |
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_CAP_LARGE_FILES |
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_CAP_NT_SMBS |
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_CAP_STATUS32 |
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_CAP_LARGE_READX |
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_CAP_LARGE_WRITEX;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow caps = vcp->vc_sopt.sv_caps & caps_mask;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* No unicode unless server supports and encryption on */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!((vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (vcp->vc_flags & SMBV_UNICODE))) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 &= 0xffff - SMB_FLAGS2_UNICODE;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_toserver = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow minauth = vcp->vc_vopt & SMBVOPT_MINAUTH;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_intok) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_intoklen > 65536 ||
4bff34e37def8a90f9194d81bc345c52ba20086athurlow !(vcp->vc_hflags2 & SMB_FLAGS2_EXT_SEC) ||
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EINVAL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto ssn_exit;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_smbuid = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Try only plain text passwords.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow state = STATE_NTLMV2; /* try NTLMv2 first */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow state = STATE_NOUCPW; /* try plain-text mixed-case first */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlowagain:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!vcp->vc_intok)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_smbuid = SMB_UID_UNKNOWN;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!vcp->vc_intok) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We're not doing extended security, which, for
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * now, means we're not doing Kerberos.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Fail if the minimum authentication level is
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Kerberos.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (minauth >= SMBVOPT_MINAUTH_KERBEROS) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EAUTH;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto ssn_exit;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Server wants encrypted passwords.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (state > STATE_NTLMV2) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We tried NTLMv2 in STATE_NTLMV2.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Shall we allow fallback? (to NTLM)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (minauth >= SMBVOPT_MINAUTH_NTLMV2) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EAUTH;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto ssn_exit;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (state > STATE_NOUCPW) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We tried NTLM in STATE_NOUCPW.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * No need to try it again.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EAUTH;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto ssn_exit;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Plain-text passwords.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Fail if the minimum authentication level is
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * LM or better.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (minauth > SMBVOPT_MINAUTH_NTLM) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EAUTH;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto ssn_exit;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto ssn_exit;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Domain name must be upper-case, as that's what's used
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * when computing LMv2 and NTLMv2 responses - and, for NTLMv2,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the domain name in the request has to be upper-cased as well.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (That appears not to be the case for the user name. Go
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * figure.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * don't need to uppercase domain string. It's already uppercase UTF-8.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ucdp_sl = strlen(vcp->vc_domain);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ucdp = kmem_zalloc(ucdp_sl + 1, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow memcpy(ucdp, vcp->vc_domain, ucdp_sl + 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_intok) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow caps |= SMB_CAP_EXT_SECURITY;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else if (!(vcp->vc_sopt.sv_sm & SMB_SM_USER)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * In the share security mode password will be used
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * only in the tree authentication
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = "";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow unipp = &smb_unieol;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uniplen = sizeof (smb_unieol);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf = kmem_alloc(SMB_MAXPASSWORDLEN + 1, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (state == STATE_NTLMV2) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Compute the LMv2 and NTLMv2 responses,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * derived from the challenge, the user name,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the domain/workgroup into which we're
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * logging, and the Unicode password.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Construct the client nonce by getting
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * a bunch of random data.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (void) random_get_pseudo_bytes((void *)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow &client_nonce, sizeof (client_nonce));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Convert the user name to upper-case, as
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * that's what's used when computing LMv2
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * and NTLMv2 responses.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ucup_sl = strlen(vcp->vc_username);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ucup = kmem_alloc(ucup_sl + 1, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_toupper((const char *)vcp->vc_username,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ucup, ucup_sl);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ucup[ucup_sl] = '\0';
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Compute the LMv2 response, derived
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * from the server challenge, the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * user name, the domain/workgroup
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * into which we're logging, the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * client nonce, and the NT hash.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_ntlmv2response(vcp->vc_nthash,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (uchar_t *)ucup, (uchar_t *)ucdp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_challenge,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (uchar_t *)&client_nonce, 8,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (uchar_t **)&encpass, &plen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = encpass;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Construct the blob.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ntlmv2_blob = make_ntlmv2_blob(vcp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow client_nonce, &ntlmv2_bloblen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Compute the NTLMv2 response, derived
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * from the server challenge, the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * user name, the domain/workgroup
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * into which we're logging, the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * blob, and the NT hash.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_ntlmv2response(vcp->vc_nthash,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (uchar_t *)ucup, (uchar_t *)ucdp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_challenge,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ntlmv2_blob, ntlmv2_bloblen,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (uchar_t **)&ntencpass, &uniplen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uniplen2 = uniplen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow unipp = ntencpass;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmplen = plen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(ucup, ucup_sl + 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free((char *)ntlmv2_blob,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sizeof (struct ntlmv2_blobhdr) +
4bff34e37def8a90f9194d81bc345c52ba20086athurlow 3 * sizeof (struct ntlmv2_namehdr) +
4bff34e37def8a90f9194d81bc345c52ba20086athurlow 4 +
4bff34e37def8a90f9194d81bc345c52ba20086athurlow 2 * strlen(vcp->vc_domain) +
4bff34e37def8a90f9194d81bc345c52ba20086athurlow 2 * strlen(vcp->vc_srvname));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = 24;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow encpass = kmem_zalloc(plen, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Compute the LM response, derived
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * from the challenge and the ASCII
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * password.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (minauth < SMBVOPT_MINAUTH_NTLM) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_lmresponse(vcp->vc_lmhash,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_challenge,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (uchar_t *)encpass);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = encpass;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Compute the NTLM response, derived from
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the challenge and the NT hash.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uniplen = 24;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uniplen2 = uniplen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ntencpass = kmem_alloc(uniplen, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_lmresponse(vcp->vc_nthash,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_challenge,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (uchar_t *)ntencpass);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow unipp = ntencpass;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We try w/o uppercasing first so Samba mixed case
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * passwords work. If that fails, we come back and
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * try uppercasing to satisfy OS/2 and Windows for
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Workgroups.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow get_ascii_password(vcp, (state == STATE_UCPW), pbuf);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = strlen(pbuf) + 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = pbuf;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uniplen = plen * 2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uniplen2 = uniplen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ntencpass = kmem_alloc(uniplen, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (void) smb_strtouni(ntencpass, smb_vc_getpass(vcp),
4bff34e37def8a90f9194d81bc345c52ba20086athurlow 0, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen--;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The uniplen is zeroed because Samba cannot deal
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * with this 2nd cleartext password. This Samba
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * "bug" is actually a workaround for problems in
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Microsoft clients.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uniplen = 0; /* -= 2 */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow unipp = ntencpass;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = &rqp->sr_rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow up = vcp->vc_username;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If userid is null we are attempting anonymous browse login
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * so passwords must be zero length.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (*up == '\0') {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = uniplen = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0xff);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxtx);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxmux);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, vcp->vc_number);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, vcp->vc_sopt.sv_skey);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((SMB_DIALECT(vcp)) < SMB_DIALECT_NTLM0_12) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, plen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, pp, plen, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); /* user */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, ucdp, SMB_CS_NONE); /* domain */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_intok) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, vcp->vc_intoklen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, 0); /* reserved */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, caps); /* my caps */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, vcp->vc_intok, vcp->vc_intoklen,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow MB_MSYSTEM); /* security blob */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, plen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, uniplen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, 0); /* reserved */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, caps); /* my caps */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, pp, plen, MB_MSYSTEM); /* password */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, (caddr_t)unipp, uniplen, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); /* user */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, ucdp, SMB_CS_NONE); /* dom */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, NativeOS, SMB_CS_NONE); /* OS */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, LanMan, SMB_CS_NONE); /* LAN Mgr */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (ntencpass) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(ntencpass, uniplen2);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ntencpass = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (encpass) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(encpass, 24);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow encpass = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (ucdp) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(ucdp, ucdp_sl + 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ucdp = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This request should not wait for
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * connection state changes, etc.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_INTERNAL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, SMBSSNSETUPTIMO);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnoaccess)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EAUTH;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!(rqp->sr_errclass == ERRDOS &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_serror == ERRmoredata))
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_smbuid = rqp->sr_rpuid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_uint8(mdp, &wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_intok) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc != 4)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else if (wc != 3)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, NULL); /* secondary cmd */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, NULL); /* mbz */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL); /* andxoffset */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &action); /* action */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_intok)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &bl); /* ext security */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL); /* byte count */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_intok) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtoklen = bl;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtok = kmem_alloc(bl, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_mem(mdp, vcp->vc_outtok, bl, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* server OS, LANMGR, & Domain here */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlowbad:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (encpass) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(encpass, tmplen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow encpass = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (pbuf) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(pbuf, SMB_MAXPASSWORDLEN + 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_sopt.sv_sm & SMB_SM_USER && !vcp->vc_intok &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (error || (*up != '\0' && action & SMB_ACT_GUEST &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow state == STATE_NTLMV2 && smb_antique(rqp)))) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We're doing user-level authentication (so we are actually
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * sending authentication stuff over the wire), and we're
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * not doing extended security, and the stuff we tried
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * failed (or we we're trying to login a real user but
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * got granted guest access instead.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow declinedguest = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Should we try the next type of authentication?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (state < STATE_UCPW) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Yes, we still have more to try.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow state++;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto again;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowssn_exit:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error && declinedguest)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBERROR("we declined ntlmv2 guest access. errno will be %d\n",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Restore things we changed and return */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 = saveflags2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_toserver = savetoserver;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_ssnclose(struct smb_vc *vcp, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_smbuid == SMB_UID_UNKNOWN)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_LOGOFF_ANDX, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = &rqp->sr_rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0xff);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Run this with a relatively short timeout.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We don't really care about the result,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * as we're just trying to play nice and
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * "say goodbye" before we hangup.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX: Add SMBLOGOFFTIMO somewhere?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, 5);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic char smb_any_share[] = "?????";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic char *
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_share_typename(int stype)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *pp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow switch (stype) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case STYPE_DISKTREE:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = "A:";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case STYPE_PRINTQ:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = smb_any_share; /* can't use LPT: here... */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case STYPE_DEVICE:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = "COMM";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case STYPE_IPC:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = "IPC";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow default:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = smb_any_share;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (pp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq rq, *rqp = &rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *pp, *pbuf, *encpass;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *pw;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uchar_t hash[SMB_PWH_MAX];
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error, plen, caseopt;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int upper = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowagain:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp = SSTOVC(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Make this a "VC-level" request, so it will have
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * rqp->sr_share == NULL, and smb_iod_sendrq()
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * will send it with TID = SMB_TID_UNKNOWN
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This also serves to bypass the wait for
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * share state changes, which this call is
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * trying to carry out.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * No longer need to set ssp->ss_tid
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * here, but it's harmless enough.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ssp->ss_tid = SMB_TID_UNKNOWN;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_CONNECT_ANDX,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow caseopt = SMB_CS_NONE;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_sopt.sv_sm & SMB_SM_USER) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = "";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow encpass = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf = kmem_alloc(SMB_MAXPASSWORDLEN + 1, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow encpass = kmem_alloc(24, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pw = smb_share_getpass(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We try w/o uppercasing first so Samba mixed case
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * passwords work. If that fails we come back and try
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * uppercasing to satisfy OS/2 and Windows for Workgroups.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (upper++) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_toupper(pw, pbuf, SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_oldlm_hash(pw, hash);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow strncpy(pbuf, pw, SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_ntlmv1hash(pw, hash);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf[SMB_MAXPASSWORDLEN] = '\0';
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef NOICONVSUPPORT
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We need to convert here to the server codeset.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Initially we will send the same stuff and see what happens
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * witout the conversion. REVISIT.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow iconv_convstr(vcp->vc_toserver, pbuf, pbuf, SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = 24;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_lmresponse(hash,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_challenge,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (uchar_t *)encpass);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = encpass;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = strlen(pbuf) + 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = pbuf;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = &rqp->sr_rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0xff);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0); /* Flags */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, plen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = mb_put_mem(mbp, pp, plen, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("error %d from mb_put_mem for pp\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dmem(mbp, vcp, "\\\\", 2, caseopt, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = vcp->vc_srvname;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_put_dmem(mbp, vcp, pp, strlen(pp), caseopt, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("error %d from smb_put_dmem for srvname\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dmem(mbp, vcp, "\\", 1, caseopt, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = ssp->ss_name;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_put_dstring(mbp, vcp, pp, caseopt);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("error %d from smb_put_dstring for ss_name\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* The type name is always ASCII */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = smb_share_typename(ssp->ss_type);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = mb_put_mem(mbp, pp, strlen(pp) + 1, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("error %d from mb_put_mem for ss_type\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Don't want to risk missing a successful
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * tree connect response.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_NOINTR_RECV;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Success! */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_SS_LOCK(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ssp->ss_tid = rqp->sr_rptid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ssp->ss_vcgenid = vcp->vc_genid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ssp->ss_flags |= SMBS_CONNECTED;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_SS_UNLOCK(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowbad:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (encpass)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(encpass, 24);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (pbuf)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(pbuf, SMB_MAXPASSWORDLEN + 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error && upper == 1)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto again;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (ssp->ss_tid == SMB_TID_UNKNOWN)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Build this as a "VC-level" request, so it will
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * avoid testing the _GONE flag on the share,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * which has already been set at this point.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Add the share pointer "by hand" below, so
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * smb_iod_sendrq will plug in the TID.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp = SSTOVC(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_DISCONNECT, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_share = ssp; /* by hand */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = &rqp->sr_rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef lint
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Run this with a relatively short timeout. (5 sec.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We don't really care about the result here, but we
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * do need to make sure we send this out, or we could
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * "leak" active tree IDs on interrupt or timeout.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The NOINTR_SEND flag makes this request immune to
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * interrupt or timeout until the send is done.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_NOINTR_SEND;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, 5);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ssp->ss_tid = SMB_TID_UNKNOWN;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_readx(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uio_t *uiop, struct smb_cred *scred, int timo)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp = SSTOVC(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int8_t wc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t residhi, residlo, off, doff;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int32_t resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX) == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Fall back to the old cmd. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (smb_smb_read(ssp, fid, len, rresid, uiop,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow scred, timo));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Have ReadX but not large files? */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((uiop->uio_loffset + *len) > UINT32_MAX)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EFBIG);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *len = min(*len, vcp->vc_rxmax);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0xff); /* no secondary command */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0); /* MBZ */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0); /* offset to secondary */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, (u_int32_t)(uiop->uio_offset));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, (u_int16_t)*len); /* MaxCount */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, (u_int16_t)*len); /* MinCount */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* (only indicates blocking) */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, (unsigned)*len >> 16); /* MaxCountHigh */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, (u_int16_t)*len); /* Remaining ("obsolete") */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, (u_int32_t)((uiop->uio_loffset) >> 32));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (timo == 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow timo = smb_timo_read;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off = SMB_HDRLEN;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off++;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc != 12) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off++;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off++;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off += 2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off += 2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL); /* data compaction mode */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off += 2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off += 2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &residlo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off += 2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &doff); /* data offset */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off += 2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &residhi);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off += 2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow resid = (residhi << 16) | residlo;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off += 4*2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL); /* ByteCount */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow off += 2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (doff > off) /* pad byte(s)? */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (resid == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *rresid = resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_uio(mdp, uiop, resid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *rresid = resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_writex(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uio_t *uiop, struct smb_cred *scred, int timo)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp = SSTOVC(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int8_t wc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX) == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Fall back to the old cmd. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (smb_smb_write(ssp, fid, len, rresid, uiop,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow scred, timo));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Have WriteX but not large files? */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((uiop->uio_loffset + *len) > UINT32_MAX)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EFBIG);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *len = min(*len, vcp->vc_wxmax);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0xff); /* no secondary command */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0); /* MBZ */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0); /* offset to secondary */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, (u_int32_t)(uiop->uio_offset));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, 0); /* MBZ (timeout) */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0); /* !write-thru */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, (u_int16_t)((unsigned)*len >> 16));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, (u_int16_t)*len);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 64); /* data offset from header start */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, (u_int32_t)((uiop->uio_loffset) >> 32));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0xee); /* mimic xp pad byte! */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = mb_put_uio(mbp, uiop, *len);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (timo == 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow timo = smb_timo_write;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc != 6) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &resid); /* actually is # written */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *rresid = resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * if LARGE_WRITEX then there's one more bit of # written
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &resid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *rresid |= (int)(resid & 1) << 16;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_read(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uio_t *uiop, struct smb_cred *scred, int timo)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t resid, bc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int8_t wc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error, rlen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* This cmd is limited to 32-bit offsets. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((uiop->uio_loffset + *len) > UINT32_MAX)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EFBIG);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *len = rlen = min(*len, SSTOVC(ssp)->vc_rxmax);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, (u_int16_t)rlen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, (u_int32_t)uiop->uio_offset);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, (u_int16_t)min(uiop->uio_resid, 0xffff));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (timo == 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow timo = smb_timo_read;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc != 5) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &resid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &bc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, NULL); /* ignore buffer type */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &resid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (resid == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *rresid = resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_uio(mdp, uiop, resid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *rresid = resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_write(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uio_t *uiop, struct smb_cred *scred, int timo)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int8_t wc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* This cmd is limited to 32-bit offsets. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((uiop->uio_loffset + *len) > UINT32_MAX)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EFBIG);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *len = resid = min(*len, SSTOVC(ssp)->vc_wxmax);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, resid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, (u_int32_t)uiop->uio_offset);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, (u_int16_t)min(uiop->uio_resid, 0xffff));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, SMB_DT_DATA);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, resid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = mb_put_uio(mbp, uiop, resid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (timo == 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow timo = smb_timo_write;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc != 1) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &resid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *rresid = resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Common function for read/write with UIO.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Called by netsmb smb_usr_rw,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * smbfs_readvnode, smbfs_writevnode
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_rwuio(struct smb_share *ssp, u_int16_t fid, uio_rw_t rw,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uio_t *uiop, struct smb_cred *scred, int timo)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ssize_t old_resid, tsize;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow offset_t old_offset;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int len, resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow old_offset = uiop->uio_loffset;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow old_resid = tsize = uiop->uio_resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow while (tsize > 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Lint: tsize may be 64-bits */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow len = SMB_MAX_LARGE_RW_SIZE;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (len > tsize)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow len = (int)tsize;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rw == UIO_READ)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_smb_readx(ssp, fid, &len, &resid, uiop,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow scred, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_smb_writex(ssp, fid, &len, &resid, uiop,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow scred, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (resid < len) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EIO;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tsize -= resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow timo = 0; /* only first write is special */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Errors can happen in copyin/copyout, the rpc, etc. so
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * they imply resid is unreliable. The only safe thing is
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * to pretend zero bytes made it. We needn't restore the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * iovs because callers don't depend on them in error
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * paths - uio_resid and uio_offset are what matter.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uiop->uio_loffset = old_offset;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uiop->uio_resid = old_resid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic u_int32_t smbechoes = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = &rqp->sr_rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 1); /* echo count */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, atomic_inc_32_nv(&smbechoes));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note: the IOD calls this, so
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * this request must not wait for
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * connection state changes, etc.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_INTERNAL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef APPLE
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_checkdir(struct smb_share *ssp, void *dnp, char *name,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int nmlen, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CHECK_DIRECTORY, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, SMB_DT_ASCII);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * All we need to do is marshall the path: "\\"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (the root of the share) into this request.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We essentially in-line smbfs_fullpath() here,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * except no mb_put_padbyte (already aligned).
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, SSTOVC(ssp), "\\", SMB_CS_NONE);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif /* APPLE */