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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #ifndef _KERNEL 26 #include <stdlib.h> 27 #include <string.h> 28 #else 29 #include <sys/types.h> 30 #include <sys/sunddi.h> 31 #endif 32 #include <smbsrv/string.h> 33 #include <smbsrv/smb.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 * smb_match 48 */ 49 boolean_t 50 smb_match(char *patn, char *str) 51 { 52 int depth = 0; 53 54 return (smb_match_private(patn, str, &depth) == 1); 55 } 56 57 /* 58 * The '*' character matches multiple characters. 59 * The '?' character matches a single character. 60 * 61 * If the pattern has trailing '?'s then it matches the specified number 62 * of characters or less. For example, "x??" matches "xab", "xa" and "x", 63 * but not "xabc". 64 * 65 * Returns: 66 * 1 match 67 * 0 no-match 68 * -1 no-match, too many wildcards in pattern 69 */ 70 static int 71 smb_match_private(const char *patn, const char *str, int *depth) 72 { 73 int rc; 74 75 for (;;) { 76 switch (*patn) { 77 case '\0': 78 return (*str == '\0'); 79 80 case '?': 81 if (*str != 0) { 82 str++; 83 patn++; 84 continue; 85 } else { 86 return (0); 87 } 88 /*NOTREACHED*/ 89 90 case '*': 91 patn += strspn(patn, "*"); 92 if (*patn == '\0') 93 return (1); 94 95 if ((*depth)++ >= SMB_MATCH_DEPTH_MAX) 96 return (-1); 97 98 while (*str) { 99 rc = smb_match_private(patn, str, depth); 100 if (rc != 0) 101 return (rc); 102 str++; 103 } 104 return (0); 105 106 default: 107 if (*str != *patn) 108 return (0); 109 str++; 110 patn++; 111 continue; 112 } 113 } 114 /*NOTREACHED*/ 115 } 116 117 /* 118 * smb_match_ci 119 */ 120 boolean_t 121 smb_match_ci(char *patn, char *str) 122 { 123 int depth = 0; 124 125 return (smb_match_ci_private(patn, str, &depth) == 1); 126 } 127 128 /* 129 * The '*' character matches multiple characters. 130 * The '?' character matches a single character. 131 * 132 * If the pattern has trailing '?'s then it matches the specified number 133 * of characters or less. For example, "x??" matches "xab", "xa" and "x", 134 * but not "xabc". 135 * 136 * Returns: 137 * 1 match 138 * 0 no-match 139 * -1 no-match, too many wildcards in pattern 140 */ 141 static int 142 smb_match_ci_private(const char *patn, const char *str, int *depth) 143 { 144 const char *p; 145 smb_wchar_t wc1, wc2; 146 int nbytes1, nbytes2; 147 int rc; 148 149 /* 150 * "<" is a special pattern that matches only those names that do 151 * NOT have an extension. "." and ".." are ok. 152 */ 153 if (strcmp(patn, "<") == 0) { 154 if ((strcmp(str, ".") == 0) || (strcmp(str, "..") == 0)) 155 return (1); 156 if (strchr(str, '.') == 0) 157 return (1); 158 return (0); 159 } 160 161 for (;;) { 162 switch (*patn) { 163 case '\0': 164 return (*str == '\0'); 165 166 case '?': 167 if (*str != 0) { 168 str++; 169 patn++; 170 continue; 171 } else { 172 p = patn; 173 p += strspn(p, "?"); 174 return ((*p == '\0') ? 1 : 0); 175 } 176 /*NOTREACHED*/ 177 178 case '*': 179 patn += strspn(patn, "*"); 180 if (*patn == '\0') 181 return (1); 182 183 if ((*depth)++ >= SMB_MATCH_DEPTH_MAX) 184 return (-1); 185 186 while (*str) { 187 rc = smb_match_ci_private(patn, str, depth); 188 if (rc != 0) 189 return (rc); 190 str++; 191 } 192 return (0); 193 194 default: 195 nbytes1 = smb_mbtowc(&wc1, patn, MTS_MB_CHAR_MAX); 196 nbytes2 = smb_mbtowc(&wc2, str, MTS_MB_CHAR_MAX); 197 if ((nbytes1 == -1) || (nbytes2 == -1)) 198 return (-1); 199 200 if (wc1 != wc2) { 201 wc1 = smb_tolower(wc1); 202 wc2 = smb_tolower(wc2); 203 if (wc1 != wc2) 204 return (0); 205 } 206 207 patn += nbytes1; 208 str += nbytes2; 209 continue; 210 } 211 } 212 /*NOTREACHED*/ 213 } 214 215 uint32_t 216 smb_crc_gen(uint8_t *buf, size_t len) 217 { 218 uint32_t crc = SMB_CRC_POLYNOMIAL; 219 uint8_t *p; 220 int i; 221 222 for (p = buf, i = 0; i < len; ++i, ++p) { 223 crc = (crc ^ (uint32_t)*p) + (crc << 12); 224 225 if (crc == 0 || crc == 0xFFFFFFFF) 226 crc = SMB_CRC_POLYNOMIAL; 227 } 228 229 return (crc); 230 } 231