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