FreeBSD/Linux Kernel Cross Reference
sys/netsmb/smb_usr.c
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: releng/5.1/sys/netsmb/smb_usr.c 103543 2002-09-18 14:21:52Z phk $
33 */
34 #include <sys/param.h>
35 #include <sys/malloc.h>
36 #include <sys/kernel.h>
37 #include <sys/systm.h>
38 #include <sys/conf.h>
39 #include <sys/proc.h>
40 #include <sys/fcntl.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
43 #include <sys/sysctl.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 #include <netsmb/smb_dev.h>
53
54 /*
55 * helpers for nsmb device. Can be moved to the smb_dev.c file.
56 */
57 static void smb_usr_vcspec_free(struct smb_vcspec *spec);
58
59 static int
60 smb_usr_vc2spec(struct smbioc_ossn *dp, struct smb_vcspec *spec)
61 {
62 int flags = 0;
63
64 bzero(spec, sizeof(*spec));
65
66 #ifdef NETSMB_NO_ANON_USER
67 if (dp->ioc_user[0] == 0)
68 return EINVAL;
69 #endif
70
71 if (dp->ioc_server == NULL)
72 return EINVAL;
73 if (dp->ioc_localcs[0] == 0) {
74 SMBERROR("no local charset ?\n");
75 return EINVAL;
76 }
77
78 spec->sap = smb_memdupin(dp->ioc_server, dp->ioc_svlen);
79 if (spec->sap == NULL)
80 return ENOMEM;
81 if (dp->ioc_local) {
82 spec->lap = smb_memdupin(dp->ioc_local, dp->ioc_lolen);
83 if (spec->lap == NULL) {
84 smb_usr_vcspec_free(spec);
85 return ENOMEM;
86 }
87 }
88 spec->srvname = dp->ioc_srvname;
89 spec->pass = dp->ioc_password;
90 spec->domain = dp->ioc_workgroup;
91 spec->username = dp->ioc_user;
92 spec->mode = dp->ioc_mode;
93 spec->rights = dp->ioc_rights;
94 spec->owner = dp->ioc_owner;
95 spec->group = dp->ioc_group;
96 spec->localcs = dp->ioc_localcs;
97 spec->servercs = dp->ioc_servercs;
98 if (dp->ioc_opt & SMBVOPT_PRIVATE)
99 flags |= SMBV_PRIVATE;
100 if (dp->ioc_opt & SMBVOPT_SINGLESHARE)
101 flags |= SMBV_PRIVATE | SMBV_SINGLESHARE;
102 spec->flags = flags;
103 return 0;
104 }
105
106 static void
107 smb_usr_vcspec_free(struct smb_vcspec *spec)
108 {
109 if (spec->sap)
110 smb_memfree(spec->sap);
111 if (spec->lap)
112 smb_memfree(spec->lap);
113 }
114
115 static int
116 smb_usr_share2spec(struct smbioc_oshare *dp, struct smb_sharespec *spec)
117 {
118 bzero(spec, sizeof(*spec));
119 spec->mode = dp->ioc_mode;
120 spec->rights = dp->ioc_rights;
121 spec->owner = dp->ioc_owner;
122 spec->group = dp->ioc_group;
123 spec->name = dp->ioc_share;
124 spec->stype = dp->ioc_stype;
125 spec->pass = dp->ioc_password;
126 return 0;
127 }
128
129 int
130 smb_usr_lookup(struct smbioc_lookup *dp, struct smb_cred *scred,
131 struct smb_vc **vcpp, struct smb_share **sspp)
132 {
133 struct smb_vc *vcp = NULL;
134 struct smb_vcspec vspec;
135 struct smb_sharespec sspec, *sspecp = NULL;
136 int error;
137
138 if (dp->ioc_level < SMBL_VC || dp->ioc_level > SMBL_SHARE)
139 return EINVAL;
140 error = smb_usr_vc2spec(&dp->ioc_ssn, &vspec);
141 if (error)
142 return error;
143 if (dp->ioc_flags & SMBLK_CREATE)
144 vspec.flags |= SMBV_CREATE;
145
146 if (dp->ioc_level >= SMBL_SHARE) {
147 error = smb_usr_share2spec(&dp->ioc_sh, &sspec);
148 if (error)
149 goto out;
150 sspecp = &sspec;
151 }
152 error = smb_sm_lookup(&vspec, sspecp, scred, &vcp);
153 if (error == 0) {
154 *vcpp = vcp;
155 *sspp = vspec.ssp;
156 }
157 out:
158 smb_usr_vcspec_free(&vspec);
159 return error;
160 }
161
162 /*
163 * Connect to the resource specified by smbioc_ossn structure.
164 * It may either find an existing connection or try to establish a new one.
165 * If no errors occured smb_vc returned locked and referenced.
166 */
167 int
168 smb_usr_opensession(struct smbioc_ossn *dp, struct smb_cred *scred,
169 struct smb_vc **vcpp)
170 {
171 struct smb_vc *vcp = NULL;
172 struct smb_vcspec vspec;
173 int error;
174
175 error = smb_usr_vc2spec(dp, &vspec);
176 if (error)
177 return error;
178 if (dp->ioc_opt & SMBVOPT_CREATE)
179 vspec.flags |= SMBV_CREATE;
180
181 error = smb_sm_lookup(&vspec, NULL, scred, &vcp);
182 smb_usr_vcspec_free(&vspec);
183 return error;
184 }
185
186 int
187 smb_usr_openshare(struct smb_vc *vcp, struct smbioc_oshare *dp,
188 struct smb_cred *scred, struct smb_share **sspp)
189 {
190 struct smb_share *ssp;
191 struct smb_sharespec shspec;
192 int error;
193
194 error = smb_usr_share2spec(dp, &shspec);
195 if (error)
196 return error;
197 error = smb_vc_lookupshare(vcp, &shspec, scred, &ssp);
198 if (error == 0) {
199 *sspp = ssp;
200 return 0;
201 }
202 if ((dp->ioc_opt & SMBSOPT_CREATE) == 0)
203 return error;
204 error = smb_share_create(vcp, &shspec, scred, &ssp);
205 if (error)
206 return error;
207 error = smb_smb_treeconnect(ssp, scred);
208 if (error) {
209 smb_share_put(ssp, scred);
210 } else
211 *sspp = ssp;
212 return error;
213 }
214
215 int
216 smb_usr_simplerequest(struct smb_share *ssp, struct smbioc_rq *dp,
217 struct smb_cred *scred)
218 {
219 struct smb_rq rq, *rqp = &rq;
220 struct mbchain *mbp;
221 struct mdchain *mdp;
222 u_int8_t wc;
223 u_int16_t bc;
224 int error;
225
226 switch (dp->ioc_cmd) {
227 case SMB_COM_TRANSACTION2:
228 case SMB_COM_TRANSACTION2_SECONDARY:
229 case SMB_COM_CLOSE_AND_TREE_DISC:
230 case SMB_COM_TREE_CONNECT:
231 case SMB_COM_TREE_DISCONNECT:
232 case SMB_COM_NEGOTIATE:
233 case SMB_COM_SESSION_SETUP_ANDX:
234 case SMB_COM_LOGOFF_ANDX:
235 case SMB_COM_TREE_CONNECT_ANDX:
236 return EPERM;
237 }
238 error = smb_rq_init(rqp, SSTOCP(ssp), dp->ioc_cmd, scred);
239 if (error)
240 return error;
241 mbp = &rqp->sr_rq;
242 smb_rq_wstart(rqp);
243 error = mb_put_mem(mbp, dp->ioc_twords, dp->ioc_twc * 2, MB_MUSER);
244 if (error)
245 goto bad;
246 smb_rq_wend(rqp);
247 smb_rq_bstart(rqp);
248 error = mb_put_mem(mbp, dp->ioc_tbytes, dp->ioc_tbc, MB_MUSER);
249 if (error)
250 goto bad;
251 smb_rq_bend(rqp);
252 error = smb_rq_simple(rqp);
253 if (error)
254 goto bad;
255 mdp = &rqp->sr_rp;
256 md_get_uint8(mdp, &wc);
257 dp->ioc_rwc = wc;
258 wc *= 2;
259 if (wc > dp->ioc_rpbufsz) {
260 error = EBADRPC;
261 goto bad;
262 }
263 error = md_get_mem(mdp, dp->ioc_rpbuf, wc, MB_MUSER);
264 if (error)
265 goto bad;
266 md_get_uint16le(mdp, &bc);
267 if ((wc + bc) > dp->ioc_rpbufsz) {
268 error = EBADRPC;
269 goto bad;
270 }
271 dp->ioc_rbc = bc;
272 error = md_get_mem(mdp, dp->ioc_rpbuf + wc, bc, MB_MUSER);
273 bad:
274 dp->ioc_errclass = rqp->sr_errclass;
275 dp->ioc_serror = rqp->sr_serror;
276 dp->ioc_error = rqp->sr_error;
277 smb_rq_done(rqp);
278 return error;
279
280 }
281
282 static int
283 smb_cpdatain(struct mbchain *mbp, int len, caddr_t data)
284 {
285 int error;
286
287 if (len == 0)
288 return 0;
289 error = mb_init(mbp);
290 if (error)
291 return error;
292 return mb_put_mem(mbp, data, len, MB_MUSER);
293 }
294
295 int
296 smb_usr_t2request(struct smb_share *ssp, struct smbioc_t2rq *dp,
297 struct smb_cred *scred)
298 {
299 struct smb_t2rq t2, *t2p = &t2;
300 struct mdchain *mdp;
301 int error, len;
302
303 if (dp->ioc_tparamcnt > 0xffff || dp->ioc_tdatacnt > 0xffff ||
304 dp->ioc_setupcnt > 3)
305 return EINVAL;
306 error = smb_t2_init(t2p, SSTOCP(ssp), dp->ioc_setup[0], scred);
307 if (error)
308 return error;
309 len = t2p->t2_setupcount = dp->ioc_setupcnt;
310 if (len > 1)
311 t2p->t2_setupdata = dp->ioc_setup;
312 if (dp->ioc_name) {
313 t2p->t_name = smb_strdupin(dp->ioc_name, 128);
314 if (t2p->t_name == NULL) {
315 error = ENOMEM;
316 goto bad;
317 }
318 }
319 t2p->t2_maxscount = 0;
320 t2p->t2_maxpcount = dp->ioc_rparamcnt;
321 t2p->t2_maxdcount = dp->ioc_rdatacnt;
322 error = smb_cpdatain(&t2p->t2_tparam, dp->ioc_tparamcnt, dp->ioc_tparam);
323 if (error)
324 goto bad;
325 error = smb_cpdatain(&t2p->t2_tdata, dp->ioc_tdatacnt, dp->ioc_tdata);
326 if (error)
327 goto bad;
328 error = smb_t2_request(t2p);
329 if (error)
330 goto bad;
331 mdp = &t2p->t2_rparam;
332 if (mdp->md_top) {
333 len = m_fixhdr(mdp->md_top);
334 if (len > dp->ioc_rparamcnt) {
335 error = EMSGSIZE;
336 goto bad;
337 }
338 dp->ioc_rparamcnt = len;
339 error = md_get_mem(mdp, dp->ioc_rparam, len, MB_MUSER);
340 if (error)
341 goto bad;
342 } else
343 dp->ioc_rparamcnt = 0;
344 mdp = &t2p->t2_rdata;
345 if (mdp->md_top) {
346 len = m_fixhdr(mdp->md_top);
347 if (len > dp->ioc_rdatacnt) {
348 error = EMSGSIZE;
349 goto bad;
350 }
351 dp->ioc_rdatacnt = len;
352 error = md_get_mem(mdp, dp->ioc_rdata, len, MB_MUSER);
353 } else
354 dp->ioc_rdatacnt = 0;
355 bad:
356 if (t2p->t_name)
357 smb_strfree(t2p->t_name);
358 smb_t2_done(t2p);
359 return error;
360 }
Cache object: 2d6aa651d5444408145d09d075d4be4c
|