<module>redback-common-integrations</module>
<module>redback-rest</module>
<module>redback-struts2</module>
- <module>redback-jee</module>
<module>redback-jsecurity</module>
<module>redback-integrations-security</module>
</modules>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Licensed to the Apache Software Foundation (ASF) under one
- ~ or more contributor license agreements. See the NOTICE file
- ~ distributed with this work for additional information
- ~ regarding copyright ownership. The ASF licenses this file
- ~ to you 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.
- -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.codehaus.redback</groupId>
- <artifactId>redback-integrations</artifactId>
- <version>1.5-SNAPSHOT</version>
- </parent>
- <artifactId>redback-jee</artifactId>
- <name>Redback :: Integration :: J(2)EE</name>
- <packaging>pom</packaging>
-
- <modules>
- <module>redback-jee-web-integration</module>
- </modules>
-</project>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Licensed to the Apache Software Foundation (ASF) under one
- ~ or more contributor license agreements. See the NOTICE file
- ~ distributed with this work for additional information
- ~ regarding copyright ownership. The ASF licenses this file
- ~ to you 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.
- -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.codehaus.redback</groupId>
- <artifactId>redback-jee</artifactId>
- <version>1.5-SNAPSHOT</version>
- </parent>
- <artifactId>redback-jee-web-integration</artifactId>
- <name>Redback :: Integration :: J(2)EE Web Integration</name>
- <packaging>jar</packaging>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context-support</artifactId>
- </dependency>
- <dependency>
- <groupId>javax.annotation</groupId>
- <artifactId>jsr250-api</artifactId>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.codehaus.redback</groupId>
- <artifactId>redback-system</artifactId>
- </dependency>
- <dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- </dependency>
- </dependencies>
-</project>
+++ /dev/null
-package org.codehaus.plexus.redback.http;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-import java.util.Properties;
-
-import org.codehaus.plexus.util.StringUtils;
-
-/**
- * Collection of Utility methods useful in an Http environment.
- *
- * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
- * @version $Id$
- * @todo should move this to plexus-utils or plexus-utils-web
- */
-public class HttpUtils
-{
- /**
- * Convert typical complex header into properties.
- * <p/>
- * <p/>
- * Example:
- * </p>
- * <p/>
- * <code>
- * realm="Somewhere Over The Rainbow", domain="kansas.co.us", nonce="65743ABCF"
- * </code>
- * <p/>
- * <p>becomes</p>
- * <p/>
- * <code>
- * Map ( "realm", "Somewhere Over The Rainbox" )
- * Map ( "domain", "kansas.co.us" )
- * Map ( "nonce", "65743ABCF" )
- * </code>
- *
- * @param rawheader
- * @param majorDelim
- * @param subDelim
- * @return
- */
- public static Properties complexHeaderToProperties( String rawheader, String majorDelim, String subDelim )
- {
- Properties ret = new Properties();
-
- if ( StringUtils.isEmpty( rawheader ) )
- {
- return ret;
- }
-
- String array[] = StringUtils.split( rawheader, majorDelim );
- for ( int i = 0; i < array.length; i++ )
- {
- // String quotes.
- String rawelem = StringUtils.replace( array[i], "\"", "" );
- String parts[] = StringUtils.split( rawelem, subDelim, 2 );
-
- ret.setProperty( StringUtils.trim( parts[0] ), StringUtils.trim( parts[1] ) );
- }
-
- return ret;
- }
-}
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication;
-
-import org.codehaus.plexus.redback.authentication.AuthenticationDataSource;
-import org.codehaus.plexus.redback.authentication.AuthenticationException;
-import org.codehaus.plexus.redback.authentication.AuthenticationResult;
-import org.codehaus.plexus.redback.policy.AccountLockedException;
-import org.codehaus.plexus.redback.policy.MustChangePasswordException;
-import org.codehaus.plexus.redback.system.SecuritySession;
-import org.codehaus.plexus.redback.system.SecuritySystem;
-import org.codehaus.plexus.redback.users.User;
-import org.codehaus.plexus.redback.users.UserNotFoundException;
-import org.codehaus.plexus.util.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.inject.Inject;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * HttpAuthenticator is the workings of an authenticator for http with the session storage abstracted
- *
- * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
- * @author Andrew Williams
- * @version $Id$
- */
-public abstract class AbstractHttpAuthenticator
- implements HttpAuthenticator
-{
- protected Logger log = LoggerFactory.getLogger( getClass() );
-
- @Inject
- protected SecuritySystem securitySystem;
-
- /**
- * The Public Face of the Authenticator.
- *
- * @throws org.codehaus.plexus.redback.policy.MustChangePasswordException
- *
- * @throws org.codehaus.plexus.redback.policy.AccountLockedException
- *
- */
- protected AuthenticationResult authenticate( AuthenticationDataSource ds, Object session )
- throws AuthenticationException, AccountLockedException, MustChangePasswordException
- {
- try
- {
- SecuritySession securitySession = securitySystem.authenticate( ds );
-
- setSecuritySession( securitySession, session );
-
- return securitySession.getAuthenticationResult();
- }
- catch ( AuthenticationException e )
- {
- String msg = "Unable to authenticate user: " + ds;
- log.info( msg, e );
- throw new HttpAuthenticationException( msg, e );
- }
- catch ( UserNotFoundException e )
- {
- log.info( "Login attempt against unknown user: {}", ds );
- throw new HttpAuthenticationException( "User name or password invalid.", e );
- }
- }
-
- /**
- * Entry point for a Filter.
- *
- * @param request
- * @param response
- * @throws org.codehaus.plexus.redback.authentication.AuthenticationException
- *
- */
- public void authenticate( HttpServletRequest request, HttpServletResponse response )
- throws AuthenticationException
- {
- try
- {
- AuthenticationResult result = getAuthenticationResult( request, response );
-
- if ( ( result == null ) || ( !result.isAuthenticated() ) )
- {
- throw new HttpAuthenticationException( "You are not authenticated." );
- }
- }
- catch ( AccountLockedException e )
- {
- throw new HttpAuthenticationException( "Your account is locked." );
- }
- catch ( MustChangePasswordException e )
- {
- throw new HttpAuthenticationException( "You must change your password." );
- }
-
- }
-
- protected abstract Object getSessionValue( Object session, String key );
-
- protected abstract void setSessionValue( Object session, String key, Object value );
-
- protected User getSessionUser( Object session )
- {
- return (User) getSessionValue( session, SecuritySession.USERKEY );
- }
-
- protected boolean isAlreadyAuthenticated( Object session )
- {
- User user = getSessionUser( session );
-
- return ( ( user != null ) && !user.isLocked() );
- }
-
- protected SecuritySession getSecuritySession( Object session )
- {
- return (SecuritySession) getSessionValue( session, SecuritySession.SESSION_KEY );
- }
-
- protected void setSecuritySession( SecuritySession session, Object sessionObj )
- {
- setSessionValue( sessionObj, SecuritySession.SESSION_KEY, session );
- setSessionValue( sessionObj, SecuritySession.USERKEY, session.getUser() );
- }
-
- protected void setSessionUser( User user, Object session )
- {
- setSessionValue( session, SecuritySession.SESSION_KEY, null );
- setSessionValue( session, SecuritySession.USERKEY, user );
- }
-
- protected String storeDefaultUser( String principal, Object session )
- {
- setSessionValue( session, SecuritySession.SESSION_KEY, null );
- setSessionValue( session, SecuritySession.USERKEY, null );
-
- if ( StringUtils.isEmpty( principal ) )
- {
- return null;
- }
-
- try
- {
- User user = securitySystem.getUserManager().findUser( principal );
- setSessionValue( session, SecuritySession.USERKEY, user );
-
- return user.getPrincipal().toString();
-
- }
- catch ( UserNotFoundException e )
- {
- log.warn( "Default User '" + principal + "' not found.", e );
- return null;
- }
- }
-}
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication;
-
-import org.codehaus.plexus.redback.authentication.AuthenticationException;
-
-/**
- * HttpAuthenticationException
- *
- * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
- * @version $Id$
- */
-public class HttpAuthenticationException
- extends AuthenticationException
-{
-
- public HttpAuthenticationException()
- {
- super();
- }
-
- public HttpAuthenticationException( String message, Throwable cause )
- {
- super( message, cause );
- }
-
- public HttpAuthenticationException( String message )
- {
- super( message );
- }
-
- public HttpAuthenticationException( Throwable cause )
- {
- super( cause );
- }
-
-}
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication;
-
-import org.codehaus.plexus.redback.authentication.AuthenticationException;
-import org.codehaus.plexus.redback.authentication.AuthenticationResult;
-import org.codehaus.plexus.redback.policy.AccountLockedException;
-import org.codehaus.plexus.redback.policy.MustChangePasswordException;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-/**
- * HttpAuthenticator
- *
- * @author Andrew Williams
- * @version $Id$
- */
-public interface HttpAuthenticator
-{
- /**
- * Entry point for a Filter.
- *
- * @param request
- * @param response
- * @throws AuthenticationException
- */
- void authenticate( HttpServletRequest request, HttpServletResponse response )
- throws AuthenticationException;
-
- /**
- * Issue a Challenge Response back to the HTTP Client.
- *
- * @param request
- * @param response
- * @param realmName
- * @param exception
- * @throws java.io.IOException
- */
- void challenge( HttpServletRequest request, HttpServletResponse response, String realmName,
- AuthenticationException exception )
- throws IOException;
-
- /**
- * Parse the incoming request and return an AuthenticationResult.
- *
- * @param request
- * @param response
- * @return null if no http auth credentials, or the actual authentication result based on the credentials.
- * @throws AuthenticationException
- * @throws org.codehaus.plexus.redback.policy.MustChangePasswordException
- *
- * @throws org.codehaus.plexus.redback.policy.AccountLockedException
- *
- */
- AuthenticationResult getAuthenticationResult( HttpServletRequest request, HttpServletResponse response )
- throws AuthenticationException, AccountLockedException, MustChangePasswordException;
-
-}
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication;
-
-import java.util.Map;
-
-import org.codehaus.plexus.redback.authentication.AuthenticationDataSource;
-import org.codehaus.plexus.redback.authentication.AuthenticationException;
-import org.codehaus.plexus.redback.authentication.AuthenticationResult;
-import org.codehaus.plexus.redback.policy.AccountLockedException;
-import org.codehaus.plexus.redback.policy.MustChangePasswordException;
-import org.codehaus.plexus.redback.system.SecuritySession;
-import org.codehaus.plexus.redback.users.User;
-
-/**
- * An HttpAuthenticator using a Map for session storage
- *
- * @author Andrew Williams
- * @version $Id$
- * @since 1.0
- */
-public abstract class MapBasedHttpAuthenticator
- extends AbstractHttpAuthenticator
-{
-
- protected Object getSessionValue( Object session, String key )
- {
- if ( !( session instanceof Map ) )
- {
- throw new IllegalArgumentException( "The session for a MapBasedAuthenticator must be a java.util.Map" );
- }
-
- return ( (Map) session ).get( key );
- }
-
- protected void setSessionValue( Object session, String key, Object value )
- {
- if ( !( session instanceof Map ) )
- {
- throw new IllegalArgumentException( "The session for a MapBasedAuthenticator must be a java.util.Map" );
- }
-
- ( (Map) session ).put( key, value );
- }
-
- public AuthenticationResult authenticate( AuthenticationDataSource ds, Map session )
- throws AuthenticationException, AccountLockedException, MustChangePasswordException
- {
- return super.authenticate( ds, session );
- }
-
- public User getSessionUser( Map session )
- {
- return super.getSessionUser( session );
- }
-
- public boolean isAlreadyAuthenticated( Map session )
- {
- return super.isAlreadyAuthenticated( session );
- }
-
- public SecuritySession getSecuritySession( Map session )
- {
- return super.getSecuritySession( session );
- }
-
- public void setSecuritySession( SecuritySession session, Map sessionObj )
- {
- super.setSecuritySession( session, sessionObj );
- }
-
- public void setSessionUser( User user, Map session )
- {
- super.setSessionUser( user, session );
- }
-
- public String storeDefaultUser( String principal, Map session )
- {
- return super.storeDefaultUser( principal, session );
- }
-}
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication;
-
-import javax.servlet.http.HttpSession;
-
-import org.codehaus.plexus.redback.authentication.AuthenticationDataSource;
-import org.codehaus.plexus.redback.authentication.AuthenticationException;
-import org.codehaus.plexus.redback.authentication.AuthenticationResult;
-import org.codehaus.plexus.redback.policy.AccountLockedException;
-import org.codehaus.plexus.redback.policy.MustChangePasswordException;
-import org.codehaus.plexus.redback.system.SecuritySession;
-import org.codehaus.plexus.redback.users.User;
-
-/**
- * An HttpAuthenticator using an HttpSession for session storage
- *
- * @author Andrew Williams
- * @version $Id$
- * @since 1.0
- */
-public abstract class SessionBasedHttpAuthenticator
- extends AbstractHttpAuthenticator
-{
-
- protected Object getSessionValue( Object session, String key )
- {
- if ( !( session instanceof HttpSession ) )
- {
- throw new IllegalArgumentException( "The session for a SessionBasedAuthenticator must be a javax.servlet.http.HttpSession" );
- }
-
- return ( (HttpSession) session ).getAttribute( key );
- }
-
- protected void setSessionValue( Object session, String key, Object value )
- {
- if ( !( session instanceof HttpSession ) )
- {
- throw new IllegalArgumentException( "The session for a SessionBasedAuthenticator must be a javax.servlet.http.HttpSession" );
- }
-
- ( (HttpSession) session ).setAttribute( key, value );
- }
-
- public AuthenticationResult authenticate( AuthenticationDataSource ds, HttpSession session )
- throws AuthenticationException, AccountLockedException, MustChangePasswordException
- {
- return super.authenticate( ds, session );
- }
-
- public User getSessionUser( HttpSession session )
- {
- return super.getSessionUser( session );
- }
-
- public boolean isAlreadyAuthenticated( HttpSession session )
- {
- return super.isAlreadyAuthenticated( session );
- }
-
- public SecuritySession getSecuritySession( HttpSession session )
- {
- return super.getSecuritySession( session );
- }
-
- public void setSecuritySession( SecuritySession session, HttpSession sessionObj )
- {
- super.setSecuritySession( session, sessionObj );
- }
-
- public void setSessionUser( User user, HttpSession session )
- {
- super.setSessionUser( user, session );
- }
-
- public String storeDefaultUser( String principal, HttpSession session )
- {
- return super.storeDefaultUser( principal, session );
- }
-}
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication.basic;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import org.apache.commons.codec.binary.Base64;
-import org.codehaus.plexus.redback.authentication.AuthenticationException;
-import org.codehaus.plexus.redback.authentication.AuthenticationResult;
-import org.codehaus.plexus.redback.authentication.PasswordBasedAuthenticationDataSource;
-import org.codehaus.plexus.redback.http.authentication.SessionBasedHttpAuthenticator;
-import org.codehaus.plexus.redback.policy.AccountLockedException;
-import org.codehaus.plexus.redback.policy.MustChangePasswordException;
-import org.codehaus.plexus.util.StringUtils;
-import org.springframework.stereotype.Service;
-
-/**
- * HttpBasicAuthentication
- *
- * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
- * @author Andrew Williams
- * @version $Id$
- */
-@Service("httpAuthenticator#basic")
-public class HttpBasicAuthentication
- extends SessionBasedHttpAuthenticator
-{
-
- public String getId()
- {
- return HttpBasicAuthentication.class.getName();
- }
-
- public AuthenticationResult getAuthenticationResult( HttpServletRequest request, HttpServletResponse response )
- throws AuthenticationException, AccountLockedException, MustChangePasswordException
- {
- HttpSession session = request.getSession();
-
- if ( isAlreadyAuthenticated( session ) )
- {
- return getSecuritySession( session ).getAuthenticationResult();
- }
-
- PasswordBasedAuthenticationDataSource authDataSource;
- String header = request.getHeader( "Authorization" );
-
- // in tomcat this is : authorization=Basic YWRtaW46TWFuYWdlMDc=
- if ( header == null )
- {
- header = request.getHeader("authorization");
- }
-
- if ( ( header != null ) && header.startsWith( "Basic " ) )
- {
- String base64Token = header.substring( 6 );
- String token = new String( Base64.decodeBase64( base64Token.getBytes() ) );
-
- String username = "";
- String password = "";
- int delim = token.indexOf( ':' );
-
- if ( delim != ( -1 ) )
- {
- username = token.substring( 0, delim );
- password = token.substring( delim + 1 );
- }
-
- authDataSource = new PasswordBasedAuthenticationDataSource( username, password );
- return super.authenticate( authDataSource, session );
- }
- else
- {
- return null;
- }
- }
-
- /**
- * Return a HTTP 403 - Access Denied response.
- *
- * @param request the request to use.
- * @param response the response to use.
- * @param realmName the realm name to state.
- * @param exception the exception to base the message off of.
- * @throws IOException if there was a problem with the {@link HttpServletResponse#sendError(int,String)} call.
- */
- public void challenge( HttpServletRequest request, HttpServletResponse response, String realmName,
- AuthenticationException exception )
- throws IOException
- {
- response.addHeader( "WWW-Authenticate", "Basic realm=\"" + realmName + "\"" );
- String message = "You must provide a username and password to access this resource.";
- if ( ( exception != null ) && StringUtils.isNotEmpty( exception.getMessage() ) )
- {
- message = exception.getMessage();
- }
- response.sendError( HttpServletResponse.SC_UNAUTHORIZED, message );
- }
-}
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication.digest;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-/**
- * Digest
- *
- * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
- * @version $Id$
- * @todo move to plexus-utils in future
- */
-public class Digest
-{
- public static String md5Hex( String data )
- {
- MessageDigest digest = getDigest( "MD5" );
- return Hex.encode( digest.digest( data.getBytes() ) );
- }
-
- public static MessageDigest getDigest( String algorithm )
- {
- try
- {
- return MessageDigest.getInstance( algorithm );
- }
- catch ( NoSuchAlgorithmException e )
- {
- throw new RuntimeException( "Error initializing MessageDigest: " + e.getMessage(), e );
- }
- }
-}
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication.digest;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-/**
- * Hex
- *
- * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
- * @version $Id$
- * @todo should probably move this to plexus-utils or plexus-security-common
- */
-public class Hex
-{
- private static final byte[] DIGITS = "0123456789abcdef".getBytes();
-
- public static String encode( byte[] data )
- {
- int l = data.length;
-
- byte[] raw = new byte[l * 2];
-
- for ( int i = 0, j = 0; i < l; i++ )
- {
- raw[j++] = DIGITS[( 0xF0 & data[i] ) >>> 4];
- raw[j++] = DIGITS[0x0F & data[i]];
- }
-
- return new String( raw );
- }
-
- public static String encode( String raw )
- {
- return encode( raw.getBytes() );
- }
-}
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication.digest;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-import org.apache.commons.codec.binary.Base64;
-import org.codehaus.plexus.redback.authentication.AuthenticationException;
-import org.codehaus.plexus.redback.authentication.AuthenticationResult;
-import org.codehaus.plexus.redback.authentication.TokenBasedAuthenticationDataSource;
-import org.codehaus.plexus.redback.http.authentication.HttpAuthenticationException;
-import org.codehaus.plexus.redback.http.authentication.SessionBasedHttpAuthenticator;
-import org.codehaus.plexus.redback.policy.AccountLockedException;
-import org.codehaus.plexus.redback.policy.MustChangePasswordException;
-import org.codehaus.plexus.redback.users.User;
-import org.codehaus.plexus.redback.users.UserManager;
-import org.codehaus.plexus.redback.users.UserNotFoundException;
-import org.codehaus.plexus.util.StringUtils;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import java.io.IOException;
-
-/**
- * HttpDigestAuthentication methods for working with <a href="http://www.faqs.org/rfcs/rfc2617.html">RFC 2617 HTTP Authentication</a>.
- *
- * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
- * @author Andrew Williams
- * @version $Id$
- */
-@Service( "attpAuthenticator#digest" )
-public class HttpDigestAuthentication
- extends SessionBasedHttpAuthenticator
-{
- @Resource( name = "userManager#configurable" )
- private UserManager userManager;
-
- /**
- *
- */
- private int nonceLifetimeSeconds = 300;
-
- /**
- * NOTE: Must be alphanumeric.
- */
- private String digestKey = "OrycteropusAfer";
-
- private String realm;
-
- public String getId()
- {
- return HttpDigestAuthentication.class.getName();
- }
-
- public AuthenticationResult getAuthenticationResult( HttpServletRequest request, HttpServletResponse response )
- throws AuthenticationException, AccountLockedException, MustChangePasswordException
- {
- HttpSession session = request.getSession();
-
- if ( isAlreadyAuthenticated( session ) )
- {
- return getSecuritySession( session ).getAuthenticationResult();
- }
-
- TokenBasedAuthenticationDataSource authDataSource = new TokenBasedAuthenticationDataSource();
- String authHeader = request.getHeader( "Authorization" );
-
- // in tomcat this is : authorization=Basic YWRtaW46TWFuYWdlMDc=
- if ( authHeader == null )
- {
- authHeader = request.getHeader( "authorization" );
- }
-
- if ( ( authHeader != null ) && authHeader.startsWith( "Digest " ) )
- {
- String rawDigestHeader = authHeader.substring( 7 );
-
- HttpDigestHeader digestHeader = new HttpDigestHeader();
- digestHeader.parseClientHeader( rawDigestHeader, getRealm(), digestKey );
-
- // Lookup password for presented username
- User user = findUser( digestHeader.username );
- authDataSource.setPrincipal( user.getPrincipal().toString() );
-
- String serverSideHash = generateDigestHash( digestHeader, user.getPassword(), request.getMethod() );
-
- if ( !StringUtils.equals( serverSideHash, digestHeader.response ) )
- {
- throw new HttpAuthenticationException( "Digest response was invalid." );
- }
- }
-
- return super.authenticate( authDataSource, session );
- }
-
- public User findUser( String username )
- throws HttpAuthenticationException
- {
- try
- {
- return userManager.findUser( username );
- }
- catch ( UserNotFoundException e )
- {
- String msg = "Unable to find primary user '" + username + "'.";
- log.error( msg, e );
- throw new HttpAuthenticationException( msg, e );
- }
- }
-
- /**
- * Issue HTTP Digest Authentication Challenge
- *
- * @param request the request to use.
- * @param response the response to use.
- * @param realmName the realm name to state.
- * @param exception the exception to base the message off of.
- * @throws IOException if there was a problem with the {@link HttpServletResponse#sendError(int, String)} call.
- */
- public void challenge( HttpServletRequest request, HttpServletResponse response, String realmName,
- AuthenticationException exception )
- throws IOException
- {
- // The Challenge Header
- StringBuilder authHeader = new StringBuilder();
- authHeader.append( "Digest " );
- // [REQUIRED] The name to appear in the dialog box to the user.
- authHeader.append( "realm=\"" ).append( realmName ).append( "\"" );
- // [OPTIONAL] We do not use the optional 'domain' header.
- // authHeader.append( "domain=\"" ).append( domain ).append( "\"" );
- // [REQUIRED] Nonce specification.
- authHeader.append( ", nonce=\"" );
- long timestamp = System.currentTimeMillis() + ( nonceLifetimeSeconds * 1000 );
- // Not using ETag from RFC 2617 intentionally.
- String hraw = String.valueOf( timestamp ) + ":" + digestKey;
- String rawnonce = String.valueOf( timestamp ) + ":" + Digest.md5Hex( hraw );
- authHeader.append( Base64.encodeBase64( rawnonce.getBytes() ) );
- authHeader.append( "\"" );
- // [REQUIRED] The RFC 2617 Quality of Protection.
- // MSIE Appears to only support 'auth'
- // Do not use 'opaque' here. (Your MSIE users will have issues)
- authHeader.append( ", qop=\"auth\"" );
- // [BROKEN] since we force the 'auth' qop we cannot use the opaque option.
- // authHeader.append( ", opaque=\"").append(opaqueString).append("\"");
-
- // [OPTIONAL] Use of the stale option is reserved for expired nonce strings.
- if ( exception instanceof NonceExpirationException )
- {
- authHeader.append( ", stale=\"true\"" );
- }
-
- // [OPTIONAL] We do not use the optional Algorithm header.
- // authHeader.append( ", algorithm=\"MD5\"");
-
- response.addHeader( "WWW-Authenticate", authHeader.toString() );
- response.sendError( HttpServletResponse.SC_UNAUTHORIZED, exception.getMessage() );
- }
-
- private String generateDigestHash( HttpDigestHeader digestHeader, String password, String httpMethod )
- {
- String a1 = Digest.md5Hex( digestHeader.username + ":" + realm + ":" + password );
- String a2 = Digest.md5Hex( httpMethod + ":" + digestHeader.uri );
-
- String digest;
-
- if ( StringUtils.isEmpty( digestHeader.qop ) )
- {
- digest = a1 + ":" + digestHeader.nonce + ":" + a2;
- }
- else if ( StringUtils.equals( "auth", digestHeader.qop ) )
- {
- digest = a1 + ":" + digestHeader.nonce + ":" + digestHeader.nc + ":" + digestHeader.cnonce + ":"
- + digestHeader.qop + ":" + a2;
- }
- else
- {
- throw new IllegalStateException(
- "Http Digest Parameter [qop] with value of [" + digestHeader.qop + "] is unsupported." );
- }
-
- return Digest.md5Hex( digest );
- }
-
- public String getRealm()
- {
- return realm;
- }
-
- public void setRealm( String realm )
- {
- this.realm = realm;
- }
-
-}
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication.digest;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-import org.apache.commons.codec.binary.Base64;
-import org.codehaus.plexus.redback.http.HttpUtils;
-import org.codehaus.plexus.redback.http.authentication.HttpAuthenticationException;
-import org.codehaus.plexus.util.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.annotation.Scope;
-import org.springframework.stereotype.Service;
-
-import java.util.Properties;
-
-/**
- * HttpDigestHeader
- *
- * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
- * @version $Id$
- */
-@Service( "httpClientHeader" )
-@Scope( "protype" )
-class HttpDigestHeader
-{
-
- private Logger log = LoggerFactory.getLogger( getClass() );
-
- public String username;
-
- public String realm;
-
- public String nonce;
-
- public String uri;
-
- public String response;
-
- public String qop;
-
- public String nc;
-
- public String cnonce;
-
- public void parseClientHeader( String rawHeader, String expectedRealm, String digestKey )
- throws HttpAuthenticationException
- {
- Properties authHeaderProps = HttpUtils.complexHeaderToProperties( rawHeader, ",", "=" );
-
- username = authHeaderProps.getProperty( "username" );
- realm = authHeaderProps.getProperty( "realm" );
- nonce = authHeaderProps.getProperty( "nonce" );
- uri = authHeaderProps.getProperty( "uri" );
- response = authHeaderProps.getProperty( "response" );
- qop = authHeaderProps.getProperty( "qop" );
- nc = authHeaderProps.getProperty( "nc" );
- cnonce = authHeaderProps.getProperty( "cnonce" );
-
- // [RFC 2067] Validate all required values
- if ( StringUtils.isEmpty( username ) || StringUtils.isEmpty( realm ) || StringUtils.isEmpty( nonce )
- || StringUtils.isEmpty( uri ) || StringUtils.isEmpty( response ) )
- {
- log.debug( "Missing mandatory fields: Raw Digest Header : [{}]", rawHeader );
-
- throw new HttpAuthenticationException( "Missing mandatory digest fields per RFC2069." );
- }
-
- // [RFC 2617] Validate realm.
- if ( !StringUtils.equals( expectedRealm, realm ) )
- {
- log.debug( "Realm name is invalid: expected [{}] but got [{}]", expectedRealm, realm );
-
- throw new HttpAuthenticationException( "Response realm does not match expected realm." );
- }
-
- // [RFC 2617] Validate "auth" qop
- if ( StringUtils.equals( "auth", qop ) )
- {
- if ( StringUtils.isEmpty( nc ) || StringUtils.isEmpty( cnonce ) )
- {
- log.debug( "Missing mandatory qop fields: nc [{}] cnonce [{}]", nc, cnonce );
-
- throw new HttpAuthenticationException( "Missing mandatory qop digest fields per RFC2617." );
- }
- }
-
- // [RFC 2617] Validate nonce
- if ( !Base64.isArrayByteBase64( nonce.getBytes() ) )
- {
- log.debug( "Nonce is not encoded in Base64: nonce [{}]", nonce );
-
- throw new HttpAuthenticationException( "Response nonce is not encoded in Base64." );
- }
-
- // Decode nonce
- String decodedNonce = new String( Base64.decodeBase64( nonce.getBytes() ) );
- String nonceTokens[] = StringUtils.split( decodedNonce, ":" );
-
- // Validate nonce format
- if ( nonceTokens.length != 2 )
- {
- log.debug( "Nonce format expected [2] elements, but got [{}] instead. Decoded nonce [{}]",
- nonceTokens.length, decodedNonce );
-
- throw new HttpAuthenticationException(
- "Nonce format is invalid. " + "Received an unexpected number of sub elements." );
- }
-
- // Extract nonce timestamp
- long nonceTimestamp = 0;
-
- try
- {
- nonceTimestamp = Long.parseLong( nonceTokens[0] );
- }
- catch ( NumberFormatException e )
- {
- throw new HttpAuthenticationException( "Unexpected nonce timestamp." );
- }
-
- // Extract nonce signature
- String expectedSignature = Digest.md5Hex( nonceTimestamp + ":" + digestKey );
-
- if ( !StringUtils.equals( expectedSignature, nonceTokens[1] ) )
- {
- log.error( "Nonce parameter has been compromised." );
-
- throw new HttpAuthenticationException( "Nonce parameter has been compromised." );
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication.digest;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-import org.codehaus.plexus.redback.http.authentication.HttpAuthenticationException;
-
-/**
- * NonceExpirationException
- *
- * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
- * @version $Id$
- */
-public class NonceExpirationException
- extends HttpAuthenticationException
-{
-
- public NonceExpirationException()
- {
- super();
- }
-
- public NonceExpirationException( String message, Throwable cause )
- {
- super( message, cause );
- }
-
- public NonceExpirationException( String message )
- {
- super( message );
- }
-
- public NonceExpirationException( Throwable cause )
- {
- super( cause );
- }
-}
+++ /dev/null
-<?xml version="1.0"?>
-
-<!--
- ~ Licensed to the Apache Software Foundation (ASF) under one
- ~ or more contributor license agreements. See the NOTICE file
- ~ distributed with this work for additional information
- ~ regarding copyright ownership. The ASF licenses this file
- ~ to you 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.
- -->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-2.5.xsd"
- default-lazy-init="true">
-
- <context:annotation-config />
- <context:component-scan base-package="org.codehaus.plexus.redback.http.authentication"/>
-
-</beans>
\ No newline at end of file
+++ /dev/null
-package org.codehaus.plexus.redback.http.authentication.digest;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-import junit.framework.TestCase;
-
-public class HexTest
- extends TestCase
-{
- public void testEncoding()
- {
- String raw = "Lenore\nLenore";
- String lenoreHex = "4c656e6f7265";
- String expected = lenoreHex + "0a" + lenoreHex;
-
- assertEquals( expected, Hex.encode( raw ) );
- }
-
- public void testTheRaven()
- {
- String raw = "Quoth the Raven, \"Nevermore.\"";
- String expected = "51756f74682074686520526176656e2c20224e657665726d6f72652e22";
-
- assertEquals( expected, Hex.encode( raw.getBytes() ) );
- }
-}