Skip to content

Commit

Permalink
pam: In GDM mode, send the broker selection using a choice list
Browse files Browse the repository at this point in the history
  • Loading branch information
3v1n0 committed Jul 28, 2023
1 parent 5a85314 commit 3c2baa6
Showing 1 changed file with 107 additions and 7 deletions.
114 changes: 107 additions & 7 deletions pam/pam.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"syscall"
"time"

"github.com/elliotchance/orderedmap/v2"
"github.com/skip2/go-qrcode"
"github.com/ubuntu/authd"
"github.com/ubuntu/authd/internal/brokers"
Expand Down Expand Up @@ -47,6 +48,7 @@ const (
ClientTypeNone ClientType = iota + 1
ClientTypeTerminal
ClientTypeStandard
ClientTypeGdm
)

type PAMClient interface {
Expand Down Expand Up @@ -84,6 +86,10 @@ type PAMClientTerminal struct {
PAMClientBase
}

type PAMClientGdm struct {
PAMClientBase
}

func NewPAMClientBase(clientType ClientType, pamh pamHandle,
client authd.PAMClient) *PAMClientBase {
return &PAMClientBase{clientType, pamh, client,
Expand All @@ -94,6 +100,10 @@ func NewPAMClientTerminal(pamh pamHandle, client authd.PAMClient) *PAMClientTerm
return &PAMClientTerminal{*NewPAMClientBase(ClientTypeTerminal, pamh, client)}
}

func NewPAMClientGdm(pamh pamHandle, client authd.PAMClient) *PAMClientGdm {
return &PAMClientGdm{*NewPAMClientBase(ClientTypeGdm, pamh, client)}
}

func (base *PAMClientBase) getClientType() ClientType {
return base.clientType
}
Expand Down Expand Up @@ -166,6 +176,8 @@ func pam_sm_authenticate(pamh *C.pam_handle_t, flags, argc C.int, argv **C.char)
var pamClient PAMClient
if term.IsTerminal(int(os.Stdin.Fd())) {
pamClient = NewPAMClientTerminal(pamh, client)
} else if gdmChoiceListSupported() {
pamClient = NewPAMClientGdm(pamh, client)
} else {
pamClient = NewPAMClientBase(ClientTypeStandard, pamh, client)
}
Expand All @@ -179,6 +191,8 @@ func pam_sm_authenticate(pamh *C.pam_handle_t, flags, argc C.int, argv **C.char)
return C.PAM_AUTH_ERR
}

// IF BROKER DISCONNECTED... fail!

brokersInfo, err := client.AvailableBrokers(context.TODO(), &authd.ABRequest{
UserName: &user,
})
Expand Down Expand Up @@ -339,15 +353,27 @@ func pam_sm_authenticate(pamh *C.pam_handle_t, flags, argc C.int, argv **C.char)

// selectBroker allows interactive broker selection.
// Only one choice will be returned immediately.
func (pamClient *PAMClientBase) selectBrokerInteractive(
brokersInfo []*authd.ABResponse_BrokerInfo) (brokerID, brokerName string, err error) {
func maybeGetBroker(brokersInfo []*authd.ABResponse_BrokerInfo) (
*authd.ABResponse_BrokerInfo, error) {
if len(brokersInfo) < 1 {
return "", "", errors.New("no broker found")
return nil, errors.New("no broker found")
}

// Default choice for one possibility.
if len(brokersInfo) == 1 {
return brokersInfo[0].GetId(), brokersInfo[0].GetName(), nil
return brokersInfo[0], nil
}

return nil, nil
}

func (pamClient *PAMClientBase) selectBrokerInteractive(
brokersInfo []*authd.ABResponse_BrokerInfo) (brokerID, brokerName string, err error) {
broker, err := maybeGetBroker(brokersInfo)
if err != nil {
return "", "", err
} else if broker != nil {
return broker.GetId(), broker.GetName(), nil
}

var choices []string
Expand All @@ -369,6 +395,31 @@ func (pamClient *PAMClientBase) selectBrokerInteractive(
return ids[i], brokersInfo[i].GetName(), nil
}

func (pamClient *PAMClientGdm) selectBrokerInteractive(
brokersInfo []*authd.ABResponse_BrokerInfo) (brokerID, brokerName string, err error) {
broker, err := maybeGetBroker(brokersInfo)
if err != nil {
return "", "", err
} else if broker != nil {
return broker.GetId(), broker.GetName(), nil
}

var choices = orderedmap.NewOrderedMap[string, string]()
sendInfof(pamClient.pamh, "Sending choices to gdm %v", choices)
for _, b := range brokersInfo {
choices.Set(b.GetId(), b.GetName())
}
choices.Set("go-back", "Go back")

id, err := gdmChoiceListRequest(pamClient.pamh, "Select broker", choices)
if err != nil {
return "", "", err
} else if id == "go-back" {
return "", "", errGoBack
}
return id, choices.GetOrDefault(id, ""), nil
}

func (pamClient *PAMClientBase) getSupportedLayouts() []*authd.UILayout {
required, optional := "required", "optional"
supportedEntries := "optional:chars,chars_password"
Expand All @@ -391,6 +442,21 @@ func (pamClient *PAMClientBase) getSupportedLayouts() []*authd.UILayout {
}
}

func (pamClient *PAMClientGdm) getSupportedLayouts() []*authd.UILayout {
required := "required"
supportedEntries := "optional:chars,chars_password"
waitOptional := "optional:true,false"

return []*authd.UILayout{
{
Type: "form",
Label: &required,
Entry: &supportedEntries,
Wait: &waitOptional,
},
}
}

// startBrokerSession returns the sessionID and available authentication modes after marking a broker as current.
func (pamClient *PAMClientBase) startBrokerSession(brokerID, username string) error {
// Start a transaction for this user with the broker.
Expand Down Expand Up @@ -440,7 +506,7 @@ func (pamClient *PAMClientBase) startBrokerSession(brokerID, username string) er

// selectAuthenticationModeInteractive allows interactive authentication mode selection.
// Only one choice will be returned immediately.
func (pamClient *PAMClientBase) selectAuthenticationModeInteractive() (name string, err error) {
func (pamClient *PAMClientBase) maybeGetAuthMode() (string, error) {
if len(pamClient.authModes) < 1 {
return "", errors.New("no authentication mode supported")
}
Expand All @@ -449,6 +515,16 @@ func (pamClient *PAMClientBase) selectAuthenticationModeInteractive() (name stri
if len(pamClient.authModes) == 1 {
return pamClient.authModes[0].GetName(), nil
}
return "", nil
}

func (pamClient *PAMClientBase) selectAuthenticationModeInteractive() (name string, err error) {
authMode, err := pamClient.maybeGetAuthMode()
if err != nil {
return "", err
} else if authMode != "" {
return authMode, nil
}

var choices []string
var ids []string
Expand All @@ -466,6 +542,30 @@ func (pamClient *PAMClientBase) selectAuthenticationModeInteractive() (name stri
return ids[i], nil
}

func (pamClient *PAMClientGdm) selectAuthenticationModeInteractive() (name string, err error) {
authMode, err := pamClient.maybeGetAuthMode()
if err != nil {
return "", err
} else if authMode != "" {
return authMode, nil
}

var choices = orderedmap.NewOrderedMap[string, string]()
sendInfof(pamClient.pamh, "Sending choices to gdm %v", choices)
for _, m := range pamClient.authModes {
choices.Set(m.GetName(), m.GetLabel())
}
choices.Set("go-back", "Go back")

id, err := gdmChoiceListRequest(pamClient.pamh, "Select authentication mode", choices)
if err != nil {
return "", err
} else if id == "go-back" {
return "", errGoBack
}
return id, nil
}

func (pamClient *PAMClientBase) promptForInt(title string, choices []string, prompt string) (
r int, err error) {
pamPrompt := title
Expand All @@ -480,7 +580,7 @@ func (pamClient *PAMClientBase) promptForInt(title string, choices []string, pro
if err != nil {
return 0, fmt.Errorf("error while reading stdin: %v", err)
}
if r == "r" {
if r == "r" && pamClient.clientType != ClientTypeGdm {
return 0, errGoBack
}
if r == "" {
Expand Down Expand Up @@ -531,7 +631,7 @@ func (pamClient *PAMClientBase) formChallenge(uiLayout *authd.UILayout) (
return nil, err
}

if input == "r" {
if input == "r" /* TODO: && pamClient.clientType != ClientTypeGdm */ {
return nil, errGoBack
}

Expand Down

0 comments on commit 3c2baa6

Please sign in to comment.