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/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 53 MALLOC_DEFINE(M_SMBDATA, "SMBDATA", "Misc netsmb data"); 54 MALLOC_DEFINE(M_SMBSTR, "SMBSTR", "netsmb string data"); 55 MALLOC_DEFINE(M_SMBTEMP, "SMBTEMP", "Temp netsmb data"); 56 57 smb_unichar smb_unieol = 0; 58 59 void 60 smb_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 71 int 72 smb_td_intr(struct thread *td) 73 { 74 struct proc *p; 75 sigset_t tmpset; 76 77 if (td == NULL) 78 return 0; 79 80 p = td->td_proc; 81 PROC_LOCK(p); 82 tmpset = p->p_siglist; 83 SIGSETOR(tmpset, td->td_siglist); 84 SIGSETNAND(tmpset, td->td_sigmask); 85 mtx_lock(&p->p_sigacts->ps_mtx); 86 SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore); 87 mtx_unlock(&p->p_sigacts->ps_mtx); 88 if (SIGNOTEMPTY(td->td_siglist) && SMB_SIGMASK(tmpset)) { 89 PROC_UNLOCK(p); 90 return EINTR; 91 } 92 PROC_UNLOCK(p); 93 return 0; 94 } 95 96 char * 97 smb_strdup(const char *s) 98 { 99 char *p; 100 int len; 101 102 len = s ? strlen(s) + 1 : 1; 103 p = malloc(len, M_SMBSTR, M_WAITOK); 104 if (s) 105 bcopy(s, p, len); 106 else 107 *p = 0; 108 return p; 109 } 110 111 /* 112 * duplicate string from a user space. 113 */ 114 char * 115 smb_strdupin(char *s, int maxlen) 116 { 117 char *p, bt; 118 int len = 0; 119 120 for (p = s; ;p++) { 121 if (copyin(p, &bt, 1)) 122 return NULL; 123 len++; 124 if (maxlen && len > maxlen) 125 return NULL; 126 if (bt == 0) 127 break; 128 } 129 p = malloc(len, M_SMBSTR, M_WAITOK); 130 copyin(s, p, len); 131 return p; 132 } 133 134 /* 135 * duplicate memory block from a user space. 136 */ 137 void * 138 smb_memdupin(void *umem, int len) 139 { 140 char *p; 141 142 if (len > 8 * 1024) 143 return NULL; 144 p = malloc(len, M_SMBSTR, M_WAITOK); 145 if (copyin(umem, p, len) == 0) 146 return p; 147 free(p, M_SMBSTR); 148 return NULL; 149 } 150 151 /* 152 * duplicate memory block in the kernel space. 153 */ 154 void * 155 smb_memdup(const void *umem, int len) 156 { 157 char *p; 158 159 if (len > 8 * 1024) 160 return NULL; 161 p = malloc(len, M_SMBSTR, M_WAITOK); 162 if (p == NULL) 163 return NULL; 164 bcopy(umem, p, len); 165 return p; 166 } 167 168 void 169 smb_strfree(char *s) 170 { 171 free(s, M_SMBSTR); 172 } 173 174 void 175 smb_memfree(void *s) 176 { 177 free(s, M_SMBSTR); 178 } 179 180 void * 181 smb_zmalloc(unsigned long size, struct malloc_type *type, int flags) 182 { 183 184 return malloc(size, type, flags | M_ZERO); 185 } 186 187 void 188 smb_strtouni(u_int16_t *dst, const char *src) 189 { 190 while (*src) { 191 *dst++ = htole16(*src++); 192 } 193 *dst = 0; 194 } 195 196 #ifdef SMB_SOCKETDATA_DEBUG 197 void 198 m_dumpm(struct mbuf *m) { 199 char *p; 200 int len; 201 printf("d="); 202 while(m) { 203 p=mtod(m,char *); 204 len=m->m_len; 205 printf("(%d)",len); 206 while(len--){ 207 printf("%02x ",((int)*(p++)) & 0xff); 208 } 209 m=m->m_next; 210 }; 211 printf("\n"); 212 } 213 #endif 214 215 int 216 smb_maperror(int eclass, int eno) 217 { 218 if (eclass == 0 && eno == 0) 219 return 0; 220 switch (eclass) { 221 case ERRDOS: 222 switch (eno) { 223 case ERRbadfunc: 224 case ERRbadmcb: 225 case ERRbadenv: 226 case ERRbadformat: 227 case ERRrmuns: 228 return EINVAL; 229 case ERRbadfile: 230 case ERRbadpath: 231 case ERRremcd: 232 case 66: /* nt returns it when share not available */ 233 case 67: /* observed from nt4sp6 when sharename wrong */ 234 return ENOENT; 235 case ERRnofids: 236 return EMFILE; 237 case ERRnoaccess: 238 case ERRbadshare: 239 return EACCES; 240 case ERRbadfid: 241 return EBADF; 242 case ERRnomem: 243 return ENOMEM; /* actually remote no mem... */ 244 case ERRbadmem: 245 return EFAULT; 246 case ERRbadaccess: 247 return EACCES; 248 case ERRbaddata: 249 return E2BIG; 250 case ERRbaddrive: 251 case ERRnotready: /* nt */ 252 return ENXIO; 253 case ERRdiffdevice: 254 return EXDEV; 255 case ERRnofiles: 256 return 0; /* eeof ? */ 257 return ETXTBSY; 258 case ERRlock: 259 return EDEADLK; 260 case ERRfilexists: 261 return EEXIST; 262 case 123: /* dunno what is it, but samba maps as noent */ 263 return ENOENT; 264 case 145: /* samba */ 265 return ENOTEMPTY; 266 case 183: 267 return EEXIST; 268 case ERRquota: 269 return EDQUOT; 270 } 271 break; 272 case ERRSRV: 273 switch (eno) { 274 case ERRerror: 275 return EINVAL; 276 case ERRbadpw: 277 case ERRpasswordExpired: 278 return EAUTH; 279 case ERRaccess: 280 return EACCES; 281 case ERRinvnid: 282 return ENETRESET; 283 case ERRinvnetname: 284 SMBERROR("NetBIOS name is invalid\n"); 285 return EAUTH; 286 case 3: /* reserved and returned */ 287 return EIO; 288 case ERRaccountExpired: 289 case ERRbadClient: 290 case ERRbadLogonTime: 291 return EPERM; 292 case ERRnosupport: 293 return EBADRPC; 294 } 295 break; 296 case ERRHRD: 297 switch (eno) { 298 case ERRnowrite: 299 return EROFS; 300 case ERRbadunit: 301 return ENODEV; 302 case ERRnotready: 303 case ERRbadcmd: 304 case ERRdata: 305 return EIO; 306 case ERRbadreq: 307 return EBADRPC; 308 case ERRbadshare: 309 return ETXTBSY; 310 case ERRlock: 311 return EDEADLK; 312 } 313 break; 314 } 315 SMBERROR("Unmapped error %d:%d\n", eclass, eno); 316 return EBADRPC; 317 } 318 319 static int 320 smb_copy_iconv(struct mbchain *mbp, c_caddr_t src, caddr_t dst, size_t len) 321 { 322 size_t outlen = len; 323 324 return iconv_conv((struct iconv_drv*)mbp->mb_udata, &src, &len, &dst, &outlen); 325 } 326 327 int 328 smb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 329 int size, int caseopt) 330 { 331 struct iconv_drv *dp = vcp->vc_toserver; 332 333 if (size == 0) 334 return 0; 335 if (dp == NULL) { 336 return mb_put_mem(mbp, src, size, MB_MSYSTEM); 337 } 338 mbp->mb_copy = smb_copy_iconv; 339 mbp->mb_udata = dp; 340 return mb_put_mem(mbp, src, size, MB_MCUSTOM); 341 } 342 343 int 344 smb_put_dstring(struct mbchain *mbp, struct smb_vc *vcp, const char *src, 345 int caseopt) 346 { 347 int error; 348 349 error = smb_put_dmem(mbp, vcp, src, strlen(src), caseopt); 350 if (error) 351 return error; 352 return mb_put_uint8(mbp, 0); 353 } 354 355 int 356 smb_put_asunistring(struct smb_rq *rqp, const char *src) 357 { 358 struct mbchain *mbp = &rqp->sr_rq; 359 struct iconv_drv *dp = rqp->sr_vc->vc_toserver; 360 u_char c; 361 int error; 362 363 while (*src) { 364 iconv_convmem(dp, &c, src++, 1); 365 error = mb_put_uint16le(mbp, c); 366 if (error) 367 return error; 368 } 369 return mb_put_uint16le(mbp, 0); 370 } 371