aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Mandrikov <mandrikov@gmail.com>2012-01-12 10:02:16 +0400
committerEvgeny Mandrikov <mandrikov@gmail.com>2012-01-13 11:36:50 +0400
commit095be864644d766a7d5ff2be9cfff55866b875ba (patch)
tree2b633f3bbf3998933a7a1579daba089ee4097e9c
parent7be3485cc15dc72c82790d8069b4c301a1aa5862 (diff)
downloadsonarqube-095be864644d766a7d5ff2be9cfff55866b875ba.tar.gz
sonarqube-095be864644d766a7d5ff2be9cfff55866b875ba.zip
SONAR-3138 Prevent security flaw, refactor code
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/lib/need_authentication.rb145
1 files changed, 81 insertions, 64 deletions
diff --git a/sonar-server/src/main/webapp/WEB-INF/lib/need_authentication.rb b/sonar-server/src/main/webapp/WEB-INF/lib/need_authentication.rb
index e7335d80369..afa3160562b 100644
--- a/sonar-server/src/main/webapp/WEB-INF/lib/need_authentication.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/lib/need_authentication.rb
@@ -22,14 +22,13 @@
# Use Sonar database (table USERS) to authenticate users.
#
class DefaultRealm
- def authenticate?(login, password)
- return false if login.blank? || password.blank?
- user = User.find_by_login(login)
- user && user.authenticated?(password)
- end
-
- def synchronize(user, password)
- # nothing to do
+ def authenticate?(username, password)
+ user = User.find_by_login(username)
+ if user && user.authenticated?(password)
+ return user
+ else
+ return nil
+ end
end
def editable_password?
@@ -39,7 +38,7 @@ end
#
# Use an external security system with fallback to Sonar database.
-# See the Java extension point org.sonar.api.security.Realm
+# See the Java extension point org.sonar.api.security.SecurityRealm
#
class PluginRealm
def initialize(java_realm)
@@ -48,43 +47,92 @@ class PluginRealm
@java_groups_provider = java_realm.getGroupsProvider()
end
- def authenticate?(login, password)
- return false if login.blank? || password.blank?
- begin
- if @java_authenticator.authenticate(login, password)
- return true
+ def authenticate?(username, password)
+ if @java_users_provider
+ begin
+ details = @java_users_provider.doGetUserDetails(username)
+ rescue Exception => e
+ Rails.logger.error("Error from external users provider: #{e.message}")
+ return fallback(username, password)
+ else
+ # User exist in external system
+ auth(username, password, details) if details
+ # No such user in external system
+ return fallback(username, password)
end
- rescue Exception => e
- Java::OrgSonarServerUi::JRubyFacade.new.logError("Error from external authenticator: #{e.message}")
+ else
+ # Legacy authenticator
+ return auth(username, password, nil)
end
- # Fallback to password from Sonar Database
- user = User.find_by_login(login)
- return user && user.authenticated?(password)
end
- def synchronize(user, password)
- if @java_users_provider
+ #
+ # Fallback to password from Sonar Database
+ #
+ def fallback(username, password)
+ user = User.find_by_login(username)
+ if user && user.authenticated?(password)
+ return user
+ else
+ return nil
+ end
+ end
+
+ #
+ # Authenticate user using external system
+ #
+ def auth(username, password, details)
+ if @java_authenticator
begin
- details = @java_users_provider.doGetUserDetails(user.login)
+ status = @java_authenticator.authenticate(username, password)
rescue Exception => e
- Java::OrgSonarServerUi::JRubyFacade.new.logError("Error from external users provider: #{e.message}")
+ Rails.logger.error("Error from external authenticator: #{e.message}")
+ return fallback(username, password)
else
- if details
- user.update_attributes(:name => details.getName(), :email => details.getEmail(), :password => password, :password_confirmation => password)
- # Synchronize groups only when succeeded to synchronize details
- synchronize_groups(user)
- user.save
- end
+ return nil if !status
+ # Authenticated
+ return syncronize(username, password, details)
end
+ else
+ # No authenticator
+ return nil
end
end
+ #
+ # Authentication in external system was successful - replicate password, details and groups into Sonar
+ #
+ def syncronize(username, password, details)
+ user = User.find_by_login(username)
+ if !user
+ # No such user in Sonar database
+ java_facade = Java::OrgSonarServerUi::JRubyFacade.new
+ return nil if !java_facade.getSettings().getBoolean('sonar.authenticator.createUsers')
+ # Automatically create a user in the sonar db if authentication has been successfully done
+ user = User.new(:login => username, :name => username, :email => '', :password => password, :password_confirmation => password)
+ default_group_name = java_facade.getSettings().getString('sonar.defaultGroup')
+ default_group = Group.find_by_name(default_group_name)
+ if default_group
+ user.groups << default_group
+ else
+ Rails.logger.error("The default user group does not exist: #{default_group_name}. Please check the parameter 'Default user group' in general settings.")
+ end
+ end
+ if details
+ user.update_attributes(:name => details.getName(), :email => details.getEmail())
+ end
+ user.update_attributes(:password => password, :password_confirmation => password)
+ synchronize_groups(user)
+ user.save
+ return user
+ end
+
def synchronize_groups(user)
if @java_groups_provider
begin
groups = @java_groups_provider.doGetGroups(user.login)
rescue Exception => e
- Java::OrgSonarServerUi::JRubyFacade.new.logError("Error from external groups provider: #{e.message}")
+ Rails.logger.error("Error from external groups provider: #{e.message}")
else
if groups
user.groups = []
@@ -139,47 +187,16 @@ module NeedAuthentication
# This will also let us return a human error message.
#
def authenticate(login, password)
- return nil if login.blank?
- java_facade = Java::OrgSonarServerUi::JRubyFacade.new
+ return nil if login.blank? || password.blank?
# Downcase login (typically for Active Directory)
# Note that login in Sonar DB is case-sensitive, however in this case authentication and automatic user creation will always happen with downcase login
- downcase = java_facade.getSettings().getBoolean('sonar.authenticator.downcase')
+ downcase = Java::OrgSonarServerUi::JRubyFacade.new.getSettings().getBoolean('sonar.authenticator.downcase')
if downcase
login = login.downcase
end
- user = User.find_by_login(login)
- if user
- # User exists
- return nil if !RealmFactory.realm.authenticate?(login, password)
- # Password correct
-
- # Synchronize details
- RealmFactory.realm.synchronize(user, password)
- else
- # User not found
- return nil if !RealmFactory.realm.authenticate?(login, password)
- # Password correct
-
- # Automatically create a user in the sonar db if authentication has been successfully done
- create_user = java_facade.getSettings().getBoolean('sonar.authenticator.createUsers')
- if create_user
- user = User.new(:login => login, :name => login, :email => '', :password => password, :password_confirmation => password)
- default_group_name = java_facade.getSettings().getString('sonar.defaultGroup')
- default_group = Group.find_by_name(default_group_name)
- if default_group
- user.groups<<default_group
- user.save
- else
- logger.error("The default user group does not exist: #{default_group_name}. Please check the parameter 'Default user group' in general settings.")
- end
-
- # Synchronize details
- RealmFactory.realm.synchronize(user, password)
- end
- end
- return user
+ return RealmFactory.realm.authenticate?(login, password)
end
def editable_password?