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