axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ruchith Fernando <ruchith.ferna...@gmail.com>
Subject Re: Rampart STS Username service not returning password in callback
Date Fri, 25 Jan 2013 03:20:30 GMT
Hi Guys,

This seems to be a bug in WSS4J.

In the plain text password case the validator[1] should simply load
the password into the callback and let the callback handler take care
of authentication.
IIRC this was the behavior earlier with the use of
WSPasswordCallback.USERNAME_TOKEN_UNKNOWN. This allows the service
developer to store any derived/hashed form of the password and then
use the callback handler to process incoming passwords.

Thanks,
Ruchith

1.) http://svn.apache.org/repos/asf/webservices/wss4j/tags/1_6_4/src/main/java/org/apache/ws/security/validate/UsernameTokenValidator.java


On Mon, Jan 21, 2013 at 6:59 AM, Martin Gainty <mgainty@hotmail.com> wrote:
>
>
>
> ________________________________
> From: brianreinhold@lampreynetworks.com
> To: java-dev@axis.apache.org
> Subject: RE: Rampart STS Username service not returning password in callback
> Date: Sun, 20 Jan 2013 08:10:04 -0500
>
> Martin,
>
>
>
> I’m not sure I follow what you are saying. Are you suggesting there is a
> means to accomplish the same thing (get actual sent password in the
> callback) without changing the code AND is compliant with WS-Trust clients?
>
> MG>yes...take this example from
> org.apache.ws.security.dom.handler.CallbackRefTest
> MG>
>
> private CallbackHandler callbackHandler = new
> UsernamePasswordCallbackHandler();
>
>   /**
>      * A test for WSHandler.getPassword(...) where the password is obtained
> from a
>      * Callback Handler, which is obtained from the handler options using a
> ref.
>      */
>     @org.junit.Test
>     public void
>     testHandlerOptionRef() throws Exception {
>         final WSSConfig cfg = WSSConfig.getNewInstance();
>         final RequestData reqData = new RequestData();
>         reqData.setWssConfig(cfg);
>         reqData.setUsername("alice");
>         reqData.setPwType(WSConstants.PW_DIGEST);    // type of requested
> Password from response can be PW_TEXT
>         reqData.setMsgContext(new java.util.TreeMap<String, String>());
>         final java.util.List<Integer> actions = new
> java.util.ArrayList<Integer>();
>
> /* Here are the options for our actions
>
>  public static final int NO_SECURITY = 0;
>     public static final int UT = 0x1; // perform UsernameToken
>     public static final int SIGN = 0x2; // Perform Signature
>     public static final int ENCR = 0x4; // Perform Encryption
>
>     public static final int ST_UNSIGNED = 0x8; // perform SAMLToken unsigned
>     public static final int ST_SIGNED = 0x10; // perform SAMLToken signed
>
>     public static final int TS = 0x20; // insert Timestamp
>     public static final int UT_SIGN = 0x40; // perform signature with UT
> secret key
>     public static final int SC = 0x80;      // this is a
> SignatureConfirmation
>
> */
>
>       int action=Integer.valueOf(WSConstants.UT);
>         actions.add(action);
>
> /*
>
> where UsernameToken class contains both username AND password elements
>
>    private Element elementUsername = null;
>     private Element elementPassword = null;
>
> */
>
> /* what is the soap envelope we will use for our document    public static
> final String SAMPLE_SOAP_MSG =
>         "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
>         + "<SOAP-ENV:Envelope "
>         +   "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
>         +   "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
>         +   "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
>         +   "<SOAP-ENV:Body>"
>         +       "<add
> xmlns=\"http://ws.apache.org/counter/counter_port_type\">"
>         +           "<value xmlns=\"\">15</value>"
>         +       "</add>"
>         +   "</SOAP-ENV:Body>"
>         + "</SOAP-ENV:Envelope>";
>
> */
>
> //construct a simple SoapEnvelope doc with counter_port_type set to 15
>         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
>         CustomHandler handler = new CustomHandler();
>
> //public static final String PW_CALLBACK_CLASS = "passwordCallbackClass";
>         handler.setOption(WSHandlerConstants.PW_CALLBACK_REF,
> callbackHandler);
>
> //Notice the handler has not set the password but expects password from
> response created by callback
>         handler.send(
>             WSConstants.UT,
>             doc,
>             reqData,
>             actions,
>             true
>         );
>
>         String outputString =
>             XMLUtils.PrettyDocumentToString(doc);
>         if (LOG.isDebugEnabled()) {
>             LOG.debug(outputString);
>         }
>         assertTrue(outputString.indexOf("alice") != -1);
>         assertTrue(outputString.indexOf("securityPassword") != -1);
>     }
> MG>
>
>
>
> In any case, I think it’s an oversight by WSS4J that they require that the
> service must KNOW the password. In the code I see no way to avoid the issue.
> In all cases when the user’s (my) callback routine is signaled, the callback
> passed to the user always has the password set to null and the user’s
> callback routine is expected to provide the actual password. The latter part
> is okay as a means to validate the password is okay, but what WSS4J needs to
> do then is to provide a second routine, getSentPassword() which is the value
> of the sent password, clear or digested.
>
> MG> recalling the password type is set in the RequestData
> MG> reqData.setPwType(WSConstants.PW_TEXT);
>
> MG> String getSentPassword(Document doc,RequestedData
> reqData,CallbackHandler callbackHandler,int Action,WSHandler handler)
>
>  {
>   if(reqData.getPwType().equals(WSConstants.PASSWORD_DIGEST)
>
>   {
>
>    List<WSSecurityEngineResult> results =
> secEngine.processSecurityHeader(doc, null, callbackHandler, null);
>
>    WSSecurityEngineResult actionResult =
> WSSecurityUtil.fetchActionResult(results, WSConstants.UT);
>     UsernameToken receivedToken =
>         (UsernameToken)
> actionResult.get(WSSecurityEngineResult.TAG_USERNAME_TOKEN);
>       return receivedToken.hashCode());
>
>   }
>
>   if(reqData.getPwType().equals(WSConstants.PASSWORD_TEXT)
>
>   {
>
>     callbackHandler=getPasswordCallbackHandler(reqData);
>
>     WSPasswordCallback password_callback=handler.getPasswordCB(
>          reqData.getUsername(),
>          action,
>          callbackHandler,
>          reqData);
>      return password_callback.getPassword();
>
>    }
>
> }
> MG>
>
>
>
> This would allow the service to respond as it sees fit. In my case that
> would be storing a password digest so my service (and a successful hacker)
> would never be able to know the real passwords.
>
>
>
> I would do that except the callback created implements ‘Callback’ which is
> not part of WSS4J. Changing that interface looks like it would have FAR
> reaching consequences.
> MG>i think we can use WSPasswordCallback password_callback =
> handler.getPasswordCB from WSHandler
>
>
>
> Brian
> MG>WDYT
>
>
>
> From: Martin Gainty [mailto:mgainty@hotmail.com]
> Sent: Saturday, January 19, 2013 7:40 PM
> To: java-dev@axis.apache.org
> Subject: RE: Rampart STS Username service not returning password in callback
>
>
>
>
>
>
>
> ________________________________
>
> From: brianreinhold@lampreynetworks.com
> To: java-dev@axis.apache.org
> Subject: RE: Rampart STS Username service not returning password in callback
> Date: Sat, 19 Jan 2013 08:58:15 -0500
>
> Hi Martin,
>
>
>
> I did something different. The problem is in WSS4J. In the
> UsernameTokenValidation file I simply passed the password to the callback
> constructor which was previously null. Now I have to change the approach a
> little bit. In my handler I read the password, do my hash, and if it matches
> my stored hash I do nothing since the password is already set. This will
> cause WSS4J to accept the message. If it doesn’t match I set the password to
> current password + “bad” just to make it different causing the message to be
> rejected.
>
>
>
> I don’t like it but I really saw no other choice and don’t understand why
> WSS4J didn’t give the choice. They could have added another variable
> ‘rawPassword’ and a getter for it. This would allow the service to use the
> raw password for whatever purpose it needs. The user would still set
> ‘password’ as expected by WSS4J.
>
> MG>take a look at the org.apache.ws.security.dom.message.WSSecUsernameToken
> getSecretKey
>
> MG>/**
>      * getSecretKey
>      *
>      * After the <code>prepare()</code> method was called use this method
>      * to compute a derived secret key. If "useDerivedKey" is set, then the
> returned secret
>      * key is derived as per the UsernameToken 1.1 specification. Otherwise,
> the generation
>      * of this secret key is according to the WS-Trust specifications.
>      *
>      * @return Return the derived secret key of this token or null if
> <code>prepare()</code>
>      * was not called before.
>      */
>
> MG>boolean useDerivedKey is set to false initially so the secretKey coming
> back from WSS4J is a WS-Trust compliant secretKey
> MG>setting plain text Password can be accomplished with
> MG>setPasswordType(WSConstants#PASSWORD_TEXT)
> MG>setPasswordsAreEncoded(false)
> MG>the prepare method sets the password into the UsernameToken object (in
> the prepare method)
>
> MG>ut.setPassword(password);
>
>
>
> It works and I can store passwords as hashes and be interoperable with the
> WS-Trust standard.
>
> MG>you have a solution..and thats all that matters
> MG>congrats on acquiring a WS-Trust solution!..i hope the journey was
> pleasant and as informative for you as  it was for me
>
>
>
> Brian
>
> MG>Martin
>
>
>
> From: Martin Gainty [mailto:mgainty@hotmail.com]
> Sent: Friday, January 18, 2013 11:24 PM
> To: java-dev@axis.apache.org
> Subject: RE: Rampart STS Username service not returning password in callback
>
>
>
> Hi Brian
>
> assume your CallbackHandler looks something like like
>
> public class PWCBHandler implements
> javax.security.auth.callback.CallbackHandler {
>     public void handle(javax.security.auth.callback.Callback[] callbacks)
> throws IOException,
>             javax.security.auth.callback.UnsupportedCallbackException {
>         for (int i = 0; i < callbacks.length; i++) {
>              org.apache.ws.security.WSPasswordCallback pwcb =
> (org.apache.ws.security.WSPasswordCallback)callbacks[i];
>
> put the CallbackHandler into the Options class for the serviceClient to
> pickup e.g.
>
> Options options = client.getOptions();
> options.put(WSHandlerConstants.PW_CALLBACK_REF, new
> PasswordCallbackHandler());
>
>  serviceClient.setOptions(options);
>                 try {
>                     //Blocking invocation
>                     serviceClient.sendReceive(getOMElement());
>                     fail("Service Should throw an error..");
>                 } catch (AxisFault axisFault) {
>                     assertEquals("Testing negative scenarios with Apache
> Rampart. Intentional Exception", axisFault.getMessage());
>                 }
>
> http://wso2.org/library/3733
>
> HTH,
> Martin
> ______________________________________________
> Verzicht und Vertraulichkeitanmerkung/Note de déni et de confidentialité
>
> Diese Nachricht ist vertraulich. Sollten Sie nicht der vorgesehene
> Empfaenger sein, so bitten wir hoeflich um eine Mitteilung. Jede unbefugte
> Weiterleitung oder Fertigung einer Kopie ist unzulaessig. Diese Nachricht
> dient lediglich dem Austausch von Informationen und entfaltet keine
> rechtliche Bindungswirkung. Aufgrund der leichten Manipulierbarkeit von
> E-Mails koennen wir keine Haftung fuer den Inhalt uebernehmen.
>
> Ce message est confidentiel et peut être privilégié. Si vous n'êtes pas le
> destinataire prévu, nous te demandons avec bonté que pour satisfaire
> informez l'expéditeur. N'importe quelle diffusion non autorisée ou la copie
> de ceci est interdite. Ce message sert à l'information seulement et n'aura
> pas n'importe quel effet légalement obligatoire. Étant donné que les email
> peuvent facilement être sujets à la manipulation, nous ne pouvons accepter
> aucune responsabilité pour le contenu fourni.
>
>
>
>
>
> ________________________________
>
> From: brianreinhold@lampreynetworks.com
> To: java-dev@axis.apache.org
> Subject: RE: Rampart STS Username service not returning password in callback
> Date: Fri, 18 Jan 2013 12:01:19 -0500
>
> Martin,
>
>
>
> Can you tell me where the password callback in my service gets called from?
> It’s the password callback configured by the following line in the STS
> service.xml
>
>
>
>
> <ramp:passwordCallbackClass>com.lni.exchange.wan.receive.binding.axis2.PasswordCallback</ramp:passwordCallbackClass>
>
>
>
>
>
> Brian
>
>
>
> From: Martin Gainty [mailto:mgainty@hotmail.com]
> Sent: Wednesday, January 16, 2013 5:14 PM
> To: java-dev@axis.apache.org
> Subject: RE: Rampart STS Username service not returning password in callback
>
>
>
> http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
>
> i think I found an element we can use
>
> (where both noonce and Password would be child elements of
> wsc:DerivedKeyToken) so here is the TestCase
>
>  org.apache.rampart.handler.config.OutflowConfiguration ofc = new
> org.apache.rampart.handler.config.OutflowConfiguration();
>
>   ofc.setActionItems("UsernameToken Encrypt");
>   ofc.setUser("Mohammed");
>   ofc.setAddUTElements("Nonce Created");  //Noonce
>   ofc.setEncryptionParts("{Element}{" + WSSE_NS + "}UsernameToken");
>   ofc.setEncryptionUser("osama");
>   ofc.setEncryptionPropFile("interop.properties");
>   ofc.setPasswordCallbackClass("org.apache.axis2.security.PWCallback");
>   ofc.setEncryptionSymAlgorithm(WSConstants.TRIPLE_DES);  //change this to
> MD5 or SHA-1
>   ofc.setPasswordType(WSConstants.PW_TEXT);
>   ofc.setEncryptionKeyIdentifier(WSSHandlerConstants.SKI_KEY_IDENTIFIER);
>
> //so here is the new OutFlowConfiguration Element
>    ofc.setPassword("YadaYadaYada");
>
>   return ofc;
>
> //org.apache.rampart.handler.config.OutflowConfiguration change
>  public void setPassword(String passwordType) {
>   this.actionList[this.currentAction].put(
>     WSHandlerConstants.PASSWORD, password);
>  }
> //org.apache.ws.security.dom.handler.WSHandlerConstants add this element
> public static final String PASSWORD = "password"
>
> //correct ...why touch WSS4J for one minor update to a constant ..(maybe
> using constant "password" is better)
>
> //org.apache.rampart.handler.config.OutflowConfiguration change with
> constant
> public void setPassword(String passwordType) {
> this.actionList[this.currentAction].put(
>     "password", password);
> }
>
> reference
> http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
>
> WDYT?
> Martin
>></xsd:
>
> ________________________________
>
> No virus found in this message.
> Checked by AVG - www.avg.com
> Version: 2013.0.2890 / Virus Database: 2638/6037 - Release Date: 01/16/13
>
> No virus found in this message.
> Checked by AVG - www.avg.com
> Version: 2013.0.2890 / Virus Database: 2638/6037 - Release Date: 01/16/13
>
> ________________________________
>
> No virus found in this message.
> Checked by AVG - www.avg.com
> Version: 2013.0.2890 / Virus Database: 2639/6041 - Release Date: 01/18/13
>
> No virus found in this message.
> Checked by AVG - www.avg.com
> Version: 2013.0.2890 / Virus Database: 2639/6041 - Release Date: 01/18/13
>
> ________________________________
>
> No virus found in this message.
> Checked by AVG - www.avg.com
> Version: 2013.0.2890 / Virus Database: 2639/6045 - Release Date: 01/20/13
>
> No virus found in this message.
> Checked by AVG - www.avg.com
> Version: 2013.0.2890 / Virus Database: 2639/6045 - Release Date: 01/20/13



-- 
http://ruchith.org

---------------------------------------------------------------------
To unsubscribe, e-mail: java-dev-unsubscribe@axis.apache.org
For additional commands, e-mail: java-dev-help@axis.apache.org


Mime
View raw message