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