smb_subr.c revision 148517
1139823Simp/*- 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 */ 32116189Sobrien 33116189Sobrien#include <sys/cdefs.h> 34116189Sobrien__FBSDID("$FreeBSD: head/sys/netsmb/smb_subr.c 148517 2005-07-29 13:22:37Z imura $"); 35116189Sobrien 3675374Sbp#include <sys/param.h> 3775374Sbp#include <sys/systm.h> 3895533Smike#include <sys/endian.h> 3975374Sbp#include <sys/kernel.h> 4075374Sbp#include <sys/malloc.h> 4175374Sbp#include <sys/proc.h> 4275374Sbp#include <sys/lock.h> 4375374Sbp#include <sys/sysctl.h> 4475374Sbp#include <sys/socket.h> 4575374Sbp#include <sys/signalvar.h> 4675374Sbp#include <sys/mbuf.h> 4775374Sbp 4875374Sbp#include <sys/iconv.h> 4975374Sbp 5075374Sbp#include <netsmb/smb.h> 5175374Sbp#include <netsmb/smb_conn.h> 5275374Sbp#include <netsmb/smb_rq.h> 5375374Sbp#include <netsmb/smb_subr.h> 5475374Sbp 5575374SbpMALLOC_DEFINE(M_SMBDATA, "SMBDATA", "Misc netsmb data"); 5675374SbpMALLOC_DEFINE(M_SMBSTR, "SMBSTR", "netsmb string data"); 5775374SbpMALLOC_DEFINE(M_SMBTEMP, "SMBTEMP", "Temp netsmb data"); 5875374Sbp 5975374Sbpsmb_unichar smb_unieol = 0; 6075374Sbp 6175374Sbpvoid 6287192Sbpsmb_makescred(struct smb_cred *scred, struct thread *td, struct ucred *cred) 6375374Sbp{ 6487192Sbp if (td) { 6587192Sbp scred->scr_td = td; 6691406Sjhb scred->scr_cred = cred ? cred : td->td_ucred; 6775374Sbp } else { 6887192Sbp scred->scr_td = NULL; 6975374Sbp scred->scr_cred = cred ? cred : NULL; 7075374Sbp } 7175374Sbp} 7275374Sbp 7375374Sbpint 74112888Sjeffsmb_td_intr(struct thread *td) 7575374Sbp{ 76112888Sjeff struct proc *p; 7775374Sbp sigset_t tmpset; 7875374Sbp 79112888Sjeff if (td == NULL) 8075374Sbp return 0; 81112888Sjeff 82112888Sjeff p = td->td_proc; 83110849Stjr PROC_LOCK(p); 84104306Sjmallett tmpset = p->p_siglist; 85112888Sjeff SIGSETOR(tmpset, td->td_siglist); 86112888Sjeff SIGSETNAND(tmpset, td->td_sigmask); 87114983Sjhb mtx_lock(&p->p_sigacts->ps_mtx); 88114983Sjhb SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore); 89114983Sjhb mtx_unlock(&p->p_sigacts->ps_mtx); 90112888Sjeff if (SIGNOTEMPTY(td->td_siglist) && SMB_SIGMASK(tmpset)) { 91110849Stjr PROC_UNLOCK(p); 9275374Sbp return EINTR; 93110849Stjr } 94110849Stjr PROC_UNLOCK(p); 9575374Sbp return 0; 9675374Sbp} 9775374Sbp 9875374Sbpchar * 9975374Sbpsmb_strdup(const char *s) 10075374Sbp{ 10175374Sbp char *p; 10275374Sbp int len; 10375374Sbp 10475374Sbp len = s ? strlen(s) + 1 : 1; 105111119Simp p = malloc(len, M_SMBSTR, M_WAITOK); 10675374Sbp if (s) 10775374Sbp bcopy(s, p, len); 10875374Sbp else 10975374Sbp *p = 0; 11075374Sbp return p; 11175374Sbp} 11275374Sbp 11375374Sbp/* 11475374Sbp * duplicate string from a user space. 11575374Sbp */ 11675374Sbpchar * 11775374Sbpsmb_strdupin(char *s, int maxlen) 11875374Sbp{ 11975374Sbp char *p, bt; 12075374Sbp int len = 0; 12175374Sbp 12275374Sbp for (p = s; ;p++) { 12375374Sbp if (copyin(p, &bt, 1)) 12475374Sbp return NULL; 12575374Sbp len++; 12675374Sbp if (maxlen && len > maxlen) 12775374Sbp return NULL; 12875374Sbp if (bt == 0) 12975374Sbp break; 13075374Sbp } 131111119Simp p = malloc(len, M_SMBSTR, M_WAITOK); 13275374Sbp copyin(s, p, len); 13375374Sbp return p; 13475374Sbp} 13575374Sbp 13675374Sbp/* 13775374Sbp * duplicate memory block from a user space. 13875374Sbp */ 13975374Sbpvoid * 14075374Sbpsmb_memdupin(void *umem, int len) 14175374Sbp{ 14275374Sbp char *p; 14375374Sbp 14475374Sbp if (len > 8 * 1024) 14575374Sbp return NULL; 146111119Simp p = malloc(len, M_SMBSTR, M_WAITOK); 14775374Sbp if (copyin(umem, p, len) == 0) 14875374Sbp return p; 14975374Sbp free(p, M_SMBSTR); 15075374Sbp return NULL; 15175374Sbp} 15275374Sbp 15375374Sbp/* 15475374Sbp * duplicate memory block in the kernel space. 15575374Sbp */ 15675374Sbpvoid * 15775374Sbpsmb_memdup(const void *umem, int len) 15875374Sbp{ 15975374Sbp char *p; 16075374Sbp 16175374Sbp if (len > 8 * 1024) 16275374Sbp return NULL; 163111119Simp p = malloc(len, M_SMBSTR, M_WAITOK); 16475374Sbp if (p == NULL) 16575374Sbp return NULL; 16675374Sbp bcopy(umem, p, len); 16775374Sbp return p; 16875374Sbp} 16975374Sbp 17075374Sbpvoid 17175374Sbpsmb_strfree(char *s) 17275374Sbp{ 17375374Sbp free(s, M_SMBSTR); 17475374Sbp} 17575374Sbp 17675374Sbpvoid 17775374Sbpsmb_memfree(void *s) 17875374Sbp{ 17975374Sbp free(s, M_SMBSTR); 18075374Sbp} 18175374Sbp 18275374Sbpvoid * 18375374Sbpsmb_zmalloc(unsigned long size, struct malloc_type *type, int flags) 18475374Sbp{ 18575374Sbp 18675374Sbp return malloc(size, type, flags | M_ZERO); 18775374Sbp} 18875374Sbp 18975374Sbpvoid 19075374Sbpsmb_strtouni(u_int16_t *dst, const char *src) 19175374Sbp{ 19275374Sbp while (*src) { 193107940Srobert *dst++ = htole16(*src++); 19475374Sbp } 19575374Sbp *dst = 0; 19675374Sbp} 19775374Sbp 19875374Sbp#ifdef SMB_SOCKETDATA_DEBUG 19975374Sbpvoid 20075374Sbpm_dumpm(struct mbuf *m) { 20175374Sbp char *p; 20275374Sbp int len; 20375374Sbp printf("d="); 20475374Sbp while(m) { 20575374Sbp p=mtod(m,char *); 20675374Sbp len=m->m_len; 20775374Sbp printf("(%d)",len); 20875374Sbp while(len--){ 20975374Sbp printf("%02x ",((int)*(p++)) & 0xff); 21075374Sbp } 21175374Sbp m=m->m_next; 21275374Sbp }; 21375374Sbp printf("\n"); 21475374Sbp} 21575374Sbp#endif 21675374Sbp 21775374Sbpint 21875374Sbpsmb_maperror(int eclass, int eno) 21975374Sbp{ 22075374Sbp if (eclass == 0 && eno == 0) 22175374Sbp return 0; 22275374Sbp switch (eclass) { 22375374Sbp case ERRDOS: 22475374Sbp switch (eno) { 22575374Sbp case ERRbadfunc: 22675374Sbp case ERRbadmcb: 22775374Sbp case ERRbadenv: 22875374Sbp case ERRbadformat: 22975374Sbp case ERRrmuns: 23075374Sbp return EINVAL; 23175374Sbp case ERRbadfile: 23275374Sbp case ERRbadpath: 23375374Sbp case ERRremcd: 23475374Sbp case 66: /* nt returns it when share not available */ 23582046Sbp case 67: /* observed from nt4sp6 when sharename wrong */ 23675374Sbp return ENOENT; 23775374Sbp case ERRnofids: 23875374Sbp return EMFILE; 23975374Sbp case ERRnoaccess: 24075374Sbp case ERRbadshare: 24175374Sbp return EACCES; 24275374Sbp case ERRbadfid: 24375374Sbp return EBADF; 24475374Sbp case ERRnomem: 24575374Sbp return ENOMEM; /* actually remote no mem... */ 24675374Sbp case ERRbadmem: 24775374Sbp return EFAULT; 24875374Sbp case ERRbadaccess: 24975374Sbp return EACCES; 25075374Sbp case ERRbaddata: 25175374Sbp return E2BIG; 25275374Sbp case ERRbaddrive: 25375374Sbp case ERRnotready: /* nt */ 25475374Sbp return ENXIO; 25575374Sbp case ERRdiffdevice: 25675374Sbp return EXDEV; 25775374Sbp case ERRnofiles: 25875374Sbp return 0; /* eeof ? */ 25975374Sbp return ETXTBSY; 26075374Sbp case ERRlock: 26175374Sbp return EDEADLK; 26275374Sbp case ERRfilexists: 26375374Sbp return EEXIST; 26475374Sbp case 123: /* dunno what is it, but samba maps as noent */ 26575374Sbp return ENOENT; 26675374Sbp case 145: /* samba */ 26775374Sbp return ENOTEMPTY; 26875374Sbp case 183: 26975374Sbp return EEXIST; 27094914Sbp case ERRquota: 27194914Sbp return EDQUOT; 27275374Sbp } 27375374Sbp break; 27475374Sbp case ERRSRV: 27575374Sbp switch (eno) { 27675374Sbp case ERRerror: 27775374Sbp return EINVAL; 27875374Sbp case ERRbadpw: 27994914Sbp case ERRpasswordExpired: 28075374Sbp return EAUTH; 28175374Sbp case ERRaccess: 28275374Sbp return EACCES; 28375374Sbp case ERRinvnid: 28475374Sbp return ENETRESET; 28575374Sbp case ERRinvnetname: 28675374Sbp SMBERROR("NetBIOS name is invalid\n"); 28775374Sbp return EAUTH; 28875374Sbp case 3: /* reserved and returned */ 28975374Sbp return EIO; 29094914Sbp case ERRaccountExpired: 29194914Sbp case ERRbadClient: 29294914Sbp case ERRbadLogonTime: 29375374Sbp return EPERM; 29494914Sbp case ERRnosupport: 29594914Sbp return EBADRPC; 29675374Sbp } 29775374Sbp break; 29875374Sbp case ERRHRD: 29975374Sbp switch (eno) { 30075374Sbp case ERRnowrite: 30175374Sbp return EROFS; 30275374Sbp case ERRbadunit: 30375374Sbp return ENODEV; 30475374Sbp case ERRnotready: 30575374Sbp case ERRbadcmd: 30675374Sbp case ERRdata: 30775374Sbp return EIO; 30875374Sbp case ERRbadreq: 30975374Sbp return EBADRPC; 31075374Sbp case ERRbadshare: 31175374Sbp return ETXTBSY; 31275374Sbp case ERRlock: 31375374Sbp return EDEADLK; 31475374Sbp } 31575374Sbp break; 31675374Sbp } 31775374Sbp SMBERROR("Unmapped error %d:%d\n", eclass, eno); 31875374Sbp return EBADRPC; 31975374Sbp} 32075374Sbp 32175374Sbpstatic int 322148517Simurasmb_copy_iconv(struct mbchain *mbp, c_caddr_t src, caddr_t dst, 323148517Simura size_t *srclen, size_t *dstlen) 32475374Sbp{ 325148517Simura int error; 326148517Simura size_t inlen = *srclen, outlen = *dstlen; 32775374Sbp 328148517Simura error = iconv_conv((struct iconv_drv*)mbp->mb_udata, &src, &inlen, 329148517Simura &dst, &outlen); 330148517Simura if (inlen != *srclen || outlen != *dstlen) { 331148517Simura *srclen -= inlen; 332148517Simura *dstlen -= outlen; 333148517Simura return 0; 334148517Simura } else 335148517Simura return error; 33675374Sbp} 33775374Sbp 33875374Sbpint 33975374Sbpsmb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 34075374Sbp int size, int caseopt) 34175374Sbp{ 34275374Sbp struct iconv_drv *dp = vcp->vc_toserver; 34375374Sbp 34475374Sbp if (size == 0) 34575374Sbp return 0; 34675374Sbp if (dp == NULL) { 34775374Sbp return mb_put_mem(mbp, src, size, MB_MSYSTEM); 34875374Sbp } 34975374Sbp mbp->mb_copy = smb_copy_iconv; 35075374Sbp mbp->mb_udata = dp; 35175374Sbp return mb_put_mem(mbp, src, size, MB_MCUSTOM); 35275374Sbp} 35375374Sbp 35475374Sbpint 35575374Sbpsmb_put_dstring(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 35675374Sbp int caseopt) 35775374Sbp{ 35875374Sbp int error; 35975374Sbp 36075374Sbp error = smb_put_dmem(mbp, vcp, src, strlen(src), caseopt); 36175374Sbp if (error) 36275374Sbp return error; 36375374Sbp return mb_put_uint8(mbp, 0); 36475374Sbp} 36575374Sbp 36675374Sbpint 36775374Sbpsmb_put_asunistring(struct smb_rq *rqp, const char *src) 36875374Sbp{ 36975374Sbp struct mbchain *mbp = &rqp->sr_rq; 37075374Sbp struct iconv_drv *dp = rqp->sr_vc->vc_toserver; 37175374Sbp u_char c; 37275374Sbp int error; 37375374Sbp 37475374Sbp while (*src) { 37575374Sbp iconv_convmem(dp, &c, src++, 1); 37675374Sbp error = mb_put_uint16le(mbp, c); 37775374Sbp if (error) 37875374Sbp return error; 37975374Sbp } 38075374Sbp return mb_put_uint16le(mbp, 0); 38175374Sbp} 382