summaryrefslogtreecommitdiff
path: root/client/client.go
diff options
context:
space:
mode:
authorAria <me@aria.rip>2023-10-01 22:55:08 +0100
committerAria <me@aria.rip>2023-10-01 22:55:08 +0100
commit7045a630996e08c18beb7c3d39e1b2752c8a4ba4 (patch)
treee539793ccb588433f44cc0e1b52821cb6953a85a /client/client.go
parentca56d194c605ef7ba09f46eff11374b492f83804 (diff)
a working version with only changing passwords
Diffstat (limited to 'client/client.go')
-rw-r--r--client/client.go91
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
}