3 Copyright 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
17 #include <sys/cygwin.h>
21 #include <sys/fcntl.h>
24 static const char version
[] = "$Revision$";
26 SID_IDENTIFIER_AUTHORITY sid_world_auth
= {SECURITY_WORLD_SID_AUTHORITY
};
27 SID_IDENTIFIER_AUTHORITY sid_nt_auth
= {SECURITY_NT_AUTHORITY
};
29 NET_API_STATUS
WINAPI (*netapibufferfree
)(PVOID
);
30 NET_API_STATUS
WINAPI (*netuserenum
)(LPWSTR
,DWORD
,DWORD
,PBYTE
*,DWORD
,PDWORD
,PDWORD
,PDWORD
);
31 NET_API_STATUS
WINAPI (*netlocalgroupenum
)(LPWSTR
,DWORD
,PBYTE
*,DWORD
,PDWORD
,PDWORD
,PDWORD
);
32 NET_API_STATUS
WINAPI (*netgetdcname
)(LPWSTR
,LPWSTR
,PBYTE
*);
33 NET_API_STATUS
WINAPI (*netusergetinfo
)(LPWSTR
,LPWSTR
,DWORD
,PBYTE
*);
36 #define min(a,b) (((a)<(b))?(a):(b))
42 HANDLE h
= LoadLibrary ("netapi32.dll");
47 if (!(netapibufferfree
= (void *) GetProcAddress (h
, "NetApiBufferFree")))
49 if (!(netuserenum
= (void *) GetProcAddress (h
, "NetUserEnum")))
51 if (!(netlocalgroupenum
= (void *) GetProcAddress (h
, "NetLocalGroupEnum")))
53 if (!(netgetdcname
= (void *) GetProcAddress (h
, "NetGetDCName")))
55 if (!(netusergetinfo
= (void *) GetProcAddress (h
, "NetUserGetInfo")))
69 sprintf(t
, "%u", GetSidIdentifierAuthority (sid
)->Value
[5]);
71 for (i
= 0; i
< *GetSidSubAuthorityCount (sid
); ++i
)
73 sprintf(t
, "-%lu", *GetSidSubAuthority (sid
, i
));
80 psx_dir (char *in
, char *out
)
82 if (isalpha (in
[0]) && in
[1] == ':')
84 sprintf (out
, "/cygdrive/%c", in
[0]);
103 uni2ansi (LPWSTR wcs
, char *mbs
, int size
)
106 WideCharToMultiByte (CP_ACP
, 0, wcs
, -1, mbs
, size
, NULL
, NULL
);
112 print_win_error(DWORD code
)
116 if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
117 | FORMAT_MESSAGE_IGNORE_INSERTS
,
120 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
121 (LPTSTR
) buf
, sizeof (buf
), NULL
))
122 fprintf (stderr
, "mkpasswd: [%lu] %s", code
, buf
);
124 fprintf (stderr
, "mkpasswd: error %lu", code
);
128 enum_users (LPWSTR servername
, int print_sids
, int print_cygpath
,
129 const char * passed_home_path
, int id_offset
, char *disp_username
)
132 DWORD entriesread
= 0;
133 DWORD totalentries
= 0;
134 DWORD resume_handle
= 0;
136 char ansi_srvname
[256];
140 uni2ansi (servername
, ansi_srvname
, sizeof (ansi_srvname
));
146 if (disp_username
!= NULL
)
148 MultiByteToWideChar (CP_ACP
, 0, disp_username
, -1, uni_name
, 512 );
149 rc
= netusergetinfo(servername
, (LPWSTR
) & uni_name
, 3,
150 (LPBYTE
*) &buffer
);
154 rc
= netuserenum (servername
, 3, FILTER_NORMAL_ACCOUNT
,
155 (LPBYTE
*) & buffer
, 1024,
156 &entriesread
, &totalentries
, &resume_handle
);
159 case ERROR_ACCESS_DENIED
:
163 case ERROR_MORE_DATA
:
172 for (i
= 0; i
< entriesread
; i
++)
176 char homedir_psx
[MAX_PATH
];
177 char homedir_w32
[MAX_PATH
];
178 char domain_name
[100];
179 DWORD domname_len
= 100;
180 char psid_buffer
[1024];
181 PSID psid
= (PSID
) psid_buffer
;
182 DWORD sid_length
= 1024;
183 SID_NAME_USE acc_type
;
185 int uid
= buffer
[i
].usri3_user_id
;
186 int gid
= buffer
[i
].usri3_primary_group_id
;
187 uni2ansi (buffer
[i
].usri3_name
, username
, sizeof (username
));
188 uni2ansi (buffer
[i
].usri3_full_name
, fullname
, sizeof (fullname
));
189 homedir_w32
[0] = homedir_psx
[0] = '\0';
190 if (passed_home_path
[0] == '\0')
192 uni2ansi (buffer
[i
].usri3_home_dir
, homedir_w32
,
193 sizeof (homedir_w32
));
194 if (homedir_w32
[0] != '\0')
197 cygwin_conv_to_posix_path (homedir_w32
, homedir_psx
);
199 psx_dir (homedir_w32
, homedir_psx
);
203 strcpy (homedir_psx
, "/home/");
204 strcat (homedir_psx
, username
);
209 strcpy (homedir_psx
, passed_home_path
);
210 strcat (homedir_psx
, username
);
215 if (!LookupAccountName (servername
? ansi_srvname
: NULL
,
218 domain_name
, &domname_len
,
221 print_win_error(GetLastError ());
224 else if (acc_type
== SidTypeDomain
)
228 strcpy (domname
, domain_name
);
229 strcat (domname
, "\\");
230 strcat (domname
, username
);
233 if (!LookupAccountName (servername
? ansi_srvname
: NULL
,
236 domain_name
, &domname_len
,
239 print_win_error(GetLastError ());
244 printf ("%s:unused_by_nt/2000/xp:%d:%d:%s%s%s%s%s%s%s%s:%s:/bin/bash\n",
249 print_sids
&& fullname
[0] ? "," : "",
250 print_sids
? "U-" : "",
251 print_sids
? domain_name
: "",
252 print_sids
&& domain_name
[0] ? "\\" : "",
253 print_sids
? username
: "",
254 print_sids
? "," : "",
255 print_sids
? put_sid (psid
) : "",
259 netapibufferfree (buffer
);
262 while (rc
== ERROR_MORE_DATA
);
265 netapibufferfree (servername
);
271 enum_local_groups (int print_sids
)
273 LOCALGROUP_INFO_0
*buffer
;
274 DWORD entriesread
= 0;
275 DWORD totalentries
= 0;
276 DWORD resume_handle
= 0;
283 rc
= netlocalgroupenum (NULL
, 0, (LPBYTE
*) & buffer
, 1024,
284 &entriesread
, &totalentries
, &resume_handle
);
287 case ERROR_ACCESS_DENIED
:
291 case ERROR_MORE_DATA
:
300 for (i
= 0; i
< entriesread
; i
++)
302 char localgroup_name
[100];
303 char domain_name
[100];
304 DWORD domname_len
= 100;
305 char psid_buffer
[1024];
306 PSID psid
= (PSID
) psid_buffer
;
307 DWORD sid_length
= 1024;
309 SID_NAME_USE acc_type
;
310 uni2ansi (buffer
[i
].lgrpi0_name
, localgroup_name
, sizeof (localgroup_name
));
312 if (!LookupAccountName (NULL
, localgroup_name
, psid
,
313 &sid_length
, domain_name
, &domname_len
,
316 print_win_error(GetLastError ());
319 else if (acc_type
== SidTypeDomain
)
323 strcpy (domname
, domain_name
);
324 strcat (domname
, "\\");
325 strcat (domname
, localgroup_name
);
328 if (!LookupAccountName (NULL
, domname
,
330 domain_name
, &domname_len
,
333 print_win_error(GetLastError ());
338 gid
= *GetSidSubAuthority (psid
, *GetSidSubAuthorityCount(psid
) - 1);
340 printf ("%s:*:%ld:%ld:%s%s::\n", localgroup_name
, gid
, gid
,
341 print_sids
? "," : "",
342 print_sids
? put_sid (psid
) : "");
345 netapibufferfree (buffer
);
348 while (rc
== ERROR_MORE_DATA
);
354 print_special (int print_sids
,
355 PSID_IDENTIFIER_AUTHORITY auth
, BYTE cnt
,
356 DWORD sub1
, DWORD sub2
, DWORD sub3
, DWORD sub4
,
357 DWORD sub5
, DWORD sub6
, DWORD sub7
, DWORD sub8
)
359 char name
[256], dom
[256];
360 DWORD len
, len2
, rid
;
364 if (AllocateAndInitializeSid (auth
, cnt
, sub1
, sub2
, sub3
, sub4
,
365 sub5
, sub6
, sub7
, sub8
, &sid
))
367 if (LookupAccountSid (NULL
, sid
,
368 name
, (len
= 256, &len
),
369 dom
, (len2
= 256, &len
),
388 printf ("%s:*:%lu:%lu:%s%s::\n",
390 print_sids
? "," : "",
391 print_sids
? put_sid (sid
) : "");
398 usage (FILE * stream
, int status
)
400 fprintf (stream
, "Usage: mkpasswd [OPTION]... [domain]\n\n"
401 "This program prints a /etc/passwd file to stdout\n\n"
403 " -l,--local print local user accounts\n"
404 " -d,--domain print domain accounts (from current domain\n"
405 " if no domain specified)\n"
406 " -o,--id-offset offset change the default offset (10000) added to uids\n"
407 " in domain accounts.\n"
408 " -g,--local-groups print local group information too\n"
409 " if no domain specified\n"
410 " -m,--no-mount don't use mount points for home dir\n"
411 " -s,--no-sids don't print SIDs in GCOS field\n"
412 " (this affects ntsec)\n"
413 " -p,--path-to-home path use specified path instead of user account home dir\n"
414 " -u,--username username only return information for the specified user\n"
415 " -h,--help displays this message\n"
416 " -v,--version version information and exit\n\n"
417 "One of `-l', `-d' or `-g' must be given on NT/W2K.\n");
421 struct option longopts
[] = {
422 {"local", no_argument
, NULL
, 'l'},
423 {"domain", no_argument
, NULL
, 'd'},
424 {"id-offset", required_argument
, NULL
, 'o'},
425 {"local-groups", no_argument
, NULL
, 'g'},
426 {"no-mount", no_argument
, NULL
, 'm'},
427 {"no-sids", no_argument
, NULL
, 's'},
428 {"path-to-home", required_argument
, NULL
, 'p'},
429 {"username", required_argument
, NULL
, 'u'},
430 {"help", no_argument
, NULL
, 'h'},
431 {"version", no_argument
, NULL
, 'v'},
432 {0, no_argument
, NULL
, 0}
435 char opts
[] = "ldo:gsmhp:u:v";
440 const char *v
= strchr (version
, ':');
450 len
= strchr (v
, ' ') - v
;
453 mkpasswd (cygwin) %.*s\n\
454 passwd File Generator\n\
455 Copyright 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.\n\
456 Compiled on %s", len
, v
, __DATE__
);
460 main (int argc
, char **argv
)
462 LPWSTR servername
= NULL
;
463 DWORD rc
= ERROR_SUCCESS
;
464 WCHAR domain_name
[200];
466 int print_domain
= 0;
467 int print_local_groups
= 0;
468 int domain_name_specified
= 0;
470 int print_cygpath
= 1;
471 int id_offset
= 10000;
473 char *disp_username
= NULL
;
475 char name
[256], passed_home_path
[MAX_PATH
];
478 passed_home_path
[0] = '\0';
480 setmode (1, O_BINARY
);
482 if (GetVersion () < 0x80000000)
485 return usage (stderr
, 1);
488 while ((i
= getopt_long (argc
, argv
, opts
, longopts
, NULL
)) != EOF
)
498 id_offset
= strtol (optarg
, NULL
, 10);
501 print_local_groups
= 1;
510 if (optarg
[0] != '/')
512 fprintf (stderr
, "%s: `%s' is not a fully qualified path.\n",
516 strcpy (passed_home_path
, optarg
);
517 if (optarg
[strlen (optarg
)-1] != '/')
518 strcat (passed_home_path
, "/");
521 disp_username
= optarg
;
524 return usage (stdout
, 0);
529 fprintf (stderr
, "Try `%s --help' for more information.\n", argv
[0]);
532 if (!print_local
&& !print_domain
&& !print_local_groups
)
534 fprintf (stderr
, "%s: Specify one of `-l', `-d' or `-g'\n", argv
[0]);
541 fprintf (stderr
, "%s: A domain name is only accepted "
542 "when `-d' is given.\n", argv
[0]);
545 mbstowcs (domain_name
, argv
[optind
], (strlen (argv
[optind
]) + 1));
546 domain_name_specified
= 1;
551 /* This takes Windows 9x/ME into account. */
552 if (GetVersion () >= 0x80000000)
554 /* Same behaviour as in cygwin/uinfo.cc (internal_getlogin). */
555 if (!GetUserName (name
, (len
= 256, &len
)))
556 strcpy (name
, "unknown");
558 if (passed_home_path
[0] == '\0')
559 strcpy (passed_home_path
, "/home/");
561 printf ("%s::%ld:%ld::%s%s:/bin/bash\n", name
,
562 DOMAIN_USER_RID_ADMIN
,
563 DOMAIN_ALIAS_RID_ADMINS
,
572 print_win_error(GetLastError ());
577 * Get `Everyone' group
579 if (disp_username
== NULL
)
581 print_special (print_sids
, &sid_world_auth
, 1, SECURITY_WORLD_RID
,
582 0, 0, 0, 0, 0, 0, 0);
586 print_special (print_sids
, &sid_nt_auth
, 1, SECURITY_LOCAL_SYSTEM_RID
,
587 0, 0, 0, 0, 0, 0, 0);
589 * Get `administrators' group
591 if (!print_local_groups
)
592 print_special (print_sids
, &sid_nt_auth
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
593 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0);
595 if (print_local_groups
)
596 enum_local_groups (print_sids
);
601 if (domain_name_specified
)
602 rc
= netgetdcname (NULL
, domain_name
, (LPBYTE
*) & servername
);
605 rc
= netgetdcname (NULL
, NULL
, (LPBYTE
*) & servername
);
607 if (rc
!= ERROR_SUCCESS
)
613 enum_users (servername
, print_sids
, print_cygpath
, passed_home_path
,
614 id_offset
, disp_username
);
618 enum_users (NULL
, print_sids
, print_cygpath
, passed_home_path
, 0,
622 netapibufferfree (servername
);