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
18 #include <sys/cygwin.h>
22 #include <sys/fcntl.h>
25 static const char version
[] = "$Revision$";
27 SID_IDENTIFIER_AUTHORITY sid_world_auth
= {SECURITY_WORLD_SID_AUTHORITY
};
28 SID_IDENTIFIER_AUTHORITY sid_nt_auth
= {SECURITY_NT_AUTHORITY
};
30 NET_API_STATUS
WINAPI (*netapibufferfree
)(PVOID
);
31 NET_API_STATUS
WINAPI (*netuserenum
)(LPWSTR
,DWORD
,DWORD
,PBYTE
*,DWORD
,PDWORD
,PDWORD
,PDWORD
);
32 NET_API_STATUS
WINAPI (*netlocalgroupenum
)(LPWSTR
,DWORD
,PBYTE
*,DWORD
,PDWORD
,PDWORD
,PDWORD
);
33 NET_API_STATUS
WINAPI (*netgetdcname
)(LPWSTR
,LPWSTR
,PBYTE
*);
34 NET_API_STATUS
WINAPI (*netusergetinfo
)(LPWSTR
,LPWSTR
,DWORD
,PBYTE
*);
37 #define min(a,b) (((a)<(b))?(a):(b))
43 HANDLE h
= LoadLibrary ("netapi32.dll");
48 if (!(netapibufferfree
= (void *) GetProcAddress (h
, "NetApiBufferFree")))
50 if (!(netuserenum
= (void *) GetProcAddress (h
, "NetUserEnum")))
52 if (!(netlocalgroupenum
= (void *) GetProcAddress (h
, "NetLocalGroupEnum")))
54 if (!(netgetdcname
= (void *) GetProcAddress (h
, "NetGetDCName")))
56 if (!(netusergetinfo
= (void *) GetProcAddress (h
, "NetUserGetInfo")))
70 sprintf(t
, "%u", GetSidIdentifierAuthority (sid
)->Value
[5]);
72 for (i
= 0; i
< *GetSidSubAuthorityCount (sid
); ++i
)
74 sprintf(t
, "-%lu", *GetSidSubAuthority (sid
, i
));
81 psx_dir (char *in
, char *out
)
83 if (isalpha (in
[0]) && in
[1] == ':')
85 sprintf (out
, "/cygdrive/%c", in
[0]);
104 uni2ansi (LPWSTR wcs
, char *mbs
, int size
)
107 WideCharToMultiByte (CP_ACP
, 0, wcs
, -1, mbs
, size
, NULL
, NULL
);
113 print_win_error(DWORD code
)
117 if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
118 | FORMAT_MESSAGE_IGNORE_INSERTS
,
121 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
122 (LPTSTR
) buf
, sizeof (buf
), NULL
))
123 fprintf (stderr
, "mkpasswd: [%lu] %s", code
, buf
);
125 fprintf (stderr
, "mkpasswd: error %lu", code
);
129 enum_users (LPWSTR servername
, int print_sids
, int print_cygpath
,
130 const char * passed_home_path
, int id_offset
, char *disp_username
)
133 DWORD entriesread
= 0;
134 DWORD totalentries
= 0;
135 DWORD resume_handle
= 0;
137 char ansi_srvname
[256];
141 uni2ansi (servername
, ansi_srvname
, sizeof (ansi_srvname
));
147 if (disp_username
!= NULL
)
149 MultiByteToWideChar (CP_ACP
, 0, disp_username
, -1, uni_name
, 512 );
150 rc
= netusergetinfo(servername
, (LPWSTR
) & uni_name
, 3,
151 (LPBYTE
*) &buffer
);
155 rc
= netuserenum (servername
, 3, FILTER_NORMAL_ACCOUNT
,
156 (LPBYTE
*) & buffer
, 1024,
157 &entriesread
, &totalentries
, &resume_handle
);
160 case ERROR_ACCESS_DENIED
:
164 case ERROR_MORE_DATA
:
173 for (i
= 0; i
< entriesread
; i
++)
177 char homedir_psx
[MAX_PATH
];
178 char homedir_w32
[MAX_PATH
];
179 char domain_name
[100];
180 DWORD domname_len
= 100;
181 char psid_buffer
[1024];
182 PSID psid
= (PSID
) psid_buffer
;
183 DWORD sid_length
= 1024;
184 SID_NAME_USE acc_type
;
186 int uid
= buffer
[i
].usri3_user_id
;
187 int gid
= buffer
[i
].usri3_primary_group_id
;
188 uni2ansi (buffer
[i
].usri3_name
, username
, sizeof (username
));
189 uni2ansi (buffer
[i
].usri3_full_name
, fullname
, sizeof (fullname
));
190 homedir_w32
[0] = homedir_psx
[0] = '\0';
191 if (passed_home_path
[0] == '\0')
193 uni2ansi (buffer
[i
].usri3_home_dir
, homedir_w32
,
194 sizeof (homedir_w32
));
195 if (homedir_w32
[0] != '\0')
198 cygwin_conv_to_posix_path (homedir_w32
, homedir_psx
);
200 psx_dir (homedir_w32
, homedir_psx
);
204 strcpy (homedir_psx
, "/home/");
205 strcat (homedir_psx
, username
);
210 strcpy (homedir_psx
, passed_home_path
);
211 strcat (homedir_psx
, username
);
216 if (!LookupAccountName (servername
? ansi_srvname
: NULL
,
219 domain_name
, &domname_len
,
222 print_win_error(GetLastError ());
225 else if (acc_type
== SidTypeDomain
)
229 strcpy (domname
, domain_name
);
230 strcat (domname
, "\\");
231 strcat (domname
, username
);
234 if (!LookupAccountName (servername
? ansi_srvname
: NULL
,
237 domain_name
, &domname_len
,
240 print_win_error(GetLastError ());
245 printf ("%s:unused_by_nt/2000/xp:%d:%d:%s%s%s%s%s%s%s%s:%s:/bin/bash\n",
250 print_sids
&& fullname
[0] ? "," : "",
251 print_sids
? "U-" : "",
252 print_sids
? domain_name
: "",
253 print_sids
&& domain_name
[0] ? "\\" : "",
254 print_sids
? username
: "",
255 print_sids
? "," : "",
256 print_sids
? put_sid (psid
) : "",
260 netapibufferfree (buffer
);
263 while (rc
== ERROR_MORE_DATA
);
266 netapibufferfree (servername
);
272 enum_local_groups (int print_sids
)
274 LOCALGROUP_INFO_0
*buffer
;
275 DWORD entriesread
= 0;
276 DWORD totalentries
= 0;
277 DWORD resume_handle
= 0;
284 rc
= netlocalgroupenum (NULL
, 0, (LPBYTE
*) & buffer
, 1024,
285 &entriesread
, &totalentries
, &resume_handle
);
288 case ERROR_ACCESS_DENIED
:
292 case ERROR_MORE_DATA
:
301 for (i
= 0; i
< entriesread
; i
++)
303 char localgroup_name
[100];
304 char domain_name
[100];
305 DWORD domname_len
= 100;
306 char psid_buffer
[1024];
307 PSID psid
= (PSID
) psid_buffer
;
308 DWORD sid_length
= 1024;
310 SID_NAME_USE acc_type
;
311 uni2ansi (buffer
[i
].lgrpi0_name
, localgroup_name
, sizeof (localgroup_name
));
313 if (!LookupAccountName (NULL
, localgroup_name
, psid
,
314 &sid_length
, domain_name
, &domname_len
,
317 print_win_error(GetLastError ());
320 else if (acc_type
== SidTypeDomain
)
324 strcpy (domname
, domain_name
);
325 strcat (domname
, "\\");
326 strcat (domname
, localgroup_name
);
329 if (!LookupAccountName (NULL
, domname
,
331 domain_name
, &domname_len
,
334 print_win_error(GetLastError ());
339 gid
= *GetSidSubAuthority (psid
, *GetSidSubAuthorityCount(psid
) - 1);
341 printf ("%s:*:%ld:%ld:%s%s::\n", localgroup_name
, gid
, gid
,
342 print_sids
? "," : "",
343 print_sids
? put_sid (psid
) : "");
346 netapibufferfree (buffer
);
349 while (rc
== ERROR_MORE_DATA
);
355 print_special (int print_sids
,
356 PSID_IDENTIFIER_AUTHORITY auth
, BYTE cnt
,
357 DWORD sub1
, DWORD sub2
, DWORD sub3
, DWORD sub4
,
358 DWORD sub5
, DWORD sub6
, DWORD sub7
, DWORD sub8
)
360 char name
[256], dom
[256];
361 DWORD len
, len2
, rid
;
365 if (AllocateAndInitializeSid (auth
, cnt
, sub1
, sub2
, sub3
, sub4
,
366 sub5
, sub6
, sub7
, sub8
, &sid
))
368 if (LookupAccountSid (NULL
, sid
,
369 name
, (len
= 256, &len
),
370 dom
, (len2
= 256, &len
),
389 printf ("%s:*:%lu:%lu:%s%s::\n",
390 name
, rid
, rid
== 18 ? 544 : rid
, /* SYSTEM hack */
391 print_sids
? "," : "",
392 print_sids
? put_sid (sid
) : "");
399 usage (FILE * stream
, int status
)
401 fprintf (stream
, "Usage: mkpasswd [OPTION]... [domain]\n\n"
402 "This program prints a /etc/passwd file to stdout\n\n"
404 " -l,--local print local user accounts\n"
405 " -d,--domain print domain accounts (from current domain\n"
406 " if no domain specified)\n"
407 " -o,--id-offset offset change the default offset (10000) added to uids\n"
408 " in domain accounts.\n"
409 " -g,--local-groups print local group information too\n"
410 " if no domain specified\n"
411 " -m,--no-mount don't use mount points for home dir\n"
412 " -s,--no-sids don't print SIDs in GCOS field\n"
413 " (this affects ntsec)\n"
414 " -p,--path-to-home path use specified path instead of user account home dir\n"
415 " -u,--username username only return information for the specified user\n"
416 " -h,--help displays this message\n"
417 " -v,--version version information and exit\n\n"
418 "One of `-l', `-d' or `-g' must be given on NT/W2K.\n");
422 struct option longopts
[] = {
423 {"local", no_argument
, NULL
, 'l'},
424 {"domain", no_argument
, NULL
, 'd'},
425 {"id-offset", required_argument
, NULL
, 'o'},
426 {"local-groups", no_argument
, NULL
, 'g'},
427 {"no-mount", no_argument
, NULL
, 'm'},
428 {"no-sids", no_argument
, NULL
, 's'},
429 {"path-to-home", required_argument
, NULL
, 'p'},
430 {"username", required_argument
, NULL
, 'u'},
431 {"help", no_argument
, NULL
, 'h'},
432 {"version", no_argument
, NULL
, 'v'},
433 {0, no_argument
, NULL
, 0}
436 char opts
[] = "ldo:gsmhp:u:v";
441 const char *v
= strchr (version
, ':');
451 len
= strchr (v
, ' ') - v
;
454 mkpasswd (cygwin) %.*s\n\
455 passwd File Generator\n\
456 Copyright 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.\n\
458 ", len
, v
, __DATE__
);
462 main (int argc
, char **argv
)
464 LPWSTR servername
= NULL
;
465 DWORD rc
= ERROR_SUCCESS
;
466 WCHAR domain_name
[200];
468 int print_domain
= 0;
469 int print_local_groups
= 0;
470 int domain_name_specified
= 0;
472 int print_cygpath
= 1;
473 int id_offset
= 10000;
475 char *disp_username
= NULL
;
477 char name
[256], passed_home_path
[MAX_PATH
];
480 passed_home_path
[0] = '\0';
482 setmode (1, O_BINARY
);
484 if (GetVersion () < 0x80000000)
487 return usage (stderr
, 1);
490 while ((i
= getopt_long (argc
, argv
, opts
, longopts
, NULL
)) != EOF
)
500 id_offset
= strtol (optarg
, NULL
, 10);
503 print_local_groups
= 1;
512 if (optarg
[0] != '/')
514 fprintf (stderr
, "%s: `%s' is not a fully qualified path.\n",
518 strcpy (passed_home_path
, optarg
);
519 if (optarg
[strlen (optarg
)-1] != '/')
520 strcat (passed_home_path
, "/");
523 disp_username
= optarg
;
526 return usage (stdout
, 0);
531 fprintf (stderr
, "Try `%s --help' for more information.\n", argv
[0]);
534 if (!print_local
&& !print_domain
&& !print_local_groups
)
536 fprintf (stderr
, "%s: Specify one of `-l', `-d' or `-g'\n", argv
[0]);
543 fprintf (stderr
, "%s: A domain name is only accepted "
544 "when `-d' is given.\n", argv
[0]);
547 mbstowcs (domain_name
, argv
[optind
], (strlen (argv
[optind
]) + 1));
548 domain_name_specified
= 1;
553 /* This takes Windows 9x/ME into account. */
554 if (GetVersion () >= 0x80000000)
556 /* Same behaviour as in cygwin/uinfo.cc (internal_getlogin). */
557 if (!GetUserName (name
, (len
= 256, &len
)))
558 strcpy (name
, "unknown");
560 if (passed_home_path
[0] == '\0')
561 strcpy (passed_home_path
, "/home/");
563 printf ("%s::%ld:%ld::%s%s:/bin/bash\n", name
,
564 DOMAIN_USER_RID_ADMIN
,
565 DOMAIN_ALIAS_RID_ADMINS
,
574 print_win_error(GetLastError ());
578 if (disp_username
== NULL
)
582 * Get `Everyone' group
584 print_special (print_sids
, &sid_world_auth
, 1, SECURITY_WORLD_RID
,
585 0, 0, 0, 0, 0, 0, 0);
590 print_special (print_sids
, &sid_nt_auth
, 1, SECURITY_LOCAL_SYSTEM_RID
,
591 0, 0, 0, 0, 0, 0, 0);
593 * Get `administrators' group
595 if (!print_local_groups
)
596 print_special (print_sids
, &sid_nt_auth
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
597 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0);
599 if (print_local_groups
)
600 enum_local_groups (print_sids
);
605 if (domain_name_specified
)
606 rc
= netgetdcname (NULL
, domain_name
, (LPBYTE
*) & servername
);
609 rc
= netgetdcname (NULL
, NULL
, (LPBYTE
*) & servername
);
611 if (rc
!= ERROR_SUCCESS
)
617 enum_users (servername
, print_sids
, print_cygpath
, passed_home_path
,
618 id_offset
, disp_username
);
622 enum_users (NULL
, print_sids
, print_cygpath
, passed_home_path
, 0,
626 netapibufferfree (servername
);