예제 #1
0
func newTestServer() (Server, error) {

	// Create a new backend object.
	b := redis.New("test", "tcp", "127.0.0.1:6379")

	// Create a new crypter.
	c, err := crypto.NewRandomCrypter()
	if err != nil {
		return nil, err
	}

	private, _ := ssh.ParsePrivateKey(ServerTestPrivateKey)
	if err != nil {
		return nil, err
	}

	s := NewServer(b, c, private)

	for _, publicKey := range ServerTestPublicKeys {
		publicKeyParsed, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKey))
		if err != nil {
			return s, err
		}

		s.AddReadKey(publicKeyParsed)
		s.AddWriteKey(publicKeyParsed)
	}

	return s, nil
}
예제 #2
0
func ReadUserAuthKeys(u string) (publicKeys []ssh.PublicKey, err error) {
	uacc, err := user.Lookup(u)
	if err != nil {
		return
	}

	b, err := ioutil.ReadFile(path.Join(uacc.HomeDir, ".ssh/authorized_keys"))
	if err != nil {
		return
	}

	buf := bytes.NewBuffer(b)
	for {
		line, err := buf.ReadBytes('\n')
		if err == io.EOF {
			break
		}
		if err != nil {
			return nil, err
		}

		if strings.HasPrefix(string(line), "#") {
			continue
		}

		publicKey, _, _, _, err := ssh.ParseAuthorizedKey(line)
		if err != nil {
			return nil, err
		}
		publicKeys = append(publicKeys, publicKey)
	}
	return
}
예제 #3
0
파일: base.go 프로젝트: wkhunter/sshproxy
func CheckHostKey(HostKey string) (checkHostKey func(string, net.Addr, ssh.PublicKey) error) {
	var err error
	var public ssh.PublicKey
	var publices []ssh.PublicKey
	rest := []byte(HostKey)
	for {
		public, _, _, rest, err = ssh.ParseAuthorizedKey(rest)
		if err != nil {
			err = nil
			break
		}
		publices = append(publices, public)
	}

	checkHostKey = func(hostname string, remote net.Addr, key ssh.PublicKey) (err error) {
		hostkey := key.Marshal()
		log.Debug("remote hostkey: %s, type: %s", hostname, key.Type())

		for _, public := range publices {
			if key.Type() == public.Type() && bytes.Compare(hostkey, public.Marshal()) == 0 {
				log.Info("host key match: %s", hostname)
				return nil
			}
		}
		log.Info("host key not match: %s", hostname)
		return ErrHostKey
	}
	return
}
예제 #4
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))
	}
}
예제 #5
0
func TestSSHFingerprint(t *testing.T) {
	Convey("Test generating SSH fingerprint", t, func() {
		pubkey, _, _, _, err := ssh.ParseAuthorizedKey([]byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXg9Vmhy9YSB8BcN3yHgQjdX9lN3j2KRpv7kVDXSiIana2WbKP7IiTS0uJcJWUM3vlHjdL9KOO0jCWWzVFIcmLhiVVG+Fy2tothBp/NhjR8WWG/6Jg/6tXvVkLG6bDgfbDaLWdE5xzjL0YG8TrIluqnu0J5GHKrQcXF650PlqkGo+whpXrS8wOG+eUmsHX9L1w/Z3TkQlMjQNJEoRbqqSrp7yGj4JqzbtLpsglPRlobD7LHp+5ZDxzpk9i+6hoMxp2muDFxnEtZyED6IMQlNNEGkc3sdmGPOo26oW2+ePkBcjpOpdVif/Iya/jDLuLFHAOol6G34Tr4IdTgaL0qCCr TEST KEY"))
		panic_the_err(err)
		fingerprint := SSHFingerprint(pubkey)
		So(fingerprint, ShouldEqual, "c0:61:84:fc:e8:c9:52:dc:cd:a9:8e:82:a2:70:0a:30")
	})
}
예제 #6
0
func TestEncode(t *testing.T) {
	Convey("Test Encode A String", t, func() {
		pubkey, _, _, _, err := ssh.ParseAuthorizedKey([]byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXg9Vmhy9YSB8BcN3yHgQjdX9lN3j2KRpv7kVDXSiIana2WbKP7IiTS0uJcJWUM3vlHjdL9KOO0jCWWzVFIcmLhiVVG+Fy2tothBp/NhjR8WWG/6Jg/6tXvVkLG6bDgfbDaLWdE5xzjL0YG8TrIluqnu0J5GHKrQcXF650PlqkGo+whpXrS8wOG+eUmsHX9L1w/Z3TkQlMjQNJEoRbqqSrp7yGj4JqzbtLpsglPRlobD7LHp+5ZDxzpk9i+6hoMxp2muDFxnEtZyED6IMQlNNEGkc3sdmGPOo26oW2+ePkBcjpOpdVif/Iya/jDLuLFHAOol6G34Tr4IdTgaL0qCCr TEST KEY"))
		panic_the_err(err)
		plaintext := "some plaintext"
		ciphertext, err := CredulousEncode(plaintext, pubkey)
		So(err, ShouldEqual, nil)
		So(len(ciphertext), ShouldEqual, 556)
	})
}
예제 #7
0
// ParseAuthorisedKey parses a non-comment line from an
// authorized_keys file and returns the constituent parts.
// Based on description in "man sshd".
func ParseAuthorisedKey(line string) (*AuthorisedKey, error) {
	key, comment, _, _, ok := ssh.ParseAuthorizedKey([]byte(line))
	if !ok {
		return nil, fmt.Errorf("invalid authorized_key %q", line)
	}
	keyBytes := ssh.MarshalPublicKey(key)
	return &AuthorisedKey{
		Key:     keyBytes,
		Comment: comment,
	}, nil
}
예제 #8
0
// ParseAuthorisedKey parses a non-comment line from an
// authorized_keys file and returns the constituent parts.
// Based on description in "man sshd".
func ParseAuthorisedKey(line string) (*AuthorisedKey, error) {
	key, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(line))
	if err != nil {
		return nil, fmt.Errorf("invalid authorized_key %q", line)
	}
	return &AuthorisedKey{
		Type:    key.Type(),
		Key:     key.Marshal(),
		Comment: comment,
	}, nil
}
예제 #9
0
func readSSHPubkeyFile(filename string) (pubkey ssh.PublicKey, err error) {
	pubkeyString, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	pubkey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(pubkeyString))
	if err != nil {
		return nil, err
	}
	return pubkey, nil
}
예제 #10
0
func newKey(name, user, raw string) (*Key, error) {
	key, comment, _, _, ok := ssh.ParseAuthorizedKey([]byte(raw))
	if !ok {
		return nil, ErrInvalidKey
	}
	body := ssh.MarshalAuthorizedKey(key)
	k := Key{
		Name:     name,
		Body:     string(body),
		Comment:  comment,
		UserName: user,
	}
	return &k, nil
}
예제 #11
0
func newKey(name, user, raw string) (*Key, error) {
	key, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(raw))
	if err != nil {
		return nil, ErrInvalidKey
	}
	body := ssh.MarshalAuthorizedKey(key.(ssh.PublicKey))
	k := Key{
		Name:      name,
		Body:      string(body),
		Comment:   comment,
		UserName:  user,
		CreatedAt: time.Now(),
	}
	return &k, nil
}
예제 #12
0
파일: keys_test.go 프로젝트: Jyggafey/drone
func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []authResult) {
	rest := authKeys
	var values []authResult
	for len(rest) > 0 {
		var r authResult
		r.pubKey, r.comments, r.options, rest, r.ok = ssh.ParseAuthorizedKey(rest)
		r.rest = string(rest)
		values = append(values, r)
	}

	if !reflect.DeepEqual(values, expected) {
		t.Errorf("got %q, expected %q", values, expected)
	}

}
예제 #13
0
// TestHostKeyChecker tests to check existing key
func TestHostKeyChecker(t *testing.T) {
	keyFile := NewHostKeyFile(hostFile)
	checker := NewHostKeyChecker(keyFile)

	addr, key, _ := parseKnownHostsLine([]byte(hostLine))
	tcpAddr, _ := net.ResolveTCPAddr("tcp", addr)

	if err := checker.Check("localhost", tcpAddr, key); err != nil {
		t.Fatalf("checker should succeed for %v: %v", tcpAddr.String(), err)
	}

	wrongKey, _, _, _, _ := gossh.ParseAuthorizedKey([]byte(wrongAuthorizedKey))
	if err := checker.Check("localhost", tcpAddr, wrongKey); err != ErrUnmatchKey {
		t.Fatalf("checker should fail with %v", ErrUnmatchKey)
	}
}
예제 #14
0
func serverFetchPublicKeys(url string) ([]ssh.PublicKey, error) {

	// Fetch the public keys.
	response, err := serverClient.Get(url)
	if err != nil {
		return nil, err
	}

	// Read out the entire body.
	jsonResponse, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	// Build a raw keys object that reflects the expected structure of the JSON.
	var rawKeys []struct {
		Key string
	}

	// Try to parse the body of the response as JSON.
	if err := json.Unmarshal(jsonResponse, &rawKeys); err != nil {
		return nil, err
	}

	// Build a new authorizer and iterate through the raw keys, parsing them
	// and then adding them.
	publicKeys := make([]ssh.PublicKey, 0, len(rawKeys))
	for _, rawKey := range rawKeys {

		// We're only interested in the key itself and whether or not there was an error.
		publicKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(rawKey.Key))
		if err != nil {
			return publicKeys, err
		}

		// Add the key to the list.
		publicKeys = publicKeys[:len(publicKeys)+1]
		publicKeys[len(publicKeys)-1] = publicKey
	}

	return publicKeys, nil
}
예제 #15
0
파일: keys.go 프로젝트: pancakeio/pk
// Read SSH public key bytes from path
func sshReadPubKey(path string) (ssh.PublicKey, string, error) {
	f, err := os.Open(filepath.FromSlash(path))
	if err != nil {
		return nil, "", err
	}

	keyBytes, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, "", err
	}

	if bytes.Contains(keyBytes, []byte("PRIVATE")) {
		return nil, "", errPrivKey(path)
	}

	key, comment, _, _, ok := ssh.ParseAuthorizedKey(keyBytes)
	if !ok {
		return nil, "", errNotKey
	}

	return key, comment, nil
}
예제 #16
0
func TestMarshalParsePublicKey(t *testing.T) {
	pub := getTestPublicKey(t)
	authKeys := ssh.MarshalAuthorizedKey(pub)
	actualFields := strings.Fields(string(authKeys))
	if len(actualFields) == 0 {
		t.Fatalf("failed authKeys: %v", authKeys)
	}

	// drop the comment
	expectedFields := strings.Fields(keys["authorized_keys"])[0:2]

	if !reflect.DeepEqual(actualFields, expectedFields) {
		t.Errorf("got %v, expected %v", actualFields, expectedFields)
	}

	actPub, _, _, _, ok := ssh.ParseAuthorizedKey([]byte(keys["authorized_keys"]))
	if !ok {
		t.Fatalf("cannot parse %v", keys["authorized_keys"])
	}
	if !reflect.DeepEqual(actPub, pub) {
		t.Errorf("got %v, expected %v", actPub, pub)
	}
}
예제 #17
0
파일: keys.go 프로젝트: pancakeio/pk
// Find SSH keys on the local file system
func getSSHKeys(existingKeyFingerprints map[string]bool) map[string]string {
	candidateKeys := make(map[string]string)

	// get key from id_rsa.pub
	rsaKey, rsaComment, rsaErr := sshReadPubKey(idRsaPubPath)
	if rsaErr == nil {
		candidateKeys[string(ssh.MarshalPublicKey(rsaKey))] = rsaComment
	}

	// get key from id_dsa.pub
	dsaKey, dsaComment, dsaErr := sshReadPubKey(idDsaPubPath)
	if dsaErr == nil {
		candidateKeys[string(ssh.MarshalPublicKey(dsaKey))] = dsaComment
	}

	// get keys from ssh-add
	out, err := exec.Command("ssh-add", "-L").Output()
	sshAddKeys := strings.TrimSpace(string(out))
	if err == nil && sshAddKeys != "" {
		for _, k := range strings.Split(sshAddKeys, "\n") {
			key, comment, _, _, ok := ssh.ParseAuthorizedKey([]byte(k))
			if ok {
				candidateKeys[string(ssh.MarshalPublicKey(key))] = comment
			}
		}
	}

	for k, _ := range candidateKeys {
		pubKey, _, _ := ssh.ParsePublicKey([]byte(k))
		fp := fingerprint(pubKey)
		if _, ok := existingKeyFingerprints[fp]; ok {
			delete(candidateKeys, k)
		}
	}

	return candidateKeys
}
예제 #18
0
파일: known_hosts.go 프로젝트: Blystad/deis
// parseKnownHostsLine parses a line from a known hosts file.  It returns a
// string containing the hosts section of the line, a gossh.PublicKey parsed
// from the line, and any error encountered during the parsing.
func parseKnownHostsLine(line []byte) (string, gossh.PublicKey, error) {

	// Skip any leading whitespace.
	line = bytes.TrimLeft(line, "\t ")

	// Skip comments and empty lines.
	if bytes.HasPrefix(line, []byte("#")) || len(line) == 0 {
		return "", nil, nil
	}

	// Skip markers.
	if bytes.HasPrefix(line, []byte("@")) {
		return "", nil, errors.New("marker functionality not implemented")
	}

	// Find the end of the host name(s) portion.
	end := bytes.IndexAny(line, "\t ")
	if end <= 0 {
		return "", nil, errors.New("bad format (insufficient fields)")
	}
	hosts := string(line[:end])
	keyBytes := line[end+1:]

	// Check for hashed host names.
	if strings.HasPrefix(hosts, sshHashDelim) {
		return "", nil, errors.New("hashed hosts not implemented")
	}

	// Finally, actually try to extract the key.
	key, _, _, _, err := gossh.ParseAuthorizedKey(keyBytes)
	if err != nil {
		return "", nil, fmt.Errorf("error parsing key: %v", err)
	}

	return hosts, key, nil
}
예제 #19
0
func main() {
	usage := `Authorized Keys.

Usage:
  authorized-keys <user> [--force-server=<server>] [--test]
  authorized-keys -h | --help
  authorized-keys -v | --version

Options:
  -h --help                Show this screen.
  -v --version             Show version.
  --force-server=<server>  Force server name.
  --test                  Test mode - no logging, just print users and key fingerprints.
`
	arguments, err := docopt.Parse(usage, nil, true, "Authorized Keys build "+builddate, false)

	if err != nil {
		initError(usage, 2)
	}

	var test = false
	if arguments["--test"] == true {
		test = true
	}

	if arguments["<user>"] == nil {
		initError("No user defined", 3)
	}

	// Load config file
	const configfile = "/usr/local/etc/authorized-keys.conf"
	configsource, err := ioutil.ReadFile(configfile)
	config := configData{}
	if err != nil {
		os.Stderr.WriteString("Error opening config file " + configfile + ", using defaults\n")
		programDir := filepath.Dir(os.Args[0])
		config.Data = programDir + "/authorized-keys.yaml"
		config.Log = programDir + "/authorized-keys.log"
	} else {
		err = yaml.Unmarshal(configsource, &config)
		if err != nil {
			initError(err.Error(), 4)
		}
	}

	// Open log file
	if !test {
		l, err := os.OpenFile(config.Log, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0660)
		if err != nil {
			initError("error opening log file: '"+config.Log+"'"+err.Error(), 5)
		}
		defer l.Close()
		log.SetOutput(io.MultiWriter(l, os.Stderr))
	} else {
		log.SetOutput(os.Stderr)
	}

	// Username
	username := fmt.Sprintf("%s", arguments["<user>"])
	if !safestring(username) {
		log.Fatalln("User '" + username + "' is not safe string")
	}

	// Hostname (server name)
	var hostname string
	if arguments["--force-server"] == nil {
		hostname, _ = os.Hostname()
	} else {
		hostname = fmt.Sprintf("%s", arguments["--force-server"])
	}

	if !safestring(hostname) {
		log.Fatalln("Host '" + hostname + "' is not safe string")
	}

	// Data file
	source, err := ioutil.ReadFile(config.Data)
	if err != nil {
		initError("Can't read data file "+config.Data, 5)
	}
	authorizedKeys := authorizedKeys{}
	err = yaml.Unmarshal(source, &authorizedKeys)
	if err != nil {
		initError("Cannot parse yaml file "+err.Error(), 6)
	}

	// Debug
	log.Println("Requested authorized_keys for server '" + hostname + "' and user '" + username + "'")

	// Find server/user
	_, ok := authorizedKeys.Access[hostname][username]
	if !ok {
		log.Fatalln("Server '" + hostname + "' not found")
	}

	// Find aliases for server/user
	users, ok := authorizedKeys.Access[hostname][username]
	if !ok {
		log.Fatalln("No users found")
	}

	// Find all keys for aliases
	var keys []string
	for _, user := range users {
		k, ok := authorizedKeys.Users[user]["keys"]
		if !ok {
			log.Fatalln("User '" + user + "' doesn't have any keys defined")
		}
		// Validate and append each key
		for index, key := range k {
			publickey, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(key))

			if err == nil {
				keys = append(keys, key)
				if test {
					fingerprint := fmt.Sprintf("%x", md5.Sum(publickey.Marshal()))
					log.Printf("Using key %q for user %q. Fingerprint: %s", comment, user, formatFingerPrint(fingerprint))
				} else {
					log.Printf("Using key %q for user %q", comment, user)
				}

			} else {
				log.Printf("Skipping key %d for user %q", index, user)
			}
		}
	}

	// Output for sshd
	if !test {
		os.Stdout.WriteString(strings.Join(keys, "\n"))
	}
}
예제 #20
0
파일: keys_test.go 프로젝트: Jyggafey/drone
func TestInvalidEntry(t *testing.T) {
	_, _, _, _, ok := ssh.ParseAuthorizedKey(authInvalid)
	if ok {
		t.Errorf("Expected invalid entry, returned valid entry")
	}
}