smb_subr.c revision 87192
152419Sjulian/* 252416Sjulian * Copyright (c) 2000-2001 Boris Popov 352416Sjulian * All rights reserved. 4156813Sru * 5156813Sru * Redistribution and use in source and binary forms, with or without 6136851Sru * modification, are permitted provided that the following conditions 7116808Sharti * are met: 8141726Sru * 1. Redistributions of source code must retain the above copyright 9124711Sru * notice, this list of conditions and the following disclaimer. 1079745Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 1179745Sbrooks * notice, this list of conditions and the following disclaimer in the 1279745Sbrooks * documentation and/or other materials provided with the distribution. 13141212Sru * 3. All advertising materials mentioning features or use of this software 1479745Sbrooks * must display the following acknowledgement: 1583366Sjulian * This product includes software developed by Boris Popov. 16102197Sarchie * 4. Neither the name of the author nor the names of any co-contributors 1779745Sbrooks * may be used to endorse or promote products derived from this software 18113757Swpaul * without specific prior written permission. 1979745Sbrooks * 2083998Sbrooks * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2183998Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2279745Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23128355Sru * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2479745Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2584053Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26141352Sglebius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2779745Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28102197Sarchie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2979745Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30124711Sru * SUCH DAMAGE. 31145965Sglebius * 32135335Sglebius * $FreeBSD: head/sys/netsmb/smb_subr.c 87192 2001-12-02 08:47:29Z bp $ 3379745Sbrooks */ 3479745Sbrooks#include <sys/param.h> 3579745Sbrooks#include <sys/systm.h> 3679745Sbrooks#include <sys/kernel.h> 3779745Sbrooks#include <sys/malloc.h> 3879745Sbrooks#include <sys/proc.h> 3979745Sbrooks#include <sys/lock.h> 40141746Sru#include <sys/sysctl.h> 4180305Sbrooks#include <sys/socket.h> 42128635Srik#include <sys/signalvar.h> 43140884Simp#include <sys/mbuf.h> 44140884Simp 45147232Sglebius#include <sys/iconv.h> 4679745Sbrooks 4779745Sbrooks#include <netsmb/smb.h> 48136851Sru#include <netsmb/smb_conn.h> 49126447Sru#include <netsmb/smb_rq.h> 50126447Sru#include <netsmb/smb_subr.h> 5152416Sjulian 52140884SimpMALLOC_DEFINE(M_SMBDATA, "SMBDATA", "Misc netsmb data"); 53140884SimpMALLOC_DEFINE(M_SMBSTR, "SMBSTR", "netsmb string data"); 54140884SimpMALLOC_DEFINE(M_SMBTEMP, "SMBTEMP", "Temp netsmb data"); 55140884Simp 56140884Simpsmb_unichar smb_unieol = 0; 57156813Sru 58124711Sruvoid 59107125Sjuliansmb_makescred(struct smb_cred *scred, struct thread *td, struct ucred *cred) 60131768Semax{ 61156813Sru if (td) { 62131768Semax scred->scr_td = td; 63125123Semax scred->scr_cred = cred ? cred : td->td_proc->p_ucred; 64107125Sjulian } else { 6552416Sjulian scred->scr_td = NULL; 66 scred->scr_cred = cred ? cred : NULL; 67 } 68} 69 70int 71smb_proc_intr(struct proc *p) 72{ 73 sigset_t tmpset; 74 75 if (p == NULL) 76 return 0; 77 tmpset = p->p_siglist; 78 SIGSETNAND(tmpset, p->p_sigmask); 79 SIGSETNAND(tmpset, p->p_sigignore); 80 if (SIGNOTEMPTY(p->p_siglist) && SMB_SIGMASK(tmpset)) 81 return EINTR; 82 return 0; 83} 84 85char * 86smb_strdup(const char *s) 87{ 88 char *p; 89 int len; 90 91 len = s ? strlen(s) + 1 : 1; 92 p = malloc(len, M_SMBSTR, M_WAITOK); 93 if (s) 94 bcopy(s, p, len); 95 else 96 *p = 0; 97 return p; 98} 99 100/* 101 * duplicate string from a user space. 102 */ 103char * 104smb_strdupin(char *s, int maxlen) 105{ 106 char *p, bt; 107 int len = 0; 108 109 for (p = s; ;p++) { 110 if (copyin(p, &bt, 1)) 111 return NULL; 112 len++; 113 if (maxlen && len > maxlen) 114 return NULL; 115 if (bt == 0) 116 break; 117 } 118 p = malloc(len, M_SMBSTR, M_WAITOK); 119 copyin(s, p, len); 120 return p; 121} 122 123/* 124 * duplicate memory block from a user space. 125 */ 126void * 127smb_memdupin(void *umem, int len) 128{ 129 char *p; 130 131 if (len > 8 * 1024) 132 return NULL; 133 p = malloc(len, M_SMBSTR, M_WAITOK); 134 if (copyin(umem, p, len) == 0) 135 return p; 136 free(p, M_SMBSTR); 137 return NULL; 138} 139 140/* 141 * duplicate memory block in the kernel space. 142 */ 143void * 144smb_memdup(const void *umem, int len) 145{ 146 char *p; 147 148 if (len > 8 * 1024) 149 return NULL; 150 p = malloc(len, M_SMBSTR, M_WAITOK); 151 if (p == NULL) 152 return NULL; 153 bcopy(umem, p, len); 154 return p; 155} 156 157void 158smb_strfree(char *s) 159{ 160 free(s, M_SMBSTR); 161} 162 163void 164smb_memfree(void *s) 165{ 166 free(s, M_SMBSTR); 167} 168 169void * 170smb_zmalloc(unsigned long size, struct malloc_type *type, int flags) 171{ 172 173 return malloc(size, type, flags | M_ZERO); 174} 175 176void 177smb_strtouni(u_int16_t *dst, const char *src) 178{ 179 while (*src) { 180 *dst++ = htoles(*src++); 181 } 182 *dst = 0; 183} 184 185#ifdef SMB_SOCKETDATA_DEBUG 186void 187m_dumpm(struct mbuf *m) { 188 char *p; 189 int len; 190 printf("d="); 191 while(m) { 192 p=mtod(m,char *); 193 len=m->m_len; 194 printf("(%d)",len); 195 while(len--){ 196 printf("%02x ",((int)*(p++)) & 0xff); 197 } 198 m=m->m_next; 199 }; 200 printf("\n"); 201} 202#endif 203 204int 205smb_maperror(int eclass, int eno) 206{ 207 if (eclass == 0 && eno == 0) 208 return 0; 209 switch (eclass) { 210 case ERRDOS: 211 switch (eno) { 212 case ERRbadfunc: 213 case ERRbadmcb: 214 case ERRbadenv: 215 case ERRbadformat: 216 case ERRrmuns: 217 return EINVAL; 218 case ERRbadfile: 219 case ERRbadpath: 220 case ERRremcd: 221 case 66: /* nt returns it when share not available */ 222 case 67: /* observed from nt4sp6 when sharename wrong */ 223 return ENOENT; 224 case ERRnofids: 225 return EMFILE; 226 case ERRnoaccess: 227 case ERRbadshare: 228 return EACCES; 229 case ERRbadfid: 230 return EBADF; 231 case ERRnomem: 232 return ENOMEM; /* actually remote no mem... */ 233 case ERRbadmem: 234 return EFAULT; 235 case ERRbadaccess: 236 return EACCES; 237 case ERRbaddata: 238 return E2BIG; 239 case ERRbaddrive: 240 case ERRnotready: /* nt */ 241 return ENXIO; 242 case ERRdiffdevice: 243 return EXDEV; 244 case ERRnofiles: 245 return 0; /* eeof ? */ 246 return ETXTBSY; 247 case ERRlock: 248 return EDEADLK; 249 case ERRfilexists: 250 return EEXIST; 251 case 123: /* dunno what is it, but samba maps as noent */ 252 return ENOENT; 253 case 145: /* samba */ 254 return ENOTEMPTY; 255 case 183: 256 return EEXIST; 257 } 258 break; 259 case ERRSRV: 260 switch (eno) { 261 case ERRerror: 262 return EINVAL; 263 case ERRbadpw: 264 return EAUTH; 265 case ERRaccess: 266 return EACCES; 267 case ERRinvnid: 268 return ENETRESET; 269 case ERRinvnetname: 270 SMBERROR("NetBIOS name is invalid\n"); 271 return EAUTH; 272 case 3: /* reserved and returned */ 273 return EIO; 274 case 2239: /* NT: account exists but disabled */ 275 return EPERM; 276 } 277 break; 278 case ERRHRD: 279 switch (eno) { 280 case ERRnowrite: 281 return EROFS; 282 case ERRbadunit: 283 return ENODEV; 284 case ERRnotready: 285 case ERRbadcmd: 286 case ERRdata: 287 return EIO; 288 case ERRbadreq: 289 return EBADRPC; 290 case ERRbadshare: 291 return ETXTBSY; 292 case ERRlock: 293 return EDEADLK; 294 } 295 break; 296 } 297 SMBERROR("Unmapped error %d:%d\n", eclass, eno); 298 return EBADRPC; 299} 300 301static int 302smb_copy_iconv(struct mbchain *mbp, c_caddr_t src, caddr_t dst, int len) 303{ 304 int outlen = len; 305 306 return iconv_conv((struct iconv_drv*)mbp->mb_udata, &src, &len, &dst, &outlen); 307} 308 309int 310smb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 311 int size, int caseopt) 312{ 313 struct iconv_drv *dp = vcp->vc_toserver; 314 315 if (size == 0) 316 return 0; 317 if (dp == NULL) { 318 return mb_put_mem(mbp, src, size, MB_MSYSTEM); 319 } 320 mbp->mb_copy = smb_copy_iconv; 321 mbp->mb_udata = dp; 322 return mb_put_mem(mbp, src, size, MB_MCUSTOM); 323} 324 325int 326smb_put_dstring(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 327 int caseopt) 328{ 329 int error; 330 331 error = smb_put_dmem(mbp, vcp, src, strlen(src), caseopt); 332 if (error) 333 return error; 334 return mb_put_uint8(mbp, 0); 335} 336 337int 338smb_put_asunistring(struct smb_rq *rqp, const char *src) 339{ 340 struct mbchain *mbp = &rqp->sr_rq; 341 struct iconv_drv *dp = rqp->sr_vc->vc_toserver; 342 u_char c; 343 int error; 344 345 while (*src) { 346 iconv_convmem(dp, &c, src++, 1); 347 error = mb_put_uint16le(mbp, c); 348 if (error) 349 return error; 350 } 351 return mb_put_uint16le(mbp, 0); 352} 353