99 lines
2.6 KiB
C++
99 lines
2.6 KiB
C++
/* setlsapwd.cc: Set LSA private data password for current user.
|
|
|
|
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 "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;
|
|
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);
|
|
|
|
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 = lsa_open_policy (NULL, POLICY_CREATE_SECRET)))
|
|
{
|
|
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);
|
|
lsa_close_policy (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)
|
|
{
|
|
RtlSecureZeroMemory (data.Buffer, data.Length);
|
|
free (data_buf);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|