Beispiel #1
0
func TestAgentForward(t *testing.T) {
	server := newServer(t)
	defer server.Shutdown()
	conn := server.Dial(clientConfig())
	defer conn.Close()

	keyring := agent.NewKeyring()
	keyring.Add(testPrivateKeys["dsa"], nil, "")
	pub := testPublicKeys["dsa"]

	sess, err := conn.NewSession()
	if err != nil {
		t.Fatalf("NewSession: %v", err)
	}
	if err := agent.RequestAgentForwarding(sess); err != nil {
		t.Fatalf("RequestAgentForwarding: %v", err)
	}

	if err := agent.ForwardToAgent(conn, keyring); err != nil {
		t.Fatalf("SetupForwardKeyring: %v", err)
	}
	out, err := sess.CombinedOutput("ssh-add -L")
	if err != nil {
		t.Fatalf("running ssh-add: %v, out %s", err, out)
	}
	key, _, _, _, err := ssh.ParseAuthorizedKey(out)
	if err != nil {
		t.Fatalf("ParseAuthorizedKey(%q): %v", out, err)
	}

	if !bytes.Equal(key.Marshal(), pub.Marshal()) {
		t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub))
	}
}
Beispiel #2
0
func (S) TestPatterns(c *C) {
	const sep = " "
	var input bytes.Buffer

	key := genPublicKey(c)
	keyBytes := bytes.TrimRight(bytes.TrimSpace(ssh.MarshalAuthorizedKey(key)), "\n")

	// format: pattern
	input.WriteString("*.example")
	input.WriteString(sep)
	input.Write(keyBytes)
	input.WriteString("\n")

	// format: negated pattern
	input.WriteString("!*.example.or?")
	input.WriteString(sep)
	input.Write(keyBytes)
	input.WriteString("\n")

	k, err := Unmarshal(bytes.NewReader(input.Bytes()))
	c.Assert(err, IsNil)

	// Test HostKeyCallback
	addr := &net.TCPAddr{
		Port: 22,
	}
	c.Assert(k.HostKeyCallback("foo.example:22", addr, key), IsNil)                         // pattern match
	c.Assert(k.HostKeyCallback("foo.example.org:22", addr, key), Equals, HostNotFoundError) // negated pattern match
	c.Assert(k.HostKeyCallback("anything.example.com:22", addr, key), IsNil)                // negated pattern miss

	// Make sure output is the same as input
	var output bytes.Buffer
	c.Assert(k.Marshal(&output), IsNil)
	c.Assert(output.String(), Equals, input.String())
}
Beispiel #3
0
func checkAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	status, err := exitStatus(exec.Command(authChecker[0],
		append(authChecker[1:], conn.User(), string(bytes.TrimSpace(ssh.MarshalAuthorizedKey(key))))...).Run())
	if err != nil {
		return nil, err
	}
	if status.Status == 0 {
		return nil, nil
	}
	return nil, ErrUnauthorized
}
Beispiel #4
0
func genSSHKey() (*sshData, error) {
	keyFile, err := ioutil.TempFile("", "")
	if err != nil {
		return nil, err

	}
	defer keyFile.Close()
	rsaKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}
	pem.Encode(keyFile, &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: x509.MarshalPKCS1PrivateKey(rsaKey),
	})

	pubFile, err := ioutil.TempFile("", "")
	if err != nil {
		return nil, err
	}
	defer pubFile.Close()
	rsaPubKey, err := ssh.NewPublicKey(&rsaKey.PublicKey)
	if err != nil {
		return nil, err
	}
	if _, err := pubFile.Write(ssh.MarshalAuthorizedKey(rsaPubKey)); err != nil {
		return nil, err
	}

	wrapperFile, err := ioutil.TempFile("", "")
	if err != nil {
		return nil, err
	}
	defer wrapperFile.Close()
	if err := sshWrapper.Execute(wrapperFile, map[string]string{"SSHKey": keyFile.Name()}); err != nil {
		return nil, err
	}
	if err := wrapperFile.Chmod(0700); err != nil {
		return nil, err
	}

	return &sshData{
		Key: keyFile.Name(),
		Pub: pubFile.Name(),
		Env: []string{"GIT_SSH=" + wrapperFile.Name()},
		Cleanup: func() {
			os.RemoveAll(keyFile.Name())
			os.RemoveAll(pubFile.Name())
			os.RemoveAll(wrapperFile.Name())
		},
	}, nil
}
func (a *GenSSHKeyAction) Run(s *State) error {
	data := &SSHKey{}
	s.StepData[a.ID] = data

	var pemBuf bytes.Buffer

	rsaKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return err
	}
	pem.Encode(&pemBuf, &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: x509.MarshalPKCS1PrivateKey(rsaKey),
	})
	rsaPubKey, err := ssh.NewPublicKey(&rsaKey.PublicKey)
	if err != nil {
		return err
	}
	data.RSAPublic = string(bytes.TrimSpace(ssh.MarshalAuthorizedKey(rsaPubKey)))

	ecKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		return err
	}
	ecBytes, err := x509.MarshalECPrivateKey(ecKey)
	if err != nil {
		return err
	}
	pem.Encode(&pemBuf, &pem.Block{Type: "EC PRIVATE KEY", Bytes: ecBytes})
	ecPubKey, err := ssh.NewPublicKey(&ecKey.PublicKey)
	if err != nil {
		return err
	}
	data.ECDSAPublic = string(bytes.TrimSpace(ssh.MarshalAuthorizedKey(ecPubKey)))

	data.PrivateKeys = pemBuf.String()

	return nil
}
Beispiel #6
0
func checkAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	cmd := exec.Command(*authChecker,
		conn.User(),
		string(bytes.TrimSpace(ssh.MarshalAuthorizedKey(key))),
	)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	status, err := exitStatus(cmd.Run())
	if err != nil {
		return nil, err
	}
	if status.Status == 0 {
		return nil, nil
	}
	return nil, ErrUnauthorized
}
Beispiel #7
0
// This generates a single RSA 2048-bit SSH key
func Generate() (*SSHKey, error) {
	data := &SSHKey{}

	rsaKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}
	var pemBuf bytes.Buffer
	pem.Encode(&pemBuf, &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: x509.MarshalPKCS1PrivateKey(rsaKey),
	})
	rsaPubKey, err := ssh.NewPublicKey(&rsaKey.PublicKey)
	if err != nil {
		return nil, err
	}
	data.PublicKey = bytes.TrimSpace(ssh.MarshalAuthorizedKey(rsaPubKey))
	data.PrivateKey = rsaKey

	return data, nil
}
Beispiel #8
0
func (r *KeyRepo) Add(data interface{}) error {
	key := data.(*ct.Key)

	if key.Key == "" {
		return errors.New("controller: key must not be blank")
	}

	pubKey, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(key.Key))
	if err != nil {
		return err
	}

	key.ID = fingerprintKey(pubKey.Marshal())
	key.Key = string(bytes.TrimSpace(ssh.MarshalAuthorizedKey(pubKey)))
	key.Comment = comment

	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	err = tx.QueryRow("INSERT INTO keys (fingerprint, key, comment) VALUES ($1, $2, $3) RETURNING created_at", key.ID, key.Key, key.Comment).Scan(&key.CreatedAt)
	if postgres.IsUniquenessError(err, "") {
		tx.Rollback()
		return nil
	}
	if err != nil {
		tx.Rollback()
		return err
	}
	if err := createEvent(tx.Exec, &ct.Event{
		ObjectID:   key.ID,
		ObjectType: ct.EventTypeKey,
	}, key); err != nil {
		tx.Rollback()
		return err
	}
	return tx.Commit()
}
Beispiel #9
0
func (r *KeyRepo) Add(data interface{}) error {
	key := data.(*ct.Key)

	if key.Key == "" {
		return errors.New("controller: key must not be blank")
	}

	pubKey, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(key.Key))
	if err != nil {
		return err
	}

	key.ID = fingerprintKey(pubKey.Marshal())
	key.Key = string(bytes.TrimSpace(ssh.MarshalAuthorizedKey(pubKey)))
	key.Comment = comment

	err = r.db.QueryRow("INSERT INTO keys (fingerprint, key, comment) VALUES ($1, $2, $3) RETURNING created_at", key.ID, key.Key, key.Comment).Scan(&key.CreatedAt)
	if e, ok := err.(*pq.Error); ok && e.Code.Name() == "unique_violation" {
		return nil
	}
	return err
}
Beispiel #10
0
func (l *Line) Marshal() ([]byte, error) {
	const sep = " "
	var buf bytes.Buffer

	// flag part
	var flag string
	if l.Revoked {
		flag = "revoked"
	}
	if l.CertAuthority {
		flag = "cert-authority"
	}
	if flag != "" {
		fmt.Fprintf(&buf, "@%s", flag)
		buf.WriteString(sep)
	}

	// hosts part
	for i, h := range l.Hosts {
		if h.Hash != nil && (i != 0 || len(l.Hosts) > 1) {
			return nil, fmt.Errorf("knownhosts: Hashed host must be only host on line, found %d!", len(l.Hosts))
		}
		if b := h.Marshal(); b != nil {
			buf.Write(b)
		} else {
			return nil, fmt.Errorf("knownhosts: Invalid host: %#v", h)
		}
		if i != len(l.Hosts)-1 {
			buf.WriteString(",")
		}
	}
	buf.WriteString(sep)

	// key part (has trailing newline)
	buf.Write(ssh.MarshalAuthorizedKey(l.PublicKey))

	return buf.Bytes(), nil
}
Beispiel #11
0
func (S) TestComments(c *C) {
	const sep = " "
	var input bytes.Buffer

	key := genPublicKey(c)
	keyBytes := bytes.TrimRight(bytes.TrimSpace(ssh.MarshalAuthorizedKey(key)), "\n")

	// commented out host
	host1Addr := "101.102.103.72"
	input.WriteString("# ")
	input.WriteString(host1Addr)
	input.WriteString(sep)
	input.Write(keyBytes)
	input.WriteString("\n")

	k, err := Unmarshal(&input)
	c.Assert(err, IsNil)

	// Test HostKeyCallback
	addr := &net.TCPAddr{
		Port: 22,
	}
	c.Assert(k.HostKeyCallback(host1Addr+":22", addr, key), Equals, HostNotFoundError)
}
Beispiel #12
0
// newServer returns a new mock ssh server.
func newServer(t *testing.T) *server {
	if testing.Short() {
		t.Skip("skipping test due to -short")
	}
	dir, err := ioutil.TempDir("", "sshtest")
	if err != nil {
		t.Fatal(err)
	}
	f, err := os.Create(filepath.Join(dir, "sshd_config"))
	if err != nil {
		t.Fatal(err)
	}
	err = configTmpl.Execute(f, map[string]string{
		"Dir": dir,
	})
	if err != nil {
		t.Fatal(err)
	}
	f.Close()

	for k, v := range testdata.PEMBytes {
		filename := "id_" + k
		writeFile(filepath.Join(dir, filename), v)
		writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k]))
	}

	return &server{
		t:          t,
		configfile: f.Name(),
		cleanup: func() {
			if err := os.RemoveAll(dir); err != nil {
				t.Error(err)
			}
		},
	}
}
Beispiel #13
0
func (S) TestNonPatterns(c *C) {
	const sep = " "
	var input bytes.Buffer

	key := genPublicKey(c)
	keyBytes := bytes.TrimRight(bytes.TrimSpace(ssh.MarshalAuthorizedKey(key)), "\n")

	// format: host key
	host1Addr := "101.102.103.72"
	input.WriteString(host1Addr)
	input.WriteString(sep)
	input.Write(keyBytes)
	input.WriteString("\n")

	// format: host key
	host2Addr := "test.example.com"
	input.WriteString(host2Addr)
	input.WriteString(sep)
	input.Write(keyBytes)
	input.WriteString("\n")

	// format: @flag [host]:port key
	host3Addr := "3.example.com"
	host3Port := "2222"
	input.WriteString("@revoked")
	input.WriteString(sep)
	input.WriteString("[" + host3Addr + "]:" + host3Port)
	input.WriteString(sep)
	input.Write(keyBytes)
	input.WriteString("\n")

	// format: host,host,host key
	host4Addr := "4.example.com"
	host5Addr := "102.101.72.100"
	host6Addr := "6.example.com"
	input.WriteString(strings.Join([]string{host4Addr, host5Addr, host6Addr}, ","))
	input.WriteString(sep)
	input.Write(keyBytes)
	input.WriteString("\n")

	// format: host,[host]:port,host key
	host7Addr := "7.example.com"
	host8Addr := "102.101.72.100"
	host8Port := "2223"
	host9Addr := "9.example.com"
	input.WriteString(strings.Join([]string{host7Addr, "[" + host8Addr + "]:" + host8Port, host9Addr}, ","))
	input.WriteString(sep)
	input.Write(keyBytes)
	input.WriteString("\n")

	// format: @flag host,host key
	host10Addr := "10.example.com"
	host11Addr := "11.example.com"
	input.WriteString("@revoked")
	input.WriteString(sep)
	input.WriteString(strings.Join([]string{host10Addr, host11Addr}, ","))
	input.WriteString(sep)
	input.Write(keyBytes)
	input.WriteString("\n")

	// format: hashed
	host12Addr := "12.example.com"
	host12Salt := random.Bytes(16)
	host12SaltEncoded := base64.StdEncoding.EncodeToString(host12Salt)
	host12Mac := hmac.New(sha1.New, host12Salt)
	host12Mac.Write([]byte(host12Addr))
	host12MacEncoded := base64.StdEncoding.EncodeToString(host12Mac.Sum(nil))
	input.WriteString("|1|" + host12SaltEncoded + "|" + host12MacEncoded)
	input.WriteString(sep)
	input.Write(keyBytes)
	input.WriteString("\n")

	k, err := Unmarshal(bytes.NewReader(input.Bytes()))
	c.Assert(err, IsNil)

	// Test HostKeyCallback
	addr := &net.TCPAddr{
		Port: 22,
	}
	c.Assert(k.HostKeyCallback(host1Addr+":22", addr, key), IsNil)
	c.Assert(k.HostKeyCallback(host2Addr+":22", addr, key), IsNil)
	c.Assert(k.HostKeyCallback(host3Addr+":2222", &net.TCPAddr{Port: 2222}, key), Equals, HostRevokedError)
	c.Assert(k.HostKeyCallback(host4Addr+":22", addr, key), IsNil)
	c.Assert(k.HostKeyCallback(host5Addr+":22", addr, key), IsNil)
	c.Assert(k.HostKeyCallback(host6Addr+":22", addr, key), IsNil)
	c.Assert(k.HostKeyCallback(host7Addr+":22", addr, key), IsNil)
	c.Assert(k.HostKeyCallback(host8Addr+":2223", &net.TCPAddr{Port: 2223}, key), IsNil)
	c.Assert(k.HostKeyCallback(host9Addr+":22", addr, key), IsNil)
	c.Assert(k.HostKeyCallback(host10Addr+":22", addr, key), Equals, HostRevokedError)
	c.Assert(k.HostKeyCallback(host11Addr+":22", addr, key), Equals, HostRevokedError)
	c.Assert(k.HostKeyCallback("notfound.example.com:22", addr, key), Equals, HostNotFoundError)
	c.Assert(k.HostKeyCallback(host3Addr+":2223", &net.TCPAddr{Port: 2223}, key), Equals, HostNotFoundError)
	c.Assert(k.HostKeyCallback(host1Addr+":2222", &net.TCPAddr{Port: 2222}, key), Equals, HostNotFoundError)
	c.Assert(k.HostKeyCallback(host12Addr+":22", addr, key), IsNil) // hash match

	// Make sure output is the same as input
	var output bytes.Buffer
	c.Assert(k.Marshal(&output), IsNil)
	c.Assert(output.String(), Equals, input.String())

	// Test AppendHost with Writer
	var output2 bytes.Buffer
	var input2 bytes.Buffer
	c.Assert(k.AppendHost("new1.example.com:2223", key, &output2), IsNil)
	input2.WriteString("[new1.example.com]:2223")
	input2.WriteString(sep)
	input2.Write(keyBytes)
	input2.WriteString("\n")
	input.Write(input2.Bytes())
	c.Assert(output2.String(), Equals, input2.String())

	// Test AppendHost without Writer
	c.Assert(k.AppendHost("new2.example.com:22", key, nil), IsNil)
	input.WriteString("new2.example.com")
	input.WriteString(sep)
	input.Write(keyBytes)
	input.WriteString("\n")
	output.Reset()
	c.Assert(k.Marshal(&output), IsNil)
	c.Assert(output.String(), Equals, input.String())
}