OSDN Git Service

* Makefile.in (OBJS): Add setpwd.o.
authorcorinna <corinna>
Wed, 26 Nov 2008 10:18:52 +0000 (10:18 +0000)
committercorinna <corinna>
Wed, 26 Nov 2008 10:18:52 +0000 (10:18 +0000)
* README: Explain new service to store passwords in the LSA registry
area.
* bsd_helper.cc (get_token_info): Make externally available.
* bsd_helper.h (get_token_info): Declare.
* client.cc (client_request::handle_request): Add case for
CYGSERVER_REQUEST_SETPWD request.
* setpwd.cc: New file implementing the CYGSERVER_REQUEST_SETPWD
request.

winsup/cygserver/ChangeLog
winsup/cygserver/Makefile.in
winsup/cygserver/README
winsup/cygserver/bsd_helper.cc
winsup/cygserver/bsd_helper.h
winsup/cygserver/client.cc
winsup/cygserver/setpwd.cc [new file with mode: 0644]

index c3d4870..0ba9e46 100644 (file)
@@ -1,3 +1,15 @@
+2008-11-26  Corinna Vinschen  <corinna@vinschen.de>
+
+       * Makefile.in (OBJS): Add setpwd.o.
+       * README: Explain new service to store passwords in the LSA registry
+       area.
+       * bsd_helper.cc (get_token_info): Make externally available.
+       * bsd_helper.h (get_token_info): Declare.
+       * client.cc (client_request::handle_request): Add case for
+       CYGSERVER_REQUEST_SETPWD request.
+       * setpwd.cc: New file implementing the CYGSERVER_REQUEST_SETPWD
+       request.
+
 2008-10-30  Christopher Faylor  <me+cygwin@cgf.cx>
 
        * Makefile.in: Use -static-libgcc when creating cygserver.exe.
index dd8ad96..4192bda 100644 (file)
@@ -41,7 +41,7 @@ override CXXFLAGS+=-MMD -DHAVE_DECL_GETOPT=0 -D__OUTSIDE_CYGWIN__ -DSYSCONFDIR="
 OBJS:= cygserver.o client.o process.o msg.o sem.o shm.o threaded_queue.o \
        transport.o transport_pipes.o \
        bsd_helper.o bsd_log.o bsd_mutex.o \
-       sysv_msg.o sysv_sem.o sysv_shm.o
+       sysv_msg.o sysv_sem.o sysv_shm.o setpwd.o
 LIBOBJS:=${patsubst %.o,lib%.o,$(OBJS)}
 
 CYGWIN_OBJS:=$(cygwin_build)/version.o
index 279e513..0136550 100644 (file)
@@ -12,6 +12,12 @@ What is Cygserver?
   - XSI IPC Message Queues.
   - XSI IPC Semaphores.
   - XSI IPC Shared Memory.
+  - Allows non-privileged users to store obfuscated passwords in the
+    registry to be used for setuid(2) to create user tokens with network
+    credentials.  This service is used by `passwd -R'.  Using the stored
+    passwords in setuid(2) does not require running cygserver.  The
+    registry storage is the same as Windows uses to store passwords for
+    accounts running Windows services.
 
 
 Cygserver command line options:
index a137b7e..6dabdc8 100644 (file)
@@ -308,7 +308,7 @@ is_grp_member (gid_t grp, gid_t *grplist, int listsize)
  * This function mallocs the necessary buffer spcae by itself.  It
  * must be free'd by the calling function.
  */
-static void *
+void *
 get_token_info (HANDLE tok, TOKEN_INFORMATION_CLASS tic)
 {
   void *buf;
index 014b82a..0458985 100644 (file)
@@ -44,6 +44,7 @@ int win_copyout (struct thread *, const void *, void *, size_t);
 #define copyin(a,b,c) win_copyin((td),(a),(b),(c))
 #define copyout(a,b,c) win_copyout((td),(a),(b),(c))
 
+void *get_token_info (HANDLE, TOKEN_INFORMATION_CLASS);
 int ipcperm (struct thread *, struct ipc_perm *, unsigned int);
 int suser (struct thread *);
 bool adjust_identity_info (struct proc *p);
index 953e5a1..f66a995 100644 (file)
@@ -27,6 +27,7 @@ details. */
 #include "cygserver_msg.h"
 #include "cygserver_sem.h"
 #include "cygserver_shm.h"
+#include "cygserver_setpwd.h"
 
 #include "cygserver.h"
 #include "transport.h"
@@ -293,6 +294,9 @@ client_request::handle_request (transport_layer_base *const conn,
     case CYGSERVER_REQUEST_SHM:
       req = new client_request_shm;
       break;
+    case CYGSERVER_REQUEST_SETPWD:
+      req = new client_request_setpwd;
+      break;
     default:
       syscall_printf ("unknown request code %d received: request ignored",
                      header.request_code);
diff --git a/winsup/cygserver/setpwd.cc b/winsup/cygserver/setpwd.cc
new file mode 100644 (file)
index 0000000..39989f8
--- /dev/null
@@ -0,0 +1,100 @@
+/* setpwd.cc: Set LSA private data password for current user.
+
+   Copyright 2008 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. */
+
+#ifdef __OUTSIDE_CYGWIN__
+#include "woutsup.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <wchar.h>
+
+#include <ntsecapi.h>
+#include <ntdef.h>
+#include "ntdll.h"
+
+#include "cygserver.h"
+#include "process.h"
+#include "transport.h"
+
+#include "cygserver_setpwd.h"
+
+client_request_setpwd::client_request_setpwd ()
+  : client_request (CYGSERVER_REQUEST_SETPWD,
+                   &_parameters, sizeof (_parameters))
+{ 
+}
+
+void
+client_request_setpwd::serve (transport_layer_base *const conn,
+                             process_cache *const cache)
+{
+  HANDLE tok;
+  PTOKEN_USER user;
+  WCHAR sidbuf[128], key_name [128 + wcslen (CYGWIN_LSA_KEY_PREFIX)];
+  UNICODE_STRING sid, key, data;
+
+  syscall_printf ("Request to set private data");
+  if (msglen () != sizeof (_parameters.in))
+    {
+      syscall_printf ("bad request body length: expecting %lu bytes, got %lu",
+                     sizeof (_parameters), msglen ());
+      error_code (EINVAL);
+      msglen (0);
+      return;
+    }
+  msglen (0);
+  if (!conn->impersonate_client ())
+    {
+      error_code (EACCES);
+      return;
+    }
+  if (!OpenThreadToken (GetCurrentThread (), TOKEN_READ, TRUE, &tok))
+    {
+      conn->revert_to_self ();
+      error_code (EACCES);
+      return;
+    }
+  /* Get uid from user SID in token. */
+  user = (PTOKEN_USER) get_token_info (tok, TokenUser);
+  CloseHandle (tok);
+  conn->revert_to_self ();
+  if (!user)
+    {
+      error_code (EACCES);
+      return;
+    }
+  LSA_OBJECT_ATTRIBUTES oa = { 0, 0, 0, 0, 0, 0 };
+  HANDLE lsa;
+  NTSTATUS status = LsaOpenPolicy (NULL, &oa, POLICY_CREATE_SECRET, &lsa);
+  if (!NT_SUCCESS (status))
+    {
+      error_code (LsaNtStatusToWinError (status));
+      return;
+    }
+  RtlInitEmptyUnicodeString (&sid, sidbuf, sizeof sidbuf);
+  RtlConvertSidToUnicodeString (&sid, user->User.Sid, FALSE);
+  free (user);
+  RtlInitEmptyUnicodeString (&key, key_name, sizeof key_name);
+  RtlAppendUnicodeToString (&key, CYGWIN_LSA_KEY_PREFIX);
+  RtlAppendUnicodeStringToString (&key, &sid);
+  RtlInitUnicodeString (&data, _parameters.in.passwd);
+  status = LsaStorePrivateData (lsa, &key, data.Length ? &data : NULL);
+  if (NT_SUCCESS (status))
+    error_code (0);
+  else
+    error_code (LsaNtStatusToWinError (status));
+  syscall_printf ("Request to set private data returns error %d", error_code ());
+  LsaClose (lsa);
+}
+#endif /* __OUTSIDE_CYGWIN__ */