package service

import (
	
	
	
	

	goidentity 
	
	
	
)

// NewKRB5BasicAuthenticator creates a new NewKRB5BasicAuthenticator
func ( string,  *config.Config,  *Settings,  *client.Settings) KRB5BasicAuthenticator {
	return KRB5BasicAuthenticator{
		BasicHeaderValue: ,
		clientConfig:     ,
		serviceSettings:  ,
		clientSettings:   ,
	}
}

// KRB5BasicAuthenticator implements gokrb5.com/jcmturner/goidentity.Authenticator interface.
// It takes username and password so can be used for basic authentication.
type KRB5BasicAuthenticator struct {
	BasicHeaderValue string
	serviceSettings  *Settings
	clientSettings   *client.Settings
	clientConfig     *config.Config
	realm            string
	username         string
	password         string
}

// Authenticate and return the identity. The boolean indicates if the authentication was successful.
func ( KRB5BasicAuthenticator) () ( goidentity.Identity,  bool,  error) {
	.realm, .username, .password,  = parseBasicHeaderValue(.BasicHeaderValue)
	if  != nil {
		 = fmt.Errorf("could not parse basic authentication header: %v", )
		return
	}
	 := client.NewWithPassword(.username, .realm, .password, .clientConfig)
	 = .Login()
	if  != nil {
		// Username and/or password could be wrong
		 = fmt.Errorf("error with user credentials during login: %v", )
		return
	}
	, ,  := .GetServiceTicket(.serviceSettings.SName())
	if  != nil {
		 = fmt.Errorf("could not get service ticket: %v", )
		return
	}
	 = .DecryptEncPart(.serviceSettings.Keytab, .serviceSettings.KeytabPrincipal())
	if  != nil {
		 = fmt.Errorf("could not decrypt service ticket: %v", )
		return
	}
	.Credentials.SetAuthTime(time.Now().UTC())
	.Credentials.SetAuthenticated(true)
	, ,  := .GetPACType(.serviceSettings.Keytab, .serviceSettings.KeytabPrincipal(), .serviceSettings.Logger())
	if  &&  != nil {
		 = fmt.Errorf("error processing PAC: %v", )
		return
	}
	if  {
		// There is a valid PAC. Adding attributes to creds
		.Credentials.SetADCredentials(credentials.ADCredentials{
			GroupMembershipSIDs: .KerbValidationInfo.GetGroupMembershipSIDs(),
			LogOnTime:           .KerbValidationInfo.LogOnTime.Time(),
			LogOffTime:          .KerbValidationInfo.LogOffTime.Time(),
			PasswordLastSet:     .KerbValidationInfo.PasswordLastSet.Time(),
			EffectiveName:       .KerbValidationInfo.EffectiveName.Value,
			FullName:            .KerbValidationInfo.FullName.Value,
			UserID:              int(.KerbValidationInfo.UserID),
			PrimaryGroupID:      int(.KerbValidationInfo.PrimaryGroupID),
			LogonServer:         .KerbValidationInfo.LogonServer.Value,
			LogonDomainName:     .KerbValidationInfo.LogonDomainName.Value,
			LogonDomainID:       .KerbValidationInfo.LogonDomainID.String(),
		})
	}
	 = true
	 = .Credentials
	return
}

// Mechanism returns the authentication mechanism.
func ( KRB5BasicAuthenticator) () string {
	return "Kerberos Basic"
}

func parseBasicHeaderValue( string) (, ,  string,  error) {
	,  := base64.StdEncoding.DecodeString()
	if  != nil {
		return
	}
	 := string()
	 := strings.SplitN(, ":", 2)
	 = [1]
	// Domain and username can be specified in 2 formats:
	// <Username> - no domain specified
	// <Domain>\<Username>
	// <Username>@<Domain>
	if strings.Contains([0], `\`) {
		 := strings.SplitN([0], `\`, 2)
		 = [0]
		 = [1]
	} else if strings.Contains([0], `@`) {
		 := strings.SplitN([0], `@`, 2)
		 = [1]
		 = [0]
	} else {
		 = [0]
	}
	return
}