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 static const char version
[] = "$Revision$";
28 SID_IDENTIFIER_AUTHORITY sid_world_auth
= {SECURITY_WORLD_SID_AUTHORITY
};
29 SID_IDENTIFIER_AUTHORITY sid_nt_auth
= {SECURITY_NT_AUTHORITY
};
31 NET_API_STATUS
WINAPI (*netapibufferfree
)(PVOID
);
32 NET_API_STATUS
WINAPI (*netuserenum
)(LPWSTR
,DWORD
,DWORD
,PBYTE
*,DWORD
,PDWORD
,PDWORD
,PDWORD
);
33 NET_API_STATUS
WINAPI (*netlocalgroupenum
)(LPWSTR
,DWORD
,PBYTE
*,DWORD
,PDWORD
,PDWORD
,PDWORD
);
34 NET_API_STATUS
WINAPI (*netgetdcname
)(LPWSTR
,LPWSTR
,PBYTE
*);
35 NET_API_STATUS
WINAPI (*netusergetinfo
)(LPWSTR
,LPWSTR
,DWORD
,PBYTE
*);
38 #define min(a,b) (((a)<(b))?(a):(b))
44 HANDLE h
= LoadLibrary ("netapi32.dll");
49 if (!(netapibufferfree
= (void *) GetProcAddress (h
, "NetApiBufferFree")))
51 if (!(netuserenum
= (void *) GetProcAddress (h
, "NetUserEnum")))
53 if (!(netlocalgroupenum
= (void *) GetProcAddress (h
, "NetLocalGroupEnum")))
55 if (!(netgetdcname
= (void *) GetProcAddress (h
, "NetGetDCName")))
57 if (!(netusergetinfo
= (void *) GetProcAddress (h
, "NetUserGetInfo")))
71 sprintf(t
, "%u", GetSidIdentifierAuthority (sid
)->Value
[5]);
73 for (i
= 0; i
< *GetSidSubAuthorityCount (sid
); ++i
)
75 sprintf(t
, "-%lu", *GetSidSubAuthority (sid
, i
));
82 psx_dir (char *in
, char *out
)
84 if (isalpha (in
[0]) && in
[1] == ':')
86 sprintf (out
, "/cygdrive/%c", in
[0]);
105 uni2ansi (LPWSTR wcs
, char *mbs
, int size
)
108 WideCharToMultiByte (CP_ACP
, 0, wcs
, -1, mbs
, size
, NULL
, NULL
);
114 print_win_error(DWORD code
)
118 if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
119 | FORMAT_MESSAGE_IGNORE_INSERTS
,
122 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
123 (LPTSTR
) buf
, sizeof (buf
), NULL
))
124 fprintf (stderr
, "mkpasswd: [%lu] %s", code
, buf
);
126 fprintf (stderr
, "mkpasswd: error %lu", code
);
130 current_user (int print_sids
, int print_cygpath
,
131 const char * passed_home_path
, int id_offset
, const char * disp_username
)
133 char name
[UNLEN
+ 1], *envname
, *envdomain
;
143 if ((!GetUserName (name
, (len
= sizeof (name
), &len
)) && (errpos
= __LINE__
))
145 || !(envname
= getenv("USERNAME"))
146 || strcasecmp (envname
, name
)
147 || (disp_username
&& strcasecmp(envname
, disp_username
))
148 || (!GetComputerName (name
, (len
= sizeof (name
), &len
))
149 && (errpos
= __LINE__
))
150 || !(envdomain
= getenv("USERDOMAIN"))
152 || !strcasecmp (envdomain
, name
)
153 || (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY
, &ptok
)
154 && (errpos
= __LINE__
))
155 || (!GetTokenInformation (ptok
, TokenUser
, &tu
, sizeof tu
, &len
)
156 && (errpos
= __LINE__
))
157 || (!GetTokenInformation (ptok
, TokenPrimaryGroup
, &tg
, sizeof tg
, &len
)
158 && (errpos
= __LINE__
))
159 || (!CloseHandle (ptok
) && (errpos
= __LINE__
)))
163 print_win_error (GetLastError ());
164 fprintf(stderr
, " on line %d\n", errpos
);
169 int uid
= *GetSidSubAuthority (tu
.psid
, *GetSidSubAuthorityCount(tu
.psid
) - 1);
170 int gid
= *GetSidSubAuthority (tg
.psid
, *GetSidSubAuthorityCount(tg
.psid
) - 1);
171 char homedir_psx
[MAX_PATH
] = {0}, homedir_w32
[MAX_PATH
] = {0};
173 char *envhomedrive
= getenv ("HOMEDRIVE");
174 char *envhomepath
= getenv ("HOMEPATH");
176 if (passed_home_path
[0] == '\0')
178 if (envhomepath
&& envhomepath
[0])
181 strlcpy (homedir_w32
, envhomedrive
, sizeof (homedir_w32
));
182 if (envhomepath
[0] != '\\')
183 strlcat (homedir_w32
, "\\", sizeof (homedir_w32
));
184 strlcat (homedir_w32
, envhomepath
, sizeof (homedir_w32
));
186 cygwin_conv_to_posix_path (homedir_w32
, homedir_psx
);
188 psx_dir (homedir_w32
, homedir_psx
);
192 strlcpy (homedir_psx
, "/home/", sizeof (homedir_psx
));
193 strlcat (homedir_psx
, envname
, sizeof (homedir_psx
));
198 strlcpy (homedir_psx
, passed_home_path
, sizeof (homedir_psx
));
199 strlcat (homedir_psx
, envname
, sizeof (homedir_psx
));
202 printf ("%s:unused_by_nt/2000/xp:%d:%d:%s%s%s%s%s%s%s%s:%s:/bin/bash\n",
207 print_sids
? "," : "",
208 print_sids
? "U-" : "",
209 print_sids
? envdomain
: "",
210 print_sids
? "\\" : "",
211 print_sids
? envname
: "",
212 print_sids
? "," : "",
213 print_sids
? put_sid (tu
.psid
) : "",
218 enum_users (LPWSTR servername
, int print_sids
, int print_cygpath
,
219 const char * passed_home_path
, int id_offset
, char *disp_username
)
222 DWORD entriesread
= 0;
223 DWORD totalentries
= 0;
224 DWORD resume_handle
= 0;
226 char ansi_srvname
[256];
230 uni2ansi (servername
, ansi_srvname
, sizeof (ansi_srvname
));
236 if (disp_username
!= NULL
)
238 MultiByteToWideChar (CP_ACP
, 0, disp_username
, -1, uni_name
, 512 );
239 rc
= netusergetinfo(servername
, (LPWSTR
) & uni_name
, 3,
240 (LPBYTE
*) &buffer
);
244 rc
= netuserenum (servername
, 3, FILTER_NORMAL_ACCOUNT
,
245 (LPBYTE
*) & buffer
, 1024,
246 &entriesread
, &totalentries
, &resume_handle
);
249 case ERROR_ACCESS_DENIED
:
253 case ERROR_MORE_DATA
:
262 for (i
= 0; i
< entriesread
; i
++)
266 char homedir_psx
[MAX_PATH
];
267 char homedir_w32
[MAX_PATH
];
268 char domain_name
[100];
269 DWORD domname_len
= 100;
270 char psid_buffer
[1024];
271 PSID psid
= (PSID
) psid_buffer
;
272 DWORD sid_length
= 1024;
273 SID_NAME_USE acc_type
;
275 int uid
= buffer
[i
].usri3_user_id
;
276 int gid
= buffer
[i
].usri3_primary_group_id
;
277 uni2ansi (buffer
[i
].usri3_name
, username
, sizeof (username
));
278 uni2ansi (buffer
[i
].usri3_full_name
, fullname
, sizeof (fullname
));
279 homedir_w32
[0] = homedir_psx
[0] = '\0';
280 if (passed_home_path
[0] == '\0')
282 uni2ansi (buffer
[i
].usri3_home_dir
, homedir_w32
,
283 sizeof (homedir_w32
));
284 if (homedir_w32
[0] != '\0')
287 cygwin_conv_to_posix_path (homedir_w32
, homedir_psx
);
289 psx_dir (homedir_w32
, homedir_psx
);
293 strcpy (homedir_psx
, "/home/");
294 strcat (homedir_psx
, username
);
299 strcpy (homedir_psx
, passed_home_path
);
300 strcat (homedir_psx
, username
);
305 if (!LookupAccountName (servername
? ansi_srvname
: NULL
,
308 domain_name
, &domname_len
,
311 print_win_error(GetLastError ());
314 else if (acc_type
== SidTypeDomain
)
318 strcpy (domname
, domain_name
);
319 strcat (domname
, "\\");
320 strcat (domname
, username
);
323 if (!LookupAccountName (servername
? ansi_srvname
: NULL
,
326 domain_name
, &domname_len
,
329 print_win_error(GetLastError ());
334 printf ("%s:unused_by_nt/2000/xp:%d:%d:%s%s%s%s%s%s%s%s:%s:/bin/bash\n",
339 print_sids
&& fullname
[0] ? "," : "",
340 print_sids
? "U-" : "",
341 print_sids
? domain_name
: "",
342 print_sids
&& domain_name
[0] ? "\\" : "",
343 print_sids
? username
: "",
344 print_sids
? "," : "",
345 print_sids
? put_sid (psid
) : "",
349 netapibufferfree (buffer
);
352 while (rc
== ERROR_MORE_DATA
);
355 netapibufferfree (servername
);
361 enum_local_groups (int print_sids
)
363 LOCALGROUP_INFO_0
*buffer
;
364 DWORD entriesread
= 0;
365 DWORD totalentries
= 0;
366 DWORD resume_handle
= 0;
373 rc
= netlocalgroupenum (NULL
, 0, (LPBYTE
*) & buffer
, 1024,
374 &entriesread
, &totalentries
, &resume_handle
);
377 case ERROR_ACCESS_DENIED
:
381 case ERROR_MORE_DATA
:
390 for (i
= 0; i
< entriesread
; i
++)
392 char localgroup_name
[100];
393 char domain_name
[100];
394 DWORD domname_len
= 100;
395 char psid_buffer
[1024];
396 PSID psid
= (PSID
) psid_buffer
;
397 DWORD sid_length
= 1024;
399 SID_NAME_USE acc_type
;
400 uni2ansi (buffer
[i
].lgrpi0_name
, localgroup_name
, sizeof (localgroup_name
));
402 if (!LookupAccountName (NULL
, localgroup_name
, psid
,
403 &sid_length
, domain_name
, &domname_len
,
406 print_win_error(GetLastError ());
409 else if (acc_type
== SidTypeDomain
)
413 strcpy (domname
, domain_name
);
414 strcat (domname
, "\\");
415 strcat (domname
, localgroup_name
);
418 if (!LookupAccountName (NULL
, domname
,
420 domain_name
, &domname_len
,
423 print_win_error(GetLastError ());
428 gid
= *GetSidSubAuthority (psid
, *GetSidSubAuthorityCount(psid
) - 1);
430 printf ("%s:*:%ld:%ld:%s%s::\n", localgroup_name
, gid
, gid
,
431 print_sids
? "," : "",
432 print_sids
? put_sid (psid
) : "");
435 netapibufferfree (buffer
);
438 while (rc
== ERROR_MORE_DATA
);
444 print_special (int print_sids
,
445 PSID_IDENTIFIER_AUTHORITY auth
, BYTE cnt
,
446 DWORD sub1
, DWORD sub2
, DWORD sub3
, DWORD sub4
,
447 DWORD sub5
, DWORD sub6
, DWORD sub7
, DWORD sub8
)
449 char name
[256], dom
[256];
450 DWORD len
, len2
, rid
;
454 if (AllocateAndInitializeSid (auth
, cnt
, sub1
, sub2
, sub3
, sub4
,
455 sub5
, sub6
, sub7
, sub8
, &sid
))
457 if (LookupAccountSid (NULL
, sid
,
458 name
, (len
= 256, &len
),
459 dom
, (len2
= 256, &len
),
478 printf ("%s:*:%lu:%lu:%s%s::\n",
479 name
, rid
, rid
== 18 ? 544 : rid
, /* SYSTEM hack */
480 print_sids
? "," : "",
481 print_sids
? put_sid (sid
) : "");
488 usage (FILE * stream
, int isNT
)
490 fprintf (stream
, "Usage: mkpasswd [OPTION]... [domain]\n\n"
491 "This program prints a /etc/passwd file to stdout\n\n"
494 fprintf (stream
, " -l,--local print local user accounts\n"
495 " -c,--current print current account, if a domain account\n"
496 " -d,--domain print domain accounts (from current domain\n"
497 " if no domain specified)\n"
498 " -o,--id-offset offset change the default offset (10000) added to uids\n"
499 " in domain accounts.\n"
500 " -g,--local-groups print local group information too\n"
501 " if no domain specified\n"
502 " -m,--no-mount don't use mount points for home dir\n"
503 " -s,--no-sids don't print SIDs in GCOS field\n"
504 " (this affects ntsec)\n");
505 fprintf (stream
, " -p,--path-to-home path use specified path instead of user account home dir\n"
506 " -u,--username username only return information for the specified user\n"
507 " -h,--help displays this message\n"
508 " -v,--version version information and exit\n\n");
510 fprintf (stream
, "One of `-l', `-d' or `-g' must be given.\n");
514 struct option longopts
[] = {
515 {"local", no_argument
, NULL
, 'l'},
516 {"current", no_argument
, NULL
, 'c'},
517 {"domain", no_argument
, NULL
, 'd'},
518 {"id-offset", required_argument
, NULL
, 'o'},
519 {"local-groups", no_argument
, NULL
, 'g'},
520 {"no-mount", no_argument
, NULL
, 'm'},
521 {"no-sids", no_argument
, NULL
, 's'},
522 {"path-to-home", required_argument
, NULL
, 'p'},
523 {"username", required_argument
, NULL
, 'u'},
524 {"help", no_argument
, NULL
, 'h'},
525 {"version", no_argument
, NULL
, 'v'},
526 {0, no_argument
, NULL
, 0}
529 char opts
[] = "lcdo:gsmhp:u:v";
534 const char *v
= strchr (version
, ':');
544 len
= strchr (v
, ' ') - v
;
547 mkpasswd (cygwin) %.*s\n\
548 passwd File Generator\n\
549 Copyright 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.\n\
551 ", len
, v
, __DATE__
);
555 main (int argc
, char **argv
)
557 LPWSTR servername
= NULL
;
558 DWORD rc
= ERROR_SUCCESS
;
559 WCHAR domain_name
[200];
561 int print_current
= 0;
562 int print_domain
= 0;
563 int print_local_groups
= 0;
564 int domain_name_specified
= 0;
566 int print_cygpath
= 1;
567 int id_offset
= 10000;
570 char *disp_username
= NULL
;
571 char name
[256], passed_home_path
[MAX_PATH
];
574 isNT
= (GetVersion () < 0x80000000);
575 passed_home_path
[0] = '\0';
577 setmode (1, O_BINARY
);
579 if (isNT
&& argc
== 1)
580 return usage (stderr
, isNT
);
583 while ((i
= getopt_long (argc
, argv
, opts
, longopts
, NULL
)) != EOF
)
596 id_offset
= strtol (optarg
, NULL
, 10);
599 print_local_groups
= 1;
608 if (optarg
[0] != '/')
610 fprintf (stderr
, "%s: `%s' is not a fully qualified path.\n",
614 strcpy (passed_home_path
, optarg
);
615 if (optarg
[strlen (optarg
)-1] != '/')
616 strcat (passed_home_path
, "/");
619 disp_username
= optarg
;
622 usage (stdout
, isNT
);
628 fprintf (stderr
, "Try `%s --help' for more information.\n", argv
[0]);
634 /* This takes Windows 9x/ME into account. */
635 if (passed_home_path
[0] == '\0')
636 strcpy (passed_home_path
, "/home/");
639 printf ("admin:use_crypt:%lu:%lu:Administrator:%sadmin:/bin/bash\n",
640 DOMAIN_USER_RID_ADMIN
,
641 DOMAIN_ALIAS_RID_ADMINS
,
643 if (GetUserName (name
, (len
= 256, &len
)))
644 disp_username
= name
;
646 if (disp_username
&& disp_username
[0])
648 /* Create a pseudo random uid */
649 unsigned long uid
= 0, i
;
650 for (i
= 0; disp_username
[i
]; i
++)
651 uid
+= toupper (disp_username
[i
]) << ((6 * i
) % 25);
652 uid
= (uid
% (65535 - DOMAIN_USER_RID_ADMIN
- 1))
653 + DOMAIN_USER_RID_ADMIN
+ 1;
655 printf ("%s:use_crypt:%lu:%lu:%s:%s%s:/bin/bash\n",
658 DOMAIN_ALIAS_RID_ADMINS
,
665 if (!print_local
&& !print_domain
&& !print_local_groups
)
667 fprintf (stderr
, "%s: Specify one of `-l', `-d' or `-g'\n", argv
[0]);
674 fprintf (stderr
, "%s: A domain name is only accepted "
675 "when `-d' is given.\n", argv
[0]);
678 mbstowcs (domain_name
, argv
[optind
], (strlen (argv
[optind
]) + 1));
679 domain_name_specified
= 1;
683 print_win_error(GetLastError ());
687 if (disp_username
== NULL
)
691 * Get `Everyone' group
693 print_special (print_sids
, &sid_world_auth
, 1, SECURITY_WORLD_RID
,
694 0, 0, 0, 0, 0, 0, 0);
699 print_special (print_sids
, &sid_nt_auth
, 1, SECURITY_LOCAL_SYSTEM_RID
,
700 0, 0, 0, 0, 0, 0, 0);
702 * Get `administrators' group
704 if (!print_local_groups
)
705 print_special (print_sids
, &sid_nt_auth
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
706 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0);
708 if (print_local_groups
)
709 enum_local_groups (print_sids
);
714 if (domain_name_specified
)
715 rc
= netgetdcname (NULL
, domain_name
, (LPBYTE
*) & servername
);
718 rc
= netgetdcname (NULL
, NULL
, (LPBYTE
*) & servername
);
720 if (rc
!= ERROR_SUCCESS
)
726 enum_users (servername
, print_sids
, print_cygpath
, passed_home_path
,
727 id_offset
, disp_username
);
731 enum_users (NULL
, print_sids
, print_cygpath
, passed_home_path
, 0,
734 if (print_current
&& !print_domain
)
735 current_user(print_sids
, print_cygpath
, passed_home_path
,
736 id_offset
, disp_username
);
739 netapibufferfree (servername
);