OSDN Git Service

Initial checkin of text Corinna sent to cygwin-announce.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / uinfo.cc
index 8a4b86d..ee90e52 100644 (file)
@@ -1,7 +1,7 @@
 /* uinfo.cc: user info (uid, gid, etc...)
 
    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007, 2008 Red Hat, Inc.
+   2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
 
 This file is part of Cygwin.
 
@@ -13,7 +13,9 @@ details. */
 #include <unistd.h>
 #include <wininet.h>
 #include <stdlib.h>
+#include <wchar.h>
 #include <lm.h>
+#include <iptypes.h>
 #include <sys/cygwin.h>
 #include "cygerrno.h"
 #include "pinfo.h"
@@ -21,6 +23,7 @@ details. */
 #include "fhandler.h"
 #include "dtable.h"
 #include "cygheap.h"
+#include "shared_info.h"
 #include "registry.h"
 #include "child_info.h"
 #include "environ.h"
@@ -34,49 +37,72 @@ details. */
 void
 cygheap_user::init ()
 {
-  char user_name[UNLEN + 1];
+  WCHAR user_name[UNLEN + 1];
   DWORD user_name_len = UNLEN + 1;
 
-  set_name (GetUserName (user_name, &user_name_len) ? user_name : "unknown");
+  /* This code is only run if a Cygwin process gets started by a native
+     Win32 process.  We try to get the username from the environment,
+     first USERNAME (Win32), then USER (POSIX).  If that fails (which is
+     very unlikely), it only has an impact if we don't have an entry in
+     /etc/passwd for this user either.  In that case the username sticks
+     to "unknown".  Since this is called early in initialization, and
+     since we don't want pull in a dependency to any other DLL except
+     ntdll and kernel32 at this early stage, don't call GetUserName,
+     GetUserNameEx, NetWkstaUserGetInfo, etc. */
+  if (GetEnvironmentVariableW (L"USERNAME", user_name, user_name_len)
+      || GetEnvironmentVariableW (L"USER", user_name, user_name_len))
+    {
+      char mb_user_name[user_name_len = sys_wcstombs (NULL, 0, user_name)];
+      sys_wcstombs (mb_user_name, user_name_len, user_name);
+      set_name (mb_user_name);
+    }
+  else
+    set_name ("unknown");
 
-  DWORD siz;
+  NTSTATUS status;
+  ULONG size;
   PSECURITY_DESCRIPTOR psd;
 
-  if (!GetTokenInformation (hProcToken, TokenPrimaryGroup,
-                           &groups.pgsid, sizeof (cygsid), &siz))
-    system_printf ("GetTokenInformation (TokenPrimaryGroup), %E");
+  status = NtQueryInformationToken (hProcToken, TokenPrimaryGroup,
+                                   &groups.pgsid, sizeof (cygsid), &size);
+  if (!NT_SUCCESS (status))
+    system_printf ("NtQueryInformationToken (TokenPrimaryGroup), %p", status);
 
   /* Get the SID from current process and store it in effec_cygsid */
-  if (!GetTokenInformation (hProcToken, TokenUser, &effec_cygsid,
-                           sizeof (cygsid), &siz))
+  status = NtQueryInformationToken (hProcToken, TokenUser, &effec_cygsid,
+                                   sizeof (cygsid), &size);
+  if (!NT_SUCCESS (status))
     {
-      system_printf ("GetTokenInformation (TokenUser), %E");
+      system_printf ("NtQueryInformationToken (TokenUser), %p", status);
       return;
     }
 
   /* Set token owner to the same value as token user */
-  if (!SetTokenInformation (hProcToken, TokenOwner, &effec_cygsid,
-                           sizeof (cygsid)))
-    debug_printf ("SetTokenInformation(TokenOwner), %E");
+  status = NtSetInformationToken (hProcToken, TokenOwner, &effec_cygsid,
+                                 sizeof (cygsid));
+  if (!NT_SUCCESS (status))
+    debug_printf ("NtSetInformationToken(TokenOwner), %p", status);
 
   /* Standard way to build a security descriptor with the usual DACL */
   PSECURITY_ATTRIBUTES sa_buf = (PSECURITY_ATTRIBUTES) alloca (1024);
   psd = (PSECURITY_DESCRIPTOR)
-               (sec_user_nih (sa_buf, sid()))->lpSecurityDescriptor;
+               (sec_user_nih (sa_buf, sid()))->lpSecurityDescriptor;
 
-  BOOL acl_exists, dummy;
+  BOOLEAN acl_exists, dummy;
   TOKEN_DEFAULT_DACL dacl;
-  if (GetSecurityDescriptorDacl (psd, &acl_exists, &dacl.DefaultDacl, &dummy)
-      && acl_exists && dacl.DefaultDacl)
+
+  status = RtlGetDaclSecurityDescriptor (psd, &acl_exists, &dacl.DefaultDacl,
+                                        &dummy);
+  if (NT_SUCCESS (status) && acl_exists && dacl.DefaultDacl)
     {
-      NTSTATUS status;
 
       /* Set the default DACL and the process DACL */
-      if (!SetTokenInformation (hProcToken, TokenDefaultDacl, &dacl,
-                               sizeof (dacl)))
-       system_printf ("SetTokenInformation (TokenDefaultDacl), %E");
-      if ((status = NtSetSecurityObject (hMainProc, DACL_SECURITY_INFORMATION,
-                                        psd)))
+      status = NtSetInformationToken (hProcToken, TokenDefaultDacl, &dacl,
+                                     sizeof (dacl));
+      if (!NT_SUCCESS (status))
+       system_printf ("NtSetInformationToken (TokenDefaultDacl), %p", status);
+      if ((status = NtSetSecurityObject (NtCurrentProcess (),
+                                        DACL_SECURITY_INFORMATION, psd)))
        system_printf ("NtSetSecurityObject, %lx", status);
     }
   else
@@ -106,9 +132,12 @@ internal_getlogin (cygheap_user &user)
          if (gsid != user.groups.pgsid)
            {
              /* Set primary group to the group in /etc/passwd. */
-             if (!SetTokenInformation (hProcToken, TokenPrimaryGroup,
-                                       &gsid, sizeof gsid))
-               debug_printf ("SetTokenInformation(TokenPrimaryGroup), %E");
+             NTSTATUS status = NtSetInformationToken (hProcToken,
+                                                      TokenPrimaryGroup,
+                                                      &gsid, sizeof gsid);
+             if (!NT_SUCCESS (status))
+               debug_printf ("NtSetInformationToken (TokenPrimaryGroup), %p",
+                             status);
              else
                user.groups.pgsid = gsid;
              clear_procimptoken ();
@@ -133,7 +162,8 @@ uinfo_init ()
   else if (cygheap->user.issetuid ()
           && cygheap->user.saved_uid == cygheap->user.real_uid
           && cygheap->user.saved_gid == cygheap->user.real_gid
-          && !cygheap->user.groups.issetgroups ())
+          && !cygheap->user.groups.issetgroups ()
+          && !cygheap->user.setuid_to_restricted)
     {
       cygheap->user.reimpersonate ();
       return;
@@ -147,14 +177,17 @@ uinfo_init ()
   cygheap->user.internal_token = NO_IMPERSONATION;
   cygheap->user.curr_primary_token = NO_IMPERSONATION;
   cygheap->user.curr_imp_token = NO_IMPERSONATION;
+  cygheap->user.ext_token_is_restricted = false;
+  cygheap->user.curr_token_is_restricted = false;
+  cygheap->user.setuid_to_restricted = false;
   cygheap->user.set_saved_sid ();      /* Update the original sid */
-  cygheap->user.reimpersonate ();
+  cygheap->user.deimpersonate ();
 }
 
 extern "C" int
 getlogin_r (char *name, size_t namesize)
 {
-  char *login = getlogin ();
+  const char *login = cygheap->user.name ();
   size_t len = strlen (login) + 1;
   if (len > namesize)
     return ERANGE;
@@ -168,7 +201,14 @@ getlogin_r (char *name, size_t namesize)
 extern "C" char *
 getlogin (void)
 {
-  return strcpy (_my_tls.locals.username, cygheap->user.name ());
+  static char username[UNLEN];
+  int ret = getlogin_r (username, UNLEN);
+  if (ret)
+    {
+      set_errno (ret);
+      return NULL;
+    }
+  return username;
 }
 
 extern "C" __uid32_t
@@ -245,15 +285,6 @@ cygheap_user::ontherange (homebodies what, struct passwd *pw)
   if (what == CH_HOME)
     {
       char *p;
-      if (homedrive)
-       newhomedrive = homedrive;
-      else if ((p = getenv ("HOMEDRIVE")))
-       newhomedrive = p;
-
-      if (homepath)
-       newhomepath = homepath;
-      else if ((p = getenv ("HOMEPATH")))
-       newhomepath = p;
 
       if ((p = getenv ("HOME")))
        debug_printf ("HOME is already in the environment %s", p);
@@ -264,17 +295,12 @@ cygheap_user::ontherange (homebodies what, struct passwd *pw)
              debug_printf ("Set HOME (from /etc/passwd) to %s", pw->pw_dir);
              setenv ("HOME", pw->pw_dir, 1);
            }
-         else if (!newhomedrive || !newhomepath)
-           setenv ("HOME", "/", 1);
          else
            {
-             char *home = tp.c_get ();
-             char *buf = tp.c_get ();
-             strcpy (buf, newhomedrive);
-             strcat (buf, newhomepath);
-             cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, buf, home,
-                               NT_MAX_PATH);
-             debug_printf ("Set HOME (from HOMEDRIVE/HOMEPATH) to %s", home);
+             char home[strlen (name ()) + 8];
+
+             debug_printf ("Set HOME to default /home/USER");
+             __small_sprintf (home, "/home/%s", name ());
              setenv ("HOME", home, 1);
            }
        }
@@ -300,7 +326,7 @@ cygheap_user::ontherange (homebodies what, struct passwd *pw)
              if (!(ret = NetUserGetInfo (wlogsrv, wuser, 3, (LPBYTE *) &ui)))
                {
                  sys_wcstombs (homepath_env_buf, NT_MAX_PATH,
-                               ui->usri3_home_dir);
+                               ui->usri3_home_dir);
                  if (!homepath_env_buf[0])
                    {
                      sys_wcstombs (homepath_env_buf, NT_MAX_PATH,
@@ -369,9 +395,9 @@ cygheap_user::env_logsrv (const char *name, size_t namelen)
   if (!mydomain || ascii_strcasematch (myname, "SYSTEM"))
     return almost_null;
 
-  WCHAR wdomain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+  WCHAR wdomain[MAX_DOMAIN_NAME_LEN + 1];
   WCHAR wlogsrv[INTERNET_MAX_HOST_NAME_LENGTH + 3];
-  sys_mbstowcs (wdomain, INTERNET_MAX_HOST_NAME_LENGTH + 1, mydomain);
+  sys_mbstowcs (wdomain, MAX_DOMAIN_NAME_LEN + 1, mydomain);
   cfree_and_set (plogsrv, almost_null);
   if (get_logon_server (wdomain, wlogsrv, false))
     sys_wcstombs_alloc (&plogsrv, HEAP_STR, wlogsrv);
@@ -384,21 +410,21 @@ cygheap_user::env_domain (const char *name, size_t namelen)
   if (pwinname && test_uid (pdomain, name, namelen))
     return pdomain;
 
-  char username[UNLEN + 1];
-  DWORD ulen = sizeof (username);
-  char userdomain[DNLEN + 1];
-  DWORD dlen = sizeof (userdomain);
+  DWORD ulen = UNLEN + 1;
+  WCHAR username[ulen];
+  DWORD dlen = MAX_DOMAIN_NAME_LEN + 1;
+  WCHAR userdomain[dlen];
   SID_NAME_USE use;
 
   cfree_and_set (pwinname, almost_null);
   cfree_and_set (pdomain, almost_null);
-  if (!LookupAccountSid (NULL, sid (), username, &ulen,
-                        userdomain, &dlen, &use))
+  if (!LookupAccountSidW (NULL, sid (), username, &ulen,
+                         userdomain, &dlen, &use))
     __seterrno ();
   else
     {
-      pwinname = cstrdup (username);
-      pdomain = cstrdup (userdomain);
+      sys_wcstombs_alloc (&pwinname, HEAP_STR, username);
+      sys_wcstombs_alloc (&pdomain, HEAP_STR, userdomain);
     }
   return pdomain;
 }
@@ -444,19 +470,16 @@ cygheap_user::env_systemroot (const char *name, size_t namelen)
 {
   if (!psystemroot)
     {
-      int size = GetWindowsDirectory (NULL, 0);
+      int size = GetSystemWindowsDirectoryW (NULL, 0);
       if (size > 0)
        {
-         psystemroot = (char *) cmalloc_abort (HEAP_STR, ++size);
-         size = GetWindowsDirectory (psystemroot, size);
-         if (size <= 0)
-           {
-             cfree (psystemroot);
-             psystemroot = NULL;
-           }
+         WCHAR wsystemroot[size];
+         size = GetSystemWindowsDirectoryW (wsystemroot, size);
+         if (size > 0)
+           sys_wcstombs_alloc (&psystemroot, HEAP_STR, wsystemroot);
        }
       if (size <= 0)
-       debug_printf ("GetWindowsDirectory(), %E");
+       debug_printf ("GetSystemWindowsDirectoryW(), %E");
     }
   return psystemroot;
 }
@@ -507,13 +530,12 @@ pwdgrp::add_line (char *eptr)
 }
 
 void
-pwdgrp::load (const char *posix_fname)
+pwdgrp::load (const wchar_t *rel_path)
 {
   static const char failed[] = "failed";
   static const char succeeded[] = "succeeded";
   const char *res = failed;
   HANDLE fh = NULL;
-  LARGE_INTEGER off = { QuadPart:0LL };
 
   NTSTATUS status;
   OBJECT_ATTRIBUTES attr;
@@ -525,23 +547,28 @@ pwdgrp::load (const char *posix_fname)
   buf = NULL;
   curr_lines = 0;
 
-  pc.check (posix_fname);
-  etc_ix = etc::init (etc_ix, pc.get_nt_native_path ());
-
-  paranoid_printf ("%s", posix_fname);
-
-  if (pc.error || !pc.exists () || pc.isdir ())
+  if (!path &&
+      !(path = (PWCHAR) malloc ((wcslen (installation_root)
+                                + wcslen (rel_path) + 1) * sizeof (WCHAR))))
     {
-      paranoid_printf ("strange path_conv problem");
+      paranoid_printf ("malloc (%W) failed", rel_path);
       goto out;
     }
-  status = NtOpenFile (&fh, FILE_READ_DATA,
-                      pc.get_object_attr (attr, sec_none_nih), &io,
-                      FILE_SHARE_VALID_FLAGS, 0);
+  wcpcpy (wcpcpy (path, installation_root), rel_path);
+  RtlInitUnicodeString (&upath, path);
+
+  InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
+  etc_ix = etc::init (etc_ix, &attr);
+
+  paranoid_printf ("%S", &upath);
+
+  status = NtOpenFile (&fh, SYNCHRONIZE | FILE_READ_DATA, &attr, &io,
+                      FILE_SHARE_VALID_FLAGS,
+                      FILE_SYNCHRONOUS_IO_NONALERT
+                      | FILE_OPEN_FOR_BACKUP_INTENT);
   if (!NT_SUCCESS (status))
     {
-      paranoid_printf ("NtOpenFile(%S) failed, status %p",
-                       pc.get_nt_native_path (), status);
+      paranoid_printf ("NtOpenFile(%S) failed, status %p", &upath, status);
       goto out;
     }
   status = NtQueryInformationFile (fh, &io, &fsi, sizeof fsi,
@@ -549,7 +576,7 @@ pwdgrp::load (const char *posix_fname)
   if (!NT_SUCCESS (status))
     {
       paranoid_printf ("NtQueryInformationFile(%S) failed, status %p",
-                      pc.get_nt_native_path (), status);
+                      &upath, status);
       goto out;
     }
   /* FIXME: Should we test for HighPart set?  If so, the
@@ -562,25 +589,23 @@ pwdgrp::load (const char *posix_fname)
       paranoid_printf ("malloc (%d) failed", fsi.EndOfFile.LowPart);
       goto out;
     }
-  status = NtReadFile (fh, NULL, NULL, NULL, &io, buf,
-                      fsi.EndOfFile.LowPart, &off, NULL);
+  status = NtReadFile (fh, NULL, NULL, NULL, &io, buf, fsi.EndOfFile.LowPart,
+                      NULL, NULL);
   if (!NT_SUCCESS (status))
     {
-      paranoid_printf ("NtReadFile(%S) failed, status %p",
-                      pc.get_nt_native_path (), status);
+      paranoid_printf ("NtReadFile(%S) failed, status %p", &upath, status);
       free (buf);
       goto out;
     }
   buf[fsi.EndOfFile.LowPart] = '\0';
-  char *eptr = buf;
-  while ((eptr = add_line (eptr)))
+  for (char *eptr = buf; (eptr = add_line (eptr)); )
     continue;
-  debug_printf ("%s curr_lines %d", posix_fname, curr_lines);
+  debug_printf ("%W curr_lines %d", rel_path, curr_lines);
   res = succeeded;
 
 out:
   if (fh)
     NtClose (fh);
-  debug_printf ("%s load %s", posix_fname, res);
+  debug_printf ("%W load %s", rel_path, res);
   initialized = true;
 }