Beispiel #1
0
func PAM(ctx *cli.Context) {
	// We need to find the user's home first.
	username := os.Getenv("PAM_USER")
	homedir := mustLookupHomeDir(username)

	nullok := ctx.Bool("nullok")
	conf, err := client.ReadDefaultConfig(homedir)
	if err != nil {
		if nullok {
			os.Exit(0)
		} else {
			fatalf("Error reading config: %v\n", err)
		}
	}

	if len(conf.Registrations) == 0 {
		if nullok {
			os.Exit(0)
		} else {
			fatalf("Error: no registrations found\n")
		}
	}

	c := mustGRPCClient(conf.Addr, conf.Token, ctx.GlobalString("ca_file"))

	hostname, err := os.Hostname()
	if err != nil {
		fatalf("Error getting hostname: %v", err)
	}
	msg := fmt.Sprintf("%s@%s", username, hostname)

	pa, err := c.PrepareAuthentication(
		msg, conf.AppID, conf.RegistrationValues())
	if err != nil {
		fatalf("Error preparing authentication: %v\n", err)
	}

	fmt.Printf("Authenticate here and press enter:  %s\n", pa.Key.Url)

	// Closing stdout makes pam_prompt_exec send the prompt over.
	os.Stdout.Close()

	// Read input, and check if it's a backup code.
	// Never take a backup code of less than 6 characters, just in case some
	// data handling error makes them appear in conf.BackupCodes.
	input := readLine()
	if _, ok := conf.BackupCodes[input]; len(input) >= 6 && ok {
		delete(conf.BackupCodes, input)
		mustWriteConfig(conf, homedir)
		os.Exit(0)
	}

	err = c.CompleteAuthentication(pa)
	if err != nil {
		fatalf("Error completing authentication: %v\n", err)
	}

	os.Exit(0)
}
Beispiel #2
0
func mustReadConfig() *client.Config {
	conf, err := client.ReadDefaultConfig("")
	if err != nil {
		fatalf("Error reading config: %v\n", err)
	}

	return conf
}
Beispiel #3
0
func Init(ctx *cli.Context) {
	if !ctx.Bool("override") {
		// We don't want to accidentally override the config.
		_, err := client.ReadDefaultConfig("")
		if err == nil {
			fmt.Printf("Configuration already exists at %s\n",
				client.DefaultConfigFullPath(""))
			fmt.Printf("Use --override to continue anyway.\n")
			os.Exit(1)
		}
	}

	fmt.Printf("- GRPC server address to use? (e.g. 'mydomain.com:8801')\n")
	addr := readLine()
	fmt.Printf("- Authorization token? (given to you by the server admin)\n")
	token := readLine()

	fmt.Printf("- Contacting server...\n")
	c, err := client.GRPCClient(addr, token, ctx.GlobalString("ca_file"))
	if err != nil {
		fmt.Printf("Error connecting with the server: %v\n", err)
		fmt.Printf("Check the parameters above and try again.\n")
		os.Exit(1)
	}

	appID, err := c.GetAppID()
	if err != nil {
		fmt.Printf("RPC error: %v\n", err)
		fmt.Printf("Check the parameters above and try again.\n")
		os.Exit(1)
	}

	fmt.Printf("It worked!  AppID: %s\n", appID)

	conf := &client.Config{
		Addr:          addr,
		Token:         token,
		AppID:         appID,
		Registrations: map[string][]byte{},
	}

	err = conf.NewBackupCodes()
	if err != nil {
		fatalf("Error generating backup codes: %v\n", err)
	}

	mustWriteConfig(conf, "")
	fmt.Printf("Config written to %s\n", client.DefaultConfigFullPath(""))

	fmt.Printf("\n")
	fmt.Printf("Please write down your backup codes:\n")
	printBackupCodes(conf)

	fmt.Printf("\n")
	fmt.Printf("All done!\n")
	fmt.Printf("To register a security key, run:  remoteu2f-cli register\n")
}