xref: /titanic_44/usr/src/common/smbsrv/smb_match.c (revision 148c5f43199ca0b43fc8e3b643aab11cd66ea327)
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*148c5f43SAlan Wright  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23da6c28aaSamw  */
24da6c28aaSamw 
25da6c28aaSamw #ifndef _KERNEL
26da6c28aaSamw #include <stdlib.h>
27da6c28aaSamw #include <string.h>
28da6c28aaSamw #else
29da6c28aaSamw #include <sys/types.h>
30da6c28aaSamw #include <sys/sunddi.h>
31da6c28aaSamw #endif
32bbf6f00cSJordan Brown #include <smbsrv/string.h>
33bbf6f00cSJordan Brown #include <smbsrv/smb.h>
34da6c28aaSamw 
353a6c5f83SAlan Wright /*
363a6c5f83SAlan Wright  * Maximum recursion depth for the wildcard match functions.
373a6c5f83SAlan Wright  * These functions may recurse when processing a '*'.
383a6c5f83SAlan Wright  */
393a6c5f83SAlan Wright #define	SMB_MATCH_DEPTH_MAX	32
403a6c5f83SAlan Wright 
4194fff790SAlan Wright #define	SMB_CRC_POLYNOMIAL	0xD8B5D8B5
42da6c28aaSamw 
433a6c5f83SAlan Wright static int smb_match_private(const char *, const char *, int *);
443a6c5f83SAlan Wright static int smb_match_ci_private(const char *, const char *, int *);
453a6c5f83SAlan Wright 
46da6c28aaSamw /*
47*148c5f43SAlan Wright  * smb_match
48da6c28aaSamw  */
49*148c5f43SAlan Wright boolean_t
50da6c28aaSamw smb_match(char *patn, char *str)
51da6c28aaSamw {
523a6c5f83SAlan Wright 	int depth = 0;
533a6c5f83SAlan Wright 
54*148c5f43SAlan Wright 	return (smb_match_private(patn, str, &depth) == 1);
553a6c5f83SAlan Wright }
563a6c5f83SAlan Wright 
573a6c5f83SAlan Wright /*
583a6c5f83SAlan Wright  * The '*' character matches multiple characters.
593a6c5f83SAlan Wright  * The '?' character matches a single character.
603a6c5f83SAlan Wright  *
613a6c5f83SAlan Wright  * If the pattern has trailing '?'s then it matches the specified number
623a6c5f83SAlan Wright  * of characters or less.  For example, "x??" matches "xab", "xa" and "x",
633a6c5f83SAlan Wright  * but not "xabc".
643a6c5f83SAlan Wright  *
653a6c5f83SAlan Wright  * Returns:
663a6c5f83SAlan Wright  * 1	match
673a6c5f83SAlan Wright  * 0	no-match
683a6c5f83SAlan Wright  * -1	no-match, too many wildcards in pattern
693a6c5f83SAlan Wright  */
703a6c5f83SAlan Wright static int
713a6c5f83SAlan Wright smb_match_private(const char *patn, const char *str, int *depth)
723a6c5f83SAlan Wright {
733a6c5f83SAlan Wright 	int rc;
743a6c5f83SAlan Wright 
75da6c28aaSamw 	for (;;) {
76da6c28aaSamw 		switch (*patn) {
77bbf6f00cSJordan Brown 		case '\0':
78bbf6f00cSJordan Brown 			return (*str == '\0');
79da6c28aaSamw 
80da6c28aaSamw 		case '?':
81da6c28aaSamw 			if (*str != 0) {
82da6c28aaSamw 				str++;
83da6c28aaSamw 				patn++;
84da6c28aaSamw 				continue;
85da6c28aaSamw 			} else {
86da6c28aaSamw 				return (0);
87da6c28aaSamw 			}
88da6c28aaSamw 			/*NOTREACHED*/
89da6c28aaSamw 
90da6c28aaSamw 		case '*':
913a6c5f83SAlan Wright 			patn += strspn(patn, "*");
92bbf6f00cSJordan Brown 			if (*patn == '\0')
93da6c28aaSamw 				return (1);
94da6c28aaSamw 
953a6c5f83SAlan Wright 			if ((*depth)++ >= SMB_MATCH_DEPTH_MAX)
963a6c5f83SAlan Wright 				return (-1);
97da6c28aaSamw 
98da6c28aaSamw 			while (*str) {
993a6c5f83SAlan Wright 				rc = smb_match_private(patn, str, depth);
1003a6c5f83SAlan Wright 				if (rc != 0)
1013a6c5f83SAlan Wright 					return (rc);
102da6c28aaSamw 				str++;
103da6c28aaSamw 			}
104da6c28aaSamw 			return (0);
105da6c28aaSamw 
106da6c28aaSamw 		default:
107da6c28aaSamw 			if (*str != *patn)
108da6c28aaSamw 				return (0);
109da6c28aaSamw 			str++;
110da6c28aaSamw 			patn++;
111da6c28aaSamw 			continue;
112da6c28aaSamw 		}
113da6c28aaSamw 	}
1143a6c5f83SAlan Wright 	/*NOTREACHED*/
115da6c28aaSamw }
116da6c28aaSamw 
1173a6c5f83SAlan Wright /*
118*148c5f43SAlan Wright  * smb_match_ci
1193a6c5f83SAlan Wright  */
120*148c5f43SAlan Wright boolean_t
121da6c28aaSamw smb_match_ci(char *patn, char *str)
122da6c28aaSamw {
1233a6c5f83SAlan Wright 	int depth = 0;
1243a6c5f83SAlan Wright 
125*148c5f43SAlan Wright 	return (smb_match_ci_private(patn, str, &depth) == 1);
1263a6c5f83SAlan Wright }
1273a6c5f83SAlan Wright 
1283a6c5f83SAlan Wright /*
1293a6c5f83SAlan Wright  * The '*' character matches multiple characters.
1303a6c5f83SAlan Wright  * The '?' character matches a single character.
1313a6c5f83SAlan Wright  *
1323a6c5f83SAlan Wright  * If the pattern has trailing '?'s then it matches the specified number
1333a6c5f83SAlan Wright  * of characters or less.  For example, "x??" matches "xab", "xa" and "x",
1343a6c5f83SAlan Wright  * but not "xabc".
1353a6c5f83SAlan Wright  *
1363a6c5f83SAlan Wright  * Returns:
1373a6c5f83SAlan Wright  * 1	match
1383a6c5f83SAlan Wright  * 0	no-match
1393a6c5f83SAlan Wright  * -1	no-match, too many wildcards in pattern
1403a6c5f83SAlan Wright  */
1413a6c5f83SAlan Wright static int
1423a6c5f83SAlan Wright smb_match_ci_private(const char *patn, const char *str, int *depth)
1433a6c5f83SAlan Wright {
1443a6c5f83SAlan Wright 	const char	*p;
145bbf6f00cSJordan Brown 	smb_wchar_t	wc1, wc2;
146bbf6f00cSJordan Brown 	int		nbytes1, nbytes2;
1473a6c5f83SAlan Wright 	int		rc;
1483a6c5f83SAlan Wright 
149da6c28aaSamw 	/*
150da6c28aaSamw 	 * "<" is a special pattern that matches only those names that do
151da6c28aaSamw 	 * NOT have an extension. "." and ".." are ok.
152da6c28aaSamw 	 */
153da6c28aaSamw 	if (strcmp(patn, "<") == 0) {
154da6c28aaSamw 		if ((strcmp(str, ".") == 0) || (strcmp(str, "..") == 0))
155da6c28aaSamw 			return (1);
156da6c28aaSamw 		if (strchr(str, '.') == 0)
157da6c28aaSamw 			return (1);
158da6c28aaSamw 		return (0);
159da6c28aaSamw 	}
1603a6c5f83SAlan Wright 
161da6c28aaSamw 	for (;;) {
162da6c28aaSamw 		switch (*patn) {
163bbf6f00cSJordan Brown 		case '\0':
164bbf6f00cSJordan Brown 			return (*str == '\0');
165da6c28aaSamw 
166da6c28aaSamw 		case '?':
167da6c28aaSamw 			if (*str != 0) {
168da6c28aaSamw 				str++;
169da6c28aaSamw 				patn++;
170da6c28aaSamw 				continue;
171da6c28aaSamw 			} else {
1723a6c5f83SAlan Wright 				p = patn;
1733a6c5f83SAlan Wright 				p += strspn(p, "?");
1743a6c5f83SAlan Wright 				return ((*p == '\0') ? 1 : 0);
175da6c28aaSamw 			}
176da6c28aaSamw 			/*NOTREACHED*/
177da6c28aaSamw 
178da6c28aaSamw 		case '*':
1793a6c5f83SAlan Wright 			patn += strspn(patn, "*");
180bbf6f00cSJordan Brown 			if (*patn == '\0')
181da6c28aaSamw 				return (1);
182da6c28aaSamw 
1833a6c5f83SAlan Wright 			if ((*depth)++ >= SMB_MATCH_DEPTH_MAX)
1843a6c5f83SAlan Wright 				return (-1);
1853a6c5f83SAlan Wright 
186da6c28aaSamw 			while (*str) {
1873a6c5f83SAlan Wright 				rc = smb_match_ci_private(patn, str, depth);
1883a6c5f83SAlan Wright 				if (rc != 0)
1893a6c5f83SAlan Wright 					return (rc);
190da6c28aaSamw 				str++;
191da6c28aaSamw 			}
192da6c28aaSamw 			return (0);
193da6c28aaSamw 
194da6c28aaSamw 		default:
195bbf6f00cSJordan Brown 			nbytes1 = smb_mbtowc(&wc1, patn, MTS_MB_CHAR_MAX);
196bbf6f00cSJordan Brown 			nbytes2 = smb_mbtowc(&wc2, str, MTS_MB_CHAR_MAX);
197bbf6f00cSJordan Brown 			if ((nbytes1 == -1) || (nbytes2 == -1))
198bbf6f00cSJordan Brown 				return (-1);
199da6c28aaSamw 
200bbf6f00cSJordan Brown 			if (wc1 != wc2) {
201bbf6f00cSJordan Brown 				wc1 = smb_tolower(wc1);
202bbf6f00cSJordan Brown 				wc2 = smb_tolower(wc2);
203bbf6f00cSJordan Brown 				if (wc1 != wc2)
204da6c28aaSamw 					return (0);
205da6c28aaSamw 			}
206bbf6f00cSJordan Brown 
207bbf6f00cSJordan Brown 			patn += nbytes1;
208bbf6f00cSJordan Brown 			str += nbytes2;
209da6c28aaSamw 			continue;
210da6c28aaSamw 		}
211da6c28aaSamw 	}
212da6c28aaSamw 	/*NOTREACHED*/
213da6c28aaSamw }
21494fff790SAlan Wright 
21594fff790SAlan Wright uint32_t
21694fff790SAlan Wright smb_crc_gen(uint8_t *buf, size_t len)
21794fff790SAlan Wright {
21894fff790SAlan Wright 	uint32_t crc = SMB_CRC_POLYNOMIAL;
21994fff790SAlan Wright 	uint8_t *p;
22094fff790SAlan Wright 	int i;
22194fff790SAlan Wright 
22294fff790SAlan Wright 	for (p = buf, i = 0; i < len; ++i, ++p) {
22394fff790SAlan Wright 		crc = (crc ^ (uint32_t)*p) + (crc << 12);
22494fff790SAlan Wright 
22594fff790SAlan Wright 		if (crc == 0 || crc == 0xFFFFFFFF)
22694fff790SAlan Wright 			crc = SMB_CRC_POLYNOMIAL;
22794fff790SAlan Wright 	}
22894fff790SAlan Wright 
22994fff790SAlan Wright 	return (crc);
23094fff790SAlan Wright }
231