github.com/glycerine/xcryptossh@v7.0.4+incompatible/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  	"github.com/glycerine/xcryptossh"
    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 agentUnlockMsg
   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 parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmBeforeUse bool, extensions []ConstraintExtension, err error) {
   159  	for len(constraints) != 0 {
   160  		switch constraints[0] {
   161  		case agentConstrainLifetime:
   162  			lifetimeSecs = binary.BigEndian.Uint32(constraints[1:5])
   163  			constraints = constraints[5:]
   164  		case agentConstrainConfirm:
   165  			confirmBeforeUse = true
   166  			constraints = constraints[1:]
   167  		case agentConstrainExtension:
   168  			var msg constrainExtensionAgentMsg
   169  			if err = ssh.Unmarshal(constraints, &msg); err != nil {
   170  				return 0, false, nil, err
   171  			}
   172  			extensions = append(extensions, ConstraintExtension{
   173  				ExtensionName:    msg.ExtensionName,
   174  				ExtensionDetails: msg.ExtensionDetails,
   175  			})
   176  			constraints = msg.Rest
   177  		default:
   178  			return 0, false, nil, fmt.Errorf("unknown constraint type: %d", constraints[0])
   179  		}
   180  	}
   181  	return
   182  }
   183  
   184  func setConstraints(key *AddedKey, constraintBytes []byte) error {
   185  	lifetimeSecs, confirmBeforeUse, constraintExtensions, err := parseConstraints(constraintBytes)
   186  	if err != nil {
   187  		return err
   188  	}
   189  
   190  	key.LifetimeSecs = lifetimeSecs
   191  	key.ConfirmBeforeUse = confirmBeforeUse
   192  	key.ConstraintExtensions = constraintExtensions
   193  	return nil
   194  }
   195  
   196  func parseRSAKey(req []byte) (*AddedKey, error) {
   197  	var k rsaKeyMsg
   198  	if err := ssh.Unmarshal(req, &k); err != nil {
   199  		return nil, err
   200  	}
   201  	if k.E.BitLen() > 30 {
   202  		return nil, errors.New("agent: RSA public exponent too large")
   203  	}
   204  	priv := &rsa.PrivateKey{
   205  		PublicKey: rsa.PublicKey{
   206  			E: int(k.E.Int64()),
   207  			N: k.N,
   208  		},
   209  		D:      k.D,
   210  		Primes: []*big.Int{k.P, k.Q},
   211  	}
   212  	priv.Precompute()
   213  
   214  	addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
   215  	if err := setConstraints(addedKey, k.Constraints); err != nil {
   216  		return nil, err
   217  	}
   218  	return addedKey, nil
   219  }
   220  
   221  func parseEd25519Key(req []byte) (*AddedKey, error) {
   222  	var k ed25519KeyMsg
   223  	if err := ssh.Unmarshal(req, &k); err != nil {
   224  		return nil, err
   225  	}
   226  	priv := ed25519.PrivateKey(k.Priv)
   227  
   228  	addedKey := &AddedKey{PrivateKey: &priv, Comment: k.Comments}
   229  	if err := setConstraints(addedKey, k.Constraints); err != nil {
   230  		return nil, err
   231  	}
   232  	return addedKey, nil
   233  }
   234  
   235  func parseDSAKey(req []byte) (*AddedKey, error) {
   236  	var k dsaKeyMsg
   237  	if err := ssh.Unmarshal(req, &k); err != nil {
   238  		return nil, err
   239  	}
   240  	priv := &dsa.PrivateKey{
   241  		PublicKey: dsa.PublicKey{
   242  			Parameters: dsa.Parameters{
   243  				P: k.P,
   244  				Q: k.Q,
   245  				G: k.G,
   246  			},
   247  			Y: k.Y,
   248  		},
   249  		X: k.X,
   250  	}
   251  
   252  	addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
   253  	if err := setConstraints(addedKey, k.Constraints); err != nil {
   254  		return nil, err
   255  	}
   256  	return addedKey, nil
   257  }
   258  
   259  func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) {
   260  	priv = &ecdsa.PrivateKey{
   261  		D: privScalar,
   262  	}
   263  
   264  	switch curveName {
   265  	case "nistp256":
   266  		priv.Curve = elliptic.P256()
   267  	case "nistp384":
   268  		priv.Curve = elliptic.P384()
   269  	case "nistp521":
   270  		priv.Curve = elliptic.P521()
   271  	default:
   272  		return nil, fmt.Errorf("agent: unknown curve %q", curveName)
   273  	}
   274  
   275  	priv.X, priv.Y = elliptic.Unmarshal(priv.Curve, keyBytes)
   276  	if priv.X == nil || priv.Y == nil {
   277  		return nil, errors.New("agent: point not on curve")
   278  	}
   279  
   280  	return priv, nil
   281  }
   282  
   283  func parseEd25519Cert(req []byte) (*AddedKey, error) {
   284  	var k ed25519CertMsg
   285  	if err := ssh.Unmarshal(req, &k); err != nil {
   286  		return nil, err
   287  	}
   288  	pubKey, err := ssh.ParsePublicKey(k.CertBytes)
   289  	if err != nil {
   290  		return nil, err
   291  	}
   292  	priv := ed25519.PrivateKey(k.Priv)
   293  	cert, ok := pubKey.(*ssh.Certificate)
   294  	if !ok {
   295  		return nil, errors.New("agent: bad ED25519 certificate")
   296  	}
   297  
   298  	addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}
   299  	if err := setConstraints(addedKey, k.Constraints); err != nil {
   300  		return nil, err
   301  	}
   302  	return addedKey, nil
   303  }
   304  
   305  func parseECDSAKey(req []byte) (*AddedKey, error) {
   306  	var k ecdsaKeyMsg
   307  	if err := ssh.Unmarshal(req, &k); err != nil {
   308  		return nil, err
   309  	}
   310  
   311  	priv, err := unmarshalECDSA(k.Curve, k.KeyBytes, k.D)
   312  	if err != nil {
   313  		return nil, err
   314  	}
   315  
   316  	addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
   317  	if err := setConstraints(addedKey, k.Constraints); err != nil {
   318  		return nil, err
   319  	}
   320  	return addedKey, nil
   321  }
   322  
   323  func parseRSACert(req []byte) (*AddedKey, error) {
   324  	var k rsaCertMsg
   325  	if err := ssh.Unmarshal(req, &k); err != nil {
   326  		return nil, err
   327  	}
   328  
   329  	pubKey, err := ssh.ParsePublicKey(k.CertBytes)
   330  	if err != nil {
   331  		return nil, err
   332  	}
   333  
   334  	cert, ok := pubKey.(*ssh.Certificate)
   335  	if !ok {
   336  		return nil, errors.New("agent: bad RSA certificate")
   337  	}
   338  
   339  	// An RSA publickey as marshaled by rsaPublicKey.Marshal() in keys.go
   340  	var rsaPub struct {
   341  		Name string
   342  		E    *big.Int
   343  		N    *big.Int
   344  	}
   345  	if err := ssh.Unmarshal(cert.Key.Marshal(), &rsaPub); err != nil {
   346  		return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err)
   347  	}
   348  
   349  	if rsaPub.E.BitLen() > 30 {
   350  		return nil, errors.New("agent: RSA public exponent too large")
   351  	}
   352  
   353  	priv := rsa.PrivateKey{
   354  		PublicKey: rsa.PublicKey{
   355  			E: int(rsaPub.E.Int64()),
   356  			N: rsaPub.N,
   357  		},
   358  		D:      k.D,
   359  		Primes: []*big.Int{k.Q, k.P},
   360  	}
   361  	priv.Precompute()
   362  
   363  	addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}
   364  	if err := setConstraints(addedKey, k.Constraints); err != nil {
   365  		return nil, err
   366  	}
   367  	return addedKey, nil
   368  }
   369  
   370  func parseDSACert(req []byte) (*AddedKey, error) {
   371  	var k dsaCertMsg
   372  	if err := ssh.Unmarshal(req, &k); err != nil {
   373  		return nil, err
   374  	}
   375  	pubKey, err := ssh.ParsePublicKey(k.CertBytes)
   376  	if err != nil {
   377  		return nil, err
   378  	}
   379  	cert, ok := pubKey.(*ssh.Certificate)
   380  	if !ok {
   381  		return nil, errors.New("agent: bad DSA certificate")
   382  	}
   383  
   384  	// A DSA publickey as marshaled by dsaPublicKey.Marshal() in keys.go
   385  	var w struct {
   386  		Name       string
   387  		P, Q, G, Y *big.Int
   388  	}
   389  	if err := ssh.Unmarshal(cert.Key.Marshal(), &w); err != nil {
   390  		return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err)
   391  	}
   392  
   393  	priv := &dsa.PrivateKey{
   394  		PublicKey: dsa.PublicKey{
   395  			Parameters: dsa.Parameters{
   396  				P: w.P,
   397  				Q: w.Q,
   398  				G: w.G,
   399  			},
   400  			Y: w.Y,
   401  		},
   402  		X: k.X,
   403  	}
   404  
   405  	addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}
   406  	if err := setConstraints(addedKey, k.Constraints); err != nil {
   407  		return nil, err
   408  	}
   409  	return addedKey, nil
   410  }
   411  
   412  func parseECDSACert(req []byte) (*AddedKey, error) {
   413  	var k ecdsaCertMsg
   414  	if err := ssh.Unmarshal(req, &k); err != nil {
   415  		return nil, err
   416  	}
   417  
   418  	pubKey, err := ssh.ParsePublicKey(k.CertBytes)
   419  	if err != nil {
   420  		return nil, err
   421  	}
   422  	cert, ok := pubKey.(*ssh.Certificate)
   423  	if !ok {
   424  		return nil, errors.New("agent: bad ECDSA certificate")
   425  	}
   426  
   427  	// An ECDSA publickey as marshaled by ecdsaPublicKey.Marshal() in keys.go
   428  	var ecdsaPub struct {
   429  		Name string
   430  		ID   string
   431  		Key  []byte
   432  	}
   433  	if err := ssh.Unmarshal(cert.Key.Marshal(), &ecdsaPub); err != nil {
   434  		return nil, err
   435  	}
   436  
   437  	priv, err := unmarshalECDSA(ecdsaPub.ID, ecdsaPub.Key, k.D)
   438  	if err != nil {
   439  		return nil, err
   440  	}
   441  
   442  	addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}
   443  	if err := setConstraints(addedKey, k.Constraints); err != nil {
   444  		return nil, err
   445  	}
   446  	return addedKey, nil
   447  }
   448  
   449  func (s *server) insertIdentity(req []byte) error {
   450  	var record struct {
   451  		Type string `sshtype:"17|25"`
   452  		Rest []byte `ssh:"rest"`
   453  	}
   454  
   455  	if err := ssh.Unmarshal(req, &record); err != nil {
   456  		return err
   457  	}
   458  
   459  	var addedKey *AddedKey
   460  	var err error
   461  
   462  	switch record.Type {
   463  	case ssh.KeyAlgoRSA:
   464  		addedKey, err = parseRSAKey(req)
   465  	case ssh.KeyAlgoDSA:
   466  		addedKey, err = parseDSAKey(req)
   467  	case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521:
   468  		addedKey, err = parseECDSAKey(req)
   469  	case ssh.KeyAlgoED25519:
   470  		addedKey, err = parseEd25519Key(req)
   471  	case ssh.CertAlgoRSAv01:
   472  		addedKey, err = parseRSACert(req)
   473  	case ssh.CertAlgoDSAv01:
   474  		addedKey, err = parseDSACert(req)
   475  	case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01:
   476  		addedKey, err = parseECDSACert(req)
   477  	case ssh.CertAlgoED25519v01:
   478  		addedKey, err = parseEd25519Cert(req)
   479  	default:
   480  		return fmt.Errorf("agent: not implemented: %q", record.Type)
   481  	}
   482  
   483  	if err != nil {
   484  		return err
   485  	}
   486  	return s.agent.Add(*addedKey)
   487  }
   488  
   489  // ServeAgent serves the agent protocol on the given connection. It
   490  // returns when an I/O error occurs.
   491  func ServeAgent(agent Agent, c io.ReadWriter) error {
   492  	s := &server{agent}
   493  
   494  	var length [4]byte
   495  	for {
   496  		if _, err := io.ReadFull(c, length[:]); err != nil {
   497  			return err
   498  		}
   499  		l := binary.BigEndian.Uint32(length[:])
   500  		if l > maxAgentResponseBytes {
   501  			// We also cap requests.
   502  			return fmt.Errorf("agent: request too large: %d", l)
   503  		}
   504  
   505  		req := make([]byte, l)
   506  		if _, err := io.ReadFull(c, req); err != nil {
   507  			return err
   508  		}
   509  
   510  		repData := s.processRequestBytes(req)
   511  		if len(repData) > maxAgentResponseBytes {
   512  			return fmt.Errorf("agent: reply too large: %d bytes", len(repData))
   513  		}
   514  
   515  		binary.BigEndian.PutUint32(length[:], uint32(len(repData)))
   516  		if _, err := c.Write(length[:]); err != nil {
   517  			return err
   518  		}
   519  		if _, err := c.Write(repData); err != nil {
   520  			return err
   521  		}
   522  	}
   523  }