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