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_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 90 char * 91 smb_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 */ 108 char * 109 smb_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 */ 131 void * 132 smb_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 */ 148 void * 149 smb_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 162 void 163 smb_strfree(char *s) 164 { 165 free(s, M_SMBSTR); 166 } 167 168 void 169 smb_memfree(void *s) 170 { 171 free(s, M_SMBSTR); 172 } 173 174 void * 175 smb_zmalloc(unsigned long size, struct malloc_type *type, int flags) 176 { 177 178 return malloc(size, type, flags | M_ZERO); 179 } 180 181 void 182 smb_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 191 void 192 m_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 209 int 210 smb_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 313 static int 314 smb_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 321 int 322 smb_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 337 int 338 smb_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 349 int 350 smb_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