Ejemplo n.º 1
0
func (c *BaseCluster) sshConfig() (*ssh.ClientConfig, error) {
	signer, err := ssh.NewSignerFromKey(c.SSHKey.PrivateKey)
	if err != nil {
		return nil, err
	}
	sshConfig := &ssh.ClientConfig{
		User: c.SSHUsername,
		Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
	}
	return sshConfig, nil
}
Ejemplo n.º 2
0
func testLockAgent(agent Agent, t *testing.T) {
	if err := agent.Add(testPrivateKeys["rsa"], nil, "comment 1"); err != nil {
		t.Errorf("Add: %v", err)
	}
	if err := agent.Add(testPrivateKeys["dsa"], nil, "comment dsa"); err != nil {
		t.Errorf("Add: %v", err)
	}
	if keys, err := agent.List(); err != nil {
		t.Errorf("List: %v", err)
	} else if len(keys) != 2 {
		t.Errorf("Want 2 keys, got %v", keys)
	}

	passphrase := []byte("secret")
	if err := agent.Lock(passphrase); err != nil {
		t.Errorf("Lock: %v", err)
	}

	if keys, err := agent.List(); err != nil {
		t.Errorf("List: %v", err)
	} else if len(keys) != 0 {
		t.Errorf("Want 0 keys, got %v", keys)
	}

	signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"])
	if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil {
		t.Fatalf("Sign did not fail")
	}

	if err := agent.Remove(signer.PublicKey()); err == nil {
		t.Fatalf("Remove did not fail")
	}

	if err := agent.RemoveAll(); err == nil {
		t.Fatalf("RemoveAll did not fail")
	}

	if err := agent.Unlock(nil); err == nil {
		t.Errorf("Unlock with wrong passphrase succeeded")
	}
	if err := agent.Unlock(passphrase); err != nil {
		t.Errorf("Unlock: %v", err)
	}

	if err := agent.Remove(signer.PublicKey()); err != nil {
		t.Fatalf("Remove: %v", err)
	}

	if keys, err := agent.List(); err != nil {
		t.Errorf("List: %v", err)
	} else if len(keys) != 1 {
		t.Errorf("Want 1 keys, got %v", keys)
	}
}
Ejemplo n.º 3
0
func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string) error {
	var req []byte
	switch k := s.(type) {
	case *rsa.PrivateKey:
		if len(k.Primes) != 2 {
			return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes))
		}
		k.Precompute()
		req = ssh.Marshal(rsaCertMsg{
			Type:      cert.Type(),
			CertBytes: cert.Marshal(),
			D:         k.D,
			Iqmp:      k.Precomputed.Qinv,
			P:         k.Primes[0],
			Q:         k.Primes[1],
			Comments:  comment,
		})
	case *dsa.PrivateKey:
		req = ssh.Marshal(dsaCertMsg{
			Type:      cert.Type(),
			CertBytes: cert.Marshal(),
			X:         k.X,
			Comments:  comment,
		})
	case *ecdsa.PrivateKey:
		req = ssh.Marshal(ecdsaCertMsg{
			Type:      cert.Type(),
			CertBytes: cert.Marshal(),
			D:         k.D,
			Comments:  comment,
		})
	default:
		return fmt.Errorf("agent: unsupported key type %T", s)
	}

	signer, err := ssh.NewSignerFromKey(s)
	if err != nil {
		return err
	}
	if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
		return errors.New("agent: signer and cert have different public key")
	}

	resp, err := c.call(req)
	if err != nil {
		return err
	}
	if _, ok := resp.(*successAgentMsg); ok {
		return nil
	}
	return errors.New("agent: failure")
}
Ejemplo n.º 4
0
func (p privateKeySigner) Decrypt() (ssh.Signer, error) {
	if p.key == nil {
		pem, err := x509.DecryptPEMBlock(p.pem, []byte(p.Passphrase()))
		if err != nil {
			return nil, err
		}
		p.key, err = x509.ParsePKCS1PrivateKey(pem)
		if err != nil {
			return nil, err
		}
		p.Encrypted = false
	}
	return ssh.NewSignerFromKey(p.key)
}
Ejemplo n.º 5
0
func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate) {
	signer, err := ssh.NewSignerFromKey(key)
	if err != nil {
		t.Fatalf("NewSignerFromKey(%T): %v", key, err)
	}
	// The agent should start up empty.
	if keys, err := agent.List(); err != nil {
		t.Fatalf("RequestIdentities: %v", err)
	} else if len(keys) > 0 {
		t.Fatalf("got %d keys, want 0: %v", len(keys), keys)
	}

	// Attempt to insert the key, with certificate if specified.
	var pubKey ssh.PublicKey
	if cert != nil {
		err = agent.Add(key, cert, "comment")
		pubKey = cert
	} else {
		err = agent.Add(key, nil, "comment")
		pubKey = signer.PublicKey()
	}
	if err != nil {
		t.Fatalf("insert(%T): %v", key, err)
	}

	// Did the key get inserted successfully?
	if keys, err := agent.List(); err != nil {
		t.Fatalf("List: %v", err)
	} else if len(keys) != 1 {
		t.Fatalf("got %v, want 1 key", keys)
	} else if keys[0].Comment != "comment" {
		t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment")
	} else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) {
		t.Fatalf("key mismatch")
	}

	// Can the agent make a valid signature?
	data := []byte("hello")
	sig, err := agent.Sign(pubKey, data)
	if err != nil {
		t.Fatalf("Sign(%s): %v", pubKey.Type(), err)
	}

	if err := pubKey.Verify(data, sig); err != nil {
		t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
	}
}
Ejemplo n.º 6
0
func (c *SSHCluster) importSSHKeyPair(t *TargetServer) error {
	var buf bytes.Buffer
	_, file, readFileErrChan := c.base.PromptFileInput(fmt.Sprintf("Please provide your private key for %s@%s", t.User, t.IP))
	if _, err := io.Copy(&buf, file); err != nil {
		readFileErrChan <- err
		return err
	}
	readFileErrChan <- nil // no error reading file
	b, _ := pem.Decode(buf.Bytes())
	if b == nil {
		return fmt.Errorf("Invalid private key")
	}
	var pemBytes []byte
	if x509.IsEncryptedPEMBlock(b) {
		passphrase := c.base.PromptProtectedInput("Please enter the passphrase for the key")
		var err error
		pemBytes, err = x509.DecryptPEMBlock(b, []byte(passphrase))
		if err != nil {
			return err
		}
	} else {
		pemBytes = b.Bytes
	}
	privateKey, err := x509.ParsePKCS1PrivateKey(pemBytes)
	if err != nil {
		return err
	}

	signer, err := ssh.NewSignerFromKey(privateKey)
	if err != nil {
		return err
	}
	auth := []ssh.AuthMethod{ssh.PublicKeys(signer)}

	sshConfig := c.sshConfigForAuth(t, auth)

	c.base.SendLog(fmt.Sprintf("Testing provided key for %s@%s", t.User, t.IP))
	if !c.testAndAddAuthentication(t, sshConfig) {
		return fmt.Errorf("Provided key for %s@%s failed to authenticate", t.User, t.IP)
	}
	c.base.SendLog(fmt.Sprintf("Key verified for %s@%s", t.User, t.IP))
	return nil
}
Ejemplo n.º 7
0
func init() {
	var err error

	n := len(testdata.PEMBytes)
	testPrivateKeys = make(map[string]interface{}, n)
	testSigners = make(map[string]ssh.Signer, n)
	testPublicKeys = make(map[string]ssh.PublicKey, n)
	for t, k := range testdata.PEMBytes {
		testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k)
		if err != nil {
			panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
		}
		testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t])
		if err != nil {
			panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
		}
		testPublicKeys[t] = testSigners[t].PublicKey()
	}

	// Create a cert and sign it for use in tests.
	testCert := &ssh.Certificate{
		Nonce:           []byte{},                       // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
		ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
		ValidAfter:      0,                              // unix epoch
		ValidBefore:     ssh.CertTimeInfinity,           // The end of currently representable time.
		Reserved:        []byte{},                       // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
		Key:             testPublicKeys["ecdsa"],
		SignatureKey:    testPublicKeys["rsa"],
		Permissions: ssh.Permissions{
			CriticalOptions: map[string]string{},
			Extensions:      map[string]string{},
		},
	}
	testCert.SignCert(rand.Reader, testSigners["rsa"])
	testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
	testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"])
	if err != nil {
		panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
	}
}
Ejemplo n.º 8
0
func addKey(conf *ssh.ServerConfig, block *pem.Block) (err error) {
	var key interface{}
	switch block.Type {
	case "RSA PRIVATE KEY":
		key, err = x509.ParsePKCS1PrivateKey(block.Bytes)
	case "EC PRIVATE KEY":
		key, err = x509.ParseECPrivateKey(block.Bytes)
	case "DSA PRIVATE KEY":
		key, err = ssh.ParseDSAPrivateKey(block.Bytes)
	default:
		return fmt.Errorf("unsupported key type %q", block.Type)
	}
	if err != nil {
		return err
	}
	signer, err := ssh.NewSignerFromKey(key)
	if err != nil {
		return err
	}
	conf.AddHostKey(signer)
	return nil
}
Ejemplo n.º 9
0
// Insert adds a private key to the keyring. If a certificate
// is given, that certificate is added as public key.
func (r *keyring) Add(priv interface{}, cert *ssh.Certificate, comment string) error {
	r.mu.Lock()
	defer r.mu.Unlock()
	if r.locked {
		return errLocked
	}
	signer, err := ssh.NewSignerFromKey(priv)

	if err != nil {
		return err
	}

	if cert != nil {
		signer, err = ssh.NewCertSigner(cert, signer)
		if err != nil {
			return err
		}
	}

	r.keys = append(r.keys, privKey{signer, comment})

	return nil
}
Ejemplo n.º 10
0
func (c *SSHCluster) findSSHAuth() error {
	c.base.SendLog("Detecting authentication")

	testAndAddAuthMethod := func(t *TargetServer, a ssh.AuthMethod) bool {
		sshConfig := c.sshConfigForAuth(t, []ssh.AuthMethod{a})
		if c.testAndAddAuthentication(t, sshConfig) {
			c.base.SendLog(fmt.Sprintf("Verified authentication for %s@%s", t.User, t.IP))
			return true
		}
		return false
	}

	testAndAddSigner := func(t *TargetServer, s ssh.Signer) bool {
		return testAndAddAuthMethod(t, ssh.PublicKeys(s))
	}

	testAllAuthenticated := func(targets []*TargetServer) bool {
		for _, t := range targets {
			if t.SSHConfig == nil {
				return false
			}
		}
		return true
	}

	sshAgent := c.sshAgent()
	sshAgentAuth := ssh.PublicKeysCallback(sshAgent.Signers)
	for _, t := range c.Targets {
		testAndAddAuthMethod(t, sshAgentAuth)
	}

	if testAllAuthenticated(c.Targets) {
		return nil
	}

	var agentKeys [][]byte
	if keys, err := sshAgent.List(); err == nil {
		agentKeys = make([][]byte, len(keys))
		for i, k := range keys {
			agentKeys[i] = k.Marshal()
		}
	}

	var signers []privateKeySigner

signerloop:
	for _, s := range c.findSSHKeySigners() {
		if s.publicKey != nil {
			for _, k := range agentKeys {
				if bytes.Equal(k, s.publicKey.Marshal()) {
					continue signerloop
				}
			}
		}
		signers = append(signers, s)
	}

outer:
	for _, t := range c.Targets {
		if t.SSHConfig != nil {
			continue
		}
		for _, s := range signers {
			if s.Encrypted {
				if s.publicKey == nil {
					signer, err := s.Decrypt()
					if err != nil {
						continue
					}
					if testAndAddSigner(t, signer) {
						continue outer
					}
				} else {
					if testAndAddSigner(t, s) {
						continue outer
					}
				}
			} else {
				signer, err := ssh.NewSignerFromKey(s.key)
				if err != nil {
					continue
				}
				if testAndAddSigner(t, signer) {
					continue outer
				}
			}
		}
	}

	for _, t := range c.Targets {
		if t.SSHConfig != nil {
			continue
		}
		answer, err := c.base.ChoicePrompt(Choice{
			Message: "No working authentication found.\nPlease choose one of the following options:",
			Options: []ChoiceOption{
				{
					Type:  1,
					Name:  "Private key",
					Value: "1",
				},
				{
					Name:  "Password",
					Value: "2",
				},
				{
					Name:  "Abort",
					Value: "3",
				},
			},
		})
		if err != nil {
			return err
		}
		switch answer {
		case "1":
			if err := c.importSSHKeyPair(t); err != nil {
				return err
			} else {
				continue
			}
		case "2":
			password := c.base.PromptProtectedInput(fmt.Sprintf("Please enter your password for %s@%s", t.User, t.IP))
			if testAndAddAuthMethod(t, ssh.Password(password)) {
				continue
			}
		}
		return fmt.Errorf("No working authentication found")
	}
	return nil
}