* external.cc (cygwin_internal): In the CW_SET_PRIV_KEY case, fetch additional username parameter. * setlsapwd.cc (setlsapwd): Add username parameter. Allow admin to set the hidden password for other users.
		
			
				
	
	
		
			104 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* setlsapwd.cc: Set LSA private data password for current user.
 | |
| 
 | |
|    Copyright 2008, 2009, 2011 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. */
 | |
| 
 | |
| #include "winsup.h"
 | |
| #include "shared_info.h"
 | |
| #include "cygerrno.h"
 | |
| #include "path.h"
 | |
| #include "fhandler.h"
 | |
| #include "dtable.h"
 | |
| #include "cygheap.h"
 | |
| #include "security.h"
 | |
| #include "cygserver_setpwd.h"
 | |
| #include "pwdgrp.h"
 | |
| #include "ntdll.h"
 | |
| #include <ntsecapi.h>
 | |
| #include <stdlib.h>
 | |
| #include <wchar.h>
 | |
| 
 | |
| /*
 | |
|  * client_request_setpwd Constructor
 | |
|  */
 | |
| 
 | |
| client_request_setpwd::client_request_setpwd (PUNICODE_STRING passwd)
 | |
|   : client_request (CYGSERVER_REQUEST_SETPWD, &_parameters, sizeof (_parameters))
 | |
| {
 | |
|   memset (_parameters.in.passwd, 0, sizeof _parameters.in.passwd);
 | |
|   if (passwd->Length > 0 && passwd->Length < 256 * sizeof (WCHAR))
 | |
|     wcpncpy (_parameters.in.passwd, passwd->Buffer, 255);
 | |
| 
 | |
|   msglen (sizeof (_parameters.in));
 | |
| }
 | |
| 
 | |
| unsigned long
 | |
| setlsapwd (const char *passwd, const char *username)
 | |
| {
 | |
|   unsigned long ret = (unsigned long) -1;
 | |
|   HANDLE lsa = INVALID_HANDLE_VALUE;
 | |
|   WCHAR sid[128];
 | |
|   WCHAR key_name[128 + wcslen (CYGWIN_LSA_KEY_PREFIX)];
 | |
|   PWCHAR data_buf = NULL;
 | |
|   UNICODE_STRING key;
 | |
|   UNICODE_STRING data;
 | |
| 
 | |
|   if (username)
 | |
|     {
 | |
|       cygsid psid;
 | |
|       struct passwd *pw = internal_getpwnam (username, false);
 | |
| 
 | |
|       if (!pw || !psid.getfrompw (pw))
 | |
| 	{
 | |
| 	  set_errno (ENOENT);
 | |
| 	  return ret;
 | |
| 	}
 | |
|       wcpcpy (wcpcpy (key_name, CYGWIN_LSA_KEY_PREFIX), psid.string (sid));
 | |
|     }
 | |
|   else
 | |
|     wcpcpy (wcpcpy (key_name, CYGWIN_LSA_KEY_PREFIX),
 | |
| 	    cygheap->user.get_windows_id (sid));
 | |
|   RtlInitUnicodeString (&key, key_name);
 | |
|   if (!passwd || ! *passwd
 | |
|       || sys_mbstowcs_alloc (&data_buf, HEAP_NOTHEAP, passwd))
 | |
|     {
 | |
|       memset (&data, 0, sizeof data);
 | |
|       if (data_buf)
 | |
| 	RtlInitUnicodeString (&data, data_buf);
 | |
|       /* First try it locally.  Works for admin accounts. */
 | |
|       if ((lsa = open_local_policy (POLICY_CREATE_SECRET))
 | |
| 	  != INVALID_HANDLE_VALUE)
 | |
| 	{
 | |
| 	  NTSTATUS status = LsaStorePrivateData (lsa, &key,
 | |
| 						 data.Length ? &data : NULL);
 | |
| 	  /* Success or we're trying to remove a password entry which doesn't
 | |
| 	     exist. */
 | |
| 	  if (NT_SUCCESS (status)
 | |
| 	      || (data.Length == 0 && status == STATUS_OBJECT_NAME_NOT_FOUND))
 | |
| 	    ret = 0;
 | |
| 	  else
 | |
| 	    __seterrno_from_nt_status (status);
 | |
| 	  LsaClose (lsa);
 | |
| 	}
 | |
|       else if (ret && !username)
 | |
| 	{
 | |
| 	  client_request_setpwd request (&data);
 | |
| 	  if (request.make_request () == -1 || request.error_code ())
 | |
| 	    set_errno (request.error_code ());
 | |
| 	  else
 | |
| 	    ret = 0;
 | |
| 	}
 | |
|       if (data_buf)
 | |
| 	{
 | |
| 	  memset (data.Buffer, 0, data.Length);
 | |
| 	  free (data_buf);
 | |
| 	}
 | |
|     }
 | |
|   return ret;
 | |
| }
 |