2
* Windows to Linux user mapping for ntfs-3g
5
* Copyright (c) 2007-2008 Jean-Pierre Andre
7
* A quick'n dirty program scanning owners of files in
8
* "c:\Documents and Settings" (and "c:\Users")
9
* and asking user to map them to Linux accounts
14
* - first version, limited to Win32
17
* - ported to Linux (rewritten would be more correct)
19
* Nov 2007 Version 1.0.0
20
* - added more defaults
22
* Nov 2007 Version 1.0.1
23
* - avoided examining files whose name begin with a '$'
25
* Jan 2008 Version 1.0.2
26
* - moved user mapping file to directory .NTFS-3G (hidden for Linux)
27
* - fixed an error case in Windows version
29
* Nov 2008 Version 1.1.0
30
* - fixed recursions for account in Linux version
31
* - searched owner in c:\Users (standard location for Vista)
33
* May 2009 Version 1.1.1
34
* - reordered mapping records to limit usage of same SID for user and group
35
* - fixed decoding SIDs on 64-bit systems
36
* - fixed a pointer to dynamic data in mapping tables
37
* - fixed default mapping on Windows
38
* - fixed bug for renaming UserMapping on Windows
40
* May 2009 Version 1.1.2
41
* - avoided selecting DOS names on Linux
43
* Nov 2009 Version 1.1.3
44
* - shutdown compiler warnings for unused parameters
46
* Jan 2010 Version 1.1.4
47
* - fixed compilation problems for Mac OSX (Erik Larsson)
51
* This program is free software; you can redistribute it and/or modify
52
* it under the terms of the GNU General Public License as published by
53
* the Free Software Foundation; either version 2 of the License, or
54
* (at your option) any later version.
56
* This program is distributed in the hope that it will be useful,
57
* but WITHOUT ANY WARRANTY; without even the implied warranty of
58
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59
* GNU General Public License for more details.
61
* You should have received a copy of the GNU General Public License
62
* along with this program (in the main directory of the NTFS-3G
63
* distribution in the file COPYING); if not, write to the Free Software
64
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
68
* General parameters which may have to be adapted to needs
72
#define USESTUBS 1 /* API stubs generated at link time */
74
#define USESTUBS 0 /* direct calls to API, based on following definitions */
75
#define ENVNTFS3G "NTFS3G"
76
#define LIBFILE64 "/lib64/libntfs-3g.so.851"
77
#define LIBFILE "/lib/libntfs-3g.so.851"
80
#define GET_FILE_SECURITY "ntfs_get_file_security"
81
#define SET_FILE_SECURITY "ntfs_set_file_security"
82
#define READ_DIRECTORY "ntfs_read_directory"
83
#define INIT_FILE_SECURITY "ntfs_initialize_file_security"
84
#define LEAVE_FILE_SECURITY "ntfs_leave_file_security"
86
#define VERSION "1.1.4"
87
#define MAPDIR ".NTFS-3G"
88
#define MAPFILE "UserMapping"
89
#define MAXATTRSZ 2048
92
#define OWNERS1 "Documents and Settings"
93
#define OWNERS2 "Users"
96
* Define WIN32 for a Windows execution
97
* may have to be adapted to compiler or something else
101
#if defined(__WIN32) | defined(__WIN32__) | defined(WNSC)
107
#define BANNER "Generated by usermap for Windows, v " VERSION
109
#define BANNER "Generated by usermap for Linux, v " VERSION
117
#include <sys/types.h>
118
#include <sys/stat.h>
122
* Define the security API according to platform
132
typedef enum { DENIED, AGREED } boolean;
139
typedef enum { DENIED, AGREED } boolean, BOOL;
140
typedef unsigned int DWORD; /* must be 32 bits whatever the platform */
141
typedef DWORD *LPDWORD;
143
enum { OWNER_SECURITY_INFORMATION = 1,
144
GROUP_SECURITY_INFORMATION = 2,
145
DACL_SECURITY_INFORMATION = 4,
146
SACL_SECURITY_INFORMATION = 8
156
typedef int (*dircallback)(struct CALLBACK *context, char *ntfsname,
157
int length, int type, long long pos, unsigned long long mft_ref,
158
unsigned int dt_type);
162
#define STATIC static
164
BOOL ntfs_get_file_security(void *scapi,
165
const char *path, DWORD selection,
166
char *buf, DWORD buflen, LPDWORD psize);
167
BOOL ntfs_set_file_security(void *scapi,
168
const char *path, DWORD selection, const char *attr);
169
BOOL ntfs_read_directory(void *scapi,
170
const char *path, dircallback callback, void *context);
171
void *ntfs_initialize_file_security(const char *device,
173
BOOL ntfs_leave_file_security(void *scapi);
179
BOOL (*ntfs_get_file_security)(void *scapi,
180
const char *path, DWORD selection,
181
char *buf, DWORD buflen, LPDWORD psize);
182
BOOL (*ntfs_set_file_security)(void *scapi,
183
const char *path, DWORD selection, const char *attr);
184
BOOL (*ntfs_read_directory)(void *scapi,
185
const char *path, dircallback callback, void *context);
186
void *(*ntfs_initialize_file_security)(const char *device,
188
BOOL (*ntfs_leave_file_security)(void *scapi);
192
STATIC boolean open_security_api(void);
193
STATIC boolean close_security_api(void);
194
STATIC boolean open_volume(const char *volume);
195
STATIC boolean close_volume(const char *volume);
200
struct MAPPING *next;
204
const unsigned char *sid;
209
struct MAPPING *firstmapping;
210
struct MAPPING *lastmapping;
213
char *currentwinname;
215
unsigned char *currentsid;
221
void *ntfs_context = (void*)NULL;
224
* Shut down compiler warnings for unused parameters
227
static long unused(const void *p)
233
* Open and close the security API (platform dependent)
236
STATIC boolean open_security_api(void)
246
libfile = getenv(ENVNTFS3G);
248
libfile = (sizeof(char*) == 8 ? LIBFILE64 : LIBFILE);
249
ntfs_handle = dlopen(libfile,RTLD_LAZY);
251
ntfs_initialize_file_security =
252
dlsym(ntfs_handle,INIT_FILE_SECURITY);
255
fprintf(stderr," %s\n",error);
257
ntfs_leave_file_security =
258
dlsym(ntfs_handle,LEAVE_FILE_SECURITY);
259
ntfs_get_file_security =
260
dlsym(ntfs_handle,GET_FILE_SECURITY);
261
ntfs_set_file_security =
262
dlsym(ntfs_handle,SET_FILE_SECURITY);
263
ntfs_read_directory =
264
dlsym(ntfs_handle,READ_DIRECTORY);
265
err = !ntfs_initialize_file_security
266
|| !ntfs_leave_file_security
267
|| !ntfs_get_file_security
268
|| !ntfs_set_file_security
269
|| !ntfs_read_directory;
271
fprintf(stderr,"ntfs-3g API not available\n");
274
fprintf(stderr,"Could not open ntfs-3g library\n");
275
fprintf(stderr,"\nPlease set environment variable \"" ENVNTFS3G "\"\n");
276
fprintf(stderr,"to appropriate path and retry\n");
282
STATIC boolean close_security_api(void)
287
return (!dlclose(ntfs_handle));
292
* Open and close a volume (platform dependent)
293
* assuming a single volume needs to be opened at any time
296
STATIC boolean open_volume(const char *volume)
302
ntfs_context = ntfs_initialize_file_security(volume,0);
304
fprintf(stderr,"\"%s\" opened\n",volume);
307
fprintf(stderr,"Could not open \"%s\"\n",volume);
308
fprintf(stderr,"Make sure \"%s\" is not mounted\n",volume);
311
fprintf(stderr,"A volume is already open\n");
315
STATIC boolean close_volume(const char *volume)
319
r = ntfs_leave_file_security(ntfs_context);
321
fprintf(stderr,"\"%s\" closed\n",volume);
323
fprintf(stderr,"Could not close \"%s\"\n",volume);
324
ntfs_context = (void*)NULL;
329
* A poor man's conversion of Unicode to UTF8
330
* We are assuming outputs to terminal expect UTF8
333
STATIC void to_utf8(char *dst, const char *src, unsigned int cnt)
338
for (i=0; i<cnt; i++) {
340
ch += (*src++ & 255) << 8;
345
*dst++ = 0xc0 + (ch >> 6);
346
*dst++ = 0x80 + (ch & 63);
348
*dst++ = 0xe0 + (ch >> 12);
349
*dst++ = 0x80 + ((ch >> 6) & 63);
350
*dst++ = 0x80 + (ch & 63);
356
STATIC int utf8_size(const char *src, unsigned int cnt)
363
for (i=0; i<cnt; i++) {
365
ch += (*src++ & 255) << 8;
380
STATIC void welcome(void)
382
printf("\nThis tool will help you to build a mapping of Windows users\n");
383
printf("to Linux users.\n");
384
printf("Be prepared to give Linux user id (uid) and group id (gid)\n");
385
printf("for owners of files which will be selected.\n");
388
STATIC unsigned int get2l(const unsigned char *attr, int p)
394
for (i = 0; i < 2; i++)
395
v += (attr[p + i] & 255) << (8 * i);
399
STATIC unsigned long get4l(const unsigned char *attr, int p)
405
for (i = 0; i < 4; i++)
406
v += (attr[p + i] & 255L) << (8 * i);
410
STATIC unsigned long long get6h(const unsigned char *attr, int p)
413
unsigned long long v;
416
for (i = 0; i < 6; i++)
417
v = (v << 8) + (attr[p + i] & 255L);
421
STATIC char *decodesid(const unsigned char *sid)
425
unsigned long long auth;
426
unsigned long subauth;
428
str = (char *)malloc(MAXSIDSZ);
431
sprintf(&str[strlen(str)], "-%d", sid[0]); /* revision */
432
auth = get6h(sid, 2);
434
sprintf(&str[strlen(str)], "-%I64u", auth); /* main authority */
436
sprintf(&str[strlen(str)], "-%llu", auth); /* main authority */
438
for (i = 0; (i < 8) && (i < sid[1]); i++) {
439
subauth = get4l(sid, 8 + 4 * i);
440
sprintf(&str[strlen(str)], "-%lu", subauth); /* sub-authority */
447
* Test whether a generic group (S-1-5-21- ... -513)
450
STATIC boolean isgenericgroup(const char *sid)
454
yes = !strncmp(sid,"S-1-5-21-",9)
455
&& !strcmp(strrchr(sid,'-'),"-513");
459
STATIC unsigned char *makegroupsid(const unsigned char *sid)
461
static unsigned char groupsid[MAXSIDSZ];
465
memcpy(groupsid, sid, size);
466
/* replace last level by 513 */
467
groupsid[size - 4] = 1;
468
groupsid[size - 3] = 2;
469
groupsid[size - 2] = 0;
470
groupsid[size - 1] = 0;
474
STATIC void domapping(const char *accname, const char *filename,
475
const unsigned char *sid, int type)
482
struct MAPPING *mapping;
486
if ((get6h(sid, 2) == 5) && (get4l(sid, 8) == 21)) {
487
sidstr = decodesid(sid);
488
mapping = firstmapping;
489
while (mapping && strcmp(mapping->sidstr, sidstr))
490
mapping = mapping->next;
494
|| !strcmp(mapping->login, accname)))
495
free(sidstr); /* decision already known */
501
printf("Under Windows login \"%s\"\n", accname);
502
printf(" file \"%s\" has no mapped %s\n",
503
filename,(type ? "group" : "owner"));
504
printf("By which Linux login should this file be owned ?\n");
505
printf("Enter %s of login, or just press \"enter\" if this file\n",
506
(type ? "gid" : "uid"));
507
printf("does not belong to a user, or you do not known to whom\n");
513
p = fgets(buf, 80, stdin);
514
if (p && p[0] && (p[strlen(p) - 1] == '\n'))
515
p[strlen(p) - 1] = '\0';
518
&& ((p[0] == '0') || !strcmp(p, "root"))) {
519
printf("Please do not map users to root\n");
520
printf("Administrators will be mapped automatically\n");
524
printf("Please retry\n");
529
malloc(sizeof(struct MAPPING));
530
mapping->next = (struct MAPPING *)NULL;
531
mapping->defined = DENIED;
533
lastmapping->next = mapping;
535
firstmapping = mapping;
536
lastmapping = mapping;
540
idstr = (char *)malloc(strlen(p) + 1);
544
mapping->uidstr = "";
545
mapping->gidstr = idstr;
547
mapping->uidstr = idstr;
548
mapping->gidstr = idstr;
550
mapping->defined = AGREED;
553
mapping->sidstr = sidstr;
555
login = (char*)malloc(strlen(accname) + 1);
557
strcpy(login,accname);
558
mapping->login = login;
560
mapping->login = (char*)NULL;
561
sidsz = 8 + sid[1]*4;
562
p = (char*)malloc(sidsz);
564
memcpy(p, sid, sidsz);
566
mapping->sid = (unsigned char*)p;
572
STATIC void listaclusers(const char *accname, const unsigned char *attr, int off)
578
cnt = get2l(attr, off + 4);
580
for (i = 0; i < cnt; i++) {
581
domapping(accname, (char *)NULL, &attr[off + x + 8], 2);
582
x += get2l(attr, off + x + 2);
588
STATIC void account(const char *accname, const char *dir, const char *name, int type)
590
unsigned char attr[MAXATTRSZ];
591
unsigned long attrsz;
595
fullname = (char *)malloc(strlen(dir) + strlen(name) + 2);
597
strcpy(fullname, dir);
598
strcat(fullname, "\\");
599
strcat(fullname, name);
600
attrib = GetFileAttributes(fullname);
601
if (attrib & 0x10) { /* only directories processed */
603
(fullname, OWNER_SECURITY_INFORMATION, attr, MAXATTRSZ,
605
domapping(accname, name, &attr[20], 0);
608
(fullname, GROUP_SECURITY_INFORMATION, attr,
610
domapping(accname, name, &attr[20], 1);
612
printf(" No group SID\n");
615
(fullname, DACL_SECURITY_INFORMATION, attr,
616
MAXATTRSZ, &attrsz)) {
618
listaclusers(accname, attr, 20);
621
(" No discretionary access control list\n");
630
STATIC void account(const char *accname, const char *dir, const char *name, int type)
632
unsigned char attr[MAXATTRSZ];
636
fullname = (char *)malloc(strlen(dir) + strlen(name) + 2);
638
strcpy(fullname, dir);
639
strcat(fullname, "/");
640
strcat(fullname, name);
641
if (ntfs_get_file_security(ntfs_context,
642
fullname, OWNER_SECURITY_INFORMATION,
643
(char*)attr, MAXATTRSZ, &attrsz)) {
644
domapping(accname, name, &attr[20], 0);
646
if (ntfs_get_file_security(ntfs_context,
647
fullname, GROUP_SECURITY_INFORMATION,
648
(char*)attr, MAXATTRSZ, &attrsz))
649
domapping(accname, name, &attr[20], 1);
651
printf(" No group SID\n");
653
if (ntfs_get_file_security(ntfs_context,
654
fullname, DACL_SECURITY_INFORMATION,
655
(char*)attr, MAXATTRSZ, &attrsz)) {
657
listaclusers(accname, attr, 20);
659
printf(" No discretionary access control list for %s !\n",
670
* recursive search of file owners and groups in a directory
675
STATIC boolean recurse(const char *accname, const char *dir, int levels)
677
WIN32_FIND_DATA found;
684
filter = (char *)malloc(strlen(dir) + 5);
687
strcat(filter, "\\*.*");
688
search = FindFirstFile(filter, &found);
689
if (search != INVALID_HANDLE_VALUE) {
691
if (found.cFileName[0] != '.') {
692
account(accname, dir, found.cFileName,1);
695
(char *)malloc(strlen(dir) +
696
strlen(found.cFileName)
699
strcpy(fullname, dir);
700
strcat(fullname, "\\");
710
} while (FindNextFile(search, &found));
715
printf("Directory %s not found\n",dir);
723
STATIC boolean recurse(const char *accname, const char *dir, int levels, int docset);
725
STATIC int callback(struct CALLBACK *context, char *ntfsname,
726
int length, int type, long long pos, unsigned long long mft_ref,
727
unsigned int dt_type)
734
unused((void*)&mft_ref);
735
unused((void*)&dt_type);
736
fullname = (char *)malloc(strlen(context->dir)
737
+ utf8_size(ntfsname, length) + 2);
739
if (strcmp(context->dir,"/")) {
740
strcpy(fullname, context->dir);
741
strcat(fullname, "/");
743
strcpy(fullname,"/");
744
/* Unicode to ascii conversion by a lazy man */
745
name = &fullname[strlen(fullname)];
746
to_utf8(name, ntfsname, length);
747
/* ignore special files and DOS names */
751
&& (name[0] != '$')) {
752
switch (context->docset) {
755
* only "Documents and Settings"
758
if (!strcmp(name,OWNERS1)
759
|| !strcmp(name,OWNERS2)) {
760
recurse((char*)NULL, fullname, 2, 1);
764
* within "Documents and Settings"
768
accname = (char*)malloc(strlen(name) + 1);
770
strcpy(accname, name);
771
if (context->levels > 0)
772
recurse(name, fullname,
773
context->levels - 1, 0);
777
* not related to "Documents and Settings"
781
account(context->accname, context->dir,
783
if (context->levels > 0)
784
recurse(context->accname, fullname,
785
context->levels - 1, 0);
791
/* check expected return value */
795
STATIC boolean recurse(const char *accname, const char *dir, int levels, int docset)
797
struct CALLBACK context;
802
context.accname = accname;
803
context.levels = levels;
804
context.docset = docset;
805
ntfs_read_directory(ntfs_context,dir,callback,&context);
811
* Search directory "Documents and Settings" for user accounts
816
STATIC boolean getusers(const char *dir, int levels)
818
WIN32_FIND_DATA found;
826
/* first get files from "Documents and Settings" */
828
if (sizeof(OWNERS1) > sizeof(OWNERS2))
829
filter = (char *)malloc(strlen(dir) + strlen(OWNERS1) + 6);
831
filter = (char *)malloc(strlen(dir) + strlen(OWNERS2) + 6);
835
strcat(filter, "\\");
836
strcat(filter, docset);
837
strcat(filter, "\\*.*");
838
search = FindFirstFile(filter, &found);
839
/* if failed, retry with "Users" */
840
if (search == INVALID_HANDLE_VALUE) {
843
strcat(filter, "\\");
844
strcat(filter, docset);
845
strcat(filter, "\\*.*");
846
search = FindFirstFile(filter, &found);
848
if (search != INVALID_HANDLE_VALUE) {
850
if (found.cFileName[0] != '.') {
852
(char *)malloc(strlen(dir)
854
+ strlen(found.cFileName) + 3);
856
malloc(strlen(found.cFileName) + 1);
857
if (fullname && accname) {
861
strcpy(fullname, dir);
862
strcat(fullname, "\\");
863
strcat(fullname, docset);
864
strcat(fullname, "\\");
867
recurse(accname, fullname, 2);
872
} while (FindNextFile(search, &found));
875
printf("No subdirectory found in %s\\%s\n",dir,docset);
877
/* now search in other directories */
879
strcat(filter, "\\*.*");
880
search = FindFirstFile(filter, &found);
881
if (search != INVALID_HANDLE_VALUE) {
883
if ((found.cFileName[0] != '.')
884
&& strcmp(found.cFileName,OWNERS1)
885
&& strcmp(found.cFileName,OWNERS2)) {
887
(char *)malloc(strlen(dir)
888
+ strlen(found.cFileName) + 2);
890
strcpy(fullname, dir);
891
strcat(fullname, "\\");
894
recurse((char*)NULL, fullname, 2);
898
} while (FindNextFile(search, &found));
901
printf("No directory found in %s\n",dir);
910
STATIC boolean getusers(const char *dir, int levels)
913
struct CALLBACK context;
915
printf("* Search for \"" OWNERS1 "\" and \"" OWNERS2 "\"\n");
918
context.accname = (const char*)NULL;
919
context.levels = levels;
921
ntfs_read_directory(ntfs_context,dir,callback,&context);
922
printf("* Search for other directories %s\n",dir);
924
ntfs_read_directory(ntfs_context,dir,callback,&context);
933
* Get the current login name (Win32 only)
936
STATIC void loginname(boolean silent)
941
unsigned long namesz;
943
unsigned long domainsz;
949
winname = (char*)malloc(MAXNAMESZ);
950
domain = (char*)malloc(MAXNAMESZ);
951
sid = (char*)malloc(MAXSIDSZ);
954
domainsz = MAXNAMESZ;
959
&& GetUserName(winname,&namesz)) {
960
winname[namesz] = '\0';
962
printf("Your current user name is %s\n",winname);
964
r = LookupAccountName((char*)NULL,winname,sid,&sidsz,
965
domain,&domainsz,&nametype);
967
domain[domainsz] = '\0';
969
printf("Your account domain is %s\n",domain);
974
currentwinname = winname;
975
currentdomain = domain;
978
currentwinname = (char*)NULL;
979
currentdomain = (char*)NULL;
980
currentsid = (unsigned char*)NULL;
985
* Minimal output on stdout
988
boolean minimal(unsigned char *sid)
990
const unsigned char *groupsid;
995
groupsid = makegroupsid(sid);
996
printf("# %s\n",BANNER);
997
printf("# For Windows account \"%s\" in domain \"%s\"\n",
998
currentwinname, currentdomain);
999
printf("# Replace \"user\" and \"group\" hereafter by matching Linux login\n");
1000
printf("user::%s\n",decodesid(sid));
1001
printf(":group:%s\n",decodesid(groupsid));
1009
STATIC boolean outputmap(const char *volume, const char *dir)
1015
struct MAPPING *mapping;
1026
fullname = (char *)malloc(strlen(MAPFILE) + 1
1027
+ strlen(volume) + 1
1028
+ (dir ? strlen(dir) + 1 : 0));
1031
strcpy(fullname, volume);
1032
if (dir && dir[0]) {
1033
strcat(fullname, "\\");
1034
strcat(fullname,dir);
1037
/* build directory, if not present */
1038
if (GetFileAttributes(fullname) & 0x80000000) {
1039
printf("* Creating directory %s\n", fullname);
1043
strcat(fullname, "\\");
1044
strcat(fullname, MAPFILE);
1047
if (!(GetFileAttributes(fullname) & 0x80000000)) {
1048
backup = (char*)malloc(strlen(fullname) + 5);
1049
strcpy(backup,fullname);
1050
strcat(backup,".bak");
1052
if (!rename(fullname,backup))
1053
printf("* Old mapping file moved to %s\n",backup);
1056
strcpy(fullname, MAPFILE);
1059
s = stat(fullname,&st);
1061
backup = (char*)malloc(strlen(fullname + 5));
1062
strcpy(backup,fullname);
1063
strcat(backup,".bak");
1064
if (rename(fullname,backup))
1065
printf("* Old mapping file moved to %s\n",backup);
1069
printf("* Creating file %s\n", fullname);
1072
fn = open(fullname,O_CREAT + O_TRUNC + O_WRONLY + O_BINARY,
1073
S_IREAD + S_IWRITE);
1075
fn = open(fullname,O_CREAT + O_TRUNC + O_WRONLY,
1076
S_IREAD + S_IWRITE);
1079
sprintf(buf,"# %s\n",BANNER);
1080
if (!write(fn,buf,strlen(buf)))
1084
/* records for owner only or group only */
1085
for (mapping = firstmapping; mapping && !err;
1086
mapping = mapping->next)
1087
if (mapping->defined
1088
&& (!mapping->uidstr[0] || !mapping->gidstr[0])) {
1089
sprintf(buf,"%s:%s:%s\n",
1093
if (!write(fn,buf,strlen(buf)))
1098
/* records for both owner and group */
1099
for (mapping = firstmapping; mapping && !err;
1100
mapping = mapping->next)
1101
if (mapping->defined
1102
&& mapping->uidstr[0] && mapping->gidstr[0]) {
1103
sprintf(buf,"%s:%s:%s\n",
1107
if (!write(fn,buf,strlen(buf)))
1115
printf("Undecided :\n");
1116
for (mapping = firstmapping; mapping;
1117
mapping = mapping->next)
1118
if (!mapping->defined) {
1119
printf(" %s\n", mapping->sidstr);
1123
printf("\n* You will have to move the file \"" MAPFILE "\"\n");
1124
printf(" to directory \"" MAPDIR "\" after mounting\n");
1129
fprintf(stderr, "* Could not create mapping file \"%s\"\n", fullname);
1133
STATIC boolean sanitize(void)
1139
struct MAPPING *mapping;
1140
struct MAPPING *firstowner;
1141
struct MAPPING *genericgroup;
1142
struct MAPPING *group;
1145
/* count owners and groups */
1146
/* and find first user, and a generic group */
1149
firstowner = (struct MAPPING*)NULL;
1150
genericgroup = (struct MAPPING*)NULL;
1151
for (mapping=firstmapping; mapping; mapping=mapping->next) {
1152
if (mapping->defined && mapping->uidstr[0]) {
1154
firstowner = mapping;
1157
if (mapping->defined && mapping->gidstr[0] && !mapping->uidstr[0]) {
1160
if (!mapping->defined && isgenericgroup(mapping->sidstr)) {
1161
genericgroup = mapping;
1165
/* no user defined, on Windows, suggest a mapping */
1166
/* based on account currently used */
1167
if (!ownercnt && currentwinname && currentsid) {
1171
printf("\nYou have defined no file owner,\n");
1172
printf(" please enter the Linux login which should be mapped\n");
1173
printf(" to account you are currently using\n");
1174
printf(" Linux user ? ");
1175
p = fgets(buf, 80, stdin);
1176
if (p && p[0] && (p[strlen(p) - 1] == '\n'))
1177
p[strlen(p) - 1] = '\0';
1179
firstowner = (struct MAPPING*)malloc(sizeof(struct MAPPING));
1180
owner = (char*)malloc(strlen(p) + 1);
1181
if (firstowner && owner) {
1183
firstowner->next = firstmapping;
1184
firstowner->uidstr = owner;
1185
firstowner->gidstr = "";
1186
firstowner->sidstr = decodesid(currentsid);
1187
firstowner->sid = currentsid;
1188
firstmapping = firstowner;
1190
/* prefer a generic group with the same authorities */
1191
for (mapping=firstmapping; mapping;
1192
mapping=mapping->next)
1193
if (!mapping->defined
1194
&& isgenericgroup(mapping->sidstr)
1195
&& !memcmp(firstowner->sidstr,
1197
strlen(mapping->sidstr)-3))
1198
genericgroup = mapping;
1205
* No group was selected, but there were a generic group
1206
* insist in using it, associated to the first user
1209
printf("\nYou have defined no group, this can cause problems\n");
1210
printf("Do you accept defining a standard group ?\n");
1211
if (!fgets(buf,80,stdin)
1213
&& (buf[0] != 'N'))) {
1215
genericgroup->uidstr = "";
1216
genericgroup->gidstr = firstowner->uidstr;
1217
genericgroup->defined = AGREED;
1219
group = (struct MAPPING*)
1220
malloc(sizeof(struct MAPPING));
1222
makegroupsid(firstowner->sid));
1223
if (group && sidstr) {
1225
group->gidstr = firstowner->
1227
group->sidstr = sidstr;
1228
group->defined = AGREED;
1229
group->next = firstmapping;
1230
firstmapping = group;
1237
printf("\nYou have defined no user, no mapping can be built\n");
1244
STATIC boolean checkoptions(int argc, char *argv[], boolean silent)
1255
for (xarg=1; (xarg<argc) && !err; xarg++) {
1257
if (pvol[0] && (pvol[1] == ':') && !pvol[2]) {
1258
err = !(((pvol[0] >= 'A') && (pvol[0] <= 'Z'))
1259
|| ((pvol[0] >= 'a') && (pvol[0] <= 'z')));
1264
fprintf(stderr, "Usage : usermap [vol1: [vol2: ...]]\n");
1265
fprintf(stderr, " \"voln\" are the letters of the partition to share with Linux\n");
1266
fprintf(stderr, " eg C:\n");
1267
fprintf(stderr, " the Windows system partition should be named first\n");
1270
unused((void*)argv);
1271
unused((void*)&silent);
1274
fprintf(stderr, "Usage : usermap dev1 [dev2 ...]\n");
1275
fprintf(stderr, " \"dev.\" are the devices to share with Windows\n");
1276
fprintf(stderr, " eg /dev/sdb1\n");
1277
fprintf(stderr, " the devices should not be mounted\n");
1278
fprintf(stderr, " the Windows system partition should be named first\n");
1281
fprintf(stderr, "\nSorry, only root can start usermap\n");
1288
STATIC boolean process(int argc, char *argv[])
1294
firstmapping = (struct MAPPING *)NULL;
1295
lastmapping = (struct MAPPING *)NULL;
1298
for (xarg=1; (xarg<argc) && ok; xarg++) {
1299
printf("\n* Scanning \"%s\" (two levels)\n",argv[xarg]);
1300
ok = getusers(argv[xarg],2);
1303
for (xarg=1; (xarg<argc) && ok; xarg++)
1304
if (open_volume(argv[xarg])) {
1305
printf("\n* Scanning \"%s\" (two levels)\n",argv[xarg]);
1306
ok = getusers("/",2);
1307
close_volume(argv[xarg]);
1311
if (ok && sanitize()) {
1312
targ = (argc > 2 ? 2 : 1);
1313
if (!outputmap(argv[targ],MAPDIR)) {
1314
printf("Trying to write file on root directory\n");
1315
if (outputmap(argv[targ],(const char*)NULL)) {
1316
printf("\nNote : you will have to move the file to directory \"%s\" on Linux\n",
1327
int main(int argc, char *argv[])
1332
silent = !isatty(1);
1335
if (checkoptions(argc, argv, silent)) {
1339
ok = minimal(currentsid);
1341
ok = process(argc, argv);
1343
if (open_security_api()) {
1344
ok = process(argc,argv);
1345
if (!close_security_api()) ok = DENIED;