diff options
author | Aria <me@aria.rip> | 2023-10-01 22:55:08 +0100 |
---|---|---|
committer | Aria <me@aria.rip> | 2023-10-01 22:55:08 +0100 |
commit | 7045a630996e08c18beb7c3d39e1b2752c8a4ba4 (patch) | |
tree | e539793ccb588433f44cc0e1b52821cb6953a85a /client/client.go | |
parent | ca56d194c605ef7ba09f46eff11374b492f83804 (diff) |
a working version with only changing passwords
Diffstat (limited to 'client/client.go')
-rw-r--r-- | client/client.go | 91 |
1 files changed, 84 insertions, 7 deletions
diff --git a/client/client.go b/client/client.go index b7f5eee..1bfad5f 100644 --- a/client/client.go +++ b/client/client.go @@ -1,19 +1,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{} +type client struct { + *sync.Mutex -func ClientFromConfig(config *config.Config) (client, error) { - return client{}, nil + kCfg *krbConfig.Config + kClient *krbClient.Client } -func (c client) SetPassword(username string, password string) error { - return nil // TODO +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) SetPasswordWithOld(username string, oldPassword, newPassword string) error { - return nil // TODO +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 } |