// remoteCmdOutput runs the given command on a remote server at the given hostname as the given user. func remoteCmdOutput(username, hostname, cmd string, privateKey []byte) (b []byte, err error) { p, err := ssh.ParseRawPrivateKey(privateKey) if err != nil { return b, err } s, err := ssh.NewSignerFromKey(p) if err != nil { return b, err } pub := ssh.PublicKeys(s) clientConfig := &ssh.ClientConfig{ User: username, Auth: []ssh.AuthMethod{pub}, } client, err := ssh.Dial("tcp", hostname, clientConfig) if err != nil { return b, errors.New("ERROR: Failed to dial: " + err.Error()) } defer client.Close() session, err := client.NewSession() if err != nil { return b, errors.New("ERROR: Failed to create session: " + err.Error()) } defer session.Close() b, err = session.Output(cmd) if err != nil { return b, fmt.Errorf("ERROR: Failed to run cmd on host %s: %s", hostname, err.Error()) } return b, nil }
func makeSigner(keyname string) (signer ssh.Signer, err error) { fp, err := os.Open(keyname) if err != nil { return } defer fp.Close() buf, err := ioutil.ReadAll(fp) if err != nil { panic(err) return } key, err := ssh.ParseRawPrivateKey(buf) if err != nil { panic(err) return } signer, err = ssh.NewSignerFromKey(key) if err != nil { panic(err) return } return }
// addKey parses an SSH private key for execd. It takes in the SSH server configuration and the key to add. // It returns an error if the key is unsupported by execd. 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 }
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) } }
// GenerateKey generates a new ECDSA keypair suitable for use // as an ssh host key. // It can be passed as a parameter to ssh.ServerConfig.AddHostKey func GenerateKey() (ssh.Signer, error) { pk, err := libtrust.GenerateECP521PrivateKey() if err != nil { return nil, err } s, err := ssh.NewSignerFromKey(pk.CryptoPrivateKey()) if err != nil { return nil, err } return s, nil }
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") }
func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate) { signer, err := ssh.NewSignerFromKey(key) if err != nil { t.Fatalf("NewSignerFromKey: %v", 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: %v", 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: %v", err) } if err := pubKey.Verify(data, sig); err != nil { t.Fatalf("key signature Verify: %v", err) } }
func (c *container) dialSSH() (*ssh.Client, error) { key, err := ssh.ParseRawPrivateKey([]byte(c.PrivateKey)) if err != nil { return nil, err } signer, err := ssh.NewSignerFromKey(key) if err != nil { return nil, err } host := c.HostAddr + ":" + c.SSHHostPort config := ssh.ClientConfig{ Config: ssh.Config{Rand: rand.Reader}, Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)}, User: c.User, } return ssh.Dial("tcp", host, &config) }
// A method for the construction of the configuration // object necessary for the connection to the host. func (s *Session) NewConfig(user user) error { // get the content of the private key file key, err := loadPEM(os.ExpandEnv(tools.Expanduser(user.GetPrivateKey()))) if err != nil { return err } // parse the key parsed, err := ssh.ParseRawPrivateKey(key) if err != nil { formatter.ColoredPrintln( formatter.Red, false, "Can't parse the private key!\n", "Reason is: ", err.Error(), ) } // convert into signer signer, err := ssh.NewSignerFromKey(parsed) if err != nil { formatter.ColoredPrintln( formatter.Red, false, "Can't create signer from private key!\n", "Reason is: ", err.Error(), ) } // Construct the configuration with password authentication s.Config = &ssh.ClientConfig{ User: user.GetUsername(), Auth: []ssh.AuthMethod{ ssh.PublicKeys(signer), }, } return nil }
func TestSSHMux(t *testing.T) { key, err := rsa.GenerateKey(rand.Reader, 512) if err != nil { t.Fatal("GenerateKey", err) } l, err := net.Listen("tcp", ":0") if err != nil { t.Fatal("net.Listen", err) } id, err := ssh.NewSignerFromKey(key) if err != nil { t.Fatal("NewSignerFromKey(%T)", key, err) } listener := newSSHListener(l, id) dialer := newSSHDialer(id) testDialerMux(t, dialer, listener) }
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)) } }
func (c *Config) populateAuthMethods() error { privKeyText, err := ioutil.ReadFile(c.privateKeyFile) if err != nil { return err } privKey, err := ssh.ParseRawPrivateKey(privKeyText) if err != nil { return err } signer, err := ssh.NewSignerFromKey(privKey) if err != nil { return err } c.authMethods = []ssh.AuthMethod{ ssh.PublicKeys(signer), } return nil }
// 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 }
func InitSSH() error { if enable, exist := common.Cfg.GetIntProperty("SSH", "Enable"); exist { if enable == 0 { return nil } } SSHEnable = true log.Println("Init SSH.") if proxy, exist := common.Cfg.GetProperty("SSH", "Proxy"); exist { sshLocalProxy, _ = url.Parse(proxy) } if enable, exist := common.Cfg.GetIntProperty("SSH", "RemoteResolve"); exist { sshResolveRemote = (enable != 0) } var manager SSH RegisteRemoteConnManager(&manager) index := 0 for ; ; index = index + 1 { v, exist := common.Cfg.GetProperty("SSH", "Server["+strconv.Itoa(index)+"]") if !exist || len(v) == 0 { break } var ssh_conn SSHRawConnection if u, err := url.Parse(v); nil == err { ssh_conn.Server = u.Host if !strings.Contains(u.Host, ":") { ssh_conn.Server = net.JoinHostPort(u.Host, "22") } if u.User == nil { log.Printf("Invalid SSH server url:%s, no user found in url.\n", v) continue } else { if pass, exist := u.User.Password(); exist { ssh_conn.ClientConfig = &ssh.ClientConfig{ User: u.User.Username(), Auth: []ssh.ClientAuth{ ssh.ClientAuthPassword(password(pass)), }, } } else { if identify := u.Query().Get("i"); len(identify) > 0 { if content, err := ioutil.ReadFile(identify); nil != err { log.Printf("Invalid SSH identify path:%s for reason:%v.\n", identify, err) continue } else { block, _ := pem.Decode([]byte(content)) if nil == block { log.Printf("Invalid pem content for path:%s.\n", identify) continue } clientKeychain := new(keychain) if strings.Contains(block.Type, "RSA") { rsakey, err := ssh.ParsePrivateKey(block.Bytes) if err != nil { log.Printf("Invalid RSA private key for %v.\n", err) continue } clientKeychain.add(rsakey) } else { dsakey, err := ssh.NewSignerFromKey(block.Bytes) if err != nil { log.Printf("Invalid DSA private key for %v.\n", err) continue } clientKeychain.add(dsakey) } ssh_conn.ClientConfig = &ssh.ClientConfig{ User: u.User.Username(), Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(clientKeychain), }, } } } else { log.Printf("Invalid SSH server url:%s, no pass/identify found in url.\n", v) continue } } } if _, err := ssh_conn.GetClientConn(true); nil == err { manager.selector.Add(&ssh_conn) log.Printf("SSH server %s connected.\n", ssh_conn.Server) } else { log.Printf("Invalid SSH server url:%s to connect for reason:%v\n", v, err) } } else { log.Printf("Invalid SSH server url:%s for reason:%v\n", v, err) } } if index == 0 { return errors.New("No configed SSH server.") } return nil }