penguin/kstore-cred

helper to access windows credential store

main.go

raw ยท 1744 bytes

package main

import (
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	"github.com/danieljoos/wincred"
)

const (
	CRED_NAME = "RBASH-KSTORE"
)

func usage(stdfd *os.File) {
	name := filepath.Base(os.Args[0])
	space := strings.Repeat(" ", len(name))

	fmt.Fprintf(stdfd, "Usage: %s get\n", name)
	fmt.Fprintf(stdfd, "       %s set < secret\n", space)
	fmt.Fprintf(stdfd, "       %s del\n", space)
	fmt.Fprintf(stdfd, "       %s help\n", space)
}

func getAuthSecret() (*wincred.GenericCredential, error) {
	return wincred.GetGenericCredential(CRED_NAME)
}

func delAuthSecret() error {
	cred, _ := getAuthSecret()
	if cred == nil {
		return nil
	}
	return cred.Delete()
}

func setAuthSecret(newSecret []byte) error {
	newSecret = []byte(strings.TrimRight(string(newSecret), "\r\n"))
	if len(newSecret) == 0 {
		return errors.New("empty passphrase")
	}

	cred, _ := getAuthSecret()
	if cred == nil {
		cred = wincred.NewGenericCredential(CRED_NAME)
	}

	cred.CredentialBlob = newSecret
	return cred.Write()
}

func main() {
	if len(os.Args) < 2 {
		usage(os.Stderr)
		os.Exit(1)
	}

	var err error

	switch os.Args[1] {
	case "get":
		var cred *wincred.GenericCredential
		cred, err = getAuthSecret()
		if err == nil {
			fmt.Print(string(cred.CredentialBlob))
		}

	case "set":
		if len(os.Args) > 2 {
			err = errors.New("do not pass passphrase as an argument; pipe it on stdin")
			break
		}

		var b []byte
		b, err = io.ReadAll(os.Stdin)
		if err == nil {
			err = setAuthSecret(b)
		}

	case "del":
		err = delAuthSecret()

	case "help", "-h", "--help":
		usage(os.Stdout)

	default:
		usage(os.Stderr)
		err = fmt.Errorf("unknown command: %s", os.Args[1])
	}

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}