]> sourceware.org Git - newlib-cygwin.git/blobdiff - winsup/utils/mkpasswd.c
Cygwin: add 3.2.1 release file and add fixes up to this point
[newlib-cygwin.git] / winsup / utils / mkpasswd.c
index 66cf9f364d80e40dbb466ebc0ebf3fca57803eb4..3bbdb1c71033da91808900ba01a9cf2e8db7a3a5 100644 (file)
@@ -1,15 +1,12 @@
 /* mkpasswd.c:
 
-   Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2008, 2009,
-   2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
-
    This file is part of Cygwin.
 
    This software is a copyrighted work licensed under the terms of the
    Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
    details. */
 
-#define _WIN32_WINNT 0x0600
+#define _WIN32_WINNT 0x0a00
 #include <errno.h>
 #include <ctype.h>
 #include <stdlib.h>
@@ -35,8 +32,6 @@
 
 #define print_win_error(x) _print_win_error(x, __LINE__)
 
-#define MAX_SID_LEN 40
-
 SID_IDENTIFIER_AUTHORITY sid_world_auth = {SECURITY_WORLD_SID_AUTHORITY};
 SID_IDENTIFIER_AUTHORITY sid_nt_auth = {SECURITY_NT_AUTHORITY};
 
@@ -134,7 +129,8 @@ enum_unix_users (domlist_t *mach, const char *sep, DWORD id_offset,
   WCHAR dom[MAX_DOMAIN_NAME_LEN + 1];
   DWORD ulen, dlen, sidlen;
   PSID psid;
-  char psid_buffer[MAX_SID_LEN];
+  PSID numeric_psid;
+  char psid_buffer[SECURITY_MAX_SID_SIZE];
   SID_NAME_USE acc_type;
 
   int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1);
@@ -145,12 +141,13 @@ enum_unix_users (domlist_t *mach, const char *sep, DWORD id_offset,
       return;
     }
 
-  if (!AllocateAndInitializeSid (&auth, 2, 1, 0, 0, 0, 0, 0, 0, 0, &psid))
+  if (!AllocateAndInitializeSid (&auth, 2, 1, 0, 0, 0, 0, 0, 0, 0,
+                                &numeric_psid))
     return;
 
   if (!(user_list = strdup (unix_user_list)))
     {
-      FreeSid (psid);
+      FreeSid (numeric_psid);
       return;
     }
 
@@ -161,17 +158,19 @@ enum_unix_users (domlist_t *mach, const char *sep, DWORD id_offset,
          PWCHAR p = wcpcpy (user, L"Unix User\\");
          ret = mbstowcs (p, ustr, UNLEN + 1);
          if (ret < 1 || ret >= UNLEN + 1)
-           fprintf (stderr, "%s: Invalid user name '%s'.  Skipping...\n",
-                    program_invocation_short_name, ustr);
-         else if (LookupAccountNameW (machine, user,
-                                      psid = (PSID) psid_buffer,
-                                      (sidlen = MAX_SID_LEN, &sidlen),
-                                      dom,
-                                      (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen),
-                                      &acc_type))
-           printf ("%s%s%ls:unused:%" PRIu32 ":99999:,%s::\n",
-                   mach->with_dom ? "Unix_User" : "",
-                   mach->with_dom ? sep : "",
+           {
+             fprintf (stderr, "%s: Invalid user name '%s'.  Skipping...\n",
+                      program_invocation_short_name, ustr);
+             continue;
+           }
+         psid = (PSID) psid_buffer;
+         sidlen = SECURITY_MAX_SID_SIZE;
+         dlen = MAX_DOMAIN_NAME_LEN + 1;
+         if (LookupAccountNameW (machine, user, psid, &sidlen,
+                                 dom, &dlen, &acc_type))
+           printf ("%s%s%ls:*:%" PRIu32 ":99999:,%s::\n",
+                   "Unix_User",
+                   sep,
                    user + 10,
                    (unsigned int) (id_offset +
                    *GetSidSubAuthority (psid,
@@ -198,17 +197,17 @@ enum_unix_users (domlist_t *mach, const char *sep, DWORD id_offset,
            }
          for (; start <= stop; ++ start)
            {
+             psid = numeric_psid;
              *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1)
              = start;
-             if (LookupAccountSidW (machine, psid,
-                                    user, (ulen = GNLEN + 1, &ulen),
-                                    dom,
-                                    (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen),
-                                    &acc_type)
+             ulen = GNLEN + 1;
+             dlen = MAX_DOMAIN_NAME_LEN + 1;
+             if (LookupAccountSidW (machine, psid, user, &ulen,
+                                    dom, &dlen, &acc_type)
                  && !iswdigit (user[0]))
-               printf ("%s%s%ls:unused:%" PRIu32 ":99999:,%s::\n",
-                       mach->with_dom ? "Unix_User" : "",
-                       mach->with_dom ? sep : "",
+               printf ("%s%s%ls:*:%" PRIu32 ":99999:,%s::\n",
+                       "Unix_User",
+                       sep,
                        user,
                        (unsigned int) (id_offset + start),
                        put_sid (psid));
@@ -217,7 +216,7 @@ enum_unix_users (domlist_t *mach, const char *sep, DWORD id_offset,
     }
 
   free (user_list);
-  FreeSid (psid);
+  FreeSid (numeric_psid);
 }
 
 static int
@@ -279,9 +278,9 @@ enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
          char homedir_psx[PATH_MAX];
          WCHAR domain_name[MAX_DOMAIN_NAME_LEN + 1];
          DWORD domname_len = MAX_DOMAIN_NAME_LEN + 1;
-         char psid_buffer[MAX_SID_LEN];
+         char psid_buffer[SECURITY_MAX_SID_SIZE];
          PSID psid = (PSID) psid_buffer;
-         DWORD sid_length = MAX_SID_LEN;
+         DWORD sid_length = SECURITY_MAX_SID_SIZE;
          SID_NAME_USE acc_type;
 
          int uid = buffer[i].usri3_user_id;
@@ -313,11 +312,13 @@ enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
          else if (acc_type == SidTypeDomain)
            {
              WCHAR domname[MAX_DOMAIN_NAME_LEN + UNLEN + 2];
+             PWCHAR p;
 
-             wcscpy (domname, machine);
-             wcscat (domname, L"\\");
-             wcscat (domname, buffer[i].usri3_name);
-             sid_length = MAX_SID_LEN;
+             p = wcpcpy (domname, machine);
+             p = wcpcpy (p, L"\\");
+             p = wcpncpy (p, buffer[i].usri3_name, UNLEN);
+             *p = L'\0';
+             sid_length = SECURITY_MAX_SID_SIZE;
              domname_len = sizeof (domname);
              if (!LookupAccountNameW (machine, domname, psid,
                                       &sid_length, domain_name,
@@ -333,7 +334,7 @@ enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
          else if (EqualSid (curr_user.psid, psid))
            got_curr_user = TRUE;
 
-         printf ("%ls%s%ls:unused:%" PRIu32 ":%" PRIu32
+         printf ("%ls%s%ls:*:%" PRIu32 ":%" PRIu32
                  ":%ls%sU-%ls\\%ls,%s:%s:/bin/bash\n",
                  mach->with_dom ? domain_name : L"",
                  mach->with_dom ? sep : "",
@@ -357,7 +358,7 @@ enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
   return 0;
 }
 
-static int
+static int __attribute__ ((__noreturn__))
 usage (FILE * stream)
 {
   fprintf (stream,
@@ -370,33 +371,35 @@ usage (FILE * stream)
 "\n"
 "Options:\n"
 "\n"
-"   -l,--local [machine]    print local user accounts\n"
-"                           (from local machine if no machine specified)\n"
-"   -L,--Local machine      ditto, but generate username with machine prefix\n"
-"   -d,--domain [domain]    print domain accounts\n"
-"                           (from current domain if no domain specified)\n"
-"   -c,--current            print current user\n"
-"   -S,--separator char     for -l use character char as domain\\user\n"
-"                           separator in username instead of the default '%s'\n"
-"   -o,--id-offset offset   change the default offset (0x10000) added to uids\n"
-"                           in domain or foreign server accounts.\n"
-"   -u,--username username  only return information for the specified user\n"
-"                           one of -l, -d must be specified, too\n"
-"   -b,--no-builtin         don't print BUILTIN users\n"
-"   -p,--path-to-home path  use specified path instead of user account home dir\n"
-"                           or /home prefix\n"
-"   -U,--unix userlist      print UNIX users when using -l on a UNIX Samba\n"
-"                           server.  userlist is a comma-separated list of\n"
+"   -l,--local [machine]    Print local user accounts of \"machine\",\n"
+"                           from local machine if no machine specified.\n"
+"                           Automatically adding machine prefix for local\n"
+"                           machine depends on settings in /etc/nsswitch.conf.\n"
+"   -L,--Local machine      Ditto, but generate username with machine prefix.\n"
+"   -d,--domain [domain]    Print domain accounts,\n"
+"                           from current domain if no domain specified.\n"
+"   -c,--current            Print current user.\n"
+"   -S,--separator char     For -L use character char as domain\\user\n"
+"                           separator in username instead of the default '%s'.\n"
+"   -o,--id-offset offset   Change the default offset (0x10000) added to uids\n"
+"                           of foreign local machine accounts.  Use with -l/-L.\n"
+"   -u,--username username  Only return information for the specified user.\n"
+"                           One of -l, -d must be specified, too\n"
+"   -b,--no-builtin         Don't print BUILTIN users.\n"
+"   -p,--path-to-home path  Use specified path instead of user account home dir\n"
+"                           or /home prefix.\n"
+"   -U,--unix userlist      Print UNIX users when using -l on a UNIX Samba\n"
+"                           server.  Userlist is a comma-separated list of\n"
 "                           usernames or uid ranges (root,-25,50-100).\n"
-"                           (enumerating large ranges can take a long time!)\n"
-"   -h,--help               displays this message\n"
-"   -V,--version            version information and exit\n"
+"                           Enumerating large ranges can take a long time!\n"
+"   -h,--help               Displays this message.\n"
+"   -V,--version            Version information and exit.\n"
 "\n"
 "Default is to print local accounts on stand-alone machines, domain accounts\n"
 "on domain controllers and domain member machines.\n"
 "\n", program_invocation_short_name,
       (const char *) cygwin_internal (CW_GETNSSSEP));
-  return 1;
+  exit (stream == stdout ? 0 : 1);
 }
 
 static struct option longopts[] = {
@@ -427,7 +430,7 @@ print_version ()
 {
   printf ("mkpasswd (cygwin) %d.%d.%d\n"
          "Passwd File Generator\n"
-         "Copyright (C) 1997 - %s Red Hat, Inc.\n"
+         "Copyright (C) 1997 - %s Cygwin Authors\n"
          "This is free software; see the source for copying conditions.  There is NO\n"
          "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
          CYGWIN_VERSION_DLL_MAJOR / 1000,
@@ -441,6 +444,7 @@ main (int argc, char **argv)
 {
   int print_domlist = 0;
   domlist_t domlist[32];
+  char cname[1024];
   char *opt, *p, *ep;
   int print_current = 0;
   int print_builtin = 1;
@@ -452,6 +456,7 @@ main (int argc, char **argv)
   char *disp_username = NULL;
   char passed_home_path[PATH_MAX];
   int optional_args = 0;
+  uintptr_t nss_src = cygwin_internal (CW_GETNSS_PWD_SRC);
 
   passed_home_path[0] = '\0';
   if (!isatty (1))
@@ -513,21 +518,48 @@ main (int argc, char **argv)
                       program_invocation_short_name,
                       domlist[i].domain ? "domain" : "machine",
                       domlist[i].str);
-             goto skip;
+             break;
            }
        domlist[print_domlist].str = opt;
        if (opt && (p = strchr (opt, ',')))
          {
            if (p == opt)
              {
-               fprintf (stderr, "%s: Malformed domain,offset string '%s'.  "
+               fprintf (stderr, "%s: Malformed domain string '%s'.  "
                         "Skipping...\n", program_invocation_short_name, opt);
                break;
              }
            *p = '\0';
          }
-       domlist[print_domlist++].with_dom = (c == 'L');
-skip:
+       if (c == 'l' || c == 'L')
+         {
+           DWORD csize = sizeof cname;
+
+           domlist[print_domlist].with_dom = (c == 'L');
+           if (!opt)
+             {
+               /* If the system uses /etc/passwd exclusively as account DB,
+                  create local group names the old fashioned way. */
+               if (nss_src == NSS_SRC_FILES)
+                 {
+                   GetComputerNameExA (ComputerNameNetBIOS, cname, &csize);
+                   domlist[print_domlist].str = cname;
+                 }
+             }
+           else if (nss_src != NSS_SRC_FILES)
+             {
+               /* If the system uses Windows account DBs, check if machine
+                  name is local machine.  If so, remove the domain name to
+                  enforce system naming convention. */
+               if (GetComputerNameExA (strchr (opt, '.')
+                                       ? ComputerNameDnsFullyQualified
+                                       : ComputerNameNetBIOS,
+                                       cname, &csize)
+                   && strcasecmp (opt, cname) == 0)
+                 domlist[print_domlist].str = NULL;
+             }
+         }
+       ++print_domlist;
        break;
       case 'S':
        sep_char = optarg;
@@ -574,7 +606,6 @@ skip:
        break;
       case 'h':
        usage (stdout);
-       return 0;
       case 'V':
        print_version ();
        return 0;
@@ -676,8 +707,9 @@ skip:
     {
       if (domlist[i].domain || !domlist[i].str)
        continue;
-      enum_users (domlist + i, sep_char, passed_home_path, off, disp_username,
-                 print_current);
+      enum_users (domlist + i, sep_char, passed_home_path,
+                 (nss_src == NSS_SRC_FILES) ? 0x30000 : off,
+                 disp_username, print_current);
       if (!domlist[i].domain && domlist[i].str && print_unix)
        enum_unix_users (domlist + i, sep_char, 0xff000000, print_unix);
       off += id_offset;
This page took 0.033464 seconds and 5 git commands to generate.