xref: /titanic_52/usr/src/lib/smbsrv/libsmb/common/smb_util.c (revision b819cea2f73f98c5662230cc9affc8cc84f77fcf)
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 /*
22148c5f43SAlan Wright  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*b819cea2SGordon Ross  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw #include <ctype.h>
27da6c28aaSamw #include <stdio.h>
28148c5f43SAlan Wright #include <stdarg.h>
29148c5f43SAlan Wright #include <unistd.h>
30148c5f43SAlan Wright #include <sys/fcntl.h>
31da6c28aaSamw #include <string.h>
321fcced4cSJordan Brown #include <strings.h>
33da6c28aaSamw #include <stdlib.h>
34da6c28aaSamw #include <pthread.h>
35da6c28aaSamw #include <sys/varargs.h>
36da6c28aaSamw #include <sys/types.h>
376d57f833SAlan Wright #include <sys/mnttab.h>
38b89a8333Snatalie li - Sun Microsystems - Irvine United States #include <tiuser.h>
39b89a8333Snatalie li - Sun Microsystems - Irvine United States #include <netconfig.h>
40b89a8333Snatalie li - Sun Microsystems - Irvine United States #include <netdir.h>
41b89a8333Snatalie li - Sun Microsystems - Irvine United States #include <sys/systeminfo.h>
42b89a8333Snatalie li - Sun Microsystems - Irvine United States #include <sys/utsname.h>
436d57f833SAlan Wright #include <libzfs.h>
441fcced4cSJordan Brown #include <dlfcn.h>
45148c5f43SAlan Wright #include <time.h>
46148c5f43SAlan Wright #include <syslog.h>
476d57f833SAlan Wright #include <smbsrv/string.h>
486d57f833SAlan Wright #include <smbsrv/libsmb.h>
49b89a8333Snatalie li - Sun Microsystems - Irvine United States 
501fcced4cSJordan Brown #define	SMB_LIB_ALT	"/usr/lib/smbsrv/libsmbex.so"
511fcced4cSJordan Brown 
52b89a8333Snatalie li - Sun Microsystems - Irvine United States static boolean_t smb_netgroup_match(struct nd_hostservlist *, char *, int);
53b89a8333Snatalie li - Sun Microsystems - Irvine United States 
54b89a8333Snatalie li - Sun Microsystems - Irvine United States extern int __multi_innetgr();
55b89a8333Snatalie li - Sun Microsystems - Irvine United States extern int __netdir_getbyaddr_nosrv(struct netconfig *,
56b89a8333Snatalie li - Sun Microsystems - Irvine United States     struct nd_hostservlist **, struct netbuf *);
57da6c28aaSamw 
58da6c28aaSamw #define	C2H(c)		"0123456789ABCDEF"[(c)]
59da6c28aaSamw #define	H2C(c)    (((c) >= '0' && (c) <= '9') ? ((c) - '0') :     \
60da6c28aaSamw 	((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) :         \
61da6c28aaSamw 	((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) :         \
62da6c28aaSamw 	'\0')
63da6c28aaSamw #define	DEFAULT_SBOX_SIZE		256
64da6c28aaSamw 
65da6c28aaSamw /*
66da6c28aaSamw  *
67da6c28aaSamw  * hexdump
68da6c28aaSamw  *
69da6c28aaSamw  * Simple hex dump display function. Displays nbytes of buffer in hex and
70da6c28aaSamw  * printable format. Non-printing characters are shown as '.'. It is safe
71da6c28aaSamw  * to pass a null pointer. Each line begins with the offset. If nbytes is
72da6c28aaSamw  * 0, the line will be blank except for the offset. Example output:
73da6c28aaSamw  *
74da6c28aaSamw  * 00000000  54 68 69 73 20 69 73 20 61 20 70 72 6F 67 72 61  This is a progra
75da6c28aaSamw  * 00000010  6D 20 74 65 73 74 2E 00                          m test..
76da6c28aaSamw  *
77da6c28aaSamw  */
78da6c28aaSamw void
79dc20a302Sas200622 hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start)
80da6c28aaSamw {
81da6c28aaSamw 	static char *hex = "0123456789ABCDEF";
82da6c28aaSamw 	int i, count;
83da6c28aaSamw 	int offset;
84da6c28aaSamw 	unsigned char *p;
85da6c28aaSamw 	char ascbuf[64];
86da6c28aaSamw 	char hexbuf[64];
87da6c28aaSamw 	char *ap = ascbuf;
88da6c28aaSamw 	char *hp = hexbuf;
89da6c28aaSamw 
90dc20a302Sas200622 	if ((p = buffer) == NULL)
91da6c28aaSamw 		return;
92da6c28aaSamw 
93da6c28aaSamw 	offset = *start;
94da6c28aaSamw 
95da6c28aaSamw 	*ap = '\0';
96da6c28aaSamw 	*hp = '\0';
97da6c28aaSamw 	count = 0;
98da6c28aaSamw 
99da6c28aaSamw 	for (i = 0; i < nbytes; ++i) {
100da6c28aaSamw 		if (i && (i % 16) == 0) {
101dc20a302Sas200622 			smb_tracef("%06X %s  %s", offset, hexbuf, ascbuf);
102da6c28aaSamw 			ap = ascbuf;
103da6c28aaSamw 			hp = hexbuf;
104da6c28aaSamw 			count = 0;
105da6c28aaSamw 			offset += 16;
106da6c28aaSamw 		}
107da6c28aaSamw 
108da6c28aaSamw 		ap += sprintf(ap, "%c",
109da6c28aaSamw 		    (*p >= 0x20 && *p < 0x7F) ? *p : '.');
110da6c28aaSamw 		hp += sprintf(hp, " %c%c",
111da6c28aaSamw 		    hex[(*p >> 4) & 0x0F], hex[(*p & 0x0F)]);
112da6c28aaSamw 		++p;
113da6c28aaSamw 		++count;
114da6c28aaSamw 	}
115da6c28aaSamw 
116da6c28aaSamw 	if (count) {
117dc20a302Sas200622 		smb_tracef("%06X %-48s  %s", offset, hexbuf, ascbuf);
118da6c28aaSamw 		offset += count;
119da6c28aaSamw 	}
120da6c28aaSamw 
121da6c28aaSamw 	*start = offset;
122da6c28aaSamw }
123da6c28aaSamw 
124da6c28aaSamw void
125da6c28aaSamw hexdump(unsigned char *buffer, int nbytes)
126da6c28aaSamw {
127da6c28aaSamw 	unsigned long start = 0;
128da6c28aaSamw 
129dc20a302Sas200622 	hexdump_offset(buffer, nbytes, &start);
130da6c28aaSamw }
131da6c28aaSamw 
132da6c28aaSamw /*
133da6c28aaSamw  * bintohex
134da6c28aaSamw  *
135da6c28aaSamw  * Converts the given binary data (srcbuf) to
136da6c28aaSamw  * its equivalent hex chars (hexbuf).
137da6c28aaSamw  *
138da6c28aaSamw  * hexlen should be at least twice as srclen.
139da6c28aaSamw  * if hexbuf is not big enough returns 0.
140da6c28aaSamw  * otherwise returns number of valid chars in
141da6c28aaSamw  * hexbuf which is srclen * 2.
142da6c28aaSamw  */
143da6c28aaSamw size_t
144da6c28aaSamw bintohex(const char *srcbuf, size_t srclen,
145da6c28aaSamw     char *hexbuf, size_t hexlen)
146da6c28aaSamw {
147da6c28aaSamw 	size_t outlen;
148da6c28aaSamw 	char c;
149da6c28aaSamw 
150da6c28aaSamw 	outlen = srclen << 1;
151da6c28aaSamw 
152da6c28aaSamw 	if (hexlen < outlen)
153da6c28aaSamw 		return (0);
154da6c28aaSamw 
155da6c28aaSamw 	while (srclen-- > 0) {
156da6c28aaSamw 		c = *srcbuf++;
157da6c28aaSamw 		*hexbuf++ = C2H(c & 0xF);
158da6c28aaSamw 		*hexbuf++ = C2H((c >> 4) & 0xF);
159da6c28aaSamw 	}
160da6c28aaSamw 
161da6c28aaSamw 	return (outlen);
162da6c28aaSamw }
163da6c28aaSamw 
164da6c28aaSamw /*
165da6c28aaSamw  * hextobin
166da6c28aaSamw  *
167da6c28aaSamw  * Converts hex to binary.
168da6c28aaSamw  *
169da6c28aaSamw  * Assuming hexbuf only contains hex digits (chars)
170da6c28aaSamw  * this function convert every two bytes of hexbuf
171da6c28aaSamw  * to one byte and put it in dstbuf.
172da6c28aaSamw  *
173da6c28aaSamw  * hexlen should be an even number.
174da6c28aaSamw  * dstlen should be at least half of hexlen.
175da6c28aaSamw  *
176da6c28aaSamw  * Returns 0 if sizes are not correct, otherwise
177da6c28aaSamw  * returns the number of converted bytes in dstbuf
178da6c28aaSamw  * which is half of hexlen.
179da6c28aaSamw  */
180da6c28aaSamw size_t
181da6c28aaSamw hextobin(const char *hexbuf, size_t hexlen,
182da6c28aaSamw     char *dstbuf, size_t dstlen)
183da6c28aaSamw {
184da6c28aaSamw 	size_t outlen;
185da6c28aaSamw 
186da6c28aaSamw 	if ((hexlen % 2) != 0)
187da6c28aaSamw 		return (0);
188da6c28aaSamw 
189da6c28aaSamw 	outlen = hexlen >> 1;
190da6c28aaSamw 	if (dstlen < outlen)
191da6c28aaSamw 		return (0);
192da6c28aaSamw 
193da6c28aaSamw 	while (hexlen > 0) {
194da6c28aaSamw 		*dstbuf = H2C(*hexbuf) & 0x0F;
195da6c28aaSamw 		hexbuf++;
196da6c28aaSamw 		*dstbuf++ |= (H2C(*hexbuf) << 4) & 0xF0;
197da6c28aaSamw 		hexbuf++;
198da6c28aaSamw 
199da6c28aaSamw 		hexlen -= 2;
200da6c28aaSamw 	}
201da6c28aaSamw 
202da6c28aaSamw 	return (outlen);
203da6c28aaSamw }
204da6c28aaSamw 
205da6c28aaSamw /*
2068d7e4166Sjose borrego  * Trim leading and trailing characters in the set defined by class
2078d7e4166Sjose borrego  * from a buffer containing a null-terminated string.
2088d7e4166Sjose borrego  * For example, if the input buffer contained "ABtext23" and class
2098d7e4166Sjose borrego  * contains "ABC123", the buffer will contain "text" on return.
2108d7e4166Sjose borrego  *
2118d7e4166Sjose borrego  * This function modifies the contents of buf in place and returns
2128d7e4166Sjose borrego  * a pointer to buf.
2138d7e4166Sjose borrego  */
2148d7e4166Sjose borrego char *
2158d7e4166Sjose borrego strtrim(char *buf, const char *class)
2168d7e4166Sjose borrego {
2178d7e4166Sjose borrego 	char *p = buf;
2188d7e4166Sjose borrego 	char *q = buf;
2198d7e4166Sjose borrego 
2208d7e4166Sjose borrego 	if (buf == NULL)
2218d7e4166Sjose borrego 		return (NULL);
2228d7e4166Sjose borrego 
2238d7e4166Sjose borrego 	p += strspn(p, class);
2248d7e4166Sjose borrego 
2258d7e4166Sjose borrego 	if (p != buf) {
2268d7e4166Sjose borrego 		while ((*q = *p++) != '\0')
2278d7e4166Sjose borrego 			++q;
2288d7e4166Sjose borrego 	}
2298d7e4166Sjose borrego 
2308d7e4166Sjose borrego 	while (q != buf) {
2318d7e4166Sjose borrego 		--q;
2328d7e4166Sjose borrego 		if (strspn(q, class) == 0)
2338d7e4166Sjose borrego 			return (buf);
2348d7e4166Sjose borrego 		*q = '\0';
2358d7e4166Sjose borrego 	}
2368d7e4166Sjose borrego 
2378d7e4166Sjose borrego 	return (buf);
2388d7e4166Sjose borrego }
2398d7e4166Sjose borrego 
2408d7e4166Sjose borrego /*
2418d7e4166Sjose borrego  * Strip the characters in the set defined by class from a buffer
2428d7e4166Sjose borrego  * containing a null-terminated string.
2438d7e4166Sjose borrego  * For example, if the input buffer contained "XYA 1textZ string3"
2448d7e4166Sjose borrego  * and class contains "123XYZ", the buffer will contain "A text string"
2458d7e4166Sjose borrego  * on return.
2468d7e4166Sjose borrego  *
2478d7e4166Sjose borrego  * This function modifies the contents of buf in place and returns
2488d7e4166Sjose borrego  * a pointer to buf.
2498d7e4166Sjose borrego  */
2508d7e4166Sjose borrego char *
2518d7e4166Sjose borrego strstrip(char *buf, const char *class)
2528d7e4166Sjose borrego {
2538d7e4166Sjose borrego 	char *p = buf;
2548d7e4166Sjose borrego 	char *q = buf;
2558d7e4166Sjose borrego 
2568d7e4166Sjose borrego 	if (buf == NULL)
2578d7e4166Sjose borrego 		return (NULL);
2588d7e4166Sjose borrego 
2598d7e4166Sjose borrego 	while (*p) {
2608d7e4166Sjose borrego 		p += strspn(p, class);
2618d7e4166Sjose borrego 		*q++ = *p++;
2628d7e4166Sjose borrego 	}
2638d7e4166Sjose borrego 
2648d7e4166Sjose borrego 	*q = '\0';
2658d7e4166Sjose borrego 	return (buf);
2668d7e4166Sjose borrego }
2678d7e4166Sjose borrego 
2688d7e4166Sjose borrego /*
269da6c28aaSamw  * trim_whitespace
270da6c28aaSamw  *
271da6c28aaSamw  * Trim leading and trailing whitespace chars (as defined by isspace)
272da6c28aaSamw  * from a buffer. Example; if the input buffer contained "  text  ",
273da6c28aaSamw  * it will contain "text", when we return. We assume that the buffer
274da6c28aaSamw  * contains a null terminated string. A pointer to the buffer is
275da6c28aaSamw  * returned.
276da6c28aaSamw  */
277da6c28aaSamw char *
278da6c28aaSamw trim_whitespace(char *buf)
279da6c28aaSamw {
280da6c28aaSamw 	char *p = buf;
281da6c28aaSamw 	char *q = buf;
282da6c28aaSamw 
283dc20a302Sas200622 	if (buf == NULL)
284dc20a302Sas200622 		return (NULL);
285da6c28aaSamw 
286da6c28aaSamw 	while (*p && isspace(*p))
287da6c28aaSamw 		++p;
288da6c28aaSamw 
289da6c28aaSamw 	while ((*q = *p++) != 0)
290da6c28aaSamw 		++q;
291da6c28aaSamw 
292da6c28aaSamw 	if (q != buf) {
293da6c28aaSamw 		while ((--q, isspace(*q)) != 0)
294da6c28aaSamw 			*q = '\0';
295da6c28aaSamw 	}
296da6c28aaSamw 
297da6c28aaSamw 	return (buf);
298da6c28aaSamw }
299da6c28aaSamw 
300da6c28aaSamw /*
301da6c28aaSamw  * This is the hash mechanism used to encrypt passwords for commands like
302da6c28aaSamw  * SamrSetUserInformation. It uses a 256 byte s-box.
303da6c28aaSamw  */
304da6c28aaSamw void
305da6c28aaSamw rand_hash(
306da6c28aaSamw     unsigned char *data,
307da6c28aaSamw     size_t datalen,
308da6c28aaSamw     unsigned char *key,
309da6c28aaSamw     size_t keylen)
310da6c28aaSamw {
311da6c28aaSamw 	unsigned char sbox[DEFAULT_SBOX_SIZE];
312da6c28aaSamw 	unsigned char tmp;
313da6c28aaSamw 	unsigned char index_i = 0;
314da6c28aaSamw 	unsigned char index_j = 0;
315da6c28aaSamw 	unsigned char j = 0;
316da6c28aaSamw 	int i;
317da6c28aaSamw 
318da6c28aaSamw 	for (i = 0; i < DEFAULT_SBOX_SIZE; ++i)
319da6c28aaSamw 		sbox[i] = (unsigned char)i;
320da6c28aaSamw 
321da6c28aaSamw 	for (i = 0; i < DEFAULT_SBOX_SIZE; ++i) {
322da6c28aaSamw 		j += (sbox[i] + key[i % keylen]);
323da6c28aaSamw 
324da6c28aaSamw 		tmp = sbox[i];
325da6c28aaSamw 		sbox[i] = sbox[j];
326da6c28aaSamw 		sbox[j] = tmp;
327da6c28aaSamw 	}
328da6c28aaSamw 
329da6c28aaSamw 	for (i = 0; i < datalen; ++i) {
330da6c28aaSamw 		index_i++;
331da6c28aaSamw 		index_j += sbox[index_i];
332da6c28aaSamw 
333da6c28aaSamw 		tmp = sbox[index_i];
334da6c28aaSamw 		sbox[index_i] = sbox[index_j];
335da6c28aaSamw 		sbox[index_j] = tmp;
336da6c28aaSamw 
337da6c28aaSamw 		tmp = sbox[index_i] + sbox[index_j];
338da6c28aaSamw 		data[i] = data[i] ^ sbox[tmp];
339da6c28aaSamw 	}
340da6c28aaSamw }
341b89a8333Snatalie li - Sun Microsystems - Irvine United States 
342b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
343b89a8333Snatalie li - Sun Microsystems - Irvine United States  * smb_chk_hostaccess
344b89a8333Snatalie li - Sun Microsystems - Irvine United States  *
345148c5f43SAlan Wright  * Determines whether the specified host is in the given access list.
346148c5f43SAlan Wright  *
347b89a8333Snatalie li - Sun Microsystems - Irvine United States  * We match on aliases of the hostname as well as on the canonical name.
348b89a8333Snatalie li - Sun Microsystems - Irvine United States  * Names in the access list may be either hosts or netgroups;  they're
349b89a8333Snatalie li - Sun Microsystems - Irvine United States  * not distinguished syntactically.  We check for hosts first because
350b89a8333Snatalie li - Sun Microsystems - Irvine United States  * it's cheaper (just M*N strcmp()s), then try netgroups.
351b89a8333Snatalie li - Sun Microsystems - Irvine United States  *
352b89a8333Snatalie li - Sun Microsystems - Irvine United States  * Function returns:
353148c5f43SAlan Wright  *	-1 for "all" (list is empty "" or "*")
354148c5f43SAlan Wright  *	0 not found  (host is not in the list or list is NULL)
355b89a8333Snatalie li - Sun Microsystems - Irvine United States  *	1 found
3567f667e74Sjose borrego  *
357b89a8333Snatalie li - Sun Microsystems - Irvine United States  */
358b89a8333Snatalie li - Sun Microsystems - Irvine United States int
3597f667e74Sjose borrego smb_chk_hostaccess(smb_inaddr_t *ipaddr, char *access_list)
360b89a8333Snatalie li - Sun Microsystems - Irvine United States {
3619b241b4eSYuri Pankov 	char addr[INET_ADDRSTRLEN];
3629b241b4eSYuri Pankov 	char buff[256];
3639b241b4eSYuri Pankov 	char *cstr = access_list, *gr = access_list;
364b89a8333Snatalie li - Sun Microsystems - Irvine United States 	char *host;
3652807a6ecSYuri Pankov 	int clres;
3669b241b4eSYuri Pankov 	int i;
3679b241b4eSYuri Pankov 	int nentries = 0;
3689b241b4eSYuri Pankov 	int off;
3699b241b4eSYuri Pankov 	int response;
3709b241b4eSYuri Pankov 	int sbr = 0;
371b89a8333Snatalie li - Sun Microsystems - Irvine United States 	struct nd_hostservlist *clnames;
372b89a8333Snatalie li - Sun Microsystems - Irvine United States 	struct in_addr inaddr;
373b89a8333Snatalie li - Sun Microsystems - Irvine United States 	struct sockaddr_in sa;
3749b241b4eSYuri Pankov 	struct sockaddr_in6 sa6;
375b89a8333Snatalie li - Sun Microsystems - Irvine United States 	struct netbuf buf;
376b89a8333Snatalie li - Sun Microsystems - Irvine United States 	struct netconfig *config;
3779b241b4eSYuri Pankov 	struct netent n, *np;
378b89a8333Snatalie li - Sun Microsystems - Irvine United States 
379148c5f43SAlan Wright 	if (access_list == NULL)
380148c5f43SAlan Wright 		return (0);
3817f667e74Sjose borrego 
3829b241b4eSYuri Pankov 	/* If access list is empty or "*" - then it's "all" */
383148c5f43SAlan Wright 	if (*access_list == '\0' || strcmp(access_list, "*") == 0)
384b89a8333Snatalie li - Sun Microsystems - Irvine United States 		return (-1);
385b89a8333Snatalie li - Sun Microsystems - Irvine United States 
3869b241b4eSYuri Pankov 	switch (ipaddr->a_family) {
3879b241b4eSYuri Pankov 	case AF_INET:
3889b241b4eSYuri Pankov 		inaddr.s_addr = ipaddr->a_ipv4;
389b89a8333Snatalie li - Sun Microsystems - Irvine United States 		sa.sin_family = AF_INET;
390b89a8333Snatalie li - Sun Microsystems - Irvine United States 		sa.sin_port = 0;
391b89a8333Snatalie li - Sun Microsystems - Irvine United States 		sa.sin_addr = inaddr;
392b89a8333Snatalie li - Sun Microsystems - Irvine United States 		buf.len = buf.maxlen = sizeof (sa);
393b89a8333Snatalie li - Sun Microsystems - Irvine United States 		buf.buf = (char *)&sa;
394b89a8333Snatalie li - Sun Microsystems - Irvine United States 		config = getnetconfigent("tcp");
3959b241b4eSYuri Pankov 		break;
3969b241b4eSYuri Pankov 	case AF_INET6:
3979b241b4eSYuri Pankov 		sa6.sin6_family = AF_INET6;
3989b241b4eSYuri Pankov 		sa6.sin6_port = 0;
3999b241b4eSYuri Pankov 		sa6.sin6_addr = ipaddr->a_ipv6;
4009b241b4eSYuri Pankov 		buf.len = buf.maxlen = sizeof (sa6);
4019b241b4eSYuri Pankov 		buf.buf = (char *)&sa6;
4029b241b4eSYuri Pankov 		config = getnetconfigent("tcp6");
4039b241b4eSYuri Pankov 		break;
4049b241b4eSYuri Pankov 	default:
4059b241b4eSYuri Pankov 		return (1);
4069b241b4eSYuri Pankov 	}
4079b241b4eSYuri Pankov 
408b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (config == NULL)
409b89a8333Snatalie li - Sun Microsystems - Irvine United States 		return (1);
410b89a8333Snatalie li - Sun Microsystems - Irvine United States 
4119b241b4eSYuri Pankov 	/* Try to lookup client hostname */
4122807a6ecSYuri Pankov 	clres = __netdir_getbyaddr_nosrv(config, &clnames, &buf);
413b89a8333Snatalie li - Sun Microsystems - Irvine United States 	freenetconfigent(config);
414b89a8333Snatalie li - Sun Microsystems - Irvine United States 
4159b241b4eSYuri Pankov 	for (;;) {
4169b241b4eSYuri Pankov 		if ((cstr = strpbrk(cstr, "[]:")) != NULL) {
4179b241b4eSYuri Pankov 			switch (*cstr) {
4189b241b4eSYuri Pankov 			case '[':
4199b241b4eSYuri Pankov 			case ']':
4209b241b4eSYuri Pankov 				sbr = !sbr;
4219b241b4eSYuri Pankov 				cstr++;
4229b241b4eSYuri Pankov 				continue;
4239b241b4eSYuri Pankov 			case ':':
4249b241b4eSYuri Pankov 				if (sbr) {
4259b241b4eSYuri Pankov 					cstr++;
4269b241b4eSYuri Pankov 					continue;
4279b241b4eSYuri Pankov 				}
4289b241b4eSYuri Pankov 				*cstr = '\0';
4299b241b4eSYuri Pankov 			}
4309b241b4eSYuri Pankov 		}
431b89a8333Snatalie li - Sun Microsystems - Irvine United States 
432b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/*
4339b241b4eSYuri Pankov 		 * If the list name has a '-' prepended then a match of
4349b241b4eSYuri Pankov 		 * the following name implies failure instead of success.
435b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 */
436b89a8333Snatalie li - Sun Microsystems - Irvine United States 		if (*gr == '-') {
437b89a8333Snatalie li - Sun Microsystems - Irvine United States 			response = 0;
438b89a8333Snatalie li - Sun Microsystems - Irvine United States 			gr++;
439b89a8333Snatalie li - Sun Microsystems - Irvine United States 		} else {
440b89a8333Snatalie li - Sun Microsystems - Irvine United States 			response = 1;
441b89a8333Snatalie li - Sun Microsystems - Irvine United States 		}
442b89a8333Snatalie li - Sun Microsystems - Irvine United States 
443b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/*
4449b241b4eSYuri Pankov 		 * First check if we have '@' entry, as it doesn't
4459b241b4eSYuri Pankov 		 * require client hostname.
4462807a6ecSYuri Pankov 		 */
4479b241b4eSYuri Pankov 		if (*gr == '@') {
4489b241b4eSYuri Pankov 			gr++;
4499b241b4eSYuri Pankov 
4509b241b4eSYuri Pankov 			if (!isdigit(*gr) && *gr != '[') {
4519b241b4eSYuri Pankov 				/* Netname support */
4529b241b4eSYuri Pankov 				if ((np = getnetbyname_r(gr, &n, buff,
4539b241b4eSYuri Pankov 				    sizeof (buff))) != NULL &&
4549b241b4eSYuri Pankov 				    np->n_net != 0) {
4559b241b4eSYuri Pankov 					while ((np->n_net & 0xFF000000u) == 0)
4569b241b4eSYuri Pankov 						np->n_net <<= 8;
4579b241b4eSYuri Pankov 					np->n_net = htonl(np->n_net);
4589b241b4eSYuri Pankov 					if (inet_ntop(AF_INET, &np->n_net, addr,
4599b241b4eSYuri Pankov 					    INET_ADDRSTRLEN) == NULL)
4609b241b4eSYuri Pankov 						break;
4619b241b4eSYuri Pankov 					if (inet_matchaddr(buf.buf, addr))
4622807a6ecSYuri Pankov 						return (response);
4639b241b4eSYuri Pankov 				}
4649b241b4eSYuri Pankov 			} else {
4659b241b4eSYuri Pankov 				if (inet_matchaddr(buf.buf, gr))
4669b241b4eSYuri Pankov 					return (response);
4679b241b4eSYuri Pankov 			}
4689b241b4eSYuri Pankov 
4699b241b4eSYuri Pankov 			if (cstr == NULL)
4709b241b4eSYuri Pankov 				break;
4719b241b4eSYuri Pankov 
4729b241b4eSYuri Pankov 			gr = ++cstr;
4739b241b4eSYuri Pankov 
4749b241b4eSYuri Pankov 			continue;
4759b241b4eSYuri Pankov 		}
4769b241b4eSYuri Pankov 
4772807a6ecSYuri Pankov 		/*
4782807a6ecSYuri Pankov 		 * No other checks can be performed if client address
4792807a6ecSYuri Pankov 		 * can't be resolved.
4802807a6ecSYuri Pankov 		 */
4819b241b4eSYuri Pankov 		if (clres) {
4829b241b4eSYuri Pankov 			if (cstr == NULL)
4839b241b4eSYuri Pankov 				break;
4849b241b4eSYuri Pankov 
4859b241b4eSYuri Pankov 			gr = ++cstr;
4869b241b4eSYuri Pankov 
4872807a6ecSYuri Pankov 			continue;
4889b241b4eSYuri Pankov 		}
4899b241b4eSYuri Pankov 
4909b241b4eSYuri Pankov 		/* Otherwise loop through all client hostname aliases */
491b89a8333Snatalie li - Sun Microsystems - Irvine United States 		for (i = 0; i < clnames->h_cnt; i++) {
492b89a8333Snatalie li - Sun Microsystems - Irvine United States 			host = clnames->h_hostservs[i].h_host;
493b89a8333Snatalie li - Sun Microsystems - Irvine United States 			/*
494b89a8333Snatalie li - Sun Microsystems - Irvine United States 			 * If the list name begins with a dot then
495b89a8333Snatalie li - Sun Microsystems - Irvine United States 			 * do a domain name suffix comparison.
496b89a8333Snatalie li - Sun Microsystems - Irvine United States 			 * A single dot matches any name with no
497b89a8333Snatalie li - Sun Microsystems - Irvine United States 			 * suffix.
498b89a8333Snatalie li - Sun Microsystems - Irvine United States 			 */
499b89a8333Snatalie li - Sun Microsystems - Irvine United States 			if (*gr == '.') {
5009b241b4eSYuri Pankov 				if (*(gr + 1) == '\0') {
501b89a8333Snatalie li - Sun Microsystems - Irvine United States 					if (strchr(host, '.') == NULL)
502b89a8333Snatalie li - Sun Microsystems - Irvine United States 						return (response);
503b89a8333Snatalie li - Sun Microsystems - Irvine United States 				} else {
504b89a8333Snatalie li - Sun Microsystems - Irvine United States 					off = strlen(host) - strlen(gr);
505b89a8333Snatalie li - Sun Microsystems - Irvine United States 					if (off > 0 &&
506b89a8333Snatalie li - Sun Microsystems - Irvine United States 					    strcasecmp(host + off, gr) == 0) {
507b89a8333Snatalie li - Sun Microsystems - Irvine United States 						return (response);
508b89a8333Snatalie li - Sun Microsystems - Irvine United States 					}
509b89a8333Snatalie li - Sun Microsystems - Irvine United States 				}
510b89a8333Snatalie li - Sun Microsystems - Irvine United States 			} else {
5119b241b4eSYuri Pankov 				/* Just do a hostname match */
512b89a8333Snatalie li - Sun Microsystems - Irvine United States 				if (strcasecmp(gr, host) == 0)
513b89a8333Snatalie li - Sun Microsystems - Irvine United States 					return (response);
514b89a8333Snatalie li - Sun Microsystems - Irvine United States 				}
515b89a8333Snatalie li - Sun Microsystems - Irvine United States 			}
516b89a8333Snatalie li - Sun Microsystems - Irvine United States 
517b89a8333Snatalie li - Sun Microsystems - Irvine United States 		nentries++;
5189b241b4eSYuri Pankov 
5199b241b4eSYuri Pankov 		if (cstr == NULL)
5209b241b4eSYuri Pankov 			break;
5219b241b4eSYuri Pankov 
5229b241b4eSYuri Pankov 		gr = ++cstr;
523b89a8333Snatalie li - Sun Microsystems - Irvine United States 	}
524b89a8333Snatalie li - Sun Microsystems - Irvine United States 
5252807a6ecSYuri Pankov 	if (clres)
5262807a6ecSYuri Pankov 		return (0);
527b89a8333Snatalie li - Sun Microsystems - Irvine United States 
5282807a6ecSYuri Pankov 	return (smb_netgroup_match(clnames, access_list, nentries));
529b89a8333Snatalie li - Sun Microsystems - Irvine United States }
530b89a8333Snatalie li - Sun Microsystems - Irvine United States 
531b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
532b89a8333Snatalie li - Sun Microsystems - Irvine United States  * smb_netgroup_match
533b89a8333Snatalie li - Sun Microsystems - Irvine United States  *
534b89a8333Snatalie li - Sun Microsystems - Irvine United States  * Check whether any of the hostnames in clnames are
535b89a8333Snatalie li - Sun Microsystems - Irvine United States  * members (or non-members) of the netgroups in glist.
536b89a8333Snatalie li - Sun Microsystems - Irvine United States  * Since the innetgr lookup is rather expensive, the
537b89a8333Snatalie li - Sun Microsystems - Irvine United States  * result is cached. The cached entry is valid only
538b89a8333Snatalie li - Sun Microsystems - Irvine United States  * for VALID_TIME seconds.  This works well because
539b89a8333Snatalie li - Sun Microsystems - Irvine United States  * typically these lookups occur in clusters when
540b89a8333Snatalie li - Sun Microsystems - Irvine United States  * a client is mounting.
541b89a8333Snatalie li - Sun Microsystems - Irvine United States  *
542b89a8333Snatalie li - Sun Microsystems - Irvine United States  * Note that this routine establishes a host membership
543b89a8333Snatalie li - Sun Microsystems - Irvine United States  * in a list of netgroups - we've no idea just which
544b89a8333Snatalie li - Sun Microsystems - Irvine United States  * netgroup in the list it is a member of.
545b89a8333Snatalie li - Sun Microsystems - Irvine United States  *
546b89a8333Snatalie li - Sun Microsystems - Irvine United States  * glist is a character array containing grc strings
547b89a8333Snatalie li - Sun Microsystems - Irvine United States  * representing netgroup names (optionally prefixed
548b89a8333Snatalie li - Sun Microsystems - Irvine United States  * with '-'). Each string is ended with '\0'  and
549b89a8333Snatalie li - Sun Microsystems - Irvine United States  * followed immediately by the next string.
550b89a8333Snatalie li - Sun Microsystems - Irvine United States  */
551b89a8333Snatalie li - Sun Microsystems - Irvine United States static boolean_t
552b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_netgroup_match(struct nd_hostservlist *clnames, char  *glist, int grc)
553b89a8333Snatalie li - Sun Microsystems - Irvine United States {
554b89a8333Snatalie li - Sun Microsystems - Irvine United States 	char **grl;
555b89a8333Snatalie li - Sun Microsystems - Irvine United States 	char *gr;
556b89a8333Snatalie li - Sun Microsystems - Irvine United States 	int nhosts = clnames->h_cnt;
557b89a8333Snatalie li - Sun Microsystems - Irvine United States 	char *host;
558b89a8333Snatalie li - Sun Microsystems - Irvine United States 	int i, j, n;
559b89a8333Snatalie li - Sun Microsystems - Irvine United States 	boolean_t response;
560b89a8333Snatalie li - Sun Microsystems - Irvine United States 	boolean_t belong = B_FALSE;
561b89a8333Snatalie li - Sun Microsystems - Irvine United States 	static char *domain = NULL;
562b89a8333Snatalie li - Sun Microsystems - Irvine United States 
563b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (domain == NULL) {
564b89a8333Snatalie li - Sun Microsystems - Irvine United States 		int	ssize;
565b89a8333Snatalie li - Sun Microsystems - Irvine United States 
566b89a8333Snatalie li - Sun Microsystems - Irvine United States 		domain = malloc(SYS_NMLN);
567b89a8333Snatalie li - Sun Microsystems - Irvine United States 		if (domain == NULL)
568b89a8333Snatalie li - Sun Microsystems - Irvine United States 			return (B_FALSE);
569b89a8333Snatalie li - Sun Microsystems - Irvine United States 
570b89a8333Snatalie li - Sun Microsystems - Irvine United States 		ssize = sysinfo(SI_SRPC_DOMAIN, domain, SYS_NMLN);
571b89a8333Snatalie li - Sun Microsystems - Irvine United States 		if (ssize > SYS_NMLN) {
572b89a8333Snatalie li - Sun Microsystems - Irvine United States 			free(domain);
573b89a8333Snatalie li - Sun Microsystems - Irvine United States 			domain = malloc(ssize);
574b89a8333Snatalie li - Sun Microsystems - Irvine United States 			if (domain == NULL)
575b89a8333Snatalie li - Sun Microsystems - Irvine United States 				return (B_FALSE);
576b89a8333Snatalie li - Sun Microsystems - Irvine United States 			ssize = sysinfo(SI_SRPC_DOMAIN, domain, ssize);
577b89a8333Snatalie li - Sun Microsystems - Irvine United States 		}
578b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/* Check for error in syscall or NULL domain name */
579b89a8333Snatalie li - Sun Microsystems - Irvine United States 		if (ssize <= 1)
580b89a8333Snatalie li - Sun Microsystems - Irvine United States 			return (B_FALSE);
581b89a8333Snatalie li - Sun Microsystems - Irvine United States 	}
582b89a8333Snatalie li - Sun Microsystems - Irvine United States 
583b89a8333Snatalie li - Sun Microsystems - Irvine United States 	grl = calloc(grc, sizeof (char *));
584b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (grl == NULL)
585b89a8333Snatalie li - Sun Microsystems - Irvine United States 		return (B_FALSE);
586b89a8333Snatalie li - Sun Microsystems - Irvine United States 
587b89a8333Snatalie li - Sun Microsystems - Irvine United States 	for (i = 0, gr = glist; i < grc && !belong; ) {
588b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/*
589b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * If the netgroup name has a '-' prepended
590b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * then a match of this name implies a failure
591b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * instead of success.
592b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 */
593b89a8333Snatalie li - Sun Microsystems - Irvine United States 		response = (*gr != '-') ? B_TRUE : B_FALSE;
594b89a8333Snatalie li - Sun Microsystems - Irvine United States 
595b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/*
596b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * Subsequent names with or without a '-' (but no mix)
597b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * can be grouped together for a single check.
598b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 */
599b89a8333Snatalie li - Sun Microsystems - Irvine United States 		for (n = 0; i < grc; i++, n++, gr += strlen(gr) + 1) {
600b89a8333Snatalie li - Sun Microsystems - Irvine United States 			if ((response && *gr == '-') ||
601b89a8333Snatalie li - Sun Microsystems - Irvine United States 			    (!response && *gr != '-'))
602b89a8333Snatalie li - Sun Microsystems - Irvine United States 				break;
603b89a8333Snatalie li - Sun Microsystems - Irvine United States 
604b89a8333Snatalie li - Sun Microsystems - Irvine United States 			grl[n] = response ? gr : gr + 1;
605b89a8333Snatalie li - Sun Microsystems - Irvine United States 		}
606b89a8333Snatalie li - Sun Microsystems - Irvine United States 
607b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/*
608b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * Check the netgroup for each
609b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * of the hosts names (usually just one).
610b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 */
611b89a8333Snatalie li - Sun Microsystems - Irvine United States 		for (j = 0; j < nhosts && !belong; j++) {
612b89a8333Snatalie li - Sun Microsystems - Irvine United States 			host = clnames->h_hostservs[j].h_host;
613b89a8333Snatalie li - Sun Microsystems - Irvine United States 			if (__multi_innetgr(n, grl, 1, &host, 0, NULL,
614b89a8333Snatalie li - Sun Microsystems - Irvine United States 			    1, &domain))
615b89a8333Snatalie li - Sun Microsystems - Irvine United States 				belong = B_TRUE;
616b89a8333Snatalie li - Sun Microsystems - Irvine United States 		}
617b89a8333Snatalie li - Sun Microsystems - Irvine United States 	}
618b89a8333Snatalie li - Sun Microsystems - Irvine United States 
619b89a8333Snatalie li - Sun Microsystems - Irvine United States 	free(grl);
620b89a8333Snatalie li - Sun Microsystems - Irvine United States 	return (belong ? response : B_FALSE);
621b89a8333Snatalie li - Sun Microsystems - Irvine United States }
6226d57f833SAlan Wright 
6236d57f833SAlan Wright /*
6246d57f833SAlan Wright  * Resolve the ZFS dataset from a path.
62529bd2886SAlan Wright  * Returns,
62629bd2886SAlan Wright  *	0  = On success.
62729bd2886SAlan Wright  *	-1 = Failure to open /etc/mnttab file or to get ZFS dataset.
6286d57f833SAlan Wright  */
6296d57f833SAlan Wright int
6306d57f833SAlan Wright smb_getdataset(const char *path, char *dataset, size_t len)
6316d57f833SAlan Wright {
6326d57f833SAlan Wright 	char tmppath[MAXPATHLEN];
6336d57f833SAlan Wright 	char *cp;
6346d57f833SAlan Wright 	FILE *fp;
6356d57f833SAlan Wright 	struct mnttab mnttab;
6366d57f833SAlan Wright 	struct mnttab mntpref;
6376d57f833SAlan Wright 	int rc = -1;
6386d57f833SAlan Wright 
6396d57f833SAlan Wright 	if ((fp = fopen(MNTTAB, "r")) == NULL)
6406d57f833SAlan Wright 		return (-1);
6416d57f833SAlan Wright 
6426d57f833SAlan Wright 	(void) memset(&mnttab, '\0', sizeof (mnttab));
6436d57f833SAlan Wright 	(void) strlcpy(tmppath, path, MAXPATHLEN);
6446d57f833SAlan Wright 	cp = tmppath;
6456d57f833SAlan Wright 
6466d57f833SAlan Wright 	while (*cp != '\0') {
6476d57f833SAlan Wright 		resetmnttab(fp);
6486d57f833SAlan Wright 		(void) memset(&mntpref, '\0', sizeof (mntpref));
6496d57f833SAlan Wright 		mntpref.mnt_mountp = tmppath;
6506d57f833SAlan Wright 
6516d57f833SAlan Wright 		if (getmntany(fp, &mnttab, &mntpref) == 0) {
65229bd2886SAlan Wright 			if (mnttab.mnt_fstype == NULL)
65329bd2886SAlan Wright 				break;
65429bd2886SAlan Wright 
65529bd2886SAlan Wright 			if (strcmp(mnttab.mnt_fstype, "zfs") != 0)
65629bd2886SAlan Wright 				break;
6576d57f833SAlan Wright 			/*
6586d57f833SAlan Wright 			 * Ensure that there are no leading slashes
6596d57f833SAlan Wright 			 * (required for zfs_open).
6606d57f833SAlan Wright 			 */
6616d57f833SAlan Wright 			cp = mnttab.mnt_special;
6626d57f833SAlan Wright 			cp += strspn(cp, "/");
6636d57f833SAlan Wright 			(void) strlcpy(dataset, cp, len);
6646d57f833SAlan Wright 			rc = 0;
6656d57f833SAlan Wright 			break;
6666d57f833SAlan Wright 		}
6676d57f833SAlan Wright 
668fc724630SAlan Wright 		if (strcmp(tmppath, "/") == 0)
669fc724630SAlan Wright 			break;
670fc724630SAlan Wright 
671fc724630SAlan Wright 		if ((cp = strrchr(tmppath, '/')) == NULL)
672fc724630SAlan Wright 			break;
673fc724630SAlan Wright 
674fc724630SAlan Wright 		/*
675fc724630SAlan Wright 		 * The path has multiple components.
676fc724630SAlan Wright 		 * Remove the last component and try again.
677fc724630SAlan Wright 		 */
6786d57f833SAlan Wright 		*cp = '\0';
6796d57f833SAlan Wright 		if (tmppath[0] == '\0')
6806d57f833SAlan Wright 			(void) strcpy(tmppath, "/");
6816d57f833SAlan Wright 
6826d57f833SAlan Wright 		cp = tmppath;
6836d57f833SAlan Wright 	}
6846d57f833SAlan Wright 
6856d57f833SAlan Wright 	(void) fclose(fp);
6866d57f833SAlan Wright 	return (rc);
6876d57f833SAlan Wright }
68829bd2886SAlan Wright 
68929bd2886SAlan Wright /*
6901fcced4cSJordan Brown  * smb_dlopen
6911fcced4cSJordan Brown  *
6921fcced4cSJordan Brown  * Check to see if an interposer library exists.  If it exists
6931fcced4cSJordan Brown  * and reports a valid version number and key (UUID), return
6941fcced4cSJordan Brown  * a handle to the library.  Otherwise, return NULL.
6951fcced4cSJordan Brown  */
6961fcced4cSJordan Brown void *
6971fcced4cSJordan Brown smb_dlopen(void)
6981fcced4cSJordan Brown {
6991fcced4cSJordan Brown 	uuid_t uuid;
7001fcced4cSJordan Brown 	void *interposer_hdl;
7011fcced4cSJordan Brown 	typedef int (*smbex_versionfn_t)(smbex_version_t *);
7021fcced4cSJordan Brown 	smbex_versionfn_t getversion;
7031fcced4cSJordan Brown 	smbex_version_t *version;
7041fcced4cSJordan Brown 
7051fcced4cSJordan Brown 	bzero(&uuid, sizeof (uuid_t));
7061fcced4cSJordan Brown 	if (uuid_parse(SMBEX_KEY, uuid) < 0)
7071fcced4cSJordan Brown 		return (NULL);
7081fcced4cSJordan Brown 
7091fcced4cSJordan Brown 	interposer_hdl = dlopen(SMB_LIB_ALT, RTLD_NOW | RTLD_LOCAL);
7101fcced4cSJordan Brown 	if (interposer_hdl == NULL)
7111fcced4cSJordan Brown 		return (NULL);
7121fcced4cSJordan Brown 
7131fcced4cSJordan Brown 	bzero(&getversion, sizeof (smbex_versionfn_t));
7141fcced4cSJordan Brown 	getversion = (smbex_versionfn_t)dlsym(interposer_hdl,
7151fcced4cSJordan Brown 	    "smbex_get_version");
7161fcced4cSJordan Brown 	if ((getversion == NULL) ||
7171fcced4cSJordan Brown 	    (version = malloc(sizeof (smbex_version_t))) == NULL) {
7181fcced4cSJordan Brown 		(void) dlclose(interposer_hdl);
7191fcced4cSJordan Brown 		return (NULL);
7201fcced4cSJordan Brown 	}
7211fcced4cSJordan Brown 	bzero(version, sizeof (smbex_version_t));
7221fcced4cSJordan Brown 
7231fcced4cSJordan Brown 	if ((getversion(version) != 0) ||
7241fcced4cSJordan Brown 	    (version->v_version != SMBEX_VERSION) ||
7251fcced4cSJordan Brown 	    (uuid_compare(version->v_uuid, uuid) != 0)) {
7261fcced4cSJordan Brown 		free(version);
7271fcced4cSJordan Brown 		(void) dlclose(interposer_hdl);
7281fcced4cSJordan Brown 		return (NULL);
7291fcced4cSJordan Brown 	}
7301fcced4cSJordan Brown 
7311fcced4cSJordan Brown 	free(version);
7321fcced4cSJordan Brown 	return (interposer_hdl);
7331fcced4cSJordan Brown }
7341fcced4cSJordan Brown 
7351fcced4cSJordan Brown /*
7361fcced4cSJordan Brown  * smb_dlclose
7371fcced4cSJordan Brown  *
7381fcced4cSJordan Brown  * Closes handle to the interposed library.
7391fcced4cSJordan Brown  */
7401fcced4cSJordan Brown void
7411fcced4cSJordan Brown smb_dlclose(void *handle)
7421fcced4cSJordan Brown {
7431fcced4cSJordan Brown 	if (handle)
7441fcced4cSJordan Brown 		(void) dlclose(handle);
7451fcced4cSJordan Brown }
7461fcced4cSJordan Brown 
7471fcced4cSJordan Brown /*
7489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * This function is a wrapper for getnameinfo() to look up a hostname given an
7499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * IP address. The hostname returned by this function is used for constructing
7509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * the service principal name field of KRB AP-REQs. Hence, it should be
7519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * converted to lowercase for RFC 4120 section 6.2.1 conformance.
75229bd2886SAlan Wright  */
75329bd2886SAlan Wright int
75429bd2886SAlan Wright smb_getnameinfo(smb_inaddr_t *ip, char *hostname, int hostlen, int flags)
75529bd2886SAlan Wright {
75629bd2886SAlan Wright 	socklen_t salen;
75729bd2886SAlan Wright 	struct sockaddr_in6 sin6;
75829bd2886SAlan Wright 	struct sockaddr_in sin;
75929bd2886SAlan Wright 	void *sp;
7609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int rc;
76129bd2886SAlan Wright 
76229bd2886SAlan Wright 	if (ip->a_family == AF_INET) {
76329bd2886SAlan Wright 		salen = sizeof (struct sockaddr_in);
76429bd2886SAlan Wright 		sin.sin_family = ip->a_family;
76529bd2886SAlan Wright 		sin.sin_port = 0;
76629bd2886SAlan Wright 		sin.sin_addr.s_addr = ip->a_ipv4;
76729bd2886SAlan Wright 		sp = &sin;
76829bd2886SAlan Wright 	} else {
76929bd2886SAlan Wright 		salen = sizeof (struct sockaddr_in6);
77029bd2886SAlan Wright 		sin6.sin6_family = ip->a_family;
77129bd2886SAlan Wright 		sin6.sin6_port = 0;
77229bd2886SAlan Wright 		(void) memcpy(&sin6.sin6_addr.s6_addr, &ip->a_ipv6,
77329bd2886SAlan Wright 		    sizeof (sin6.sin6_addr.s6_addr));
77429bd2886SAlan Wright 		sp = &sin6;
77529bd2886SAlan Wright 	}
7769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = (getnameinfo((struct sockaddr *)sp, salen,
7789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    hostname, hostlen, NULL, 0, flags))) == 0)
7799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) smb_strlwr(hostname);
7809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (rc);
78229bd2886SAlan Wright }
783fe1c642dSBill Krier 
784fe1c642dSBill Krier /*
785fe1c642dSBill Krier  * A share name is considered invalid if it contains control
786fe1c642dSBill Krier  * characters or any of the following characters (MSDN 236388).
787fe1c642dSBill Krier  *
788fe1c642dSBill Krier  *	" / \ [ ] : | < > + ; , ? * =
789fe1c642dSBill Krier  */
790fe1c642dSBill Krier uint32_t
791fe1c642dSBill Krier smb_name_validate_share(const char *sharename)
792fe1c642dSBill Krier {
793fe1c642dSBill Krier 	const char *invalid = "\"/\\[]:|<>+;,?*=";
794fe1c642dSBill Krier 	const char *p;
795fe1c642dSBill Krier 
796fe1c642dSBill Krier 	if (sharename == NULL)
797fe1c642dSBill Krier 		return (ERROR_INVALID_PARAMETER);
798fe1c642dSBill Krier 
799fe1c642dSBill Krier 	if (strpbrk(sharename, invalid) != NULL)
800fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
801fe1c642dSBill Krier 
802fe1c642dSBill Krier 	for (p = sharename; *p != '\0'; p++) {
803fe1c642dSBill Krier 		if (iscntrl(*p))
804fe1c642dSBill Krier 			return (ERROR_INVALID_NAME);
805fe1c642dSBill Krier 	}
806fe1c642dSBill Krier 
807fe1c642dSBill Krier 	return (ERROR_SUCCESS);
808fe1c642dSBill Krier }
809fe1c642dSBill Krier 
810fe1c642dSBill Krier /*
811fe1c642dSBill Krier  * User and group names are limited to 256 characters, cannot be terminated
812fe1c642dSBill Krier  * by '.' and must not contain control characters or any of the following
813fe1c642dSBill Krier  * characters.
814fe1c642dSBill Krier  *
815fe1c642dSBill Krier  *	" / \ [ ] < > + ; , ? * = @
816fe1c642dSBill Krier  */
817fe1c642dSBill Krier uint32_t
818fe1c642dSBill Krier smb_name_validate_account(const char *name)
819fe1c642dSBill Krier {
820fe1c642dSBill Krier 	const char	*invalid = "\"/\\[]<>+;,?*=@";
821fe1c642dSBill Krier 	const char	*p;
822fe1c642dSBill Krier 	int		len;
823fe1c642dSBill Krier 
824fe1c642dSBill Krier 	if ((name == NULL) || (*name == '\0'))
825fe1c642dSBill Krier 		return (ERROR_INVALID_PARAMETER);
826fe1c642dSBill Krier 
827fe1c642dSBill Krier 	len = strlen(name);
828fe1c642dSBill Krier 	if ((len > MAXNAMELEN) || (name[len - 1] == '.'))
829fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
830fe1c642dSBill Krier 
831fe1c642dSBill Krier 	if (strpbrk(name, invalid) != NULL)
832fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
833fe1c642dSBill Krier 
834fe1c642dSBill Krier 	for (p = name; *p != '\0'; p++) {
835fe1c642dSBill Krier 		if (iscntrl(*p))
836fe1c642dSBill Krier 			return (ERROR_INVALID_NAME);
837fe1c642dSBill Krier 	}
838fe1c642dSBill Krier 
839fe1c642dSBill Krier 	return (ERROR_SUCCESS);
840fe1c642dSBill Krier }
841fe1c642dSBill Krier 
842fe1c642dSBill Krier /*
843fe1c642dSBill Krier  * Check a domain name for RFC 1035 and 1123 compliance.  Domain names may
844fe1c642dSBill Krier  * contain alphanumeric characters, hyphens and dots.  The first and last
845fe1c642dSBill Krier  * character of a label must be alphanumeric.  Interior characters may be
846fe1c642dSBill Krier  * alphanumeric or hypens.
847fe1c642dSBill Krier  *
848fe1c642dSBill Krier  * Domain names should not contain underscores but we allow them because
849fe1c642dSBill Krier  * Windows names are often in non-compliance with this rule.
850fe1c642dSBill Krier  */
851fe1c642dSBill Krier uint32_t
852fe1c642dSBill Krier smb_name_validate_domain(const char *domain)
853fe1c642dSBill Krier {
854fe1c642dSBill Krier 	boolean_t new_label = B_TRUE;
855fe1c642dSBill Krier 	const char *p;
856fe1c642dSBill Krier 	char label_terminator;
857fe1c642dSBill Krier 
858fe1c642dSBill Krier 	if (domain == NULL)
859fe1c642dSBill Krier 		return (ERROR_INVALID_PARAMETER);
860fe1c642dSBill Krier 
861fe1c642dSBill Krier 	if (*domain == '\0')
862fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
863fe1c642dSBill Krier 
864fe1c642dSBill Krier 	label_terminator = *domain;
865fe1c642dSBill Krier 
866fe1c642dSBill Krier 	for (p = domain; *p != '\0'; ++p) {
867fe1c642dSBill Krier 		if (new_label) {
868fe1c642dSBill Krier 			if (!isalnum(*p))
869fe1c642dSBill Krier 				return (ERROR_INVALID_NAME);
870fe1c642dSBill Krier 			new_label = B_FALSE;
871fe1c642dSBill Krier 			label_terminator = *p;
872fe1c642dSBill Krier 			continue;
873fe1c642dSBill Krier 		}
874fe1c642dSBill Krier 
875fe1c642dSBill Krier 		if (*p == '.') {
876fe1c642dSBill Krier 			if (!isalnum(label_terminator))
877fe1c642dSBill Krier 				return (ERROR_INVALID_NAME);
878fe1c642dSBill Krier 			new_label = B_TRUE;
879fe1c642dSBill Krier 			label_terminator = *p;
880fe1c642dSBill Krier 			continue;
881fe1c642dSBill Krier 		}
882fe1c642dSBill Krier 
883fe1c642dSBill Krier 		label_terminator = *p;
884fe1c642dSBill Krier 
885fe1c642dSBill Krier 		if (isalnum(*p) || *p == '-' || *p == '_')
886fe1c642dSBill Krier 			continue;
887fe1c642dSBill Krier 
888fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
889fe1c642dSBill Krier 	}
890fe1c642dSBill Krier 
891fe1c642dSBill Krier 	if (!isalnum(label_terminator))
892fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
893fe1c642dSBill Krier 
894fe1c642dSBill Krier 	return (ERROR_SUCCESS);
895fe1c642dSBill Krier }
896fe1c642dSBill Krier 
897fe1c642dSBill Krier /*
898fe1c642dSBill Krier  * A NetBIOS domain name can contain letters (a-zA-Z), numbers (0-9) and
899fe1c642dSBill Krier  * hyphens.
900fe1c642dSBill Krier  *
901fe1c642dSBill Krier  * It cannot:
902fe1c642dSBill Krier  * 	- be blank or longer than 15 chracters
903fe1c642dSBill Krier  * 	- contain all numbers
904fe1c642dSBill Krier  * 	- be the same as the computer name
905fe1c642dSBill Krier  */
906fe1c642dSBill Krier uint32_t
907fe1c642dSBill Krier smb_name_validate_nbdomain(const char *name)
908fe1c642dSBill Krier {
909fe1c642dSBill Krier 	char		netbiosname[NETBIOS_NAME_SZ];
910fe1c642dSBill Krier 	const char	*p;
911fe1c642dSBill Krier 	int		len;
912fe1c642dSBill Krier 
913fe1c642dSBill Krier 	if (name == NULL)
914fe1c642dSBill Krier 		return (ERROR_INVALID_PARAMETER);
915fe1c642dSBill Krier 
916fe1c642dSBill Krier 	len = strlen(name);
917fe1c642dSBill Krier 	if (len == 0 || len >= NETBIOS_NAME_SZ)
918fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
919fe1c642dSBill Krier 
920fe1c642dSBill Krier 	if (strspn(name, "0123456789") == len)
921fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
922fe1c642dSBill Krier 
923fe1c642dSBill Krier 	if (smb_getnetbiosname(netbiosname, NETBIOS_NAME_SZ) == 0) {
924fe1c642dSBill Krier 		if (smb_strcasecmp(name, netbiosname, 0) == 0)
925fe1c642dSBill Krier 			return (ERROR_INVALID_NAME);
926fe1c642dSBill Krier 	}
927fe1c642dSBill Krier 
928fe1c642dSBill Krier 	for (p = name; *p != '\0'; ++p) {
929fe1c642dSBill Krier 		if (isalnum(*p) || *p == '-' || *p == '_')
930fe1c642dSBill Krier 			continue;
931fe1c642dSBill Krier 
932fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
933fe1c642dSBill Krier 	}
934fe1c642dSBill Krier 
935fe1c642dSBill Krier 	return (ERROR_SUCCESS);
936fe1c642dSBill Krier }
937fe1c642dSBill Krier 
938fe1c642dSBill Krier /*
939fe1c642dSBill Krier  * A workgroup name can contain 1 to 15 characters but cannot be the same
940fe1c642dSBill Krier  * as the NetBIOS name.  The name must begin with a letter or number.
941fe1c642dSBill Krier  *
942fe1c642dSBill Krier  * The name cannot consist entirely of spaces or dots, which is covered
943fe1c642dSBill Krier  * by the requirement that the name must begin with an alphanumeric
944fe1c642dSBill Krier  * character.
945fe1c642dSBill Krier  *
946fe1c642dSBill Krier  * The name must not contain control characters or any of the following
947fe1c642dSBill Krier  * characters.
948fe1c642dSBill Krier  *
949fe1c642dSBill Krier  *	" / \ [ ] : | < > + = ; , ?
950fe1c642dSBill Krier  */
951fe1c642dSBill Krier uint32_t
952fe1c642dSBill Krier smb_name_validate_workgroup(const char *workgroup)
953fe1c642dSBill Krier {
954fe1c642dSBill Krier 	char netbiosname[NETBIOS_NAME_SZ];
955fe1c642dSBill Krier 	const char *invalid = "\"/\\[]:|<>+=;,?";
956fe1c642dSBill Krier 	const char *p;
957fe1c642dSBill Krier 
958fe1c642dSBill Krier 	if (workgroup == NULL)
959fe1c642dSBill Krier 		return (ERROR_INVALID_PARAMETER);
960fe1c642dSBill Krier 
961fe1c642dSBill Krier 	if (*workgroup == '\0' || (!isalnum(*workgroup)))
962fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
963fe1c642dSBill Krier 
964fe1c642dSBill Krier 	if (strlen(workgroup) >= NETBIOS_NAME_SZ)
965fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
966fe1c642dSBill Krier 
967fe1c642dSBill Krier 	if (smb_getnetbiosname(netbiosname, NETBIOS_NAME_SZ) == 0) {
968fe1c642dSBill Krier 		if (smb_strcasecmp(workgroup, netbiosname, 0) == 0)
969fe1c642dSBill Krier 			return (ERROR_INVALID_NAME);
970fe1c642dSBill Krier 	}
971fe1c642dSBill Krier 
972fe1c642dSBill Krier 	if (strpbrk(workgroup, invalid) != NULL)
973fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
974fe1c642dSBill Krier 
975fe1c642dSBill Krier 	for (p = workgroup; *p != '\0'; p++) {
976fe1c642dSBill Krier 		if (iscntrl(*p))
977fe1c642dSBill Krier 			return (ERROR_INVALID_NAME);
978fe1c642dSBill Krier 	}
979fe1c642dSBill Krier 
980fe1c642dSBill Krier 	return (ERROR_SUCCESS);
981fe1c642dSBill Krier }
982fe1c642dSBill Krier 
983fe1c642dSBill Krier /*
9849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Check for invalid characters in the given path.  The list of invalid
9859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * characters includes control characters and the following:
9869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
9879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * " / \ [ ] : | < > + ; , ? * =
9889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
9899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Since this is checking a path not each component, '/' is accepted
9909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * as separator not an invalid character, except as the first character
9919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * since this is supposed to be a relative path.
9929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
9939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uint32_t
9949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_name_validate_rpath(const char *relpath)
9959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
9969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	char *invalid = "\"\\[]:|<>+;,?*=";
9979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	char *cp;
9989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
9999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((relpath == NULL) || (*relpath == '\0') || (*relpath == '/'))
10009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (ERROR_INVALID_NAME);
10019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (strpbrk(relpath, invalid))
10039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (ERROR_INVALID_NAME);
10049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	for (cp = (char *)relpath; *cp != '\0'; cp++) {
10069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (iscntrl(*cp))
10079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			return (ERROR_INVALID_NAME);
10089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
10099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (ERROR_SUCCESS);
10119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
10129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
1014fe1c642dSBill Krier  * Parse a string to obtain the account and domain names as separate strings.
1015fe1c642dSBill Krier  *
1016fe1c642dSBill Krier  * Names containing a backslash ('\') are known as qualified or composite
1017fe1c642dSBill Krier  * names.  The string preceding the backslash should be the domain name
1018fe1c642dSBill Krier  * and the string following the slash should be a name within that domain.
1019fe1c642dSBill Krier  *
1020fe1c642dSBill Krier  * Names that do not contain a backslash are known as isolated names.
1021fe1c642dSBill Krier  * An isolated name may be a single label, such as john, or may be in
1022fe1c642dSBill Krier  * user principal name (UPN) form, such as john@example.com.
1023fe1c642dSBill Krier  *
1024fe1c642dSBill Krier  *	domain\name
1025fe1c642dSBill Krier  *	domain/name
1026fe1c642dSBill Krier  *	name
1027fe1c642dSBill Krier  *	name@domain
1028fe1c642dSBill Krier  *
1029fe1c642dSBill Krier  * If we encounter any of the forms above in arg, the @, / or \ separator
1030fe1c642dSBill Krier  * is replaced by \0 and the name and domain pointers are set to point to
1031fe1c642dSBill Krier  * the appropriate components in arg.  Otherwise, name and domain pointers
1032fe1c642dSBill Krier  * will be set to NULL.
1033fe1c642dSBill Krier  */
1034fe1c642dSBill Krier void
1035fe1c642dSBill Krier smb_name_parse(char *arg, char **account, char **domain)
1036fe1c642dSBill Krier {
1037fe1c642dSBill Krier 	char *p;
1038fe1c642dSBill Krier 
1039fe1c642dSBill Krier 	*account = NULL;
1040fe1c642dSBill Krier 	*domain = NULL;
1041fe1c642dSBill Krier 
1042fe1c642dSBill Krier 	if ((p = strpbrk(arg, "/\\@")) != NULL) {
1043fe1c642dSBill Krier 		if (*p == '@') {
1044fe1c642dSBill Krier 			*p = '\0';
1045fe1c642dSBill Krier 			++p;
1046fe1c642dSBill Krier 			*domain = p;
1047fe1c642dSBill Krier 			*account = arg;
1048fe1c642dSBill Krier 		} else {
1049fe1c642dSBill Krier 			*p = '\0';
1050fe1c642dSBill Krier 			++p;
1051fe1c642dSBill Krier 			*account = p;
1052fe1c642dSBill Krier 			*domain = arg;
1053fe1c642dSBill Krier 		}
1054fe1c642dSBill Krier 	}
1055fe1c642dSBill Krier }
1056148c5f43SAlan Wright 
1057148c5f43SAlan Wright /*
1058148c5f43SAlan Wright  * The txid is an arbitrary transaction.  A new txid is returned on each call.
1059148c5f43SAlan Wright  *
1060148c5f43SAlan Wright  * 0 or -1 are not assigned so that they can be used to detect
1061148c5f43SAlan Wright  * invalid conditions.
1062148c5f43SAlan Wright  */
1063148c5f43SAlan Wright uint32_t
1064148c5f43SAlan Wright smb_get_txid(void)
1065148c5f43SAlan Wright {
1066148c5f43SAlan Wright 	static mutex_t	txmutex;
1067148c5f43SAlan Wright 	static uint32_t	txid;
1068148c5f43SAlan Wright 	uint32_t	txid_ret;
1069148c5f43SAlan Wright 
1070148c5f43SAlan Wright 	(void) mutex_lock(&txmutex);
1071148c5f43SAlan Wright 
1072148c5f43SAlan Wright 	if (txid == 0)
1073148c5f43SAlan Wright 		txid = time(NULL);
1074148c5f43SAlan Wright 
1075148c5f43SAlan Wright 	do {
1076148c5f43SAlan Wright 		++txid;
1077148c5f43SAlan Wright 	} while (txid == 0 || txid == (uint32_t)-1);
1078148c5f43SAlan Wright 
1079148c5f43SAlan Wright 	txid_ret = txid;
1080148c5f43SAlan Wright 	(void) mutex_unlock(&txmutex);
1081148c5f43SAlan Wright 
1082148c5f43SAlan Wright 	return (txid_ret);
1083148c5f43SAlan Wright }
1084