diff --git a/server/src/main/java/password/pwm/config/value/ActionValue.java b/server/src/main/java/password/pwm/config/value/ActionValue.java index a72c181a3..e4cb92b42 100644 --- a/server/src/main/java/password/pwm/config/value/ActionValue.java +++ b/server/src/main/java/password/pwm/config/value/ActionValue.java @@ -27,6 +27,7 @@ import password.pwm.config.stored.StoredConfigXmlSerializer; import password.pwm.config.stored.XmlOutputProcessData; import password.pwm.config.value.data.ActionConfiguration; +import password.pwm.error.PwmInternalException; import password.pwm.error.PwmOperationalException; import password.pwm.util.java.JavaHelper; import password.pwm.util.java.JsonUtil; @@ -57,7 +58,7 @@ public class ActionValue extends AbstractValue implements StoredValue public ActionValue( final List values ) { - this.values = Collections.unmodifiableList( values ); + this.values = List.copyOf( JavaHelper.stripNulls( values ) ); } public static StoredValueFactory factory( ) @@ -80,10 +81,7 @@ public ActionValue fromJson( final String input ) ); srcList = srcList == null ? Collections.emptyList() : srcList; - while ( srcList.contains( null ) ) - { - srcList.remove( null ); - } + srcList = JavaHelper.stripNulls( srcList ); return new ActionValue( Collections.unmodifiableList( srcList ) ); } } @@ -97,11 +95,9 @@ public ActionValue fromXmlElement( throws PwmOperationalException { final int syntaxVersion = figureCurrentStoredSyntax( settingElement ); - final List values = new ArrayList<>(); - - final boolean oldType = PwmSettingSyntax.STRING_ARRAY.toString().equals( - settingElement.getAttributeValue( StoredConfigXmlSerializer.StoredConfigXmlConstants.XML_ATTRIBUTE_SYNTAX ) ); final List valueElements = settingElement.getChildren( StoredConfigXmlSerializer.StoredConfigXmlConstants.XML_ELEMENT_VALUE ); + + final List values = new ArrayList<>( valueElements.size() ); for ( final XmlElement loopValueElement : valueElements ) { final String stringValue = loopValueElement.getText(); @@ -109,68 +105,11 @@ public ActionValue fromXmlElement( { if ( syntaxVersion < 2 ) { - if ( oldType ) - { - if ( loopValueElement.getAttributeValue( StoredConfigXmlSerializer.StoredConfigXmlConstants.XML_ATTRIBUTE_LOCALE ) == null ) - { - final ActionConfiguration.ActionConfigurationOldVersion1 oldVersion1 = ActionConfiguration.ActionConfigurationOldVersion1 - .parseOldConfigString( stringValue ); - values.add( convertOldVersion1Values( oldVersion1 ) ); - } - } - else - { - final ActionConfiguration.ActionConfigurationOldVersion1 parsedAc = JsonUtil - .deserialize( stringValue, ActionConfiguration.ActionConfigurationOldVersion1.class ); - if ( parsedAc != null ) - { - final Optional decodedValue = StoredValueEncoder.decode( - parsedAc.getPassword(), - StoredValueEncoder.Mode.ENCODED, - pwmSecurityKey ); - decodedValue.ifPresent( s -> - { - values.add( convertOldVersion1Values( parsedAc.toBuilder().password( s ).build() ) ); - } ); - } - } + parseV1configurationValue( pwmSecurityKey, loopValueElement, stringValue ).ifPresent( values::add ); } else if ( syntaxVersion == 2 ) { - final ActionConfiguration value = JsonUtil.deserialize( stringValue, ActionConfiguration.class ); - final List clonedWebActions = new ArrayList<>(); - for ( final ActionConfiguration.WebAction webAction : value.getWebActions() ) - { - // add success status if empty list - final List successStatus = JavaHelper.isEmpty( webAction.getSuccessStatus() ) - ? Collections.singletonList( 200 ) - : webAction.getSuccessStatus(); - - // decrypt pw - try - { - - - final Optional decodedValue = StoredValueEncoder.decode( - webAction.getPassword(), - StoredValueEncoder.Mode.ENCODED, - pwmSecurityKey ); - decodedValue.ifPresent( s -> - { - clonedWebActions.add( webAction.toBuilder() - .password( s ) - .successStatus( successStatus ) - .build() ); - } ); - } - catch ( final PwmOperationalException e ) - { - LOGGER.warn( () -> "error decoding stored pw value on setting '" + pwmSetting.getKey() + "': " + e.getMessage() ); - } - } - - final ActionConfiguration clonedAction = value.toBuilder().webActions( clonedWebActions ).build(); - values.add( clonedAction ); + parseV2configurationValue( pwmSetting, pwmSecurityKey, stringValue ).ifPresent( values::add ); } else { @@ -181,39 +120,97 @@ else if ( syntaxVersion == 2 ) return new ActionValue( values ); } - }; - } - @Override - public List toXmlValues( final String valueElementName, final XmlOutputProcessData xmlOutputProcessData ) - { - final List returnList = new ArrayList<>(); - for ( final ActionConfiguration value : values ) - { - final List clonedWebActions = new ArrayList<>(); - for ( final ActionConfiguration.WebAction webAction : value.getWebActions() ) + private Optional parseV1configurationValue( + final PwmSecurityKey pwmSecurityKey, + final XmlElement loopValueElement, + final String stringValue + ) + throws PwmOperationalException + { + final XmlElement settingElement = loopValueElement.parent(); + final boolean oldType = PwmSettingSyntax.STRING_ARRAY.toString().equals( + settingElement.getAttributeValue( StoredConfigXmlSerializer.StoredConfigXmlConstants.XML_ATTRIBUTE_SYNTAX ) ); + + if ( oldType ) + { + if ( loopValueElement.getAttributeValue( StoredConfigXmlSerializer.StoredConfigXmlConstants.XML_ATTRIBUTE_LOCALE ).isEmpty() ) + { + final ActionConfiguration.ActionConfigurationOldVersion1 oldVersion1 = ActionConfiguration.ActionConfigurationOldVersion1 + .parseOldConfigString( stringValue ); + return Optional.of( convertOldVersion1Values( oldVersion1 ) ); + } + } + else + { + final ActionConfiguration.ActionConfigurationOldVersion1 parsedAc = JsonUtil + .deserialize( stringValue, ActionConfiguration.ActionConfigurationOldVersion1.class ); + if ( parsedAc != null ) + { + final Optional decodedValue = StoredValueEncoder.decode( + parsedAc.getPassword(), + StoredValueEncoder.Mode.ENCODED, + pwmSecurityKey ); + + if ( decodedValue.isPresent() ) + { + return Optional.of( convertOldVersion1Values( parsedAc.toBuilder().password( decodedValue.get() ).build() ) ); + } + } + } + + return Optional.empty(); + } + + private Optional parseV2configurationValue( final PwmSetting pwmSetting, final PwmSecurityKey pwmSecurityKey, final String stringValue ) { - if ( !StringUtil.isEmpty( webAction.getPassword() ) ) + final ActionConfiguration value = JsonUtil.deserialize( stringValue, ActionConfiguration.class ); + final List clonedWebActions = new ArrayList<>( value.getWebActions().size() ); + + for ( final ActionConfiguration.WebAction webAction : value.getWebActions() ) { + // add success status if empty list + final List successStatus = JavaHelper.isEmpty( webAction.getSuccessStatus() ) + ? Collections.singletonList( 200 ) + : webAction.getSuccessStatus(); + + // decrypt pw + Optional decodedValue = Optional.empty(); try { - final String encodedValue = StoredValueEncoder.encode( + decodedValue = StoredValueEncoder.decode( webAction.getPassword(), - xmlOutputProcessData.getStoredValueEncoderMode(), - xmlOutputProcessData.getPwmSecurityKey() ); - clonedWebActions.add( webAction.toBuilder() - .password( encodedValue ) - .build() ); + StoredValueEncoder.Mode.ENCODED, + pwmSecurityKey ); } catch ( final PwmOperationalException e ) { - LOGGER.warn( () -> "error encoding stored pw value: " + e.getMessage() ); + LOGGER.warn( () -> "error decoding stored pw value on setting '" + pwmSetting.getKey() + "': " + e.getMessage() ); } + + final String passwordValue = decodedValue.orElse( "" ); + clonedWebActions.add( webAction.toBuilder() + .password( passwordValue ) + .successStatus( successStatus ) + .build() ); } + + return Optional.of( value.toBuilder().webActions( clonedWebActions ).build() ); } + }; + } - final ActionConfiguration clonedAction = value.toBuilder().webActions( clonedWebActions ).build(); + @Override + public List toXmlValues( final String valueElementName, final XmlOutputProcessData xmlOutputProcessData ) + { + final List returnList = new ArrayList<>( values.size() ); + for ( final ActionConfiguration value : values ) + { + final List clonedWebActions = encodePasswordInWebActions( value.getWebActions(), xmlOutputProcessData ); + final ActionConfiguration clonedAction = value.toBuilder() + .webActions( clonedWebActions ) + .build(); final XmlElement valueElement = XmlFactory.getFactory().newElement( valueElementName ); @@ -223,6 +220,35 @@ public List toXmlValues( final String valueElementName, final XmlOut return returnList; } + private static List encodePasswordInWebActions( + final List webActions, + final XmlOutputProcessData xmlOutputProcessData + ) + { + final List clonedWebActions = new ArrayList<>( webActions.size() ); + + for ( final ActionConfiguration.WebAction webAction : webActions ) + { + try + { + final String encodedValue = StringUtil.isEmpty( webAction.getPassword() ) + ? "" + : StoredValueEncoder.encode( webAction.getPassword(), + xmlOutputProcessData.getStoredValueEncoderMode(), + xmlOutputProcessData.getPwmSecurityKey() ); + clonedWebActions.add( webAction.toBuilder() + .password( encodedValue ) + .build() ); + } + catch ( final PwmOperationalException e ) + { + throw new PwmInternalException( "error encoding stored pw value: " + e.getMessage(), e ); + } + } + return Collections.unmodifiableList( clonedWebActions ); + } + + @Override public List toNativeObject( ) { diff --git a/server/src/test/java/password/pwm/config/value/ActionValueTest.java b/server/src/test/java/password/pwm/config/value/ActionValueTest.java new file mode 100644 index 000000000..d02f9f055 --- /dev/null +++ b/server/src/test/java/password/pwm/config/value/ActionValueTest.java @@ -0,0 +1,228 @@ +/* + * Password Management Servlets (PWM) + * http://www.pwm-project.org + * + * Copyright (c) 2006-2009 Novell, Inc. + * Copyright (c) 2009-2021 The PWM Project + * + * 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 password.pwm.config.value; + +import org.junit.Assert; +import org.junit.Test; +import password.pwm.config.PwmSetting; +import password.pwm.config.stored.XmlOutputProcessData; +import password.pwm.config.value.data.ActionConfiguration; +import password.pwm.util.java.JsonUtil; +import password.pwm.util.java.XmlDocument; +import password.pwm.util.java.XmlElement; +import password.pwm.util.java.XmlFactory; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.ResourceBundle; + +public class ActionValueTest +{ + @Test + public void fromXmlTestFull() + throws Exception + { + final String settingValueValue = xmlTestValue( "jsonDataFull" ); + final InputStream inputStream = new ByteArrayInputStream( settingValueValue.getBytes() ); + final XmlDocument xmlDocument = XmlFactory.getFactory().parseXml( inputStream ); + final XmlElement settingsElement = xmlDocument.getRootElement(); + final XmlElement settingElement = settingsElement.getChild( "setting" ).orElseThrow(); + final ActionValue actionValue = ( ActionValue ) ActionValue.factory().fromXmlElement( PwmSetting.CHANGE_PASSWORD_WRITE_ATTRIBUTES, settingElement, null ); + + final List actionConfigurations = actionValue.toNativeObject(); + Assert.assertEquals( 1, actionConfigurations.size() ); + + final ActionConfiguration action1 = actionConfigurations.get( 0 ); + Assert.assertEquals( "action1", action1.getName() ); + Assert.assertEquals( "description", action1.getDescription() ); + Assert.assertEquals( 1, action1.getWebActions().size() ); + Assert.assertEquals( 1, action1.getLdapActions().size() ); + + final ActionConfiguration.WebAction webAction = action1.getWebActions().get( 0 ); + Assert.assertEquals( ActionConfiguration.WebMethod.post, webAction.getMethod() ); + Assert.assertEquals( 2, webAction.getHeaders().size() ); + Assert.assertEquals( "v1", webAction.getHeaders().get( "h1" ) ); + Assert.assertEquals( "v2", webAction.getHeaders().get( "h2" ) ); + Assert.assertEquals( "username", webAction.getUsername() ); + Assert.assertEquals( "password", webAction.getPassword() ); + Assert.assertEquals( "https://www.example.com", webAction.getUrl() ); + Assert.assertEquals( "BODY", webAction.getBody() ); + Assert.assertEquals( getTestCerts(), webAction.getCertificates() ); + Assert.assertEquals( 2, webAction.getSuccessStatus().size() ); + Assert.assertTrue( webAction.getSuccessStatus().contains( 200 ) ); + Assert.assertTrue( webAction.getSuccessStatus().contains( 201 ) ); + + final ActionConfiguration.LdapAction ldapAction = action1.getLdapActions().get( 0 ); + Assert.assertEquals( "ldapAttribute1", ldapAction.getAttributeName() ); + Assert.assertEquals( "value1", ldapAction.getAttributeValue() ); + Assert.assertEquals( ActionConfiguration.LdapMethod.remove, ldapAction.getLdapMethod() ); + } + + @Test + public void toXmlTestFull() + throws Exception + { + final ActionConfiguration.WebAction webAction = ActionConfiguration.WebAction.builder() + .method( ActionConfiguration.WebMethod.post ) + .headers( makeHeaderTestMap() ) + .username( "username" ) + .password( "password" ) + .url( "https://www.example.com" ) + .body( "BODY" ) + .certificates( getTestCerts() ) + .successStatus( List.of( 200, 201 ) ) + .build(); + + final ActionConfiguration.LdapAction ldapAction = ActionConfiguration.LdapAction.builder() + .attributeName( "ldapAttribute1" ) + .attributeValue( "value1" ) + .ldapMethod( ActionConfiguration.LdapMethod.remove ) + .build(); + + final ActionConfiguration action1 = ActionConfiguration.builder() + .name( "action1" ) + .description( "description" ) + .webActions( List.of( webAction ) ) + .ldapActions( List.of( ldapAction ) ) + .build(); + + final ActionValue actionValue = new ActionValue( List.of( action1 ) ); + final XmlOutputProcessData xmlOutputProcessData = XmlOutputProcessData.builder() + .storedValueEncoderMode( StoredValueEncoder.Mode.PLAIN ) + .build(); + final List valueElements = actionValue.toXmlValues( "value", xmlOutputProcessData ); + final XmlElement settingElement = XmlFactory.getFactory().newElement( "setting" ); + settingElement.setAttribute( "syntaxVersion", "2" ); + settingElement.addContent( valueElements ); + + final XmlDocument xmlDocument = XmlFactory.getFactory().newDocument( "settings" ); + xmlDocument.getRootElement().addContent( settingElement ); + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + XmlFactory.getFactory().outputDocument( xmlDocument, baos, XmlFactory.OutputFlag.Compact ); + final String xmlStringOutput = baos.toString(); + + Assert.assertEquals( xmlTestValue( "jsonDataFull" ), xmlStringOutput ); + } + + @Test + public void fromXmlBasicWeb() + throws Exception + { + final String settingValueValue = xmlTestValue( "jsonDataBasicWeb" ); + final InputStream inputStream = new ByteArrayInputStream( settingValueValue.getBytes() ); + final XmlDocument xmlDocument = XmlFactory.getFactory().parseXml( inputStream ); + final XmlElement settingsElement = xmlDocument.getRootElement(); + final XmlElement settingElement = settingsElement.getChild( "setting" ).orElseThrow(); + final ActionValue actionValue = ( ActionValue ) ActionValue.factory().fromXmlElement( PwmSetting.CHANGE_PASSWORD_WRITE_ATTRIBUTES, settingElement, null ); + + final List actionConfigurations = actionValue.toNativeObject(); + Assert.assertEquals( 1, actionConfigurations.size() ); + + final ActionConfiguration action1 = actionConfigurations.get( 0 ); + Assert.assertEquals( "action1", action1.getName() ); + Assert.assertNull( action1.getDescription() ); + Assert.assertEquals( 1, action1.getWebActions().size() ); + Assert.assertEquals( 0, action1.getLdapActions().size() ); + + final ActionConfiguration.WebAction webAction = action1.getWebActions().get( 0 ); + Assert.assertEquals( ActionConfiguration.WebMethod.get, webAction.getMethod() ); + Assert.assertEquals( "", webAction.getUsername() ); + Assert.assertEquals( "", webAction.getPassword() ); + Assert.assertEquals( "https://www.example.com", webAction.getUrl() ); + Assert.assertEquals( "", webAction.getBody() ); + Assert.assertEquals( 0, webAction.getCertificates().size() ); + Assert.assertEquals( 1, webAction.getSuccessStatus().size() ); + Assert.assertTrue( webAction.getSuccessStatus().contains( 200 ) ); + } + + + @Test + public void toXmlTestBasicWeb() + throws Exception + { + final ActionConfiguration.WebAction webAction = ActionConfiguration.WebAction.builder() + .method( ActionConfiguration.WebMethod.get ) + .url( "https://www.example.com" ) + .build(); + + final ActionConfiguration action1 = ActionConfiguration.builder() + .name( "action1" ) + .webActions( List.of( webAction ) ) + .build(); + + final ActionValue actionValue = new ActionValue( List.of( action1 ) ); + final XmlOutputProcessData xmlOutputProcessData = XmlOutputProcessData.builder() + .storedValueEncoderMode( StoredValueEncoder.Mode.PLAIN ) + .build(); + + final List valueElements = actionValue.toXmlValues( "value", xmlOutputProcessData ); + final XmlElement settingElement = XmlFactory.getFactory().newElement( "setting" ); + settingElement.setAttribute( "syntaxVersion", "2" ); + settingElement.addContent( valueElements ); + + final XmlDocument xmlDocument = XmlFactory.getFactory().newDocument( "settings" ); + xmlDocument.getRootElement().addContent( settingElement ); + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + XmlFactory.getFactory().outputDocument( xmlDocument, baos, XmlFactory.OutputFlag.Compact ); + final String xmlStringOutput = baos.toString(); + + Assert.assertEquals( xmlTestValue( "jsonDataBasicWeb" ), xmlStringOutput ); + } + + private static Map makeHeaderTestMap() + { + // ordered map is required for json string matching + final Map map = new LinkedHashMap<>(); + map.put( "h1", "v1" ); + map.put( "h2", "v2" ); + return Collections.unmodifiableMap( map ); + } + + private static List getTestCerts() + { + final String stringData = readResourceString( "certData1" ); + final X509Certificate[] certArray = JsonUtil.deserialize( stringData, X509Certificate[].class ); + return Arrays.asList( certArray ); + } + + private static String xmlTestValue( final String key ) + { + final String jsonValue = readResourceString( key ); + final String xmlValueValue = "" + jsonValue + ""; + final String settingValueValue = "" + xmlValueValue + ""; + return "" + settingValueValue + ""; + } + + private static String readResourceString( final String key ) + { + final ResourceBundle bundle = ResourceBundle.getBundle( ActionValueTest.class.getName() ); + return bundle.getString( key ); + } +} diff --git a/server/src/test/resources/password/pwm/config/value/ActionValueTest.properties b/server/src/test/resources/password/pwm/config/value/ActionValueTest.properties new file mode 100644 index 000000000..376a9a25b --- /dev/null +++ b/server/src/test/resources/password/pwm/config/value/ActionValueTest.properties @@ -0,0 +1,23 @@ +# +# Password Management Servlets (PWM) +# http://www.pwm-project.org +# +# Copyright (c) 2006-2009 Novell, Inc. +# Copyright (c) 2009-2021 The PWM Project +# +# 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. +# + +jsonDataFull={"name":"action1","description":"description","webActions":[{"method":"post","headers":{"h1":"v1","h2":"v2"},"url":"https://www.example.com","body":"BODY","username":"username","password":"PLAIN:password","certificates":["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"],"successStatus":[200,201]}],"ldapActions":[{"ldapMethod":"remove","attributeName":"ldapAttribute1","attributeValue":"value1"}]} +certData1=["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"] +jsonDataBasicWeb={"name":"action1","webActions":[{"method":"get","headers":{},"url":"https://www.example.com","body":"","username":"","password":"","certificates":[],"successStatus":[200]}],"ldapActions":[]}