smb_subr.c revision 107940
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 107940 2002-12-16 16:20:06Z robert $ 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; 78104306Sjmallett tmpset = p->p_siglist; 7975374Sbp SIGSETNAND(tmpset, p->p_sigmask); 8075374Sbp SIGSETNAND(tmpset, p->p_sigignore); 81104306Sjmallett if (SIGNOTEMPTY(p->p_siglist) && SMB_SIGMASK(tmpset)) 8275374Sbp return EINTR; 8375374Sbp return 0; 8475374Sbp} 8575374Sbp 8675374Sbpchar * 8775374Sbpsmb_strdup(const char *s) 8875374Sbp{ 8975374Sbp char *p; 9075374Sbp int len; 9175374Sbp 9275374Sbp len = s ? strlen(s) + 1 : 1; 9375374Sbp p = malloc(len, M_SMBSTR, M_WAITOK); 9475374Sbp if (s) 9575374Sbp bcopy(s, p, len); 9675374Sbp else 9775374Sbp *p = 0; 9875374Sbp return p; 9975374Sbp} 10075374Sbp 10175374Sbp/* 10275374Sbp * duplicate string from a user space. 10375374Sbp */ 10475374Sbpchar * 10575374Sbpsmb_strdupin(char *s, int maxlen) 10675374Sbp{ 10775374Sbp char *p, bt; 10875374Sbp int len = 0; 10975374Sbp 11075374Sbp for (p = s; ;p++) { 11175374Sbp if (copyin(p, &bt, 1)) 11275374Sbp return NULL; 11375374Sbp len++; 11475374Sbp if (maxlen && len > maxlen) 11575374Sbp return NULL; 11675374Sbp if (bt == 0) 11775374Sbp break; 11875374Sbp } 11975374Sbp p = malloc(len, M_SMBSTR, M_WAITOK); 12075374Sbp copyin(s, p, len); 12175374Sbp return p; 12275374Sbp} 12375374Sbp 12475374Sbp/* 12575374Sbp * duplicate memory block from a user space. 12675374Sbp */ 12775374Sbpvoid * 12875374Sbpsmb_memdupin(void *umem, int len) 12975374Sbp{ 13075374Sbp char *p; 13175374Sbp 13275374Sbp if (len > 8 * 1024) 13375374Sbp return NULL; 13475374Sbp p = malloc(len, M_SMBSTR, M_WAITOK); 13575374Sbp if (copyin(umem, p, len) == 0) 13675374Sbp return p; 13775374Sbp free(p, M_SMBSTR); 13875374Sbp return NULL; 13975374Sbp} 14075374Sbp 14175374Sbp/* 14275374Sbp * duplicate memory block in the kernel space. 14375374Sbp */ 14475374Sbpvoid * 14575374Sbpsmb_memdup(const void *umem, int len) 14675374Sbp{ 14775374Sbp char *p; 14875374Sbp 14975374Sbp if (len > 8 * 1024) 15075374Sbp return NULL; 15175374Sbp p = malloc(len, M_SMBSTR, M_WAITOK); 15275374Sbp if (p == NULL) 15375374Sbp return NULL; 15475374Sbp bcopy(umem, p, len); 15575374Sbp return p; 15675374Sbp} 15775374Sbp 15875374Sbpvoid 15975374Sbpsmb_strfree(char *s) 16075374Sbp{ 16175374Sbp free(s, M_SMBSTR); 16275374Sbp} 16375374Sbp 16475374Sbpvoid 16575374Sbpsmb_memfree(void *s) 16675374Sbp{ 16775374Sbp free(s, M_SMBSTR); 16875374Sbp} 16975374Sbp 17075374Sbpvoid * 17175374Sbpsmb_zmalloc(unsigned long size, struct malloc_type *type, int flags) 17275374Sbp{ 17375374Sbp 17475374Sbp return malloc(size, type, flags | M_ZERO); 17575374Sbp} 17675374Sbp 17775374Sbpvoid 17875374Sbpsmb_strtouni(u_int16_t *dst, const char *src) 17975374Sbp{ 18075374Sbp while (*src) { 181107940Srobert *dst++ = htole16(*src++); 18275374Sbp } 18375374Sbp *dst = 0; 18475374Sbp} 18575374Sbp 18675374Sbp#ifdef SMB_SOCKETDATA_DEBUG 18775374Sbpvoid 18875374Sbpm_dumpm(struct mbuf *m) { 18975374Sbp char *p; 19075374Sbp int len; 19175374Sbp printf("d="); 19275374Sbp while(m) { 19375374Sbp p=mtod(m,char *); 19475374Sbp len=m->m_len; 19575374Sbp printf("(%d)",len); 19675374Sbp while(len--){ 19775374Sbp printf("%02x ",((int)*(p++)) & 0xff); 19875374Sbp } 19975374Sbp m=m->m_next; 20075374Sbp }; 20175374Sbp printf("\n"); 20275374Sbp} 20375374Sbp#endif 20475374Sbp 20575374Sbpint 20675374Sbpsmb_maperror(int eclass, int eno) 20775374Sbp{ 20875374Sbp if (eclass == 0 && eno == 0) 20975374Sbp return 0; 21075374Sbp switch (eclass) { 21175374Sbp case ERRDOS: 21275374Sbp switch (eno) { 21375374Sbp case ERRbadfunc: 21475374Sbp case ERRbadmcb: 21575374Sbp case ERRbadenv: 21675374Sbp case ERRbadformat: 21775374Sbp case ERRrmuns: 21875374Sbp return EINVAL; 21975374Sbp case ERRbadfile: 22075374Sbp case ERRbadpath: 22175374Sbp case ERRremcd: 22275374Sbp case 66: /* nt returns it when share not available */ 22382046Sbp case 67: /* observed from nt4sp6 when sharename wrong */ 22475374Sbp return ENOENT; 22575374Sbp case ERRnofids: 22675374Sbp return EMFILE; 22775374Sbp case ERRnoaccess: 22875374Sbp case ERRbadshare: 22975374Sbp return EACCES; 23075374Sbp case ERRbadfid: 23175374Sbp return EBADF; 23275374Sbp case ERRnomem: 23375374Sbp return ENOMEM; /* actually remote no mem... */ 23475374Sbp case ERRbadmem: 23575374Sbp return EFAULT; 23675374Sbp case ERRbadaccess: 23775374Sbp return EACCES; 23875374Sbp case ERRbaddata: 23975374Sbp return E2BIG; 24075374Sbp case ERRbaddrive: 24175374Sbp case ERRnotready: /* nt */ 24275374Sbp return ENXIO; 24375374Sbp case ERRdiffdevice: 24475374Sbp return EXDEV; 24575374Sbp case ERRnofiles: 24675374Sbp return 0; /* eeof ? */ 24775374Sbp return ETXTBSY; 24875374Sbp case ERRlock: 24975374Sbp return EDEADLK; 25075374Sbp case ERRfilexists: 25175374Sbp return EEXIST; 25275374Sbp case 123: /* dunno what is it, but samba maps as noent */ 25375374Sbp return ENOENT; 25475374Sbp case 145: /* samba */ 25575374Sbp return ENOTEMPTY; 25675374Sbp case 183: 25775374Sbp return EEXIST; 25894914Sbp case ERRquota: 25994914Sbp return EDQUOT; 26075374Sbp } 26175374Sbp break; 26275374Sbp case ERRSRV: 26375374Sbp switch (eno) { 26475374Sbp case ERRerror: 26575374Sbp return EINVAL; 26675374Sbp case ERRbadpw: 26794914Sbp case ERRpasswordExpired: 26875374Sbp return EAUTH; 26975374Sbp case ERRaccess: 27075374Sbp return EACCES; 27175374Sbp case ERRinvnid: 27275374Sbp return ENETRESET; 27375374Sbp case ERRinvnetname: 27475374Sbp SMBERROR("NetBIOS name is invalid\n"); 27575374Sbp return EAUTH; 27675374Sbp case 3: /* reserved and returned */ 27775374Sbp return EIO; 27894914Sbp case ERRaccountExpired: 27994914Sbp case ERRbadClient: 28094914Sbp case ERRbadLogonTime: 28175374Sbp return EPERM; 28294914Sbp case ERRnosupport: 28394914Sbp return EBADRPC; 28475374Sbp } 28575374Sbp break; 28675374Sbp case ERRHRD: 28775374Sbp switch (eno) { 28875374Sbp case ERRnowrite: 28975374Sbp return EROFS; 29075374Sbp case ERRbadunit: 29175374Sbp return ENODEV; 29275374Sbp case ERRnotready: 29375374Sbp case ERRbadcmd: 29475374Sbp case ERRdata: 29575374Sbp return EIO; 29675374Sbp case ERRbadreq: 29775374Sbp return EBADRPC; 29875374Sbp case ERRbadshare: 29975374Sbp return ETXTBSY; 30075374Sbp case ERRlock: 30175374Sbp return EDEADLK; 30275374Sbp } 30375374Sbp break; 30475374Sbp } 30575374Sbp SMBERROR("Unmapped error %d:%d\n", eclass, eno); 30675374Sbp return EBADRPC; 30775374Sbp} 30875374Sbp 30975374Sbpstatic int 310106667Sjhbsmb_copy_iconv(struct mbchain *mbp, c_caddr_t src, caddr_t dst, size_t len) 31175374Sbp{ 312106667Sjhb size_t outlen = len; 31375374Sbp 31475374Sbp return iconv_conv((struct iconv_drv*)mbp->mb_udata, &src, &len, &dst, &outlen); 31575374Sbp} 31675374Sbp 31775374Sbpint 31875374Sbpsmb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 31975374Sbp int size, int caseopt) 32075374Sbp{ 32175374Sbp struct iconv_drv *dp = vcp->vc_toserver; 32275374Sbp 32375374Sbp if (size == 0) 32475374Sbp return 0; 32575374Sbp if (dp == NULL) { 32675374Sbp return mb_put_mem(mbp, src, size, MB_MSYSTEM); 32775374Sbp } 32875374Sbp mbp->mb_copy = smb_copy_iconv; 32975374Sbp mbp->mb_udata = dp; 33075374Sbp return mb_put_mem(mbp, src, size, MB_MCUSTOM); 33175374Sbp} 33275374Sbp 33375374Sbpint 33475374Sbpsmb_put_dstring(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 33575374Sbp int caseopt) 33675374Sbp{ 33775374Sbp int error; 33875374Sbp 33975374Sbp error = smb_put_dmem(mbp, vcp, src, strlen(src), caseopt); 34075374Sbp if (error) 34175374Sbp return error; 34275374Sbp return mb_put_uint8(mbp, 0); 34375374Sbp} 34475374Sbp 34575374Sbpint 34675374Sbpsmb_put_asunistring(struct smb_rq *rqp, const char *src) 34775374Sbp{ 34875374Sbp struct mbchain *mbp = &rqp->sr_rq; 34975374Sbp struct iconv_drv *dp = rqp->sr_vc->vc_toserver; 35075374Sbp u_char c; 35175374Sbp int error; 35275374Sbp 35375374Sbp while (*src) { 35475374Sbp iconv_convmem(dp, &c, src++, 1); 35575374Sbp error = mb_put_uint16le(mbp, c); 35675374Sbp if (error) 35775374Sbp return error; 35875374Sbp } 35975374Sbp return mb_put_uint16le(mbp, 0); 36075374Sbp} 361