blob: e6d4180590235b2ef8aa69c11d473f75dff272b3 [file] [log] [blame]
Scott Bakered4efab2020-01-13 19:12:25 -08001package client
2
3import (
4 "fmt"
5 "net"
6
7 "gopkg.in/jcmturner/gokrb5.v7/kadmin"
8 "gopkg.in/jcmturner/gokrb5.v7/messages"
9)
10
11// Kpasswd server response codes.
12const (
13 KRB5_KPASSWD_SUCCESS = 0
14 KRB5_KPASSWD_MALFORMED = 1
15 KRB5_KPASSWD_HARDERROR = 2
16 KRB5_KPASSWD_AUTHERROR = 3
17 KRB5_KPASSWD_SOFTERROR = 4
18 KRB5_KPASSWD_ACCESSDENIED = 5
19 KRB5_KPASSWD_BAD_VERSION = 6
20 KRB5_KPASSWD_INITIAL_FLAG_NEEDED = 7
21)
22
23// ChangePasswd changes the password of the client to the value provided.
24func (cl *Client) ChangePasswd(newPasswd string) (bool, error) {
25 ASReq, err := messages.NewASReqForChgPasswd(cl.Credentials.Domain(), cl.Config, cl.Credentials.CName())
26 if err != nil {
27 return false, err
28 }
29 ASRep, err := cl.ASExchange(cl.Credentials.Domain(), ASReq, 0)
30 if err != nil {
31 return false, err
32 }
33
34 msg, key, err := kadmin.ChangePasswdMsg(cl.Credentials.CName(), cl.Credentials.Domain(), newPasswd, ASRep.Ticket, ASRep.DecryptedEncPart.Key)
35 if err != nil {
36 return false, err
37 }
38 r, err := cl.sendToKPasswd(msg)
39 if err != nil {
40 return false, err
41 }
42 err = r.Decrypt(key)
43 if err != nil {
44 return false, err
45 }
46 if r.ResultCode != KRB5_KPASSWD_SUCCESS {
47 return false, fmt.Errorf("error response from kdamin: %s", r.Result)
48 }
49 cl.Credentials.WithPassword(newPasswd)
50 return true, nil
51}
52
53func (cl *Client) sendToKPasswd(msg kadmin.Request) (r kadmin.Reply, err error) {
54 _, kps, err := cl.Config.GetKpasswdServers(cl.Credentials.Domain(), true)
55 if err != nil {
56 return
57 }
58 addr := kps[1]
59 b, err := msg.Marshal()
60 if err != nil {
61 return
62 }
63 if len(b) <= cl.Config.LibDefaults.UDPPreferenceLimit {
64 return cl.sendKPasswdUDP(b, addr)
65 }
66 return cl.sendKPasswdTCP(b, addr)
67}
68
69func (cl *Client) sendKPasswdTCP(b []byte, kadmindAddr string) (r kadmin.Reply, err error) {
70 tcpAddr, err := net.ResolveTCPAddr("tcp", kadmindAddr)
71 if err != nil {
72 return
73 }
74 conn, err := net.DialTCP("tcp", nil, tcpAddr)
75 if err != nil {
76 return
77 }
78 rb, err := cl.sendTCP(conn, b)
79 err = r.Unmarshal(rb)
80 return
81}
82
83func (cl *Client) sendKPasswdUDP(b []byte, kadmindAddr string) (r kadmin.Reply, err error) {
84 udpAddr, err := net.ResolveUDPAddr("udp", kadmindAddr)
85 if err != nil {
86 return
87 }
88 conn, err := net.DialUDP("udp", nil, udpAddr)
89 if err != nil {
90 return
91 }
92 rb, err := cl.sendUDP(conn, b)
93 err = r.Unmarshal(rb)
94 return
95}