5
5
"io"
6
6
"os"
7
7
"os/exec"
8
+ "os/user"
9
+ "strconv"
8
10
"sync"
9
11
"syscall"
10
12
"unsafe"
@@ -39,6 +41,35 @@ func handleSession(perms *ssh.Permissions, newChannel ssh.NewChannel) {
39
41
40
42
execCmd := func (name string , arg ... string ) error {
41
43
cmd := exec .Command (name , arg ... )
44
+ username , ok := perms .CriticalOptions ["user" ]
45
+ var usr * user.User
46
+ if ok {
47
+ var err error
48
+ usr , err = user .Lookup (username )
49
+ if err != nil {
50
+ return err
51
+ }
52
+ } else {
53
+ usr , err = user .Current ()
54
+ if err != nil {
55
+ return err
56
+ }
57
+ }
58
+ uid , err := strconv .ParseUint (usr .Uid , 10 , 32 )
59
+ if err != nil {
60
+ return err
61
+ }
62
+ gid , err := strconv .ParseUint (usr .Gid , 10 , 32 )
63
+ if err != nil {
64
+ return err
65
+ }
66
+ if cmd .SysProcAttr == nil {
67
+ cmd .SysProcAttr = & syscall.SysProcAttr {}
68
+ }
69
+ cmd .SysProcAttr .Credential = & syscall.Credential {
70
+ Uid : uint32 (uid ),
71
+ Gid : uint32 (gid ),
72
+ }
42
73
close := func () {
43
74
cmd .Process .Kill ()
44
75
err := cmd .Wait ()
@@ -47,20 +78,16 @@ func handleSession(perms *ssh.Permissions, newChannel ssh.NewChannel) {
47
78
}
48
79
49
80
tb := []byte {0 , 0 , 0 , 0 }
50
- connection .SendRequest ("exit-status" , false , tb )
81
+ _ , err = connection .SendRequest ("exit-status" , false , tb )
82
+ if err != nil {
83
+ log .Error ("Error sending exit status" , "error" , err )
84
+ }
51
85
52
86
once .Do (closeConn )
53
87
54
88
log .Debug ("Session closed" )
55
89
}
56
90
57
- var pipesWait sync.WaitGroup
58
- pipesWait .Add (2 )
59
- go func () {
60
- pipesWait .Wait ()
61
- close ()
62
- }()
63
-
64
91
if hasRequestedPty {
65
92
log .Debug ("Creating pty..." )
66
93
cmdf , err = pty .Start (cmd )
@@ -70,12 +97,14 @@ func handleSession(perms *ssh.Permissions, newChannel ssh.NewChannel) {
70
97
71
98
var once sync.Once
72
99
go func () {
73
- io .Copy (connection , cmdf )
74
- pipesWait .Done ()
100
+ _ , err := io .Copy (connection , cmdf )
101
+ log .Debug ("Pty to connection copy ended" , "error" , err )
102
+ once .Do (close )
75
103
}()
76
104
go func () {
77
- io .Copy (cmdf , connection )
78
- pipesWait .Done ()
105
+ _ , err := io .Copy (cmdf , connection )
106
+ log .Debug ("Connection to pty copy ended" , "error" , err )
107
+ once .Do (close )
79
108
}()
80
109
81
110
termLen := ptyPayload [3 ]
@@ -98,6 +127,13 @@ func handleSession(perms *ssh.Permissions, newChannel ssh.NewChannel) {
98
127
}
99
128
100
129
// we want to wait for stdout and stderr before closing connection, but don't really mind about stdin
130
+ var pipesWait sync.WaitGroup
131
+ pipesWait .Add (2 )
132
+ go func () {
133
+ pipesWait .Wait ()
134
+ close ()
135
+ }()
136
+
101
137
go func () {
102
138
_ , err := io .Copy (stdin , connection )
103
139
log .Debug ("Stdin copy ended" , "error" , err )
0 commit comments