From a473715df32beb853de2383e47baff44127d7aa7 Mon Sep 17 00:00:00 2001 From: Erik Onarheim Date: Tue, 19 Jan 2016 14:40:29 -0600 Subject: [PATCH] Implement GetProcCredName in gosigar to address elastic/beats#590 elastic/topbeat#36 in windows --- sigar_interface.go | 1 + sigar_windows.go | 47 +++++++++++++++++++++++++++++++++++++++++++ sigar_windows_test.go | 13 ++++++++++++ 3 files changed, 61 insertions(+) diff --git a/sigar_interface.go b/sigar_interface.go index dd72a76b0..f4e99a56e 100644 --- a/sigar_interface.go +++ b/sigar_interface.go @@ -106,6 +106,7 @@ const ( type ProcState struct { Name string + Username string State RunState Ppid int Tty int diff --git a/sigar_windows.go b/sigar_windows.go index 7e4fe45a4..e9f744b7d 100644 --- a/sigar_windows.go +++ b/sigar_windows.go @@ -278,6 +278,12 @@ func (self *ProcState) Get(pid int) error { if err != nil { return err } + + self.Username, err = GetProcCredName(pid) + if err != nil { + return err + } + return nil } @@ -306,6 +312,47 @@ func GetProcName(pid int) (string, error) { } +func GetProcCredName(pid int) (string, error) { + var err error + + handle, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid)) + + if err != nil { + return "", fmt.Errorf("OpenProcess fails with %v", err) + } + + defer syscall.CloseHandle(handle) + + var token syscall.Token + + // Find process token via win32 + err = syscall.OpenProcessToken(handle, syscall.TOKEN_QUERY, &token) + + if err != nil { + return "", fmt.Errorf("Error opening process token %v", err) + } + + // Find the token user + tokenUser, err := token.GetTokenUser() + if err != nil { + return "", fmt.Errorf("Error getting token user %v", err) + } + + // Close token to prevent handle leaks + err = token.Close() + if err != nil { + return "", fmt.Errorf("Error failed to closed process token") + } + + // look up domain account by sid + account, domain, _, err := tokenUser.User.Sid.LookupAccount("localhost") + if err != nil { + return "", fmt.Errorf("Error looking up sid %v", err) + } + + return fmt.Sprintf("%s\\%s", domain, account), nil +} + func GetProcStatus(pid int) (RunState, error) { handle, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid)) diff --git a/sigar_windows_test.go b/sigar_windows_test.go index 38d66f36f..f0db19501 100644 --- a/sigar_windows_test.go +++ b/sigar_windows_test.go @@ -3,6 +3,7 @@ package sigar_test import ( "math" "os" + "os/user" "strings" "testing" @@ -32,6 +33,18 @@ var _ = Describe("SigarWindows", func() { Ω(usage.Total).Should(BeNumerically(">", 0)) }) }) + + Describe("Process", func() { + It("gets the current process user name", func() { + proc := sigar.ProcState{} + err := proc.Get(os.Getpid()) + user, usererr := user.Current() + + Ω(err).ShouldNot(HaveOccurred()) + Ω(usererr).ShouldNot(HaveOccurred()) + Ω(proc.Username).Should(Equal(user.Username)) + }) + }) }) func TestProcArgs(t *testing.T) {