Skip to content

Commit

Permalink
Merge pull request #3779 from rundeck/issue/3768
Browse files Browse the repository at this point in the history
Add jetty password encoding compatibility to spring security password validation
  • Loading branch information
gschueler committed Aug 3, 2018
2 parents 8631f93 + 0b6e8b1 commit b44a1af
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
3 changes: 3 additions & 0 deletions rundeckapp/grails-app/conf/spring/resources.groovy
Expand Up @@ -45,6 +45,7 @@ import com.dtolabs.rundeck.server.plugins.services.*
import com.dtolabs.rundeck.server.plugins.storage.DbStoragePluginFactory
import com.dtolabs.rundeck.server.storage.StorageTreeFactory
import groovy.io.FileType
import org.rundeck.security.JettyCompatibleSpringSecurityPasswordEncoder
import org.rundeck.security.RundeckJaasAuthorityGranter
import org.rundeck.security.RundeckPreauthenticationRequestHeaderFilter
import org.rundeck.security.RundeckUserDetailsService
Expand Down Expand Up @@ -453,11 +454,13 @@ beans={
]
}
} else {
jettyCompatiblePasswordEncoder(JettyCompatibleSpringSecurityPasswordEncoder)
//if not using jaas for security provide a simple default
Properties realmProperties = new Properties()
realmProperties.load(new File(grailsApplication.config.rundeck.security.fileUserDataSource).newInputStream())
realmPropertyFileDataSource(InMemoryUserDetailsManager, realmProperties)
realmAuthProvider(DaoAuthenticationProvider) {
passwordEncoder = ref("jettyCompatiblePasswordEncoder")
userDetailsService = ref('realmPropertyFileDataSource')
}
}
Expand Down
@@ -0,0 +1,48 @@
/*
* Copyright 2018 Rundeck, Inc. (http://rundeck.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rundeck.security

import org.eclipse.jetty.util.security.Credential
import org.eclipse.jetty.util.security.Password
import org.grails.web.util.WebUtils
import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder

/**
* This class checks passwords the same way the Jetty jaas module.
* When the grails spring security plugin updates to spring security 5.x this class will no longer
* work and will need to be migrated to the new encoder technique
*/
@Deprecated
class JettyCompatibleSpringSecurityPasswordEncoder extends PlaintextPasswordEncoder {

@Override
String encodePassword(final String rawPass, final Object salt) {
return super.encodePassword(rawPass,salt)
}

@Override
boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) {
if(!encPass || !rawPass) return false
if(encPass.startsWith("MD5:")) return Credential.MD5.digest(rawPass) == encPass
if(encPass.startsWith("OBF:")) return Password.obfuscate(rawPass) == encPass
if(encPass.startsWith("CRYPT:")) return Credential.Crypt.crypt(username, rawPass) == encPass
return super.isPasswordValid(encPass,rawPass,salt)
}

String getUsername() {
WebUtils.retrieveGrailsWebRequest().getCurrentRequest().getParameter("j_username")
}
}
@@ -0,0 +1,55 @@
/*
* Copyright 2018 Rundeck, Inc. (http://rundeck.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rundeck.security

import spock.lang.Specification


class JettyCompatibleSpringSecurityPasswordEncoderTest extends Specification {
JettyCompatibleSpringSecurityPasswordEncoder encoder

def setup() {
encoder = new JettyCompatibleSpringSecurityPasswordEncoder()
encoder.metaClass.getUsername = { -> return "jsmith" }
}

def "Is Password Valid Plaintext"() {
expect:
encoder.isPasswordValid("plaintext","plaintext",null)
!encoder.isPasswordValid("plaintext","plaintxt",null)
}

def "Is Password Valid OBF"() {
expect:
encoder.isPasswordValid("OBF:1uve1sho1w8h1vgz1vgv1wui1wtw1vfz1vfv1w991shu1uus","obfusticated",null)
!encoder.isPasswordValid("OBF:1uve1sho1w8h1vgz1vgv1wui1wtw1vfz1vfv1w991shu1uus","nomatch",null)
}
def "Is Password Valid MD5"() {
expect:
encoder.isPasswordValid("MD5:72edc62d1e5f879981032f4ccd82be54","mymd5passwd",null)
!encoder.isPasswordValid("MD5:72edc62d1e5f879981032f4ccd82be54","nomatch",null)
}
def "Is Password Valid CRYPT"() {
expect:
encoder.isPasswordValid("CRYPT:jsf1JcISnTyL6","mycryptpass",null)
!encoder.isPasswordValid("CRYPT:jsf1JcISnTyL6","nomatch",null)
}
def "Is Password Valid null"() {
expect:
!encoder.isPasswordValid("MD5:7ddf32e17a6ac5ce04a8ecbf782ca509",null,null)
!encoder.isPasswordValid(null,"somepassword",null)
}
}

0 comments on commit b44a1af

Please sign in to comment.