1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
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
}
|