Rejected reserved files names when option windows_names is set

Windows applies legacy restrictions to file names, so when the option
windows_names is applied, reject the same reserved names, which are
CON, PRN, AUX, NUL, COM1..COM9, and LPT1..LPT9
edge.strict_endians
Jean-Pierre André 2014-03-11 10:56:31 +01:00
parent e5ea399ee6
commit 543b17b7ef
6 changed files with 120 additions and 16 deletions

View File

@ -69,6 +69,8 @@ extern ntfschar *ntfs_str2ucs(const char *s, int *len);
extern void ntfs_ucsfree(ntfschar *ucs);
extern BOOL ntfs_forbidden_chars(const ntfschar *name, int len);
extern BOOL ntfs_forbidden_names(ntfs_volume *vol,
const ntfschar *name, int len);
extern BOOL ntfs_collapsible_chars(ntfs_volume *vol,
const ntfschar *shortname, int shortlen,
const ntfschar *longname, int longlen);

View File

@ -5,7 +5,7 @@
* Copyright (c) 2004-2005 Richard Russon
* Copyright (c) 2004-2008 Szabolcs Szakacsits
* Copyright (c) 2005-2007 Yura Pakhuchiy
* Copyright (c) 2008-2010 Jean-Pierre Andre
* Copyright (c) 2008-2014 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -2650,7 +2650,8 @@ int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
if (shortlen > MAX_DOS_NAME_LENGTH)
shortlen = MAX_DOS_NAME_LENGTH;
/* make sure the short name has valid chars */
if ((shortlen < 0) || ntfs_forbidden_chars(shortname,shortlen)) {
if ((shortlen < 0)
|| ntfs_forbidden_names(ni->vol,shortname,shortlen)) {
ntfs_inode_close_in_dir(ni,dir_ni);
ntfs_inode_close(dir_ni);
res = -errno;
@ -2661,7 +2662,7 @@ int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
if (longlen > 0) {
oldlen = get_dos_name(ni, dnum, oldname);
if ((oldlen >= 0)
&& !ntfs_forbidden_chars(longname, longlen)) {
&& !ntfs_forbidden_names(ni->vol, longname, longlen)) {
if (oldlen > 0) {
if (flags & XATTR_CREATE) {
res = -1;

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2004 Anton Altaparmakov
* Copyright (c) 2002-2009 Szabolcs Szakacsits
* Copyright (c) 2008-2011 Jean-Pierre Andre
* Copyright (c) 2008-2014 Jean-Pierre Andre
* Copyright (c) 2008 Bernhard Kaindl
*
* This program/include file is free software; you can redistribute it and/or
@ -1367,7 +1367,7 @@ BOOL ntfs_forbidden_chars(const ntfschar *name, int len)
BOOL forbidden;
int ch;
int i;
u32 mainset = (1L << ('\"' - 0x20))
static const u32 mainset = (1L << ('\"' - 0x20))
| (1L << ('*' - 0x20))
| (1L << ('/' - 0x20))
| (1L << (':' - 0x20))
@ -1376,8 +1376,8 @@ BOOL ntfs_forbidden_chars(const ntfschar *name, int len)
| (1L << ('?' - 0x20));
forbidden = (len == 0)
|| (le16_to_cpu(name[len-1]) == ' ')
|| (le16_to_cpu(name[len-1]) == '.');
|| (name[len-1] == const_cpu_to_le16(' '))
|| (name[len-1] == const_cpu_to_le16('.'));
for (i=0; i<len; i++) {
ch = le16_to_cpu(name[i]);
if ((ch < 0x20)
@ -1392,6 +1392,92 @@ BOOL ntfs_forbidden_chars(const ntfschar *name, int len)
return (forbidden);
}
/*
* Check whether a name contains no forbidden chars and
* is not a reserved name for DOS or Win32 use
*
* The reserved names are CON, PRN, AUX, NUL, COM1..COM9, LPT1..LPT9
* with no suffix or any suffix.
*
* If the name is forbidden, errno is set to EINVAL
*/
BOOL ntfs_forbidden_names(ntfs_volume *vol, const ntfschar *name, int len)
{
BOOL forbidden;
int h;
static const ntfschar dot = const_cpu_to_le16('.');
static const ntfschar con[] = { const_cpu_to_le16('c'),
const_cpu_to_le16('o'), const_cpu_to_le16('n') };
static const ntfschar prn[] = { const_cpu_to_le16('p'),
const_cpu_to_le16('r'), const_cpu_to_le16('n') };
static const ntfschar aux[] = { const_cpu_to_le16('a'),
const_cpu_to_le16('u'), const_cpu_to_le16('x') };
static const ntfschar nul[] = { const_cpu_to_le16('n'),
const_cpu_to_le16('u'), const_cpu_to_le16('l') };
static const ntfschar com[] = { const_cpu_to_le16('c'),
const_cpu_to_le16('o'), const_cpu_to_le16('m') };
static const ntfschar lpt[] = { const_cpu_to_le16('l'),
const_cpu_to_le16('p'), const_cpu_to_le16('t') };
forbidden = ntfs_forbidden_chars(name, len);
if (!forbidden && (len >= 3)) {
/*
* Rough hash check to tell whether the first couple of chars
* may be one of CO PR AU NU LP or lowercase variants.
*/
h = ((le16_to_cpu(name[0]) & 31)*48)
^ ((le16_to_cpu(name[1]) & 31)*165);
if ((h % 23) == 17) {
/* do a full check, depending on the third char */
switch (le16_to_cpu(name[2]) & ~0x20) {
case 'N' :
if (((len == 3) || (name[3] == dot))
&& (!ntfs_ucsncasecmp(name, con, 3,
vol->upcase, vol->upcase_len)
|| !ntfs_ucsncasecmp(name, prn, 3,
vol->upcase, vol->upcase_len)))
forbidden = TRUE;
break;
case 'X' :
if (((len == 3) || (name[3] == dot))
&& !ntfs_ucsncasecmp(name, aux, 3,
vol->upcase, vol->upcase_len))
forbidden = TRUE;
break;
case 'L' :
if (((len == 3) || (name[3] == dot))
&& !ntfs_ucsncasecmp(name, nul, 3,
vol->upcase, vol->upcase_len))
forbidden = TRUE;
break;
case 'M' :
if ((len > 3)
&& (le16_to_cpu(name[3]) >= '1')
&& (le16_to_cpu(name[3]) <= '9')
&& ((len == 4) || (name[4] == dot))
&& !ntfs_ucsncasecmp(name, com, 3,
vol->upcase, vol->upcase_len))
forbidden = TRUE;
break;
case 'T' :
if ((len > 3)
&& (le16_to_cpu(name[3]) >= '1')
&& (le16_to_cpu(name[3]) <= '9')
&& ((len == 4) || (name[4] == dot))
&& !ntfs_ucsncasecmp(name, lpt, 3,
vol->upcase, vol->upcase_len))
forbidden = TRUE;
break;
}
}
}
if (forbidden)
errno = EINVAL;
return (forbidden);
}
/*
* Check whether the same name can be used as a DOS and
* a Win32 name

View File

@ -1851,7 +1851,7 @@ static int ntfs_fuse_create(fuse_req_t req, fuse_ino_t parent, const char *name,
uname_len = ntfs_mbstoucs(name, &uname);
if ((uname_len < 0)
|| (ctx->windows_names
&& ntfs_forbidden_chars(uname,uname_len))) {
&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
res = -errno;
goto exit;
}
@ -2067,7 +2067,7 @@ static int ntfs_fuse_newlink(fuse_req_t req __attribute__((unused)),
uname_len = ntfs_mbstoucs(newname, &uname);
if ((uname_len < 0)
|| (ctx->windows_names
&& ntfs_forbidden_chars(uname,uname_len))) {
&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
res = -errno;
goto exit;
}

View File

@ -250,10 +250,24 @@ adjusted to the latest name.
.TP
.B windows_names
This option prevents files, directories and extended attributes to be
created with a name not allowed by windows, either because it contains
some not allowed character (which are the nine characters " * / : < > ? \\ | and
those whose code is less than 0x20) or because the last character is a space
or a dot. Existing such files can still be read (and renamed).
created with a name not allowed by windows, because
.RS
.RS
.sp
- it contains some not allowed character,
.br
- or the last character is a space or a dot,
.br
- or the name is reserved.
.sp
.RE
The forbidden characters are the nine characters " * / : < > ? \\ | and
those whose code is less than 0x20, and
the reserved names are CON, PRN, AUX, NUL, COM1..COM9, LPT1..LPT9,
with no suffix or followed by a dot.
.sp
Existing such files can still be read (and renamed).
.RE
.TP
.B allow_other
This option overrides the security measure restricting file access

View File

@ -1636,7 +1636,7 @@ static int ntfs_fuse_create(const char *org_path, mode_t typemode, dev_t dev,
uname_len = ntfs_mbstoucs(name, &uname);
if ((uname_len < 0)
|| (ctx->windows_names
&& ntfs_forbidden_chars(uname,uname_len))) {
&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
res = -errno;
goto exit;
}
@ -1840,7 +1840,8 @@ static int ntfs_fuse_mknod_common(const char *org_path, mode_t mode, dev_t dev,
if (stream_name_len
&& (!S_ISREG(mode)
|| (ctx->windows_names
&& ntfs_forbidden_chars(stream_name,stream_name_len)))) {
&& ntfs_forbidden_names(ctx->vol,stream_name,
stream_name_len)))) {
res = -EINVAL;
goto exit;
}
@ -1909,7 +1910,7 @@ static int ntfs_fuse_link(const char *old_path, const char *new_path)
uname_len = ntfs_mbstoucs(name, &uname);
if ((uname_len < 0)
|| (ctx->windows_names
&& ntfs_forbidden_chars(uname,uname_len))) {
&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
res = -errno;
goto exit;
}