xref: /illumos-gate/usr/src/lib/smbsrv/libsmb/common/smb_util.c (revision 9b241b4ed1cf882400b069ff9853cdd310d469bf)
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.
232807a6ecSYuri Pankov  * Copyright 2011 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 
52148c5f43SAlan Wright #define	SMB_TIMEBUF_SZ		16
53148c5f43SAlan Wright #define	SMB_TRACEBUF_SZ		200
54148c5f43SAlan Wright 
55148c5f43SAlan Wright #define	SMB_LOG_FILE_FMT	"/var/smb/%s_log.txt"
56148c5f43SAlan Wright 
57148c5f43SAlan Wright typedef struct smb_log_pri {
58148c5f43SAlan Wright 	char	*lp_name;
59148c5f43SAlan Wright 	int	lp_value;
60148c5f43SAlan Wright } smb_log_pri_t;
61148c5f43SAlan Wright 
62148c5f43SAlan Wright static smb_log_pri_t smb_log_pri[] = {
63148c5f43SAlan Wright 	"panic",	LOG_EMERG,
64148c5f43SAlan Wright 	"emerg",	LOG_EMERG,
65148c5f43SAlan Wright 	"alert",	LOG_ALERT,
66148c5f43SAlan Wright 	"crit",		LOG_CRIT,
67148c5f43SAlan Wright 	"error",	LOG_ERR,
68148c5f43SAlan Wright 	"err",		LOG_ERR,
69148c5f43SAlan Wright 	"warn",		LOG_WARNING,
70148c5f43SAlan Wright 	"warning",	LOG_WARNING,
71148c5f43SAlan Wright 	"notice",	LOG_NOTICE,
72148c5f43SAlan Wright 	"info",		LOG_INFO,
73148c5f43SAlan Wright 	"debug",	LOG_DEBUG
74148c5f43SAlan Wright };
75148c5f43SAlan Wright 
76148c5f43SAlan Wright static void smb_log_trace(int, const char *);
77148c5f43SAlan Wright static smb_log_t *smb_log_get(smb_log_hdl_t);
78148c5f43SAlan Wright static void smb_log_dump(smb_log_t *);
79148c5f43SAlan Wright 
80b89a8333Snatalie li - Sun Microsystems - Irvine United States static boolean_t smb_netgroup_match(struct nd_hostservlist *, char *, int);
81b89a8333Snatalie li - Sun Microsystems - Irvine United States 
82*9b241b4eSYuri Pankov extern int __multi_innetgr();
83b89a8333Snatalie li - Sun Microsystems - Irvine United States extern int __netdir_getbyaddr_nosrv(struct netconfig *,
84b89a8333Snatalie li - Sun Microsystems - Irvine United States     struct nd_hostservlist **, struct netbuf *);
85da6c28aaSamw 
86148c5f43SAlan Wright static smb_loglist_t smb_loglist;
87148c5f43SAlan Wright 
88da6c28aaSamw #define	C2H(c)		"0123456789ABCDEF"[(c)]
89da6c28aaSamw #define	H2C(c)    (((c) >= '0' && (c) <= '9') ? ((c) - '0') :     \
90da6c28aaSamw 	((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) :         \
91da6c28aaSamw 	((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) :         \
92da6c28aaSamw 	'\0')
93da6c28aaSamw #define	DEFAULT_SBOX_SIZE		256
94da6c28aaSamw 
95da6c28aaSamw /*
96da6c28aaSamw  *
97da6c28aaSamw  * hexdump
98da6c28aaSamw  *
99da6c28aaSamw  * Simple hex dump display function. Displays nbytes of buffer in hex and
100da6c28aaSamw  * printable format. Non-printing characters are shown as '.'. It is safe
101da6c28aaSamw  * to pass a null pointer. Each line begins with the offset. If nbytes is
102da6c28aaSamw  * 0, the line will be blank except for the offset. Example output:
103da6c28aaSamw  *
104da6c28aaSamw  * 00000000  54 68 69 73 20 69 73 20 61 20 70 72 6F 67 72 61  This is a progra
105da6c28aaSamw  * 00000010  6D 20 74 65 73 74 2E 00                          m test..
106da6c28aaSamw  *
107da6c28aaSamw  */
108da6c28aaSamw void
109dc20a302Sas hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start)
110da6c28aaSamw {
111da6c28aaSamw 	static char *hex = "0123456789ABCDEF";
112da6c28aaSamw 	int i, count;
113da6c28aaSamw 	int offset;
114da6c28aaSamw 	unsigned char *p;
115da6c28aaSamw 	char ascbuf[64];
116da6c28aaSamw 	char hexbuf[64];
117da6c28aaSamw 	char *ap = ascbuf;
118da6c28aaSamw 	char *hp = hexbuf;
119da6c28aaSamw 
120dc20a302Sas 	if ((p = buffer) == NULL)
121da6c28aaSamw 		return;
122da6c28aaSamw 
123da6c28aaSamw 	offset = *start;
124da6c28aaSamw 
125da6c28aaSamw 	*ap = '\0';
126da6c28aaSamw 	*hp = '\0';
127da6c28aaSamw 	count = 0;
128da6c28aaSamw 
129da6c28aaSamw 	for (i = 0; i < nbytes; ++i) {
130da6c28aaSamw 		if (i && (i % 16) == 0) {
131dc20a302Sas 			smb_tracef("%06X %s  %s", offset, hexbuf, ascbuf);
132da6c28aaSamw 			ap = ascbuf;
133da6c28aaSamw 			hp = hexbuf;
134da6c28aaSamw 			count = 0;
135da6c28aaSamw 			offset += 16;
136da6c28aaSamw 		}
137da6c28aaSamw 
138da6c28aaSamw 		ap += sprintf(ap, "%c",
139da6c28aaSamw 		    (*p >= 0x20 && *p < 0x7F) ? *p : '.');
140da6c28aaSamw 		hp += sprintf(hp, " %c%c",
141da6c28aaSamw 		    hex[(*p >> 4) & 0x0F], hex[(*p & 0x0F)]);
142da6c28aaSamw 		++p;
143da6c28aaSamw 		++count;
144da6c28aaSamw 	}
145da6c28aaSamw 
146da6c28aaSamw 	if (count) {
147dc20a302Sas 		smb_tracef("%06X %-48s  %s", offset, hexbuf, ascbuf);
148da6c28aaSamw 		offset += count;
149da6c28aaSamw 	}
150da6c28aaSamw 
151da6c28aaSamw 	*start = offset;
152da6c28aaSamw }
153da6c28aaSamw 
154da6c28aaSamw void
155da6c28aaSamw hexdump(unsigned char *buffer, int nbytes)
156da6c28aaSamw {
157da6c28aaSamw 	unsigned long start = 0;
158da6c28aaSamw 
159dc20a302Sas 	hexdump_offset(buffer, nbytes, &start);
160da6c28aaSamw }
161da6c28aaSamw 
162da6c28aaSamw /*
163da6c28aaSamw  * bintohex
164da6c28aaSamw  *
165da6c28aaSamw  * Converts the given binary data (srcbuf) to
166da6c28aaSamw  * its equivalent hex chars (hexbuf).
167da6c28aaSamw  *
168da6c28aaSamw  * hexlen should be at least twice as srclen.
169da6c28aaSamw  * if hexbuf is not big enough returns 0.
170da6c28aaSamw  * otherwise returns number of valid chars in
171da6c28aaSamw  * hexbuf which is srclen * 2.
172da6c28aaSamw  */
173da6c28aaSamw size_t
174da6c28aaSamw bintohex(const char *srcbuf, size_t srclen,
175da6c28aaSamw     char *hexbuf, size_t hexlen)
176da6c28aaSamw {
177da6c28aaSamw 	size_t outlen;
178da6c28aaSamw 	char c;
179da6c28aaSamw 
180da6c28aaSamw 	outlen = srclen << 1;
181da6c28aaSamw 
182da6c28aaSamw 	if (hexlen < outlen)
183da6c28aaSamw 		return (0);
184da6c28aaSamw 
185da6c28aaSamw 	while (srclen-- > 0) {
186da6c28aaSamw 		c = *srcbuf++;
187da6c28aaSamw 		*hexbuf++ = C2H(c & 0xF);
188da6c28aaSamw 		*hexbuf++ = C2H((c >> 4) & 0xF);
189da6c28aaSamw 	}
190da6c28aaSamw 
191da6c28aaSamw 	return (outlen);
192da6c28aaSamw }
193da6c28aaSamw 
194da6c28aaSamw /*
195da6c28aaSamw  * hextobin
196da6c28aaSamw  *
197da6c28aaSamw  * Converts hex to binary.
198da6c28aaSamw  *
199da6c28aaSamw  * Assuming hexbuf only contains hex digits (chars)
200da6c28aaSamw  * this function convert every two bytes of hexbuf
201da6c28aaSamw  * to one byte and put it in dstbuf.
202da6c28aaSamw  *
203da6c28aaSamw  * hexlen should be an even number.
204da6c28aaSamw  * dstlen should be at least half of hexlen.
205da6c28aaSamw  *
206da6c28aaSamw  * Returns 0 if sizes are not correct, otherwise
207da6c28aaSamw  * returns the number of converted bytes in dstbuf
208da6c28aaSamw  * which is half of hexlen.
209da6c28aaSamw  */
210da6c28aaSamw size_t
211da6c28aaSamw hextobin(const char *hexbuf, size_t hexlen,
212da6c28aaSamw     char *dstbuf, size_t dstlen)
213da6c28aaSamw {
214da6c28aaSamw 	size_t outlen;
215da6c28aaSamw 
216da6c28aaSamw 	if ((hexlen % 2) != 0)
217da6c28aaSamw 		return (0);
218da6c28aaSamw 
219da6c28aaSamw 	outlen = hexlen >> 1;
220da6c28aaSamw 	if (dstlen < outlen)
221da6c28aaSamw 		return (0);
222da6c28aaSamw 
223da6c28aaSamw 	while (hexlen > 0) {
224da6c28aaSamw 		*dstbuf = H2C(*hexbuf) & 0x0F;
225da6c28aaSamw 		hexbuf++;
226da6c28aaSamw 		*dstbuf++ |= (H2C(*hexbuf) << 4) & 0xF0;
227da6c28aaSamw 		hexbuf++;
228da6c28aaSamw 
229da6c28aaSamw 		hexlen -= 2;
230da6c28aaSamw 	}
231da6c28aaSamw 
232da6c28aaSamw 	return (outlen);
233da6c28aaSamw }
234da6c28aaSamw 
2358d7e4166Sjose borrego /*
2368d7e4166Sjose borrego  * Trim leading and trailing characters in the set defined by class
2378d7e4166Sjose borrego  * from a buffer containing a null-terminated string.
2388d7e4166Sjose borrego  * For example, if the input buffer contained "ABtext23" and class
2398d7e4166Sjose borrego  * contains "ABC123", the buffer will contain "text" on return.
2408d7e4166Sjose borrego  *
2418d7e4166Sjose borrego  * This function modifies the contents of buf in place and returns
2428d7e4166Sjose borrego  * a pointer to buf.
2438d7e4166Sjose borrego  */
2448d7e4166Sjose borrego char *
2458d7e4166Sjose borrego strtrim(char *buf, const char *class)
2468d7e4166Sjose borrego {
2478d7e4166Sjose borrego 	char *p = buf;
2488d7e4166Sjose borrego 	char *q = buf;
2498d7e4166Sjose borrego 
2508d7e4166Sjose borrego 	if (buf == NULL)
2518d7e4166Sjose borrego 		return (NULL);
2528d7e4166Sjose borrego 
2538d7e4166Sjose borrego 	p += strspn(p, class);
2548d7e4166Sjose borrego 
2558d7e4166Sjose borrego 	if (p != buf) {
2568d7e4166Sjose borrego 		while ((*q = *p++) != '\0')
2578d7e4166Sjose borrego 			++q;
2588d7e4166Sjose borrego 	}
2598d7e4166Sjose borrego 
2608d7e4166Sjose borrego 	while (q != buf) {
2618d7e4166Sjose borrego 		--q;
2628d7e4166Sjose borrego 		if (strspn(q, class) == 0)
2638d7e4166Sjose borrego 			return (buf);
2648d7e4166Sjose borrego 		*q = '\0';
2658d7e4166Sjose borrego 	}
2668d7e4166Sjose borrego 
2678d7e4166Sjose borrego 	return (buf);
2688d7e4166Sjose borrego }
2698d7e4166Sjose borrego 
2708d7e4166Sjose borrego /*
2718d7e4166Sjose borrego  * Strip the characters in the set defined by class from a buffer
2728d7e4166Sjose borrego  * containing a null-terminated string.
2738d7e4166Sjose borrego  * For example, if the input buffer contained "XYA 1textZ string3"
2748d7e4166Sjose borrego  * and class contains "123XYZ", the buffer will contain "A text string"
2758d7e4166Sjose borrego  * on return.
2768d7e4166Sjose borrego  *
2778d7e4166Sjose borrego  * This function modifies the contents of buf in place and returns
2788d7e4166Sjose borrego  * a pointer to buf.
2798d7e4166Sjose borrego  */
2808d7e4166Sjose borrego char *
2818d7e4166Sjose borrego strstrip(char *buf, const char *class)
2828d7e4166Sjose borrego {
2838d7e4166Sjose borrego 	char *p = buf;
2848d7e4166Sjose borrego 	char *q = buf;
2858d7e4166Sjose borrego 
2868d7e4166Sjose borrego 	if (buf == NULL)
2878d7e4166Sjose borrego 		return (NULL);
2888d7e4166Sjose borrego 
2898d7e4166Sjose borrego 	while (*p) {
2908d7e4166Sjose borrego 		p += strspn(p, class);
2918d7e4166Sjose borrego 		*q++ = *p++;
2928d7e4166Sjose borrego 	}
2938d7e4166Sjose borrego 
2948d7e4166Sjose borrego 	*q = '\0';
2958d7e4166Sjose borrego 	return (buf);
2968d7e4166Sjose borrego }
2978d7e4166Sjose borrego 
298da6c28aaSamw /*
299da6c28aaSamw  * trim_whitespace
300da6c28aaSamw  *
301da6c28aaSamw  * Trim leading and trailing whitespace chars (as defined by isspace)
302da6c28aaSamw  * from a buffer. Example; if the input buffer contained "  text  ",
303da6c28aaSamw  * it will contain "text", when we return. We assume that the buffer
304da6c28aaSamw  * contains a null terminated string. A pointer to the buffer is
305da6c28aaSamw  * returned.
306da6c28aaSamw  */
307da6c28aaSamw char *
308da6c28aaSamw trim_whitespace(char *buf)
309da6c28aaSamw {
310da6c28aaSamw 	char *p = buf;
311da6c28aaSamw 	char *q = buf;
312da6c28aaSamw 
313dc20a302Sas 	if (buf == NULL)
314dc20a302Sas 		return (NULL);
315da6c28aaSamw 
316da6c28aaSamw 	while (*p && isspace(*p))
317da6c28aaSamw 		++p;
318da6c28aaSamw 
319da6c28aaSamw 	while ((*q = *p++) != 0)
320da6c28aaSamw 		++q;
321da6c28aaSamw 
322da6c28aaSamw 	if (q != buf) {
323da6c28aaSamw 		while ((--q, isspace(*q)) != 0)
324da6c28aaSamw 			*q = '\0';
325da6c28aaSamw 	}
326da6c28aaSamw 
327da6c28aaSamw 	return (buf);
328da6c28aaSamw }
329da6c28aaSamw 
330da6c28aaSamw /*
331da6c28aaSamw  * randomize
332da6c28aaSamw  *
333da6c28aaSamw  * Randomize the contents of the specified buffer.
334da6c28aaSamw  */
335da6c28aaSamw void
336da6c28aaSamw randomize(char *data, unsigned len)
337da6c28aaSamw {
338da6c28aaSamw 	unsigned dwlen = len / 4;
339da6c28aaSamw 	unsigned remlen = len % 4;
340da6c28aaSamw 	unsigned tmp;
341da6c28aaSamw 	unsigned i; /*LINTED E_BAD_PTR_CAST_ALIGN*/
342da6c28aaSamw 	unsigned *p = (unsigned *)data;
343da6c28aaSamw 
344da6c28aaSamw 	for (i = 0; i < dwlen; ++i)
345da6c28aaSamw 		*p++ = random();
346da6c28aaSamw 
347da6c28aaSamw 	if (remlen) {
348da6c28aaSamw 		tmp = random();
349da6c28aaSamw 		(void) memcpy(p, &tmp, remlen);
350da6c28aaSamw 	}
351da6c28aaSamw }
352da6c28aaSamw 
353da6c28aaSamw /*
354da6c28aaSamw  * This is the hash mechanism used to encrypt passwords for commands like
355da6c28aaSamw  * SamrSetUserInformation. It uses a 256 byte s-box.
356da6c28aaSamw  */
357da6c28aaSamw void
358da6c28aaSamw rand_hash(
359da6c28aaSamw     unsigned char *data,
360da6c28aaSamw     size_t datalen,
361da6c28aaSamw     unsigned char *key,
362da6c28aaSamw     size_t keylen)
363da6c28aaSamw {
364da6c28aaSamw 	unsigned char sbox[DEFAULT_SBOX_SIZE];
365da6c28aaSamw 	unsigned char tmp;
366da6c28aaSamw 	unsigned char index_i = 0;
367da6c28aaSamw 	unsigned char index_j = 0;
368da6c28aaSamw 	unsigned char j = 0;
369da6c28aaSamw 	int i;
370da6c28aaSamw 
371da6c28aaSamw 	for (i = 0; i < DEFAULT_SBOX_SIZE; ++i)
372da6c28aaSamw 		sbox[i] = (unsigned char)i;
373da6c28aaSamw 
374da6c28aaSamw 	for (i = 0; i < DEFAULT_SBOX_SIZE; ++i) {
375da6c28aaSamw 		j += (sbox[i] + key[i % keylen]);
376da6c28aaSamw 
377da6c28aaSamw 		tmp = sbox[i];
378da6c28aaSamw 		sbox[i] = sbox[j];
379da6c28aaSamw 		sbox[j] = tmp;
380da6c28aaSamw 	}
381da6c28aaSamw 
382da6c28aaSamw 	for (i = 0; i < datalen; ++i) {
383da6c28aaSamw 		index_i++;
384da6c28aaSamw 		index_j += sbox[index_i];
385da6c28aaSamw 
386da6c28aaSamw 		tmp = sbox[index_i];
387da6c28aaSamw 		sbox[index_i] = sbox[index_j];
388da6c28aaSamw 		sbox[index_j] = tmp;
389da6c28aaSamw 
390da6c28aaSamw 		tmp = sbox[index_i] + sbox[index_j];
391da6c28aaSamw 		data[i] = data[i] ^ sbox[tmp];
392da6c28aaSamw 	}
393da6c28aaSamw }
394b89a8333Snatalie li - Sun Microsystems - Irvine United States 
395b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
396b89a8333Snatalie li - Sun Microsystems - Irvine United States  * smb_chk_hostaccess
397b89a8333Snatalie li - Sun Microsystems - Irvine United States  *
398148c5f43SAlan Wright  * Determines whether the specified host is in the given access list.
399148c5f43SAlan Wright  *
400b89a8333Snatalie li - Sun Microsystems - Irvine United States  * We match on aliases of the hostname as well as on the canonical name.
401b89a8333Snatalie li - Sun Microsystems - Irvine United States  * Names in the access list may be either hosts or netgroups;  they're
402b89a8333Snatalie li - Sun Microsystems - Irvine United States  * not distinguished syntactically.  We check for hosts first because
403b89a8333Snatalie li - Sun Microsystems - Irvine United States  * it's cheaper (just M*N strcmp()s), then try netgroups.
404b89a8333Snatalie li - Sun Microsystems - Irvine United States  *
405b89a8333Snatalie li - Sun Microsystems - Irvine United States  * Function returns:
406148c5f43SAlan Wright  *	-1 for "all" (list is empty "" or "*")
407148c5f43SAlan Wright  *	0 not found  (host is not in the list or list is NULL)
408b89a8333Snatalie li - Sun Microsystems - Irvine United States  *	1 found
4097f667e74Sjose borrego  *
410b89a8333Snatalie li - Sun Microsystems - Irvine United States  */
411b89a8333Snatalie li - Sun Microsystems - Irvine United States int
4127f667e74Sjose borrego smb_chk_hostaccess(smb_inaddr_t *ipaddr, char *access_list)
413b89a8333Snatalie li - Sun Microsystems - Irvine United States {
414*9b241b4eSYuri Pankov 	char addr[INET_ADDRSTRLEN];
415*9b241b4eSYuri Pankov 	char buff[256];
416*9b241b4eSYuri Pankov 	char *cstr = access_list, *gr = access_list;
417b89a8333Snatalie li - Sun Microsystems - Irvine United States 	char *host;
418*9b241b4eSYuri Pankov 	int clres;
419b89a8333Snatalie li - Sun Microsystems - Irvine United States 	int i;
420*9b241b4eSYuri Pankov 	int nentries = 0;
421*9b241b4eSYuri Pankov 	int off;
422b89a8333Snatalie li - Sun Microsystems - Irvine United States 	int response;
423*9b241b4eSYuri Pankov 	int sbr = 0;
424b89a8333Snatalie li - Sun Microsystems - Irvine United States 	struct nd_hostservlist *clnames;
425b89a8333Snatalie li - Sun Microsystems - Irvine United States 	struct in_addr inaddr;
426b89a8333Snatalie li - Sun Microsystems - Irvine United States 	struct sockaddr_in sa;
427*9b241b4eSYuri Pankov 	struct sockaddr_in6 sa6;
428b89a8333Snatalie li - Sun Microsystems - Irvine United States 	struct netbuf buf;
429b89a8333Snatalie li - Sun Microsystems - Irvine United States 	struct netconfig *config;
430*9b241b4eSYuri Pankov 	struct netent n, *np;
431b89a8333Snatalie li - Sun Microsystems - Irvine United States 
432148c5f43SAlan Wright 	if (access_list == NULL)
433148c5f43SAlan Wright 		return (0);
4347f667e74Sjose borrego 
435*9b241b4eSYuri Pankov 	/* If access list is empty or "*" - then it's "all" */
436148c5f43SAlan Wright 	if (*access_list == '\0' || strcmp(access_list, "*") == 0)
437b89a8333Snatalie li - Sun Microsystems - Irvine United States 		return (-1);
438b89a8333Snatalie li - Sun Microsystems - Irvine United States 
439*9b241b4eSYuri Pankov 	switch (ipaddr->a_family) {
440*9b241b4eSYuri Pankov 	case AF_INET:
441*9b241b4eSYuri Pankov 		inaddr.s_addr = ipaddr->a_ipv4;
442*9b241b4eSYuri Pankov 		sa.sin_family = AF_INET;
443*9b241b4eSYuri Pankov 		sa.sin_port = 0;
444*9b241b4eSYuri Pankov 		sa.sin_addr = inaddr;
445*9b241b4eSYuri Pankov 		buf.len = buf.maxlen = sizeof (sa);
446*9b241b4eSYuri Pankov 		buf.buf = (char *)&sa;
447*9b241b4eSYuri Pankov 		config = getnetconfigent("tcp");
448*9b241b4eSYuri Pankov 		break;
449*9b241b4eSYuri Pankov 	case AF_INET6:
450*9b241b4eSYuri Pankov 		sa6.sin6_family = AF_INET6;
451*9b241b4eSYuri Pankov 		sa6.sin6_port = 0;
452*9b241b4eSYuri Pankov 		sa6.sin6_addr = ipaddr->a_ipv6;
453*9b241b4eSYuri Pankov 		buf.len = buf.maxlen = sizeof (sa6);
454*9b241b4eSYuri Pankov 		buf.buf = (char *)&sa6;
455*9b241b4eSYuri Pankov 		config = getnetconfigent("tcp6");
456*9b241b4eSYuri Pankov 		break;
457*9b241b4eSYuri Pankov 	default:
458*9b241b4eSYuri Pankov 		return (1);
459*9b241b4eSYuri Pankov 	}
460b89a8333Snatalie li - Sun Microsystems - Irvine United States 
461b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (config == NULL)
462b89a8333Snatalie li - Sun Microsystems - Irvine United States 		return (1);
463b89a8333Snatalie li - Sun Microsystems - Irvine United States 
464*9b241b4eSYuri Pankov 	/* Try to lookup client hostname */
4652807a6ecSYuri Pankov 	clres = __netdir_getbyaddr_nosrv(config, &clnames, &buf);
466b89a8333Snatalie li - Sun Microsystems - Irvine United States 	freenetconfigent(config);
467b89a8333Snatalie li - Sun Microsystems - Irvine United States 
468*9b241b4eSYuri Pankov 	for (;;) {
469*9b241b4eSYuri Pankov 		if ((cstr = strpbrk(cstr, "[]:")) != NULL) {
470*9b241b4eSYuri Pankov 			switch (*cstr) {
471*9b241b4eSYuri Pankov 			case '[':
472*9b241b4eSYuri Pankov 			case ']':
473*9b241b4eSYuri Pankov 				sbr = !sbr;
474*9b241b4eSYuri Pankov 				cstr++;
475*9b241b4eSYuri Pankov 				continue;
476*9b241b4eSYuri Pankov 			case ':':
477*9b241b4eSYuri Pankov 				if (sbr) {
478*9b241b4eSYuri Pankov 					cstr++;
479*9b241b4eSYuri Pankov 					continue;
480*9b241b4eSYuri Pankov 				}
481*9b241b4eSYuri Pankov 				*cstr = '\0';
482*9b241b4eSYuri Pankov 			}
483*9b241b4eSYuri Pankov 		}
484b89a8333Snatalie li - Sun Microsystems - Irvine United States 
485b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/*
486*9b241b4eSYuri Pankov 		 * If the list name has a '-' prepended then a match of
487*9b241b4eSYuri Pankov 		 * the following name implies failure instead of success.
488b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 */
489b89a8333Snatalie li - Sun Microsystems - Irvine United States 		if (*gr == '-') {
490b89a8333Snatalie li - Sun Microsystems - Irvine United States 			response = 0;
491b89a8333Snatalie li - Sun Microsystems - Irvine United States 			gr++;
492b89a8333Snatalie li - Sun Microsystems - Irvine United States 		} else {
493b89a8333Snatalie li - Sun Microsystems - Irvine United States 			response = 1;
494b89a8333Snatalie li - Sun Microsystems - Irvine United States 		}
495b89a8333Snatalie li - Sun Microsystems - Irvine United States 
496b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/*
497*9b241b4eSYuri Pankov 		 * First check if we have '@' entry, as it doesn't
498*9b241b4eSYuri Pankov 		 * require client hostname.
4992807a6ecSYuri Pankov 		 */
500*9b241b4eSYuri Pankov 		if (*gr == '@') {
501*9b241b4eSYuri Pankov 			gr++;
502*9b241b4eSYuri Pankov 
503*9b241b4eSYuri Pankov 			if (!isdigit(*gr) && *gr != '[') {
504*9b241b4eSYuri Pankov 				/* Netname support */
505*9b241b4eSYuri Pankov 				if ((np = getnetbyname_r(gr, &n, buff,
506*9b241b4eSYuri Pankov 				    sizeof (buff))) != NULL &&
507*9b241b4eSYuri Pankov 				    np->n_net != 0) {
508*9b241b4eSYuri Pankov 					while ((np->n_net & 0xFF000000u) == 0)
509*9b241b4eSYuri Pankov 						np->n_net <<= 8;
510*9b241b4eSYuri Pankov 					np->n_net = htonl(np->n_net);
511*9b241b4eSYuri Pankov 					if (inet_ntop(AF_INET, &np->n_net, addr,
512*9b241b4eSYuri Pankov 					    INET_ADDRSTRLEN) == NULL)
513*9b241b4eSYuri Pankov 						break;
514*9b241b4eSYuri Pankov 					if (inet_matchaddr(buf.buf, addr))
515*9b241b4eSYuri Pankov 						return (response);
516*9b241b4eSYuri Pankov 				}
517*9b241b4eSYuri Pankov 			} else {
518*9b241b4eSYuri Pankov 				if (inet_matchaddr(buf.buf, gr))
519*9b241b4eSYuri Pankov 					return (response);
520*9b241b4eSYuri Pankov 			}
521*9b241b4eSYuri Pankov 
522*9b241b4eSYuri Pankov 			if (cstr == NULL)
523*9b241b4eSYuri Pankov 				break;
524*9b241b4eSYuri Pankov 
525*9b241b4eSYuri Pankov 			gr = ++cstr;
526*9b241b4eSYuri Pankov 
527*9b241b4eSYuri Pankov 			continue;
528*9b241b4eSYuri Pankov 		}
529*9b241b4eSYuri Pankov 
5302807a6ecSYuri Pankov 		/*
5312807a6ecSYuri Pankov 		 * No other checks can be performed if client address
5322807a6ecSYuri Pankov 		 * can't be resolved.
5332807a6ecSYuri Pankov 		 */
534*9b241b4eSYuri Pankov 		if (clres) {
535*9b241b4eSYuri Pankov 			if (cstr == NULL)
536*9b241b4eSYuri Pankov 				break;
537*9b241b4eSYuri Pankov 
538*9b241b4eSYuri Pankov 			gr = ++cstr;
539*9b241b4eSYuri Pankov 
5402807a6ecSYuri Pankov 			continue;
541*9b241b4eSYuri Pankov 		}
542*9b241b4eSYuri Pankov 
543*9b241b4eSYuri Pankov 		/* Otherwise loop through all client hostname aliases */
544b89a8333Snatalie li - Sun Microsystems - Irvine United States 		for (i = 0; i < clnames->h_cnt; i++) {
545b89a8333Snatalie li - Sun Microsystems - Irvine United States 			host = clnames->h_hostservs[i].h_host;
546b89a8333Snatalie li - Sun Microsystems - Irvine United States 			/*
547b89a8333Snatalie li - Sun Microsystems - Irvine United States 			 * If the list name begins with a dot then
548b89a8333Snatalie li - Sun Microsystems - Irvine United States 			 * do a domain name suffix comparison.
549b89a8333Snatalie li - Sun Microsystems - Irvine United States 			 * A single dot matches any name with no
550b89a8333Snatalie li - Sun Microsystems - Irvine United States 			 * suffix.
551b89a8333Snatalie li - Sun Microsystems - Irvine United States 			 */
552b89a8333Snatalie li - Sun Microsystems - Irvine United States 			if (*gr == '.') {
553*9b241b4eSYuri Pankov 				if (*(gr + 1) == '\0') {
554b89a8333Snatalie li - Sun Microsystems - Irvine United States 					if (strchr(host, '.') == NULL)
555b89a8333Snatalie li - Sun Microsystems - Irvine United States 						return (response);
556b89a8333Snatalie li - Sun Microsystems - Irvine United States 				} else {
557b89a8333Snatalie li - Sun Microsystems - Irvine United States 					off = strlen(host) - strlen(gr);
558b89a8333Snatalie li - Sun Microsystems - Irvine United States 					if (off > 0 &&
559b89a8333Snatalie li - Sun Microsystems - Irvine United States 					    strcasecmp(host + off, gr) == 0) {
560b89a8333Snatalie li - Sun Microsystems - Irvine United States 						return (response);
561b89a8333Snatalie li - Sun Microsystems - Irvine United States 					}
562b89a8333Snatalie li - Sun Microsystems - Irvine United States 				}
563b89a8333Snatalie li - Sun Microsystems - Irvine United States 			} else {
564*9b241b4eSYuri Pankov 				/* Just do a hostname match */
5652807a6ecSYuri Pankov 				if (strcasecmp(gr, host) == 0)
5662807a6ecSYuri Pankov 					return (response);
567b89a8333Snatalie li - Sun Microsystems - Irvine United States 				}
568b89a8333Snatalie li - Sun Microsystems - Irvine United States 			}
569b89a8333Snatalie li - Sun Microsystems - Irvine United States 
570b89a8333Snatalie li - Sun Microsystems - Irvine United States 		nentries++;
571*9b241b4eSYuri Pankov 
572*9b241b4eSYuri Pankov 		if (cstr == NULL)
573*9b241b4eSYuri Pankov 			break;
574*9b241b4eSYuri Pankov 
575*9b241b4eSYuri Pankov 		gr = ++cstr;
576b89a8333Snatalie li - Sun Microsystems - Irvine United States 	}
577b89a8333Snatalie li - Sun Microsystems - Irvine United States 
5782807a6ecSYuri Pankov 	if (clres)
5792807a6ecSYuri Pankov 		return (0);
580b89a8333Snatalie li - Sun Microsystems - Irvine United States 
5812807a6ecSYuri Pankov 	return (smb_netgroup_match(clnames, access_list, nentries));
582b89a8333Snatalie li - Sun Microsystems - Irvine United States }
583b89a8333Snatalie li - Sun Microsystems - Irvine United States 
584b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
585b89a8333Snatalie li - Sun Microsystems - Irvine United States  * smb_netgroup_match
586b89a8333Snatalie li - Sun Microsystems - Irvine United States  *
587b89a8333Snatalie li - Sun Microsystems - Irvine United States  * Check whether any of the hostnames in clnames are
588b89a8333Snatalie li - Sun Microsystems - Irvine United States  * members (or non-members) of the netgroups in glist.
589b89a8333Snatalie li - Sun Microsystems - Irvine United States  * Since the innetgr lookup is rather expensive, the
590b89a8333Snatalie li - Sun Microsystems - Irvine United States  * result is cached. The cached entry is valid only
591b89a8333Snatalie li - Sun Microsystems - Irvine United States  * for VALID_TIME seconds.  This works well because
592b89a8333Snatalie li - Sun Microsystems - Irvine United States  * typically these lookups occur in clusters when
593b89a8333Snatalie li - Sun Microsystems - Irvine United States  * a client is mounting.
594b89a8333Snatalie li - Sun Microsystems - Irvine United States  *
595b89a8333Snatalie li - Sun Microsystems - Irvine United States  * Note that this routine establishes a host membership
596b89a8333Snatalie li - Sun Microsystems - Irvine United States  * in a list of netgroups - we've no idea just which
597b89a8333Snatalie li - Sun Microsystems - Irvine United States  * netgroup in the list it is a member of.
598b89a8333Snatalie li - Sun Microsystems - Irvine United States  *
599b89a8333Snatalie li - Sun Microsystems - Irvine United States  * glist is a character array containing grc strings
600b89a8333Snatalie li - Sun Microsystems - Irvine United States  * representing netgroup names (optionally prefixed
601b89a8333Snatalie li - Sun Microsystems - Irvine United States  * with '-'). Each string is ended with '\0'  and
602b89a8333Snatalie li - Sun Microsystems - Irvine United States  * followed immediately by the next string.
603b89a8333Snatalie li - Sun Microsystems - Irvine United States  */
604b89a8333Snatalie li - Sun Microsystems - Irvine United States static boolean_t
605b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_netgroup_match(struct nd_hostservlist *clnames, char  *glist, int grc)
606b89a8333Snatalie li - Sun Microsystems - Irvine United States {
607b89a8333Snatalie li - Sun Microsystems - Irvine United States 	char **grl;
608b89a8333Snatalie li - Sun Microsystems - Irvine United States 	char *gr;
609b89a8333Snatalie li - Sun Microsystems - Irvine United States 	int nhosts = clnames->h_cnt;
610b89a8333Snatalie li - Sun Microsystems - Irvine United States 	char *host;
611b89a8333Snatalie li - Sun Microsystems - Irvine United States 	int i, j, n;
612b89a8333Snatalie li - Sun Microsystems - Irvine United States 	boolean_t response;
613b89a8333Snatalie li - Sun Microsystems - Irvine United States 	boolean_t belong = B_FALSE;
614b89a8333Snatalie li - Sun Microsystems - Irvine United States 	static char *domain = NULL;
615b89a8333Snatalie li - Sun Microsystems - Irvine United States 
616b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (domain == NULL) {
617b89a8333Snatalie li - Sun Microsystems - Irvine United States 		int	ssize;
618b89a8333Snatalie li - Sun Microsystems - Irvine United States 
619b89a8333Snatalie li - Sun Microsystems - Irvine United States 		domain = malloc(SYS_NMLN);
620b89a8333Snatalie li - Sun Microsystems - Irvine United States 		if (domain == NULL)
621b89a8333Snatalie li - Sun Microsystems - Irvine United States 			return (B_FALSE);
622b89a8333Snatalie li - Sun Microsystems - Irvine United States 
623b89a8333Snatalie li - Sun Microsystems - Irvine United States 		ssize = sysinfo(SI_SRPC_DOMAIN, domain, SYS_NMLN);
624b89a8333Snatalie li - Sun Microsystems - Irvine United States 		if (ssize > SYS_NMLN) {
625b89a8333Snatalie li - Sun Microsystems - Irvine United States 			free(domain);
626b89a8333Snatalie li - Sun Microsystems - Irvine United States 			domain = malloc(ssize);
627b89a8333Snatalie li - Sun Microsystems - Irvine United States 			if (domain == NULL)
628b89a8333Snatalie li - Sun Microsystems - Irvine United States 				return (B_FALSE);
629b89a8333Snatalie li - Sun Microsystems - Irvine United States 			ssize = sysinfo(SI_SRPC_DOMAIN, domain, ssize);
630b89a8333Snatalie li - Sun Microsystems - Irvine United States 		}
631b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/* Check for error in syscall or NULL domain name */
632b89a8333Snatalie li - Sun Microsystems - Irvine United States 		if (ssize <= 1)
633b89a8333Snatalie li - Sun Microsystems - Irvine United States 			return (B_FALSE);
634b89a8333Snatalie li - Sun Microsystems - Irvine United States 	}
635b89a8333Snatalie li - Sun Microsystems - Irvine United States 
636b89a8333Snatalie li - Sun Microsystems - Irvine United States 	grl = calloc(grc, sizeof (char *));
637b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (grl == NULL)
638b89a8333Snatalie li - Sun Microsystems - Irvine United States 		return (B_FALSE);
639b89a8333Snatalie li - Sun Microsystems - Irvine United States 
640b89a8333Snatalie li - Sun Microsystems - Irvine United States 	for (i = 0, gr = glist; i < grc && !belong; ) {
641b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/*
642b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * If the netgroup name has a '-' prepended
643b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * then a match of this name implies a failure
644b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * instead of success.
645b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 */
646b89a8333Snatalie li - Sun Microsystems - Irvine United States 		response = (*gr != '-') ? B_TRUE : B_FALSE;
647b89a8333Snatalie li - Sun Microsystems - Irvine United States 
648b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/*
649b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * Subsequent names with or without a '-' (but no mix)
650b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * can be grouped together for a single check.
651b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 */
652b89a8333Snatalie li - Sun Microsystems - Irvine United States 		for (n = 0; i < grc; i++, n++, gr += strlen(gr) + 1) {
653b89a8333Snatalie li - Sun Microsystems - Irvine United States 			if ((response && *gr == '-') ||
654b89a8333Snatalie li - Sun Microsystems - Irvine United States 			    (!response && *gr != '-'))
655b89a8333Snatalie li - Sun Microsystems - Irvine United States 				break;
656b89a8333Snatalie li - Sun Microsystems - Irvine United States 
657b89a8333Snatalie li - Sun Microsystems - Irvine United States 			grl[n] = response ? gr : gr + 1;
658b89a8333Snatalie li - Sun Microsystems - Irvine United States 		}
659b89a8333Snatalie li - Sun Microsystems - Irvine United States 
660b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/*
661b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * Check the netgroup for each
662b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 * of the hosts names (usually just one).
663b89a8333Snatalie li - Sun Microsystems - Irvine United States 		 */
664b89a8333Snatalie li - Sun Microsystems - Irvine United States 		for (j = 0; j < nhosts && !belong; j++) {
665b89a8333Snatalie li - Sun Microsystems - Irvine United States 			host = clnames->h_hostservs[j].h_host;
666b89a8333Snatalie li - Sun Microsystems - Irvine United States 			if (__multi_innetgr(n, grl, 1, &host, 0, NULL,
667b89a8333Snatalie li - Sun Microsystems - Irvine United States 			    1, &domain))
668b89a8333Snatalie li - Sun Microsystems - Irvine United States 				belong = B_TRUE;
669b89a8333Snatalie li - Sun Microsystems - Irvine United States 		}
670b89a8333Snatalie li - Sun Microsystems - Irvine United States 	}
671b89a8333Snatalie li - Sun Microsystems - Irvine United States 
672b89a8333Snatalie li - Sun Microsystems - Irvine United States 	free(grl);
673b89a8333Snatalie li - Sun Microsystems - Irvine United States 	return (belong ? response : B_FALSE);
674b89a8333Snatalie li - Sun Microsystems - Irvine United States }
6756d57f833SAlan Wright 
6766d57f833SAlan Wright /*
6776d57f833SAlan Wright  * Resolve the ZFS dataset from a path.
67829bd2886SAlan Wright  * Returns,
67929bd2886SAlan Wright  *	0  = On success.
68029bd2886SAlan Wright  *	-1 = Failure to open /etc/mnttab file or to get ZFS dataset.
6816d57f833SAlan Wright  */
6826d57f833SAlan Wright int
6836d57f833SAlan Wright smb_getdataset(const char *path, char *dataset, size_t len)
6846d57f833SAlan Wright {
6856d57f833SAlan Wright 	char tmppath[MAXPATHLEN];
6866d57f833SAlan Wright 	char *cp;
6876d57f833SAlan Wright 	FILE *fp;
6886d57f833SAlan Wright 	struct mnttab mnttab;
6896d57f833SAlan Wright 	struct mnttab mntpref;
6906d57f833SAlan Wright 	int rc = -1;
6916d57f833SAlan Wright 
6926d57f833SAlan Wright 	if ((fp = fopen(MNTTAB, "r")) == NULL)
6936d57f833SAlan Wright 		return (-1);
6946d57f833SAlan Wright 
6956d57f833SAlan Wright 	(void) memset(&mnttab, '\0', sizeof (mnttab));
6966d57f833SAlan Wright 	(void) strlcpy(tmppath, path, MAXPATHLEN);
6976d57f833SAlan Wright 	cp = tmppath;
6986d57f833SAlan Wright 
6996d57f833SAlan Wright 	while (*cp != '\0') {
7006d57f833SAlan Wright 		resetmnttab(fp);
7016d57f833SAlan Wright 		(void) memset(&mntpref, '\0', sizeof (mntpref));
7026d57f833SAlan Wright 		mntpref.mnt_mountp = tmppath;
7036d57f833SAlan Wright 
7046d57f833SAlan Wright 		if (getmntany(fp, &mnttab, &mntpref) == 0) {
70529bd2886SAlan Wright 			if (mnttab.mnt_fstype == NULL)
70629bd2886SAlan Wright 				break;
70729bd2886SAlan Wright 
70829bd2886SAlan Wright 			if (strcmp(mnttab.mnt_fstype, "zfs") != 0)
70929bd2886SAlan Wright 				break;
7106d57f833SAlan Wright 			/*
7116d57f833SAlan Wright 			 * Ensure that there are no leading slashes
7126d57f833SAlan Wright 			 * (required for zfs_open).
7136d57f833SAlan Wright 			 */
7146d57f833SAlan Wright 			cp = mnttab.mnt_special;
7156d57f833SAlan Wright 			cp += strspn(cp, "/");
7166d57f833SAlan Wright 			(void) strlcpy(dataset, cp, len);
7176d57f833SAlan Wright 			rc = 0;
7186d57f833SAlan Wright 			break;
7196d57f833SAlan Wright 		}
7206d57f833SAlan Wright 
721fc724630SAlan Wright 		if (strcmp(tmppath, "/") == 0)
722fc724630SAlan Wright 			break;
723fc724630SAlan Wright 
724fc724630SAlan Wright 		if ((cp = strrchr(tmppath, '/')) == NULL)
725fc724630SAlan Wright 			break;
726fc724630SAlan Wright 
727fc724630SAlan Wright 		/*
728fc724630SAlan Wright 		 * The path has multiple components.
729fc724630SAlan Wright 		 * Remove the last component and try again.
730fc724630SAlan Wright 		 */
731fc724630SAlan Wright 		*cp = '\0';
732fc724630SAlan Wright 		if (tmppath[0] == '\0')
733fc724630SAlan Wright 			(void) strcpy(tmppath, "/");
7346d57f833SAlan Wright 
7356d57f833SAlan Wright 		cp = tmppath;
7366d57f833SAlan Wright 	}
7376d57f833SAlan Wright 
7386d57f833SAlan Wright 	(void) fclose(fp);
7396d57f833SAlan Wright 	return (rc);
7406d57f833SAlan Wright }
74129bd2886SAlan Wright 
7421fcced4cSJordan Brown /*
7431fcced4cSJordan Brown  * smb_dlopen
7441fcced4cSJordan Brown  *
7451fcced4cSJordan Brown  * Check to see if an interposer library exists.  If it exists
7461fcced4cSJordan Brown  * and reports a valid version number and key (UUID), return
7471fcced4cSJordan Brown  * a handle to the library.  Otherwise, return NULL.
7481fcced4cSJordan Brown  */
7491fcced4cSJordan Brown void *
7501fcced4cSJordan Brown smb_dlopen(void)
7511fcced4cSJordan Brown {
7521fcced4cSJordan Brown 	uuid_t uuid;
7531fcced4cSJordan Brown 	void *interposer_hdl;
7541fcced4cSJordan Brown 	typedef int (*smbex_versionfn_t)(smbex_version_t *);
7551fcced4cSJordan Brown 	smbex_versionfn_t getversion;
7561fcced4cSJordan Brown 	smbex_version_t *version;
7571fcced4cSJordan Brown 
7581fcced4cSJordan Brown 	bzero(&uuid, sizeof (uuid_t));
7591fcced4cSJordan Brown 	if (uuid_parse(SMBEX_KEY, uuid) < 0)
7601fcced4cSJordan Brown 		return (NULL);
7611fcced4cSJordan Brown 
7621fcced4cSJordan Brown 	interposer_hdl = dlopen(SMB_LIB_ALT, RTLD_NOW | RTLD_LOCAL);
7631fcced4cSJordan Brown 	if (interposer_hdl == NULL)
7641fcced4cSJordan Brown 		return (NULL);
7651fcced4cSJordan Brown 
7661fcced4cSJordan Brown 	bzero(&getversion, sizeof (smbex_versionfn_t));
7671fcced4cSJordan Brown 	getversion = (smbex_versionfn_t)dlsym(interposer_hdl,
7681fcced4cSJordan Brown 	    "smbex_get_version");
7691fcced4cSJordan Brown 	if ((getversion == NULL) ||
7701fcced4cSJordan Brown 	    (version = malloc(sizeof (smbex_version_t))) == NULL) {
7711fcced4cSJordan Brown 		(void) dlclose(interposer_hdl);
7721fcced4cSJordan Brown 		return (NULL);
7731fcced4cSJordan Brown 	}
7741fcced4cSJordan Brown 	bzero(version, sizeof (smbex_version_t));
7751fcced4cSJordan Brown 
7761fcced4cSJordan Brown 	if ((getversion(version) != 0) ||
7771fcced4cSJordan Brown 	    (version->v_version != SMBEX_VERSION) ||
7781fcced4cSJordan Brown 	    (uuid_compare(version->v_uuid, uuid) != 0)) {
7791fcced4cSJordan Brown 		free(version);
7801fcced4cSJordan Brown 		(void) dlclose(interposer_hdl);
7811fcced4cSJordan Brown 		return (NULL);
7821fcced4cSJordan Brown 	}
7831fcced4cSJordan Brown 
7841fcced4cSJordan Brown 	free(version);
7851fcced4cSJordan Brown 	return (interposer_hdl);
7861fcced4cSJordan Brown }
7871fcced4cSJordan Brown 
7881fcced4cSJordan Brown /*
7891fcced4cSJordan Brown  * smb_dlclose
7901fcced4cSJordan Brown  *
7911fcced4cSJordan Brown  * Closes handle to the interposed library.
7921fcced4cSJordan Brown  */
7931fcced4cSJordan Brown void
7941fcced4cSJordan Brown smb_dlclose(void *handle)
7951fcced4cSJordan Brown {
7961fcced4cSJordan Brown 	if (handle)
7971fcced4cSJordan Brown 		(void) dlclose(handle);
7981fcced4cSJordan Brown }
7991fcced4cSJordan Brown 
80029bd2886SAlan Wright /*
8019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * This function is a wrapper for getnameinfo() to look up a hostname given an
8029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * IP address. The hostname returned by this function is used for constructing
8039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * the service principal name field of KRB AP-REQs. Hence, it should be
8049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * converted to lowercase for RFC 4120 section 6.2.1 conformance.
80529bd2886SAlan Wright  */
80629bd2886SAlan Wright int
80729bd2886SAlan Wright smb_getnameinfo(smb_inaddr_t *ip, char *hostname, int hostlen, int flags)
80829bd2886SAlan Wright {
80929bd2886SAlan Wright 	socklen_t salen;
81029bd2886SAlan Wright 	struct sockaddr_in6 sin6;
81129bd2886SAlan Wright 	struct sockaddr_in sin;
81229bd2886SAlan Wright 	void *sp;
8139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int rc;
81429bd2886SAlan Wright 
81529bd2886SAlan Wright 	if (ip->a_family == AF_INET) {
81629bd2886SAlan Wright 		salen = sizeof (struct sockaddr_in);
81729bd2886SAlan Wright 		sin.sin_family = ip->a_family;
81829bd2886SAlan Wright 		sin.sin_port = 0;
81929bd2886SAlan Wright 		sin.sin_addr.s_addr = ip->a_ipv4;
82029bd2886SAlan Wright 		sp = &sin;
82129bd2886SAlan Wright 	} else {
82229bd2886SAlan Wright 		salen = sizeof (struct sockaddr_in6);
82329bd2886SAlan Wright 		sin6.sin6_family = ip->a_family;
82429bd2886SAlan Wright 		sin6.sin6_port = 0;
82529bd2886SAlan Wright 		(void) memcpy(&sin6.sin6_addr.s6_addr, &ip->a_ipv6,
82629bd2886SAlan Wright 		    sizeof (sin6.sin6_addr.s6_addr));
82729bd2886SAlan Wright 		sp = &sin6;
82829bd2886SAlan Wright 	}
8299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = (getnameinfo((struct sockaddr *)sp, salen,
8319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    hostname, hostlen, NULL, 0, flags))) == 0)
8329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) smb_strlwr(hostname);
8339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (rc);
83529bd2886SAlan Wright }
836fe1c642dSBill Krier 
837fe1c642dSBill Krier /*
838fe1c642dSBill Krier  * A share name is considered invalid if it contains control
839fe1c642dSBill Krier  * characters or any of the following characters (MSDN 236388).
840fe1c642dSBill Krier  *
841fe1c642dSBill Krier  *	" / \ [ ] : | < > + ; , ? * =
842fe1c642dSBill Krier  */
843fe1c642dSBill Krier uint32_t
844fe1c642dSBill Krier smb_name_validate_share(const char *sharename)
845fe1c642dSBill Krier {
846fe1c642dSBill Krier 	const char *invalid = "\"/\\[]:|<>+;,?*=";
847fe1c642dSBill Krier 	const char *p;
848fe1c642dSBill Krier 
849fe1c642dSBill Krier 	if (sharename == NULL)
850fe1c642dSBill Krier 		return (ERROR_INVALID_PARAMETER);
851fe1c642dSBill Krier 
852fe1c642dSBill Krier 	if (strpbrk(sharename, invalid) != NULL)
853fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
854fe1c642dSBill Krier 
855fe1c642dSBill Krier 	for (p = sharename; *p != '\0'; p++) {
856fe1c642dSBill Krier 		if (iscntrl(*p))
857fe1c642dSBill Krier 			return (ERROR_INVALID_NAME);
858fe1c642dSBill Krier 	}
859fe1c642dSBill Krier 
860fe1c642dSBill Krier 	return (ERROR_SUCCESS);
861fe1c642dSBill Krier }
862fe1c642dSBill Krier 
863fe1c642dSBill Krier /*
864fe1c642dSBill Krier  * User and group names are limited to 256 characters, cannot be terminated
865fe1c642dSBill Krier  * by '.' and must not contain control characters or any of the following
866fe1c642dSBill Krier  * characters.
867fe1c642dSBill Krier  *
868fe1c642dSBill Krier  *	" / \ [ ] < > + ; , ? * = @
869fe1c642dSBill Krier  */
870fe1c642dSBill Krier uint32_t
871fe1c642dSBill Krier smb_name_validate_account(const char *name)
872fe1c642dSBill Krier {
873fe1c642dSBill Krier 	const char	*invalid = "\"/\\[]<>+;,?*=@";
874fe1c642dSBill Krier 	const char	*p;
875fe1c642dSBill Krier 	int		len;
876fe1c642dSBill Krier 
877fe1c642dSBill Krier 	if ((name == NULL) || (*name == '\0'))
878fe1c642dSBill Krier 		return (ERROR_INVALID_PARAMETER);
879fe1c642dSBill Krier 
880fe1c642dSBill Krier 	len = strlen(name);
881fe1c642dSBill Krier 	if ((len > MAXNAMELEN) || (name[len - 1] == '.'))
882fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
883fe1c642dSBill Krier 
884fe1c642dSBill Krier 	if (strpbrk(name, invalid) != NULL)
885fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
886fe1c642dSBill Krier 
887fe1c642dSBill Krier 	for (p = name; *p != '\0'; p++) {
888fe1c642dSBill Krier 		if (iscntrl(*p))
889fe1c642dSBill Krier 			return (ERROR_INVALID_NAME);
890fe1c642dSBill Krier 	}
891fe1c642dSBill Krier 
892fe1c642dSBill Krier 	return (ERROR_SUCCESS);
893fe1c642dSBill Krier }
894fe1c642dSBill Krier 
895fe1c642dSBill Krier /*
896fe1c642dSBill Krier  * Check a domain name for RFC 1035 and 1123 compliance.  Domain names may
897fe1c642dSBill Krier  * contain alphanumeric characters, hyphens and dots.  The first and last
898fe1c642dSBill Krier  * character of a label must be alphanumeric.  Interior characters may be
899fe1c642dSBill Krier  * alphanumeric or hypens.
900fe1c642dSBill Krier  *
901fe1c642dSBill Krier  * Domain names should not contain underscores but we allow them because
902fe1c642dSBill Krier  * Windows names are often in non-compliance with this rule.
903fe1c642dSBill Krier  */
904fe1c642dSBill Krier uint32_t
905fe1c642dSBill Krier smb_name_validate_domain(const char *domain)
906fe1c642dSBill Krier {
907fe1c642dSBill Krier 	boolean_t new_label = B_TRUE;
908fe1c642dSBill Krier 	const char *p;
909fe1c642dSBill Krier 	char label_terminator;
910fe1c642dSBill Krier 
911fe1c642dSBill Krier 	if (domain == NULL)
912fe1c642dSBill Krier 		return (ERROR_INVALID_PARAMETER);
913fe1c642dSBill Krier 
914fe1c642dSBill Krier 	if (*domain == '\0')
915fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
916fe1c642dSBill Krier 
917fe1c642dSBill Krier 	label_terminator = *domain;
918fe1c642dSBill Krier 
919fe1c642dSBill Krier 	for (p = domain; *p != '\0'; ++p) {
920fe1c642dSBill Krier 		if (new_label) {
921fe1c642dSBill Krier 			if (!isalnum(*p))
922fe1c642dSBill Krier 				return (ERROR_INVALID_NAME);
923fe1c642dSBill Krier 			new_label = B_FALSE;
924fe1c642dSBill Krier 			label_terminator = *p;
925fe1c642dSBill Krier 			continue;
926fe1c642dSBill Krier 		}
927fe1c642dSBill Krier 
928fe1c642dSBill Krier 		if (*p == '.') {
929fe1c642dSBill Krier 			if (!isalnum(label_terminator))
930fe1c642dSBill Krier 				return (ERROR_INVALID_NAME);
931fe1c642dSBill Krier 			new_label = B_TRUE;
932fe1c642dSBill Krier 			label_terminator = *p;
933fe1c642dSBill Krier 			continue;
934fe1c642dSBill Krier 		}
935fe1c642dSBill Krier 
936fe1c642dSBill Krier 		label_terminator = *p;
937fe1c642dSBill Krier 
938fe1c642dSBill Krier 		if (isalnum(*p) || *p == '-' || *p == '_')
939fe1c642dSBill Krier 			continue;
940fe1c642dSBill Krier 
941fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
942fe1c642dSBill Krier 	}
943fe1c642dSBill Krier 
944fe1c642dSBill Krier 	if (!isalnum(label_terminator))
945fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
946fe1c642dSBill Krier 
947fe1c642dSBill Krier 	return (ERROR_SUCCESS);
948fe1c642dSBill Krier }
949fe1c642dSBill Krier 
950fe1c642dSBill Krier /*
951fe1c642dSBill Krier  * A NetBIOS domain name can contain letters (a-zA-Z), numbers (0-9) and
952fe1c642dSBill Krier  * hyphens.
953fe1c642dSBill Krier  *
954fe1c642dSBill Krier  * It cannot:
955fe1c642dSBill Krier  * 	- be blank or longer than 15 chracters
956fe1c642dSBill Krier  * 	- contain all numbers
957fe1c642dSBill Krier  * 	- be the same as the computer name
958fe1c642dSBill Krier  */
959fe1c642dSBill Krier uint32_t
960fe1c642dSBill Krier smb_name_validate_nbdomain(const char *name)
961fe1c642dSBill Krier {
962fe1c642dSBill Krier 	char		netbiosname[NETBIOS_NAME_SZ];
963fe1c642dSBill Krier 	const char	*p;
964fe1c642dSBill Krier 	int		len;
965fe1c642dSBill Krier 
966fe1c642dSBill Krier 	if (name == NULL)
967fe1c642dSBill Krier 		return (ERROR_INVALID_PARAMETER);
968fe1c642dSBill Krier 
969fe1c642dSBill Krier 	len = strlen(name);
970fe1c642dSBill Krier 	if (len == 0 || len >= NETBIOS_NAME_SZ)
971fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
972fe1c642dSBill Krier 
973fe1c642dSBill Krier 	if (strspn(name, "0123456789") == len)
974fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
975fe1c642dSBill Krier 
976fe1c642dSBill Krier 	if (smb_getnetbiosname(netbiosname, NETBIOS_NAME_SZ) == 0) {
977fe1c642dSBill Krier 		if (smb_strcasecmp(name, netbiosname, 0) == 0)
978fe1c642dSBill Krier 			return (ERROR_INVALID_NAME);
979fe1c642dSBill Krier 	}
980fe1c642dSBill Krier 
981fe1c642dSBill Krier 	for (p = name; *p != '\0'; ++p) {
982fe1c642dSBill Krier 		if (isalnum(*p) || *p == '-' || *p == '_')
983fe1c642dSBill Krier 			continue;
984fe1c642dSBill Krier 
985fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
986fe1c642dSBill Krier 	}
987fe1c642dSBill Krier 
988fe1c642dSBill Krier 	return (ERROR_SUCCESS);
989fe1c642dSBill Krier }
990fe1c642dSBill Krier 
991fe1c642dSBill Krier /*
992fe1c642dSBill Krier  * A workgroup name can contain 1 to 15 characters but cannot be the same
993fe1c642dSBill Krier  * as the NetBIOS name.  The name must begin with a letter or number.
994fe1c642dSBill Krier  *
995fe1c642dSBill Krier  * The name cannot consist entirely of spaces or dots, which is covered
996fe1c642dSBill Krier  * by the requirement that the name must begin with an alphanumeric
997fe1c642dSBill Krier  * character.
998fe1c642dSBill Krier  *
999fe1c642dSBill Krier  * The name must not contain control characters or any of the following
1000fe1c642dSBill Krier  * characters.
1001fe1c642dSBill Krier  *
1002fe1c642dSBill Krier  *	" / \ [ ] : | < > + = ; , ?
1003fe1c642dSBill Krier  */
1004fe1c642dSBill Krier uint32_t
1005fe1c642dSBill Krier smb_name_validate_workgroup(const char *workgroup)
1006fe1c642dSBill Krier {
1007fe1c642dSBill Krier 	char netbiosname[NETBIOS_NAME_SZ];
1008fe1c642dSBill Krier 	const char *invalid = "\"/\\[]:|<>+=;,?";
1009fe1c642dSBill Krier 	const char *p;
1010fe1c642dSBill Krier 
1011fe1c642dSBill Krier 	if (workgroup == NULL)
1012fe1c642dSBill Krier 		return (ERROR_INVALID_PARAMETER);
1013fe1c642dSBill Krier 
1014fe1c642dSBill Krier 	if (*workgroup == '\0' || (!isalnum(*workgroup)))
1015fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
1016fe1c642dSBill Krier 
1017fe1c642dSBill Krier 	if (strlen(workgroup) >= NETBIOS_NAME_SZ)
1018fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
1019fe1c642dSBill Krier 
1020fe1c642dSBill Krier 	if (smb_getnetbiosname(netbiosname, NETBIOS_NAME_SZ) == 0) {
1021fe1c642dSBill Krier 		if (smb_strcasecmp(workgroup, netbiosname, 0) == 0)
1022fe1c642dSBill Krier 			return (ERROR_INVALID_NAME);
1023fe1c642dSBill Krier 	}
1024fe1c642dSBill Krier 
1025fe1c642dSBill Krier 	if (strpbrk(workgroup, invalid) != NULL)
1026fe1c642dSBill Krier 		return (ERROR_INVALID_NAME);
1027fe1c642dSBill Krier 
1028fe1c642dSBill Krier 	for (p = workgroup; *p != '\0'; p++) {
1029fe1c642dSBill Krier 		if (iscntrl(*p))
1030fe1c642dSBill Krier 			return (ERROR_INVALID_NAME);
1031fe1c642dSBill Krier 	}
1032fe1c642dSBill Krier 
1033fe1c642dSBill Krier 	return (ERROR_SUCCESS);
1034fe1c642dSBill Krier }
1035fe1c642dSBill Krier 
10369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
10379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Check for invalid characters in the given path.  The list of invalid
10389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * characters includes control characters and the following:
10399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
10409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * " / \ [ ] : | < > + ; , ? * =
10419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
10429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Since this is checking a path not each component, '/' is accepted
10439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * as separator not an invalid character, except as the first character
10449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * since this is supposed to be a relative path.
10459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
10469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uint32_t
10479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_name_validate_rpath(const char *relpath)
10489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
10499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	char *invalid = "\"\\[]:|<>+;,?*=";
10509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	char *cp;
10519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((relpath == NULL) || (*relpath == '\0') || (*relpath == '/'))
10539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (ERROR_INVALID_NAME);
10549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (strpbrk(relpath, invalid))
10569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (ERROR_INVALID_NAME);
10579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	for (cp = (char *)relpath; *cp != '\0'; cp++) {
10599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (iscntrl(*cp))
10609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			return (ERROR_INVALID_NAME);
10619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
10629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (ERROR_SUCCESS);
10649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
10659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1066fe1c642dSBill Krier /*
1067fe1c642dSBill Krier  * Parse a string to obtain the account and domain names as separate strings.
1068fe1c642dSBill Krier  *
1069fe1c642dSBill Krier  * Names containing a backslash ('\') are known as qualified or composite
1070fe1c642dSBill Krier  * names.  The string preceding the backslash should be the domain name
1071fe1c642dSBill Krier  * and the string following the slash should be a name within that domain.
1072fe1c642dSBill Krier  *
1073fe1c642dSBill Krier  * Names that do not contain a backslash are known as isolated names.
1074fe1c642dSBill Krier  * An isolated name may be a single label, such as john, or may be in
1075fe1c642dSBill Krier  * user principal name (UPN) form, such as john@example.com.
1076fe1c642dSBill Krier  *
1077fe1c642dSBill Krier  *	domain\name
1078fe1c642dSBill Krier  *	domain/name
1079fe1c642dSBill Krier  *	name
1080fe1c642dSBill Krier  *	name@domain
1081fe1c642dSBill Krier  *
1082fe1c642dSBill Krier  * If we encounter any of the forms above in arg, the @, / or \ separator
1083fe1c642dSBill Krier  * is replaced by \0 and the name and domain pointers are set to point to
1084fe1c642dSBill Krier  * the appropriate components in arg.  Otherwise, name and domain pointers
1085fe1c642dSBill Krier  * will be set to NULL.
1086fe1c642dSBill Krier  */
1087fe1c642dSBill Krier void
1088fe1c642dSBill Krier smb_name_parse(char *arg, char **account, char **domain)
1089fe1c642dSBill Krier {
1090fe1c642dSBill Krier 	char *p;
1091fe1c642dSBill Krier 
1092fe1c642dSBill Krier 	*account = NULL;
1093fe1c642dSBill Krier 	*domain = NULL;
1094fe1c642dSBill Krier 
1095fe1c642dSBill Krier 	if ((p = strpbrk(arg, "/\\@")) != NULL) {
1096fe1c642dSBill Krier 		if (*p == '@') {
1097fe1c642dSBill Krier 			*p = '\0';
1098fe1c642dSBill Krier 			++p;
1099fe1c642dSBill Krier 			*domain = p;
1100fe1c642dSBill Krier 			*account = arg;
1101fe1c642dSBill Krier 		} else {
1102fe1c642dSBill Krier 			*p = '\0';
1103fe1c642dSBill Krier 			++p;
1104fe1c642dSBill Krier 			*account = p;
1105fe1c642dSBill Krier 			*domain = arg;
1106fe1c642dSBill Krier 		}
1107fe1c642dSBill Krier 	}
1108fe1c642dSBill Krier }
1109148c5f43SAlan Wright 
1110148c5f43SAlan Wright /*
1111148c5f43SAlan Wright  * The txid is an arbitrary transaction.  A new txid is returned on each call.
1112148c5f43SAlan Wright  *
1113148c5f43SAlan Wright  * 0 or -1 are not assigned so that they can be used to detect
1114148c5f43SAlan Wright  * invalid conditions.
1115148c5f43SAlan Wright  */
1116148c5f43SAlan Wright uint32_t
1117148c5f43SAlan Wright smb_get_txid(void)
1118148c5f43SAlan Wright {
1119148c5f43SAlan Wright 	static mutex_t	txmutex;
1120148c5f43SAlan Wright 	static uint32_t	txid;
1121148c5f43SAlan Wright 	uint32_t	txid_ret;
1122148c5f43SAlan Wright 
1123148c5f43SAlan Wright 	(void) mutex_lock(&txmutex);
1124148c5f43SAlan Wright 
1125148c5f43SAlan Wright 	if (txid == 0)
1126148c5f43SAlan Wright 		txid = time(NULL);
1127148c5f43SAlan Wright 
1128148c5f43SAlan Wright 	do {
1129148c5f43SAlan Wright 		++txid;
1130148c5f43SAlan Wright 	} while (txid == 0 || txid == (uint32_t)-1);
1131148c5f43SAlan Wright 
1132148c5f43SAlan Wright 	txid_ret = txid;
1133148c5f43SAlan Wright 	(void) mutex_unlock(&txmutex);
1134148c5f43SAlan Wright 
1135148c5f43SAlan Wright 	return (txid_ret);
1136148c5f43SAlan Wright }
1137148c5f43SAlan Wright 
1138148c5f43SAlan Wright /*
1139148c5f43SAlan Wright  *  Creates a log object and inserts it into a list of logs.
1140148c5f43SAlan Wright  */
1141148c5f43SAlan Wright smb_log_hdl_t
1142148c5f43SAlan Wright smb_log_create(int max_cnt, char *name)
1143148c5f43SAlan Wright {
1144148c5f43SAlan Wright 	smb_loglist_item_t *log_node;
1145148c5f43SAlan Wright 	smb_log_t *log = NULL;
1146148c5f43SAlan Wright 	smb_log_hdl_t handle = 0;
1147148c5f43SAlan Wright 
1148148c5f43SAlan Wright 	if (max_cnt <= 0 || name == NULL)
1149148c5f43SAlan Wright 		return (0);
1150148c5f43SAlan Wright 
1151148c5f43SAlan Wright 	(void) mutex_lock(&smb_loglist.ll_mtx);
1152148c5f43SAlan Wright 
1153148c5f43SAlan Wright 	log_node = malloc(sizeof (smb_loglist_item_t));
1154148c5f43SAlan Wright 
1155148c5f43SAlan Wright 	if (log_node != NULL) {
1156148c5f43SAlan Wright 		log = &log_node->lli_log;
1157148c5f43SAlan Wright 
1158148c5f43SAlan Wright 		bzero(log, sizeof (smb_log_t));
1159148c5f43SAlan Wright 
1160148c5f43SAlan Wright 		handle = log->l_handle = smb_get_txid();
1161148c5f43SAlan Wright 		log->l_max_cnt = max_cnt;
1162148c5f43SAlan Wright 		(void) snprintf(log->l_file, sizeof (log->l_file),
1163148c5f43SAlan Wright 		    SMB_LOG_FILE_FMT, name);
1164148c5f43SAlan Wright 
1165148c5f43SAlan Wright 		list_create(&log->l_list, sizeof (smb_log_item_t),
1166148c5f43SAlan Wright 		    offsetof(smb_log_item_t, li_lnd));
1167148c5f43SAlan Wright 
1168148c5f43SAlan Wright 		if (smb_loglist.ll_list.list_size == 0)
1169148c5f43SAlan Wright 			list_create(&smb_loglist.ll_list,
1170148c5f43SAlan Wright 			    sizeof (smb_loglist_item_t),
1171148c5f43SAlan Wright 			    offsetof(smb_loglist_item_t, lli_lnd));
1172148c5f43SAlan Wright 
1173148c5f43SAlan Wright 		list_insert_tail(&smb_loglist.ll_list, log_node);
1174148c5f43SAlan Wright 	}
1175148c5f43SAlan Wright 
1176148c5f43SAlan Wright 	(void) mutex_unlock(&smb_loglist.ll_mtx);
1177148c5f43SAlan Wright 
1178148c5f43SAlan Wright 	return (handle);
1179148c5f43SAlan Wright }
1180148c5f43SAlan Wright 
1181148c5f43SAlan Wright /*
1182148c5f43SAlan Wright  * Keep the most recent log entries, based on max count.
1183148c5f43SAlan Wright  * If the priority is LOG_ERR or higher then the entire log is
1184148c5f43SAlan Wright  * dumped to a file.
1185148c5f43SAlan Wright  *
1186148c5f43SAlan Wright  * The date format for each message is the same as a syslog entry.
1187148c5f43SAlan Wright  *
1188148c5f43SAlan Wright  * The log is also added to syslog via smb_log_trace().
1189148c5f43SAlan Wright  */
1190148c5f43SAlan Wright void
1191148c5f43SAlan Wright smb_log(smb_log_hdl_t hdl, int priority, const char *fmt, ...)
1192148c5f43SAlan Wright {
1193148c5f43SAlan Wright 	va_list		ap;
1194148c5f43SAlan Wright 	smb_log_t	*log;
1195148c5f43SAlan Wright 	smb_log_item_t	*msg;
1196148c5f43SAlan Wright 	time_t		now;
1197148c5f43SAlan Wright 	struct		tm *tm;
1198148c5f43SAlan Wright 	char		timebuf[SMB_TIMEBUF_SZ];
1199148c5f43SAlan Wright 	char		buf[SMB_TRACEBUF_SZ];
1200148c5f43SAlan Wright 	char		netbiosname[NETBIOS_NAME_SZ];
1201148c5f43SAlan Wright 	char		*pri_name;
1202148c5f43SAlan Wright 	int		i;
1203148c5f43SAlan Wright 
1204148c5f43SAlan Wright 	va_start(ap, fmt);
1205148c5f43SAlan Wright 	(void) vsnprintf(buf, SMB_TRACEBUF_SZ, fmt, ap);
1206148c5f43SAlan Wright 	va_end(ap);
1207148c5f43SAlan Wright 
1208148c5f43SAlan Wright 	priority &= LOG_PRIMASK;
1209148c5f43SAlan Wright 	smb_log_trace(priority, buf);
1210148c5f43SAlan Wright 
1211148c5f43SAlan Wright 	if ((log = smb_log_get(hdl)) == NULL)
1212148c5f43SAlan Wright 		return;
1213148c5f43SAlan Wright 
1214148c5f43SAlan Wright 	(void) mutex_lock(&log->l_mtx);
1215148c5f43SAlan Wright 
1216148c5f43SAlan Wright 	(void) time(&now);
1217148c5f43SAlan Wright 	tm = localtime(&now);
1218148c5f43SAlan Wright 	(void) strftime(timebuf, SMB_TIMEBUF_SZ, "%b %d %H:%M:%S", tm);
1219148c5f43SAlan Wright 
1220148c5f43SAlan Wright 	if (smb_getnetbiosname(netbiosname, NETBIOS_NAME_SZ) != 0)
1221148c5f43SAlan Wright 		(void) strlcpy(netbiosname, "unknown", NETBIOS_NAME_SZ);
1222148c5f43SAlan Wright 
1223148c5f43SAlan Wright 	if (log->l_cnt == log->l_max_cnt) {
1224148c5f43SAlan Wright 		msg = list_head(&log->l_list);
1225148c5f43SAlan Wright 		list_remove(&log->l_list, msg);
1226148c5f43SAlan Wright 	} else {
1227148c5f43SAlan Wright 		if ((msg = malloc(sizeof (smb_log_item_t))) == NULL) {
1228148c5f43SAlan Wright 			(void) mutex_unlock(&log->l_mtx);
1229148c5f43SAlan Wright 			return;
1230148c5f43SAlan Wright 		}
1231148c5f43SAlan Wright 		log->l_cnt++;
1232148c5f43SAlan Wright 	}
1233148c5f43SAlan Wright 
1234148c5f43SAlan Wright 	pri_name = "info";
1235148c5f43SAlan Wright 	for (i = 0; i < sizeof (smb_log_pri) / sizeof (smb_log_pri[0]); i++) {
1236148c5f43SAlan Wright 		if (priority == smb_log_pri[i].lp_value) {
1237148c5f43SAlan Wright 			pri_name = smb_log_pri[i].lp_name;
1238148c5f43SAlan Wright 			break;
1239148c5f43SAlan Wright 		}
1240148c5f43SAlan Wright 	}
1241148c5f43SAlan Wright 
1242148c5f43SAlan Wright 	(void) snprintf(msg->li_msg, SMB_LOG_LINE_SZ,
1243148c5f43SAlan Wright 	    "%s %s smb[%d]: [ID 0 daemon.%s] %s",
1244148c5f43SAlan Wright 	    timebuf, netbiosname, getpid(), pri_name, buf);
1245148c5f43SAlan Wright 	list_insert_tail(&log->l_list, msg);
1246148c5f43SAlan Wright 
1247148c5f43SAlan Wright 	if (priority <= LOG_ERR)
1248148c5f43SAlan Wright 		smb_log_dump(log);
1249148c5f43SAlan Wright 
1250148c5f43SAlan Wright 	(void) mutex_unlock(&log->l_mtx);
1251148c5f43SAlan Wright }
1252148c5f43SAlan Wright 
1253148c5f43SAlan Wright /*
1254148c5f43SAlan Wright  * Dumps all the logs in the log list.
1255148c5f43SAlan Wright  */
1256148c5f43SAlan Wright void
1257148c5f43SAlan Wright smb_log_dumpall()
1258148c5f43SAlan Wright {
1259148c5f43SAlan Wright 	smb_loglist_item_t *log_node;
1260148c5f43SAlan Wright 
1261148c5f43SAlan Wright 	(void) mutex_lock(&smb_loglist.ll_mtx);
1262148c5f43SAlan Wright 
1263148c5f43SAlan Wright 	log_node = list_head(&smb_loglist.ll_list);
1264148c5f43SAlan Wright 
1265148c5f43SAlan Wright 	while (log_node != NULL) {
1266148c5f43SAlan Wright 		smb_log_dump(&log_node->lli_log);
1267148c5f43SAlan Wright 		log_node = list_next(&smb_loglist.ll_list, log_node);
1268148c5f43SAlan Wright 	}
1269148c5f43SAlan Wright 
1270148c5f43SAlan Wright 	(void) mutex_unlock(&smb_loglist.ll_mtx);
1271148c5f43SAlan Wright }
1272148c5f43SAlan Wright 
1273148c5f43SAlan Wright static void
1274148c5f43SAlan Wright smb_log_trace(int priority, const char *s)
1275148c5f43SAlan Wright {
1276148c5f43SAlan Wright 	syslog(priority, "%s", s);
1277148c5f43SAlan Wright }
1278148c5f43SAlan Wright 
1279148c5f43SAlan Wright static smb_log_t *
1280148c5f43SAlan Wright smb_log_get(smb_log_hdl_t hdl)
1281148c5f43SAlan Wright {
1282148c5f43SAlan Wright 	smb_loglist_item_t *log_node;
1283148c5f43SAlan Wright 	smb_log_t *log;
1284148c5f43SAlan Wright 
1285148c5f43SAlan Wright 	(void) mutex_lock(&smb_loglist.ll_mtx);
1286148c5f43SAlan Wright 
1287148c5f43SAlan Wright 	log_node = list_head(&smb_loglist.ll_list);
1288148c5f43SAlan Wright 
1289148c5f43SAlan Wright 	while (log_node != NULL) {
1290148c5f43SAlan Wright 		if (log_node->lli_log.l_handle == hdl) {
1291148c5f43SAlan Wright 			log = &log_node->lli_log;
1292148c5f43SAlan Wright 			(void) mutex_unlock(&smb_loglist.ll_mtx);
1293148c5f43SAlan Wright 			return (log);
1294148c5f43SAlan Wright 		}
1295148c5f43SAlan Wright 		log_node = list_next(&smb_loglist.ll_list, log_node);
1296148c5f43SAlan Wright 	}
1297148c5f43SAlan Wright 
1298148c5f43SAlan Wright 	(void) mutex_unlock(&smb_loglist.ll_mtx);
1299148c5f43SAlan Wright 	return (NULL);
1300148c5f43SAlan Wright }
1301148c5f43SAlan Wright 
1302148c5f43SAlan Wright /*
1303148c5f43SAlan Wright  * Dumps the log to a file.
1304148c5f43SAlan Wright  */
1305148c5f43SAlan Wright static void
1306148c5f43SAlan Wright smb_log_dump(smb_log_t *log)
1307148c5f43SAlan Wright {
1308148c5f43SAlan Wright 	smb_log_item_t *msg;
1309148c5f43SAlan Wright 	FILE *fp;
1310148c5f43SAlan Wright 
1311148c5f43SAlan Wright 	if ((fp = fopen(log->l_file, "w")) == NULL)
1312148c5f43SAlan Wright 		return;
1313148c5f43SAlan Wright 
1314148c5f43SAlan Wright 	msg = list_head(&log->l_list);
1315148c5f43SAlan Wright 
1316148c5f43SAlan Wright 	while (msg != NULL) {
1317148c5f43SAlan Wright 		(void) fprintf(fp, "%s\n", msg->li_msg);
1318148c5f43SAlan Wright 		msg = list_next(&log->l_list, msg);
1319148c5f43SAlan Wright 	}
1320148c5f43SAlan Wright 
1321148c5f43SAlan Wright 	(void) fclose(fp);
1322148c5f43SAlan Wright }
1323