smb_subr.c revision 82046
175374Sbp/* 275374Sbp * Copyright (c) 2000-2001 Boris Popov 375374Sbp * All rights reserved. 475374Sbp * 575374Sbp * Redistribution and use in source and binary forms, with or without 675374Sbp * modification, are permitted provided that the following conditions 775374Sbp * are met: 875374Sbp * 1. Redistributions of source code must retain the above copyright 975374Sbp * notice, this list of conditions and the following disclaimer. 1075374Sbp * 2. Redistributions in binary form must reproduce the above copyright 1175374Sbp * notice, this list of conditions and the following disclaimer in the 1275374Sbp * documentation and/or other materials provided with the distribution. 1375374Sbp * 3. All advertising materials mentioning features or use of this software 1475374Sbp * must display the following acknowledgement: 1575374Sbp * This product includes software developed by Boris Popov. 1675374Sbp * 4. Neither the name of the author nor the names of any co-contributors 1775374Sbp * may be used to endorse or promote products derived from this software 1875374Sbp * without specific prior written permission. 1975374Sbp * 2075374Sbp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2175374Sbp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2275374Sbp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2375374Sbp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2475374Sbp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2575374Sbp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2675374Sbp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2775374Sbp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2875374Sbp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2975374Sbp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3075374Sbp * SUCH DAMAGE. 3175374Sbp * 3275374Sbp * $FreeBSD: head/sys/netsmb/smb_subr.c 82046 2001-08-21 09:16:57Z bp $ 3375374Sbp */ 3475374Sbp#include <sys/param.h> 3575374Sbp#include <sys/systm.h> 3675374Sbp#include <sys/kernel.h> 3775374Sbp#include <sys/malloc.h> 3875374Sbp#include <sys/proc.h> 3975374Sbp#include <sys/lock.h> 4075374Sbp#include <sys/sysctl.h> 4175374Sbp#include <sys/socket.h> 4275374Sbp#include <sys/signalvar.h> 4375374Sbp#include <sys/mbuf.h> 4475374Sbp 4575374Sbp#include <sys/iconv.h> 4675374Sbp 4775374Sbp#include <netsmb/smb.h> 4875374Sbp#include <netsmb/smb_conn.h> 4975374Sbp#include <netsmb/smb_rq.h> 5075374Sbp#include <netsmb/smb_subr.h> 5175374Sbp 5275374SbpMALLOC_DEFINE(M_SMBDATA, "SMBDATA", "Misc netsmb data"); 5375374SbpMALLOC_DEFINE(M_SMBSTR, "SMBSTR", "netsmb string data"); 5475374SbpMALLOC_DEFINE(M_SMBTEMP, "SMBTEMP", "Temp netsmb data"); 5575374Sbp 5675374Sbpsmb_unichar smb_unieol = 0; 5775374Sbp 5875374Sbpvoid 5975374Sbpsmb_makescred(struct smb_cred *scred, struct proc *p, struct ucred *cred) 6075374Sbp{ 6175374Sbp if (p) { 6275374Sbp scred->scr_p = p; 6375374Sbp scred->scr_cred = cred ? cred : p->p_ucred; 6475374Sbp } else { 6575374Sbp scred->scr_p = NULL; 6675374Sbp scred->scr_cred = cred ? cred : NULL; 6775374Sbp } 6875374Sbp} 6975374Sbp 7075374Sbpint 7175374Sbpsmb_proc_intr(struct proc *p) 7275374Sbp{ 7375374Sbp sigset_t tmpset; 7475374Sbp 7575374Sbp if (p == NULL) 7675374Sbp return 0; 7775374Sbp tmpset = p->p_siglist; 7875374Sbp SIGSETNAND(tmpset, p->p_sigmask); 7975374Sbp SIGSETNAND(tmpset, p->p_sigignore); 8075374Sbp if (SIGNOTEMPTY(p->p_siglist) && SMB_SIGMASK(tmpset)) 8175374Sbp return EINTR; 8275374Sbp return 0; 8375374Sbp} 8475374Sbp 8575374Sbpchar * 8675374Sbpsmb_strdup(const char *s) 8775374Sbp{ 8875374Sbp char *p; 8975374Sbp int len; 9075374Sbp 9175374Sbp len = s ? strlen(s) + 1 : 1; 9275374Sbp p = malloc(len, M_SMBSTR, M_WAITOK); 9375374Sbp if (s) 9475374Sbp bcopy(s, p, len); 9575374Sbp else 9675374Sbp *p = 0; 9775374Sbp return p; 9875374Sbp} 9975374Sbp 10075374Sbp/* 10175374Sbp * duplicate string from a user space. 10275374Sbp */ 10375374Sbpchar * 10475374Sbpsmb_strdupin(char *s, int maxlen) 10575374Sbp{ 10675374Sbp char *p, bt; 10775374Sbp int len = 0; 10875374Sbp 10975374Sbp for (p = s; ;p++) { 11075374Sbp if (copyin(p, &bt, 1)) 11175374Sbp return NULL; 11275374Sbp len++; 11375374Sbp if (maxlen && len > maxlen) 11475374Sbp return NULL; 11575374Sbp if (bt == 0) 11675374Sbp break; 11775374Sbp } 11875374Sbp p = malloc(len, M_SMBSTR, M_WAITOK); 11975374Sbp copyin(s, p, len); 12075374Sbp return p; 12175374Sbp} 12275374Sbp 12375374Sbp/* 12475374Sbp * duplicate memory block from a user space. 12575374Sbp */ 12675374Sbpvoid * 12775374Sbpsmb_memdupin(void *umem, int len) 12875374Sbp{ 12975374Sbp char *p; 13075374Sbp 13175374Sbp if (len > 8 * 1024) 13275374Sbp return NULL; 13375374Sbp p = malloc(len, M_SMBSTR, M_WAITOK); 13475374Sbp if (copyin(umem, p, len) == 0) 13575374Sbp return p; 13675374Sbp free(p, M_SMBSTR); 13775374Sbp return NULL; 13875374Sbp} 13975374Sbp 14075374Sbp/* 14175374Sbp * duplicate memory block in the kernel space. 14275374Sbp */ 14375374Sbpvoid * 14475374Sbpsmb_memdup(const void *umem, int len) 14575374Sbp{ 14675374Sbp char *p; 14775374Sbp 14875374Sbp if (len > 8 * 1024) 14975374Sbp return NULL; 15075374Sbp p = malloc(len, M_SMBSTR, M_WAITOK); 15175374Sbp if (p == NULL) 15275374Sbp return NULL; 15375374Sbp bcopy(umem, p, len); 15475374Sbp return p; 15575374Sbp} 15675374Sbp 15775374Sbpvoid 15875374Sbpsmb_strfree(char *s) 15975374Sbp{ 16075374Sbp free(s, M_SMBSTR); 16175374Sbp} 16275374Sbp 16375374Sbpvoid 16475374Sbpsmb_memfree(void *s) 16575374Sbp{ 16675374Sbp free(s, M_SMBSTR); 16775374Sbp} 16875374Sbp 16975374Sbpvoid * 17075374Sbpsmb_zmalloc(unsigned long size, struct malloc_type *type, int flags) 17175374Sbp{ 17275374Sbp 17375374Sbp return malloc(size, type, flags | M_ZERO); 17475374Sbp} 17575374Sbp 17675374Sbpvoid 17775374Sbpsmb_strtouni(u_int16_t *dst, const char *src) 17875374Sbp{ 17975374Sbp while (*src) { 18075374Sbp *dst++ = htoles(*src++); 18175374Sbp } 18275374Sbp *dst = 0; 18375374Sbp} 18475374Sbp 18575374Sbp#ifdef SMB_SOCKETDATA_DEBUG 18675374Sbpvoid 18775374Sbpm_dumpm(struct mbuf *m) { 18875374Sbp char *p; 18975374Sbp int len; 19075374Sbp printf("d="); 19175374Sbp while(m) { 19275374Sbp p=mtod(m,char *); 19375374Sbp len=m->m_len; 19475374Sbp printf("(%d)",len); 19575374Sbp while(len--){ 19675374Sbp printf("%02x ",((int)*(p++)) & 0xff); 19775374Sbp } 19875374Sbp m=m->m_next; 19975374Sbp }; 20075374Sbp printf("\n"); 20175374Sbp} 20275374Sbp#endif 20375374Sbp 20475374Sbpint 20575374Sbpsmb_maperror(int eclass, int eno) 20675374Sbp{ 20775374Sbp if (eclass == 0 && eno == 0) 20875374Sbp return 0; 20975374Sbp switch (eclass) { 21075374Sbp case ERRDOS: 21175374Sbp switch (eno) { 21275374Sbp case ERRbadfunc: 21375374Sbp case ERRbadmcb: 21475374Sbp case ERRbadenv: 21575374Sbp case ERRbadformat: 21675374Sbp case ERRrmuns: 21775374Sbp return EINVAL; 21875374Sbp case ERRbadfile: 21975374Sbp case ERRbadpath: 22075374Sbp case ERRremcd: 22175374Sbp case 66: /* nt returns it when share not available */ 22282046Sbp case 67: /* observed from nt4sp6 when sharename wrong */ 22375374Sbp return ENOENT; 22475374Sbp case ERRnofids: 22575374Sbp return EMFILE; 22675374Sbp case ERRnoaccess: 22775374Sbp case ERRbadshare: 22875374Sbp return EACCES; 22975374Sbp case ERRbadfid: 23075374Sbp return EBADF; 23175374Sbp case ERRnomem: 23275374Sbp return ENOMEM; /* actually remote no mem... */ 23375374Sbp case ERRbadmem: 23475374Sbp return EFAULT; 23575374Sbp case ERRbadaccess: 23675374Sbp return EACCES; 23775374Sbp case ERRbaddata: 23875374Sbp return E2BIG; 23975374Sbp case ERRbaddrive: 24075374Sbp case ERRnotready: /* nt */ 24175374Sbp return ENXIO; 24275374Sbp case ERRdiffdevice: 24375374Sbp return EXDEV; 24475374Sbp case ERRnofiles: 24575374Sbp return 0; /* eeof ? */ 24675374Sbp return ETXTBSY; 24775374Sbp case ERRlock: 24875374Sbp return EDEADLK; 24975374Sbp case ERRfilexists: 25075374Sbp return EEXIST; 25175374Sbp case 123: /* dunno what is it, but samba maps as noent */ 25275374Sbp return ENOENT; 25375374Sbp case 145: /* samba */ 25475374Sbp return ENOTEMPTY; 25575374Sbp case 183: 25675374Sbp return EEXIST; 25775374Sbp } 25875374Sbp break; 25975374Sbp case ERRSRV: 26075374Sbp switch (eno) { 26175374Sbp case ERRerror: 26275374Sbp return EINVAL; 26375374Sbp case ERRbadpw: 26475374Sbp return EAUTH; 26575374Sbp case ERRaccess: 26675374Sbp return EACCES; 26775374Sbp case ERRinvnid: 26875374Sbp return ENETRESET; 26975374Sbp case ERRinvnetname: 27075374Sbp SMBERROR("NetBIOS name is invalid\n"); 27175374Sbp return EAUTH; 27275374Sbp case 3: /* reserved and returned */ 27375374Sbp return EIO; 27475374Sbp case 2239: /* NT: account exists but disabled */ 27575374Sbp return EPERM; 27675374Sbp } 27775374Sbp break; 27875374Sbp case ERRHRD: 27975374Sbp switch (eno) { 28075374Sbp case ERRnowrite: 28175374Sbp return EROFS; 28275374Sbp case ERRbadunit: 28375374Sbp return ENODEV; 28475374Sbp case ERRnotready: 28575374Sbp case ERRbadcmd: 28675374Sbp case ERRdata: 28775374Sbp return EIO; 28875374Sbp case ERRbadreq: 28975374Sbp return EBADRPC; 29075374Sbp case ERRbadshare: 29175374Sbp return ETXTBSY; 29275374Sbp case ERRlock: 29375374Sbp return EDEADLK; 29475374Sbp } 29575374Sbp break; 29675374Sbp } 29775374Sbp SMBERROR("Unmapped error %d:%d\n", eclass, eno); 29875374Sbp return EBADRPC; 29975374Sbp} 30075374Sbp 30175374Sbpstatic int 30275374Sbpsmb_copy_iconv(struct mbchain *mbp, c_caddr_t src, caddr_t dst, int len) 30375374Sbp{ 30475374Sbp int outlen = len; 30575374Sbp 30675374Sbp return iconv_conv((struct iconv_drv*)mbp->mb_udata, &src, &len, &dst, &outlen); 30775374Sbp} 30875374Sbp 30975374Sbpint 31075374Sbpsmb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 31175374Sbp int size, int caseopt) 31275374Sbp{ 31375374Sbp struct iconv_drv *dp = vcp->vc_toserver; 31475374Sbp 31575374Sbp if (size == 0) 31675374Sbp return 0; 31775374Sbp if (dp == NULL) { 31875374Sbp return mb_put_mem(mbp, src, size, MB_MSYSTEM); 31975374Sbp } 32075374Sbp mbp->mb_copy = smb_copy_iconv; 32175374Sbp mbp->mb_udata = dp; 32275374Sbp return mb_put_mem(mbp, src, size, MB_MCUSTOM); 32375374Sbp} 32475374Sbp 32575374Sbpint 32675374Sbpsmb_put_dstring(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 32775374Sbp int caseopt) 32875374Sbp{ 32975374Sbp int error; 33075374Sbp 33175374Sbp error = smb_put_dmem(mbp, vcp, src, strlen(src), caseopt); 33275374Sbp if (error) 33375374Sbp return error; 33475374Sbp return mb_put_uint8(mbp, 0); 33575374Sbp} 33675374Sbp 33775374Sbpint 33875374Sbpsmb_put_asunistring(struct smb_rq *rqp, const char *src) 33975374Sbp{ 34075374Sbp struct mbchain *mbp = &rqp->sr_rq; 34175374Sbp struct iconv_drv *dp = rqp->sr_vc->vc_toserver; 34275374Sbp u_char c; 34375374Sbp int error; 34475374Sbp 34575374Sbp while (*src) { 34675374Sbp iconv_convmem(dp, &c, src++, 1); 34775374Sbp error = mb_put_uint16le(mbp, c); 34875374Sbp if (error) 34975374Sbp return error; 35075374Sbp } 35175374Sbp return mb_put_uint16le(mbp, 0); 35275374Sbp} 353