github.com/maenmax/kairep@v0.0.0-20210218001208-55bf3df36788/src/golang.org/x/crypto/ssh/agent/server.go (about)

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package agent
     6  
     7  import (
     8  	"crypto/dsa"
     9  	"crypto/ecdsa"
    10  	"crypto/elliptic"
    11  	"crypto/rsa"
    12  	"encoding/binary"
    13  	"errors"
    14  	"fmt"
    15  	"io"
    16  	"log"
    17  	"math/big"
    18  
    19  	"golang.org/x/crypto/ed25519"
    20  	"golang.org/x/crypto/ssh"
    21  )
    22  
    23  // Server wraps an Agent and uses it to implement the agent side of
    24  // the SSH-agent, wire protocol.
    25  type server struct {
    26  	agent Agent
    27  }
    28  
    29  func (s *server) processRequestBytes(reqData []byte) []byte {
    30  	rep, err := s.processRequest(reqData)
    31  	if err != nil {
    32  		if err != errLocked {
    33  			// TODO(hanwen): provide better logging interface?
    34  			log.Printf("agent %d: %v", reqData[0], err)
    35  		}
    36  		return []byte{agentFailure}
    37  	}
    38  
    39  	if err == nil && rep == nil {
    40  		return []byte{agentSuccess}
    41  	}
    42  
    43  	return ssh.Marshal(rep)
    44  }
    45  
    46  func marshalKey(k *Key) []byte {
    47  	var record struct {
    48  		Blob    []byte
    49  		Comment string
    50  	}
    51  	record.Blob = k.Marshal()
    52  	record.Comment = k.Comment
    53  
    54  	return ssh.Marshal(&record)
    55  }
    56  
    57  // See [PROTOCOL.agent], section 2.5.1.
    58  const agentV1IdentitiesAnswer = 2
    59  
    60  type agentV1IdentityMsg struct {
    61  	Numkeys uint32 `sshtype:"2"`
    62  }
    63  
    64  type agentRemoveIdentityMsg struct {
    65  	KeyBlob []byte `sshtype:"18"`
    66  }
    67  
    68  type agentLockMsg struct {
    69  	Passphrase []byte `sshtype:"22"`
    70  }
    71  
    72  type agentUnlockMsg struct {
    73  	Passphrase []byte `sshtype:"23"`
    74  }
    75  
    76  func (s *server) processRequest(data []byte) (interface{}, error) {
    77  	switch data[0] {
    78  	case agentRequestV1Identities:
    79  		return &agentV1IdentityMsg{0}, nil
    80  
    81  	case agentRemoveAllV1Identities:
    82  		return nil, nil
    83  
    84  	case agentRemoveIdentity:
    85  		var req agentRemoveIdentityMsg
    86  		if err := ssh.Unmarshal(data, &req); err != nil {
    87  			return nil, err
    88  		}
    89  
    90  		var wk wireKey
    91  		if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil {
    92  			return nil, err
    93  		}
    94  
    95  		return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob})
    96  
    97  	case agentRemoveAllIdentities:
    98  		return nil, s.agent.RemoveAll()
    99  
   100  	case agentLock:
   101  		var req agentLockMsg
   102  		if err := ssh.Unmarshal(data, &req); err != nil {
   103  			return nil, err
   104  		}
   105  
   106  		return nil, s.agent.Lock(req.Passphrase)
   107  
   108  	case agentUnlock:
   109  		var req agentLockMsg
   110  		if err := ssh.Unmarshal(data, &req); err != nil {
   111  			return nil, err
   112  		}
   113  		return nil, s.agent.Unlock(req.Passphrase)
   114  
   115  	case agentSignRequest:
   116  		var req signRequestAgentMsg
   117  		if err := ssh.Unmarshal(data, &req); err != nil {
   118  			return nil, err
   119  		}
   120  
   121  		var wk wireKey
   122  		if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil {
   123  			return nil, err
   124  		}
   125  
   126  		k := &Key{
   127  			Format: wk.Format,
   128  			Blob:   req.KeyBlob,
   129  		}
   130  
   131  		sig, err := s.agent.Sign(k, req.Data) //  TODO(hanwen): flags.
   132  		if err != nil {
   133  			return nil, err
   134  		}
   135  		return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil
   136  
   137  	case agentRequestIdentities:
   138  		keys, err := s.agent.List()
   139  		if err != nil {
   140  			return nil, err
   141  		}
   142  
   143  		rep := identitiesAnswerAgentMsg{
   144  			NumKeys: uint32(len(keys)),
   145  		}
   146  		for _, k := range keys {
   147  			rep.Keys = append(rep.Keys, marshalKey(k)...)
   148  		}
   149  		return rep, nil
   150  
   151  	case agentAddIdConstrained, agentAddIdentity:
   152  		return nil, s.insertIdentity(data)
   153  	}
   154  
   155  	return nil, fmt.Errorf("unknown opcode %d", data[0])
   156  }
   157  
   158  func parseRSAKey(req []byte) (*AddedKey, error) {
   159  	var k rsaKeyMsg
   160  	if err := ssh.Unmarshal(req, &k); err != nil {
   161  		return nil, err
   162  	}
   163  	if k.E.BitLen() > 30 {
   164  		return nil, errors.New("agent: RSA public exponent too large")
   165  	}
   166  	priv := &rsa.PrivateKey{
   167  		PublicKey: rsa.PublicKey{
   168  			E: int(k.E.Int64()),
   169  			N: k.N,
   170  		},
   171  		D:      k.D,
   172  		Primes: []*big.Int{k.P, k.Q},
   173  	}
   174  	priv.Precompute()
   175  
   176  	return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil
   177  }
   178  
   179  func parseEd25519Key(req []byte) (*AddedKey, error) {
   180  	var k ed25519KeyMsg
   181  	if err := ssh.Unmarshal(req, &k); err != nil {
   182  		return nil, err
   183  	}
   184  	priv := ed25519.PrivateKey(k.Priv)
   185  	return &AddedKey{PrivateKey: &priv, Comment: k.Comments}, nil
   186  }
   187  
   188  func parseDSAKey(req []byte) (*AddedKey, error) {
   189  	var k dsaKeyMsg
   190  	if err := ssh.Unmarshal(req, &k); err != nil {
   191  		return nil, err
   192  	}
   193  	priv := &dsa.PrivateKey{
   194  		PublicKey: dsa.PublicKey{
   195  			Parameters: dsa.Parameters{
   196  				P: k.P,
   197  				Q: k.Q,
   198  				G: k.G,
   199  			},
   200  			Y: k.Y,
   201  		},
   202  		X: k.X,
   203  	}
   204  
   205  	return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil
   206  }
   207  
   208  func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) {
   209  	priv = &ecdsa.PrivateKey{
   210  		D: privScalar,
   211  	}
   212  
   213  	switch curveName {
   214  	case "nistp256":
   215  		priv.Curve = elliptic.P256()
   216  	case "nistp384":
   217  		priv.Curve = elliptic.P384()
   218  	case "nistp521":
   219  		priv.Curve = elliptic.P521()
   220  	default:
   221  		return nil, fmt.Errorf("agent: unknown curve %q", curveName)
   222  	}
   223  
   224  	priv.X, priv.Y = elliptic.Unmarshal(priv.Curve, keyBytes)
   225  	if priv.X == nil || priv.Y == nil {
   226  		return nil, errors.New("agent: point not on curve")
   227  	}
   228  
   229  	return priv, nil
   230  }
   231  
   232  func parseEd25519Cert(req []byte) (*AddedKey, error) {
   233  	var k ed25519CertMsg
   234  	if err := ssh.Unmarshal(req, &k); err != nil {
   235  		return nil, err
   236  	}
   237  	pubKey, err := ssh.ParsePublicKey(k.CertBytes)
   238  	if err != nil {
   239  		return nil, err
   240  	}
   241  	priv := ed25519.PrivateKey(k.Priv)
   242  	cert, ok := pubKey.(*ssh.Certificate)
   243  	if !ok {
   244  		return nil, errors.New("agent: bad ED25519 certificate")
   245  	}
   246  	return &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}, nil
   247  }
   248  
   249  func parseECDSAKey(req []byte) (*AddedKey, error) {
   250  	var k ecdsaKeyMsg
   251  	if err := ssh.Unmarshal(req, &k); err != nil {
   252  		return nil, err
   253  	}
   254  
   255  	priv, err := unmarshalECDSA(k.Curve, k.KeyBytes, k.D)
   256  	if err != nil {
   257  		return nil, err
   258  	}
   259  
   260  	return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil
   261  }
   262  
   263  func parseRSACert(req []byte) (*AddedKey, error) {
   264  	var k rsaCertMsg
   265  	if err := ssh.Unmarshal(req, &k); err != nil {
   266  		return nil, err
   267  	}
   268  
   269  	pubKey, err := ssh.ParsePublicKey(k.CertBytes)
   270  	if err != nil {
   271  		return nil, err
   272  	}
   273  
   274  	cert, ok := pubKey.(*ssh.Certificate)
   275  	if !ok {
   276  		return nil, errors.New("agent: bad RSA certificate")
   277  	}
   278  
   279  	// An RSA publickey as marshaled by rsaPublicKey.Marshal() in keys.go
   280  	var rsaPub struct {
   281  		Name string
   282  		E    *big.Int
   283  		N    *big.Int
   284  	}
   285  	if err := ssh.Unmarshal(cert.Key.Marshal(), &rsaPub); err != nil {
   286  		return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err)
   287  	}
   288  
   289  	if rsaPub.E.BitLen() > 30 {
   290  		return nil, errors.New("agent: RSA public exponent too large")
   291  	}
   292  
   293  	priv := rsa.PrivateKey{
   294  		PublicKey: rsa.PublicKey{
   295  			E: int(rsaPub.E.Int64()),
   296  			N: rsaPub.N,
   297  		},
   298  		D:      k.D,
   299  		Primes: []*big.Int{k.Q, k.P},
   300  	}
   301  	priv.Precompute()
   302  
   303  	return &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}, nil
   304  }
   305  
   306  func parseDSACert(req []byte) (*AddedKey, error) {
   307  	var k dsaCertMsg
   308  	if err := ssh.Unmarshal(req, &k); err != nil {
   309  		return nil, err
   310  	}
   311  	pubKey, err := ssh.ParsePublicKey(k.CertBytes)
   312  	if err != nil {
   313  		return nil, err
   314  	}
   315  	cert, ok := pubKey.(*ssh.Certificate)
   316  	if !ok {
   317  		return nil, errors.New("agent: bad DSA certificate")
   318  	}
   319  
   320  	// A DSA publickey as marshaled by dsaPublicKey.Marshal() in keys.go
   321  	var w struct {
   322  		Name       string
   323  		P, Q, G, Y *big.Int
   324  	}
   325  	if err := ssh.Unmarshal(cert.Key.Marshal(), &w); err != nil {
   326  		return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err)
   327  	}
   328  
   329  	priv := &dsa.PrivateKey{
   330  		PublicKey: dsa.PublicKey{
   331  			Parameters: dsa.Parameters{
   332  				P: w.P,
   333  				Q: w.Q,
   334  				G: w.G,
   335  			},
   336  			Y: w.Y,
   337  		},
   338  		X: k.X,
   339  	}
   340  
   341  	return &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}, nil
   342  }
   343  
   344  func parseECDSACert(req []byte) (*AddedKey, error) {
   345  	var k ecdsaCertMsg
   346  	if err := ssh.Unmarshal(req, &k); err != nil {
   347  		return nil, err
   348  	}
   349  
   350  	pubKey, err := ssh.ParsePublicKey(k.CertBytes)
   351  	if err != nil {
   352  		return nil, err
   353  	}
   354  	cert, ok := pubKey.(*ssh.Certificate)
   355  	if !ok {
   356  		return nil, errors.New("agent: bad ECDSA certificate")
   357  	}
   358  
   359  	// An ECDSA publickey as marshaled by ecdsaPublicKey.Marshal() in keys.go
   360  	var ecdsaPub struct {
   361  		Name string
   362  		ID   string
   363  		Key  []byte
   364  	}
   365  	if err := ssh.Unmarshal(cert.Key.Marshal(), &ecdsaPub); err != nil {
   366  		return nil, err
   367  	}
   368  
   369  	priv, err := unmarshalECDSA(ecdsaPub.ID, ecdsaPub.Key, k.D)
   370  	if err != nil {
   371  		return nil, err
   372  	}
   373  
   374  	return &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}, nil
   375  }
   376  
   377  func (s *server) insertIdentity(req []byte) error {
   378  	var record struct {
   379  		Type string `sshtype:"17|25"`
   380  		Rest []byte `ssh:"rest"`
   381  	}
   382  
   383  	if err := ssh.Unmarshal(req, &record); err != nil {
   384  		return err
   385  	}
   386  
   387  	var addedKey *AddedKey
   388  	var err error
   389  
   390  	switch record.Type {
   391  	case ssh.KeyAlgoRSA:
   392  		addedKey, err = parseRSAKey(req)
   393  	case ssh.KeyAlgoDSA:
   394  		addedKey, err = parseDSAKey(req)
   395  	case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521:
   396  		addedKey, err = parseECDSAKey(req)
   397  	case ssh.KeyAlgoED25519:
   398  		addedKey, err = parseEd25519Key(req)
   399  	case ssh.CertAlgoRSAv01:
   400  		addedKey, err = parseRSACert(req)
   401  	case ssh.CertAlgoDSAv01:
   402  		addedKey, err = parseDSACert(req)
   403  	case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01:
   404  		addedKey, err = parseECDSACert(req)
   405  	case ssh.CertAlgoED25519v01:
   406  		addedKey, err = parseEd25519Cert(req)
   407  	default:
   408  		return fmt.Errorf("agent: not implemented: %q", record.Type)
   409  	}
   410  
   411  	if err != nil {
   412  		return err
   413  	}
   414  	return s.agent.Add(*addedKey)
   415  }
   416  
   417  // ServeAgent serves the agent protocol on the given connection. It
   418  // returns when an I/O error occurs.
   419  func ServeAgent(agent Agent, c io.ReadWriter) error {
   420  	s := &server{agent}
   421  
   422  	var length [4]byte
   423  	for {
   424  		if _, err := io.ReadFull(c, length[:]); err != nil {
   425  			return err
   426  		}
   427  		l := binary.BigEndian.Uint32(length[:])
   428  		if l > maxAgentResponseBytes {
   429  			// We also cap requests.
   430  			return fmt.Errorf("agent: request too large: %d", l)
   431  		}
   432  
   433  		req := make([]byte, l)
   434  		if _, err := io.ReadFull(c, req); err != nil {
   435  			return err
   436  		}
   437  
   438  		repData := s.processRequestBytes(req)
   439  		if len(repData) > maxAgentResponseBytes {
   440  			return fmt.Errorf("agent: reply too large: %d bytes", len(repData))
   441  		}
   442  
   443  		binary.BigEndian.PutUint32(length[:], uint32(len(repData)))
   444  		if _, err := c.Write(length[:]); err != nil {
   445  			return err
   446  		}
   447  		if _, err := c.Write(repData); err != nil {
   448  			return err
   449  		}
   450  	}
   451  }