xref: /illumos-gate/usr/src/common/smbsrv/smb_match.c (revision 8c067cfd3aea0c49a166f9fb38114b56a9160ac6)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _KERNEL
27 #include <stdlib.h>
28 #include <string.h>
29 #else
30 #include <sys/types.h>
31 #include <sys/sunddi.h>
32 #endif
33 #include <smbsrv/ctype.h>
34 
35 #define	SMB_CRC_POLYNOMIAL	0xD8B5D8B5
36 
37 /*
38  *	c	Any non-special character matches itslef
39  *	?	Match any character
40  *	ab	character 'a' followed by character 'b'
41  *	S	Any string of non-special characters
42  *	AB	String 'A' followed by string 'B'
43  *	*	Any String, including the empty string
44  */
45 int
46 smb_match(char *patn, char *str)
47 {
48 	for (;;) {
49 		switch (*patn) {
50 		case 0:
51 			return (*str == 0);
52 
53 		case '?':
54 			if (*str != 0) {
55 				str++;
56 				patn++;
57 				continue;
58 			} else {
59 				return (0);
60 			}
61 			/*NOTREACHED*/
62 
63 #if 0
64 		case '[':
65 			int	invert = 0, clower, cupper;
66 
67 			patn++;
68 			if (*patn == '!') {
69 				invert = 1;
70 				patn++;
71 			}
72 			for (;;) {
73 				clower = *patn;
74 				if (clower == 0)
75 					break;
76 				if (clower == ']') {
77 					patn++;
78 					break;
79 				}
80 				patn++;
81 				if (*patn == '-') {
82 					/* range */
83 					patn++;
84 					cupper = *patn;
85 					if (cupper == 0)
86 						break;
87 					patn++;
88 				} else {
89 					cupper = clower;
90 				}
91 				if (*str < clower || cupper < *str)
92 					continue;
93 
94 				/* match */
95 				if (invert)
96 					return (0);
97 
98 				while (*patn && *patn++ != ']')
99 					;
100 				str++;
101 				continue; /* THIS WON`T WORK */
102 			}
103 			if (invert) {
104 				str++;
105 				continue;
106 			}
107 			return (0);
108 
109 #endif
110 
111 		case '*':
112 			patn++;
113 			if (*patn == 0)
114 				return (1);
115 
116 #if 0
117 			if (*patn != '?' && *patn != '*' && *patn != '[') {
118 				/* accelerate */
119 				while (*str) {
120 					if (*str == *patn &&
121 					    match(patn+1, str+1))
122 						return (1);
123 					str++;
124 				}
125 				return (0);
126 			}
127 #endif
128 
129 			while (*str) {
130 				if (smb_match(patn, str))
131 					return (1);
132 				str++;
133 			}
134 			return (0);
135 
136 		default:
137 			if (*str != *patn)
138 				return (0);
139 			str++;
140 			patn++;
141 			continue;
142 		}
143 	}
144 }
145 
146 int
147 smb_match83(char *patn, char *str83)
148 {
149 	int	avail;
150 	char	*ptr;
151 	char	name83[14];
152 
153 	ptr = name83;
154 	for (avail = 8; (avail > 0) && (*patn != '.') && (*patn != 0);
155 	    avail--) {
156 		*(ptr++) = *(patn++);
157 	}
158 	while (avail--)
159 		*(ptr++) = ' ';
160 	*(ptr++) = '.';
161 
162 	if (*patn == '.')
163 		patn++;
164 	else if (*patn != 0)
165 		return (0);
166 
167 	for (avail = 3; (avail > 0) && (*patn != 0); avail--) {
168 		*(ptr++) = *(patn++);
169 	}
170 	if (*patn != 0)
171 		return (0);
172 
173 	while (avail--)
174 		*(ptr++) = ' ';
175 	*ptr = 0;
176 
177 	return (smb_match_ci(name83, str83));
178 }
179 
180 
181 
182 int
183 smb_match_ci(char *patn, char *str)
184 {
185 	/*
186 	 * "<" is a special pattern that matches only those names that do
187 	 * NOT have an extension. "." and ".." are ok.
188 	 */
189 	if (strcmp(patn, "<") == 0) {
190 		if ((strcmp(str, ".") == 0) || (strcmp(str, "..") == 0))
191 			return (1);
192 		if (strchr(str, '.') == 0)
193 			return (1);
194 		return (0);
195 	}
196 	for (;;) {
197 		switch (*patn) {
198 		case 0:
199 			return (*str == 0);
200 
201 		case '?':
202 			if (*str != 0) {
203 				str++;
204 				patn++;
205 				continue;
206 			} else {
207 				return (0);
208 			}
209 			/*NOTREACHED*/
210 
211 
212 		case '*':
213 			patn++;
214 			if (*patn == 0)
215 				return (1);
216 
217 			while (*str) {
218 				if (smb_match_ci(patn, str))
219 					return (1);
220 				str++;
221 			}
222 			return (0);
223 
224 		default:
225 			if (*str != *patn) {
226 				int	c1 = *str;
227 				int	c2 = *patn;
228 
229 				c1 = mts_tolower(c1);
230 				c2 = mts_tolower(c2);
231 				if (c1 != c2)
232 					return (0);
233 			}
234 			str++;
235 			patn++;
236 			continue;
237 		}
238 	}
239 	/* NOT REACHED */
240 }
241 
242 uint32_t
243 smb_crc_gen(uint8_t *buf, size_t len)
244 {
245 	uint32_t crc = SMB_CRC_POLYNOMIAL;
246 	uint8_t *p;
247 	int i;
248 
249 	for (p = buf, i = 0; i < len; ++i, ++p) {
250 		crc = (crc ^ (uint32_t)*p) + (crc << 12);
251 
252 		if (crc == 0 || crc == 0xFFFFFFFF)
253 			crc = SMB_CRC_POLYNOMIAL;
254 	}
255 
256 	return (crc);
257 }
258