@@ -30,9 +30,10 @@ type PublicKey struct {
3030type SSH struct {
3131 listener net.Listener
3232
33- sshconfig * ssh.ServerConfig
34- config * Config
35- PublicKeyLookupFunc func (string ) (* PublicKey , error )
33+ sshconfig * ssh.ServerConfig
34+ config * Config
35+ PublicKeyLookupFunc func (string ) (* PublicKey , error )
36+ ReposForKeyLookupFunc func (* PublicKey ) ([]string , error )
3637}
3738
3839func NewSSH (config Config ) * SSH {
@@ -75,7 +76,7 @@ func execCommand(cmdname string, args ...string) (string, string, error) {
7576 return string (bufOut ), string (bufErr ), err
7677}
7778
78- func (s * SSH ) handleConnection (keyID string , chans <- chan ssh.NewChannel ) {
79+ func (s * SSH ) handleConnection (exts map [ string ] string , chans <- chan ssh.NewChannel ) {
7980 for newChan := range chans {
8081 if newChan .ChannelType () != "session" {
8182 newChan .Reject (ssh .UnknownChannelType , "unknown channel type" )
@@ -142,7 +143,15 @@ func (s *SSH) handleConnection(keyID string, chans <-chan ssh.NewChannel) {
142143
143144 cmd := exec .Command (gitcmd .Command , gitcmd .Repo )
144145 cmd .Dir = s .config .Dir
145- cmd .Env = append (os .Environ (), "GITKIT_KEY=" + keyID )
146+
147+ envVariables := os .Environ ()
148+ // append data via ssh.Permissions.Extensions
149+ for k , v := range exts {
150+ log .Println ("k=" + k + ", v=" + v )
151+ envVariables = append (envVariables , "GITKIT_" + strings .ToUpper (k )+ "=" + v )
152+ }
153+ cmd .Env = envVariables
154+
146155 // cmd.Env = append(os.Environ(), "SSH_ORIGINAL_COMMAND="+cmdName)
147156
148157 stdout , err := cmd .StdoutPipe ()
@@ -209,6 +218,10 @@ func (s *SSH) setup() error {
209218 return fmt .Errorf ("public key lookup func is not provided" )
210219 }
211220
221+ if s .ReposForKeyLookupFunc == nil {
222+ log .Println ("no repository callback, an authorized user may access any repositories" )
223+ }
224+
212225 config .PublicKeyCallback = func (conn ssh.ConnMetadata , key ssh.PublicKey ) (* ssh.Permissions , error ) {
213226 pkey , err := s .PublicKeyLookupFunc (strings .TrimSpace (string (ssh .MarshalAuthorizedKey (key ))))
214227 if err != nil {
@@ -219,7 +232,23 @@ func (s *SSH) setup() error {
219232 return nil , fmt .Errorf ("auth handler did not return a key" )
220233 }
221234
222- return & ssh.Permissions {Extensions : map [string ]string {"key-id" : pkey .Id }}, nil
235+ var repos []string
236+
237+ if s .ReposForKeyLookupFunc != nil {
238+ repos , err = s .ReposForKeyLookupFunc (pkey )
239+ if err != nil {
240+ return nil , err
241+ }
242+ }
243+
244+ return & ssh.Permissions {
245+ Extensions : map [string ]string {
246+ "key" : pkey .Id ,
247+ "fingerprint" : pkey .Fingerprint ,
248+ "name" : pkey .Name ,
249+ "repositories" : strings .Join (repos , "," ),
250+ },
251+ }, nil
223252 }
224253 }
225254
@@ -296,13 +325,13 @@ func (s *SSH) Serve() error {
296325 return
297326 }
298327
299- keyId := ""
328+ var exts map [ string ] string
300329 if sConn .Permissions != nil {
301- keyId = sConn .Permissions .Extensions [ "key-id" ]
330+ exts = sConn .Permissions .Extensions
302331 }
303332
304333 go ssh .DiscardRequests (reqs )
305- go s .handleConnection (keyId , chans )
334+ go s .handleConnection (exts , chans )
306335 }()
307336 }
308337}
0 commit comments