newlib/winsup/cygserver/setpwd.cc
Corinna Vinschen d4db08d7a6 * 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-11-26 10:18:53 +00:00

101 lines
2.6 KiB
C++

/* 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__ */