smb_subr.c revision 110849
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 110849 2003-02-14 09:12:12Z tjr $ 3375374Sbp */ 3475374Sbp#include <sys/param.h> 3575374Sbp#include <sys/systm.h> 3695533Smike#include <sys/endian.h> 3775374Sbp#include <sys/kernel.h> 3875374Sbp#include <sys/malloc.h> 3975374Sbp#include <sys/proc.h> 4075374Sbp#include <sys/lock.h> 4175374Sbp#include <sys/sysctl.h> 4275374Sbp#include <sys/socket.h> 4375374Sbp#include <sys/signalvar.h> 4475374Sbp#include <sys/mbuf.h> 4575374Sbp 4675374Sbp#include <sys/iconv.h> 4775374Sbp 4875374Sbp#include <netsmb/smb.h> 4975374Sbp#include <netsmb/smb_conn.h> 5075374Sbp#include <netsmb/smb_rq.h> 5175374Sbp#include <netsmb/smb_subr.h> 5275374Sbp 5375374SbpMALLOC_DEFINE(M_SMBDATA, "SMBDATA", "Misc netsmb data"); 5475374SbpMALLOC_DEFINE(M_SMBSTR, "SMBSTR", "netsmb string data"); 5575374SbpMALLOC_DEFINE(M_SMBTEMP, "SMBTEMP", "Temp netsmb data"); 5675374Sbp 5775374Sbpsmb_unichar smb_unieol = 0; 5875374Sbp 5975374Sbpvoid 6087192Sbpsmb_makescred(struct smb_cred *scred, struct thread *td, struct ucred *cred) 6175374Sbp{ 6287192Sbp if (td) { 6387192Sbp scred->scr_td = td; 6491406Sjhb scred->scr_cred = cred ? cred : td->td_ucred; 6575374Sbp } else { 6687192Sbp scred->scr_td = NULL; 6775374Sbp scred->scr_cred = cred ? cred : NULL; 6875374Sbp } 6975374Sbp} 7075374Sbp 7175374Sbpint 7275374Sbpsmb_proc_intr(struct proc *p) 7375374Sbp{ 7475374Sbp sigset_t tmpset; 7575374Sbp 7675374Sbp if (p == NULL) 7775374Sbp return 0; 78110849Stjr PROC_LOCK(p); 79104306Sjmallett tmpset = p->p_siglist; 8075374Sbp SIGSETNAND(tmpset, p->p_sigmask); 8175374Sbp SIGSETNAND(tmpset, p->p_sigignore); 82110849Stjr if (SIGNOTEMPTY(p->p_siglist) && SMB_SIGMASK(tmpset)) { 83110849Stjr PROC_UNLOCK(p); 8475374Sbp return EINTR; 85110849Stjr } 86110849Stjr PROC_UNLOCK(p); 8775374Sbp return 0; 8875374Sbp} 8975374Sbp 9075374Sbpchar * 9175374Sbpsmb_strdup(const char *s) 9275374Sbp{ 9375374Sbp char *p; 9475374Sbp int len; 9575374Sbp 9675374Sbp len = s ? strlen(s) + 1 : 1; 97109623Salfred p = malloc(len, M_SMBSTR, 0); 9875374Sbp if (s) 9975374Sbp bcopy(s, p, len); 10075374Sbp else 10175374Sbp *p = 0; 10275374Sbp return p; 10375374Sbp} 10475374Sbp 10575374Sbp/* 10675374Sbp * duplicate string from a user space. 10775374Sbp */ 10875374Sbpchar * 10975374Sbpsmb_strdupin(char *s, int maxlen) 11075374Sbp{ 11175374Sbp char *p, bt; 11275374Sbp int len = 0; 11375374Sbp 11475374Sbp for (p = s; ;p++) { 11575374Sbp if (copyin(p, &bt, 1)) 11675374Sbp return NULL; 11775374Sbp len++; 11875374Sbp if (maxlen && len > maxlen) 11975374Sbp return NULL; 12075374Sbp if (bt == 0) 12175374Sbp break; 12275374Sbp } 123109623Salfred p = malloc(len, M_SMBSTR, 0); 12475374Sbp copyin(s, p, len); 12575374Sbp return p; 12675374Sbp} 12775374Sbp 12875374Sbp/* 12975374Sbp * duplicate memory block from a user space. 13075374Sbp */ 13175374Sbpvoid * 13275374Sbpsmb_memdupin(void *umem, int len) 13375374Sbp{ 13475374Sbp char *p; 13575374Sbp 13675374Sbp if (len > 8 * 1024) 13775374Sbp return NULL; 138109623Salfred p = malloc(len, M_SMBSTR, 0); 13975374Sbp if (copyin(umem, p, len) == 0) 14075374Sbp return p; 14175374Sbp free(p, M_SMBSTR); 14275374Sbp return NULL; 14375374Sbp} 14475374Sbp 14575374Sbp/* 14675374Sbp * duplicate memory block in the kernel space. 14775374Sbp */ 14875374Sbpvoid * 14975374Sbpsmb_memdup(const void *umem, int len) 15075374Sbp{ 15175374Sbp char *p; 15275374Sbp 15375374Sbp if (len > 8 * 1024) 15475374Sbp return NULL; 155109623Salfred p = malloc(len, M_SMBSTR, 0); 15675374Sbp if (p == NULL) 15775374Sbp return NULL; 15875374Sbp bcopy(umem, p, len); 15975374Sbp return p; 16075374Sbp} 16175374Sbp 16275374Sbpvoid 16375374Sbpsmb_strfree(char *s) 16475374Sbp{ 16575374Sbp free(s, M_SMBSTR); 16675374Sbp} 16775374Sbp 16875374Sbpvoid 16975374Sbpsmb_memfree(void *s) 17075374Sbp{ 17175374Sbp free(s, M_SMBSTR); 17275374Sbp} 17375374Sbp 17475374Sbpvoid * 17575374Sbpsmb_zmalloc(unsigned long size, struct malloc_type *type, int flags) 17675374Sbp{ 17775374Sbp 17875374Sbp return malloc(size, type, flags | M_ZERO); 17975374Sbp} 18075374Sbp 18175374Sbpvoid 18275374Sbpsmb_strtouni(u_int16_t *dst, const char *src) 18375374Sbp{ 18475374Sbp while (*src) { 185107940Srobert *dst++ = htole16(*src++); 18675374Sbp } 18775374Sbp *dst = 0; 18875374Sbp} 18975374Sbp 19075374Sbp#ifdef SMB_SOCKETDATA_DEBUG 19175374Sbpvoid 19275374Sbpm_dumpm(struct mbuf *m) { 19375374Sbp char *p; 19475374Sbp int len; 19575374Sbp printf("d="); 19675374Sbp while(m) { 19775374Sbp p=mtod(m,char *); 19875374Sbp len=m->m_len; 19975374Sbp printf("(%d)",len); 20075374Sbp while(len--){ 20175374Sbp printf("%02x ",((int)*(p++)) & 0xff); 20275374Sbp } 20375374Sbp m=m->m_next; 20475374Sbp }; 20575374Sbp printf("\n"); 20675374Sbp} 20775374Sbp#endif 20875374Sbp 20975374Sbpint 21075374Sbpsmb_maperror(int eclass, int eno) 21175374Sbp{ 21275374Sbp if (eclass == 0 && eno == 0) 21375374Sbp return 0; 21475374Sbp switch (eclass) { 21575374Sbp case ERRDOS: 21675374Sbp switch (eno) { 21775374Sbp case ERRbadfunc: 21875374Sbp case ERRbadmcb: 21975374Sbp case ERRbadenv: 22075374Sbp case ERRbadformat: 22175374Sbp case ERRrmuns: 22275374Sbp return EINVAL; 22375374Sbp case ERRbadfile: 22475374Sbp case ERRbadpath: 22575374Sbp case ERRremcd: 22675374Sbp case 66: /* nt returns it when share not available */ 22782046Sbp case 67: /* observed from nt4sp6 when sharename wrong */ 22875374Sbp return ENOENT; 22975374Sbp case ERRnofids: 23075374Sbp return EMFILE; 23175374Sbp case ERRnoaccess: 23275374Sbp case ERRbadshare: 23375374Sbp return EACCES; 23475374Sbp case ERRbadfid: 23575374Sbp return EBADF; 23675374Sbp case ERRnomem: 23775374Sbp return ENOMEM; /* actually remote no mem... */ 23875374Sbp case ERRbadmem: 23975374Sbp return EFAULT; 24075374Sbp case ERRbadaccess: 24175374Sbp return EACCES; 24275374Sbp case ERRbaddata: 24375374Sbp return E2BIG; 24475374Sbp case ERRbaddrive: 24575374Sbp case ERRnotready: /* nt */ 24675374Sbp return ENXIO; 24775374Sbp case ERRdiffdevice: 24875374Sbp return EXDEV; 24975374Sbp case ERRnofiles: 25075374Sbp return 0; /* eeof ? */ 25175374Sbp return ETXTBSY; 25275374Sbp case ERRlock: 25375374Sbp return EDEADLK; 25475374Sbp case ERRfilexists: 25575374Sbp return EEXIST; 25675374Sbp case 123: /* dunno what is it, but samba maps as noent */ 25775374Sbp return ENOENT; 25875374Sbp case 145: /* samba */ 25975374Sbp return ENOTEMPTY; 26075374Sbp case 183: 26175374Sbp return EEXIST; 26294914Sbp case ERRquota: 26394914Sbp return EDQUOT; 26475374Sbp } 26575374Sbp break; 26675374Sbp case ERRSRV: 26775374Sbp switch (eno) { 26875374Sbp case ERRerror: 26975374Sbp return EINVAL; 27075374Sbp case ERRbadpw: 27194914Sbp case ERRpasswordExpired: 27275374Sbp return EAUTH; 27375374Sbp case ERRaccess: 27475374Sbp return EACCES; 27575374Sbp case ERRinvnid: 27675374Sbp return ENETRESET; 27775374Sbp case ERRinvnetname: 27875374Sbp SMBERROR("NetBIOS name is invalid\n"); 27975374Sbp return EAUTH; 28075374Sbp case 3: /* reserved and returned */ 28175374Sbp return EIO; 28294914Sbp case ERRaccountExpired: 28394914Sbp case ERRbadClient: 28494914Sbp case ERRbadLogonTime: 28575374Sbp return EPERM; 28694914Sbp case ERRnosupport: 28794914Sbp return EBADRPC; 28875374Sbp } 28975374Sbp break; 29075374Sbp case ERRHRD: 29175374Sbp switch (eno) { 29275374Sbp case ERRnowrite: 29375374Sbp return EROFS; 29475374Sbp case ERRbadunit: 29575374Sbp return ENODEV; 29675374Sbp case ERRnotready: 29775374Sbp case ERRbadcmd: 29875374Sbp case ERRdata: 29975374Sbp return EIO; 30075374Sbp case ERRbadreq: 30175374Sbp return EBADRPC; 30275374Sbp case ERRbadshare: 30375374Sbp return ETXTBSY; 30475374Sbp case ERRlock: 30575374Sbp return EDEADLK; 30675374Sbp } 30775374Sbp break; 30875374Sbp } 30975374Sbp SMBERROR("Unmapped error %d:%d\n", eclass, eno); 31075374Sbp return EBADRPC; 31175374Sbp} 31275374Sbp 31375374Sbpstatic int 314106667Sjhbsmb_copy_iconv(struct mbchain *mbp, c_caddr_t src, caddr_t dst, size_t len) 31575374Sbp{ 316106667Sjhb size_t outlen = len; 31775374Sbp 31875374Sbp return iconv_conv((struct iconv_drv*)mbp->mb_udata, &src, &len, &dst, &outlen); 31975374Sbp} 32075374Sbp 32175374Sbpint 32275374Sbpsmb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 32375374Sbp int size, int caseopt) 32475374Sbp{ 32575374Sbp struct iconv_drv *dp = vcp->vc_toserver; 32675374Sbp 32775374Sbp if (size == 0) 32875374Sbp return 0; 32975374Sbp if (dp == NULL) { 33075374Sbp return mb_put_mem(mbp, src, size, MB_MSYSTEM); 33175374Sbp } 33275374Sbp mbp->mb_copy = smb_copy_iconv; 33375374Sbp mbp->mb_udata = dp; 33475374Sbp return mb_put_mem(mbp, src, size, MB_MCUSTOM); 33575374Sbp} 33675374Sbp 33775374Sbpint 33875374Sbpsmb_put_dstring(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 33975374Sbp int caseopt) 34075374Sbp{ 34175374Sbp int error; 34275374Sbp 34375374Sbp error = smb_put_dmem(mbp, vcp, src, strlen(src), caseopt); 34475374Sbp if (error) 34575374Sbp return error; 34675374Sbp return mb_put_uint8(mbp, 0); 34775374Sbp} 34875374Sbp 34975374Sbpint 35075374Sbpsmb_put_asunistring(struct smb_rq *rqp, const char *src) 35175374Sbp{ 35275374Sbp struct mbchain *mbp = &rqp->sr_rq; 35375374Sbp struct iconv_drv *dp = rqp->sr_vc->vc_toserver; 35475374Sbp u_char c; 35575374Sbp int error; 35675374Sbp 35775374Sbp while (*src) { 35875374Sbp iconv_convmem(dp, &c, src++, 1); 35975374Sbp error = mb_put_uint16le(mbp, c); 36075374Sbp if (error) 36175374Sbp return error; 36275374Sbp } 36375374Sbp return mb_put_uint16le(mbp, 0); 36475374Sbp} 365