@@ -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,17 @@ 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+ envVariables = append (envVariables , "GITKIT_CURRENT_REPOSITORY=" + gitcmd .Repo )
149+
150+ // append data via ssh.Permissions.Extensions
151+ for k , v := range exts {
152+ log .Println ("k=" + k + ", v=" + v )
153+ envVariables = append (envVariables , "GITKIT_" + strings .ToUpper (k )+ "=" + v )
154+ }
155+ cmd .Env = envVariables
156+
146157 // cmd.Env = append(os.Environ(), "SSH_ORIGINAL_COMMAND="+cmdName)
147158
148159 stdout , err := cmd .StdoutPipe ()
@@ -209,6 +220,10 @@ func (s *SSH) setup() error {
209220 return fmt .Errorf ("public key lookup func is not provided" )
210221 }
211222
223+ if s .ReposForKeyLookupFunc == nil {
224+ log .Println ("no repository callback, an authorized user may access any repositories" )
225+ }
226+
212227 config .PublicKeyCallback = func (conn ssh.ConnMetadata , key ssh.PublicKey ) (* ssh.Permissions , error ) {
213228 pkey , err := s .PublicKeyLookupFunc (strings .TrimSpace (string (ssh .MarshalAuthorizedKey (key ))))
214229 if err != nil {
@@ -219,7 +234,23 @@ func (s *SSH) setup() error {
219234 return nil , fmt .Errorf ("auth handler did not return a key" )
220235 }
221236
222- return & ssh.Permissions {Extensions : map [string ]string {"key-id" : pkey .Id }}, nil
237+ var repos []string
238+
239+ if s .ReposForKeyLookupFunc != nil {
240+ repos , err = s .ReposForKeyLookupFunc (pkey )
241+ if err != nil {
242+ return nil , err
243+ }
244+ }
245+
246+ return & ssh.Permissions {
247+ Extensions : map [string ]string {
248+ "key" : pkey .Id ,
249+ "fingerprint" : pkey .Fingerprint ,
250+ "name" : pkey .Name ,
251+ "repositories" : strings .Join (repos , "," ),
252+ },
253+ }, nil
223254 }
224255 }
225256
@@ -296,13 +327,13 @@ func (s *SSH) Serve() error {
296327 return
297328 }
298329
299- keyId := ""
330+ var exts map [ string ] string
300331 if sConn .Permissions != nil {
301- keyId = sConn .Permissions .Extensions [ "key-id" ]
332+ exts = sConn .Permissions .Extensions
302333 }
303334
304335 go ssh .DiscardRequests (reqs )
305- go s .handleConnection (keyId , chans )
336+ go s .handleConnection (exts , chans )
306337 }()
307338 }
308339}
0 commit comments