code.gitea.io/gitea@v1.22.3/services/auth/source/pam/source_authenticate.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package pam 5 6 import ( 7 "context" 8 "fmt" 9 "strings" 10 11 "code.gitea.io/gitea/models/auth" 12 user_model "code.gitea.io/gitea/models/user" 13 "code.gitea.io/gitea/modules/auth/pam" 14 "code.gitea.io/gitea/modules/optional" 15 "code.gitea.io/gitea/modules/setting" 16 17 "github.com/google/uuid" 18 ) 19 20 // Authenticate queries if login/password is valid against the PAM, 21 // and create a local user if success when enabled. 22 func (source *Source) Authenticate(ctx context.Context, user *user_model.User, userName, password string) (*user_model.User, error) { 23 pamLogin, err := pam.Auth(source.ServiceName, userName, password) 24 if err != nil { 25 if strings.Contains(err.Error(), "Authentication failure") { 26 return nil, user_model.ErrUserNotExist{Name: userName} 27 } 28 return nil, err 29 } 30 31 if user != nil { 32 return user, nil 33 } 34 35 // Allow PAM sources with `@` in their name, like from Active Directory 36 username := pamLogin 37 email := pamLogin 38 idx := strings.Index(pamLogin, "@") 39 if idx > -1 { 40 username = pamLogin[:idx] 41 } 42 if user_model.ValidateEmail(email) != nil { 43 if source.EmailDomain != "" { 44 email = fmt.Sprintf("%s@%s", username, source.EmailDomain) 45 } else { 46 email = fmt.Sprintf("%s@%s", username, setting.Service.NoReplyAddress) 47 } 48 if user_model.ValidateEmail(email) != nil { 49 email = uuid.New().String() + "@localhost" 50 } 51 } 52 53 user = &user_model.User{ 54 LowerName: strings.ToLower(username), 55 Name: username, 56 Email: email, 57 Passwd: password, 58 LoginType: auth.PAM, 59 LoginSource: source.authSource.ID, 60 LoginName: userName, // This is what the user typed in 61 } 62 overwriteDefault := &user_model.CreateUserOverwriteOptions{ 63 IsActive: optional.Some(true), 64 } 65 66 if err := user_model.CreateUser(ctx, user, overwriteDefault); err != nil { 67 return user, err 68 } 69 70 return user, nil 71 } 72 73 // IsSkipLocalTwoFA returns if this source should skip local 2fa for password authentication 74 func (source *Source) IsSkipLocalTwoFA() bool { 75 return source.SkipLocalTwoFA 76 }