passwd help/version patch

Joshua Daniel Franklin joshuadfranklin@yahoo.com
Thu May 30 19:13:00 GMT 2002


--- Corinna Vinschen <cygwin-patches@cygwin.com> wrote:
> > > Or perhaps change passwd to take the Cygwin name and
> > > convert it to the windows name???
> > >
> > > Corinna
> >
> > Maybe I'm missing something, but there doesn't seem to be any Win32
> > function to get a username from a uid other than NetUserEnum, but
> > I really don't think people running 'passwd bob' are wanting to enum
> > all users. The code to do it wouldn't be that hard, but it wouldn't
> > work for those people with domains (unless they specify a domain like
> > for mkpasswd).
> >
> > Maybe mkpasswd should cache the info somewhere other than just /etc/passwd
> > for this purpose? Or use the GECOS field?
>
> I'm sorry if my mail wasn't clear but I just asked for getting the
> Win32 name from the cygwin name.  The cygwin name is the one given
> on the command line or what is returned by getlogin().  The information
> about the Win32 name is then returned in the pw_gecos field by
> getpwnam().  Either a U-DOMAIN\NAME or a S-1-5-xxx sid.  If the
> U- field is given, it contains the name, otherwise a LookupAccountSid()
> gives the Win32 name from the SID.  If neither is given, the Cygwin
> username is equal to the Win32 name.
>
> There is already a function `extract_nt_dom_user()' in Cygwin, file
> security.cc which contains this functionality.  Unfortunately it
> isn't exported so it would have to be copied to passwd.c (and
> transformed to plain c).
>
> Or we export that function.  I think it is a useful functionality for
> Cygwin tools.  Perhaps with the "cygwin_" prefix.
>
> Corinna

Thanks very much for the pointers. However,
After working on it a while, I think that exporting a
cygwin_extract_nt_dom_user() would be best. The attached patch is a
halfway solution that just copies most of extract_nt_dom_user()
other than the SID code. It will get the correct username in the case of
a U-DOMAIN type of GECOS, but if only a ':S-1-5-xxx:' is in the GECOS
it fails with the old 'passwd: unknown user boalhg' message.
If a Win32 username is found, a line like: 'Windows username : bob'
is output.

I tried to build up the structures necessary for LookupAccountSid()
with the sec* stuff in winsup/cygwin as a guide, but it looks like
reinventing a C wheel from C++ spare parts. It'd be a lot better to
be able to just put cygwin_extract_nt_dom_user(pw, domain, (char *) user)
right in passwd.c IMHO.

Caveat: I don't have a real domain that I'm testing with.

2002-05-30  Joshua Daniel Franklin <joshuadfranklin@yahoo.com>

	* passwd.c (extract_nt_dom_user): New function.
	(GetPW): Try to look up Win32 username in case of NERR_UserNotFound.
-------------- next part --------------
--- passwd.c-orig	Thu May 30 20:05:05 2002
+++ passwd.c	Thu May 30 20:54:10 2002
@@ -28,6 +28,7 @@ details. */
 #define USER_PRIV_ADMIN		 2
 
 #define UF_LOCKOUT            0x00010
+#define INTERNET_MAX_HOST_NAME_LENGTH 256
 
 static const char version[] = "$Revision: 1.4 $";
 static char *prog_name;
@@ -101,15 +102,66 @@ EvalRet (int ret, const char *user)
   return 1;
 }
 
+void
+extract_nt_dom_user (const struct passwd *pw, char *domain, char *user)
+{
+  char buf[INTERNET_MAX_HOST_NAME_LENGTH + UNLEN + 2];
+  char *c;
+
+  strcpy (domain, "");
+  strcpy (buf, pw->pw_name);
+
+  if ((pw && pw->pw_gecos) && (strrchr (pw->pw_gecos, ',') == NULL))
+  {
+    return;
+  }
+
+  if (pw->pw_gecos)
+    {
+      if ((c = strstr (pw->pw_gecos, "U-")) != NULL &&
+          (c == pw->pw_gecos || c[-1] == ','))
+        {
+          buf[0] = '\0';
+          strncat (buf, c + 2, INTERNET_MAX_HOST_NAME_LENGTH + UNLEN + 1);
+          if ((c = strchr (buf, ',')) != NULL)
+            *c = '\0';
+        }
+    }
+  if ((c = strchr (buf, '\\')) != NULL)
+    {
+      *c++ = '\0';
+      strcpy (domain, buf);
+      strcpy (user, c);
+    }
+  else
+    {
+      strcpy (domain, "");
+      strcpy (user, buf);
+    }
+}
+
 PUSER_INFO_3
 GetPW (const char *user)
 {
   WCHAR name[512];
   DWORD ret;
   PUSER_INFO_3 ui;
-
+  struct passwd *pw;
+  char *domain = (char *) malloc (MAX_PATH + 1);
+    
   MultiByteToWideChar (CP_ACP, 0, user, -1, name, 512);
   ret = NetUserGetInfo (NULL, name, 3, (LPBYTE *) &ui);
+  /* Try getting a Win32 username in case the user edited /etc/passwd */
+  if (ret == NERR_UserNotFound)
+  {
+    if ((pw = getpwnam (user)))
+      extract_nt_dom_user (pw, domain, (char *) user);
+    MultiByteToWideChar (CP_ACP, 0, user, -1, name, 512);
+    ret = NetUserGetInfo (NULL, name, 3, (LPBYTE *) &ui);
+    if (ret == (int) NULL)
+      printf ("Windows username : %s\n", user);
+  }
+
   return EvalRet (ret, user) ? NULL : ui;
 }
 


More information about the Cygwin-patches mailing list