xref: /titanic_44/usr/src/lib/libsmbfs/smb/rq.c (revision 21bf64a78855d076f09716ea1c06175d954e934c)
1 /*
2  * Copyright (c) 2000, 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  * $Id: rq.c,v 1.4 2004/12/13 00:25:23 lindak Exp $
33  */
34 
35 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/ioctl.h>
40 #include <sys/errno.h>
41 #include <sys/stat.h>
42 
43 #include <ctype.h>
44 #include <errno.h>
45 #include <stdio.h>
46 #include <unistd.h>
47 #include <strings.h>
48 #include <stdlib.h>
49 #include <sysexits.h>
50 #include <libintl.h>
51 
52 #include <netsmb/smb_lib.h>
53 
54 extern uid_t real_uid, eff_uid;
55 
56 
57 int
58 smb_rq_init(struct smb_ctx *ctx, uchar_t cmd, size_t rpbufsz,
59     struct smb_rq **rqpp)
60 {
61 	struct smb_rq *rqp;
62 
63 	rqp = malloc(sizeof (*rqp));
64 	if (rqp == NULL)
65 		return (ENOMEM);
66 	bzero(rqp, sizeof (*rqp));
67 	rqp->rq_cmd = cmd;
68 	rqp->rq_ctx = ctx;
69 	mb_init(&rqp->rq_rq, M_MINSIZE);
70 	mb_init(&rqp->rq_rp, rpbufsz);
71 	*rqpp = rqp;
72 	return (0);
73 }
74 
75 void
76 smb_rq_done(struct smb_rq *rqp)
77 {
78 	mb_done(&rqp->rq_rp);
79 	mb_done(&rqp->rq_rq);
80 	free(rqp);
81 }
82 
83 void
84 smb_rq_wend(struct smb_rq *rqp)
85 {
86 	if (rqp->rq_rq.mb_count & 1)
87 		smb_error(dgettext(TEXT_DOMAIN,
88 		    "smbrq_wend: odd word count\n"), 0);
89 	rqp->rq_wcount = rqp->rq_rq.mb_count / 2;
90 	rqp->rq_rq.mb_count = 0;
91 }
92 
93 int
94 smb_rq_dmem(struct mbdata *mbp, const char *src, size_t size)
95 {
96 	struct mbuf *m;
97 	char  *dst;
98 	int cplen, error;
99 
100 	if (size == 0)
101 		return (0);
102 	m = mbp->mb_cur;
103 	if ((error = m_getm(m, size, &m)) != 0)
104 		return (error);
105 	while (size > 0) {
106 		cplen = M_TRAILINGSPACE(m);
107 		if (cplen == 0) {
108 			m = m->m_next;
109 			continue;
110 		}
111 		if (cplen > (int)size)
112 			cplen = size;
113 		dst = mtod(m, char *) + m->m_len;
114 		nls_mem_toext(dst, src, cplen);
115 		size -= cplen;
116 		src += cplen;
117 		m->m_len += cplen;
118 		mbp->mb_count += cplen;
119 	}
120 	mbp->mb_pos = mtod(m, char *) + m->m_len;
121 	mbp->mb_cur = m;
122 	return (0);
123 }
124 
125 int
126 smb_rq_dstring(struct mbdata *mbp, const char *s)
127 {
128 	return (smb_rq_dmem(mbp, s, strlen(s) + 1));
129 }
130 
131 int
132 smb_rq_simple(struct smb_rq *rqp)
133 {
134 	struct smbioc_rq krq;
135 	struct mbdata *mbp;
136 	char *data;
137 	int i;
138 
139 	mbp = smb_rq_getrequest(rqp);
140 	m_lineup(mbp->mb_top, &mbp->mb_top);
141 	data = mtod(mbp->mb_top, char *);
142 	bzero(&krq, sizeof (krq));
143 	krq.ioc_cmd = rqp->rq_cmd;
144 	krq.ioc_twc = rqp->rq_wcount;
145 	krq.ioc_twords = data;
146 	krq.ioc_tbc = mbp->mb_count;
147 	krq.ioc_tbytes = data + rqp->rq_wcount * 2;
148 
149 	mbp = smb_rq_getreply(rqp);
150 	krq.ioc_rpbufsz = mbp->mb_top->m_maxlen;
151 	krq.ioc_rpbuf = mtod(mbp->mb_top, char *);
152 	seteuid(eff_uid);
153 	if (ioctl(rqp->rq_ctx->ct_fd, SMBIOC_REQUEST, &krq) == -1) {
154 		seteuid(real_uid); /* and back to real user */
155 		return (errno);
156 	}
157 	mbp->mb_top->m_len = krq.ioc_rwc * 2 + krq.ioc_rbc;
158 	rqp->rq_wcount = krq.ioc_rwc;
159 	rqp->rq_bcount = krq.ioc_rbc;
160 	seteuid(real_uid); /* and back to real user */
161 	return (0);
162 }
163 
164 
165 int
166 smb_t2_request(struct smb_ctx *ctx, int setupcount, uint16_t *setup,
167 	const char *name,
168 	int tparamcnt, void *tparam,
169 	int tdatacnt, void *tdata,
170 	int *rparamcnt, void *rparam,
171 	int *rdatacnt, void *rdata,
172 	int *buffer_oflow)
173 {
174 	smbioc_t2rq_t *krq;
175 	int i;
176 	char *pass;
177 
178 
179 	krq = (smbioc_t2rq_t *)malloc(sizeof (smbioc_t2rq_t));
180 	bzero(krq, sizeof (*krq));
181 
182 	if (setupcount < 0 || setupcount >= SMB_MAXSETUPWORDS) {
183 		/* Bogus setup count, or too many setup words */
184 		return (EINVAL);
185 	}
186 	for (i = 0; i < setupcount; i++)
187 		krq->ioc_setup[i] = setup[i];
188 	krq->ioc_setupcnt = setupcount;
189 	strcpy(krq->ioc_name, name);
190 	krq->ioc_tparamcnt = tparamcnt;
191 	krq->ioc_tparam = tparam;
192 	krq->ioc_tdatacnt = tdatacnt;
193 	krq->ioc_tdata = tdata;
194 
195 	krq->ioc_rparamcnt = *rparamcnt;
196 	krq->ioc_rdatacnt = *rdatacnt;
197 	krq->ioc_rparam = rparam;
198 	krq->ioc_rdata  = rdata;
199 
200 	seteuid(eff_uid);
201 	if (ioctl(ctx->ct_fd, SMBIOC_T2RQ, krq) == -1) {
202 		seteuid(real_uid); /* and back to real user */
203 		return (errno);
204 	}
205 
206 	*rparamcnt = krq->ioc_rparamcnt;
207 	*rdatacnt = krq->ioc_rdatacnt;
208 	*buffer_oflow = (krq->ioc_rpflags2 & SMB_FLAGS2_ERR_STATUS) &&
209 	    (krq->ioc_error == NT_STATUS_BUFFER_OVERFLOW);
210 	seteuid(real_uid); /* and back to real user */
211 	free(krq);
212 	return (0);
213 }
214