public List process()

in modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java [74:402]


	public List<WSSecurityEngineResult> process(MessageContext msgCtx) throws WSSPolicyException,
	RampartException, WSSecurityException, AxisFault {

		boolean dotDebug = tlog.isDebugEnabled();
		
		log.debug("Enter process(MessageContext msgCtx)");

		RampartMessageData rmd = new RampartMessageData(msgCtx, false);

		RampartPolicyData rpd = rmd.getPolicyData();
		
		msgCtx.setProperty(RampartMessageData.RAMPART_POLICY_DATA, rpd);

        RampartUtil.validateTransport(rmd);

        // If there is no policy information return immediately
        if (rpd == null) {
           return null;
        }


        //TODO these checks have to be done before the convertion to avoid unnecessary convertion to LLOM -> DOOM
        // If the message is a security fault or no security
        // header required by the policy
        if(isSecurityFault(rmd) || !RampartUtil.isSecHeaderRequired(rpd,rmd.isInitiator(),true)) {
			SOAPEnvelope env = Axis2Util.getSOAPEnvelopeFromDOMDocument(rmd.getDocument(), true);

			//Convert back to llom since the inflow cannot use llom
			msgCtx.setEnvelope(env);
			Axis2Util.useDOOM(false);
            log.debug("Return process MessageContext msgCtx)");
            return null;
		}


		List<WSSecurityEngineResult> results;

		WSSecurityEngine engine = new WSSecurityEngine();
		
		//Set rampart's configuration of WSS4J
		engine.setWssConfig(rmd.getConfig());

        RampartConfig rampartConfig = rpd.getRampartConfig();
        if (rampartConfig != null) {
            WSSConfig config = engine.getWssConfig();

            // Inbound Kerberos authentication for web services
            // Check the service policy for Kerberos token and add KerberosTokenValidator for BINARY_TOKEN validation
            SupportingToken endSupptokens = rpd.getEndorsingSupportingTokens();
            if (endSupptokens != null && endSupptokens.getTokens() != null &&
                endSupptokens.getTokens().size() > 0) {
                
                log.debug("Processing endorsing supporting tokens");
                
                for (org.apache.ws.secpolicy.model.Token token : endSupptokens.getTokens()) {
                    if (token instanceof KerberosToken) {
                        log.debug("KerberosToken is found as part of the endorsing supporting tokens.Check for KerberosConfig.");
                        KerberosConfig kerberosConfig = rampartConfig.getKerberosConfig();
                        
                        if (null != kerberosConfig){
                            log.debug("KerberosConfig is found.");
                            log.debug("Creating KerberosTokenValidor with the available KerberosConfig.");
                            KerberosTokenValidator kerberosValidator = new KerberosTokenValidator();
                            
                            KerberosTokenDecoder kerberosTokenDecoder = RampartUtil.getKerberosTokenDecoder(msgCtx, kerberosConfig);
                            if (kerberosTokenDecoder != null) {
                                kerberosValidator.setKerberosTokenDecoder(kerberosTokenDecoder);
                            }
                            kerberosValidator.setContextName(kerberosConfig.getJaasContext());
                            kerberosValidator.setServiceName(kerberosConfig.getServicePrincipalName());
                            String serviceNameForm = kerberosConfig.getServicePrincipalNameForm();
                            
                            if (KerberosConfig.USERNAME_NAME_FORM.equals(serviceNameForm)) {
                                kerberosValidator.setUsernameServiceNameForm(true);    
                            }
                            
                            String principalName = kerberosConfig.getPrincipalName();
                            if (null == principalName){
                                log.debug("Principal name is not available in the KerberosConfig.Using the Rampart configuration's user.");
                                principalName = rampartConfig.getUser();
                            }
                            
                            String password = kerberosConfig.getPrincipalPassword();
                            if (password == null) {
                                log.debug("Principal password is not available in the KerberosConfig.Trying with the configured Rampart password callback.");
                                CallbackHandler handler = RampartUtil.getPasswordCB(rmd);

                                if (handler != null) {
                                    WSPasswordCallback[] cb = { 
                                            new WSPasswordCallback(principalName, WSPasswordCallback.CUSTOM_TOKEN) 
                                    };
                                    
                                    try {
                                        handler.handle(cb);
                                        if (cb[0].getPassword() != null && !"".equals(cb[0].getPassword())) {
                                            password = cb[0].getPassword();
                                        }
                                    } catch (IOException e) {
                                        throw new RampartException("errorInGettingPasswordForUser", new String[] { principalName }, e);
                                    } catch (UnsupportedCallbackException e) {
                                        throw new RampartException("errorInGettingPasswordForUser", new String[] { principalName }, e);
                                    }
                                } else{
                                    log.debug("No Rampart password handler is configured.");
                                }
                            }
                            
                            if (principalName != null && password != null) {
                                NamePasswordCallbackHandler cb = new NamePasswordCallbackHandler(principalName, password);                            
                                kerberosValidator.setCallbackHandler(cb);
                            }
                            
                            config.setValidator(WSConstants.BINARY_TOKEN, kerberosValidator);
                            log.debug("KerberosTokenValidator is configured and set for BINARY_TOKEN.");
                        } else {
                            log.debug("KerberosConfig is not found.Skipping configurating and setting of a Kerberos validator.");
                        }
                    }
                }
            }
            
            engine.setWssConfig(config);
        }

        ValidatorData data = new ValidatorData(rmd);

		SOAPHeader header = rmd.getMsgContext().getEnvelope().getHeader();
		if(header == null) {
		    throw new RampartException("missingSOAPHeader");
		}
		
        ArrayList headerBlocks = header.getHeaderBlocksWithNSURI(WSConstants.WSSE_NS);
		SOAPHeaderBlock secHeader = null;
		//Issue is axiom - a returned collection must not be null
		if(headerBlocks != null) {
    		Iterator headerBlocksIterator = headerBlocks.iterator();
    		while (headerBlocksIterator.hasNext()) {
    			SOAPHeaderBlock elem = (SOAPHeaderBlock) headerBlocksIterator.next();
    			if(elem.getLocalName().equals(WSConstants.WSSE_LN)) {
    				secHeader = elem;
    				break;
    			}
    		}
		}
		
		if(secHeader == null) {
		    throw new RampartException("missingSecurityHeader");
		}
		
		long t0=0, t1=0, t2=0, t3=0;
		if(dotDebug){
			t0 = System.currentTimeMillis();
		}

		//wss4j does not allow username tokens with no password per default, see https://issues.apache.org/jira/browse/WSS-420
		//configure it to allow them explicitly if at least one username token assertion with no password requirement is found
                RequestData requestData = new RequestData();
		if (!rmd.isInitiator()) {
		    Collection<UsernameToken> usernameTokens = RampartUtil.getUsernameTokens(rpd);
		    for (UsernameToken usernameTok : usernameTokens) {
		        if (usernameTok.isNoPassword()) {
		            log.debug("Found UsernameToken with no password assertion in policy, configuring ws security processing to allow username tokens without password." );
		            requestData.setAllowUsernameTokenNoPassword(true);
		            break;
		        }
		    }
		}
		
		String actorValue = secHeader.getRole();

		Crypto signatureCrypto = RampartUtil.getSignatureCrypto(rpd.getRampartConfig(), 
                msgCtx.getAxisService().getClassLoader());
                TokenCallbackHandler tokenCallbackHandler = new TokenCallbackHandler(rmd.getTokenStorage(), RampartUtil.getPasswordCB(rmd));
                if(rpd.isSymmetricBinding()) {
                    //Here we have to create the CB handler to get the tokens from the 
                    //token storage
                    log.debug("Processing security header using SymetricBinding");
                    requestData.setEncodePasswords(true);
                    requestData.setCallbackHandler(tokenCallbackHandler);
                    requestData.setSigVerCrypto(signatureCrypto);
                    requestData.setActor(actorValue);
                    requestData.setDecCrypto(RampartUtil.getEncryptionCrypto(rpd.getRampartConfig(), msgCtx.getAxisService().getClassLoader()));

                    WSHandlerResult result = engine.processSecurityHeader(rmd.getDocument(), requestData); 
                    results = result.getResults();
            // Removcryption tokens if this is the initiator and if initiator is receiving a message

                    if (rmd.isInitiator() && (msgCtx.getFLOW() == MessageContext.IN_FLOW ||
                            msgCtx.getFLOW() == MessageContext.IN_FAULT_FLOW)) {
                        tokenCallbackHandler.removeEncryptedToken();
                    }

                } else {

                    log.debug("Processing security header in normal path");
                    WSHandlerResult result = engine.processSecurityHeader(rmd.getDocument(), actorValue, tokenCallbackHandler, signatureCrypto, RampartUtil.getEncryptionCrypto(rpd.getRampartConfig(), msgCtx.getAxisService().getClassLoader()));
                    results = result.getResults();
		}

		if(dotDebug){
			t1 = System.currentTimeMillis();
		}

                //Store symm tokens
                //Pick the first SAML token
                //TODO : This is a hack , MUST FIX
                //get the sec context id from the req msg ctx 
		
		//Store username in MessageContext property

                if (results != null) {
                    for (int j = 0; j < results.size(); j++) {
                        WSSecurityEngineResult wser = (WSSecurityEngineResult) results.get(j);
                        final Integer actInt =
                                (Integer) wser.get(WSSecurityEngineResult.TAG_ACTION);
                        if (WSConstants.ST_UNSIGNED == actInt.intValue()) {
        
                            Object samlAssertion = wser.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
        
                            SAMLAssertionHandler samlAssertionHandler
                                    = SAMLAssertionHandlerFactory.createAssertionHandler(samlAssertion);
        
                            if (samlAssertionHandler.isBearerAssertion()) {
                                break;
                            }
                            //Store the token
                            try {
                                TokenStorage store = rmd.getTokenStorage();
                                if (store.getToken(samlAssertionHandler.getAssertionId()) == null) {
                                    Token token = new Token(samlAssertionHandler.getAssertionId(),
                                            samlAssertionHandler.getAssertionElement(),
                                            Date.from(samlAssertionHandler.getDateNotBefore()),
                                            Date.from(samlAssertionHandler.getDateNotOnOrAfter()));
        
                                    token.setSecret(samlAssertionHandler.
                                            getAssertionKeyInfoSecret(signatureCrypto, tokenCallbackHandler));
                                    store.add(token);
                                }
                            } catch (Exception e) {
                                throw new RampartException(
                                        "errorInAddingTokenIntoStore", e);
                            }
                        } else if (WSConstants.UT == actInt) {
        
                            java.security.Principal principal = (java.security.Principal) wser.get(WSSecurityEngineResult.TAG_PRINCIPAL);
        
                            UsernameTokenPrincipal userNameTokenPrincipal = (UsernameTokenPrincipal)principal;
                            String username = userNameTokenPrincipal.getName();
                            msgCtx.setProperty(RampartMessageData.USERNAME, username);
                            
                            if (userNameTokenPrincipal.getNonce() != null) {
                                // Check whether this is a replay attack. To verify that we need to check whether nonce value
                                // is a repeating one
                                int nonceLifeTimeInSeconds = 0;
        
                                if (rpd.getRampartConfig() != null) {
                                    
                                    String stringLifeTime = rpd.getRampartConfig().getNonceLifeTime();
        
                                    try {
                                        nonceLifeTimeInSeconds = Integer.parseInt(stringLifeTime);
        
                                    } catch (NumberFormatException e) {
                                        log.error("Invalid value for nonceLifeTime in rampart configuration file.", e);
                                        throw new RampartException(
                                                    "invalidNonceLifeTime", e);
        
                                    }
                                }
        
                                String serviceEndpointName = msgCtx.getAxisService().getEndpointName();
        
                                boolean valueRepeating = serviceNonceCache.isNonceRepeatingForService(serviceEndpointName, username, new String(userNameTokenPrincipal.getNonce()));
        
                                if (valueRepeating){
                                    throw new RampartException("repeatingNonceValue", new Object[]{ userNameTokenPrincipal.getNonce(), username} );
                                }
        
                                serviceNonceCache.addNonceForService(serviceEndpointName, username, new String(userNameTokenPrincipal.getNonce()), nonceLifeTimeInSeconds);
                            }
                        } else if (WSConstants.SIGN == actInt) {
                            X509Certificate cert = (X509Certificate) wser.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
        
                            if (rpd.isAsymmetricBinding() && cert == null && rpd.getInitiatorToken() != null
                                    && !rpd.getInitiatorToken().isDerivedKeys()) {
        
                                // If symmetric binding is used, the certificate should be null.
                                // If certificate is not null then probably initiator and
                                // recipient are using 2 different bindings.
                                throw new RampartException("invalidSignatureAlgo");
                            }
        
                            msgCtx.setProperty(RampartMessageData.X509_CERT, cert);
                        }
                    }
                }

		SOAPEnvelope env = Axis2Util.getSOAPEnvelopeFromDOMDocument(rmd.getDocument(), true);

		if(dotDebug){
			t2 = System.currentTimeMillis();
		}

		//Convert back to llom since the inflow cannot use DOOM
		msgCtx.setEnvelope(env);
		Axis2Util.useDOOM(false);
				
		PolicyValidatorCallbackHandler validator = RampartUtil.getPolicyValidatorCB(msgCtx, rpd);

        if (validator instanceof ExtendedPolicyValidatorCallbackHandler) {
            ExtendedPolicyValidatorCallbackHandler extendedPolicyValidatorCallbackHandler
                    = (ExtendedPolicyValidatorCallbackHandler)validator;
            extendedPolicyValidatorCallbackHandler.validate(data,results);
        } else {
            Vector resultsVector = new Vector(results);
            validator.validate(data, resultsVector);
        }


		if(dotDebug){
			t3 = System.currentTimeMillis();
			tlog.debug("processHeader by WSSecurityEngine took : " + (t1 - t0) +
					", DOOM conversion took :" + (t2 - t1) +
					", PolicyBasedResultsValidattor took " + (t3 - t2));
		}

		log.debug("Return process(MessageContext msgCtx)");
		return results;
	}