package client import ( "github.com/jcmturner/gokrb5/v8/crypto" "github.com/jcmturner/gokrb5/v8/kadmin" "github.com/jcmturner/gokrb5/v8/krberror" "github.com/jcmturner/gokrb5/v8/messages" "github.com/jcmturner/gokrb5/v8/types" ) // ChangePasswdMsg generate a change password request and also return the key needed to decrypt the reply. func ChangePasswdMsg(targetName types.PrincipalName, cname types.PrincipalName, realm, password string, tkt messages.Ticket, sessionKey types.EncryptionKey) (r kadmin.Request, k types.EncryptionKey, err error) { // Create change password data struct and marshal to bytes chgpasswd := kadmin.ChangePasswdData{ NewPasswd: []byte(password), TargName: targetName, TargRealm: realm, } chpwdb, err := chgpasswd.Marshal() if err != nil { err = krberror.Errorf(err, krberror.KRBMsgError, "error marshaling change passwd data") return } // Generate authenticator auth, err := types.NewAuthenticator(realm, cname) if err != nil { err = krberror.Errorf(err, krberror.KRBMsgError, "error generating new authenticator") return } etype, err := crypto.GetEtype(sessionKey.KeyType) if err != nil { err = krberror.Errorf(err, krberror.KRBMsgError, "error generating subkey etype") return } err = auth.GenerateSeqNumberAndSubKey(etype.GetETypeID(), etype.GetKeyByteSize()) if err != nil { err = krberror.Errorf(err, krberror.KRBMsgError, "error generating subkey") return } k = auth.SubKey // Generate AP_REQ APreq, err := messages.NewAPReq(tkt, sessionKey, auth) if err != nil { return } // Form the KRBPriv encpart data kp := messages.EncKrbPrivPart{ UserData: chpwdb, Timestamp: auth.CTime, Usec: auth.Cusec, SequenceNumber: auth.SeqNumber, } kpriv := messages.NewKRBPriv(kp) err = kpriv.EncryptEncPart(k) if err != nil { err = krberror.Errorf(err, krberror.EncryptingError, "error encrypting change passwd data") return } r = kadmin.Request{ APREQ: APreq, KRBPriv: kpriv, } return }