smb_subr.c revision 87192
152419Sjulian/*
252416Sjulian * Copyright (c) 2000-2001 Boris Popov
352416Sjulian * All rights reserved.
4156813Sru *
5156813Sru * Redistribution and use in source and binary forms, with or without
6136851Sru * modification, are permitted provided that the following conditions
7116808Sharti * are met:
8141726Sru * 1. Redistributions of source code must retain the above copyright
9124711Sru *    notice, this list of conditions and the following disclaimer.
1079745Sbrooks * 2. Redistributions in binary form must reproduce the above copyright
1179745Sbrooks *    notice, this list of conditions and the following disclaimer in the
1279745Sbrooks *    documentation and/or other materials provided with the distribution.
13141212Sru * 3. All advertising materials mentioning features or use of this software
1479745Sbrooks *    must display the following acknowledgement:
1583366Sjulian *    This product includes software developed by Boris Popov.
16102197Sarchie * 4. Neither the name of the author nor the names of any co-contributors
1779745Sbrooks *    may be used to endorse or promote products derived from this software
18113757Swpaul *    without specific prior written permission.
1979745Sbrooks *
2083998Sbrooks * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2183998Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2279745Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23128355Sru * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2479745Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2584053Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26141352Sglebius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2779745Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28102197Sarchie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2979745Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30124711Sru * SUCH DAMAGE.
31145965Sglebius *
32135335Sglebius * $FreeBSD: head/sys/netsmb/smb_subr.c 87192 2001-12-02 08:47:29Z bp $
3379745Sbrooks */
3479745Sbrooks#include <sys/param.h>
3579745Sbrooks#include <sys/systm.h>
3679745Sbrooks#include <sys/kernel.h>
3779745Sbrooks#include <sys/malloc.h>
3879745Sbrooks#include <sys/proc.h>
3979745Sbrooks#include <sys/lock.h>
40141746Sru#include <sys/sysctl.h>
4180305Sbrooks#include <sys/socket.h>
42128635Srik#include <sys/signalvar.h>
43140884Simp#include <sys/mbuf.h>
44140884Simp
45147232Sglebius#include <sys/iconv.h>
4679745Sbrooks
4779745Sbrooks#include <netsmb/smb.h>
48136851Sru#include <netsmb/smb_conn.h>
49126447Sru#include <netsmb/smb_rq.h>
50126447Sru#include <netsmb/smb_subr.h>
5152416Sjulian
52140884SimpMALLOC_DEFINE(M_SMBDATA, "SMBDATA", "Misc netsmb data");
53140884SimpMALLOC_DEFINE(M_SMBSTR, "SMBSTR", "netsmb string data");
54140884SimpMALLOC_DEFINE(M_SMBTEMP, "SMBTEMP", "Temp netsmb data");
55140884Simp
56140884Simpsmb_unichar smb_unieol = 0;
57156813Sru
58124711Sruvoid
59107125Sjuliansmb_makescred(struct smb_cred *scred, struct thread *td, struct ucred *cred)
60131768Semax{
61156813Sru	if (td) {
62131768Semax		scred->scr_td = td;
63125123Semax		scred->scr_cred = cred ? cred : td->td_proc->p_ucred;
64107125Sjulian	} else {
6552416Sjulian		scred->scr_td = NULL;
66		scred->scr_cred = cred ? cred : NULL;
67	}
68}
69
70int
71smb_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
85char *
86smb_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 */
103char *
104smb_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 */
126void *
127smb_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 */
143void *
144smb_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
157void
158smb_strfree(char *s)
159{
160	free(s, M_SMBSTR);
161}
162
163void
164smb_memfree(void *s)
165{
166	free(s, M_SMBSTR);
167}
168
169void *
170smb_zmalloc(unsigned long size, struct malloc_type *type, int flags)
171{
172
173	return malloc(size, type, flags | M_ZERO);
174}
175
176void
177smb_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
186void
187m_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
204int
205smb_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
301static int
302smb_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
309int
310smb_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
325int
326smb_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
337int
338smb_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