xref: /illumos-gate/usr/src/common/smbsrv/smb_match.c (revision bbf6f00c)
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 /*
223a6c5f83SAlan Wright  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw #ifndef _KERNEL
27da6c28aaSamw #include <stdlib.h>
28da6c28aaSamw #include <string.h>
29da6c28aaSamw #else
30da6c28aaSamw #include <sys/types.h>
31da6c28aaSamw #include <sys/sunddi.h>
32da6c28aaSamw #endif
33*bbf6f00cSJordan Brown #include <smbsrv/string.h>
34*bbf6f00cSJordan Brown #include <smbsrv/smb.h>
35da6c28aaSamw 
363a6c5f83SAlan Wright /*
373a6c5f83SAlan Wright  * Maximum recursion depth for the wildcard match functions.
383a6c5f83SAlan Wright  * These functions may recurse when processing a '*'.
393a6c5f83SAlan Wright  */
403a6c5f83SAlan Wright #define	SMB_MATCH_DEPTH_MAX	32
413a6c5f83SAlan Wright 
4294fff790SAlan Wright #define	SMB_CRC_POLYNOMIAL	0xD8B5D8B5
43da6c28aaSamw 
443a6c5f83SAlan Wright static int smb_match_private(const char *, const char *, int *);
453a6c5f83SAlan Wright static int smb_match_ci_private(const char *, const char *, int *);
463a6c5f83SAlan Wright 
47da6c28aaSamw /*
483a6c5f83SAlan Wright  * Returns:
493a6c5f83SAlan Wright  * 1	match
503a6c5f83SAlan Wright  * 0	no-match
51da6c28aaSamw  */
52da6c28aaSamw int
53da6c28aaSamw smb_match(char *patn, char *str)
54da6c28aaSamw {
553a6c5f83SAlan Wright 	int depth = 0;
563a6c5f83SAlan Wright 	int rc;
573a6c5f83SAlan Wright 
583a6c5f83SAlan Wright 	if ((rc = smb_match_private(patn, str, &depth)) == -1)
593a6c5f83SAlan Wright 		rc = 0;
603a6c5f83SAlan Wright 
613a6c5f83SAlan Wright 	return (rc);
623a6c5f83SAlan Wright }
633a6c5f83SAlan Wright 
643a6c5f83SAlan Wright /*
653a6c5f83SAlan Wright  * The '*' character matches multiple characters.
663a6c5f83SAlan Wright  * The '?' character matches a single character.
673a6c5f83SAlan Wright  *
683a6c5f83SAlan Wright  * If the pattern has trailing '?'s then it matches the specified number
693a6c5f83SAlan Wright  * of characters or less.  For example, "x??" matches "xab", "xa" and "x",
703a6c5f83SAlan Wright  * but not "xabc".
713a6c5f83SAlan Wright  *
723a6c5f83SAlan Wright  * Returns:
733a6c5f83SAlan Wright  * 1	match
743a6c5f83SAlan Wright  * 0	no-match
753a6c5f83SAlan Wright  * -1	no-match, too many wildcards in pattern
763a6c5f83SAlan Wright  */
773a6c5f83SAlan Wright static int
783a6c5f83SAlan Wright smb_match_private(const char *patn, const char *str, int *depth)
793a6c5f83SAlan Wright {
803a6c5f83SAlan Wright 	int rc;
813a6c5f83SAlan Wright 
82da6c28aaSamw 	for (;;) {
83da6c28aaSamw 		switch (*patn) {
84*bbf6f00cSJordan Brown 		case '\0':
85*bbf6f00cSJordan Brown 			return (*str == '\0');
86da6c28aaSamw 
87da6c28aaSamw 		case '?':
88da6c28aaSamw 			if (*str != 0) {
89da6c28aaSamw 				str++;
90da6c28aaSamw 				patn++;
91da6c28aaSamw 				continue;
92da6c28aaSamw 			} else {
93da6c28aaSamw 				return (0);
94da6c28aaSamw 			}
95da6c28aaSamw 			/*NOTREACHED*/
96da6c28aaSamw 
97da6c28aaSamw 		case '*':
983a6c5f83SAlan Wright 			patn += strspn(patn, "*");
99*bbf6f00cSJordan Brown 			if (*patn == '\0')
100da6c28aaSamw 				return (1);
101da6c28aaSamw 
1023a6c5f83SAlan Wright 			if ((*depth)++ >= SMB_MATCH_DEPTH_MAX)
1033a6c5f83SAlan Wright 				return (-1);
104da6c28aaSamw 
105da6c28aaSamw 			while (*str) {
1063a6c5f83SAlan Wright 				rc = smb_match_private(patn, str, depth);
1073a6c5f83SAlan Wright 				if (rc != 0)
1083a6c5f83SAlan Wright 					return (rc);
109da6c28aaSamw 				str++;
110da6c28aaSamw 			}
111da6c28aaSamw 			return (0);
112da6c28aaSamw 
113da6c28aaSamw 		default:
114da6c28aaSamw 			if (*str != *patn)
115da6c28aaSamw 				return (0);
116da6c28aaSamw 			str++;
117da6c28aaSamw 			patn++;
118da6c28aaSamw 			continue;
119da6c28aaSamw 		}
120da6c28aaSamw 	}
1213a6c5f83SAlan Wright 	/*NOTREACHED*/
122da6c28aaSamw }
123da6c28aaSamw 
124da6c28aaSamw int
125da6c28aaSamw smb_match83(char *patn, char *str83)
126da6c28aaSamw {
127da6c28aaSamw 	int	avail;
128da6c28aaSamw 	char	*ptr;
129da6c28aaSamw 	char	name83[14];
130da6c28aaSamw 
131da6c28aaSamw 	ptr = name83;
132*bbf6f00cSJordan Brown 	for (avail = SMB_NAME83_BASELEN;
133*bbf6f00cSJordan Brown 	    (avail > 0) && (*patn != '.') && (*patn != 0);
134da6c28aaSamw 	    avail--) {
135da6c28aaSamw 		*(ptr++) = *(patn++);
136da6c28aaSamw 	}
137da6c28aaSamw 	while (avail--)
138da6c28aaSamw 		*(ptr++) = ' ';
139da6c28aaSamw 	*(ptr++) = '.';
140da6c28aaSamw 
141da6c28aaSamw 	if (*patn == '.')
142da6c28aaSamw 		patn++;
143da6c28aaSamw 	else if (*patn != 0)
144da6c28aaSamw 		return (0);
145da6c28aaSamw 
146*bbf6f00cSJordan Brown 	for (avail = SMB_NAME83_EXTLEN; (avail > 0) && (*patn != 0); avail--) {
147da6c28aaSamw 		*(ptr++) = *(patn++);
148da6c28aaSamw 	}
149da6c28aaSamw 	if (*patn != 0)
150da6c28aaSamw 		return (0);
151da6c28aaSamw 
152da6c28aaSamw 	while (avail--)
153da6c28aaSamw 		*(ptr++) = ' ';
154da6c28aaSamw 	*ptr = 0;
155da6c28aaSamw 
156da6c28aaSamw 	return (smb_match_ci(name83, str83));
157da6c28aaSamw }
158da6c28aaSamw 
1593a6c5f83SAlan Wright /*
1603a6c5f83SAlan Wright  * Returns:
1613a6c5f83SAlan Wright  * 1	match
1623a6c5f83SAlan Wright  * 0	no-match
1633a6c5f83SAlan Wright  */
164da6c28aaSamw int
165da6c28aaSamw smb_match_ci(char *patn, char *str)
166da6c28aaSamw {
1673a6c5f83SAlan Wright 	int depth = 0;
1683a6c5f83SAlan Wright 	int rc;
1693a6c5f83SAlan Wright 
1703a6c5f83SAlan Wright 	if ((rc = smb_match_ci_private(patn, str, &depth)) == -1)
1713a6c5f83SAlan Wright 		rc = 0;
1723a6c5f83SAlan Wright 
1733a6c5f83SAlan Wright 	return (rc);
1743a6c5f83SAlan Wright }
1753a6c5f83SAlan Wright 
1763a6c5f83SAlan Wright /*
1773a6c5f83SAlan Wright  * The '*' character matches multiple characters.
1783a6c5f83SAlan Wright  * The '?' character matches a single character.
1793a6c5f83SAlan Wright  *
1803a6c5f83SAlan Wright  * If the pattern has trailing '?'s then it matches the specified number
1813a6c5f83SAlan Wright  * of characters or less.  For example, "x??" matches "xab", "xa" and "x",
1823a6c5f83SAlan Wright  * but not "xabc".
1833a6c5f83SAlan Wright  *
1843a6c5f83SAlan Wright  * Returns:
1853a6c5f83SAlan Wright  * 1	match
1863a6c5f83SAlan Wright  * 0	no-match
1873a6c5f83SAlan Wright  * -1	no-match, too many wildcards in pattern
1883a6c5f83SAlan Wright  */
1893a6c5f83SAlan Wright static int
1903a6c5f83SAlan Wright smb_match_ci_private(const char *patn, const char *str, int *depth)
1913a6c5f83SAlan Wright {
192*bbf6f00cSJordan Brown 	const char	*p;
193*bbf6f00cSJordan Brown 	smb_wchar_t	wc1, wc2;
194*bbf6f00cSJordan Brown 	int		nbytes1, nbytes2;
195*bbf6f00cSJordan Brown 	int		rc;
1963a6c5f83SAlan Wright 
197da6c28aaSamw 	/*
198da6c28aaSamw 	 * "<" is a special pattern that matches only those names that do
199da6c28aaSamw 	 * NOT have an extension. "." and ".." are ok.
200da6c28aaSamw 	 */
201da6c28aaSamw 	if (strcmp(patn, "<") == 0) {
202da6c28aaSamw 		if ((strcmp(str, ".") == 0) || (strcmp(str, "..") == 0))
203da6c28aaSamw 			return (1);
204da6c28aaSamw 		if (strchr(str, '.') == 0)
205da6c28aaSamw 			return (1);
206da6c28aaSamw 		return (0);
207da6c28aaSamw 	}
2083a6c5f83SAlan Wright 
209da6c28aaSamw 	for (;;) {
210da6c28aaSamw 		switch (*patn) {
211*bbf6f00cSJordan Brown 		case '\0':
212*bbf6f00cSJordan Brown 			return (*str == '\0');
213da6c28aaSamw 
214da6c28aaSamw 		case '?':
215da6c28aaSamw 			if (*str != 0) {
216da6c28aaSamw 				str++;
217da6c28aaSamw 				patn++;
218da6c28aaSamw 				continue;
219da6c28aaSamw 			} else {
2203a6c5f83SAlan Wright 				p = patn;
2213a6c5f83SAlan Wright 				p += strspn(p, "?");
2223a6c5f83SAlan Wright 				return ((*p == '\0') ? 1 : 0);
223da6c28aaSamw 			}
224da6c28aaSamw 			/*NOTREACHED*/
225da6c28aaSamw 
226da6c28aaSamw 		case '*':
2273a6c5f83SAlan Wright 			patn += strspn(patn, "*");
228*bbf6f00cSJordan Brown 			if (*patn == '\0')
229da6c28aaSamw 				return (1);
230da6c28aaSamw 
2313a6c5f83SAlan Wright 			if ((*depth)++ >= SMB_MATCH_DEPTH_MAX)
2323a6c5f83SAlan Wright 				return (-1);
2333a6c5f83SAlan Wright 
234da6c28aaSamw 			while (*str) {
2353a6c5f83SAlan Wright 				rc = smb_match_ci_private(patn, str, depth);
2363a6c5f83SAlan Wright 				if (rc != 0)
2373a6c5f83SAlan Wright 					return (rc);
238da6c28aaSamw 				str++;
239da6c28aaSamw 			}
240da6c28aaSamw 			return (0);
241da6c28aaSamw 
242da6c28aaSamw 		default:
243*bbf6f00cSJordan Brown 			nbytes1 = smb_mbtowc(&wc1, patn, MTS_MB_CHAR_MAX);
244*bbf6f00cSJordan Brown 			nbytes2 = smb_mbtowc(&wc2, str, MTS_MB_CHAR_MAX);
245*bbf6f00cSJordan Brown 			if ((nbytes1 == -1) || (nbytes2 == -1))
246*bbf6f00cSJordan Brown 				return (-1);
247da6c28aaSamw 
248*bbf6f00cSJordan Brown 			if (wc1 != wc2) {
249*bbf6f00cSJordan Brown 				wc1 = smb_tolower(wc1);
250*bbf6f00cSJordan Brown 				wc2 = smb_tolower(wc2);
251*bbf6f00cSJordan Brown 				if (wc1 != wc2)
252da6c28aaSamw 					return (0);
253da6c28aaSamw 			}
254*bbf6f00cSJordan Brown 
255*bbf6f00cSJordan Brown 			patn += nbytes1;
256*bbf6f00cSJordan Brown 			str += nbytes2;
257da6c28aaSamw 			continue;
258da6c28aaSamw 		}
259da6c28aaSamw 	}
2603a6c5f83SAlan Wright 	/*NOTREACHED*/
261da6c28aaSamw }
26294fff790SAlan Wright 
26394fff790SAlan Wright uint32_t
26494fff790SAlan Wright smb_crc_gen(uint8_t *buf, size_t len)
26594fff790SAlan Wright {
26694fff790SAlan Wright 	uint32_t crc = SMB_CRC_POLYNOMIAL;
26794fff790SAlan Wright 	uint8_t *p;
26894fff790SAlan Wright 	int i;
26994fff790SAlan Wright 
27094fff790SAlan Wright 	for (p = buf, i = 0; i < len; ++i, ++p) {
27194fff790SAlan Wright 		crc = (crc ^ (uint32_t)*p) + (crc << 12);
27294fff790SAlan Wright 
27394fff790SAlan Wright 		if (crc == 0 || crc == 0xFFFFFFFF)
27494fff790SAlan Wright 			crc = SMB_CRC_POLYNOMIAL;
27594fff790SAlan Wright 	}
27694fff790SAlan Wright 
27794fff790SAlan Wright 	return (crc);
27894fff790SAlan Wright }
279