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
|
package client
import (
"context"
"fmt"
"sync"
"git.tardisproject.uk/tcmal/vault-plugin-kerberos-secrets/config"
krbClient "github.com/jcmturner/gokrb5/v8/client"
krbConfig "github.com/jcmturner/gokrb5/v8/config"
"github.com/jcmturner/gokrb5/v8/iana/nametype"
// "github.com/jcmturner/gokrb5/v8/kadmin"
krbMessages "github.com/jcmturner/gokrb5/v8/messages"
krbTypes "github.com/jcmturner/gokrb5/v8/types"
)
type client struct {
*sync.Mutex
kCfg *krbConfig.Config
kClient *krbClient.Client
}
func ClientFromConfig(config *config.Config) (client, error) {
kCfg := krbConfig.New()
kCfg.Realms = []krbConfig.Realm{
{
Realm: config.Realm,
DefaultDomain: config.Realm,
KDC: config.KDC,
KPasswdServer: config.KPasswdServer,
AdminServer: []string{},
MasterKDC: config.KDC,
},
}
kClient := krbClient.NewWithPassword(config.Username, config.Realm, config.Password, kCfg)
return client{
&sync.Mutex{},
kCfg,
kClient,
}, nil
}
func (c client) SetPassword(ctx context.Context, username string, password string) error {
c.Lock()
defer c.Unlock()
if err := c.kClient.AffirmLogin(); err != nil {
return fmt.Errorf("error logging in as admin principal: %e", err)
}
// Get a ticket for using kadmin/admin
cl := c.kClient
ASReq, err := krbMessages.NewASReqForChgPasswd(cl.Credentials.Domain(), cl.Config, cl.Credentials.CName())
if err != nil {
return fmt.Errorf("error creating ticket request for kadmin: %s", err)
}
ASRep, err := cl.ASExchange(cl.Credentials.Domain(), ASReq, 0)
if err != nil {
return fmt.Errorf("error exchanging request for kadmin ticket: %s", err)
}
// Construct the change passwd msg
msg, key, err := ChangePasswdMsg(
krbTypes.NewPrincipalName(nametype.KRB_NT_PRINCIPAL, username),
cl.Credentials.CName(),
cl.Credentials.Domain(),
password,
ASRep.Ticket,
ASRep.DecryptedEncPart.Key,
)
if err != nil {
return fmt.Errorf("error creating change passwd msg: %s", err)
}
// Send it to kpasswd
r, err := sendToKAdmin(cl, msg)
if err != nil {
return fmt.Errorf("error communicating with kpasswd: %s", err)
}
// Decrypt the result
if r.ResultCode != 0 {
return fmt.Errorf("error response from kadmin: code: %d; result: %s; krberror: %v", r.ResultCode, r.Result, r.KRBError)
}
err = r.Decrypt(key)
if err != nil {
return fmt.Errorf("error decrypting result: %s", err)
}
return nil
}
|