|
|
@@ -6,10 +6,14 @@ import (
|
|
|
"fmt"
|
|
|
"github.com/jcmturner/gokrb5/config"
|
|
|
"github.com/jcmturner/gokrb5/credentials"
|
|
|
+ "github.com/jcmturner/gokrb5/crypto"
|
|
|
+ "github.com/jcmturner/gokrb5/crypto/etype"
|
|
|
+ "github.com/jcmturner/gokrb5/iana/errorcode"
|
|
|
"github.com/jcmturner/gokrb5/iana/nametype"
|
|
|
"github.com/jcmturner/gokrb5/keytab"
|
|
|
"github.com/jcmturner/gokrb5/messages"
|
|
|
"github.com/jcmturner/gokrb5/types"
|
|
|
+ "os"
|
|
|
)
|
|
|
|
|
|
// Client side configuration and state.
|
|
|
@@ -119,6 +123,28 @@ func (cl *Client) WithPassword(password string) *Client {
|
|
|
return cl
|
|
|
}
|
|
|
|
|
|
+// Key returns a key for the client. Preferably from a keytab and then generated from the password.
|
|
|
+// The KRBError would have been returned from the KDC and must be of type KDC_ERR_PREAUTH_REQUIRED.
|
|
|
+// If a KRBError is not available pass nil and a key will be returned from the credentials keytab.
|
|
|
+func (c *Client) Key(etype etype.EType, krberr messages.KRBError) (types.EncryptionKey, error) {
|
|
|
+ if c.Credentials.HasKeytab() && etype != nil {
|
|
|
+ return c.Credentials.Keytab.GetEncryptionKey(c.Credentials.CName.NameString, c.Credentials.Realm, 0, etype.GetETypeID())
|
|
|
+ } else if c.Credentials.HasPassword() {
|
|
|
+ if krberr.ErrorCode == errorcode.KDC_ERR_PREAUTH_REQUIRED {
|
|
|
+ var pas types.PADataSequence
|
|
|
+ err := pas.Unmarshal(krberr.EData)
|
|
|
+ if err != nil {
|
|
|
+ return types.EncryptionKey{}, fmt.Errorf("Could not get PAData from KRBError to generate key from password: %v", err)
|
|
|
+ }
|
|
|
+ key, _, err := crypto.GetKeyFromPassword(c.Credentials.Password, krberr.CName, krberr.CRealm, etype.GetETypeID(), pas)
|
|
|
+ return key, err
|
|
|
+ }
|
|
|
+ key, _, err := crypto.GetKeyFromPassword(c.Credentials.Password, c.Credentials.CName, c.Credentials.Realm, etype.GetETypeID(), types.PADataSequence{})
|
|
|
+ return key, err
|
|
|
+ }
|
|
|
+ return types.EncryptionKey{}, errors.New("Credential has neither keytab or password to generate key.")
|
|
|
+}
|
|
|
+
|
|
|
// LoadConfig loads the Kerberos configuration for the client from file path specified.
|
|
|
func (cl *Client) LoadConfig(cfgPath string) (*Client, error) {
|
|
|
cfg, err := config.Load(cfgPath)
|
|
|
@@ -131,13 +157,15 @@ func (cl *Client) LoadConfig(cfgPath string) (*Client, error) {
|
|
|
|
|
|
// IsConfigured indicates if the client has the values required set.
|
|
|
func (cl *Client) IsConfigured() bool {
|
|
|
- if !cl.Credentials.HasPassword() && !cl.Credentials.HasKeytab() {
|
|
|
+ if !cl.Credentials.HasPassword() && !cl.Credentials.HasKeytab() && cl.session.AuthTime.IsZero() {
|
|
|
return false
|
|
|
}
|
|
|
if cl.Credentials.Username == "" {
|
|
|
return false
|
|
|
}
|
|
|
if cl.Config.LibDefaults.Default_realm == "" {
|
|
|
+ fmt.Fprintf(os.Stderr, "hello: %v\n", cl)
|
|
|
+
|
|
|
return false
|
|
|
}
|
|
|
for _, r := range cl.Config.Realms {
|