mirror of
https://github.com/openvswitch/ovs
synced 2025-10-19 14:37:21 +00:00
Bump the security around named pipes to be more restrictive: disable network access and allow only administrators and above to access the named pipes. Acked-by: Anand Kumar <kumaranand@vmware.com> Acked-by: Alin Gabriel Serdean <aserdean@ovn.org> Signed-off-by: Alin Balutoiu <abalutoiu@cloudbasesolutions.com> Signed-off-by: Alin Gabriel Serdean <aserdean@ovn.org>
267 lines
9.0 KiB
Python
267 lines
9.0 KiB
Python
# Copyright (c) 2016 Cloudbase Solutions Srl
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at:
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import sys
|
|
|
|
if sys.platform != 'win32':
|
|
raise Exception("Intended to use only on Windows")
|
|
else:
|
|
import ntsecuritycon
|
|
import pywintypes
|
|
import win32con
|
|
import win32event
|
|
import win32file
|
|
import win32pipe
|
|
import win32security
|
|
import winerror
|
|
|
|
|
|
def close_handle(handle, logger=None):
|
|
try:
|
|
win32file.CloseHandle(handle)
|
|
return None
|
|
except pywintypes.error as e:
|
|
if logger is not None:
|
|
logger("failed to close handle: %s" % e.strerror)
|
|
return e.winerror
|
|
|
|
|
|
def windows_create_pipe(sAttrs=-1, nSize=None):
|
|
# Default values if parameters are not passed
|
|
if sAttrs == -1:
|
|
sAttrs = win32security.SECURITY_ATTRIBUTES()
|
|
sAttrs.bInheritHandle = 1
|
|
if nSize is None:
|
|
# If this parameter is zero, the system uses the default buffer size.
|
|
nSize = 0
|
|
|
|
try:
|
|
(read_pipe, write_pipe) = win32pipe.CreatePipe(sAttrs, nSize)
|
|
except pywintypes.error:
|
|
raise
|
|
|
|
return (read_pipe, write_pipe)
|
|
|
|
|
|
def windows_read_pipe(fd, length):
|
|
try:
|
|
(error, data) = win32file.ReadFile(fd, length)
|
|
return error, data
|
|
except pywintypes.error as e:
|
|
return e.winerror, ""
|
|
|
|
|
|
def create_file(filename, desiredAccess=None, shareMode=None, attributes=-1,
|
|
CreationDisposition=None, flagsAndAttributes=None,
|
|
hTemplateFile=-1):
|
|
# Default values if parameters are not passed
|
|
if desiredAccess is None:
|
|
desiredAccess = win32file.GENERIC_READ | win32file.GENERIC_WRITE
|
|
if shareMode is None:
|
|
shareMode = 0
|
|
if attributes == -1:
|
|
# attributes can be None
|
|
attributes = None
|
|
if CreationDisposition is None:
|
|
CreationDisposition = win32file.OPEN_EXISTING
|
|
if flagsAndAttributes is None:
|
|
flagsAndAttributes = (win32file.FILE_ATTRIBUTE_NORMAL |
|
|
win32file.FILE_FLAG_OVERLAPPED |
|
|
win32file.FILE_FLAG_NO_BUFFERING)
|
|
if hTemplateFile == -1:
|
|
hTemplateFile = None
|
|
|
|
try:
|
|
npipe = win32file.CreateFile(filename,
|
|
desiredAccess,
|
|
shareMode,
|
|
attributes,
|
|
CreationDisposition,
|
|
flagsAndAttributes,
|
|
hTemplateFile)
|
|
except pywintypes.error:
|
|
raise
|
|
return npipe
|
|
|
|
|
|
def write_file(handle, data, overlapped=None):
|
|
try:
|
|
(errCode, nBytesWritten) = win32file.WriteFile(handle,
|
|
data,
|
|
overlapped)
|
|
# Note: win32file.WriteFile doesn't throw an exception
|
|
# in case it receives ERROR_IO_PENDING.
|
|
return (errCode, nBytesWritten)
|
|
except pywintypes.error as e:
|
|
return (e.winerror, 0)
|
|
|
|
|
|
def read_file(handle, bufsize, overlapped=None):
|
|
try:
|
|
# Note: win32file.ReadFile doesn't throw an exception
|
|
# in case it receives ERROR_IO_PENDING.
|
|
(errCode, read_buffer) = win32file.ReadFile(
|
|
handle, bufsize, overlapped)
|
|
return (errCode, read_buffer)
|
|
except pywintypes.error as e:
|
|
return (e.winerror, "")
|
|
|
|
|
|
def create_named_pipe(pipename, openMode=None, pipeMode=None,
|
|
nMaxInstances=None, nOutBufferSize=None,
|
|
nInBufferSize=None, nDefaultTimeOut=None,
|
|
saAttr=-1):
|
|
# Default values if parameters are not passed
|
|
if openMode is None:
|
|
openMode = win32con.PIPE_ACCESS_DUPLEX | win32con.FILE_FLAG_OVERLAPPED
|
|
if pipeMode is None:
|
|
pipeMode = (win32con.PIPE_TYPE_MESSAGE |
|
|
win32con.PIPE_READMODE_BYTE |
|
|
win32con.PIPE_WAIT)
|
|
if nMaxInstances is None:
|
|
nMaxInstances = 64
|
|
if nOutBufferSize is None:
|
|
nOutBufferSize = 65000
|
|
if nInBufferSize is None:
|
|
nInBufferSize = 65000
|
|
if nDefaultTimeOut is None:
|
|
nDefaultTimeOut = 0
|
|
if saAttr == -1:
|
|
# saAttr can be None
|
|
saAttr = win32security.SECURITY_ATTRIBUTES()
|
|
|
|
# The identifier authority.
|
|
sia = ntsecuritycon.SECURITY_NT_AUTHORITY
|
|
|
|
# Initialize the SID.
|
|
remoteAccessSid = win32security.SID()
|
|
remoteAccessSid.Initialize(
|
|
sia, # The identifier authority.
|
|
1) # The number of sub authorities to allocate.
|
|
# Disable access over network.
|
|
remoteAccessSid.SetSubAuthority(
|
|
0, # The index of the sub authority to set
|
|
ntsecuritycon.SECURITY_NETWORK_RID)
|
|
|
|
allowedPsids = []
|
|
# Allow Windows Services to access the Named Pipe.
|
|
allowedPsid_0 = win32security.SID()
|
|
allowedPsid_0.Initialize(
|
|
sia, # The identifier authority.
|
|
1) # The number of sub authorities to allocate.
|
|
allowedPsid_0.SetSubAuthority(
|
|
0, # The index of the sub authority to set
|
|
ntsecuritycon.SECURITY_LOCAL_SYSTEM_RID)
|
|
# Allow Administrators to access the Named Pipe.
|
|
allowedPsid_1 = win32security.SID()
|
|
allowedPsid_1.Initialize(
|
|
sia, # The identifier authority.
|
|
2) # The number of sub authorities to allocate.
|
|
allowedPsid_1.SetSubAuthority(
|
|
0, # The index of the sub authority to set
|
|
ntsecuritycon.SECURITY_BUILTIN_DOMAIN_RID)
|
|
allowedPsid_1.SetSubAuthority(
|
|
1, # The index of the sub authority to set
|
|
ntsecuritycon.DOMAIN_ALIAS_RID_ADMINS)
|
|
|
|
allowedPsids.append(allowedPsid_0)
|
|
allowedPsids.append(allowedPsid_1)
|
|
|
|
# Initialize an ACL.
|
|
acl = win32security.ACL()
|
|
acl.Initialize()
|
|
# Add denied ACL.
|
|
acl.AddAccessDeniedAce(win32security.ACL_REVISION,
|
|
ntsecuritycon.GENERIC_ALL,
|
|
remoteAccessSid)
|
|
# Add allowed ACLs.
|
|
for allowedPsid in allowedPsids:
|
|
acl.AddAccessAllowedAce(win32security.ACL_REVISION,
|
|
ntsecuritycon.GENERIC_ALL,
|
|
allowedPsid)
|
|
|
|
# Initialize an SD.
|
|
sd = win32security.SECURITY_DESCRIPTOR()
|
|
sd.Initialize()
|
|
# Set DACL.
|
|
sd.SetSecurityDescriptorDacl(True, acl, False)
|
|
|
|
saAttr.bInheritHandle = 1
|
|
saAttr.SECURITY_DESCRIPTOR = sd
|
|
|
|
try:
|
|
npipe = win32pipe.CreateNamedPipe(pipename,
|
|
openMode,
|
|
pipeMode,
|
|
nMaxInstances,
|
|
nOutBufferSize,
|
|
nInBufferSize,
|
|
nDefaultTimeOut,
|
|
saAttr)
|
|
|
|
if npipe == win32file.INVALID_HANDLE_VALUE:
|
|
return None
|
|
|
|
return npipe
|
|
except pywintypes.error:
|
|
return None
|
|
|
|
|
|
def set_pipe_mode(hPipe, mode=-1, maxCollectionCount=None,
|
|
collectDataTimeout=None):
|
|
# Default values if parameters are not passed
|
|
if mode == -1:
|
|
mode = win32pipe.PIPE_READMODE_BYTE
|
|
try:
|
|
win32pipe.SetNamedPipeHandleState(
|
|
hPipe, mode, maxCollectionCount, collectDataTimeout)
|
|
except pywintypes.error:
|
|
raise
|
|
|
|
|
|
def connect_named_pipe(pipe_handle, overlapped=None):
|
|
try:
|
|
# If the result of ConnectNamedPipe is ERROR_IO_PENDING or
|
|
# ERROR_PIPE_CONNECTED, then this value is returned.
|
|
# All other error values raise a win32 exception
|
|
error = win32pipe.ConnectNamedPipe(pipe_handle, overlapped)
|
|
return error
|
|
except pywintypes.error as e:
|
|
return e.winerror
|
|
|
|
|
|
def get_pipe_name(name):
|
|
name = name.replace('/', '')
|
|
name = name.replace('\\', '')
|
|
name = "\\\\.\\pipe\\" + name
|
|
return name
|
|
|
|
|
|
def get_overlapped_result(handle, overlapped=None, bWait=False):
|
|
try:
|
|
return win32file.GetOverlappedResult(handle, overlapped, bWait)
|
|
except pywintypes.error:
|
|
raise
|
|
|
|
|
|
def get_new_event(sa=None, bManualReset=True, bInitialState=True,
|
|
objectName=None):
|
|
return win32event.CreateEvent(sa, bManualReset, bInitialState, objectName)
|
|
|
|
|
|
pipe_disconnected_errors = [winerror.ERROR_PIPE_NOT_CONNECTED,
|
|
winerror.ERROR_BAD_PIPE,
|
|
winerror.ERROR_NO_DATA,
|
|
winerror.ERROR_BROKEN_PIPE]
|