xref: /illumos-gate/usr/src/common/smbsrv/smb_match.c (revision 3a6c5f83)
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 /*
22*3a6c5f83SAlan 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
33da6c28aaSamw #include <smbsrv/ctype.h>
34da6c28aaSamw 
35*3a6c5f83SAlan Wright /*
36*3a6c5f83SAlan Wright  * Maximum recursion depth for the wildcard match functions.
37*3a6c5f83SAlan Wright  * These functions may recurse when processing a '*'.
38*3a6c5f83SAlan Wright  */
39*3a6c5f83SAlan Wright #define	SMB_MATCH_DEPTH_MAX	32
40*3a6c5f83SAlan Wright 
4194fff790SAlan Wright #define	SMB_CRC_POLYNOMIAL	0xD8B5D8B5
42da6c28aaSamw 
43*3a6c5f83SAlan Wright static int smb_match_private(const char *, const char *, int *);
44*3a6c5f83SAlan Wright static int smb_match_ci_private(const char *, const char *, int *);
45*3a6c5f83SAlan Wright 
46da6c28aaSamw /*
47*3a6c5f83SAlan Wright  * Returns:
48*3a6c5f83SAlan Wright  * 1	match
49*3a6c5f83SAlan Wright  * 0	no-match
50da6c28aaSamw  */
51da6c28aaSamw int
52da6c28aaSamw smb_match(char *patn, char *str)
53da6c28aaSamw {
54*3a6c5f83SAlan Wright 	int depth = 0;
55*3a6c5f83SAlan Wright 	int rc;
56*3a6c5f83SAlan Wright 
57*3a6c5f83SAlan Wright 	if ((rc = smb_match_private(patn, str, &depth)) == -1)
58*3a6c5f83SAlan Wright 		rc = 0;
59*3a6c5f83SAlan Wright 
60*3a6c5f83SAlan Wright 	return (rc);
61*3a6c5f83SAlan Wright }
62*3a6c5f83SAlan Wright 
63*3a6c5f83SAlan Wright /*
64*3a6c5f83SAlan Wright  * The '*' character matches multiple characters.
65*3a6c5f83SAlan Wright  * The '?' character matches a single character.
66*3a6c5f83SAlan Wright  *
67*3a6c5f83SAlan Wright  * If the pattern has trailing '?'s then it matches the specified number
68*3a6c5f83SAlan Wright  * of characters or less.  For example, "x??" matches "xab", "xa" and "x",
69*3a6c5f83SAlan Wright  * but not "xabc".
70*3a6c5f83SAlan Wright  *
71*3a6c5f83SAlan Wright  * Returns:
72*3a6c5f83SAlan Wright  * 1	match
73*3a6c5f83SAlan Wright  * 0	no-match
74*3a6c5f83SAlan Wright  * -1	no-match, too many wildcards in pattern
75*3a6c5f83SAlan Wright  */
76*3a6c5f83SAlan Wright static int
77*3a6c5f83SAlan Wright smb_match_private(const char *patn, const char *str, int *depth)
78*3a6c5f83SAlan Wright {
79*3a6c5f83SAlan Wright 	int rc;
80*3a6c5f83SAlan Wright 
81da6c28aaSamw 	for (;;) {
82da6c28aaSamw 		switch (*patn) {
83da6c28aaSamw 		case 0:
84da6c28aaSamw 			return (*str == 0);
85da6c28aaSamw 
86da6c28aaSamw 		case '?':
87da6c28aaSamw 			if (*str != 0) {
88da6c28aaSamw 				str++;
89da6c28aaSamw 				patn++;
90da6c28aaSamw 				continue;
91da6c28aaSamw 			} else {
92da6c28aaSamw 				return (0);
93da6c28aaSamw 			}
94da6c28aaSamw 			/*NOTREACHED*/
95da6c28aaSamw 
96da6c28aaSamw 		case '*':
97*3a6c5f83SAlan Wright 			patn += strspn(patn, "*");
98da6c28aaSamw 			if (*patn == 0)
99da6c28aaSamw 				return (1);
100da6c28aaSamw 
101*3a6c5f83SAlan Wright 			if ((*depth)++ >= SMB_MATCH_DEPTH_MAX)
102*3a6c5f83SAlan Wright 				return (-1);
103da6c28aaSamw 
104da6c28aaSamw 			while (*str) {
105*3a6c5f83SAlan Wright 				rc = smb_match_private(patn, str, depth);
106*3a6c5f83SAlan Wright 				if (rc != 0)
107*3a6c5f83SAlan Wright 					return (rc);
108da6c28aaSamw 				str++;
109da6c28aaSamw 			}
110da6c28aaSamw 			return (0);
111da6c28aaSamw 
112da6c28aaSamw 		default:
113da6c28aaSamw 			if (*str != *patn)
114da6c28aaSamw 				return (0);
115da6c28aaSamw 			str++;
116da6c28aaSamw 			patn++;
117da6c28aaSamw 			continue;
118da6c28aaSamw 		}
119da6c28aaSamw 	}
120*3a6c5f83SAlan Wright 	/*NOTREACHED*/
121da6c28aaSamw }
122da6c28aaSamw 
123da6c28aaSamw int
124da6c28aaSamw smb_match83(char *patn, char *str83)
125da6c28aaSamw {
126da6c28aaSamw 	int	avail;
127da6c28aaSamw 	char	*ptr;
128da6c28aaSamw 	char	name83[14];
129da6c28aaSamw 
130da6c28aaSamw 	ptr = name83;
131da6c28aaSamw 	for (avail = 8; (avail > 0) && (*patn != '.') && (*patn != 0);
132da6c28aaSamw 	    avail--) {
133da6c28aaSamw 		*(ptr++) = *(patn++);
134da6c28aaSamw 	}
135da6c28aaSamw 	while (avail--)
136da6c28aaSamw 		*(ptr++) = ' ';
137da6c28aaSamw 	*(ptr++) = '.';
138da6c28aaSamw 
139da6c28aaSamw 	if (*patn == '.')
140da6c28aaSamw 		patn++;
141da6c28aaSamw 	else if (*patn != 0)
142da6c28aaSamw 		return (0);
143da6c28aaSamw 
144da6c28aaSamw 	for (avail = 3; (avail > 0) && (*patn != 0); avail--) {
145da6c28aaSamw 		*(ptr++) = *(patn++);
146da6c28aaSamw 	}
147da6c28aaSamw 	if (*patn != 0)
148da6c28aaSamw 		return (0);
149da6c28aaSamw 
150da6c28aaSamw 	while (avail--)
151da6c28aaSamw 		*(ptr++) = ' ';
152da6c28aaSamw 	*ptr = 0;
153da6c28aaSamw 
154da6c28aaSamw 	return (smb_match_ci(name83, str83));
155da6c28aaSamw }
156da6c28aaSamw 
157*3a6c5f83SAlan Wright /*
158*3a6c5f83SAlan Wright  * Returns:
159*3a6c5f83SAlan Wright  * 1	match
160*3a6c5f83SAlan Wright  * 0	no-match
161*3a6c5f83SAlan Wright  */
162da6c28aaSamw int
163da6c28aaSamw smb_match_ci(char *patn, char *str)
164da6c28aaSamw {
165*3a6c5f83SAlan Wright 	int depth = 0;
166*3a6c5f83SAlan Wright 	int rc;
167*3a6c5f83SAlan Wright 
168*3a6c5f83SAlan Wright 	if ((rc = smb_match_ci_private(patn, str, &depth)) == -1)
169*3a6c5f83SAlan Wright 		rc = 0;
170*3a6c5f83SAlan Wright 
171*3a6c5f83SAlan Wright 	return (rc);
172*3a6c5f83SAlan Wright }
173*3a6c5f83SAlan Wright 
174*3a6c5f83SAlan Wright /*
175*3a6c5f83SAlan Wright  * The '*' character matches multiple characters.
176*3a6c5f83SAlan Wright  * The '?' character matches a single character.
177*3a6c5f83SAlan Wright  *
178*3a6c5f83SAlan Wright  * If the pattern has trailing '?'s then it matches the specified number
179*3a6c5f83SAlan Wright  * of characters or less.  For example, "x??" matches "xab", "xa" and "x",
180*3a6c5f83SAlan Wright  * but not "xabc".
181*3a6c5f83SAlan Wright  *
182*3a6c5f83SAlan Wright  * Returns:
183*3a6c5f83SAlan Wright  * 1	match
184*3a6c5f83SAlan Wright  * 0	no-match
185*3a6c5f83SAlan Wright  * -1	no-match, too many wildcards in pattern
186*3a6c5f83SAlan Wright  */
187*3a6c5f83SAlan Wright static int
188*3a6c5f83SAlan Wright smb_match_ci_private(const char *patn, const char *str, int *depth)
189*3a6c5f83SAlan Wright {
190*3a6c5f83SAlan Wright 	const char *p;
191*3a6c5f83SAlan Wright 	int rc;
192*3a6c5f83SAlan Wright 
193da6c28aaSamw 	/*
194da6c28aaSamw 	 * "<" is a special pattern that matches only those names that do
195da6c28aaSamw 	 * NOT have an extension. "." and ".." are ok.
196da6c28aaSamw 	 */
197da6c28aaSamw 	if (strcmp(patn, "<") == 0) {
198da6c28aaSamw 		if ((strcmp(str, ".") == 0) || (strcmp(str, "..") == 0))
199da6c28aaSamw 			return (1);
200da6c28aaSamw 		if (strchr(str, '.') == 0)
201da6c28aaSamw 			return (1);
202da6c28aaSamw 		return (0);
203da6c28aaSamw 	}
204*3a6c5f83SAlan Wright 
205da6c28aaSamw 	for (;;) {
206da6c28aaSamw 		switch (*patn) {
207da6c28aaSamw 		case 0:
208da6c28aaSamw 			return (*str == 0);
209da6c28aaSamw 
210da6c28aaSamw 		case '?':
211da6c28aaSamw 			if (*str != 0) {
212da6c28aaSamw 				str++;
213da6c28aaSamw 				patn++;
214da6c28aaSamw 				continue;
215da6c28aaSamw 			} else {
216*3a6c5f83SAlan Wright 				p = patn;
217*3a6c5f83SAlan Wright 				p += strspn(p, "?");
218*3a6c5f83SAlan Wright 				return ((*p == '\0') ? 1 : 0);
219da6c28aaSamw 			}
220da6c28aaSamw 			/*NOTREACHED*/
221da6c28aaSamw 
222da6c28aaSamw 		case '*':
223*3a6c5f83SAlan Wright 			patn += strspn(patn, "*");
224da6c28aaSamw 			if (*patn == 0)
225da6c28aaSamw 				return (1);
226da6c28aaSamw 
227*3a6c5f83SAlan Wright 			if ((*depth)++ >= SMB_MATCH_DEPTH_MAX)
228*3a6c5f83SAlan Wright 				return (-1);
229*3a6c5f83SAlan Wright 
230da6c28aaSamw 			while (*str) {
231*3a6c5f83SAlan Wright 				rc = smb_match_ci_private(patn, str, depth);
232*3a6c5f83SAlan Wright 				if (rc != 0)
233*3a6c5f83SAlan Wright 					return (rc);
234da6c28aaSamw 				str++;
235da6c28aaSamw 			}
236da6c28aaSamw 			return (0);
237da6c28aaSamw 
238da6c28aaSamw 		default:
239da6c28aaSamw 			if (*str != *patn) {
240da6c28aaSamw 				int	c1 = *str;
241da6c28aaSamw 				int	c2 = *patn;
242da6c28aaSamw 
243da6c28aaSamw 				c1 = mts_tolower(c1);
244da6c28aaSamw 				c2 = mts_tolower(c2);
245da6c28aaSamw 				if (c1 != c2)
246da6c28aaSamw 					return (0);
247da6c28aaSamw 			}
248da6c28aaSamw 			str++;
249da6c28aaSamw 			patn++;
250da6c28aaSamw 			continue;
251da6c28aaSamw 		}
252da6c28aaSamw 	}
253*3a6c5f83SAlan Wright 	/*NOTREACHED*/
254da6c28aaSamw }
25594fff790SAlan Wright 
25694fff790SAlan Wright uint32_t
25794fff790SAlan Wright smb_crc_gen(uint8_t *buf, size_t len)
25894fff790SAlan Wright {
25994fff790SAlan Wright 	uint32_t crc = SMB_CRC_POLYNOMIAL;
26094fff790SAlan Wright 	uint8_t *p;
26194fff790SAlan Wright 	int i;
26294fff790SAlan Wright 
26394fff790SAlan Wright 	for (p = buf, i = 0; i < len; ++i, ++p) {
26494fff790SAlan Wright 		crc = (crc ^ (uint32_t)*p) + (crc << 12);
26594fff790SAlan Wright 
26694fff790SAlan Wright 		if (crc == 0 || crc == 0xFFFFFFFF)
26794fff790SAlan Wright 			crc = SMB_CRC_POLYNOMIAL;
26894fff790SAlan Wright 	}
26994fff790SAlan Wright 
27094fff790SAlan Wright 	return (crc);
27194fff790SAlan Wright }
272