smb_match.c revision 148c5f43199ca0b43fc8e3b643aab11cd66ea327
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or http://www.opensolaris.org/os/licensing.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifndef _KERNEL
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <stdlib.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <string.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/types.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/sunddi.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown#include <smbsrv/string.h>
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown#include <smbsrv/smb.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright/*
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * Maximum recursion depth for the wildcard match functions.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * These functions may recurse when processing a '*'.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright */
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright#define SMB_MATCH_DEPTH_MAX 32
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright#define SMB_CRC_POLYNOMIAL 0xD8B5D8B5
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wrightstatic int smb_match_private(const char *, const char *, int *);
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wrightstatic int smb_match_ci_private(const char *, const char *, int *);
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright * smb_match
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wrightboolean_t
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_match(char *patn, char *str)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright int depth = 0;
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright return (smb_match_private(patn, str, &depth) == 1);
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright}
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright/*
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * The '*' character matches multiple characters.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * The '?' character matches a single character.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright *
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * If the pattern has trailing '?'s then it matches the specified number
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * of characters or less. For example, "x??" matches "xab", "xa" and "x",
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * but not "xabc".
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright *
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * Returns:
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * 1 match
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * 0 no-match
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * -1 no-match, too many wildcards in pattern
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright */
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wrightstatic int
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wrightsmb_match_private(const char *patn, const char *str, int *depth)
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright{
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright int rc;
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (;;) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (*patn) {
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown case '\0':
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown return (*str == '\0');
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case '?':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (*str != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw str++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw patn++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*NOTREACHED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case '*':
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright patn += strspn(patn, "*");
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown if (*patn == '\0')
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright if ((*depth)++ >= SMB_MATCH_DEPTH_MAX)
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (*str) {
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright rc = smb_match_private(patn, str, depth);
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright if (rc != 0)
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw str++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (*str != *patn)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw str++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw patn++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright /*NOTREACHED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright/*
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright * smb_match_ci
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wrightboolean_t
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_match_ci(char *patn, char *str)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright int depth = 0;
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright return (smb_match_ci_private(patn, str, &depth) == 1);
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright}
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright/*
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * The '*' character matches multiple characters.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * The '?' character matches a single character.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright *
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * If the pattern has trailing '?'s then it matches the specified number
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * of characters or less. For example, "x??" matches "xab", "xa" and "x",
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * but not "xabc".
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright *
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * Returns:
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * 1 match
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * 0 no-match
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * -1 no-match, too many wildcards in pattern
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright */
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wrightstatic int
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wrightsmb_match_ci_private(const char *patn, const char *str, int *depth)
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright{
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown const char *p;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown smb_wchar_t wc1, wc2;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown int nbytes1, nbytes2;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown int rc;
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * "<" is a special pattern that matches only those names that do
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * NOT have an extension. "." and ".." are ok.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (strcmp(patn, "<") == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((strcmp(str, ".") == 0) || (strcmp(str, "..") == 0))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (strchr(str, '.') == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (;;) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (*patn) {
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown case '\0':
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown return (*str == '\0');
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case '?':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (*str != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw str++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw patn++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright p = patn;
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright p += strspn(p, "?");
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright return ((*p == '\0') ? 1 : 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*NOTREACHED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case '*':
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright patn += strspn(patn, "*");
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown if (*patn == '\0')
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright if ((*depth)++ >= SMB_MATCH_DEPTH_MAX)
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright return (-1);
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (*str) {
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright rc = smb_match_ci_private(patn, str, depth);
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright if (rc != 0)
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw str++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown nbytes1 = smb_mbtowc(&wc1, patn, MTS_MB_CHAR_MAX);
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown nbytes2 = smb_mbtowc(&wc2, str, MTS_MB_CHAR_MAX);
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown if ((nbytes1 == -1) || (nbytes2 == -1))
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown if (wc1 != wc2) {
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown wc1 = smb_tolower(wc1);
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown wc2 = smb_tolower(wc2);
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown if (wc1 != wc2)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown patn += nbytes1;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown str += nbytes2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright /*NOTREACHED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wrightuint32_t
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wrightsmb_crc_gen(uint8_t *buf, size_t len)
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright{
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright uint32_t crc = SMB_CRC_POLYNOMIAL;
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright uint8_t *p;
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright int i;
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright for (p = buf, i = 0; i < len; ++i, ++p) {
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright crc = (crc ^ (uint32_t)*p) + (crc << 12);
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright if (crc == 0 || crc == 0xFFFFFFFF)
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright crc = SMB_CRC_POLYNOMIAL;
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright }
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright return (crc);
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright}