def _pipe_write(self, buf): size = len(buf) log("pipe_write: %i bytes", size) #binascii.hexlify(buf)) written = c_ulong(0) r = WriteFile(self.pipe_handle, c_char_p(buf), len(buf), byref(written), byref(self.write_overlapped)) log("WriteFile(..)=%s, len=%i", r, written.value) if not r and self.pipe_handle: e = GetLastError() if e != ERROR_IO_PENDING: log("WriteFile: %s", IO_ERROR_STR.get(e, e)) r = WaitForSingleObject(self.write_event, INFINITE) log("WaitForSingleObject(..)=%s, len=%i", WAIT_STR.get(r, r), written.value) if not self.pipe_handle: #closed already! return written.value if r: raise Exception( "failed to write buffer to named pipe handle %s" % self.pipe_handle) if self.pipe_handle: if not GetOverlappedResult(self.pipe_handle, byref(self.write_overlapped), byref(written), False): e = GetLastError() raise Exception("overlapped write failed: %s" % IO_ERROR_STR.get(e, e)) log("pipe_write: %i bytes written", written.value) if self.pipe_handle: FlushFileBuffers(self.pipe_handle) #SetFilePointer(self.pipe_handle, 0, FILE_BEGIN) return written.value
def _pipe_read(self, n): read = c_ulong(0) n_bytes = DWORD(min(n, BUFSIZE)) r = ReadFile(self.pipe_handle, self.read_buffer_ptr, n_bytes, byref(read), byref(self.read_overlapped)) log("ReadFile(%i)=%i, len=%s", n, r, read.value) if not r and self.pipe_handle: e = GetLastError() if e!=ERROR_IO_PENDING: log("ReadFile: %s", IO_ERROR_STR.get(e, e)) if e in CONNECTION_CLOSED_ERRORS: raise ConnectionClosedException(CONNECTION_CLOSED_ERRORS[e]) r = WaitForSingleObject(self.read_event, INFINITE) log("WaitForSingleObject(..)=%s, len=%s", WAIT_STR.get(r, r), read.value) if r and self.pipe_handle: raise Exception("failed to read from named pipe handle %s" % self.pipe_handle) if self.pipe_handle: if not GetOverlappedResult(self.pipe_handle, byref(self.read_overlapped), byref(read), False): e = GetLastError() if e in CONNECTION_CLOSED_ERRORS: raise ConnectionClosedException(CONNECTION_CLOSED_ERRORS[e]) raise Exception("overlapped read failed: %s" % IO_ERROR_STR.get(e, e)) if read.value==0: data = None else: data = string_at(self.read_buffer_ptr, read.value) log("pipe_read: %i bytes", len(data or "")) #, binascii.hexlify(s)) return data
def _pipe_read(self, buf): read = c_ulong(0) r = ReadFile(self.pipe_handle, self.read_buffer_ptr, BUFSIZE, byref(read), byref(self.read_overlapped)) log("ReadFile(..)=%i, len=%s", r, read.value) if not r and self.pipe_handle: e = GetLastError() if e != ERROR_IO_PENDING: log("ReadFile: %s", IO_ERROR_STR.get(e, e)) r = WaitForSingleObject(self.read_event, INFINITE) log("WaitForSingleObject(..)=%s, len=%s", WAIT_STR.get(r, r), read.value) if r and self.pipe_handle: raise Exception("failed to read from named pipe handle %s" % self.pipe_handle) if self.pipe_handle: if not GetOverlappedResult(self.pipe_handle, byref(self.read_overlapped), byref(read), False): e = GetLastError() if e != ERROR_BROKEN_PIPE: raise Exception("overlapped read failed: %s" % IO_ERROR_STR.get(e, e)) if read.value == 0: data = None else: data = string_at(self.read_buffer_ptr, read.value) log("pipe_read: %i bytes", len(data or "")) #, binascii.hexlify(s)) return data
def do_run(self): pipe_handle = None while not self.exit_loop: if not pipe_handle: try: pipe_handle = self.CreatePipeHandle() except Exception as e: log("CreatePipeHandle()", exc_info=True) log.error("Error: failed to create named pipe") log.error(" at path '%s'", self.pipe_name) log.error(" %s", e) return log("CreatePipeHandle()=%#x", pipe_handle) if c_long(pipe_handle).value==INVALID_HANDLE_VALUE: log.error("Error: invalid handle for named pipe '%s'", self.pipe_name) e = GetLastError() log.error(" '%s' (%i)", FormatMessageSystem(e).rstrip("\n\r."), e) return event = CreateEventA(None, True, False, None) overlapped = OVERLAPPED() overlapped.hEvent = event overlapped.Internal = None overlapped.InternalHigh = None overlapped.union.Pointer = None r = ConnectNamedPipe(pipe_handle, overlapped) log("ConnectNamedPipe()=%s", r) if self.exit_loop: break if r==0: e = GetLastError() log("GetLastError()=%s (%i)", FormatMessageSystem(e).rstrip("\n\r"), e) if e==ERROR_PIPE_CONNECTED: pass elif e==ERROR_IO_PENDING: while not self.exit_loop: r = WaitForSingleObject(event, INFINITE) log("WaitForSingleObject(..)=%s", WAIT_STR.get(r, r)) if r==WAIT_TIMEOUT: continue if r==0: break log.error("Error: cannot connect to named pipe '%s'", self.pipe_name) log.error(" %s", WAIT_STR.get(r, r)) CloseHandle(pipe_handle) pipe_handle = None break else: log.error("Error: cannot connect to named pipe '%s'", self.pipe_name) log.error(" error %s", e) CloseHandle(pipe_handle) pipe_handle = None if self.exit_loop: break #from now on, the pipe_handle will be managed elsewhere: if pipe_handle: self.new_connection_cb("named-pipe", self, pipe_handle) pipe_handle = None if pipe_handle: self.close_handle(pipe_handle)
def connect_to_namedpipe(pipe_name, timeout=10): log("connect_to_namedpipe(%s, %i)", pipe_name, timeout) import time start = time.time() while True: if time.time() - start >= timeout: raise Exception("timeout waiting for named pipe '%s'" % pipe_name) pipe_handle = CreateFileA(strtobytes(pipe_name), GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0) log("CreateFileA(%s)=%#x", pipe_name, pipe_handle) if pipe_handle != INVALID_HANDLE_VALUE: break err = GetLastError() log("CreateFileA(..) error=%s", err) if err == ERROR_PIPE_BUSY: if WaitNamedPipeA(pipe_name, timeout * 10000) == 0: raise Exception("timeout waiting for named pipe '%s'" % pipe_name) else: raise Exception("cannot open named pipe '%s': %s" % (pipe_name, FormatMessageSystem(err))) #we have a valid handle! dwMode = c_ulong(PIPE_READMODE_BYTE) r = SetNamedPipeHandleState(pipe_handle, byref(dwMode), None, None) log("SetNamedPipeHandleState(..)=%i", r) if not r: log.warn("Warning: SetNamedPipeHandleState failed") return pipe_handle
def untilConcludes(self, fn, *args, **kwargs): try: return super().untilConcludes(fn, *args, **kwargs) except Exception as e: code = GetLastError() log("untilConcludes(%s, ) exception: %s, error code=%s", fn, e, code, exc_info=True) closed = CONNECTION_CLOSED_ERRORS.get(code) if closed: return None raise IOError("%s: %s" % (e, code)) from None
def untilConcludes(self, fn, *args, **kwargs): try: return Connection.untilConcludes(self, fn, *args, **kwargs) except Exception as e: code = GetLastError() log("untilConcludes(%s, ) exception: %s, error code=%s", fn, e, code, exc_info=True) if code == ERROR_PIPE_NOT_CONNECTED: return None raise IOError("%s: %s" % (e, code))
def GetToken(self, token_type, token_struct): assert self.token_process data_size = DWORD() if not GetTokenInformation(self.token_process, token_type, 0, 0, byref(data_size)): if GetLastError()!=ERROR_INSUFFICIENT_BUFFER: raise WindowsError() # @UndefinedVariable log("GetTokenInformation data size %#x", data_size.value) token_data = create_string_buffer(data_size.value) self.tokens.append(token_data) if not GetTokenInformation(self.token_process, token_type, byref(token_data), data_size.value, byref(data_size)): raise WindowsError() #@UndefinedVariable token = cast(token_data, POINTER(token_struct)).contents return token
def do_run(self): while not self.exit_loop: pipe_handle = None try: pipe_handle = self.CreatePipeHandle() except Exception as e: log("CreatePipeHandle()", exc_info=True) log.error("Error: failed to create named pipe") log.error(" at path '%s'", self.pipe_name) log.error(" %s", e) return log("CreatePipeHandle()=%s", pipe_handle) if pipe_handle == INVALID_HANDLE_VALUE: log.error("Error: invalid handle for named pipe '%s'", self.pipe_name) return event = CreateEventA(None, True, False, None) overlapped = OVERLAPPED() overlapped.hEvent = event overlapped.Internal = None overlapped.InternalHigh = None overlapped.union.Pointer = None r = ConnectNamedPipe(pipe_handle, overlapped) log("ConnectNamedPipe()=%s", r) if not r and not self.exit_loop: r = WaitForSingleObject(event, INFINITE) log("WaitForSingleObject(..)=%s", WAIT_STR.get(r, r)) if r: log("do_run() error on WaitForSingleObject", exc_info=True) log.error("Error: cannot connect to named pipe '%s'", self.pipe_name) CloseHandle(pipe_handle) continue if self.exit_loop: CloseHandle(pipe_handle) break if r == 0 and False: e = GetLastError() if e == ERROR_PIPE_CONNECTED: pass else: log.error("Error: cannot connect to named pipe '%s'", self.pipe_name) log.error(" error %s", e) CloseHandle(pipe_handle) continue #from now on, the pipe_handle will be managed elsewhere: self.new_connection_cb(self, pipe_handle)
def CreatePipeSecurityAttributes(self): user = self.GetToken(TokenUser, TOKEN_USER) user_SID = user.SID.contents log("user SID=%s, attributes=%#x", user_SID, user.ATTRIBUTES) group = self.GetToken(TokenPrimaryGroup, TOKEN_PRIMARY_GROUP) group_SID = group.PrimaryGroup.contents log("group SID=%s", group_SID) SD = SECURITY_DESCRIPTOR() self.security_descriptor = SD log("SECURITY_DESCRIPTOR=%s", SD) if not InitializeSecurityDescriptor(byref(SD), SECURITY_DESCRIPTOR.REVISION): raise WindowsError() #@UndefinedVariable log("InitializeSecurityDescriptor: %s", SD) if not SetSecurityDescriptorOwner(byref(SD), user.SID, False): raise WindowsError() #@UndefinedVariable log("SetSecurityDescriptorOwner: %s", SD) if not SetSecurityDescriptorGroup(byref(SD), group.PrimaryGroup, False): raise WindowsError() #@UndefinedVariable log("SetSecurityDescriptorGroup: %s", SD) SA = SECURITY_ATTRIBUTES() log("CreatePipeSecurityObject() SECURITY_ATTRIBUTES=%s", SA) if not UNRESTRICTED: SA.descriptor = SD SA.bInheritHandle = False return SA if not SetSecurityDescriptorSacl(byref(SD), False, None, False): raise WindowsError() #@UndefinedVariable if not SetSecurityDescriptorDacl(byref(SD), True, None, False): raise WindowsError() #@UndefinedVariable #this doesn't work - and I don't know why: #SECURITY_NT_AUTHORITY = 5 #sia_anonymous = SID_IDENTIFIER_AUTHORITY((0, 0, 0, 0, 0, SECURITY_NT_AUTHORITY)) #log("SID_IDENTIFIER_AUTHORITY(SECURITY_NT_AUTHORITY)=%s", sia_anonymous) #sid_allow = SID() #log("empty SID: %s", sid_allow) #if not AllocateAndInitializeSid(byref(sia_anonymous), 1, # SECURITY_ANONYMOUS_LOGON_RID, 0, 0, 0, 0, 0, 0, 0, # byref(sid_allow), # ): # raise WindowsError() # log("AllocateAndInitializeSid(..) sid_anonymous=%s", sid_allow) sid_allow = SID() sid_size = DWORD(sizeof(SID)) sid_type = WinWorldSid SECURITY_MAX_SID_SIZE = 68 assert sizeof(SID) >= SECURITY_MAX_SID_SIZE if not CreateWellKnownSid(sid_type, None, byref(sid_allow), byref(sid_size)): log.error("error=%s", GetLastError()) raise WindowsError() #@UndefinedVariable assert sid_size.value <= SECURITY_MAX_SID_SIZE log("CreateWellKnownSid(..) sid_allow=%s, sid_size=%s", sid_allow, sid_size) acl_size = sizeof(ACL) acl_size += 2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) acl_size += GetLengthSid(byref(sid_allow)) acl_size += GetLengthSid(byref(user.SID.contents)) #acl_size += GetLengthSid(user.SID) acl_data = create_string_buffer(acl_size) acl = cast(acl_data, POINTER(ACL)).contents log("acl_size=%s, acl_data=%s, acl=%s", acl_size, acl_data, acl) if not InitializeAcl(byref(acl), acl_size, ACL_REVISION): raise WindowsError() #@UndefinedVariable log("InitializeAcl(..) acl=%s", acl) rights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL add_sid = user.SID r = AddAccessAllowedAce(byref(acl), ACL_REVISION, rights, add_sid) if r == 0: err = GetLastError() log("AddAccessAllowedAce(..)=%s", ACL_ERRORS.get(err, err)) raise WindowsError() #@UndefinedVariable rights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL add_sid = byref(sid_allow) r = AddAccessAllowedAce(byref(acl), ACL_REVISION, rights, add_sid) if r == 0: err = GetLastError() log("AddAccessAllowedAce(..)=%s", ACL_ERRORS.get(err, err)) raise WindowsError() #@UndefinedVariable if not SetSecurityDescriptorDacl(byref(SD), True, byref(acl), False): raise WindowsError() #@UndefinedVariable SA.nLength = sizeof(SECURITY_ATTRIBUTES) SA.lpSecurityDescriptor = cast(pointer(SD), c_void_p) SA.bInheritHandle = True self.security_attributes = SA return SA