smb_subr.c revision 111119
1/* 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD: head/sys/netsmb/smb_subr.c 111119 2003-02-19 05:47:46Z imp $ 33 */ 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/endian.h> 37#include <sys/kernel.h> 38#include <sys/malloc.h> 39#include <sys/proc.h> 40#include <sys/lock.h> 41#include <sys/sysctl.h> 42#include <sys/socket.h> 43#include <sys/signalvar.h> 44#include <sys/mbuf.h> 45 46#include <sys/iconv.h> 47 48#include <netsmb/smb.h> 49#include <netsmb/smb_conn.h> 50#include <netsmb/smb_rq.h> 51#include <netsmb/smb_subr.h> 52 53MALLOC_DEFINE(M_SMBDATA, "SMBDATA", "Misc netsmb data"); 54MALLOC_DEFINE(M_SMBSTR, "SMBSTR", "netsmb string data"); 55MALLOC_DEFINE(M_SMBTEMP, "SMBTEMP", "Temp netsmb data"); 56 57smb_unichar smb_unieol = 0; 58 59void 60smb_makescred(struct smb_cred *scred, struct thread *td, struct ucred *cred) 61{ 62 if (td) { 63 scred->scr_td = td; 64 scred->scr_cred = cred ? cred : td->td_ucred; 65 } else { 66 scred->scr_td = NULL; 67 scred->scr_cred = cred ? cred : NULL; 68 } 69} 70 71int 72smb_proc_intr(struct proc *p) 73{ 74 sigset_t tmpset; 75 76 if (p == NULL) 77 return 0; 78 PROC_LOCK(p); 79 tmpset = p->p_siglist; 80 SIGSETNAND(tmpset, p->p_sigmask); 81 SIGSETNAND(tmpset, p->p_sigignore); 82 if (SIGNOTEMPTY(p->p_siglist) && SMB_SIGMASK(tmpset)) { 83 PROC_UNLOCK(p); 84 return EINTR; 85 } 86 PROC_UNLOCK(p); 87 return 0; 88} 89 90char * 91smb_strdup(const char *s) 92{ 93 char *p; 94 int len; 95 96 len = s ? strlen(s) + 1 : 1; 97 p = malloc(len, M_SMBSTR, M_WAITOK); 98 if (s) 99 bcopy(s, p, len); 100 else 101 *p = 0; 102 return p; 103} 104 105/* 106 * duplicate string from a user space. 107 */ 108char * 109smb_strdupin(char *s, int maxlen) 110{ 111 char *p, bt; 112 int len = 0; 113 114 for (p = s; ;p++) { 115 if (copyin(p, &bt, 1)) 116 return NULL; 117 len++; 118 if (maxlen && len > maxlen) 119 return NULL; 120 if (bt == 0) 121 break; 122 } 123 p = malloc(len, M_SMBSTR, M_WAITOK); 124 copyin(s, p, len); 125 return p; 126} 127 128/* 129 * duplicate memory block from a user space. 130 */ 131void * 132smb_memdupin(void *umem, int len) 133{ 134 char *p; 135 136 if (len > 8 * 1024) 137 return NULL; 138 p = malloc(len, M_SMBSTR, M_WAITOK); 139 if (copyin(umem, p, len) == 0) 140 return p; 141 free(p, M_SMBSTR); 142 return NULL; 143} 144 145/* 146 * duplicate memory block in the kernel space. 147 */ 148void * 149smb_memdup(const void *umem, int len) 150{ 151 char *p; 152 153 if (len > 8 * 1024) 154 return NULL; 155 p = malloc(len, M_SMBSTR, M_WAITOK); 156 if (p == NULL) 157 return NULL; 158 bcopy(umem, p, len); 159 return p; 160} 161 162void 163smb_strfree(char *s) 164{ 165 free(s, M_SMBSTR); 166} 167 168void 169smb_memfree(void *s) 170{ 171 free(s, M_SMBSTR); 172} 173 174void * 175smb_zmalloc(unsigned long size, struct malloc_type *type, int flags) 176{ 177 178 return malloc(size, type, flags | M_ZERO); 179} 180 181void 182smb_strtouni(u_int16_t *dst, const char *src) 183{ 184 while (*src) { 185 *dst++ = htole16(*src++); 186 } 187 *dst = 0; 188} 189 190#ifdef SMB_SOCKETDATA_DEBUG 191void 192m_dumpm(struct mbuf *m) { 193 char *p; 194 int len; 195 printf("d="); 196 while(m) { 197 p=mtod(m,char *); 198 len=m->m_len; 199 printf("(%d)",len); 200 while(len--){ 201 printf("%02x ",((int)*(p++)) & 0xff); 202 } 203 m=m->m_next; 204 }; 205 printf("\n"); 206} 207#endif 208 209int 210smb_maperror(int eclass, int eno) 211{ 212 if (eclass == 0 && eno == 0) 213 return 0; 214 switch (eclass) { 215 case ERRDOS: 216 switch (eno) { 217 case ERRbadfunc: 218 case ERRbadmcb: 219 case ERRbadenv: 220 case ERRbadformat: 221 case ERRrmuns: 222 return EINVAL; 223 case ERRbadfile: 224 case ERRbadpath: 225 case ERRremcd: 226 case 66: /* nt returns it when share not available */ 227 case 67: /* observed from nt4sp6 when sharename wrong */ 228 return ENOENT; 229 case ERRnofids: 230 return EMFILE; 231 case ERRnoaccess: 232 case ERRbadshare: 233 return EACCES; 234 case ERRbadfid: 235 return EBADF; 236 case ERRnomem: 237 return ENOMEM; /* actually remote no mem... */ 238 case ERRbadmem: 239 return EFAULT; 240 case ERRbadaccess: 241 return EACCES; 242 case ERRbaddata: 243 return E2BIG; 244 case ERRbaddrive: 245 case ERRnotready: /* nt */ 246 return ENXIO; 247 case ERRdiffdevice: 248 return EXDEV; 249 case ERRnofiles: 250 return 0; /* eeof ? */ 251 return ETXTBSY; 252 case ERRlock: 253 return EDEADLK; 254 case ERRfilexists: 255 return EEXIST; 256 case 123: /* dunno what is it, but samba maps as noent */ 257 return ENOENT; 258 case 145: /* samba */ 259 return ENOTEMPTY; 260 case 183: 261 return EEXIST; 262 case ERRquota: 263 return EDQUOT; 264 } 265 break; 266 case ERRSRV: 267 switch (eno) { 268 case ERRerror: 269 return EINVAL; 270 case ERRbadpw: 271 case ERRpasswordExpired: 272 return EAUTH; 273 case ERRaccess: 274 return EACCES; 275 case ERRinvnid: 276 return ENETRESET; 277 case ERRinvnetname: 278 SMBERROR("NetBIOS name is invalid\n"); 279 return EAUTH; 280 case 3: /* reserved and returned */ 281 return EIO; 282 case ERRaccountExpired: 283 case ERRbadClient: 284 case ERRbadLogonTime: 285 return EPERM; 286 case ERRnosupport: 287 return EBADRPC; 288 } 289 break; 290 case ERRHRD: 291 switch (eno) { 292 case ERRnowrite: 293 return EROFS; 294 case ERRbadunit: 295 return ENODEV; 296 case ERRnotready: 297 case ERRbadcmd: 298 case ERRdata: 299 return EIO; 300 case ERRbadreq: 301 return EBADRPC; 302 case ERRbadshare: 303 return ETXTBSY; 304 case ERRlock: 305 return EDEADLK; 306 } 307 break; 308 } 309 SMBERROR("Unmapped error %d:%d\n", eclass, eno); 310 return EBADRPC; 311} 312 313static int 314smb_copy_iconv(struct mbchain *mbp, c_caddr_t src, caddr_t dst, size_t len) 315{ 316 size_t outlen = len; 317 318 return iconv_conv((struct iconv_drv*)mbp->mb_udata, &src, &len, &dst, &outlen); 319} 320 321int 322smb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 323 int size, int caseopt) 324{ 325 struct iconv_drv *dp = vcp->vc_toserver; 326 327 if (size == 0) 328 return 0; 329 if (dp == NULL) { 330 return mb_put_mem(mbp, src, size, MB_MSYSTEM); 331 } 332 mbp->mb_copy = smb_copy_iconv; 333 mbp->mb_udata = dp; 334 return mb_put_mem(mbp, src, size, MB_MCUSTOM); 335} 336 337int 338smb_put_dstring(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 339 int caseopt) 340{ 341 int error; 342 343 error = smb_put_dmem(mbp, vcp, src, strlen(src), caseopt); 344 if (error) 345 return error; 346 return mb_put_uint8(mbp, 0); 347} 348 349int 350smb_put_asunistring(struct smb_rq *rqp, const char *src) 351{ 352 struct mbchain *mbp = &rqp->sr_rq; 353 struct iconv_drv *dp = rqp->sr_vc->vc_toserver; 354 u_char c; 355 int error; 356 357 while (*src) { 358 iconv_convmem(dp, &c, src++, 1); 359 error = mb_put_uint16le(mbp, c); 360 if (error) 361 return error; 362 } 363 return mb_put_uint16le(mbp, 0); 364} 365