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$ 33 */ 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/malloc.h> 38 #include <sys/proc.h> 39 #include <sys/lock.h> 40 #include <sys/sysctl.h> 41 #include <sys/socket.h> 42 #include <sys/signalvar.h> 43 #include <sys/mbuf.h> 44 45 #include <sys/iconv.h> 46 47 #include <netsmb/smb.h> 48 #include <netsmb/smb_conn.h> 49 #include <netsmb/smb_rq.h> 50 #include <netsmb/smb_subr.h> 51 52 MALLOC_DEFINE(M_SMBDATA, "SMBDATA", "Misc netsmb data"); 53 MALLOC_DEFINE(M_SMBSTR, "SMBSTR", "netsmb string data"); 54 MALLOC_DEFINE(M_SMBTEMP, "SMBTEMP", "Temp netsmb data"); 55 56 smb_unichar smb_unieol = 0; 57 58 void 59 smb_makescred(struct smb_cred *scred, struct thread *td, struct ucred *cred) 60 { 61 if (td) { 62 scred->scr_td = td; 63 scred->scr_cred = cred ? cred : td->td_proc->p_ucred; 64 } else { 65 scred->scr_td = NULL; 66 scred->scr_cred = cred ? cred : NULL; 67 } 68 } 69 70 int 71 smb_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 85 char * 86 smb_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 */ 103 char * 104 smb_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 */ 126 void * 127 smb_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 */ 143 void * 144 smb_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 157 void 158 smb_strfree(char *s) 159 { 160 free(s, M_SMBSTR); 161 } 162 163 void 164 smb_memfree(void *s) 165 { 166 free(s, M_SMBSTR); 167 } 168 169 void * 170 smb_zmalloc(unsigned long size, struct malloc_type *type, int flags) 171 { 172 173 return malloc(size, type, flags | M_ZERO); 174 } 175 176 void 177 smb_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 186 void 187 m_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 204 int 205 smb_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 301 static int 302 smb_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 309 int 310 smb_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 325 int 326 smb_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 337 int 338 smb_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