package main import ( "fmt" "log" "os" "os/exec" "strings" ) type Krb5Conf struct { Principal string Keytab string Realm string } var suffixMap map[string]string = map[string]string{ "SSO": "", "EDUROAM": "/ppp", "TACACS": "/net", } func CheckDuplicatePw(username, password string) error { for suffix, _ := range suffixMap { err := checkKerberosDuplicatePw(suffix, username, password) if err != nil { return err } } return nil } func checkKerberosDuplicatePw(suffix, username, password string) error { // KRB5_CONFIG env for heimdal-kinit // KRB5CCNAME for setting the cache name principal := fmt.Sprintf("%s%s@%s", username, suffixMap[suffix], pwman.Krb5Conf.Realm) cmd := exec.Command("kinit", "--password-file=STDIN", principal) cmd.Env = append(os.Environ()) cmd.Stdin = strings.NewReader(password) out, err := cmd.CombinedOutput() if err != nil { // everything is fine, it should fail if containsEither(string(out), "kinit: Password incorrect", "krb5_get_init_creds") { return nil } return fmt.Errorf("Error while checking %s password for duplicate, got error: %v, Output: %s", suffix, err, out) } // Run kdestroy to log out kdest := exec.Command("kdestroy") kdest.Run() return fmt.Errorf("Password already used with: %s account", suffix) } func ChangeKerberosPw(suffix, username, new_password string) error { conf := pwman.Krb5Conf kerberos_uid := fmt.Sprintf("%s%s@%s", username, suffixMap[suffix], conf.Realm) err := ensureCreatedKerberosPrincipal(kerberos_uid) if err != nil { return err } cmd := exec.Command("kadmin", "-K", conf.Keytab, "-p", conf.Principal, "cpw", "-p", new_password, kerberos_uid) out, err := cmd.CombinedOutput() if err != nil { log.Println("ERROR", "Error runing kadmin for change password, got error:", err, "with script output:", string(out)) return fmt.Errorf("Error could not change password, got error: %v", err) } return nil } func ensureCreatedKerberosPrincipal(principal string) error { conf := pwman.Krb5Conf exists, err := checkKerberosPrincipalExists(principal) if err != nil { return err } if !exists { cmd := exec.Command("kadmin", "-K", conf.Keytab, "-p", conf.Principal, "add", "--use-defaults", "--random-password", principal) out, err := cmd.CombinedOutput() if err != nil { fmt.Errorf("Could not create principal %s, got error: %v, output: %s", principal, err, out) } } return nil } func checkKerberosPrincipalExists(principal string) (bool, error) { conf := pwman.Krb5Conf cmd := exec.Command("kadmin", "-K", conf.Keytab, "-p", conf.Principal, "get", principal) // get markus/ppp: Principal does not exist out, err := cmd.CombinedOutput() if err != nil { if containsEither(string(out), "Principal does not exist") { return false, nil } return false, fmt.Errorf("Could not check if principal %s exists, got error: %v, output: %s", principal, err, out) } return true, nil }