summaryrefslogtreecommitdiffstats
path: root/services/auth/source/pam/source_authenticate.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--services/auth/source/pam/source_authenticate.go76
1 files changed, 76 insertions, 0 deletions
diff --git a/services/auth/source/pam/source_authenticate.go b/services/auth/source/pam/source_authenticate.go
new file mode 100644
index 0000000..addd1bd
--- /dev/null
+++ b/services/auth/source/pam/source_authenticate.go
@@ -0,0 +1,76 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package pam
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "code.gitea.io/gitea/models/auth"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/auth/pam"
+ "code.gitea.io/gitea/modules/optional"
+ "code.gitea.io/gitea/modules/setting"
+
+ "github.com/google/uuid"
+)
+
+// Authenticate queries if login/password is valid against the PAM,
+// and create a local user if success when enabled.
+func (source *Source) Authenticate(ctx context.Context, user *user_model.User, userName, password string) (*user_model.User, error) {
+ pamLogin, err := pam.Auth(source.ServiceName, userName, password)
+ if err != nil {
+ if strings.Contains(err.Error(), "Authentication failure") {
+ return nil, user_model.ErrUserNotExist{Name: userName}
+ }
+ return nil, err
+ }
+
+ if user != nil {
+ return user, nil
+ }
+
+ // Allow PAM sources with `@` in their name, like from Active Directory
+ username := pamLogin
+ email := pamLogin
+ idx := strings.Index(pamLogin, "@")
+ if idx > -1 {
+ username = pamLogin[:idx]
+ }
+ if user_model.ValidateEmail(email) != nil {
+ if source.EmailDomain != "" {
+ email = fmt.Sprintf("%s@%s", username, source.EmailDomain)
+ } else {
+ email = fmt.Sprintf("%s@%s", username, setting.Service.NoReplyAddress)
+ }
+ if user_model.ValidateEmail(email) != nil {
+ email = uuid.New().String() + "@localhost"
+ }
+ }
+
+ user = &user_model.User{
+ LowerName: strings.ToLower(username),
+ Name: username,
+ Email: email,
+ Passwd: password,
+ LoginType: auth.PAM,
+ LoginSource: source.authSource.ID,
+ LoginName: userName, // This is what the user typed in
+ }
+ overwriteDefault := &user_model.CreateUserOverwriteOptions{
+ IsActive: optional.Some(true),
+ }
+
+ if err := user_model.CreateUser(ctx, user, overwriteDefault); err != nil {
+ return user, err
+ }
+
+ return user, nil
+}
+
+// IsSkipLocalTwoFA returns if this source should skip local 2fa for password authentication
+func (source *Source) IsSkipLocalTwoFA() bool {
+ return source.SkipLocalTwoFA
+}