xref: /freebsd/contrib/smbfs/lib/smb/ctx.c (revision ccbbd187b1b61c3d15a1e830fd598a435442d21a)
1f1b9d127SSheldon Hearn /*
234ffbc80SSheldon Hearn  * Copyright (c) 2000-2002, Boris Popov
3f1b9d127SSheldon Hearn  * All rights reserved.
4f1b9d127SSheldon Hearn  *
5f1b9d127SSheldon Hearn  * Redistribution and use in source and binary forms, with or without
6f1b9d127SSheldon Hearn  * modification, are permitted provided that the following conditions
7f1b9d127SSheldon Hearn  * are met:
8f1b9d127SSheldon Hearn  * 1. Redistributions of source code must retain the above copyright
9f1b9d127SSheldon Hearn  *    notice, this list of conditions and the following disclaimer.
10f1b9d127SSheldon Hearn  * 2. Redistributions in binary form must reproduce the above copyright
11f1b9d127SSheldon Hearn  *    notice, this list of conditions and the following disclaimer in the
12f1b9d127SSheldon Hearn  *    documentation and/or other materials provided with the distribution.
13f1b9d127SSheldon Hearn  * 3. All advertising materials mentioning features or use of this software
14f1b9d127SSheldon Hearn  *    must display the following acknowledgement:
15f1b9d127SSheldon Hearn  *    This product includes software developed by Boris Popov.
16f1b9d127SSheldon Hearn  * 4. Neither the name of the author nor the names of any co-contributors
17f1b9d127SSheldon Hearn  *    may be used to endorse or promote products derived from this software
18f1b9d127SSheldon Hearn  *    without specific prior written permission.
19f1b9d127SSheldon Hearn  *
20f1b9d127SSheldon Hearn  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21f1b9d127SSheldon Hearn  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22f1b9d127SSheldon Hearn  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23f1b9d127SSheldon Hearn  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24f1b9d127SSheldon Hearn  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25f1b9d127SSheldon Hearn  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26f1b9d127SSheldon Hearn  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27f1b9d127SSheldon Hearn  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28f1b9d127SSheldon Hearn  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29f1b9d127SSheldon Hearn  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30f1b9d127SSheldon Hearn  * SUCH DAMAGE.
31f1b9d127SSheldon Hearn  *
3234ffbc80SSheldon Hearn  * $Id: ctx.c,v 1.24 2002/04/13 14:35:28 bp Exp $
3381b431dbSTim J. Robbins  * $FreeBSD$
34f1b9d127SSheldon Hearn  */
35f1b9d127SSheldon Hearn #include <sys/param.h>
36f1b9d127SSheldon Hearn #include <sys/sysctl.h>
37f1b9d127SSheldon Hearn #include <sys/ioctl.h>
38f1b9d127SSheldon Hearn #include <sys/time.h>
39f1b9d127SSheldon Hearn #include <sys/mount.h>
40f1b9d127SSheldon Hearn #include <fcntl.h>
41f1b9d127SSheldon Hearn #include <ctype.h>
42f1b9d127SSheldon Hearn #include <errno.h>
43f1b9d127SSheldon Hearn #include <stdio.h>
44f1b9d127SSheldon Hearn #include <string.h>
45f1b9d127SSheldon Hearn #include <stdlib.h>
46f1b9d127SSheldon Hearn #include <pwd.h>
47f1b9d127SSheldon Hearn #include <grp.h>
48f1b9d127SSheldon Hearn #include <unistd.h>
49f1b9d127SSheldon Hearn #include <sys/iconv.h>
50f1b9d127SSheldon Hearn 
51f1b9d127SSheldon Hearn #define NB_NEEDRESOLVER
52f1b9d127SSheldon Hearn 
53f1b9d127SSheldon Hearn #include <netsmb/smb_lib.h>
54f1b9d127SSheldon Hearn #include <netsmb/netbios.h>
55f1b9d127SSheldon Hearn #include <netsmb/nb_lib.h>
56f1b9d127SSheldon Hearn #include <netsmb/smb_conn.h>
57f1b9d127SSheldon Hearn #include <cflib.h>
58f1b9d127SSheldon Hearn 
59f1b9d127SSheldon Hearn /*
60f1b9d127SSheldon Hearn  * Prescan command line for [-U user] argument
61f1b9d127SSheldon Hearn  * and fill context with defaults
62f1b9d127SSheldon Hearn  */
63f1b9d127SSheldon Hearn int
smb_ctx_init(struct smb_ctx * ctx,int argc,char * argv[],int minlevel,int maxlevel,int sharetype)64f1b9d127SSheldon Hearn smb_ctx_init(struct smb_ctx *ctx, int argc, char *argv[],
65f1b9d127SSheldon Hearn 	int minlevel, int maxlevel, int sharetype)
66f1b9d127SSheldon Hearn {
67f1b9d127SSheldon Hearn 	int  opt, error = 0;
6834ffbc80SSheldon Hearn 	uid_t euid;
69f1b9d127SSheldon Hearn 	const char *arg, *cp;
7034ffbc80SSheldon Hearn 	struct passwd *pwd;
71f1b9d127SSheldon Hearn 
72f1b9d127SSheldon Hearn 	bzero(ctx,sizeof(*ctx));
73f1b9d127SSheldon Hearn 	error = nb_ctx_create(&ctx->ct_nb);
74f1b9d127SSheldon Hearn 	if (error)
75f1b9d127SSheldon Hearn 		return error;
76f1b9d127SSheldon Hearn 	ctx->ct_fd = -1;
77f1b9d127SSheldon Hearn 	ctx->ct_parsedlevel = SMBL_NONE;
78f1b9d127SSheldon Hearn 	ctx->ct_minlevel = minlevel;
79f1b9d127SSheldon Hearn 	ctx->ct_maxlevel = maxlevel;
80ef29b0f6SBoris Popov 	ctx->ct_smbtcpport = SMB_TCP_PORT;
81f1b9d127SSheldon Hearn 
82f1b9d127SSheldon Hearn 	ctx->ct_ssn.ioc_opt = SMBVOPT_CREATE;
83f1b9d127SSheldon Hearn 	ctx->ct_ssn.ioc_timeout = 15;
84f1b9d127SSheldon Hearn 	ctx->ct_ssn.ioc_retrycount = 4;
85f1b9d127SSheldon Hearn 	ctx->ct_ssn.ioc_owner = SMBM_ANY_OWNER;
86f1b9d127SSheldon Hearn 	ctx->ct_ssn.ioc_group = SMBM_ANY_GROUP;
87f1b9d127SSheldon Hearn 	ctx->ct_ssn.ioc_mode = SMBM_EXEC;
88f1b9d127SSheldon Hearn 	ctx->ct_ssn.ioc_rights = SMBM_DEFAULT;
89f1b9d127SSheldon Hearn 
90f1b9d127SSheldon Hearn 	ctx->ct_sh.ioc_opt = SMBVOPT_CREATE;
91f1b9d127SSheldon Hearn 	ctx->ct_sh.ioc_owner = SMBM_ANY_OWNER;
92f1b9d127SSheldon Hearn 	ctx->ct_sh.ioc_group = SMBM_ANY_GROUP;
93f1b9d127SSheldon Hearn 	ctx->ct_sh.ioc_mode = SMBM_EXEC;
94f1b9d127SSheldon Hearn 	ctx->ct_sh.ioc_rights = SMBM_DEFAULT;
95f1b9d127SSheldon Hearn 	ctx->ct_sh.ioc_owner = SMBM_ANY_OWNER;
96f1b9d127SSheldon Hearn 	ctx->ct_sh.ioc_group = SMBM_ANY_GROUP;
97f1b9d127SSheldon Hearn 
98f1b9d127SSheldon Hearn 	nb_ctx_setscope(ctx->ct_nb, "");
9934ffbc80SSheldon Hearn 	euid = geteuid();
10034ffbc80SSheldon Hearn 	if ((pwd = getpwuid(euid)) != NULL) {
10134ffbc80SSheldon Hearn 		smb_ctx_setuser(ctx, pwd->pw_name);
102f1b9d127SSheldon Hearn 		endpwent();
10334ffbc80SSheldon Hearn 	} else if (euid == 0)
10434ffbc80SSheldon Hearn 		smb_ctx_setuser(ctx, "root");
10534ffbc80SSheldon Hearn 	else
10634ffbc80SSheldon Hearn 		return 0;
107f1b9d127SSheldon Hearn 	if (argv == NULL)
108f1b9d127SSheldon Hearn 		return 0;
109f1b9d127SSheldon Hearn 	for (opt = 1; opt < argc; opt++) {
110f1b9d127SSheldon Hearn 		cp = argv[opt];
111f1b9d127SSheldon Hearn 		if (strncmp(cp, "//", 2) != 0)
112f1b9d127SSheldon Hearn 			continue;
113f1b9d127SSheldon Hearn 		error = smb_ctx_parseunc(ctx, cp, sharetype, (const char**)&cp);
114f1b9d127SSheldon Hearn 		if (error)
115f1b9d127SSheldon Hearn 			return error;
116f1b9d127SSheldon Hearn 		ctx->ct_uncnext = cp;
117f1b9d127SSheldon Hearn 		break;
118f1b9d127SSheldon Hearn 	}
119f1b9d127SSheldon Hearn 	while (error == 0 && (opt = cf_getopt(argc, argv, ":E:L:U:")) != -1) {
120f1b9d127SSheldon Hearn 		arg = cf_optarg;
121f1b9d127SSheldon Hearn 		switch (opt) {
122f1b9d127SSheldon Hearn 		    case 'E':
123f1b9d127SSheldon Hearn 			error = smb_ctx_setcharset(ctx, arg);
124f1b9d127SSheldon Hearn 			if (error)
125f1b9d127SSheldon Hearn 				return error;
126f1b9d127SSheldon Hearn 			break;
127f1b9d127SSheldon Hearn 		    case 'L':
12819434a77SR. Imura 			error = nls_setlocale(arg);
129f1b9d127SSheldon Hearn 			if (error)
130f1b9d127SSheldon Hearn 				break;
131f1b9d127SSheldon Hearn 			break;
132f1b9d127SSheldon Hearn 		    case 'U':
133f1b9d127SSheldon Hearn 			error = smb_ctx_setuser(ctx, arg);
134f1b9d127SSheldon Hearn 			break;
135f1b9d127SSheldon Hearn 		}
136f1b9d127SSheldon Hearn 	}
137f1b9d127SSheldon Hearn 	cf_optind = cf_optreset = 1;
138f1b9d127SSheldon Hearn 	return error;
139f1b9d127SSheldon Hearn }
140f1b9d127SSheldon Hearn 
141f1b9d127SSheldon Hearn void
smb_ctx_done(struct smb_ctx * ctx)142f1b9d127SSheldon Hearn smb_ctx_done(struct smb_ctx *ctx)
143f1b9d127SSheldon Hearn {
144f1b9d127SSheldon Hearn 	if (ctx->ct_ssn.ioc_server)
145f1b9d127SSheldon Hearn 		nb_snbfree(ctx->ct_ssn.ioc_server);
146f1b9d127SSheldon Hearn 	if (ctx->ct_ssn.ioc_local)
147f1b9d127SSheldon Hearn 		nb_snbfree(ctx->ct_ssn.ioc_local);
148f1b9d127SSheldon Hearn 	if (ctx->ct_srvaddr)
149f1b9d127SSheldon Hearn 		free(ctx->ct_srvaddr);
150f1b9d127SSheldon Hearn 	if (ctx->ct_nb)
151f1b9d127SSheldon Hearn 		nb_ctx_done(ctx->ct_nb);
152f1b9d127SSheldon Hearn }
153f1b9d127SSheldon Hearn 
154f1b9d127SSheldon Hearn static int
getsubstring(const char * p,u_char sep,char * dest,int maxlen,const char ** next)155f1b9d127SSheldon Hearn getsubstring(const char *p, u_char sep, char *dest, int maxlen, const char **next)
156f1b9d127SSheldon Hearn {
157f1b9d127SSheldon Hearn 	int len;
158f1b9d127SSheldon Hearn 
159f1b9d127SSheldon Hearn 	maxlen--;
160f1b9d127SSheldon Hearn 	for (len = 0; len < maxlen && *p != sep; p++, len++, dest++) {
161f1b9d127SSheldon Hearn 		if (*p == 0)
162f1b9d127SSheldon Hearn 			return EINVAL;
163f1b9d127SSheldon Hearn 		*dest = *p;
164f1b9d127SSheldon Hearn 	}
165f1b9d127SSheldon Hearn 	*dest = 0;
166f1b9d127SSheldon Hearn 	*next = *p ? p + 1 : p;
167f1b9d127SSheldon Hearn 	return 0;
168f1b9d127SSheldon Hearn }
169f1b9d127SSheldon Hearn 
170f1b9d127SSheldon Hearn /*
171ef29b0f6SBoris Popov  * Here we expect something like "[proto:]//[user@]host[:psmb[:pnb]][/share][/path]"
172f1b9d127SSheldon Hearn  */
173f1b9d127SSheldon Hearn int
smb_ctx_parseunc(struct smb_ctx * ctx,const char * unc,int sharetype,const char ** next)174f1b9d127SSheldon Hearn smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc, int sharetype,
175f1b9d127SSheldon Hearn 	const char **next)
176f1b9d127SSheldon Hearn {
177f1b9d127SSheldon Hearn 	const char *p = unc;
178ef29b0f6SBoris Popov 	char *p1, *psmb, *pnb;
179f1b9d127SSheldon Hearn 	char tmp[1024];
180f1b9d127SSheldon Hearn 	int error ;
181f1b9d127SSheldon Hearn 
182f1b9d127SSheldon Hearn 	ctx->ct_parsedlevel = SMBL_NONE;
183f1b9d127SSheldon Hearn 	if (*p++ != '/' || *p++ != '/') {
184f1b9d127SSheldon Hearn 		smb_error("UNC should start with '//'", 0);
185f1b9d127SSheldon Hearn 		return EINVAL;
186f1b9d127SSheldon Hearn 	}
187f1b9d127SSheldon Hearn 	p1 = tmp;
188f1b9d127SSheldon Hearn 	error = getsubstring(p, '@', p1, sizeof(tmp), &p);
189f1b9d127SSheldon Hearn 	if (!error) {
190f1b9d127SSheldon Hearn 		if (ctx->ct_maxlevel < SMBL_VC) {
191f1b9d127SSheldon Hearn 			smb_error("no user name required", 0);
192f1b9d127SSheldon Hearn 			return EINVAL;
193f1b9d127SSheldon Hearn 		}
194f1b9d127SSheldon Hearn 		error = smb_ctx_setuser(ctx, tmp);
195f1b9d127SSheldon Hearn 		if (error)
196f1b9d127SSheldon Hearn 			return error;
197f1b9d127SSheldon Hearn 		ctx->ct_parsedlevel = SMBL_VC;
198f1b9d127SSheldon Hearn 	}
199f1b9d127SSheldon Hearn 	error = getsubstring(p, '/', p1, sizeof(tmp), &p);
200f1b9d127SSheldon Hearn 	if (error) {
201f1b9d127SSheldon Hearn 		error = getsubstring(p, '\0', p1, sizeof(tmp), &p);
202f1b9d127SSheldon Hearn 		if (error) {
203f1b9d127SSheldon Hearn 			smb_error("no server name found", 0);
204f1b9d127SSheldon Hearn 			return error;
205f1b9d127SSheldon Hearn 		}
206f1b9d127SSheldon Hearn 	}
207f1b9d127SSheldon Hearn 	if (*p1 == 0) {
208f1b9d127SSheldon Hearn 		smb_error("empty server name", 0);
209f1b9d127SSheldon Hearn 		return EINVAL;
210f1b9d127SSheldon Hearn 	}
211ef29b0f6SBoris Popov 	/*
212ef29b0f6SBoris Popov 	 * Check for port number specification.
213ef29b0f6SBoris Popov 	 */
214ef29b0f6SBoris Popov 	psmb = strchr(tmp, ':');
215ef29b0f6SBoris Popov 	if (psmb) {
216ef29b0f6SBoris Popov 		*psmb++ = '\0';
217ef29b0f6SBoris Popov 		pnb = strchr(psmb, ':');
218ef29b0f6SBoris Popov 		if (pnb) {
219ef29b0f6SBoris Popov 			*pnb++ = '\0';
220ef29b0f6SBoris Popov 			error = smb_ctx_setnbport(ctx, atoi(pnb));
221ef29b0f6SBoris Popov 			if (error) {
222ef29b0f6SBoris Popov 				smb_error("Invalid NetBIOS port number", 0);
223ef29b0f6SBoris Popov 				return error;
224ef29b0f6SBoris Popov 			}
225ef29b0f6SBoris Popov 		}
226ef29b0f6SBoris Popov 		error = smb_ctx_setsmbport(ctx, atoi(psmb));
227ef29b0f6SBoris Popov 		if (error) {
228ef29b0f6SBoris Popov 			smb_error("Invalid SMB port number", 0);
229ef29b0f6SBoris Popov 			return error;
230ef29b0f6SBoris Popov 		}
231ef29b0f6SBoris Popov 	}
232f1b9d127SSheldon Hearn 	error = smb_ctx_setserver(ctx, tmp);
233f1b9d127SSheldon Hearn 	if (error)
234f1b9d127SSheldon Hearn 		return error;
235f1b9d127SSheldon Hearn 	if (sharetype == SMB_ST_NONE) {
236f1b9d127SSheldon Hearn 		*next = p;
237f1b9d127SSheldon Hearn 		return 0;
238f1b9d127SSheldon Hearn 	}
239f1b9d127SSheldon Hearn 	if (*p != 0 && ctx->ct_maxlevel < SMBL_SHARE) {
240f1b9d127SSheldon Hearn 		smb_error("no share name required", 0);
241f1b9d127SSheldon Hearn 		return EINVAL;
242f1b9d127SSheldon Hearn 	}
243f1b9d127SSheldon Hearn 	error = getsubstring(p, '/', p1, sizeof(tmp), &p);
244f1b9d127SSheldon Hearn 	if (error) {
245f1b9d127SSheldon Hearn 		error = getsubstring(p, '\0', p1, sizeof(tmp), &p);
246f1b9d127SSheldon Hearn 		if (error) {
247f1b9d127SSheldon Hearn 			smb_error("unexpected end of line", 0);
248f1b9d127SSheldon Hearn 			return error;
249f1b9d127SSheldon Hearn 		}
250f1b9d127SSheldon Hearn 	}
251f1b9d127SSheldon Hearn 	if (*p1 == 0 && ctx->ct_minlevel >= SMBL_SHARE) {
252f1b9d127SSheldon Hearn 		smb_error("empty share name", 0);
253f1b9d127SSheldon Hearn 		return EINVAL;
254f1b9d127SSheldon Hearn 	}
255f1b9d127SSheldon Hearn 	*next = p;
256f1b9d127SSheldon Hearn 	if (*p1 == 0)
257f1b9d127SSheldon Hearn 		return 0;
258f1b9d127SSheldon Hearn 	error = smb_ctx_setshare(ctx, p1, sharetype);
259f1b9d127SSheldon Hearn 	return error;
260f1b9d127SSheldon Hearn }
261f1b9d127SSheldon Hearn 
262f1b9d127SSheldon Hearn int
smb_ctx_setcharset(struct smb_ctx * ctx,const char * arg)263f1b9d127SSheldon Hearn smb_ctx_setcharset(struct smb_ctx *ctx, const char *arg)
264f1b9d127SSheldon Hearn {
265f1b9d127SSheldon Hearn 	char *cp, *servercs, *localcs;
266f1b9d127SSheldon Hearn 	int cslen = sizeof(ctx->ct_ssn.ioc_localcs);
267f1b9d127SSheldon Hearn 	int scslen, lcslen, error;
268f1b9d127SSheldon Hearn 
269f1b9d127SSheldon Hearn 	cp = strchr(arg, ':');
270f1b9d127SSheldon Hearn 	lcslen = cp ? (cp - arg) : 0;
271f1b9d127SSheldon Hearn 	if (lcslen == 0 || lcslen >= cslen) {
272f1b9d127SSheldon Hearn 		smb_error("invalid local charset specification (%s)", 0, arg);
273f1b9d127SSheldon Hearn 		return EINVAL;
274f1b9d127SSheldon Hearn 	}
275f1b9d127SSheldon Hearn 	scslen = (size_t)strlen(++cp);
276f1b9d127SSheldon Hearn 	if (scslen == 0 || scslen >= cslen) {
277f1b9d127SSheldon Hearn 		smb_error("invalid server charset specification (%s)", 0, arg);
278f1b9d127SSheldon Hearn 		return EINVAL;
279f1b9d127SSheldon Hearn 	}
280f1b9d127SSheldon Hearn 	localcs = memcpy(ctx->ct_ssn.ioc_localcs, arg, lcslen);
281f1b9d127SSheldon Hearn 	localcs[lcslen] = 0;
282f1b9d127SSheldon Hearn 	servercs = strcpy(ctx->ct_ssn.ioc_servercs, cp);
283f1b9d127SSheldon Hearn 	error = nls_setrecode(localcs, servercs);
284f1b9d127SSheldon Hearn 	if (error == 0)
285f1b9d127SSheldon Hearn 		return 0;
286f1b9d127SSheldon Hearn 	smb_error("can't initialize iconv support (%s:%s)",
287f1b9d127SSheldon Hearn 	    error, localcs, servercs);
288f1b9d127SSheldon Hearn 	localcs[0] = 0;
289f1b9d127SSheldon Hearn 	servercs[0] = 0;
290f1b9d127SSheldon Hearn 	return error;
291f1b9d127SSheldon Hearn }
292f1b9d127SSheldon Hearn 
293f1b9d127SSheldon Hearn int
smb_ctx_setserver(struct smb_ctx * ctx,const char * name)294f1b9d127SSheldon Hearn smb_ctx_setserver(struct smb_ctx *ctx, const char *name)
295f1b9d127SSheldon Hearn {
2965ec3441dSTim J. Robbins 	if (strlen(name) > SMB_MAXSRVNAMELEN) {
297f1b9d127SSheldon Hearn 		smb_error("server name '%s' too long", 0, name);
298f1b9d127SSheldon Hearn 		return ENAMETOOLONG;
299f1b9d127SSheldon Hearn 	}
300f1b9d127SSheldon Hearn 	nls_str_upper(ctx->ct_ssn.ioc_srvname, name);
301f1b9d127SSheldon Hearn 	return 0;
302f1b9d127SSheldon Hearn }
303f1b9d127SSheldon Hearn 
304f1b9d127SSheldon Hearn int
smb_ctx_setnbport(struct smb_ctx * ctx,int port)305ef29b0f6SBoris Popov smb_ctx_setnbport(struct smb_ctx *ctx, int port)
306ef29b0f6SBoris Popov {
307ef29b0f6SBoris Popov 	if (port < 1 || port > 0xffff)
308ef29b0f6SBoris Popov 		return EINVAL;
309ef29b0f6SBoris Popov 	ctx->ct_nb->nb_nmbtcpport = port;
310ef29b0f6SBoris Popov 	return 0;
311ef29b0f6SBoris Popov }
312ef29b0f6SBoris Popov 
313ef29b0f6SBoris Popov int
smb_ctx_setsmbport(struct smb_ctx * ctx,int port)314ef29b0f6SBoris Popov smb_ctx_setsmbport(struct smb_ctx *ctx, int port)
315ef29b0f6SBoris Popov {
316ef29b0f6SBoris Popov 	if (port < 1 || port > 0xffff)
317ef29b0f6SBoris Popov 		return EINVAL;
318ef29b0f6SBoris Popov 	ctx->ct_smbtcpport = port;
319ef29b0f6SBoris Popov 	ctx->ct_nb->nb_smbtcpport = port;
320ef29b0f6SBoris Popov 	return 0;
321ef29b0f6SBoris Popov }
322ef29b0f6SBoris Popov 
323ef29b0f6SBoris Popov int
smb_ctx_setuser(struct smb_ctx * ctx,const char * name)324f1b9d127SSheldon Hearn smb_ctx_setuser(struct smb_ctx *ctx, const char *name)
325f1b9d127SSheldon Hearn {
3265ec3441dSTim J. Robbins 	if (strlen(name) > SMB_MAXUSERNAMELEN) {
327f1b9d127SSheldon Hearn 		smb_error("user name '%s' too long", 0, name);
328f1b9d127SSheldon Hearn 		return ENAMETOOLONG;
329f1b9d127SSheldon Hearn 	}
330f1b9d127SSheldon Hearn 	nls_str_upper(ctx->ct_ssn.ioc_user, name);
331f1b9d127SSheldon Hearn 	return 0;
332f1b9d127SSheldon Hearn }
333f1b9d127SSheldon Hearn 
334f1b9d127SSheldon Hearn int
smb_ctx_setworkgroup(struct smb_ctx * ctx,const char * name)335f1b9d127SSheldon Hearn smb_ctx_setworkgroup(struct smb_ctx *ctx, const char *name)
336f1b9d127SSheldon Hearn {
3375ec3441dSTim J. Robbins 	if (strlen(name) > SMB_MAXUSERNAMELEN) {
338f1b9d127SSheldon Hearn 		smb_error("workgroup name '%s' too long", 0, name);
339f1b9d127SSheldon Hearn 		return ENAMETOOLONG;
340f1b9d127SSheldon Hearn 	}
341f1b9d127SSheldon Hearn 	nls_str_upper(ctx->ct_ssn.ioc_workgroup, name);
342f1b9d127SSheldon Hearn 	return 0;
343f1b9d127SSheldon Hearn }
344f1b9d127SSheldon Hearn 
345f1b9d127SSheldon Hearn int
smb_ctx_setpassword(struct smb_ctx * ctx,const char * passwd)346f1b9d127SSheldon Hearn smb_ctx_setpassword(struct smb_ctx *ctx, const char *passwd)
347f1b9d127SSheldon Hearn {
348f1b9d127SSheldon Hearn 	if (passwd == NULL)
349f1b9d127SSheldon Hearn 		return EINVAL;
3505ec3441dSTim J. Robbins 	if (strlen(passwd) > SMB_MAXPASSWORDLEN) {
351f1b9d127SSheldon Hearn 		smb_error("password too long", 0);
352f1b9d127SSheldon Hearn 		return ENAMETOOLONG;
353f1b9d127SSheldon Hearn 	}
354f1b9d127SSheldon Hearn 	if (strncmp(passwd, "$$1", 3) == 0)
355f1b9d127SSheldon Hearn 		smb_simpledecrypt(ctx->ct_ssn.ioc_password, passwd);
356f1b9d127SSheldon Hearn 	else
357f1b9d127SSheldon Hearn 		strcpy(ctx->ct_ssn.ioc_password, passwd);
358f1b9d127SSheldon Hearn 	strcpy(ctx->ct_sh.ioc_password, ctx->ct_ssn.ioc_password);
359f1b9d127SSheldon Hearn 	return 0;
360f1b9d127SSheldon Hearn }
361f1b9d127SSheldon Hearn 
362f1b9d127SSheldon Hearn int
smb_ctx_setshare(struct smb_ctx * ctx,const char * share,int stype)363f1b9d127SSheldon Hearn smb_ctx_setshare(struct smb_ctx *ctx, const char *share, int stype)
364f1b9d127SSheldon Hearn {
3655ec3441dSTim J. Robbins 	if (strlen(share) > SMB_MAXSHARENAMELEN) {
366f1b9d127SSheldon Hearn 		smb_error("share name '%s' too long", 0, share);
367f1b9d127SSheldon Hearn 		return ENAMETOOLONG;
368f1b9d127SSheldon Hearn 	}
369f1b9d127SSheldon Hearn 	nls_str_upper(ctx->ct_sh.ioc_share, share);
370f1b9d127SSheldon Hearn 	if (share[0] != 0)
371f1b9d127SSheldon Hearn 		ctx->ct_parsedlevel = SMBL_SHARE;
372f1b9d127SSheldon Hearn 	ctx->ct_sh.ioc_stype = stype;
373f1b9d127SSheldon Hearn 	return 0;
374f1b9d127SSheldon Hearn }
375f1b9d127SSheldon Hearn 
376f1b9d127SSheldon Hearn int
smb_ctx_setsrvaddr(struct smb_ctx * ctx,const char * addr)377f1b9d127SSheldon Hearn smb_ctx_setsrvaddr(struct smb_ctx *ctx, const char *addr)
378f1b9d127SSheldon Hearn {
379f1b9d127SSheldon Hearn 	if (addr == NULL || addr[0] == 0)
380f1b9d127SSheldon Hearn 		return EINVAL;
381f1b9d127SSheldon Hearn 	if (ctx->ct_srvaddr)
382f1b9d127SSheldon Hearn 		free(ctx->ct_srvaddr);
383f1b9d127SSheldon Hearn 	if ((ctx->ct_srvaddr = strdup(addr)) == NULL)
384f1b9d127SSheldon Hearn 		return ENOMEM;
385f1b9d127SSheldon Hearn 	return 0;
386f1b9d127SSheldon Hearn }
387f1b9d127SSheldon Hearn 
388f1b9d127SSheldon Hearn static int
smb_parse_owner(char * pair,uid_t * uid,gid_t * gid)389f1b9d127SSheldon Hearn smb_parse_owner(char *pair, uid_t *uid, gid_t *gid)
390f1b9d127SSheldon Hearn {
391f1b9d127SSheldon Hearn 	struct group *gr;
392f1b9d127SSheldon Hearn 	struct passwd *pw;
393f1b9d127SSheldon Hearn 	char *cp;
394f1b9d127SSheldon Hearn 
395f1b9d127SSheldon Hearn 	cp = strchr(pair, ':');
396f1b9d127SSheldon Hearn 	if (cp) {
397f1b9d127SSheldon Hearn 		*cp++ = '\0';
398f1b9d127SSheldon Hearn 		if (*cp) {
399f1b9d127SSheldon Hearn 			gr = getgrnam(cp);
400f1b9d127SSheldon Hearn 			if (gr) {
401f1b9d127SSheldon Hearn 				*gid = gr->gr_gid;
402f1b9d127SSheldon Hearn 			} else
403f1b9d127SSheldon Hearn 				smb_error("Invalid group name %s, ignored",
404f1b9d127SSheldon Hearn 				    0, cp);
405f1b9d127SSheldon Hearn 		}
406f1b9d127SSheldon Hearn 	}
407f1b9d127SSheldon Hearn 	if (*pair) {
408f1b9d127SSheldon Hearn 		pw = getpwnam(pair);
409f1b9d127SSheldon Hearn 		if (pw) {
410f1b9d127SSheldon Hearn 			*uid = pw->pw_uid;
411f1b9d127SSheldon Hearn 		} else
412f1b9d127SSheldon Hearn 			smb_error("Invalid user name %s, ignored", 0, pair);
413f1b9d127SSheldon Hearn 	}
414f1b9d127SSheldon Hearn 	endpwent();
415f1b9d127SSheldon Hearn 	return 0;
416f1b9d127SSheldon Hearn }
417f1b9d127SSheldon Hearn 
418f1b9d127SSheldon Hearn int
smb_ctx_opt(struct smb_ctx * ctx,int opt,const char * arg)419f1b9d127SSheldon Hearn smb_ctx_opt(struct smb_ctx *ctx, int opt, const char *arg)
420f1b9d127SSheldon Hearn {
421f1b9d127SSheldon Hearn 	int error = 0;
422f1b9d127SSheldon Hearn 	char *p, *cp;
423f1b9d127SSheldon Hearn 
424f1b9d127SSheldon Hearn 	switch(opt) {
425f1b9d127SSheldon Hearn 	    case 'U':
426f1b9d127SSheldon Hearn 		break;
427f1b9d127SSheldon Hearn 	    case 'I':
428f1b9d127SSheldon Hearn 		error = smb_ctx_setsrvaddr(ctx, arg);
429f1b9d127SSheldon Hearn 		break;
430f1b9d127SSheldon Hearn 	    case 'M':
431f1b9d127SSheldon Hearn 		ctx->ct_ssn.ioc_rights = strtol(arg, &cp, 8);
432f1b9d127SSheldon Hearn 		if (*cp == '/') {
433f1b9d127SSheldon Hearn 			ctx->ct_sh.ioc_rights = strtol(cp + 1, &cp, 8);
434f1b9d127SSheldon Hearn 			ctx->ct_flags |= SMBCF_SRIGHTS;
435f1b9d127SSheldon Hearn 		}
436f1b9d127SSheldon Hearn 		break;
437f1b9d127SSheldon Hearn 	    case 'N':
438f1b9d127SSheldon Hearn 		ctx->ct_flags |= SMBCF_NOPWD;
439f1b9d127SSheldon Hearn 		break;
440f1b9d127SSheldon Hearn 	    case 'O':
441f1b9d127SSheldon Hearn 		p = strdup(arg);
442f1b9d127SSheldon Hearn 		cp = strchr(p, '/');
443f1b9d127SSheldon Hearn 		if (cp) {
444f1b9d127SSheldon Hearn 			*cp++ = '\0';
445f1b9d127SSheldon Hearn 			error = smb_parse_owner(cp, &ctx->ct_sh.ioc_owner,
446f1b9d127SSheldon Hearn 			    &ctx->ct_sh.ioc_group);
447f1b9d127SSheldon Hearn 		}
448f1b9d127SSheldon Hearn 		if (*p && error == 0) {
44981b431dbSTim J. Robbins 			error = smb_parse_owner(p, &ctx->ct_ssn.ioc_owner,
450f1b9d127SSheldon Hearn 			    &ctx->ct_ssn.ioc_group);
451f1b9d127SSheldon Hearn 		}
452f1b9d127SSheldon Hearn 		free(p);
453f1b9d127SSheldon Hearn 		break;
454f1b9d127SSheldon Hearn 	    case 'P':
455f1b9d127SSheldon Hearn /*		ctx->ct_ssn.ioc_opt |= SMBCOPT_PERMANENT;*/
456f1b9d127SSheldon Hearn 		break;
457f1b9d127SSheldon Hearn 	    case 'R':
458f1b9d127SSheldon Hearn 		ctx->ct_ssn.ioc_retrycount = atoi(arg);
459f1b9d127SSheldon Hearn 		break;
460f1b9d127SSheldon Hearn 	    case 'T':
461f1b9d127SSheldon Hearn 		ctx->ct_ssn.ioc_timeout = atoi(arg);
462f1b9d127SSheldon Hearn 		break;
463f1b9d127SSheldon Hearn 	    case 'W':
464f1b9d127SSheldon Hearn 		error = smb_ctx_setworkgroup(ctx, arg);
465f1b9d127SSheldon Hearn 		break;
466f1b9d127SSheldon Hearn 	}
467f1b9d127SSheldon Hearn 	return error;
468f1b9d127SSheldon Hearn }
469f1b9d127SSheldon Hearn 
470f1b9d127SSheldon Hearn #if 0
471f1b9d127SSheldon Hearn static void
472f1b9d127SSheldon Hearn smb_hexdump(const u_char *buf, int len) {
473f1b9d127SSheldon Hearn 	int ofs = 0;
474f1b9d127SSheldon Hearn 
475f1b9d127SSheldon Hearn 	while (len--) {
476f1b9d127SSheldon Hearn 		if (ofs % 16 == 0)
477f1b9d127SSheldon Hearn 			printf("\n%02X: ", ofs);
478f1b9d127SSheldon Hearn 		printf("%02x ", *buf++);
479f1b9d127SSheldon Hearn 		ofs++;
480f1b9d127SSheldon Hearn 	}
481f1b9d127SSheldon Hearn 	printf("\n");
482f1b9d127SSheldon Hearn }
483f1b9d127SSheldon Hearn #endif
484f1b9d127SSheldon Hearn 
485f1b9d127SSheldon Hearn 
486f1b9d127SSheldon Hearn static int
smb_addiconvtbl(const char * to,const char * from,const u_char * tbl)487f1b9d127SSheldon Hearn smb_addiconvtbl(const char *to, const char *from, const u_char *tbl)
488f1b9d127SSheldon Hearn {
489f1b9d127SSheldon Hearn 	int error;
490f1b9d127SSheldon Hearn 
491f1b9d127SSheldon Hearn 	error = kiconv_add_xlat_table(to, from, tbl);
492f1b9d127SSheldon Hearn 	if (error && error != EEXIST) {
493f1b9d127SSheldon Hearn 		smb_error("can not setup kernel iconv table (%s:%s)", error,
494f1b9d127SSheldon Hearn 		    from, to);
495f1b9d127SSheldon Hearn 		return error;
496f1b9d127SSheldon Hearn 	}
497f1b9d127SSheldon Hearn 	return 0;
498f1b9d127SSheldon Hearn }
499f1b9d127SSheldon Hearn 
500f1b9d127SSheldon Hearn /*
501f1b9d127SSheldon Hearn  * Verify context before connect operation(s),
502f1b9d127SSheldon Hearn  * lookup specified server and try to fill all forgotten fields.
503f1b9d127SSheldon Hearn  */
504f1b9d127SSheldon Hearn int
smb_ctx_resolve(struct smb_ctx * ctx)505f1b9d127SSheldon Hearn smb_ctx_resolve(struct smb_ctx *ctx)
506f1b9d127SSheldon Hearn {
507f1b9d127SSheldon Hearn 	struct smbioc_ossn *ssn = &ctx->ct_ssn;
508f1b9d127SSheldon Hearn 	struct smbioc_oshare *sh = &ctx->ct_sh;
509f1b9d127SSheldon Hearn 	struct nb_name nn;
510f1b9d127SSheldon Hearn 	struct sockaddr *sap;
511f1b9d127SSheldon Hearn 	struct sockaddr_nb *salocal, *saserver;
512f1b9d127SSheldon Hearn 	char *cp;
513f1b9d127SSheldon Hearn 	int error = 0;
514f1b9d127SSheldon Hearn 
515f1b9d127SSheldon Hearn 	ctx->ct_flags &= ~SMBCF_RESOLVED;
516f1b9d127SSheldon Hearn 	if (ssn->ioc_srvname[0] == 0) {
517f1b9d127SSheldon Hearn 		smb_error("no server name specified", 0);
518f1b9d127SSheldon Hearn 		return EINVAL;
519f1b9d127SSheldon Hearn 	}
520f1b9d127SSheldon Hearn 	if (ctx->ct_minlevel >= SMBL_SHARE && sh->ioc_share[0] == 0) {
521f1b9d127SSheldon Hearn 		smb_error("no share name specified for %s@%s",
522f1b9d127SSheldon Hearn 		    0, ssn->ioc_user, ssn->ioc_srvname);
523f1b9d127SSheldon Hearn 		return EINVAL;
524f1b9d127SSheldon Hearn 	}
525f1b9d127SSheldon Hearn 	error = nb_ctx_resolve(ctx->ct_nb);
526f1b9d127SSheldon Hearn 	if (error)
527f1b9d127SSheldon Hearn 		return error;
528f1b9d127SSheldon Hearn 	if (ssn->ioc_localcs[0] == 0)
5294ebd3ea1STakanori Watanabe 		strcpy(ssn->ioc_localcs, "ISO8859-1");
530f1b9d127SSheldon Hearn 	error = smb_addiconvtbl("tolower", ssn->ioc_localcs, nls_lower);
531f1b9d127SSheldon Hearn 	if (error)
532f1b9d127SSheldon Hearn 		return error;
533f1b9d127SSheldon Hearn 	error = smb_addiconvtbl("toupper", ssn->ioc_localcs, nls_upper);
534f1b9d127SSheldon Hearn 	if (error)
535f1b9d127SSheldon Hearn 		return error;
536f1b9d127SSheldon Hearn 	if (ssn->ioc_servercs[0] != 0) {
5374ebd3ea1STakanori Watanabe 		error = kiconv_add_xlat16_cspairs
538f0a446eaSR. Imura 			(ssn->ioc_servercs, ssn->ioc_localcs);
5394ebd3ea1STakanori Watanabe 		if (error) return error;
540f1b9d127SSheldon Hearn 	}
541f1b9d127SSheldon Hearn 	if (ctx->ct_srvaddr) {
542ef29b0f6SBoris Popov 		error = nb_resolvehost_in(ctx->ct_srvaddr, &sap, ctx->ct_smbtcpport);
543f1b9d127SSheldon Hearn 	} else {
544f1b9d127SSheldon Hearn 		error = nbns_resolvename(ssn->ioc_srvname, ctx->ct_nb, &sap);
545f1b9d127SSheldon Hearn 	}
546f1b9d127SSheldon Hearn 	if (error) {
547f1b9d127SSheldon Hearn 		smb_error("can't get server address", error);
548f1b9d127SSheldon Hearn 		return error;
549f1b9d127SSheldon Hearn 	}
550f1b9d127SSheldon Hearn 	nn.nn_scope = ctx->ct_nb->nb_scope;
551f1b9d127SSheldon Hearn 	nn.nn_type = NBT_SERVER;
552*ccbbd187SBrooks Davis 	if (strlen(ssn->ioc_srvname) > NB_NAMELEN)
553*ccbbd187SBrooks Davis 		return NBERROR(NBERR_NAMETOOLONG);
554*ccbbd187SBrooks Davis 	strlcpy(nn.nn_name, ssn->ioc_srvname, sizeof(nn.nn_name));
555f1b9d127SSheldon Hearn 	error = nb_sockaddr(sap, &nn, &saserver);
556f1b9d127SSheldon Hearn 	nb_snbfree(sap);
557f1b9d127SSheldon Hearn 	if (error) {
558f1b9d127SSheldon Hearn 		smb_error("can't allocate server address", error);
559f1b9d127SSheldon Hearn 		return error;
560f1b9d127SSheldon Hearn 	}
561f1b9d127SSheldon Hearn 	ssn->ioc_server = (struct sockaddr*)saserver;
562f1b9d127SSheldon Hearn 	if (ctx->ct_locname[0] == 0) {
563f1b9d127SSheldon Hearn 		error = nb_getlocalname(ctx->ct_locname);
564f1b9d127SSheldon Hearn 		if (error) {
565f1b9d127SSheldon Hearn 			smb_error("can't get local name", error);
566f1b9d127SSheldon Hearn 			return error;
567f1b9d127SSheldon Hearn 		}
568f1b9d127SSheldon Hearn 		nls_str_upper(ctx->ct_locname, ctx->ct_locname);
569f1b9d127SSheldon Hearn 	}
570*ccbbd187SBrooks Davis 	/*
571*ccbbd187SBrooks Davis 	 * Truncate the local host name to NB_NAMELEN-1 which gives a
572*ccbbd187SBrooks Davis 	 * suffix of 0 which is "workstation name".
573*ccbbd187SBrooks Davis 	 */
574*ccbbd187SBrooks Davis 	strlcpy(nn.nn_name, ctx->ct_locname, NB_NAMELEN);
575f1b9d127SSheldon Hearn 	nn.nn_type = NBT_WKSTA;
576f1b9d127SSheldon Hearn 	nn.nn_scope = ctx->ct_nb->nb_scope;
577f1b9d127SSheldon Hearn 	error = nb_sockaddr(NULL, &nn, &salocal);
578f1b9d127SSheldon Hearn 	if (error) {
579f1b9d127SSheldon Hearn 		nb_snbfree((struct sockaddr*)saserver);
580f1b9d127SSheldon Hearn 		smb_error("can't allocate local address", error);
581f1b9d127SSheldon Hearn 		return error;
582f1b9d127SSheldon Hearn 	}
583f1b9d127SSheldon Hearn 	ssn->ioc_local = (struct sockaddr*)salocal;
584f1b9d127SSheldon Hearn 	ssn->ioc_lolen = salocal->snb_len;
585f1b9d127SSheldon Hearn 	ssn->ioc_svlen = saserver->snb_len;
586f1b9d127SSheldon Hearn 	if (ssn->ioc_password[0] == 0 && (ctx->ct_flags & SMBCF_NOPWD) == 0) {
587f1b9d127SSheldon Hearn 		cp = getpass("Password:");
588f1b9d127SSheldon Hearn 		error = smb_ctx_setpassword(ctx, cp);
589f1b9d127SSheldon Hearn 		if (error)
590f1b9d127SSheldon Hearn 			return error;
591f1b9d127SSheldon Hearn 	}
592f1b9d127SSheldon Hearn 	ctx->ct_flags |= SMBCF_RESOLVED;
593f1b9d127SSheldon Hearn 	return 0;
594f1b9d127SSheldon Hearn }
595f1b9d127SSheldon Hearn 
596f1b9d127SSheldon Hearn static int
smb_ctx_gethandle(struct smb_ctx * ctx)597f1b9d127SSheldon Hearn smb_ctx_gethandle(struct smb_ctx *ctx)
598f1b9d127SSheldon Hearn {
599f1b9d127SSheldon Hearn 	int fd, i;
600f1b9d127SSheldon Hearn 	char buf[20];
601f1b9d127SSheldon Hearn 
602f1b9d127SSheldon Hearn 	fd = open("/dev/"NSMB_NAME, O_RDWR);
603f1b9d127SSheldon Hearn 	if (fd >= 0) {
604f1b9d127SSheldon Hearn 		ctx->ct_fd = fd;
605f1b9d127SSheldon Hearn 		return 0;
606f1b9d127SSheldon Hearn 	}
607f1b9d127SSheldon Hearn 	return ENOENT;
608f1b9d127SSheldon Hearn }
609f1b9d127SSheldon Hearn 
610f1b9d127SSheldon Hearn int
smb_ctx_lookup(struct smb_ctx * ctx,int level,int flags)611f1b9d127SSheldon Hearn smb_ctx_lookup(struct smb_ctx *ctx, int level, int flags)
612f1b9d127SSheldon Hearn {
613f1b9d127SSheldon Hearn 	struct smbioc_lookup rq;
614f1b9d127SSheldon Hearn 	int error;
615f1b9d127SSheldon Hearn 
616f1b9d127SSheldon Hearn 	if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) {
617f1b9d127SSheldon Hearn 		smb_error("smb_ctx_lookup() data is not resolved", 0);
618f1b9d127SSheldon Hearn 		return EINVAL;
619f1b9d127SSheldon Hearn 	}
620f1b9d127SSheldon Hearn 	if (ctx->ct_fd != -1) {
621f1b9d127SSheldon Hearn 		close(ctx->ct_fd);
622f1b9d127SSheldon Hearn 		ctx->ct_fd = -1;
623f1b9d127SSheldon Hearn 	}
624f1b9d127SSheldon Hearn 	error = smb_ctx_gethandle(ctx);
625f1b9d127SSheldon Hearn 	if (error) {
6268d4076f0SSheldon Hearn 		smb_error("can't get handle to requester (no /dev/"NSMB_NAME"* device)", 0);
627f1b9d127SSheldon Hearn 		return EINVAL;
628f1b9d127SSheldon Hearn 	}
629f1b9d127SSheldon Hearn 	bzero(&rq, sizeof(rq));
630f1b9d127SSheldon Hearn 	bcopy(&ctx->ct_ssn, &rq.ioc_ssn, sizeof(struct smbioc_ossn));
631f1b9d127SSheldon Hearn 	bcopy(&ctx->ct_sh, &rq.ioc_sh, sizeof(struct smbioc_oshare));
632f1b9d127SSheldon Hearn 	rq.ioc_flags = flags;
633f1b9d127SSheldon Hearn 	rq.ioc_level = level;
634f1b9d127SSheldon Hearn 	if (ioctl(ctx->ct_fd, SMBIOC_LOOKUP, &rq) == -1) {
635f1b9d127SSheldon Hearn 		error = errno;
636f1b9d127SSheldon Hearn 		if (flags & SMBLK_CREATE)
637f1b9d127SSheldon Hearn 			smb_error("unable to open connection", error);
638f1b9d127SSheldon Hearn 		return error;
639f1b9d127SSheldon Hearn 	}
640f1b9d127SSheldon Hearn 	return 0;
641f1b9d127SSheldon Hearn }
642f1b9d127SSheldon Hearn 
643f1b9d127SSheldon Hearn int
smb_ctx_login(struct smb_ctx * ctx)644f1b9d127SSheldon Hearn smb_ctx_login(struct smb_ctx *ctx)
645f1b9d127SSheldon Hearn {
646f1b9d127SSheldon Hearn 	struct smbioc_ossn *ssn = &ctx->ct_ssn;
647f1b9d127SSheldon Hearn 	struct smbioc_oshare *sh = &ctx->ct_sh;
648f1b9d127SSheldon Hearn 	int error;
649f1b9d127SSheldon Hearn 
650f1b9d127SSheldon Hearn 	if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) {
651f1b9d127SSheldon Hearn 		smb_error("smb_ctx_resolve() should be called first", 0);
652f1b9d127SSheldon Hearn 		return EINVAL;
653f1b9d127SSheldon Hearn 	}
654f1b9d127SSheldon Hearn 	if (ctx->ct_fd != -1) {
655f1b9d127SSheldon Hearn 		close(ctx->ct_fd);
656f1b9d127SSheldon Hearn 		ctx->ct_fd = -1;
657f1b9d127SSheldon Hearn 	}
658f1b9d127SSheldon Hearn 	error = smb_ctx_gethandle(ctx);
659f1b9d127SSheldon Hearn 	if (error) {
660f1b9d127SSheldon Hearn 		smb_error("can't get handle to requester", 0);
661f1b9d127SSheldon Hearn 		return EINVAL;
662f1b9d127SSheldon Hearn 	}
663f1b9d127SSheldon Hearn 	if (ioctl(ctx->ct_fd, SMBIOC_OPENSESSION, ssn) == -1) {
664f1b9d127SSheldon Hearn 		error = errno;
665f1b9d127SSheldon Hearn 		smb_error("can't open session to server %s", error, ssn->ioc_srvname);
666f1b9d127SSheldon Hearn 		return error;
667f1b9d127SSheldon Hearn 	}
668f1b9d127SSheldon Hearn 	if (sh->ioc_share[0] == 0)
669f1b9d127SSheldon Hearn 		return 0;
670f1b9d127SSheldon Hearn 	if (ioctl(ctx->ct_fd, SMBIOC_OPENSHARE, sh) == -1) {
671f1b9d127SSheldon Hearn 		error = errno;
672f1b9d127SSheldon Hearn 		smb_error("can't connect to share //%s/%s", error,
673f1b9d127SSheldon Hearn 		    ssn->ioc_srvname, sh->ioc_share);
674f1b9d127SSheldon Hearn 		return error;
675f1b9d127SSheldon Hearn 	}
676f1b9d127SSheldon Hearn 	return 0;
677f1b9d127SSheldon Hearn }
678f1b9d127SSheldon Hearn 
679f1b9d127SSheldon Hearn int
smb_ctx_setflags(struct smb_ctx * ctx,int level,int mask,int flags)680f1b9d127SSheldon Hearn smb_ctx_setflags(struct smb_ctx *ctx, int level, int mask, int flags)
681f1b9d127SSheldon Hearn {
682f1b9d127SSheldon Hearn 	struct smbioc_flags fl;
683f1b9d127SSheldon Hearn 
684f1b9d127SSheldon Hearn 	if (ctx->ct_fd == -1)
685f1b9d127SSheldon Hearn 		return EINVAL;
686f1b9d127SSheldon Hearn 	fl.ioc_level = level;
687f1b9d127SSheldon Hearn 	fl.ioc_mask = mask;
688f1b9d127SSheldon Hearn 	fl.ioc_flags = flags;
689f1b9d127SSheldon Hearn 	if (ioctl(ctx->ct_fd, SMBIOC_SETFLAGS, &fl) == -1)
690f1b9d127SSheldon Hearn 		return errno;
691f1b9d127SSheldon Hearn 	return 0;
692f1b9d127SSheldon Hearn }
693f1b9d127SSheldon Hearn 
694f1b9d127SSheldon Hearn /*
695f1b9d127SSheldon Hearn  * level values:
696f1b9d127SSheldon Hearn  * 0 - default
697f1b9d127SSheldon Hearn  * 1 - server
698f1b9d127SSheldon Hearn  * 2 - server:user
699f1b9d127SSheldon Hearn  * 3 - server:user:share
700f1b9d127SSheldon Hearn  */
701f1b9d127SSheldon Hearn static int
smb_ctx_readrcsection(struct smb_ctx * ctx,const char * sname,int level)702f1b9d127SSheldon Hearn smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level)
703f1b9d127SSheldon Hearn {
704f1b9d127SSheldon Hearn 	char *p;
705f1b9d127SSheldon Hearn 	int error;
706f1b9d127SSheldon Hearn 
7078d4076f0SSheldon Hearn 	if (level >= 0) {
708f1b9d127SSheldon Hearn 		rc_getstringptr(smb_rc, sname, "charsets", &p);
709f1b9d127SSheldon Hearn 		if (p) {
710f1b9d127SSheldon Hearn 			error = smb_ctx_setcharset(ctx, p);
711f1b9d127SSheldon Hearn 			if (error)
712f1b9d127SSheldon Hearn 				smb_error("charset specification in the section '%s' ignored", error, sname);
713f1b9d127SSheldon Hearn 		}
714f1b9d127SSheldon Hearn 	}
715f1b9d127SSheldon Hearn 	if (level <= 1) {
716f1b9d127SSheldon Hearn 		rc_getint(smb_rc, sname, "timeout", &ctx->ct_ssn.ioc_timeout);
717f1b9d127SSheldon Hearn 		rc_getint(smb_rc, sname, "retry_count", &ctx->ct_ssn.ioc_retrycount);
718f1b9d127SSheldon Hearn 	}
719f1b9d127SSheldon Hearn 	if (level == 1) {
720f1b9d127SSheldon Hearn 		rc_getstringptr(smb_rc, sname, "addr", &p);
721f1b9d127SSheldon Hearn 		if (p) {
722f1b9d127SSheldon Hearn 			error = smb_ctx_setsrvaddr(ctx, p);
723f1b9d127SSheldon Hearn 			if (error) {
724f1b9d127SSheldon Hearn 				smb_error("invalid address specified in the section %s", 0, sname);
725f1b9d127SSheldon Hearn 				return error;
726f1b9d127SSheldon Hearn 			}
727f1b9d127SSheldon Hearn 		}
728f1b9d127SSheldon Hearn 	}
729f1b9d127SSheldon Hearn 	if (level >= 2) {
730f1b9d127SSheldon Hearn 		rc_getstringptr(smb_rc, sname, "password", &p);
731f1b9d127SSheldon Hearn 		if (p)
732f1b9d127SSheldon Hearn 			smb_ctx_setpassword(ctx, p);
733f1b9d127SSheldon Hearn 	}
734f1b9d127SSheldon Hearn 	rc_getstringptr(smb_rc, sname, "workgroup", &p);
735f1b9d127SSheldon Hearn 	if (p)
736f1b9d127SSheldon Hearn 		smb_ctx_setworkgroup(ctx, p);
737f1b9d127SSheldon Hearn 	return 0;
738f1b9d127SSheldon Hearn }
739f1b9d127SSheldon Hearn 
740f1b9d127SSheldon Hearn /*
741f1b9d127SSheldon Hearn  * read rc file as follows:
742f1b9d127SSheldon Hearn  * 1. read [default] section
743f1b9d127SSheldon Hearn  * 2. override with [server] section
744f1b9d127SSheldon Hearn  * 3. override with [server:user:share] section
745f1b9d127SSheldon Hearn  * Since abcence of rcfile is not fatal, silently ignore this fact.
746f1b9d127SSheldon Hearn  * smb_rc file should be closed by caller.
747f1b9d127SSheldon Hearn  */
748f1b9d127SSheldon Hearn int
smb_ctx_readrc(struct smb_ctx * ctx)749f1b9d127SSheldon Hearn smb_ctx_readrc(struct smb_ctx *ctx)
750f1b9d127SSheldon Hearn {
751f1b9d127SSheldon Hearn 	char sname[SMB_MAXSRVNAMELEN + SMB_MAXUSERNAMELEN + SMB_MAXSHARENAMELEN + 4];
752f1b9d127SSheldon Hearn /*	char *p;*/
753f1b9d127SSheldon Hearn 
754f1b9d127SSheldon Hearn 	if (smb_open_rcfile() != 0)
755f1b9d127SSheldon Hearn 		return 0;
756f1b9d127SSheldon Hearn 
757f1b9d127SSheldon Hearn 	if (ctx->ct_ssn.ioc_user[0] == 0 || ctx->ct_ssn.ioc_srvname[0] == 0)
758f1b9d127SSheldon Hearn 		return 0;
759f1b9d127SSheldon Hearn 
760f1b9d127SSheldon Hearn 	smb_ctx_readrcsection(ctx, "default", 0);
761f1b9d127SSheldon Hearn 	nb_ctx_readrcsection(smb_rc, ctx->ct_nb, "default", 0);
762f1b9d127SSheldon Hearn 	smb_ctx_readrcsection(ctx, ctx->ct_ssn.ioc_srvname, 1);
763f1b9d127SSheldon Hearn 	nb_ctx_readrcsection(smb_rc, ctx->ct_nb, ctx->ct_ssn.ioc_srvname, 1);
764f1b9d127SSheldon Hearn 	/*
765f1b9d127SSheldon Hearn 	 * SERVER:USER parameters
766f1b9d127SSheldon Hearn 	 */
767f1b9d127SSheldon Hearn 	snprintf(sname, sizeof(sname), "%s:%s", ctx->ct_ssn.ioc_srvname,
768f1b9d127SSheldon Hearn 	    ctx->ct_ssn.ioc_user);
769f1b9d127SSheldon Hearn 	smb_ctx_readrcsection(ctx, sname, 2);
770f1b9d127SSheldon Hearn 
771f1b9d127SSheldon Hearn 	if (ctx->ct_sh.ioc_share[0] != 0) {
772f1b9d127SSheldon Hearn 		/*
773f1b9d127SSheldon Hearn 		 * SERVER:USER:SHARE parameters
774f1b9d127SSheldon Hearn 	         */
775f1b9d127SSheldon Hearn 		snprintf(sname, sizeof(sname), "%s:%s:%s", ctx->ct_ssn.ioc_srvname,
776f1b9d127SSheldon Hearn 		    ctx->ct_ssn.ioc_user, ctx->ct_sh.ioc_share);
777f1b9d127SSheldon Hearn 		smb_ctx_readrcsection(ctx, sname, 3);
778f1b9d127SSheldon Hearn 	}
779f1b9d127SSheldon Hearn 	return 0;
780f1b9d127SSheldon Hearn }
781f1b9d127SSheldon Hearn 
782