193 files changed, 80411 insertions, 44563 deletions
diff --git a/src/secaudit.c b/src/secaudit.c index 3e098d5..ca2264f 100755 --- a/src/secaudit.c +++ b/src/secaudit.c @@ -1,7 +1,7 @@ /* * Display and audit security attributes in an NTFS volume * - * Copyright (c) 2007-2010 Jean-Pierre Andre + * Copyright (c) 2007-2013 Jean-Pierre Andre * * Options : * -a auditing security data @@ -10,6 +10,7 @@ * -h displaying hexadecimal security descriptors within a file * -r recursing in a directory * -s setting backed-up NTFS ACLs + * -u getting a user mapping proposal * -v verbose (very verbose if set twice) * also, if compile-time option is set * -t run internal tests (with no access to storage) @@ -173,7 +174,38 @@ * - repeated the fix for return code of dorestore() * * Mar 2010, version 1.3.17 + * - adapted to new default user mapping * - fixed #ifdef'd code for selftest + * + * May 2010, version 1.3.18 + * - redefined early error logging + * + * Mar 2011, version 1.3.19 + * - fixed interface to ntfs_initialize_file_security() + * + * Apr 2011, version 1.3.20 + * - fixed false memory leak detection + * + * Jun 2011, version 1.3.21 + * - cleaned a few unneeded variables + * + * Nov 2011, version 1.3.22 + * - added a distinctive prefix to owner and group SID + * - fixed a false memory leak detection + * + * Jun 2012, version 1.3.23 + * - added support for SACL (nickgarvey) + * + * Jul 2012, version 1.3.24 + * - added self-tests for authenticated users + * - added display of ace-inherited flag + * - made runnable on OpenIndiana + * + * Aug 2012, version 1.4.0 + * - added an option for user mapping proposal + * + * Sep 2013, version 1.4.1 + * - silenced an aliasing warning by gcc >= 4.8 */ /* @@ -197,7 +229,7 @@ * General parameters which may have to be adapted to needs */ -#define AUDT_VERSION "1.3.17" +#define AUDT_VERSION "1.4.1" #define GET_FILE_SECURITY "ntfs_get_file_security" #define SET_FILE_SECURITY "ntfs_set_file_security" @@ -222,10 +254,7 @@ #include <time.h> #include <string.h> #include <stdlib.h> -#ifdef HAVE_SYS_TYPES_H #include <sys/types.h> -#endif - #include <fcntl.h> #include <errno.h> #include <stdarg.h> @@ -278,7 +307,7 @@ #ifndef STSC -#if !defined(HAVE_CONFIG_H) && POSIXACLS +#if !defined(HAVE_CONFIG_H) && POSIXACLS && !defined(__SVR4) /* require <sys/xattr.h> if not integrated into ntfs-3g package */ #define HAVE_SETXATTR 1 #endif @@ -305,8 +334,8 @@ #endif /* STSC */ -#define MS_NONE 0 /* no flag for mounting the device */ -#define MS_RDONLY 1 /* flag for mounting the device read-only */ +#define NTFS_MNT_NONE 0 /* no flag for mounting the device */ +#define NTFS_MNT_RDONLY 1 /* flag for mounting the device read-only */ struct CALLBACK; @@ -314,6 +343,11 @@ typedef int (*dircallback)(struct CALLBACK *context, char *ntfsname, int length, int type, long long pos, u64 mft_ref, unsigned int dt_type); +#ifndef HAVE_SYSLOG_H +void ntfs_log_early_error(const char *format, ...) + __attribute__((format(printf, 1, 2))); +#endif + #if USESTUBS | defined(STSC) int ntfs_get_file_security(void *scapi, @@ -337,7 +371,7 @@ int ntfs_get_gsid(void *scapi, gid_t gid, char *buf); int ntfs_get_user(void *scapi, const char *usid); int ntfs_get_group(void *scapi, const char *gsid); -void *ntfs_initialize_file_security(const char *device, int flags); +void *ntfs_initialize_file_security(const char *device, unsigned long flags); BOOL ntfs_leave_file_security(void *scapi); #else @@ -363,7 +397,8 @@ typedef int (*type_get_gsid)(void *scapi, gid_t gid, char *buf); typedef int (*type_get_user)(void *scapi, const char *usid); typedef int (*type_get_group)(void *scapi, const char *gsid); -typedef void *(*type_initialize_file_security)(const char *device, int flags); +typedef void *(*type_initialize_file_security)(const char *device, + unsigned long flags); typedef BOOL (*type_leave_file_security)(void *scapi); type_get_file_security ntfs_get_file_security; @@ -394,7 +429,7 @@ type_leave_file_security ntfs_leave_file_security; BOOL open_security_api(void); BOOL close_security_api(void); #ifndef WIN32 -BOOL open_volume(const char*, int flags); +BOOL open_volume(const char*, unsigned long flags); BOOL close_volume(const char*); #endif unsigned int get2l(const char*, int); @@ -414,7 +449,7 @@ unsigned int utf16len(const char*); void printname(FILE*, const char*); void printerror(FILE*); BOOL guess_dir(const char*); -void showsid(const char*, int, int); +void showsid(const char*, int, const char*, int); void showusid(const char*, int); void showgsid(const char*, int); void showheader(const char*, int); @@ -450,7 +485,9 @@ unsigned int getfull(char*, const char*); BOOL updatefull(const char *name, DWORD flags, char *attr); BOOL setfull(const char*, int, BOOL); BOOL singleshow(const char*); -void showmounted(const char*); +BOOL proposal(const char*, const char*); +BOOL showmounted(const char*); +BOOL processmounted(const char*); BOOL recurseshow(const char*); BOOL singleset(const char*, int); BOOL recurseset(const char*, int); @@ -465,6 +502,7 @@ BOOL iterate(RECURSE, const char*, mode_t); #else BOOL backup(const char*, const char*); BOOL listfiles(const char*, const char*); +BOOL mapproposal(const char*, const char*); #endif #if POSIXACLS BOOL setfull_posix(const char *, const struct POSIX_SECURITY*, BOOL); @@ -473,6 +511,7 @@ BOOL recurseset_posix(const char*, const struct POSIX_SECURITY*); BOOL singleset_posix(const char*, const struct POSIX_SECURITY*); struct POSIX_SECURITY *encode_posix_acl(const char*); #endif +static void *stdmalloc(size_t); static void stdfree(void*); BOOL valid_sds(const char*, unsigned int, unsigned int, @@ -545,8 +584,21 @@ static const char worldsidbytes[] = { } ; static const SID *worldsid = (const SID*)worldsidbytes; +/* + * SID for authenticated user (S-1-5-11) + */ + +static const char authsidbytes[] = { + 1, /* revision */ + 1, /* auth count */ + 0, 0, 0, 0, 0, 5, /* base */ + 11, 0, 0, 0 /* 1st level */ +}; + +static const SID *authsid = (const SID*)authsidbytes; + /* - * SID for administrator + * SID for administrator (S-1-5-32-544) */ static const char adminsidbytes[] = { @@ -559,8 +611,22 @@ static const char adminsidbytes[] = { static const SID *adminsid = (const SID*)adminsidbytes; +/* + * SID for local users (S-1-5-32-545) + */ + +static const char localsidbytes[] = { + 1, /* revision */ + 2, /* auth count */ + 0, 0, 0, 0, 0, 5, /* base */ + 32, 0, 0, 0, /* 1st level */ + 33, 2, 0, 0 /* 2nd level */ +}; + +static const SID *localsid = (const SID*)localsidbytes; + /* - * SID for system + * SID for system (S-1-5-18) */ static const char systemsidbytes[] = { @@ -584,6 +650,7 @@ BOOL opt_e; /* restore extra (currently windows attribs) */ BOOL opt_h; /* display an hexadecimal descriptor in a file */ BOOL opt_r; /* recursively apply to subdirectories */ BOOL opt_s; /* restore NTFS ACLs */ +BOOL opt_u; /* user mapping proposal */ #if SELFTESTS & !USESTUBS BOOL opt_t; /* run self-tests */ #endif @@ -626,7 +693,12 @@ BOOL open_security_api(void) libfile = getenv(ENVNTFS3G); if (!libfile) libfile = (sizeof(char*) == 8 ? LIBFILE64 : LIBFILE); +#ifdef __SVR4 + /* do not override library functions by caller ones */ + ntfs_handle = dlopen(libfile,RTLD_LAZY | RTLD_GROUP); +#else ntfs_handle = dlopen(libfile,RTLD_LAZY); +#endif if (ntfs_handle) { ntfs_initialize_file_security = (type_initialize_file_security) dlsym(ntfs_handle,INIT_FILE_SECURITY); @@ -701,13 +773,13 @@ BOOL close_security_api(void) * Assumes a single volume is opened */ -BOOL open_volume(const char *volume, int flags) +BOOL open_volume(const char *volume, unsigned long flags) { BOOL ok; ok = FALSE; if (!ntfs_context) { - ntfs_context = (*ntfs_initialize_file_security)(volume,flags); + ntfs_context = ntfs_initialize_file_security(volume,flags); if (ntfs_context) { if (*(u32*)ntfs_context != MAGIC_API) { fprintf(stderr,"Versions of ntfs-3g and secaudit" @@ -730,7 +802,7 @@ BOOL close_volume(const char *volume) { BOOL r; - r = (*ntfs_leave_file_security)(ntfs_context); + r = ntfs_leave_file_security(ntfs_context); if (r) fprintf(stderr,"\"%s\" closed\n",volume); else @@ -1273,6 +1345,23 @@ void printerror(FILE *file) #endif } +#ifndef HAVE_SYSLOG_H + +/* + * Redefine early error messages in stand-alone situations + */ + +void ntfs_log_early_error(const char *format, ...) +{ + va_list args; + + va_start(args, format); + vfprintf(stderr,format,args); + va_end(args); +} + +#endif + /* * Guess whether a security attribute is intended for a directory * based on the presence of inheritable ACE @@ -1306,7 +1395,7 @@ BOOL guess_dir(const char *attr) * See http://msdn2.microsoft.com/en-us/library/aa379649.aspx */ -void showsid(const char *attr, int off, int level) +void showsid(const char *attr, int off, const char *prefix, int level) { int cnt; int i; @@ -1433,12 +1522,12 @@ void showsid(const char *attr, int off, int level) } if (!known) printf("%*cUnknown SID\n",-level,marker); - printf("%*chex S-%d-",-level,marker,attr[off] & 255); + printf("%*c%shex S-%d-",-level,marker,prefix,attr[off] & 255); printf("%llx",auth); for (i=0; i<cnt; i++) printf("-%lx",get4l(attr,off+8+4*i)); printf("\n"); - printf("%*cdec S-%d-",-level,marker,attr[off] & 255); + printf("%*c%sdec S-%d-",-level,marker,prefix,attr[off] & 255); printf("%llu",auth); for (i=0; i<cnt; i++) printf("-%lu",get4l(attr,off+8+4*i)); @@ -1456,9 +1545,9 @@ void showusid(const char *attr, int level) marker = ' '; if (level) printf("%*c",-level,marker); - printf("User SID\n"); + printf("Owner SID\n"); off = get4l(attr,4); - showsid(attr,off,level+4); + showsid(attr,off,"O:",level+4); } void showgsid(const char *attr, int level) @@ -1474,7 +1563,7 @@ void showgsid(const char *attr, int level) printf("%*c",-level,marker); printf("Group SID\n"); off = get4l(attr,8); - showsid(attr,off,level+4); + showsid(attr,off,"G:",level+4); } void showheader(const char *attr, int level) @@ -1562,6 +1651,8 @@ void showace(const char *attr, int off, int isdir, int level) printf("%*cDon\'t propagate inherits ACE\n",-level-4,marker); if (flags & 8) printf("%*cInherit only ACE\n",-level-4,marker); + if (flags & 0x10) + printf("%*cACE was inherited\n",-level-4,marker); if (flags & 0x40) printf("%*cAudit on success\n",-level-4,marker); if (flags & 0x80) @@ -1634,7 +1725,7 @@ void showace(const char *attr, int off, int isdir, int level) printf("%*cGeneric read\n",-level-4,marker); printf("%*cSID at 0x%x\n",-level,marker,off+8); - showsid(attr,off+8,level+4); + showsid(attr,off+8,"",level+4); printf("%*cSummary :",-level,marker); if (attr[off] == 0) printf(" grant"); @@ -1994,14 +2085,15 @@ int linux_permissions(const char *attr, BOOL isdir) uid_t linux_owner(const char *attr) { - const SECURITY_DESCRIPTOR_RELATIVE *phead; const SID *usid; uid_t uid; - phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; #if OWNERFROMACL usid = ntfs_acl_owner((const char*)attr); #else + const SECURITY_DESCRIPTOR_RELATIVE *phead; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; usid = (const SID*)&attr[le32_to_cpu(phead->owner)]; #endif #if defined(WIN32) | defined(STSC) @@ -2105,6 +2197,56 @@ int dummyread(void *fileid __attribute__((unused)), #endif /* POSIXACLS & SELFTESTS & !USESTUBS */ /* + * Apply default single user mapping + * returns zero if successful + */ + +static int do_default_mapping(struct MAPPING *mapping[], + const SID *usid) +{ + struct MAPPING *usermapping; + struct MAPPING *groupmapping; + SID *sid; + int sidsz; + int res; + + res = -1; + sidsz = ntfs_sid_size(usid); +#if USESTUBS + sid = (SID*)stdmalloc(sidsz); /* will be freed within the library */ +#else + sid = (SID*)ntfs_malloc(sidsz); +#endif + if (sid) { + memcpy(sid,usid,sidsz); +#if USESTUBS + usermapping = (struct MAPPING*)stdmalloc(sizeof(struct MAPPING)); +#else + usermapping = (struct MAPPING*)ntfs_malloc(sizeof(struct MAPPING)); +#endif + if (usermapping) { +#if USESTUBS + groupmapping = (struct MAPPING*)stdmalloc(sizeof(struct MAPPING)); +#else + groupmapping = (struct MAPPING*)ntfs_malloc(sizeof(struct MAPPING)); +#endif + if (groupmapping) { + usermapping->sid = sid; + usermapping->xid = 0; + usermapping->next = (struct MAPPING*)NULL; + groupmapping->sid = sid; + groupmapping->xid = 0; + groupmapping->next = (struct MAPPING*)NULL; + mapping[MAPUSERS] = usermapping; + mapping[MAPGROUPS] = groupmapping; + res = 0; + } + } + } + return (res); +} + +/* * Build the user mapping * - according to a mapping file if defined (or default present), * - or try default single user mapping if possible @@ -2120,6 +2262,7 @@ int local_build_mapping(struct MAPPING *mapping[], const char *usermap_path) { #ifdef WIN32 char mapfile[sizeof(MAPDIR) + sizeof(MAPFILE) + 6]; + char currpath[261]; #else char *mapfile; char *p; @@ -2129,6 +2272,22 @@ int local_build_mapping(struct MAPPING *mapping[], const char *usermap_path) struct MAPLIST *firstitem = (struct MAPLIST*)NULL; struct MAPPING *usermapping; struct MAPPING *groupmapping; + static struct { + u8 revision; + u8 levels; + be16 highbase; + be32 lowbase; + le32 level1; + le32 level2; + le32 level3; + le32 level4; + le32 level5; + } defmap = { + 1, 5, const_cpu_to_be16(0), const_cpu_to_be32(5), + const_cpu_to_le32(21), + const_cpu_to_le32(DEFSECAUTH1), const_cpu_to_le32(DEFSECAUTH2), + const_cpu_to_le32(DEFSECAUTH3), const_cpu_to_le32(DEFSECBASE) + } ; /* be sure not to map anything until done */ mapping[MAPUSERS] = (struct MAPPING*)NULL; @@ -2140,8 +2299,10 @@ int local_build_mapping(struct MAPPING *mapping[], const char *usermap_path) strcpy(mapfile,"x:\\" MAPDIR "\\" MAPFILE); if (((le16*)usermap_path)[1] == ':') mapfile[0] = usermap_path[0]; - else - mapfile[0] = getdrive() + 'A' - 1; + else { + GetModuleFileName(NULL, currpath, 261); + mapfile[0] = currpath[0]; + } fd = open(mapfile,O_RDONLY); #else fd = 0; @@ -2204,6 +2365,8 @@ int local_build_mapping(struct MAPPING *mapping[], const char *usermap_path) #endif firstitem = item; } + } else { + do_default_mapping(mapping,(const SID*)&defmap); } if (mapping[MAPUSERS]) mappingtype = MAPLOCAL; @@ -2314,17 +2477,16 @@ void showhex(FILE *fd) int lth; int first; unsigned int pos; - unsigned char b; u32 v; int c; int isdir; int mode; unsigned int off; int i; + le32 *pattr; BOOL isdump; BOOL done; - b = 0; pos = 0; off = 0; done = FALSE; @@ -2381,8 +2543,9 @@ void showhex(FILE *fd) /* decode it into attribute */ if (isdump && (off == pos)) { for (i=first+8; i<lth; i+=9) { + pattr = (le32*)&attr[pos]; v = getlsbhex(&line[i]); - *(le32*)&attr[pos] = cpu_to_le32(v); + *pattr = cpu_to_le32(v); pos += 4; } } @@ -2405,7 +2568,6 @@ void showhex(FILE *fd) BOOL applyattr(const char *fullname, const char *attr, BOOL withattr, int attrib, s32 key) { - const SECURITY_DESCRIPTOR_RELATIVE *phead; struct SECURITY_DATA *psecurdata; const char *curattr; char *newattr; @@ -2413,6 +2575,10 @@ BOOL applyattr(const char *fullname, const char *attr, BOOL bad; BOOL badattrib; BOOL err; +#ifdef WIN32 + HANDLE htoken; + TOKEN_PRIVILEGES tkp; +#endif err = FALSE; psecurdata = (struct SECURITY_DATA*)NULL; @@ -2463,28 +2629,43 @@ BOOL applyattr(const char *fullname, const char *attr, if (curattr) { - phead = (const SECURITY_DESCRIPTOR_RELATIVE*)curattr; #ifdef WIN32 - /* SACL currently not set, need some special privilege */ selection = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; + if (OpenProcessToken(GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &htoken)) { + if (LookupPrivilegeValue(NULL, SE_SECURITY_NAME, + &tkp.Privileges[0].Luid)) { + tkp.PrivilegeCount = 1; + tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (AdjustTokenPrivileges(htoken, FALSE, &tkp, 0, NULL, 0)) { + selection |= SACL_SECURITY_INFORMATION; + } + } + } bad = !SetFileSecurityW((LPCWSTR)fullname, selection, (char*)curattr); if (bad) switch (GetLastError()) { case 1307 : case 1314 : - printf("** Could not set owner of "); + printf("** Could not set owner or SACL of "); printname(stdout,fullname); - printf(", retrying with no owner setting\n"); + printf(", retrying with no owner or SACL setting\n"); warnings++; bad = !SetFileSecurityW((LPCWSTR)fullname, - selection & ~OWNER_SECURITY_INFORMATION, (char*)curattr); + selection & ~OWNER_SECURITY_INFORMATION + & ~SACL_SECURITY_INFORMATION, (char*)curattr); break; default : break; } + /* Release privileges once we are done*/ + if (selection ^ SACL_SECURITY_INFORMATION) { + tkp.Privileges[0].Attributes = 0; + AdjustTokenPrivileges(htoken, FALSE, &tkp, 0, NULL, 0); + } #else selection = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION @@ -2531,8 +2712,6 @@ BOOL restore(FILE *fd) int lth; int first; unsigned int pos; - unsigned int size; - unsigned char b; int c; int isdir; int mode; @@ -2544,12 +2723,11 @@ BOOL restore(FILE *fd) int i; int count; int attrib; + le32 *pattr; BOOL withattr; BOOL done; - b = 0; pos = 0; - size = 0; off = 0; done = FALSE; withattr = FALSE; @@ -2594,7 +2772,6 @@ BOOL restore(FILE *fd) mode = linux_permissions(attr,isdir); printf("Interpreted Unix mode 0%03o\n",mode); } - size = pos; pos = 0; } if (isdump && !off) @@ -2603,8 +2780,9 @@ BOOL restore(FILE *fd) /* decode it into attribute */ if (isdump && (off == pos)) { for (i=first+8; i<lth; i+=9) { + pattr = (le32*)&attr[pos]; v = getlsbhex(&line[i]); - *(le32*)&attr[pos] = cpu_to_le32(v); + *pattr = cpu_to_le32(v); pos += 4; } } @@ -2698,7 +2876,7 @@ BOOL dorestore(const char *volume, FILE *fd) err = FALSE; if (!getuid()) { if (open_security_api()) { - if (open_volume(volume,MS_NONE)) { + if (open_volume(volume,NTFS_MNT_NONE)) { if (restore(fd)) err = TRUE; close_volume(volume); } else { @@ -2787,14 +2965,14 @@ void tryposix(struct POSIX_SECURITY *pxdesc) le32 owner_sid[] = /* S-1-5-21-3141592653-589793238-462843383-1016 */ { cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), - cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), - cpu_to_le32(AUTH3), cpu_to_le32(1016) + cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2), + cpu_to_le32(DEFSECAUTH3), cpu_to_le32(1016) } ; le32 group_sid[] = /* S-1-5-21-3141592653-589793238-462843383-513 */ { cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), - cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), - cpu_to_le32(AUTH3), cpu_to_le32(513) + cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2), + cpu_to_le32(DEFSECAUTH3), cpu_to_le32(513) } ; char *attr; @@ -3042,14 +3220,14 @@ void check_samples() le32 owner3[] = /* S-1-5-21-3141592653-589793238-462843383-1016 */ { cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), - cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), - cpu_to_le32(AUTH3), cpu_to_le32(1016) + cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2), + cpu_to_le32(DEFSECAUTH3), cpu_to_le32(1016) } ; le32 group3[] = /* S-1-5-21-3141592653-589793238-462843383-513 */ { cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), - cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), - cpu_to_le32(AUTH3), cpu_to_le32(513) + cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2), + cpu_to_le32(DEFSECAUTH3), cpu_to_le32(513) } ; #if POSIXACLS @@ -3251,7 +3429,7 @@ void check_samples() * which cannot be generated by Linux */ - for (cnt=1; cnt<=8; cnt++) { + for (cnt=1; cnt<=10; cnt++) { switch(cnt) { case 1 : /* hp/tmp */ isdir = TRUE; @@ -3349,6 +3527,32 @@ void check_samples() expectacc = expect = 0700; expectdef = 0700; break; + case 9 : /* Win8/bin */ + isdir = TRUE; + descr = build_dummy_descr(isdir, + (const SID*)owner3, (const SID*)owner3, + 6, + (int)TRUE, authsid, (int)0x3, (u32)0x1f01ff, + (int)TRUE, adminsid, (int)0x13, (u32)0x1f01ff, + (int)TRUE, systemsid, (int)0x13, (u32)0x1f01ff, + (int)TRUE, localsid, (int)0x13, (u32)0x1200a9, + (int)TRUE, authsid, (int)0x10, (u32)0x1301bf, + (int)TRUE, authsid, (int)0x1b, (u32)0xe0010000); + expectacc = expect = 0777; + expectdef = 0777; + break; + case 10 : /* Win8/bin/linem.exe */ + isdir = FALSE; + descr = build_dummy_descr(isdir, + (const SID*)owner3, (const SID*)owner3, + 4, + (int)TRUE, authsid, (int)0x10, (u32)0x1f01ff, + (int)TRUE, adminsid, (int)0x10, (u32)0x1f01ff, + (int)TRUE, systemsid, (int)0x10, (u32)0x1ff, + (int)TRUE, localsid, (int)0x10, (u32)0x1200a9); + expectacc = expect = 0777; + expectdef = 0; + break; default : expectacc = expectdef = 0; break; @@ -3858,14 +4062,14 @@ void selftests(void) le32 owner_sid[] = /* S-1-5-21-3141592653-589793238-462843383-1016 */ { cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), - cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), - cpu_to_le32(AUTH3), cpu_to_le32(1016) + cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2), + cpu_to_le32(DEFSECAUTH3), cpu_to_le32(1016) } ; le32 group_sid[] = /* S-1-5-21-3141592653-589793238-462843383-513 */ { cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), - cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), - cpu_to_le32(AUTH3), cpu_to_le32(513) + cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2), + cpu_to_le32(DEFSECAUTH3), cpu_to_le32(513) } ; #if POSIXACLS #ifdef STSC @@ -3943,6 +4147,9 @@ unsigned int getfull(char *attr, const char *fullname) ULONG attrsz; ULONG partsz; BOOL overflow; + HANDLE htoken; + TOKEN_PRIVILEGES tkp; + BOOL saclsuccess; attrsz = 0; partsz = 0; @@ -3963,9 +4170,27 @@ unsigned int getfull(char *attr, const char *fullname) } /* * SACL : just feed in or clean + * This requires the SE_SECURITY_NAME privilege */ - if (!GetFileSecurityW((LPCWSTR)fullname,SACL_SECURITY_INFORMATION, - (char*)attr,MAXATTRSZ,&attrsz)) { + saclsuccess = FALSE; + if (OpenProcessToken(GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &htoken)) { + if (LookupPrivilegeValue(NULL, SE_SECURITY_NAME, + &tkp.Privileges[0].Luid)) { + tkp.PrivilegeCount = 1; + tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (AdjustTokenPrivileges(htoken, FALSE, &tkp, 0, NULL, 0)) { + if (GetFileSecurityW((LPCWSTR)fullname, + SACL_SECURITY_INFORMATION, + (char*)attr,MAXATTRSZ,&attrsz)) { + saclsuccess = TRUE; + } + tkp.Privileges[0].Attributes = 0; + AdjustTokenPrivileges(htoken, FALSE, &tkp, 0, NULL, 0); + } + } + } + if (!saclsuccess) { attrsz = 20; set4l(attr,0); attr[0] = SECURITY_DESCRIPTOR_REVISION; @@ -4439,6 +4664,127 @@ BOOL setfull(const char *fullname, int mode, BOOL isdir) return (err); } +BOOL proposal(const char *name, const char *attr) +{ + char fullname[MAXFILENAME]; + int uoff, goff; + int i; + u64 uauth, gauth; + int ucnt, gcnt; + int uid, gid; + BOOL err; +#ifdef WIN32 + char driveletter; +#else + struct stat st; + char *p,*q; +#endif + + err = FALSE; +#ifdef WIN32 + uid = gid = 0; +#else + uid = getuid(); + gid = getgid(); +#endif + uoff = get4l(attr,4); + uauth = get6h(attr,uoff+2); + ucnt = attr[uoff+1] & 255; + goff = get4l(attr,8); + gauth = get6h(attr,goff+2); + gcnt = attr[goff+1] & 255; + + if ((ucnt == 5) && (gcnt == 5) + && (uauth == 5) && (gauth == 5) + && (get4l(attr,uoff+8) == 21) && (get4l(attr,goff+8) == 21)) { + printf("# User mapping proposal :\n"); + printf("# -------------------- cut here -------------------\n"); + if (uid) + printf("%d::",uid); + else + printf("user::"); + printf("S-%d-%llu",attr[uoff] & 255,uauth); + for (i=0; i<ucnt; i++) + printf("-%lu",get4l(attr,uoff+8+4*i)); + printf("\n"); + if (gid) + printf(":%d:",gid); + else + printf(":group:"); + printf("S-%d-%llu",attr[goff] & 255,gauth); + for (i=0; i<gcnt; i++) + printf("-%lu",get4l(attr,goff+8+4*i)); + printf("\n"); + /* generic rule, based on group */ + printf("::S-%d-%llu",attr[goff] & 255,gauth); + for (i=0; i<gcnt-1; i++) + printf("-%lu",get4l(attr,goff+8+4*i)); + printf("-10000\n"); + printf("# -------------------- cut here -------------------\n"); + if (!uid || !gid) { + printf("# Please replace \"user\" and \"group\" above by the uid\n"); + printf("# and gid of the Linux owner and group of "); + printname(stdout,name); + printf(", then\n"); + printf("# insert the modified lines into .NTFS-3G/Usermapping, with .NTFS-3G\n"); + } else + printf("# Insert the above lines into .NTFS-3G/Usermapping, with .NTFS-3G\n"); +#ifdef WIN32 + printf("# being a directory of the root of the NTFS file system.\n"); + + /* Get the drive letter to the file system */ + driveletter = 0; + if ((((name[0] >= 'a') && (name[0] <= 'z')) + || ((name[0] >= 'A') && (name[0] <= 'Z'))) + && (name[1] == ':')) + driveletter = name[0]; + else { + if (GetCurrentDirectoryA(MAXFILENAME, fullname) + && (fullname[1] == ':')) + driveletter = fullname[0]; + } + if (driveletter) { + printf("# Example : %c:\\.NTFS-3G\\UserMapping\n", + driveletter); + } +#else + printf("# being a hidden subdirectory of the root of the NTFS file system.\n"); + + /* Get the path to the root of the file system */ + if (name[0] != '/') { + p = getcwd(fullname,MAXFILENAME); + if (p) { + strcat(fullname,"/"); + strcat(fullname,name); + } + } else { + strcpy(fullname,name); + p = fullname; + } + if (p) { + /* go down the path to inode 5 (fails on symlinks) */ + do { + lstat(fullname,&st); + q = strrchr(p,'/'); + if (q && (st.st_ino != 5)) + *q = 0; + } while (strchr(p,'/') && (st.st_ino != 5)); + } + if (p && (st.st_ino == 5)) { + printf("# Example : "); + printname(stdout,p); + printf("/.NTFS-3G/UserMapping\n"); + } +#endif + } else { + printf("** Not possible : "); + printname(stdout,name); + printf(" was not created by a Windows user\n"); + err = TRUE; + } + return (err); +} + #ifdef WIN32 /* @@ -4676,6 +5022,31 @@ BOOL singleshow(const char *fullname) return (err); } +BOOL mapproposal(const char *fullname) +{ + char attr[256]; + ULONG attrsz; + int attrib; + int err; + + err = FALSE; + attrsz = 0; + attrib = GetFileAttributesW((LPCWSTR)fullname); + if ((attrib != INVALID_FILE_ATTRIBUTES) + && GetFileSecurityW((LPCWSTR)fullname, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION, + (char*)attr,256,&attrsz)) { + err = proposal(fullname,attr); + } else { + printf("** Could not access "); + printname(stdout,fullname); + printf("\n"); + printerror(stdout); + err = TRUE; + } + return (err); +} + #if POSIXACLS BOOL recurseset_posix(const char *fullname, const struct POSIX_SECURITY *pxdesc) @@ -4932,7 +5303,11 @@ void showfull(const char *fullname, BOOL isdir) | POSIX_ACL_GROUP | POSIX_ACL_MASK)))) showposix(pxdesc); +#if USESTUBS + stdfree(pxdesc); /* allocated within library */ +#else free(pxdesc); +#endif } #endif if ((opt_r || opt_b) && (securindex < MAXSECURID) @@ -5060,7 +5435,7 @@ static ssize_t ntfs_getxattr(const char *path, const char *name, void *value, si * Display all the parameters associated to a mounted file */ -void showmounted(const char *fullname) +BOOL showmounted(const char *fullname) { static char attr[MAXATTRSZ]; @@ -5076,7 +5451,9 @@ void showmounted(const char *fullname) u32 attrib; int level; BOOL isdir; + BOOL err; + err = FALSE; if (!stat(fullname,&st)) { isdir = S_ISDIR(st.st_mode); printf("%s ",(isdir ? "Directory" : "File")); @@ -5147,21 +5524,65 @@ void showmounted(const char *fullname) if (mapped) ntfs_free_mapping(context.mapping); #endif - } else + } else { printf("Descriptor fails sanity check\n"); + errors++; + } } else { printf("** Could not get the NTFS ACL, check whether file is on NTFS\n"); errors++; } - } else + } else { + printf("%s not found\n",fullname); + err = TRUE; + } + return (err); +} + +BOOL processmounted(const char *fullname) +{ + + static char attr[MAXATTRSZ]; + struct stat st; + int attrsz; + BOOL err; + + err = FALSE; + if (!opt_u) + err = showmounted(fullname); + else + if (!stat(fullname,&st)) { + attrsz = ntfs_getxattr(fullname,"system.ntfs_acl",attr,MAXATTRSZ); + if (attrsz > 0) { + if (opt_v) { + hexdump(attr,attrsz,8); + printf("Computed hash : 0x%08lx\n", + (unsigned long)hash((le32*)attr,attrsz)); + } + if (ntfs_valid_descr(attr,attrsz)) { + err = proposal(fullname, attr); + } else { + printf("*** Descriptor fails sanity check\n"); + errors++; + } + } else { + printf("** Could not get the NTFS ACL, check whether file is on NTFS\n"); + errors++; + } + } else { printf("%s not found\n",fullname); + err = TRUE; + } + return (err); } #else /* HAVE_SETXATTR */ -void showmounted(const char *fullname __attribute__((unused))) +BOOL processmounted(const char *fullname __attribute__((unused))) { - fprintf(stderr,"Not possible on this configuration\n"); + fprintf(stderr,"Not possible on this configuration,\n"); + fprintf(stderr,"you have to use an unmounted partition\n"); + return (TRUE); } #endif /* HAVE_SETXATTR */ @@ -5379,7 +5800,7 @@ BOOL backup(const char *volume, const char *root) now = time((time_t*)NULL); txtime = ctime(&now); if (!getuid() && open_security_api()) { - if (open_volume(volume,MS_RDONLY)) { + if (open_volume(volume,NTFS_MNT_RDONLY)) { printf("#\n# Recursive ACL collection on %s#\n",txtime); err = recurseshow(root); count = 0; @@ -5440,7 +5861,7 @@ BOOL listfiles(const char *volume, const char *root) int count; if (!getuid() && open_security_api()) { - if (open_volume(volume,MS_RDONLY)) { + if (open_volume(volume,NTFS_MNT_RDONLY)) { if (opt_r) { printf("\nRecursive file check\n"); err = recurseshow(root); @@ -5475,6 +5896,47 @@ BOOL listfiles(const char *volume, const char *root) return (err); } +BOOL mapproposal(const char *volume, const char *name) +{ + BOOL err; + u32 attrsz; + int securindex; + char attr[256]; /* header (20) and a couple of SIDs (max 40 each) */ + + err = FALSE; + if (!getuid() && open_security_api()) { + if (open_volume(volume,NTFS_MNT_RDONLY)) { + + attrsz = 0; + securindex = ntfs_get_file_security(ntfs_context,name, + OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION, + (char*)attr,MAXATTRSZ,&attrsz); + if (securindex) + err = proposal(name,attr); + else { + fprintf(stderr,"*** Could not get the ACL of %s\n", + name); + printerror(stdout); + errors++; + } + close_volume(volume); + } else { + fprintf(stderr,"Could not open volume %s\n",volume); + printerror(stdout); + err = TRUE; + } + close_security_api(); + } else { + if (getuid()) + fprintf(stderr,"This is only possible as root\n"); + else + fprintf(stderr,"Could not open security API\n"); + err = TRUE; + } + return (err); +} + #endif #ifndef WIN32 @@ -6170,7 +6632,7 @@ BOOL audit(const char *volume) err = FALSE; if (!getuid() && open_security_api()) { - if (open_volume(volume,MS_RDONLY)) { + if (open_volume(volume,NTFS_MNT_RDONLY)) { if (audit_sds(FALSE)) err = TRUE; if (audit_sds(TRUE)) err = TRUE; if (audit_sii()) err = TRUE; @@ -6505,7 +6967,7 @@ int getoptions(int argc, char *argv[]) opt_a = FALSE; opt_b = FALSE; - opt_e = FALSE; + opt_e = FALSE; opt_h = FALSE; #if FORCEMASK opt_m = FALSE; @@ -6515,6 +6977,7 @@ int getoptions(int argc, char *argv[]) #if SELFTESTS & !USESTUBS opt_t = FALSE; #endif + opt_u = FALSE; opt_v = 0; xarg = 1; err = FALSE; @@ -6554,6 +7017,9 @@ int getoptions(int argc, char *argv[]) opt_t = TRUE; break; #endif + case 'u' : + opt_u = TRUE; + break; case 'v' : opt_v++; break; @@ -6565,7 +7031,7 @@ int getoptions(int argc, char *argv[]) narg = argc - xarg; #ifdef WIN32 if ( ((opt_h || opt_s) && (narg > 1)) - || ((opt_r || opt_b) && ((narg < 1) || (narg > 2))) + || ((opt_r || opt_b || opt_u) && ((narg < 1) || (narg > 2))) #if SELFTESTS & !USESTUBS || (opt_t && (narg > 0)) #endif @@ -6599,6 +7065,8 @@ int getoptions(int argc, char *argv[]) fprintf(stderr," set the security parameters of file to perms\n"); fprintf(stderr," secaudit -r[v] perms directory\n"); fprintf(stderr," set the security parameters of files in directory to perms\n"); + fprintf(stderr," secaudit -u file\n"); + fprintf(stderr," get a user mapping proposal applicable to file\n"); #if POSIXACLS fprintf(stderr," Note: perms can be an octal mode or a Posix ACL description\n"); #else @@ -6609,12 +7077,13 @@ int getoptions(int argc, char *argv[]) #else if ( (opt_h && (narg > 1)) || (opt_a && (narg != 1)) - || ((opt_r || opt_b || opt_s) && ((narg < 1) || (narg > 3))) + || ((opt_r || opt_b || opt_s || opt_u) + && ((narg < 1) || (narg > 3))) #if SELFTESTS & !USESTUBS || (opt_t && (narg > 0)) #endif || (opt_e && !opt_s) - || (!opt_h && !opt_a && !opt_r && !opt_b && !opt_s + || (!opt_h && !opt_a && !opt_r && !opt_b && !opt_s && !opt_u #if SELFTESTS & !USESTUBS && !opt_t #endif @@ -6648,8 +7117,12 @@ int getoptions(int argc, char *argv[]) fprintf(stderr," set the security parameters of file to perms\n"); fprintf(stderr," secaudit -r[v] volume perms directory\n"); fprintf(stderr," set the security parameters of files in directory to perms\n"); + fprintf(stderr," secaudit -u volume file\n"); + fprintf(stderr," get a user mapping proposal applicable to file\n"); #ifdef HAVE_SETXATTR - fprintf(stderr," special case, does not require being root :\n"); + fprintf(stderr," special cases, do not require being root :\n"); + fprintf(stderr," secaudit -u mounted-file\n"); + fprintf(stderr," get a user mapping proposal applicable to mounted file\n"); fprintf(stderr," secaudit [-v] mounted-file\n"); fprintf(stderr," display the security parameters of a mounted file\n"); #endif @@ -6756,6 +7229,11 @@ void chkfree(void *p, const char *file, int line) } } +void *stdmalloc(size_t size) +{ + return (malloc(size)); +} + void stdfree(void *p) { free(p); @@ -6847,23 +7325,27 @@ char *argv[]; filename = (char*)malloc(2*size + 2); if (filename) { makeutf16(filename,argv[xarg]); + if (opt_u) { + cmderr = mapproposal(filename); + } else { #if POSIXACLS - if (local_build_mapping(context.mapping,filename)) { - printf("*** Could not get user mapping data\n"); - warnings++; - } + if (local_build_mapping(context.mapping,filename)) { + printf("*** Could not get user mapping data\n"); + warnings++; + } #endif - if (opt_b) - cmderr = backup(filename); - else { - if (opt_r) - cmderr = listfiles(filename); - else - cmderr = singleshow(filename); - } + if (opt_b) + cmderr = backup(filename); + else { + if (opt_r) + cmderr = listfiles(filename); + else + cmderr = singleshow(filename); + } #if POSIXACLS - ntfs_free_mapping(context.mapping); + ntfs_free_mapping(context.mapping); #endif + } free(filename); } else { fprintf(stderr,"No more memory\n"); @@ -6977,7 +7459,8 @@ char *argv[]; printf("** %u %s found\n",errors, (errors > 1 ? "errors were" : "error was")); else - printf("No errors were found\n"); + if (!cmderr) + printf("No errors were found\n"); if (!isatty(1)) { fflush(stdout); if (warnings) @@ -7006,13 +7489,14 @@ char *argv[]; int main(int argc, char *argv[]) { FILE *fd; - unsigned int mode; const char *p; int xarg; BOOL cmderr; int i; #if POSIXACLS struct POSIX_SECURITY *pxdesc; +#else + unsigned int mode; #endif printf("%s\n",BANNER); @@ -7061,7 +7545,7 @@ int main(int argc, char *argv[]) if (opt_s) cmderr = dorestore(argv[xarg],stdin); else - showmounted(argv[xarg]); + cmderr = processmounted(argv[xarg]); break; case 2 : if (opt_b) @@ -7078,16 +7562,18 @@ int main(int argc, char *argv[]) cmderr = TRUE; } } else - cmderr = listfiles(argv[xarg],argv[xarg+1]); + if (opt_u) + cmderr = mapproposal(argv[xarg],argv[xarg+1]); + else + cmderr = listfiles(argv[xarg],argv[xarg+1]); break; case 3 : - mode = 0; p = argv[xarg+1]; #if POSIXACLS pxdesc = encode_posix_acl(p); if (pxdesc) { if (!getuid() && open_security_api()) { - if (open_volume(argv[xarg],MS_NONE)) { + if (open_volume(argv[xarg],NTFS_MNT_NONE)) { if (opt_r) { for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) securdata[i] = (struct SECURITY_DATA*)NULL; @@ -7112,6 +7598,7 @@ int main(int argc, char *argv[]) } else cmderr = TRUE; #else + mode = 0; while ((*p >= '0') && (*p <= '7')) mode = (mode << 3) + (*p++) - '0'; if (*p) { @@ -7119,7 +7606,7 @@ int main(int argc, char *argv[]) cmderr = TRUE; } else if (!getuid() && open_security_api()) { - if (open_volume(argv[xarg],MS_NONE)) { + if (open_volume(argv[xarg],NTFS_MNT_NONE)) { if (opt_r) { for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) securdata[i] = (struct SECURITY_DATA*)NULL; |