1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22c5866007SKeyur Desai  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2312b65585SGordon Ross  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
24da6c28aaSamw  */
25da6c28aaSamw 
2689dc44ceSjose borrego #include <sys/param.h>
27da6c28aaSamw #include <string.h>
28da6c28aaSamw #include <stdlib.h>
29da6c28aaSamw #include <stdio.h>
30da6c28aaSamw #include <pwd.h>
31c5866007SKeyur Desai #include <nss_dbdefs.h>
323ad684d6Sjb #include <assert.h>
333ad684d6Sjb #include <strings.h>
34da6c28aaSamw #include <sys/stat.h>
35c5866007SKeyur Desai #include <sys/idmap.h>
36da6c28aaSamw #include <smbsrv/libsmb.h>
37da6c28aaSamw #include <smbsrv/libmlsvc.h>
38da6c28aaSamw #include <smbsrv/smbinfo.h>
39da6c28aaSamw 
40da6c28aaSamw #define	SMB_AUTOHOME_KEYSIZ	128
41da6c28aaSamw #define	SMB_AUTOHOME_MAXARG	4
42da6c28aaSamw #define	SMB_AUTOHOME_BUFSIZ	2048
43da6c28aaSamw 
44da6c28aaSamw typedef struct smb_autohome_info {
45da6c28aaSamw 	struct smb_autohome_info *magic1;
46da6c28aaSamw 	FILE *fp;
47da6c28aaSamw 	smb_autohome_t autohome;
48da6c28aaSamw 	char buf[SMB_AUTOHOME_BUFSIZ];
49da6c28aaSamw 	char *argv[SMB_AUTOHOME_MAXARG];
50da6c28aaSamw 	int lineno;
51da6c28aaSamw 	struct smb_autohome_info *magic2;
52da6c28aaSamw } smb_autohome_info_t;
53da6c28aaSamw 
54da6c28aaSamw static smb_autohome_info_t smb_ai;
55da6c28aaSamw 
56da6c28aaSamw static smb_autohome_t *smb_autohome_make_entry(smb_autohome_info_t *);
57da6c28aaSamw static char *smb_autohome_keysub(const char *, char *, int);
58da6c28aaSamw static smb_autohome_info_t *smb_autohome_getinfo(void);
593ad684d6Sjb static smb_autohome_t *smb_autohome_lookup(const char *);
603ad684d6Sjb static void smb_autohome_setent(void);
613ad684d6Sjb static void smb_autohome_endent(void);
623ad684d6Sjb static smb_autohome_t *smb_autohome_getent(const char *);
6389dc44ceSjose borrego static void smb_autohome_parse_options(smb_share_t *);
64c5866007SKeyur Desai static int smb_autohome_add_private(const char *, uid_t, gid_t);
65da6c28aaSamw 
66da6c28aaSamw /*
67bbf21555SRichard Lowe  * Add an autohome share.  See smb_autohome(5) for details.
68da6c28aaSamw  *
69da6c28aaSamw  * If share directory contains backslash path separators, they will
70da6c28aaSamw  * be converted to forward slash to support NT/DOS path style for
71da6c28aaSamw  * autohome shares.
729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * We need to serialize calls to smb_autohome_lookup because it
749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * operates on the global smb_ai structure.
75da6c28aaSamw  */
763ad684d6Sjb void
smb_autohome_add(const smb_token_t * token)77fe1c642dSBill Krier smb_autohome_add(const smb_token_t *token)
78c5866007SKeyur Desai {
79c5866007SKeyur Desai 
80c5866007SKeyur Desai 	char		*username;
81c5866007SKeyur Desai 	struct passwd	pw;
82c5866007SKeyur Desai 	char		buf[NSS_LINELEN_PASSWD];
83c5866007SKeyur Desai 	uid_t		uid;
84c5866007SKeyur Desai 	gid_t		gid;
85c5866007SKeyur Desai 
8612b65585SGordon Ross 	if (token->tkn_flags & SMB_ATF_ANON)
8712b65585SGordon Ross 		return;
8812b65585SGordon Ross 
89c5866007SKeyur Desai 	uid = token->tkn_user.i_id;
90c5866007SKeyur Desai 	gid = token->tkn_primary_grp.i_id;
91c5866007SKeyur Desai 
92c5866007SKeyur Desai 	if (IDMAP_ID_IS_EPHEMERAL(uid)) {
93c5866007SKeyur Desai 		username = token->tkn_account_name;
94c5866007SKeyur Desai 		assert(username);
95c5866007SKeyur Desai 	} else {
96c5866007SKeyur Desai 		if (getpwuid_r(uid, &pw, buf, sizeof (buf)) == NULL) {
97*297b0deaSJuno Park 			syslog(LOG_DEBUG, "unable to determine name for " \
98c5866007SKeyur Desai 			    "UID: %u\n", uid);
99c5866007SKeyur Desai 			return;
100c5866007SKeyur Desai 		}
101c5866007SKeyur Desai 		username = pw.pw_name;
102c5866007SKeyur Desai 	}
103c5866007SKeyur Desai 
104c5866007SKeyur Desai 	if (smb_autohome_add_private(username, uid, gid) != NERR_Success) {
105c5866007SKeyur Desai 		if (!smb_isstrlwr(username)) {
106c5866007SKeyur Desai 			(void) smb_strlwr(username);
107c5866007SKeyur Desai 			(void) smb_autohome_add_private(username, uid, gid);
108c5866007SKeyur Desai 		}
109c5866007SKeyur Desai 	}
110c5866007SKeyur Desai }
111c5866007SKeyur Desai 
112c5866007SKeyur Desai /*
113c5866007SKeyur Desai  * Remove an autohome share.
114c5866007SKeyur Desai  */
115c5866007SKeyur Desai void
smb_autohome_remove(const char * username)116c5866007SKeyur Desai smb_autohome_remove(const char *username)
117c5866007SKeyur Desai {
118c5866007SKeyur Desai 	smb_share_t si;
119c5866007SKeyur Desai 
120c5866007SKeyur Desai 	assert(username);
121c5866007SKeyur Desai 
122c5866007SKeyur Desai 	if (smb_shr_get((char *)username, &si) == NERR_Success) {
123c5866007SKeyur Desai 		if (si.shr_flags & SMB_SHRF_AUTOHOME)
124c5866007SKeyur Desai 			(void) smb_shr_remove((char *)username);
125c5866007SKeyur Desai 	}
126c5866007SKeyur Desai }
127c5866007SKeyur Desai 
128c5866007SKeyur Desai /*
129c5866007SKeyur Desai  * An autohome share is not created if a static share using the same name
130c5866007SKeyur Desai  * already exists.  Autohome shares will be added for each login attempt.
131c5866007SKeyur Desai  *
132c5866007SKeyur Desai  * Calling smb_shr_get() may return the first argument in all lower case so
133c5866007SKeyur Desai  * a copy is passed in instead.
134c5866007SKeyur Desai  *
135c5866007SKeyur Desai  * We need to serialize calls to smb_autohome_lookup because it
136c5866007SKeyur Desai  * operates on the global smb_ai structure.
137c5866007SKeyur Desai  */
138c5866007SKeyur Desai static int
smb_autohome_add_private(const char * username,uid_t uid,gid_t gid)139c5866007SKeyur Desai smb_autohome_add_private(const char *username, uid_t uid, gid_t gid)
140da6c28aaSamw {
1419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	static mutex_t	autohome_mutex;
142fe1c642dSBill Krier 	smb_share_t	si;
143fe1c642dSBill Krier 	smb_autohome_t	*ai;
144*297b0deaSJuno Park 	char		shr_name[MAXNAMELEN];
145da6c28aaSamw 
146c5866007SKeyur Desai 	(void) strlcpy(shr_name, username, sizeof (shr_name));
147da6c28aaSamw 
148c5866007SKeyur Desai 	if (smb_shr_get(shr_name, &si) == NERR_Success) {
1493db3f65cSamw 		if ((si.shr_flags & SMB_SHRF_AUTOHOME) == 0)
150c5866007SKeyur Desai 			return (NERR_Success);
1513db3f65cSamw 
152b89a8333Snatalie li - Sun Microsystems - Irvine United States 		(void) smb_shr_add(&si);
153c5866007SKeyur Desai 		return (NERR_Success);
1543db3f65cSamw 	}
1553db3f65cSamw 
1569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	(void) mutex_lock(&autohome_mutex);
1579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((ai = smb_autohome_lookup(username)) == NULL) {
1599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) mutex_unlock(&autohome_mutex);
160c5866007SKeyur Desai 		return (NERR_ItemNotFound);
1619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
162da6c28aaSamw 
1633db3f65cSamw 	bzero(&si, sizeof (smb_share_t));
1643db3f65cSamw 	(void) strlcpy(si.shr_path, ai->ah_path, MAXPATHLEN);
1653db3f65cSamw 	(void) strsubst(si.shr_path, '\\', '/');
166da6c28aaSamw 
1673db3f65cSamw 	(void) strlcpy(si.shr_name, username, MAXNAMELEN);
1683db3f65cSamw 	(void) strlcpy(si.shr_container, ai->ah_container, MAXPATHLEN);
169fe1c642dSBill Krier 	(void) strlcpy(si.shr_cmnt, "Autohome", SMB_SHARE_CMNT_MAX);
17089dc44ceSjose borrego 	smb_autohome_parse_options(&si);
17189dc44ceSjose borrego 	si.shr_flags |= SMB_SHRF_TRANS | SMB_SHRF_AUTOHOME;
172c5866007SKeyur Desai 	si.shr_uid = uid;
173c5866007SKeyur Desai 	si.shr_gid = gid;
174da6c28aaSamw 
1759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	(void) mutex_unlock(&autohome_mutex);
1769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
177c5866007SKeyur Desai 	return (smb_shr_add(&si));
178da6c28aaSamw }
179da6c28aaSamw 
180da6c28aaSamw /*
181da6c28aaSamw  * Search the autohome database for the specified name. The name cannot
182da6c28aaSamw  * be an empty string or begin with * or +.
183da6c28aaSamw  * 1. Search the file for the specified name.
184da6c28aaSamw  * 2. Check for the wildcard rule and, if present, treat it as a match.
185da6c28aaSamw  * 3. Check for the nsswitch rule and, if present, lookup the name
186da6c28aaSamw  *    via the name services. Note that the nsswitch rule will never
187da6c28aaSamw  *    be applied if the wildcard rule is present.
188da6c28aaSamw  *
189da6c28aaSamw  * Returns a pointer to the entry on success or null on failure.
190da6c28aaSamw  */
1913ad684d6Sjb static smb_autohome_t *
smb_autohome_lookup(const char * name)192da6c28aaSamw smb_autohome_lookup(const char *name)
193da6c28aaSamw {
194da6c28aaSamw 	struct passwd *pw;
1953ad684d6Sjb 	smb_autohome_t *ah = NULL;
196da6c28aaSamw 
197da6c28aaSamw 	if (name == NULL)
198da6c28aaSamw 		return (NULL);
199da6c28aaSamw 
200da6c28aaSamw 	if (*name == '\0' || *name == '*' || *name == '+')
201da6c28aaSamw 		return (NULL);
202da6c28aaSamw 
203da6c28aaSamw 	smb_autohome_setent();
204da6c28aaSamw 
205da6c28aaSamw 	while ((ah = smb_autohome_getent(name)) != NULL) {
206da6c28aaSamw 		if (strcasecmp(ah->ah_name, name) == 0)
207da6c28aaSamw 			break;
208da6c28aaSamw 	}
209da6c28aaSamw 
210da6c28aaSamw 	if (ah == NULL) {
211da6c28aaSamw 		smb_autohome_setent();
212da6c28aaSamw 
213da6c28aaSamw 		while ((ah = smb_autohome_getent(name)) != NULL) {
214da6c28aaSamw 			if (strcasecmp(ah->ah_name, "*") == 0) {
215da6c28aaSamw 				ah->ah_name = (char *)name;
216da6c28aaSamw 				break;
217da6c28aaSamw 			}
218da6c28aaSamw 		}
219da6c28aaSamw 	}
220da6c28aaSamw 
221da6c28aaSamw 	if (ah == NULL) {
222da6c28aaSamw 		smb_autohome_setent();
223da6c28aaSamw 
224da6c28aaSamw 		while ((ah = smb_autohome_getent("+nsswitch")) != NULL) {
225da6c28aaSamw 			if (strcasecmp("+nsswitch", ah->ah_name) != 0)
226da6c28aaSamw 				continue;
227da6c28aaSamw 			if ((pw = getpwnam(name)) == NULL) {
2283ad684d6Sjb 				ah = NULL;
229da6c28aaSamw 				break;
230da6c28aaSamw 			}
231da6c28aaSamw 
232da6c28aaSamw 			ah->ah_name = pw->pw_name;
233da6c28aaSamw 
234da6c28aaSamw 			if (ah->ah_path)
235da6c28aaSamw 				ah->ah_container = ah->ah_path;
236da6c28aaSamw 
237da6c28aaSamw 			ah->ah_path = pw->pw_dir;
238da6c28aaSamw 			break;
239da6c28aaSamw 		}
240da6c28aaSamw 	}
241da6c28aaSamw 
242da6c28aaSamw 	smb_autohome_endent();
243da6c28aaSamw 	return (ah);
244da6c28aaSamw }
245da6c28aaSamw 
246da6c28aaSamw /*
247da6c28aaSamw  * Open or rewind the autohome database.
248da6c28aaSamw  */
2493ad684d6Sjb static void
smb_autohome_setent(void)250da6c28aaSamw smb_autohome_setent(void)
251da6c28aaSamw {
252da6c28aaSamw 	smb_autohome_info_t *si;
253dc20a302Sas 	char path[MAXNAMELEN];
254da6c28aaSamw 	char filename[MAXNAMELEN];
255dc20a302Sas 	int rc;
256da6c28aaSamw 
257da6c28aaSamw 	if ((si = smb_autohome_getinfo()) != 0) {
258da6c28aaSamw 		(void) fseek(si->fp, 0L, SEEK_SET);
259da6c28aaSamw 		si->lineno = 0;
260da6c28aaSamw 		return;
261da6c28aaSamw 	}
262da6c28aaSamw 
263da6c28aaSamw 	if ((si = &smb_ai) == 0)
264da6c28aaSamw 		return;
265da6c28aaSamw 
266dc20a302Sas 	rc = smb_config_getstr(SMB_CI_AUTOHOME_MAP, path, sizeof (path));
267dc20a302Sas 	if (rc != SMBD_SMF_OK)
268dc20a302Sas 		return;
269dc20a302Sas 
270dc20a302Sas 	(void) snprintf(filename, MAXNAMELEN, "%s/%s", path,
271da6c28aaSamw 	    SMB_AUTOHOME_FILE);
272da6c28aaSamw 
273da6c28aaSamw 	if ((si->fp = fopen(filename, "r")) == NULL)
274da6c28aaSamw 		return;
275da6c28aaSamw 
276da6c28aaSamw 	si->magic1 = si;
277da6c28aaSamw 	si->magic2 = si;
278da6c28aaSamw 	si->lineno = 0;
279da6c28aaSamw }
280da6c28aaSamw 
281da6c28aaSamw /*
282da6c28aaSamw  * Close the autohome database and invalidate the autohome info.
283da6c28aaSamw  * We can't zero the whole info structure because the application
284da6c28aaSamw  * should still have access to the data after the file is closed.
285da6c28aaSamw  */
2863ad684d6Sjb static void
smb_autohome_endent(void)287da6c28aaSamw smb_autohome_endent(void)
288da6c28aaSamw {
289da6c28aaSamw 	smb_autohome_info_t *si;
290da6c28aaSamw 
291da6c28aaSamw 	if ((si = smb_autohome_getinfo()) != 0) {
292da6c28aaSamw 		(void) fclose(si->fp);
293da6c28aaSamw 		si->fp = 0;
294da6c28aaSamw 		si->magic1 = 0;
295da6c28aaSamw 		si->magic2 = 0;
296da6c28aaSamw 	}
297da6c28aaSamw }
298da6c28aaSamw 
299da6c28aaSamw /*
300da6c28aaSamw  * Return the next entry in the autohome database, opening the file
301da6c28aaSamw  * if necessary.  Returns null on EOF or error.
302da6c28aaSamw  *
303da6c28aaSamw  * Note that we are not looking for the specified name. The name is
304da6c28aaSamw  * only used for key substitution, so that the caller sees the entry
305da6c28aaSamw  * in expanded form.
306da6c28aaSamw  */
3073ad684d6Sjb static smb_autohome_t *
smb_autohome_getent(const char * name)308da6c28aaSamw smb_autohome_getent(const char *name)
309da6c28aaSamw {
310da6c28aaSamw 	smb_autohome_info_t *si;
311da6c28aaSamw 	char *bp;
312da6c28aaSamw 
313da6c28aaSamw 	if ((si = smb_autohome_getinfo()) == 0) {
314da6c28aaSamw 		smb_autohome_setent();
315da6c28aaSamw 
316da6c28aaSamw 		if ((si = smb_autohome_getinfo()) == 0)
317da6c28aaSamw 			return (0);
318da6c28aaSamw 	}
319da6c28aaSamw 
320da6c28aaSamw 	/*
321da6c28aaSamw 	 * Find the next non-comment, non-empty line.
322da6c28aaSamw 	 * Anything after a # is a comment and can be discarded.
323da6c28aaSamw 	 * Discard a newline to avoid it being included in the parsing
324da6c28aaSamw 	 * that follows.
325da6c28aaSamw 	 * Leading and training whitespace is discarded, and replicated
326da6c28aaSamw 	 * whitespace is compressed to simplify the token parsing,
327da6c28aaSamw 	 * although strsep() deals with that better than strtok().
328da6c28aaSamw 	 */
329da6c28aaSamw 	do {
330da6c28aaSamw 		if (fgets(si->buf, SMB_AUTOHOME_BUFSIZ, si->fp) == 0)
331da6c28aaSamw 			return (0);
332da6c28aaSamw 
333da6c28aaSamw 		++si->lineno;
334da6c28aaSamw 
335da6c28aaSamw 		if ((bp = strpbrk(si->buf, "#\r\n")) != 0)
336da6c28aaSamw 			*bp = '\0';
337da6c28aaSamw 
338da6c28aaSamw 		(void) trim_whitespace(si->buf);
339da6c28aaSamw 		bp = strcanon(si->buf, " \t");
340da6c28aaSamw 	} while (*bp == '\0');
341da6c28aaSamw 
342da6c28aaSamw 	(void) smb_autohome_keysub(name, si->buf, SMB_AUTOHOME_BUFSIZ);
343da6c28aaSamw 	return (smb_autohome_make_entry(si));
344da6c28aaSamw }
345da6c28aaSamw 
346da6c28aaSamw /*
347da6c28aaSamw  * Set up an autohome entry from the line buffer. The line should just
348da6c28aaSamw  * contain tokens separated by single whitespace. The line format is:
349da6c28aaSamw  *	<username> <home-dir-path> <ADS container>
350da6c28aaSamw  */
351da6c28aaSamw static smb_autohome_t *
smb_autohome_make_entry(smb_autohome_info_t * si)352da6c28aaSamw smb_autohome_make_entry(smb_autohome_info_t *si)
353da6c28aaSamw {
354da6c28aaSamw 	char *bp;
355da6c28aaSamw 	int i;
356da6c28aaSamw 
357da6c28aaSamw 	bp = si->buf;
358da6c28aaSamw 
359da6c28aaSamw 	for (i = 0; i < SMB_AUTOHOME_MAXARG; ++i)
36089dc44ceSjose borrego 		si->argv[i] = NULL;
361da6c28aaSamw 
362da6c28aaSamw 	for (i = 0; i < SMB_AUTOHOME_MAXARG; ++i) {
363da6c28aaSamw 		do {
36489dc44ceSjose borrego 			if ((si->argv[i] = strsep(&bp, " \t")) == NULL)
365da6c28aaSamw 				break;
366da6c28aaSamw 		} while (*(si->argv[i]) == '\0');
367da6c28aaSamw 
36889dc44ceSjose borrego 		if (si->argv[i] == NULL)
369da6c28aaSamw 			break;
370da6c28aaSamw 	}
371da6c28aaSamw 
372da6c28aaSamw 	if ((si->autohome.ah_name = si->argv[0]) == NULL) {
373da6c28aaSamw 		/*
374da6c28aaSamw 		 * Sanity check: the name could be an empty
375da6c28aaSamw 		 * string but it can't be a null pointer.
376da6c28aaSamw 		 */
377da6c28aaSamw 		return (0);
378da6c28aaSamw 	}
379da6c28aaSamw 
380da6c28aaSamw 	if ((si->autohome.ah_path = si->argv[1]) == NULL)
381da6c28aaSamw 		si->autohome.ah_path = "";
382da6c28aaSamw 
383da6c28aaSamw 	if ((si->autohome.ah_container = si->argv[2]) == NULL)
384da6c28aaSamw 		si->autohome.ah_container = "";
385da6c28aaSamw 
386da6c28aaSamw 	return (&si->autohome);
387da6c28aaSamw }
388da6c28aaSamw 
389da6c28aaSamw /*
390da6c28aaSamw  * Substitute the ? and & map keys.
391da6c28aaSamw  * ? is replaced by the first character of the name
392da6c28aaSamw  * & is replaced by the whole name.
393da6c28aaSamw  */
394da6c28aaSamw static char *
smb_autohome_keysub(const char * name,char * buf,int buflen)395da6c28aaSamw smb_autohome_keysub(const char *name, char *buf, int buflen)
396da6c28aaSamw {
397da6c28aaSamw 	char key[SMB_AUTOHOME_KEYSIZ];
398da6c28aaSamw 	char *ampersand;
399da6c28aaSamw 	char *tmp;
40055bf511dSas 	int bufsize = buflen;
401da6c28aaSamw 
402da6c28aaSamw 	(void) strlcpy(key, buf, SMB_AUTOHOME_KEYSIZ);
403da6c28aaSamw 
404da6c28aaSamw 	if ((tmp = strpbrk(key, " \t")) == NULL)
405da6c28aaSamw 		return (NULL);
406da6c28aaSamw 
407da6c28aaSamw 	*tmp = '\0';
408da6c28aaSamw 
40955bf511dSas 	/*
41055bf511dSas 	 * Substitution characters are not allowed in the key.
41155bf511dSas 	 */
41255bf511dSas 	if (strpbrk(key, "?&") != NULL)
41355bf511dSas 		return (NULL);
41455bf511dSas 
415da6c28aaSamw 	if (strcmp(key, "*") == 0 && name != NULL)
416da6c28aaSamw 		(void) strlcpy(key, name, SMB_AUTOHOME_KEYSIZ);
417da6c28aaSamw 
418da6c28aaSamw 	(void) strsubst(buf, '?', *key);
419da6c28aaSamw 
420da6c28aaSamw 	while ((ampersand = strchr(buf, '&')) != NULL) {
421da6c28aaSamw 		if ((tmp = strdup(ampersand + 1)) == NULL)
422da6c28aaSamw 			return (0);
423da6c28aaSamw 
42455bf511dSas 		bufsize = buflen - (ampersand - buf);
42555bf511dSas 		(void) strlcpy(ampersand, key, bufsize);
42655bf511dSas 		(void) strlcat(ampersand, tmp, bufsize);
427da6c28aaSamw 		free(tmp);
428da6c28aaSamw 	}
429da6c28aaSamw 
430da6c28aaSamw 	return (buf);
431da6c28aaSamw }
432da6c28aaSamw 
433da6c28aaSamw /*
434da6c28aaSamw  * Get a pointer to the context buffer and validate it.
435da6c28aaSamw  */
436da6c28aaSamw static smb_autohome_info_t *
smb_autohome_getinfo(void)437da6c28aaSamw smb_autohome_getinfo(void)
438da6c28aaSamw {
439da6c28aaSamw 	smb_autohome_info_t *si;
440da6c28aaSamw 
441da6c28aaSamw 	if ((si = &smb_ai) == 0)
442da6c28aaSamw 		return (0);
443da6c28aaSamw 
444da6c28aaSamw 	if ((si->magic1 == si) && (si->magic2 == si) && (si->fp != NULL))
445da6c28aaSamw 		return (si);
446da6c28aaSamw 
447da6c28aaSamw 	return (0);
448da6c28aaSamw }
44989dc44ceSjose borrego 
45089dc44ceSjose borrego /*
45189dc44ceSjose borrego  * Parse the options string, which contains a comma separated list of
45289dc44ceSjose borrego  * name-value pairs.  One of the options may be an AD container, which
45389dc44ceSjose borrego  * is also a comma separated list of name-value pairs.  For example,
45489dc44ceSjose borrego  * dn=ad,dn=sun,dn=com,ou=users
45589dc44ceSjose borrego  *
45689dc44ceSjose borrego  * All options other than the AD container will be extracted from
45789dc44ceSjose borrego  * shr_container and used to set share properties.
45889dc44ceSjose borrego  * On return, shr_container will contain the AD container string.
45989dc44ceSjose borrego  */
46089dc44ceSjose borrego static void
smb_autohome_parse_options(smb_share_t * si)46189dc44ceSjose borrego smb_autohome_parse_options(smb_share_t *si)
46289dc44ceSjose borrego {
46389dc44ceSjose borrego 	char buf[MAXPATHLEN];
46489dc44ceSjose borrego 	char **argv;
46589dc44ceSjose borrego 	char **ap;
46689dc44ceSjose borrego 	char *bp;
46789dc44ceSjose borrego 	char *value;
46889dc44ceSjose borrego 	boolean_t separator = B_FALSE;
46989dc44ceSjose borrego 	int argc;
47089dc44ceSjose borrego 	int i;
47189dc44ceSjose borrego 
47289dc44ceSjose borrego 	if (strlcpy(buf, si->shr_container, MAXPATHLEN) == 0)
47389dc44ceSjose borrego 		return;
47489dc44ceSjose borrego 
47589dc44ceSjose borrego 	for (argc = 1, bp = si->shr_container; *bp != '\0'; ++bp)
47689dc44ceSjose borrego 		if (*bp == ',')
47789dc44ceSjose borrego 			++argc;
47889dc44ceSjose borrego 
47989dc44ceSjose borrego 	if ((argv = calloc(argc + 1, sizeof (char *))) == NULL)
48089dc44ceSjose borrego 		return;
48189dc44ceSjose borrego 
48289dc44ceSjose borrego 	ap = argv;
48389dc44ceSjose borrego 	for (bp = buf, i = 0; i < argc; ++i) {
48489dc44ceSjose borrego 		do {
48589dc44ceSjose borrego 			if ((value = strsep(&bp, ",")) == NULL)
48689dc44ceSjose borrego 				break;
48789dc44ceSjose borrego 		} while (*value == '\0');
48889dc44ceSjose borrego 
48989dc44ceSjose borrego 		if (value == NULL)
49089dc44ceSjose borrego 			break;
49189dc44ceSjose borrego 
49289dc44ceSjose borrego 		*ap++ = value;
49389dc44ceSjose borrego 	}
49489dc44ceSjose borrego 	*ap = NULL;
49589dc44ceSjose borrego 
49689dc44ceSjose borrego 	si->shr_container[0] = '\0';
49789dc44ceSjose borrego 	bp = si->shr_container;
49889dc44ceSjose borrego 
49989dc44ceSjose borrego 	for (ap = argv; *ap != NULL; ++ap) {
50089dc44ceSjose borrego 		value = *ap;
50189dc44ceSjose borrego 
5028b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (strncasecmp(value, "catia=", 6) == 0) {
5039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			smb_shr_sa_setflag((value + 6), si, SMB_SHRF_CATIA);
5048b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			continue;
5058b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		}
5068b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
50789dc44ceSjose borrego 		if (strncasecmp(value, "csc=", 4) == 0) {
50889dc44ceSjose borrego 			smb_shr_sa_csc_option((value + 4), si);
50989dc44ceSjose borrego 			continue;
51089dc44ceSjose borrego 		}
51189dc44ceSjose borrego 
512e3f2c991SKeyur Desai 		if (strncasecmp(value, "abe=", 4) == 0) {
5139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			smb_shr_sa_setflag((value + 4), si, SMB_SHRF_ABE);
514e3f2c991SKeyur Desai 			continue;
515e3f2c991SKeyur Desai 		}
516e3f2c991SKeyur Desai 
51789dc44ceSjose borrego 		if (strncasecmp(value, "description=", 12) == 0) {
51889dc44ceSjose borrego 			(void) strlcpy(si->shr_cmnt, (value + 12),
51989dc44ceSjose borrego 			    SMB_SHARE_CMNT_MAX);
52089dc44ceSjose borrego 			continue;
52189dc44ceSjose borrego 		}
52289dc44ceSjose borrego 
523148c5f43SAlan Wright 		if (strncasecmp(value, "rw=", 3) == 0) {
524148c5f43SAlan Wright 			(void) strlcpy(si->shr_access_rw, (value + 3),
525148c5f43SAlan Wright 			    sizeof (si->shr_access_rw));
526148c5f43SAlan Wright 			continue;
527148c5f43SAlan Wright 		}
528148c5f43SAlan Wright 
529148c5f43SAlan Wright 		if (strncasecmp(value, "ro=", 3) == 0) {
530148c5f43SAlan Wright 			(void) strlcpy(si->shr_access_ro, (value + 3),
531148c5f43SAlan Wright 			    sizeof (si->shr_access_ro));
532148c5f43SAlan Wright 			continue;
533148c5f43SAlan Wright 		}
534148c5f43SAlan Wright 
535148c5f43SAlan Wright 		if (strncasecmp(value, "none=", 5) == 0) {
536148c5f43SAlan Wright 			(void) strlcpy(si->shr_access_none, (value + 5),
537148c5f43SAlan Wright 			    sizeof (si->shr_access_none));
538148c5f43SAlan Wright 			continue;
539148c5f43SAlan Wright 		}
540148c5f43SAlan Wright 
54189dc44ceSjose borrego 		if (separator)
54289dc44ceSjose borrego 			(void) strlcat(bp, ",", MAXPATHLEN);
54389dc44ceSjose borrego 		(void) strlcat(bp, value, MAXPATHLEN);
54489dc44ceSjose borrego 		separator = B_TRUE;
54589dc44ceSjose borrego 	}
54689dc44ceSjose borrego 
54789dc44ceSjose borrego 	free(argv);
54889dc44ceSjose borrego }
549