/* Copyright (C) 2012 Red Hat, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see . */ #include "config.h" #include "win32-util.h" #include #include #include gboolean spice_win32_set_low_integrity (void* handle, GError **error) { g_return_val_if_fail (handle != NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); /* see also http://msdn.microsoft.com/en-us/library/bb625960.aspx */ PSECURITY_DESCRIPTOR psd = NULL; PACL psacl = NULL; BOOL sacl_present = FALSE; BOOL sacl_defaulted = FALSE; char *emsg; int errsv; gboolean success = FALSE; if (!ConvertStringSecurityDescriptorToSecurityDescriptor ("S:(ML;;NW;;;LW)", SDDL_REVISION_1, &psd, NULL)) goto failed; if (!GetSecurityDescriptorSacl (psd, &sacl_present, &psacl, &sacl_defaulted)) goto failed; if (SetSecurityInfo (handle, SE_KERNEL_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, psacl) != ERROR_SUCCESS) goto failed; success = TRUE; goto end; failed: errsv = GetLastError (); emsg = g_win32_error_message (errsv); g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (errsv), "Error setting integrity: %s", emsg); g_free (emsg); end: if (psd != NULL) LocalFree (psd); return success; } static gboolean get_user_security_attributes (SECURITY_ATTRIBUTES* psa, SECURITY_DESCRIPTOR* psd, PACL* ppdacl) { EXPLICIT_ACCESS ea; TRUSTEE trst; DWORD ret = 0; ZeroMemory (psa, sizeof (*psa)); ZeroMemory (psd, sizeof (*psd)); psa->nLength = sizeof (*psa); psa->bInheritHandle = FALSE; psa->lpSecurityDescriptor = psd; ZeroMemory (&trst, sizeof (trst)); trst.pMultipleTrustee = NULL; trst.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; trst.TrusteeForm = TRUSTEE_IS_NAME; trst.TrusteeType = TRUSTEE_IS_USER; trst.ptstrName = "CURRENT_USER"; ZeroMemory (&ea, sizeof (ea)); ea.grfAccessPermissions = GENERIC_WRITE | GENERIC_READ; ea.grfAccessMode = SET_ACCESS; ea.grfInheritance = NO_INHERITANCE; ea.Trustee = trst; ret = SetEntriesInAcl (1, &ea, NULL, ppdacl); if (ret != ERROR_SUCCESS) return FALSE; if (!InitializeSecurityDescriptor (psd, SECURITY_DESCRIPTOR_REVISION)) return FALSE; if (!SetSecurityDescriptorDacl (psd, TRUE, *ppdacl, FALSE)) return FALSE; return TRUE; } #define DEFAULT_PIPE_BUF_SIZE 4096 SpiceNamedPipe* spice_win32_user_pipe_new (gchar *name, GError **error) { SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; PACL dacl = NULL; HANDLE pipe; SpiceNamedPipe *np = NULL; g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (error != NULL, NULL); if (!get_user_security_attributes (&sa, &sd, &dacl)) return NULL; pipe = CreateNamedPipe (name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | /* FIXME: why is FILE_FLAG_FIRST_PIPE_INSTANCE needed for WRITE_DAC * (apparently needed by SetSecurityInfo). This will prevent * multiple pipe listener....?! */ FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, DEFAULT_PIPE_BUF_SIZE, DEFAULT_PIPE_BUF_SIZE, 0, &sa); if (pipe == INVALID_HANDLE_VALUE) { int errsv = GetLastError (); gchar *emsg = g_win32_error_message (errsv); g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (errsv), "Error CreateNamedPipe(): %s", emsg); g_free (emsg); goto end; } /* lower integrity on Vista/Win7+ */ if ((LOBYTE (g_win32_get_windows_version()) > 0x05) && !spice_win32_set_low_integrity (pipe, error)) goto end; np = SPICE_NAMED_PIPE (g_initable_new (SPICE_TYPE_NAMED_PIPE, NULL, error, "handle", pipe, NULL)); end: LocalFree (dacl); return np; }