3 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003 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
18 #include <sys/cygwin.h>
22 #include <sys/fcntl.h>
26 #define print_win_error(x) _print_win_error(x, __LINE__)
28 static const char version
[] = "$Revision$";
30 SID_IDENTIFIER_AUTHORITY sid_world_auth
= {SECURITY_WORLD_SID_AUTHORITY
};
31 SID_IDENTIFIER_AUTHORITY sid_nt_auth
= {SECURITY_NT_AUTHORITY
};
34 LPWSTR DomainControllerName
;
35 LPWSTR DomainControllerAddress
;
36 ULONG DomainControllerAddressType
;
42 LPWSTR ClientSiteName
;
43 } *PDOMAIN_CONTROLLER_INFOW
;
45 NET_API_STATUS
WINAPI (*netapibufferfree
)(PVOID
);
46 NET_API_STATUS
WINAPI (*netuserenum
)(LPWSTR
,DWORD
,DWORD
,PBYTE
*,DWORD
,PDWORD
,PDWORD
,PDWORD
);
47 NET_API_STATUS
WINAPI (*netlocalgroupenum
)(LPWSTR
,DWORD
,PBYTE
*,DWORD
,PDWORD
,PDWORD
,PDWORD
);
48 NET_API_STATUS
WINAPI (*netgetdcname
)(LPWSTR
,LPWSTR
,PBYTE
*);
49 NET_API_STATUS
WINAPI (*netusergetinfo
)(LPWSTR
,LPWSTR
,DWORD
,PBYTE
*);
50 NET_API_STATUS
WINAPI (*dsgetdcname
)(LPWSTR
,LPWSTR
,GUID
*,LPWSTR
,ULONG
,PDOMAIN_CONTROLLER_INFOW
*);
53 #define min(a,b) (((a)<(b))?(a):(b))
59 HANDLE h
= LoadLibrary ("netapi32.dll");
64 if (!(netapibufferfree
= (void *) GetProcAddress (h
, "NetApiBufferFree")))
66 if (!(netuserenum
= (void *) GetProcAddress (h
, "NetUserEnum")))
68 if (!(netlocalgroupenum
= (void *) GetProcAddress (h
, "NetLocalGroupEnum")))
70 if (!(netgetdcname
= (void *) GetProcAddress (h
, "NetGetDCName")))
72 if (!(netusergetinfo
= (void *) GetProcAddress (h
, "NetUserGetInfo")))
75 dsgetdcname
= (void *) GetProcAddress (h
, "DsGetDcNameW");
88 sprintf(t
, "%u", GetSidIdentifierAuthority (sid
)->Value
[5]);
90 for (i
= 0; i
< *GetSidSubAuthorityCount (sid
); ++i
)
92 sprintf(t
, "-%lu", *GetSidSubAuthority (sid
, i
));
99 psx_dir (char *in
, char *out
)
101 if (isalpha (in
[0]) && in
[1] == ':')
103 sprintf (out
, "/cygdrive/%c", in
[0]);
122 uni2ansi (LPWSTR wcs
, char *mbs
, int size
)
125 WideCharToMultiByte (CP_ACP
, 0, wcs
, -1, mbs
, size
, NULL
, NULL
);
131 _print_win_error(DWORD code
, int line
)
135 if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
136 | FORMAT_MESSAGE_IGNORE_INSERTS
,
139 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
140 (LPTSTR
) buf
, sizeof (buf
), NULL
))
141 fprintf (stderr
, "mkpasswd (%d): [%lu] %s", line
, code
, buf
);
143 fprintf (stderr
, "mkpasswd (%d): error %lu", line
, code
);
147 current_user (int print_sids
, int print_cygpath
,
148 const char * passed_home_path
, int id_offset
, const char * disp_username
)
150 char name
[UNLEN
+ 1], *envname
, *envdomain
;
160 if ((!GetUserName (name
, (len
= sizeof (name
), &len
)) && (errpos
= __LINE__
))
162 || !(envname
= getenv("USERNAME"))
163 || strcasecmp (envname
, name
)
164 || (disp_username
&& strcasecmp(envname
, disp_username
))
165 || (!GetComputerName (name
, (len
= sizeof (name
), &len
))
166 && (errpos
= __LINE__
))
167 || !(envdomain
= getenv("USERDOMAIN"))
169 || !strcasecmp (envdomain
, name
)
170 || (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY
, &ptok
)
171 && (errpos
= __LINE__
))
172 || (!GetTokenInformation (ptok
, TokenUser
, &tu
, sizeof tu
, &len
)
173 && (errpos
= __LINE__
))
174 || (!GetTokenInformation (ptok
, TokenPrimaryGroup
, &tg
, sizeof tg
, &len
)
175 && (errpos
= __LINE__
))
176 || (!CloseHandle (ptok
) && (errpos
= __LINE__
)))
179 _print_win_error (GetLastError (), errpos
);
183 int uid
= *GetSidSubAuthority (tu
.psid
, *GetSidSubAuthorityCount(tu
.psid
) - 1);
184 int gid
= *GetSidSubAuthority (tg
.psid
, *GetSidSubAuthorityCount(tg
.psid
) - 1);
185 char homedir_psx
[MAX_PATH
] = {0}, homedir_w32
[MAX_PATH
] = {0};
187 char *envhomedrive
= getenv ("HOMEDRIVE");
188 char *envhomepath
= getenv ("HOMEPATH");
190 if (passed_home_path
[0] == '\0')
192 if (envhomepath
&& envhomepath
[0])
195 strlcpy (homedir_w32
, envhomedrive
, sizeof (homedir_w32
));
196 if (envhomepath
[0] != '\\')
197 strlcat (homedir_w32
, "\\", sizeof (homedir_w32
));
198 strlcat (homedir_w32
, envhomepath
, sizeof (homedir_w32
));
200 cygwin_conv_path (CCP_WIN_A_TO_POSIX
| CCP_ABSOLUTE
, homedir_w32
,
201 homedir_psx
, MAX_PATH
);
203 psx_dir (homedir_w32
, homedir_psx
);
207 strlcpy (homedir_psx
, "/home/", sizeof (homedir_psx
));
208 strlcat (homedir_psx
, envname
, sizeof (homedir_psx
));
213 strlcpy (homedir_psx
, passed_home_path
, sizeof (homedir_psx
));
214 strlcat (homedir_psx
, envname
, sizeof (homedir_psx
));
217 printf ("%s:unused_by_nt/2000/xp:%u:%u:%s%s%s%s%s%s%s%s:%s:/bin/bash\n",
222 print_sids
? "," : "",
223 print_sids
? "U-" : "",
224 print_sids
? envdomain
: "",
225 print_sids
? "\\" : "",
226 print_sids
? envname
: "",
227 print_sids
? "," : "",
228 print_sids
? put_sid (tu
.psid
) : "",
233 enum_users (LPWSTR servername
, int print_sids
, int print_cygpath
,
234 const char * passed_home_path
, int id_offset
, char *disp_username
)
237 DWORD entriesread
= 0;
238 DWORD totalentries
= 0;
239 DWORD resume_handle
= 0;
241 char ansi_srvname
[256];
245 uni2ansi (servername
, ansi_srvname
, sizeof (ansi_srvname
));
251 if (disp_username
!= NULL
)
253 MultiByteToWideChar (CP_ACP
, 0, disp_username
, -1, uni_name
, 512 );
254 rc
= netusergetinfo(servername
, (LPWSTR
) & uni_name
, 3,
259 rc
= netuserenum (servername
, 3, FILTER_NORMAL_ACCOUNT
,
260 (void *) &buffer
, 1024,
261 &entriesread
, &totalentries
, &resume_handle
);
264 case ERROR_ACCESS_DENIED
:
268 case ERROR_MORE_DATA
:
277 for (i
= 0; i
< entriesread
; i
++)
281 char homedir_psx
[MAX_PATH
];
282 char homedir_w32
[MAX_PATH
];
283 char domain_name
[100];
284 DWORD domname_len
= 100;
285 char psid_buffer
[1024];
286 PSID psid
= (PSID
) psid_buffer
;
287 DWORD sid_length
= 1024;
288 SID_NAME_USE acc_type
;
290 int uid
= buffer
[i
].usri3_user_id
;
291 int gid
= buffer
[i
].usri3_primary_group_id
;
292 uni2ansi (buffer
[i
].usri3_name
, username
, sizeof (username
));
293 uni2ansi (buffer
[i
].usri3_full_name
, fullname
, sizeof (fullname
));
294 homedir_w32
[0] = homedir_psx
[0] = '\0';
295 if (passed_home_path
[0] == '\0')
297 uni2ansi (buffer
[i
].usri3_home_dir
, homedir_w32
,
298 sizeof (homedir_w32
));
299 if (homedir_w32
[0] != '\0')
302 cygwin_conv_path (CCP_WIN_A_TO_POSIX
| CCP_ABSOLUTE
,
303 homedir_w32
, homedir_psx
, MAX_PATH
);
305 psx_dir (homedir_w32
, homedir_psx
);
309 strcpy (homedir_psx
, "/home/");
310 strcat (homedir_psx
, username
);
315 strcpy (homedir_psx
, passed_home_path
);
316 strcat (homedir_psx
, username
);
321 if (!LookupAccountName (servername
? ansi_srvname
: NULL
,
324 domain_name
, &domname_len
,
327 print_win_error(GetLastError ());
328 fprintf(stderr
, " (%s)\n", username
);
331 else if (acc_type
== SidTypeDomain
)
335 strcpy (domname
, domain_name
);
336 strcat (domname
, "\\");
337 strcat (domname
, username
);
340 if (!LookupAccountName (servername
? ansi_srvname
: NULL
,
343 domain_name
, &domname_len
,
346 print_win_error(GetLastError ());
347 fprintf(stderr
, " (%s)\n", domname
);
352 printf ("%s:unused_by_nt/2000/xp:%u:%u:%s%s%s%s%s%s%s%s:%s:/bin/bash\n",
357 print_sids
&& fullname
[0] ? "," : "",
358 print_sids
? "U-" : "",
359 print_sids
? domain_name
: "",
360 print_sids
&& domain_name
[0] ? "\\" : "",
361 print_sids
? username
: "",
362 print_sids
? "," : "",
363 print_sids
? put_sid (psid
) : "",
367 netapibufferfree (buffer
);
370 while (rc
== ERROR_MORE_DATA
);
376 enum_local_groups (int print_sids
)
378 LOCALGROUP_INFO_0
*buffer
;
379 DWORD entriesread
= 0;
380 DWORD totalentries
= 0;
381 DWORD resume_handle
= 0;
388 rc
= netlocalgroupenum (NULL
, 0, (void *) &buffer
, 1024,
389 &entriesread
, &totalentries
, &resume_handle
);
392 case ERROR_ACCESS_DENIED
:
396 case ERROR_MORE_DATA
:
405 for (i
= 0; i
< entriesread
; i
++)
407 char localgroup_name
[100];
408 char domain_name
[100];
409 DWORD domname_len
= 100;
410 char psid_buffer
[1024];
411 PSID psid
= (PSID
) psid_buffer
;
412 DWORD sid_length
= 1024;
414 SID_NAME_USE acc_type
;
415 uni2ansi (buffer
[i
].lgrpi0_name
, localgroup_name
, sizeof (localgroup_name
));
417 if (!LookupAccountName (NULL
, localgroup_name
, psid
,
418 &sid_length
, domain_name
, &domname_len
,
421 print_win_error(GetLastError ());
422 fprintf(stderr
, " (%s)\n", localgroup_name
);
425 else if (acc_type
== SidTypeDomain
)
429 strcpy (domname
, domain_name
);
430 strcat (domname
, "\\");
431 strcat (domname
, localgroup_name
);
434 if (!LookupAccountName (NULL
, domname
,
436 domain_name
, &domname_len
,
439 print_win_error(GetLastError ());
440 fprintf(stderr
, " (%s)\n", domname
);
445 gid
= *GetSidSubAuthority (psid
, *GetSidSubAuthorityCount(psid
) - 1);
447 printf ("%s:*:%ld:%ld:%s%s::\n", localgroup_name
, gid
, gid
,
448 print_sids
? "," : "",
449 print_sids
? put_sid (psid
) : "");
452 netapibufferfree (buffer
);
455 while (rc
== ERROR_MORE_DATA
);
461 print_special (int print_sids
,
462 PSID_IDENTIFIER_AUTHORITY auth
, BYTE cnt
,
463 DWORD sub1
, DWORD sub2
, DWORD sub3
, DWORD sub4
,
464 DWORD sub5
, DWORD sub6
, DWORD sub7
, DWORD sub8
)
466 char name
[256], dom
[256];
467 DWORD len
, len2
, rid
;
471 if (AllocateAndInitializeSid (auth
, cnt
, sub1
, sub2
, sub3
, sub4
,
472 sub5
, sub6
, sub7
, sub8
, &sid
))
474 if (LookupAccountSid (NULL
, sid
,
475 name
, (len
= 256, &len
),
476 dom
, (len2
= 256, &len
),
495 printf ("%s:*:%lu:%lu:%s%s::\n",
496 name
, rid
, rid
== 18 ? 544 : rid
, /* SYSTEM hack */
497 print_sids
? "," : "",
498 print_sids
? put_sid (sid
) : "");
505 usage (FILE * stream
, int isNT
)
507 fprintf (stream
, "Usage: mkpasswd [OPTION]... [domain]...\n"
508 "Print /etc/passwd file to stdout\n\n"
511 fprintf (stream
, " -l,--local print local user accounts\n"
512 " -c,--current print current account, if a domain account\n"
513 " -d,--domain print domain accounts (from current domain\n"
514 " if no domains specified)\n"
515 " -o,--id-offset offset change the default offset (10000) added to uids\n"
516 " in domain accounts.\n"
517 " -g,--local-groups print local group information too\n"
518 " if no domain specified\n"
519 " -m,--no-mount don't use mount points for home dir\n"
520 " -s,--no-sids don't print SIDs in GCOS field\n"
521 " (this affects ntsec)\n");
522 fprintf (stream
, " -p,--path-to-home path use specified path and not user account home dir or /home\n"
523 " -u,--username username only return information for the specified user\n"
524 " -h,--help displays this message\n"
525 " -v,--version version information and exit\n\n");
527 fprintf (stream
, "One of '-l', '-d' or '-g' must be given.\n");
531 struct option longopts
[] = {
532 {"local", no_argument
, NULL
, 'l'},
533 {"current", no_argument
, NULL
, 'c'},
534 {"domain", no_argument
, NULL
, 'd'},
535 {"id-offset", required_argument
, NULL
, 'o'},
536 {"local-groups", no_argument
, NULL
, 'g'},
537 {"no-mount", no_argument
, NULL
, 'm'},
538 {"no-sids", no_argument
, NULL
, 's'},
539 {"path-to-home", required_argument
, NULL
, 'p'},
540 {"username", required_argument
, NULL
, 'u'},
541 {"help", no_argument
, NULL
, 'h'},
542 {"version", no_argument
, NULL
, 'v'},
543 {0, no_argument
, NULL
, 0}
546 char opts
[] = "lcdo:gsmhp:u:v";
551 const char *v
= strchr (version
, ':');
561 len
= strchr (v
, ' ') - v
;
564 mkpasswd (cygwin) %.*s\n\
565 passwd File Generator\n\
566 Copyright 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.\n\
568 ", len
, v
, __DATE__
);
572 main (int argc
, char **argv
)
574 LPWSTR servername
= NULL
;
575 DWORD rc
= ERROR_SUCCESS
;
576 WCHAR domain_name
[200];
578 int print_current
= 0;
579 int print_domain
= 0;
580 int print_local_groups
= 0;
581 int domain_specified
= 0;
583 int print_cygpath
= 1;
584 int id_offset
= 10000;
587 char *disp_username
= NULL
;
588 char name
[256], passed_home_path
[MAX_PATH
];
591 isNT
= (GetVersion () < 0x80000000);
592 passed_home_path
[0] = '\0';
594 setmode (1, O_BINARY
);
596 if (isNT
&& argc
== 1)
597 return usage (stderr
, isNT
);
600 while ((i
= getopt_long (argc
, argv
, opts
, longopts
, NULL
)) != EOF
)
613 id_offset
= strtol (optarg
, NULL
, 10);
616 print_local_groups
= 1;
625 if (optarg
[0] != '/')
627 fprintf (stderr
, "%s: '%s' is not a fully qualified path.\n",
631 strcpy (passed_home_path
, optarg
);
632 if (optarg
[strlen (optarg
)-1] != '/')
633 strcat (passed_home_path
, "/");
636 disp_username
= optarg
;
639 usage (stdout
, isNT
);
645 fprintf (stderr
, "Try '%s --help' for more information.\n", argv
[0]);
651 /* This takes Windows 9x/ME into account. */
652 if (passed_home_path
[0] == '\0')
653 strcpy (passed_home_path
, "/home/");
656 printf ("admin:use_crypt:%lu:%lu:Administrator:%sadmin:/bin/bash\n",
657 DOMAIN_USER_RID_ADMIN
,
658 DOMAIN_ALIAS_RID_ADMINS
,
660 if (GetUserName (name
, (len
= 256, &len
)))
661 disp_username
= name
;
663 if (disp_username
&& disp_username
[0])
665 /* Create a pseudo random uid */
666 unsigned long uid
= 0, i
;
667 for (i
= 0; disp_username
[i
]; i
++)
668 uid
+= toupper (disp_username
[i
]) << ((6 * i
) % 25);
669 uid
= (uid
% (1000 - DOMAIN_USER_RID_ADMIN
- 1))
670 + DOMAIN_USER_RID_ADMIN
+ 1;
672 printf ("%s:use_crypt:%lu:%lu:%s:%s%s:/bin/bash\n",
675 DOMAIN_ALIAS_RID_ADMINS
,
682 if (!print_local
&& !print_domain
&& !print_local_groups
)
684 fprintf (stderr
, "%s: Specify one of '-l', '-d' or '-g'\n", argv
[0]);
691 fprintf (stderr
, "%s: A domain name is only accepted "
692 "when '-d' is given.\n", argv
[0]);
695 domain_specified
= 1;
699 print_win_error(GetLastError ());
703 if (disp_username
== NULL
)
707 /* Generate service starter account entries. */
708 printf ("SYSTEM:*:18:544:,S-1-5-18::\n");
709 printf ("LocalService:*:19:544:U-NT AUTHORITY\\LocalService,S-1-5-19::\n");
710 printf ("NetworkService:*:20:544:U-NT AUTHORITY\\NetworkService,S-1-5-20::\n");
711 /* Get 'administrators' group (has localized name). */
712 if (!print_local_groups
)
713 print_special (print_sids
, &sid_nt_auth
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
714 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0);
716 if (print_local_groups
)
717 enum_local_groups (print_sids
);
721 enum_users (NULL
, print_sids
, print_cygpath
, passed_home_path
, 0,
728 PDOMAIN_CONTROLLER_INFOW pdci
= NULL
;
732 if (domain_specified
)
734 mbstowcs (domain_name
, argv
[optind
], strlen (argv
[optind
]) + 1);
735 rc
= dsgetdcname (NULL
, domain_name
, NULL
, NULL
, 0, &pdci
);
738 rc
= dsgetdcname (NULL
, NULL
, NULL
, NULL
, 0, &pdci
);
739 if (rc
!= ERROR_SUCCESS
)
744 servername
= pdci
->DomainControllerName
;
748 rc
= netgetdcname (NULL
, NULL
, (void *) &servername
);
749 if (rc
== ERROR_SUCCESS
&& domain_specified
)
751 LPWSTR server
= servername
;
752 mbstowcs (domain_name
, argv
[optind
], strlen (argv
[optind
]) + 1);
753 rc
= netgetdcname (server
, domain_name
, (void *) &servername
);
754 netapibufferfree (server
);
756 if (rc
!= ERROR_SUCCESS
)
762 enum_users (servername
, print_sids
, print_cygpath
, passed_home_path
,
763 id_offset
* i
++, disp_username
);
764 netapibufferfree (pdci
? (PVOID
) pdci
: (PVOID
) servername
);
766 while (++optind
< argc
);
768 if (print_current
&& !print_domain
)
769 current_user(print_sids
, print_cygpath
, passed_home_path
,
770 id_offset
, disp_username
);