mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Synchronize SSH keys on login with LDAP + Fix SQLite deadlock on ldap ssh key deletion (#5557)
* Synchronize SSH keys on login with LDAP * BUG: Fix hang on sqlite during LDAP key deletion
This commit is contained in:
		@@ -393,7 +393,13 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR
 | 
				
			|||||||
		return nil, ErrUserNotExist{0, login, 0}
 | 
							return nil, ErrUserNotExist{0, login, 0}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var isAttributeSSHPublicKeySet = len(strings.TrimSpace(source.LDAP().AttributeSSHPublicKey)) > 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !autoRegister {
 | 
						if !autoRegister {
 | 
				
			||||||
 | 
							if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(user, source, sr.SSHPublicKey) {
 | 
				
			||||||
 | 
								RewriteAllPublicKeys()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return user, nil
 | 
							return user, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -421,7 +427,14 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR
 | 
				
			|||||||
		IsActive:    true,
 | 
							IsActive:    true,
 | 
				
			||||||
		IsAdmin:     sr.IsAdmin,
 | 
							IsAdmin:     sr.IsAdmin,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return user, CreateUser(user)
 | 
					
 | 
				
			||||||
 | 
						err := CreateUser(user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err == nil && isAttributeSSHPublicKeySet && addLdapSSHPublicKeys(user, source, sr.SSHPublicKey) {
 | 
				
			||||||
 | 
							RewriteAllPublicKeys()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return user, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//   _________   __________________________
 | 
					//   _________   __________________________
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -451,11 +451,9 @@ func GetPublicKeyByID(keyID int64) (*PublicKey, error) {
 | 
				
			|||||||
	return key, nil
 | 
						return key, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SearchPublicKeyByContent searches content as prefix (leak e-mail part)
 | 
					func searchPublicKeyByContentWithEngine(e Engine, content string) (*PublicKey, error) {
 | 
				
			||||||
// and returns public key found.
 | 
					 | 
				
			||||||
func SearchPublicKeyByContent(content string) (*PublicKey, error) {
 | 
					 | 
				
			||||||
	key := new(PublicKey)
 | 
						key := new(PublicKey)
 | 
				
			||||||
	has, err := x.
 | 
						has, err := e.
 | 
				
			||||||
		Where("content like ?", content+"%").
 | 
							Where("content like ?", content+"%").
 | 
				
			||||||
		Get(key)
 | 
							Get(key)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -466,6 +464,12 @@ func SearchPublicKeyByContent(content string) (*PublicKey, error) {
 | 
				
			|||||||
	return key, nil
 | 
						return key, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SearchPublicKeyByContent searches content as prefix (leak e-mail part)
 | 
				
			||||||
 | 
					// and returns public key found.
 | 
				
			||||||
 | 
					func SearchPublicKeyByContent(content string) (*PublicKey, error) {
 | 
				
			||||||
 | 
						return searchPublicKeyByContentWithEngine(x, content)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SearchPublicKey returns a list of public keys matching the provided arguments.
 | 
					// SearchPublicKey returns a list of public keys matching the provided arguments.
 | 
				
			||||||
func SearchPublicKey(uid int64, fingerprint string) ([]*PublicKey, error) {
 | 
					func SearchPublicKey(uid int64, fingerprint string) ([]*PublicKey, error) {
 | 
				
			||||||
	keys := make([]*PublicKey, 0, 5)
 | 
						keys := make([]*PublicKey, 0, 5)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1402,7 +1402,7 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
 | 
				
			|||||||
	// Delete keys marked for deletion
 | 
						// Delete keys marked for deletion
 | 
				
			||||||
	var sshKeysNeedUpdate bool
 | 
						var sshKeysNeedUpdate bool
 | 
				
			||||||
	for _, KeyToDelete := range keys {
 | 
						for _, KeyToDelete := range keys {
 | 
				
			||||||
		key, err := SearchPublicKeyByContent(KeyToDelete)
 | 
							key, err := searchPublicKeyByContentWithEngine(sess, KeyToDelete)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.Error(4, "SearchPublicKeyByContent: %v", err)
 | 
								log.Error(4, "SearchPublicKeyByContent: %v", err)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
@@ -1421,7 +1421,8 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
 | 
				
			|||||||
	return sshKeysNeedUpdate, nil
 | 
						return sshKeysNeedUpdate, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func addLdapSSHPublicKeys(s *LoginSource, usr *User, SSHPublicKeys []string) bool {
 | 
					// addLdapSSHPublicKeys add a users public keys. Returns true if there are changes.
 | 
				
			||||||
 | 
					func addLdapSSHPublicKeys(usr *User, s *LoginSource, SSHPublicKeys []string) bool {
 | 
				
			||||||
	var sshKeysNeedUpdate bool
 | 
						var sshKeysNeedUpdate bool
 | 
				
			||||||
	for _, sshKey := range SSHPublicKeys {
 | 
						for _, sshKey := range SSHPublicKeys {
 | 
				
			||||||
		_, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sshKey))
 | 
							_, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sshKey))
 | 
				
			||||||
@@ -1440,7 +1441,8 @@ func addLdapSSHPublicKeys(s *LoginSource, usr *User, SSHPublicKeys []string) boo
 | 
				
			|||||||
	return sshKeysNeedUpdate
 | 
						return sshKeysNeedUpdate
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func synchronizeLdapSSHPublicKeys(s *LoginSource, SSHPublicKeys []string, usr *User) bool {
 | 
					// synchronizeLdapSSHPublicKeys updates a users public keys. Returns true if there are changes.
 | 
				
			||||||
 | 
					func synchronizeLdapSSHPublicKeys(usr *User, s *LoginSource, SSHPublicKeys []string) bool {
 | 
				
			||||||
	var sshKeysNeedUpdate bool
 | 
						var sshKeysNeedUpdate bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Trace("synchronizeLdapSSHPublicKeys[%s]: Handling LDAP Public SSH Key synchronization for user %s", s.Name, usr.Name)
 | 
						log.Trace("synchronizeLdapSSHPublicKeys[%s]: Handling LDAP Public SSH Key synchronization for user %s", s.Name, usr.Name)
 | 
				
			||||||
@@ -1479,7 +1481,7 @@ func synchronizeLdapSSHPublicKeys(s *LoginSource, SSHPublicKeys []string, usr *U
 | 
				
			|||||||
			newLdapSSHKeys = append(newLdapSSHKeys, LDAPPublicSSHKey)
 | 
								newLdapSSHKeys = append(newLdapSSHKeys, LDAPPublicSSHKey)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if addLdapSSHPublicKeys(s, usr, newLdapSSHKeys) {
 | 
						if addLdapSSHPublicKeys(usr, s, newLdapSSHKeys) {
 | 
				
			||||||
		sshKeysNeedUpdate = true
 | 
							sshKeysNeedUpdate = true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1581,7 +1583,7 @@ func SyncExternalUsers() {
 | 
				
			|||||||
						log.Error(4, "SyncExternalUsers[%s]: Error creating user %s: %v", s.Name, su.Username, err)
 | 
											log.Error(4, "SyncExternalUsers[%s]: Error creating user %s: %v", s.Name, su.Username, err)
 | 
				
			||||||
					} else if isAttributeSSHPublicKeySet {
 | 
										} else if isAttributeSSHPublicKeySet {
 | 
				
			||||||
						log.Trace("SyncExternalUsers[%s]: Adding LDAP Public SSH Keys for user %s", s.Name, usr.Name)
 | 
											log.Trace("SyncExternalUsers[%s]: Adding LDAP Public SSH Keys for user %s", s.Name, usr.Name)
 | 
				
			||||||
						if addLdapSSHPublicKeys(s, usr, su.SSHPublicKey) {
 | 
											if addLdapSSHPublicKeys(usr, s, su.SSHPublicKey) {
 | 
				
			||||||
							sshKeysNeedUpdate = true
 | 
												sshKeysNeedUpdate = true
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@@ -1589,7 +1591,7 @@ func SyncExternalUsers() {
 | 
				
			|||||||
					existingUsers = append(existingUsers, usr.ID)
 | 
										existingUsers = append(existingUsers, usr.ID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					// Synchronize SSH Public Key if that attribute is set
 | 
										// Synchronize SSH Public Key if that attribute is set
 | 
				
			||||||
					if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(s, su.SSHPublicKey, usr) {
 | 
										if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(usr, s, su.SSHPublicKey) {
 | 
				
			||||||
						sshKeysNeedUpdate = true
 | 
											sshKeysNeedUpdate = true
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -247,10 +247,10 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul
 | 
				
			|||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Trace("Fetching attributes '%v', '%v', '%v', '%v' with filter %s and base %s", ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, userFilter, userDN)
 | 
						log.Trace("Fetching attributes '%v', '%v', '%v', '%v', '%v' with filter %s and base %s", ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, ls.AttributeSSHPublicKey, userFilter, userDN)
 | 
				
			||||||
	search := ldap.NewSearchRequest(
 | 
						search := ldap.NewSearchRequest(
 | 
				
			||||||
		userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, userFilter,
 | 
							userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, userFilter,
 | 
				
			||||||
		[]string{ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail},
 | 
							[]string{ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, ls.AttributeSSHPublicKey},
 | 
				
			||||||
		nil)
 | 
							nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr, err := l.Search(search)
 | 
						sr, err := l.Search(search)
 | 
				
			||||||
@@ -271,6 +271,7 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul
 | 
				
			|||||||
	firstname := sr.Entries[0].GetAttributeValue(ls.AttributeName)
 | 
						firstname := sr.Entries[0].GetAttributeValue(ls.AttributeName)
 | 
				
			||||||
	surname := sr.Entries[0].GetAttributeValue(ls.AttributeSurname)
 | 
						surname := sr.Entries[0].GetAttributeValue(ls.AttributeSurname)
 | 
				
			||||||
	mail := sr.Entries[0].GetAttributeValue(ls.AttributeMail)
 | 
						mail := sr.Entries[0].GetAttributeValue(ls.AttributeMail)
 | 
				
			||||||
 | 
						sshPublicKey := sr.Entries[0].GetAttributeValues(ls.AttributeSSHPublicKey)
 | 
				
			||||||
	isAdmin := checkAdmin(l, ls, userDN)
 | 
						isAdmin := checkAdmin(l, ls, userDN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !directBind && ls.AttributesInBind {
 | 
						if !directBind && ls.AttributesInBind {
 | 
				
			||||||
@@ -282,11 +283,12 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &SearchResult{
 | 
						return &SearchResult{
 | 
				
			||||||
		Username: username,
 | 
							Username:     username,
 | 
				
			||||||
		Name:     firstname,
 | 
							Name:         firstname,
 | 
				
			||||||
		Surname:  surname,
 | 
							Surname:      surname,
 | 
				
			||||||
		Mail:     mail,
 | 
							Mail:         mail,
 | 
				
			||||||
		IsAdmin:  isAdmin,
 | 
							SSHPublicKey: sshPublicKey,
 | 
				
			||||||
 | 
							IsAdmin:      isAdmin,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user