summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/setlsapwd.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/setlsapwd.cc')
-rw-r--r--winsup/cygwin/setlsapwd.cc90
1 files changed, 90 insertions, 0 deletions
diff --git a/winsup/cygwin/setlsapwd.cc b/winsup/cygwin/setlsapwd.cc
new file mode 100644
index 000000000..34284afd3
--- /dev/null
+++ b/winsup/cygwin/setlsapwd.cc
@@ -0,0 +1,90 @@
+/* setlsapwd.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. */
+
+#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>
+
+#ifdef USE_SERVER
+/*
+ * 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));
+}
+
+#endif /* USE_SERVER */
+
+unsigned long
+setlsapwd (const char *passwd)
+{
+ 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;
+
+ 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))
+ {
+ NTSTATUS status = STATUS_ACCESS_DENIED;
+
+ 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)
+ {
+ status = LsaStorePrivateData (lsa, &key, data.Length ? &data : NULL);
+ if (NT_SUCCESS (status))
+ ret = 0;
+ LsaClose (lsa);
+ }
+ if (ret)
+#ifdef USE_SERVER
+ {
+ /* If that fails, ask cygserver. */
+ client_request_setpwd request (&data);
+ if (request.make_request () == -1 || request.error_code ())
+ set_errno (request.error_code ());
+ else
+ ret = 0;
+ }
+#else
+ __seterrno_from_nt_status (status);
+#endif
+ if (data_buf)
+ free (data_buf);
+ }
+ return ret;
+}