blob: b3341cb938863be4022481d280a50b26f81770b4 [file] [log] [blame]
package main
import (
"code.google.com/p/gopass"
"flag"
"fmt"
"os"
"os/exec"
"syscall"
_ "veyron.io/veyron/veyron/profiles"
vsecurity "veyron.io/veyron/veyron/security"
"veyron.io/veyron/veyron/security/agent"
"veyron.io/veyron/veyron/security/agent/server"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/vlog"
)
func main() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, `Usage: %s [agent options] command command_args...
Loads the private key specified in under privatekey.pem in VEYRON_CREDENTIALS into memory, then
starts the specified command with access to the private key via the
agent protocol instead of directly reading from disk.
`, os.Args[0])
flag.PrintDefaults()
}
dir := os.Getenv("VEYRON_CREDENTIALS")
if len(dir) == 0 {
vlog.Fatal("VEYRON_CREDENTIALS must be set to directory")
}
p, err := newPrincipalFromDir(dir)
if err != nil {
vlog.Fatalf("failed to create new principal from dir(%s): %v", dir, err)
}
runtime := rt.Init()
log := runtime.Logger()
if len(flag.Args()) < 1 {
flag.Usage()
os.Exit(1)
}
if err = os.Setenv(agent.FdVarName, "3"); err != nil {
log.Fatalf("setenv: %v", err)
}
if err = os.Setenv("VEYRON_CREDENTIALS", ""); err != nil {
log.Fatalf("setenv: %v", err)
}
// Start running our server.
var sock *os.File
if sock, err = server.RunAnonymousAgent(runtime, p); err != nil {
log.Fatalf("RunAgent: %v", err)
}
// Now run the client and wait for it to finish.
cmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.ExtraFiles = []*os.File{sock}
err = cmd.Start()
if err != nil {
log.Fatalf("Error starting child: %v", err)
}
sock.Close()
cmd.Wait()
status := cmd.ProcessState.Sys().(syscall.WaitStatus)
os.Exit(status.ExitStatus())
}
func newPrincipalFromDir(dir string) (security.Principal, error) {
p, err := vsecurity.LoadPersistentPrincipal(dir, nil)
if os.IsNotExist(err) {
return handleDoesNotExist(dir)
}
if err == vsecurity.PassphraseErr {
return handlePassphrase(dir)
}
return p, err
}
func handleDoesNotExist(dir string) (security.Principal, error) {
fmt.Println("Private key file does not exist. Creating new private key...")
pass, err := gopass.GetPass("Enter passphrase (entering nothing will store unecrypted): ")
if err != nil {
return nil, fmt.Errorf("failed to read passphrase: %v", err)
}
p, err := vsecurity.CreatePersistentPrincipal(dir, []byte(pass))
if err != nil {
return nil, err
}
vsecurity.InitDefaultBlessings(p, "agent_principal")
return p, nil
}
func handlePassphrase(dir string) (security.Principal, error) {
fmt.Println("Private key file is encrypted. Please enter passphrase.")
pass, err := gopass.GetPass("Enter passphrase: ")
if err != nil {
return nil, fmt.Errorf("failed to read passphrase: %v", err)
}
return vsecurity.LoadPersistentPrincipal(dir, []byte(pass))
}