directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From smckin...@apache.org
Subject [33/51] [partial] Rename packages from org.openldap.fortress to org.apache.directory.fortress.core. Change default suffix to org.apache. Switch default ldap api from unbound to apache ldap.
Date Wed, 22 Oct 2014 15:44:52 GMT
http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/ldap/openldap/OLPWControlImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/openldap/OLPWControlImpl.java b/src/main/java/org/apache/directory/fortress/core/ldap/openldap/OLPWControlImpl.java
new file mode 100755
index 0000000..853d906
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/openldap/OLPWControlImpl.java
@@ -0,0 +1,417 @@
+/*
+ *   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.
+ *
+ */
+package org.apache.directory.fortress.core.ldap.openldap;
+
+
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.ObjectFactory;
+import org.apache.directory.fortress.core.rbac.GlobalPwMsgIds;
+import org.apache.directory.fortress.core.rbac.PwMessage;
+import org.apache.directory.fortress.core.rbac.PwPolicyControl;
+
+import com.unboundid.ldap.sdk.migrate.ldapjdk.LDAPControl;
+import org.apache.directory.fortress.core.rbac.Warning;
+
+
+/**
+ * This class reads the OpenLDAP password policy control and translates into data entity for Fortress.  In order for these checks
+ * to be successful the OpenLDAP server must have enabled the pw policy overlay.  Read the OpenLDAP man pages for how this overlay works.
+ * <p/>
+
+ *
+ * @author Shawn McKinney
+ */
+public class OLPWControlImpl implements PwPolicyControl
+{
+    private static final String CLS_NM = OLPWControlImpl.class.getName();
+    private final static Logger LOG = LoggerFactory.getLogger( CLS_NM );
+
+
+    /**
+     * Reads the OpenLDAP password policy control and sets the PwMessage with what it finds.
+     *
+     * <p/>This function will use the password policy control that is contained within the ldap connection object.
+     * Ber encoding:
+     * <ul>
+     * <li>  ------------------------------------------
+     * <li>  PasswordPolicyResponseValue ::= SEQUENCE {
+     * <li>  warning [0] CHOICE {
+     * <li>  timeBeforeExpiration [0] INTEGER (0 .. maxInt),
+     * <li>  graceLoginsRemaining [1] INTEGER (0 .. maxInt) } OPTIONAL
+     * <li>  error [1] ENUMERATED {
+     * <li>  passwordExpired        (0),
+     * <li>  accountLocked          (1),
+     * <li>  changeAfterReset       (2),
+     * <li>  passwordModNotAllowed  (3),
+     * <li>  mustSupplyOldPassword  (4),
+     * <li>  invalidPasswordSyntax  (5),
+     * <li>  passwordTooShort       (6),
+     * <li>  passwordTooYoung       (7),
+     * <li>  passwordInHistory      (8) } OPTIONAL }
+     * <li>  ---
+     * <li>  Old Encoding Scheme:
+     * <li>  PPOLICY_WARNING    0xa0
+     * <li>  PPOLICY_ERROR      0xa1
+     * <li>  PPOLICY_EXPIRE     0xa0
+     * <li>  PPOLICY_GRACE      0xa1
+     * <li>  New Encoding Scheme:
+     * <li>  PPOLICY_WARNING 0xa0
+     * <li>  PPOLICY_ERROR 0x81
+     * <li>  PPOLICY_EXPIRE 0x80
+     * <li>  PPOLICY_GRACE  0x81
+     * </ul>
+     *
+     * @param controls ldap controls object.
+     * @param isAuthenticated set to 'true' if password checks pass.
+     * @param pwMsg describes the outcome of the policy checks.
+     */
+    @Override
+    public void checkPasswordPolicy( LDAPControl[] controls, boolean isAuthenticated, PwMessage pwMsg )
+    {
+        String methodName = "checkPasswordPolicy";
+        pwMsg.setErrorId( GlobalPwMsgIds.GOOD );
+        //pwMsg.setWarningId( GlobalPwMsgIds.PP_NOWARNING );
+        pwMsg.setAuthenticated( isAuthenticated );
+
+        if ( controls == null )
+        {
+            pwMsg.setWarning( new ObjectFactory().createWarning( GlobalPwMsgIds.NO_CONTROLS_FOUND, "PW CONTROLS NOT FOUND", Warning.Type.PASSWORD ) );
+        }
+        else if ( controls.length >= 1 )
+        {
+            for ( int i = 0; i < controls.length; i++ )
+            {
+                if ( LOG.isDebugEnabled() )
+                {
+                    LOG.debug( "{} controls[{}]={}", methodName, i, controls[i] );
+                }
+
+                LDAPControl con = controls[i];
+                String id = con.getID();
+
+                if ( id.compareTo( GlobalIds.OPENLDAP_PW_RESPONSE_CONTROL ) == 0 )
+                {
+                    byte[] rB = con.getValue();
+
+                    if ( LOG.isDebugEnabled() )
+                    {
+                        LOG.debug( "{} control value length={}", methodName, rB.length );
+
+                        String bytes = "";
+
+                        for ( byte aRB : rB )
+                        {
+                            bytes = bytes + printRawData( aRB );
+                        }
+
+                        LOG.debug( "{} printRawData numbytes: {}", methodName, bytes );
+                    }
+
+                    if ( rB == null || rB[1] == 0 )
+                    {
+                        LOG.debug( methodName + " no password policy for user" );
+                        pwMsg.setWarning( new ObjectFactory().createWarning( GlobalPwMsgIds.NOT_PW_POLICY_ENABLED, "NO PW POLICY ENABLED FOR USER", Warning.Type.PASSWORD ) );
+                    }
+
+                    if ( LOG.isDebugEnabled() )
+                    {
+                        LOG.debug( "{} byte[]={}", methodName, Arrays.toString( rB ) );
+                        LOG.debug( "control.toString()={}", con.toString() );
+                    }
+
+                    int indx = 0;
+                    int lBerObjType = getInt( rB[indx++] );
+
+                    if ( LOG.isDebugEnabled() )
+                    {
+                        LOG.debug( "{} BER encoded object type={}", methodName, lBerObjType );
+                    }
+
+                    int msgLen = getInt( rB[indx++] );
+
+                    while ( indx < msgLen )
+                    {
+                        switch ( rB[indx++] )
+                        {
+                            case ( byte ) 0xa0:
+                                // BER Encoded byte array:
+                                //client: 00110000 00000101 10100000
+                                //  			     		^
+                                //		PPOLICY_WARNING  0xa0
+                                int policyWarnLen = getInt( rB[indx++] );
+
+                                switch ( rB[indx++] )
+                                {
+                                    case ( byte ) 0xa0:
+                                    case ( byte ) 0x80:
+                                        //pwMsg.setWarningId( GlobalPwMsgIds.PASSWORD_EXPIRATION_WARNING );
+                                        pwMsg.setWarning( new ObjectFactory().createWarning( GlobalPwMsgIds.PASSWORD_EXPIRATION_WARNING, "PASSWORD HAS EXPIRED", Warning.Type.PASSWORD ) );
+                                        // BER Encoded byte array:
+                                        // client: 00110000 00000110 10100000 00000100 10100000 00000010 00000010 00100100
+                                        //							 ^                  ^                   ^
+                                        //       PPOLICY_WARNING  0xa0 PPOLICY_EXPIRE 0xa0       EXP int==(decimal 548) 1000100100
+                                        int expLength = getInt( rB[indx++] );
+                                        int expire = getInt( rB[indx++] );
+
+                                        for ( int k = 1; k < expLength; k++ )
+                                        {
+                                            expire = expire << 8;
+                                            int next = getInt( rB[indx++] );
+                                            expire = expire | next;
+                                        }
+
+                                        pwMsg.setExpirationSeconds( expire );
+
+                                        if ( LOG.isDebugEnabled() )
+                                        {
+                                            LOG.debug( "{} User:{}, password expires in: {} seconds.", methodName, pwMsg.getUserId(), expire );
+                                        }
+
+                                        break;
+
+                                    case ( byte ) 0xa1:
+                                    case ( byte ) 0x81:
+                                        pwMsg.setWarning( new ObjectFactory().createWarning( GlobalPwMsgIds.PASSWORD_GRACE_WARNING, "PASSWORD IN GRACE", Warning.Type.PASSWORD ) );
+                                        // BER Encoded byte array:
+                                        //client: 00110000 00000101 10100000 00000011 10100001 00000001 01100100
+                                        //  			     		^                 ^                 ^
+                                        //			PPOLICY_WARNING  0xa0   PPOLICY_GRACE 0xa1       grace integer value
+                                        int graceLen = getInt( rB[indx++] );
+                                        int grace = getInt( rB[indx++] );
+
+                                        for ( int k = 1; k < graceLen; k++ )
+                                        {
+                                            grace = grace << 8;
+                                            int next = getInt( rB[indx++] );
+                                            grace = grace | next;
+                                        }
+
+                                        pwMsg.setGraceLogins( grace );
+
+                                        if ( LOG.isDebugEnabled() )
+                                        {
+                                            LOG.debug( "{} UserId:{}, # logins left={}", methodName, pwMsg.getUserId() + grace );
+                                        }
+
+                                        break;
+
+                                    default:
+                                        pwMsg.setWarning( new ObjectFactory().createWarning( GlobalPwMsgIds.INVALID_PASSWORD_MESSAGE, "INVALID PASSWORD", Warning.Type.PASSWORD ) );
+
+                                        if ( LOG.isDebugEnabled() )
+                                        {
+                                            LOG.debug( "{} UserId:{}, Invalid PPOlicy Type", methodName, pwMsg.getUserId() );
+                                        }
+
+                                        break;
+                                }
+
+                                break;
+
+                            case ( byte ) 0xa1:
+                            case ( byte ) 0x81:
+                                // BER Encoded byte array:
+                                //client: 00110000 00001011 10100000 00000110 10100000 00000100 00000001 11100001 00110011 01111101 10100001 00000001 00000010
+                                //							 ^                  ^                 ^                                   ^                     ^
+                                //		   PPOLICY_WARNING  0xa0 PPOLICY_EXPIRE 0xa0      expire int==(decimal 100)     PPOLICY_ERR 0xa1             ERR #==2
+                                int errLen = getInt( rB[indx++] );
+                                int err = getInt( rB[indx++] );
+
+                                if ( LOG.isDebugEnabled() )
+                                {
+                                    LOG.debug( "{} UserId:{}, PPOLICY_ERROR={}", methodName, pwMsg.getUserId(), err);
+                                }
+
+                                switch ( err )
+                                {
+                                    case 0:
+                                        pwMsg.setErrorId( GlobalPwMsgIds.PASSWORD_HAS_EXPIRED );
+                                        break;
+
+                                    case 1:
+                                        pwMsg.setErrorId( GlobalPwMsgIds.ACCOUNT_LOCKED );
+                                        break;
+
+                                    case 2:
+                                        pwMsg.setErrorId( GlobalPwMsgIds.CHANGE_AFTER_RESET );
+                                        break;
+
+                                    case 3:
+                                        pwMsg.setErrorId( GlobalPwMsgIds.NO_MODIFICATIONS );
+                                        break;
+
+                                    case 4:
+                                        pwMsg.setErrorId( GlobalPwMsgIds.MUST_SUPPLY_OLD );
+                                        break;
+
+                                    case 5:
+                                        pwMsg.setErrorId( GlobalPwMsgIds.INSUFFICIENT_QUALITY );
+                                        break;
+
+                                    case 6:
+                                        pwMsg.setErrorId( GlobalPwMsgIds.PASSWORD_TOO_SHORT );
+                                        break;
+
+                                    case 7:
+                                        pwMsg.setErrorId( GlobalPwMsgIds.PASSWORD_TOO_YOUNG );
+                                        break;
+
+                                    case 8:
+                                        pwMsg.setErrorId( GlobalPwMsgIds.HISTORY_VIOLATION );
+                                        break;
+
+                                    case 65535:
+                                        pwMsg.setErrorId( GlobalPwMsgIds.GOOD );
+                                        break;
+
+                                    default:
+                                        pwMsg.setErrorId( GlobalPwMsgIds.INVALID_PASSWORD_MESSAGE );
+                                        break;
+                                }
+
+                                break;
+
+                            default:
+                                pwMsg.setWarning( new ObjectFactory().createWarning( GlobalPwMsgIds.INVALID_PASSWORD_MESSAGE, "INVALID POLICY MESSAGE TYPE", Warning.Type.PASSWORD ) );
+
+                                if ( LOG.isDebugEnabled() )
+                                {
+                                    LOG.debug( "{} userId:{}, Invalid PPOlicy Message Type", methodName, pwMsg.getUserId());
+                                }
+
+                                break;
+                        }
+                    }
+                }
+                else
+                {
+                    pwMsg.setWarning( new ObjectFactory().createWarning( GlobalPwMsgIds.INVALID_PASSWORD_MESSAGE, "CANNOT PROCESS OPENLDAP POLICY CONTROL", Warning.Type.PASSWORD ) );
+
+                    if ( LOG.isDebugEnabled() )
+                    {
+                        LOG.debug( "{} UserId:{},  Can't process LDAP control.", methodName, pwMsg.getUserId() );
+                    }
+                }
+            }
+        }
+    }
+
+
+    /**
+     * @param bte
+     * @return int
+     */
+    private static int getInt( byte bte )
+    {
+        return bte & 0xff;
+    }
+
+
+    /**
+     * Description of the Method
+     *
+     * @param ch Description of the Parameter
+     * @return Description of the Return Value
+     */
+    private static String printRawData( byte ch )
+    {
+        int B0 = 0x01;
+        int B1 = 0x02;
+        int B2 = 0x04;
+        int B3 = 0x08;
+        int B4 = 0x10;
+        int B5 = 0x20;
+        int B6 = 0x40;
+        int B7 = 0x80;
+
+        String byteString;
+        if ( ( ch & B7 ) != 0 )
+        {
+            byteString = "1";
+        }
+        else
+        {
+            byteString = "0";
+        }
+        if ( ( ch & B6 ) != 0 )
+        {
+            byteString += "1";
+        }
+        else
+        {
+            byteString += "0";
+        }
+        if ( ( ch & B5 ) != 0 )
+        {
+            byteString += "1";
+        }
+        else
+        {
+            byteString += "0";
+        }
+        if ( ( ch & B4 ) != 0 )
+        {
+            byteString += "1";
+        }
+        else
+        {
+            byteString += "0";
+        }
+        if ( ( ch & B3 ) != 0 )
+        {
+            byteString += "1";
+        }
+        else
+        {
+            byteString += "0";
+        }
+        if ( ( ch & B2 ) != 0 )
+        {
+            byteString += "1";
+        }
+        else
+        {
+            byteString += "0";
+        }
+        if ( ( ch & B1 ) != 0 )
+        {
+            byteString += "1";
+        }
+        else
+        {
+            byteString += "0";
+        }
+        if ( ( ch & B0 ) != 0 )
+        {
+            byteString += "1";
+        }
+        else
+        {
+            byteString += "0";
+        }
+        byteString += " ";
+        return byteString;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/ldap/openldap/package.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/openldap/package.html b/src/main/java/org/apache/directory/fortress/core/ldap/openldap/package.html
new file mode 100755
index 0000000..ee649fc
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/openldap/package.html
@@ -0,0 +1,33 @@
+<!--
+ *   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.
+ *
+-->
+<html>
+   <head>
+      <title>Package Documentation for org.apache.directory.fortress.ldap.openldap</title>
+   </head>
+   <body>
+      <p>
+         This package contains openldap password policy mappings.
+      </p>
+      <p>
+          This package stores and retrieves data elements in OpenLDAP ldap object class <b>pwdPolicy</b>.  In addition this package
+          contains processing to interrogate the OpenLDAP password policy control <b>1.3.6.1.4.1.42.2.27.8.5.1</b>.
+      </p>
+   </body>
+</html>

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/ldap/package.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/package.html b/src/main/java/org/apache/directory/fortress/core/ldap/package.html
new file mode 100755
index 0000000..cffad11
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/package.html
@@ -0,0 +1,33 @@
+<!--
+ *   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.
+ *
+-->
+<html>
+   <head>
+      <title>Package Documentation for org.apache.directory.fortress.ldap</title>
+   </head>
+   <body>
+      <p>
+         This package uses <a href="http://www.unboundid.com/products/ldap-sdk/">UnboundID LDAP SDK for Java</a> to provide ldap data access along with a custom, hybrid connection pooling mechanism to maintain connections with the ldap server.
+      </p>
+      <p>
+         The <b>org.apache.directory.fortress.ldap</b> package provides ldap system functionality for the fortress DAO classes.  The apis contained within this package are for fortress use only.
+          See the corresponding javadoc contained with this package for more info.
+      </p>
+   </body>
+</html>

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/ldap/suffix/Suffix.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/suffix/Suffix.java b/src/main/java/org/apache/directory/fortress/core/ldap/suffix/Suffix.java
new file mode 100755
index 0000000..08876da
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/suffix/Suffix.java
@@ -0,0 +1,134 @@
+/*
+ *   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.
+ *
+ */
+package org.apache.directory.fortress.core.ldap.suffix;
+
+
+public class Suffix
+{
+    private String dc;
+    private String dc2;
+    private String name;
+    private String description;
+
+
+    /**
+     * Generate instance of suffix to be loaded as domain component ldap object.
+     *
+     * @param dc          top level domain component maps to 'dc' (i.e. 'com') attribute in 'dcObject' object class.
+     * @param name        second level domain component name maps to attribute in 'dcObject' object class.
+     * @param description maps to 'o' attribute in 'dcObject' object class.
+     */
+    public Suffix(String dc, String name, String description)
+    {
+        this.dc = dc;
+        this.name = name;
+        this.description = description;
+    }
+
+    /**
+     * Default constructor used by {@link org.apache.directory.fortress.core.ant.FortressAntTask}
+     */
+    public Suffix()
+    {
+    }
+
+    /**
+     * Get the second level qualifier on the domain component.  This attribute is required.
+     *
+     * @return name maps to 'dcObject' object class.
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+    /**
+     * Set the second level qualifier on the domain component.  This attribute is required.
+     *
+     * @param name maps to 'dcObject' object class.
+     */
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    /**
+     * Get the description for the domain component.  This value is not required or constrained
+     * but is validated on reasonability.
+     *
+     * @return field maps to 'o' attribute on 'dcObject'.
+     */
+    public String getDescription()
+    {
+        return description;
+    }
+
+    /**
+     * Set the description for the domain component.  This value is not required or constrained
+     * but is validated on reasonability.
+     *
+     * @param description maps to 'o' attribute on 'dcObject'.
+     */
+    public void setDescription(String description)
+    {
+        this.description = description;
+    }
+
+    /**
+     * Get top level domain component specifier, i.e. dc=com.  This attribute is required.
+     *
+     * @return dc maps to 'dc' in 'dcObject' object class.
+     */
+    public String getDc()
+    {
+        return dc;
+    }
+
+    /**
+     * Set top level domain component specifier, i.e. dc=com.  This attribute is required.
+     *
+     * @param dc maps to 'dc' in 'dcObject' object class.
+     */
+    public void setDc(String dc)
+    {
+        this.dc = dc;
+    }
+
+    /**
+     * Get top level domain component specifier, i.e. dc=com for a three part dc structure.  This attribute is optional.
+     *
+     * @return dc maps to 'dc' in 'dcObject' object class.
+     */
+    public String getDc2()
+    {
+        return dc2;
+    }
+
+    /**
+     * Get top level domain component specifier, i.e. dc=com for three part dc structure.  This attribute is optional.
+     *
+     * @return dc maps to 'dc' in 'dcObject' object class.
+     */
+    public void setDc2( String dc2 )
+    {
+        this.dc2 = dc2;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/ldap/suffix/SuffixDAO.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/suffix/SuffixDAO.java b/src/main/java/org/apache/directory/fortress/core/ldap/suffix/SuffixDAO.java
new file mode 100755
index 0000000..ba181fc
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/suffix/SuffixDAO.java
@@ -0,0 +1,178 @@
+/*
+ *   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.
+ *
+ */
+package org.apache.directory.fortress.core.ldap.suffix;
+
+
+import org.apache.directory.api.ldap.model.cursor.CursorException;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.fortress.core.ldap.ApacheDsDataProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.directory.fortress.core.CreateException;
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.RemoveException;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+
+/**
+ * This class contains the Suffix node for OpenLDAP Directory Information Tree.
+ * <br />The domain component object class is 'dcObject' <br />
+ * <p/>
+ * dcObject Auxiliary Object Class is used to store basic attributes like domain component names and description.
+ * <ul>
+ * <li>  ------------------------------------------
+ * <li> <code># RFC 2247</code>
+ * <li> <code>objectclass ( 1.3.6.1.4.1.1466.344 NAME 'dcObject'</code>
+ * <li> <code>SUP top AUXILIARY MUST dc )</code>
+ * <li>  ------------------------------------------
+ * </ul>
+ * <p/>
+ * Following wikipedia excerpt describes usage of this object <a href="http://http://en.wikipedia.org/wiki/LDAP/">Wikipedia LDAP</a>
+ * <font size="2" color="blue">
+ * <blockquote>
+ * <h3>
+ * Naming structure
+ * </h3>
+ * Since an LDAP server can return referrals to other servers for requests the server itself will not/can not serve, a naming structure for LDAP entries is needed so one can find a server holding a given DN. Since such a structure already exists in the Domain name system (DNS), servers' top level names often mimic DNS names, as they do in X.500.
+ * If an organization has domain name example.org, its top level LDAP entry will typically have the DN dc=example,dc=org (where dc means domain component). If the LDAP server is also named ldap.example.org, the organization's top level LDAP URL becomes ldap://ldap.example.org/dc=example,dc=org.
+ * Below the top level, the entry names will typically reflect the organization's internal structure or needs rather than DNS names.
+ * </blockquote>
+ * </font>
+ * <p/>
+ * This class is thread safe.
+ *
+ * @author Shawn McKinney
+ */
+final class SuffixDAO extends ApacheDsDataProvider
+{
+    private static final String CLS_NM = SuffixDAO.class.getName();
+    private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
+    private static final String DC = "dc";
+    private static final String O = "o";
+    private static final String[] SUFFIX_OBJ_CLASS =
+        {
+            GlobalIds.SUFFIX_CLASS, GlobalIds.ORGANIZATION_CLASS
+    };
+
+
+    /**
+     * Package private default constructor.
+     */
+    SuffixDAO()
+    {
+    }
+
+
+    /**
+     * @param se
+     * @throws org.apache.directory.fortress.core.CreateException
+     */
+    final void create( Suffix se )
+        throws CreateException
+    {
+        LdapConnection ld = null;
+        String nodeDn = getDn( se );
+        try
+        {
+            LOG.info( "create suffix dn [" + nodeDn + "]" );
+            Entry myEntry = new DefaultEntry( nodeDn );
+            myEntry.add( GlobalIds.OBJECT_CLASS, SUFFIX_OBJ_CLASS );
+            myEntry.add( DC, se.getName() );
+            myEntry.add( O, se.getDescription() );
+            ld = getAdminConnection();
+            add( ld, myEntry );
+        }
+        catch ( LdapException e )
+        {
+            String error = "create container node dn [" + nodeDn + "] caught LDAPException="
+                + e.getMessage();
+            throw new CreateException( GlobalErrIds.SUFX_CREATE_FAILED, error, e );
+        }
+        finally
+        {
+            closeAdminConnection( ld );
+        }
+    }
+
+
+    /**
+     * <p/>
+     * <font size="4" color="red">
+     * This method is destructive as it will remove all nodes below the suffix using recursive delete function.<BR>
+     * Extreme care should be taken during execution to ensure target directory is correct and permanent removal of data is intended.  There is no
+     * 'undo' for this operation.
+     * </font>
+     * <p/>
+     *
+     * @param se
+     * @throws org.apache.directory.fortress.core.RemoveException
+     */
+    final void remove( Suffix se )
+        throws RemoveException
+    {
+        LdapConnection ld = null;
+        String nodeDn = getDn( se );
+        LOG.info( "remove suffix dn [" + nodeDn + "]" );
+        try
+        {
+            ld = getAdminConnection();
+            deleteRecursive( ld, nodeDn );
+        }
+        catch ( CursorException e )
+        {
+            String error = "remove suffix node dn [" + nodeDn + "] caught CursorException="
+                + e.getMessage();
+            throw new RemoveException( GlobalErrIds.SUFX_DELETE_FAILED, error, e );
+        }
+        catch ( LdapException e )
+        {
+            String error = "remove suffix node dn [" + nodeDn + "] caught LDAPException="
+                + e.getMessage();
+            throw new RemoveException( GlobalErrIds.SUFX_DELETE_FAILED, error, e );
+        }
+        finally
+        {
+            closeAdminConnection( ld );
+        }
+    }
+
+
+    /**
+     *
+     * @param se
+     * @return
+     */
+    private String getDn( Suffix se )
+    {
+        String dn = DC + "=" + se.getName() + "," + DC + "=" + se.getDc();
+        // only use this domain component variable if it has been set in the build.properties file:
+        if( VUtil.isNotNullOrEmpty( se.getDc2() ) && !se.getDc2().equals( "${suffix.dc2}" ))
+        {
+            dn += "," + DC + "=" + se.getDc2();
+        }
+        LOG.debug( "suffix=" + dn );
+        return dn;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/ldap/suffix/SuffixP.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/suffix/SuffixP.java b/src/main/java/org/apache/directory/fortress/core/ldap/suffix/SuffixP.java
new file mode 100755
index 0000000..f9f7f6d
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/suffix/SuffixP.java
@@ -0,0 +1,146 @@
+/*
+ *   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.
+ *
+ */
+package org.apache.directory.fortress.core.ldap.suffix;
+
+
+import org.apache.directory.fortress.core.ValidationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+
+/**
+ * Process module for the suffix or root node of Fortress directory structure. The suffix represents the topmost node in a directory information
+ * tree.  For example dc=companyName,dc=com.  The suffix data is passed using {@link Suffix} class.  This class does perform simple data validations.
+ * The {@link org.apache.directory.fortress.core.ant.FortressAntTask#addSuffixes()} method calls the {@link #add} from this class during initial base loads.
+ * Removal {@link org.apache.directory.fortress.core.ant.FortressAntTask#deleteSuffixes()} is performed during regression tests and should never
+ * be executed targeting production directory systems.<BR>
+ * This class will accept {@link Suffix}, and forward on to it's corresponding DAO class {@link SuffixDAO} for add/delete of suffix.
+ * <p>
+ * Class will throw {@link org.apache.directory.fortress.core.SecurityException} to caller in the event of security policy, data constraint violation or system
+ * error internal to DAO object. This class will forward DAO exceptions ({@link org.apache.directory.fortress.core.FinderException},
+ * {@link org.apache.directory.fortress.core.CreateException},{@link org.apache.directory.fortress.core.UpdateException},{@link org.apache.directory.fortress.core.RemoveException}),
+ *  or {@link org.apache.directory.fortress.core.ValidationException} as {@link org.apache.directory.fortress.core.SecurityException}s with appropriate
+ * error id from {@link GlobalErrIds}.
+ * <p>
+ * <font size="3" color="red">
+ * The {@link #delete} method in this class is destructive as it will remove all nodes below the suffix using recursive delete function.<BR>
+ * Extreme care should be taken during execution to ensure target dn is correct and permanent removal of data is intended.  There is no
+ * 'undo' for this operation.
+ * </font>
+ * <p/>
+ * Simple error mapping is performed in {@link #validate} class.
+ * <p/>
+ * This class is thread safe.
+ *
+ * @author Shawn McKinney
+ */
+public class SuffixP
+{
+    private static final String CLS_NM = SuffixP.class.getName();
+    private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
+
+
+    /**
+     * Add a new suffix to the Directory Information Tree (DIT).  After added the
+     * node will be listed in domain component format, i.e. dc=companyName, dc=com, or dc=orgName, dc=org.
+     *
+     * @param suffix contains the dc name and top level dc for target node.
+     * @throws org.apache.directory.fortress.core.SecurityException in event of validation or system error.
+     */
+    public final void add( Suffix suffix )
+        throws SecurityException
+    {
+        validate( suffix );
+        SuffixDAO sDao = new SuffixDAO();
+        sDao.create( suffix );
+    }
+
+
+    /**
+     * Remove the suffix along with descendant nodes.  This is a destructive method which will remove all DIT nodes under
+     * the specified.
+     * <p/>
+     * <font size="2" color="red">
+     * This method is destructive and will remove all nodes below.<BR>
+     * Extreme care should be taken during execution to ensure target dn is correct and permanent removal of data is intended.  There is no
+     * 'undo' for this operation.
+     * </font>
+     * <p/>
+     *
+     * @param suffix contains the dc name and top level dc for target node.
+     * @throws SecurityException in event of validation or system error.
+     */
+    public final void delete( Suffix suffix )
+        throws SecurityException
+    {
+        validate( suffix );
+        SuffixDAO sDao = new SuffixDAO();
+        sDao.remove( suffix );
+    }
+
+
+    /**
+     * Method will perform simple validations to ensure the integrity of the {@link Suffix} entity targeted for insertion
+     * or deletion in directory.
+     *
+     * @param entity contains the enum type to validate
+     * @throws org.apache.directory.fortress.core.SecurityException thrown in the event the attribute is null.
+     */
+    private void validate( Suffix entity )
+        throws SecurityException
+    {
+        if ( entity.getName().length() > GlobalIds.OU_LEN )
+        {
+            String name = entity.getName();
+            String error = "validate name [" + name + "] invalid length [" + entity.getName().length() + "]";
+            LOG.warn( error );
+            throw new ValidationException( GlobalErrIds.SUFX_NAME_INVLD, error );
+        }
+        if ( !VUtil.isNotNullOrEmpty( entity.getName() ) )
+        {
+            String error = "validate name validation failed, null or empty value";
+            LOG.warn( error );
+            throw new ValidationException( GlobalErrIds.SUFX_NAME_NULL, error );
+        }
+        if ( entity.getDc().length() > GlobalIds.OU_LEN )
+        {
+            String name = entity.getName();
+            String error = "validate dc [" + name + "] invalid length [" + entity.getName().length() + "]";
+            LOG.warn( error );
+            throw new ValidationException( GlobalErrIds.SUFX_DCTOP_INVLD, error );
+        }
+        if ( !VUtil.isNotNullOrEmpty( entity.getDc() ) )
+        {
+            String error = "validate dc validation failed, null or empty value";
+            LOG.warn( error );
+            throw new ValidationException( GlobalErrIds.SUFX_DCTOP_NULL, error );
+        }
+        VUtil.safeText( entity.getDescription(), GlobalIds.DESC_LEN );
+        if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) )
+        {
+            VUtil.description( entity.getDescription() );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/ldap/suffix/package.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/suffix/package.html b/src/main/java/org/apache/directory/fortress/core/ldap/suffix/package.html
new file mode 100755
index 0000000..a5d398c
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/suffix/package.html
@@ -0,0 +1,38 @@
+<!--
+ *   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.
+ *
+-->
+<html>
+   <head>
+      <title>Package Documentation for org.apache.directory.fortress.ldap.suffix</title>
+   </head>
+   <body>
+      <p>
+         This package contains APIs to perform create and teardown the ldap suffix node.
+      </p>
+      <p>
+         Care must be taken when performing the delete api as it is destructive and will attempt to
+          recursively remove all nodes below the suffix.  This delete is not intended as safe for
+          teardown on large, production data sets.  The delete is safe for teardown of smaller directory as in initial base loads and/or regression
+          testing operations.
+          The <b>org.apache.directory.fortress.ldap.suffix</b> package provides apis to add and remove suffix node, <b>dcObject</b>.
+          The suffix node is also called 'root' or 'baseDn' and is the uppermost node within a particular Directory Information Tree.
+          Example of valid suffix nodes is <b>dc=example,dc=com</b>.  The container nodes will be located as direct descendants of the suffix.
+      </p>
+   </body>
+</html>

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/overview.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/overview.html b/src/main/java/org/apache/directory/fortress/core/overview.html
new file mode 100755
index 0000000..49ccc8f
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/overview.html
@@ -0,0 +1,68 @@
+<!--
+ *   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.
+ *
+-->
+<html>
+   <head>
+      <title>Overview of the org.apache.fortress component</title>
+   </head>
+   <body>
+       A standards based and open source Identity Access Management Java SDK for LDAP v3 compliant systems.
+       <hr>
+      <h2>What can Fortress SDK do?</h2>
+       Contained within this SDK are APIs and utilities to perform authentication, authorization, administration, audit and password policies.
+       The most important package in this system is <A HREF="org/openldap/fortress/package-summary.html">org.apache.directory.fortress</A> which contains all of the public APIs that are called by outside programs.
+      <h3>Fortress Manager APIs</h3>
+       <ol>
+       <li><a href="org/openldap/fortress/AccessMgr.html">AccessMgr</a> - This class performs runtime access control operations on objects that are provisioned <a href="http://csrc.nist.gov/groups/SNS/rbac/documents/draft-rbac-implementation-std-v01.pdf">RBAC</a> entities that reside in LDAP directory.</li>
+       <li><a href="org/openldap/fortress/AdminMgr.html">AdminMgr</a> - This class performs administrative functions to provision Fortress <a href="http://csrc.nist.gov/groups/SNS/rbac/documents/draft-rbac-implementation-std-v01.pdf">RBAC</a> entities into the LDAP directory.</li>
+       <li><a href="org/openldap/fortress/AuditMgr.html">AuditMgr</a> - This interface prescribes methods used to search OpenLDAP's slapd access log.</li>
+       <li><a href="org/openldap/fortress/DelAccessMgr.html">DelAccessMgr</a> - This interface prescribes the API for performing runtime delegated access control operations on objects that are provisioned Fortress <a href="http://profsandhu.com/journals/tissec/p113-oh.pdf">ARBAC02</a> entities that reside in LDAP directory.</li>
+       <li><a href="org/openldap/fortress/DelAdminMgr.html">DelAdminMgr</a> - This class prescribes the <a href="http://profsandhu.com/journals/tissec/p113-oh.pdf">ARBAC02</a> DelegatedAdminMgr interface for performing policy administration of Fortress ARBAC entities that reside in LDAP directory.</li>
+       <li><a href="org/openldap/fortress/DelReviewMgr.html">DelReviewMgr</a> - This class prescribes the <a href="http://profsandhu.com/journals/tissec/p113-oh.pdf">ARBAC02</a> DelegatedReviewMgr interface for performing policy interrogation of provisioned Fortress ARBAC02 entities that reside in LDAP directory.</li>
+       <li><a href="org/openldap/fortress/PwPolicyMgr.html">PwPolicyMgr</a> - This class adheres to <a href="http://tools.ietf.org/html/draft-behera-ldap-password-policy-10">IETF PW policy draft</a> and is used to perform administrative and review functions on the <a href="org/openldap/fortress/rbac/PwPolicy.html">PWPOLICIES</a> and <a href="org/openldap/fortress/rbac/User.html">USERS</a> data sets within Fortress.</li>
+       <li><a href="org/openldap/fortress/ReviewMgr.html">ReviewMgr</a> - This interface prescribes the administrative review functions on already provisioned Fortress <a href="http://csrc.nist.gov/groups/SNS/rbac/documents/draft-rbac-implementation-std-v01.pdf">RBAC</a> entities that reside in LDAP directory.</li>
+       </ol>
+       <h5>Error Handling</h5>
+       These APIs throw checked exceptions defined in <a href="org/openldap/fortress/SecurityException.html">SecurityException</a>
+       <hr>
+      <h2>What technologies are used?</h2>
+      <p>
+         Fortress SDK runs on any platform that supports Java technology and LDAP v3 protocols.  Functionality that extends beyond
+          LDAP v3 is provided via <a href="http://openldap.org/">OpenLDAP</a> specific features.  In other words Fortress was optimized to run on OpenLDAP but works on any directory.
+      </p>
+       <hr>
+      <h2>What are the conditions of use?</h2>
+      <p>
+         This software development kit is open source, thus free to use and distribute via the <a href="http://www.OpenLDAP.org/license.html">OpenLDAP Public License</a>.
+         It was developed and tested on open systems like <a href="http://www.ubuntu.com/">Ubuntu</a> and <a href="http://www.centos.org/">Centos</a> and was helped along
+         by the following open source products:
+          <ol>
+          <li><a href="http://www.openldap.org/project/">The OpenLDAP Project</a></li>
+          <li><a href="http://www.apache.org/">The Apache Software Foundation</a></li>
+          <li><a href="http://www.unboundid.com/">UnboundID</a></li>
+          <li><a href="http://www.eigenbase.org/">The Eigenbase Project</a></li>
+          <li><a href="http://ehcache.org/">Ehcache</a></li>
+          </ol>
+      </p>
+      <p>
+         Check out these <A HREF="../samples/overview-summary.html">samples</A> in the <b>org.apache.directory.fortress.core.samples</b> package to show how Fortress APIs can be used by outside clients.  The
+         <b>dist</b> target in build.xml creates the samples package in the /dist folder of this project and is intended to be used for experimentation.
+      </p>
+   </body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/package.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/package.html b/src/main/java/org/apache/directory/fortress/core/package.html
new file mode 100755
index 0000000..770d6ee
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/package.html
@@ -0,0 +1,148 @@
+<!--
+ *   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.
+ *
+-->
+<html>
+   <head>
+      <title>Package Documentation for org.apache.directory.fortress</title>
+   </head>
+   <body>
+      <p>
+         This package contains public APIs that are used by Java programs to provide Identity and Access Management functionality.  The APIs
+         are organized into categories or 'Managers'.  Each manager controls a specific area of functionality.
+      <h3>Managers</h3>
+          <ol>
+          <li>{@link org.apache.directory.fortress.AccessMgr} is used for RBAC runtime security checking</li>
+          <li>{@link org.apache.directory.fortress.AdminMgr} is for RBAC provisioning</li>
+          <li>{@link org.apache.directory.fortress.AuditMgr} is for interrogating OpenLDAP audit and historical logs</li>
+          <li>{@link org.apache.directory.fortress.DelAccessMgr} is used for ARBAC runtime security checking</li>
+          <li>{@link org.apache.directory.fortress.DelAdminMgr} is for ARBAC provisioning</li>
+          <li>{@link org.apache.directory.fortress.DelReviewMgr} is used to interrogate ARBAC policy</li>
+          <li>{@link org.apache.directory.fortress.PwPolicyMgr} is for performing OpenLDAP pwpolicy provisioning and interrogation</li>
+          <li>{@link org.apache.directory.fortress.ReviewMgr} is used to interrogate RBAC policy</li>
+          </ol>
+      </p>
+      <p>
+         The <b>org.apache.directory.fortress</b> package provides managers, factories and exception classes that can be thrown when
+          fortress needs to report an error status code back to caller.  The fortress manager APIs are based on standards like <a href="http://csrc.nist.gov/groups/SNS/rbac/documents/draft-rbac-implementation-std-v01.pdf">RBAC</a>,
+          <a href="http://profsandhu.com/journals/tissec/p113-oh.pdf">ARBAC02</a> and <a href="http://tools.ietf.org/html/draft-behera-ldap-password-policy-10/">Password Policy for LDAP Directories</a>.
+          A {@link org.apache.directory.fortress.util.time.Constraint} mechanism is used by fortress to control the {@link org.apache.directory.fortress.util.time.Time}, {@link org.apache.directory.fortress.util.time.Date} and {@link org.apache.directory.fortress.util.time.Day} of week for when a
+          {@link org.apache.directory.fortress.core.rbac.User} or {@link org.apache.directory.fortress.core.rbac.UserRole} entity can be activated within a {@link org.apache.directory.fortress.core.rbac.Session}.
+          There is also a lockout mechanism to temporarily bar entities from activating.  AuditMgr may be used to interrogate OpenLDAP audit and historical information.
+      </p>
+      <hr>
+      <h2>Description of Package Contents</h2>
+      This package contains APIs to do the following
+      <ol>
+      <li>Role Based Access Control (RBAC)</li>
+      <li>Administrative Role Based Access Control (ARBAC)</li>
+      <li>Password Policies</li>
+      <li>Audit Trail</li>
+      </ol>
+      The following sections provides more info on each.
+      <hr>
+      <h3>1. Role Based Access Control description</h3>
+      <p>
+      Many of the method names and signatures within this package were taken directly from ANSI INCITS 359-2004.
+      The RBAC Functional specification describes administrative operations for the creation
+      and maintenance of RBAC element sets and relations; administrative review functions for
+      performing administrative queries; and system functions for creating and managing
+      RBAC attributes on user sessions and making access control decisions.
+      <p/>
+      <h4>RBAC0 - Core</h4>
+      Many-to-many relationship between Users, Roles and Permissions. Selective role activation into sessions.  API to add, update, delete identity data and perform identity and access control decisions during runtime operations.
+      <p/>
+      <img src="./doc-files/RbacCore.png">
+      <h4>RBAC1 - General Hierarchical Roles</h4>
+      Simplifies role engineering tasks using inheritance of one or more parent roles.
+      <p/>
+      <img src="./doc-files/RbacHier.png">
+      <h4>RBAC2 - Static Separation of Duty (SSD) Relations</h4>
+      Enforce mutual membership exclusions across role assignments.  Facilitate dual control policies by restricting which roles may be assigned to users in combination.  SSD provide added granularity for authorization limits which help enterprises meet strict compliance regulations.
+      <p/>
+      <img src="./doc-files/RbacSSD.png">
+      <h4>RBAC3 - Dynamic Separation of Duty (DSD) Relations</h4>
+      Control allowed role combinations to be activated within an RBAC session.  DSD policies fine tune role policies that facilitate authorization dual control and two man policy restrictions during runtime security checks.
+      <p/>
+      <img src="./doc-files/RbacDSD.png">
+      <p/>
+      <hr>
+      <h3>2. Administrative Role Based Access Control (ARBAC) description</h3>
+      These APIs map directly to similar named APIs specified by ARBAC02 functions.  The ARBAC Functional specification describes delegated administrative
+      operations for the creation and maintenance of ARBAC element sets and relations.  Delegated administrative review functions for performing administrative queries
+      and system functions for creating and managing ARBAC attributes on user sessions and making delegated administrative access control decisions.
+      <h4>ARBAC02 Diagram</h4>
+      <img src="./doc-files/ARbac.png">
+      <p/>
+      Fortress fully supports the Oh/Sandhu/Zhang ARBAC02 model for delegated administration.  ARBAC provides large enterprises the capability to delegate administrative authority to users that reside outside of the security admin group.
+      Decentralizing administration helps because it provides security provisioning capability to work groups without sacrificing regulations for accountability or traceability.
+      <p/>
+      <hr>
+      <h3>3. Password Policy description</h3>
+      Fortress APIs store and interrogate policies on <a href="http://www.openldap.org/">OpenLDAP</a> which supports the IETF <a href="http://tools.ietf.org/html/draft-behera-ldap-password-policy-10/">Password Policies LDAP directories</a></li> draft.  Policies may be applied at the user, group or global level.
+      Password enforcement options include:
+      <ul>
+      <li>A configurable limit on failed authentication attempts.</li>
+      <li>A counter to track the number of failed authentication attempts.</li>
+      <li>A time frame in which the limit of consecutive failed authentication attempts must happen before action is taken.</li>
+      <li>The action to be taken when the limit is reached. The action will either be nothing, or the account will be locked.</li>
+      <li>An amount of time the account is locked (if it is to be locked) This can be indefinite.</li>
+      <li>Password expiration.</li>
+      <li>Expiration warning</li>
+      <li>Grace authentications</li>
+      <li>Password history</li>
+      <li>Password minimum age</li>
+      <li>Password minimum length</li>
+      <li>Password Change after Reset</li>
+      <li>Safe Modification of Password</li>
+      </ul>
+      <h4>Password Policy diagram</h4>
+      The following is an example of policies that can be configured. There is no limit to the number of different policies that can be created and enforced.
+      <p/>
+      <img src="./doc-files/PasswordPolicy.png">
+      <p/>
+      <hr>
+      <h3>4. History and Audit trail using OpenLDAP</h3>
+      Provides an OpenLDAP access log retrieval mechanism that enables security event monitoring.
+      <ol>
+      <li>Authentication events:
+      <li>Session enablement events
+      <li>Authorization events
+      <li>Entity mods and deletes
+      </li>
+      </ol>
+      <h4>Diagram of Audit Events</h4>
+      <img src="./doc-files/Audit.png">
+      <p/>
+      All events include Fortress context, see {@code FortEntity}.
+      <p/>
+      <h4>
+      The following APIs generate events subsequently stored in this access log:
+      </h4>
+      <ul>
+      <li> {@link org.apache.directory.fortress.AccessMgr}
+      <li> {@link org.apache.directory.fortress.AdminMgr}
+      <li> {@link org.apache.directory.fortress.AdminMgr}
+      <li> {@link org.apache.directory.fortress.DelAdminMgr}
+      <li> {@link org.apache.directory.fortress.cfg.ConfigMgr}
+      <li> {@link org.apache.directory.fortress.PwPolicyMgr}
+      </ul>
+      </p>
+   </body>
+</html>
+

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/AccelMgrImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/AccelMgrImpl.java b/src/main/java/org/apache/directory/fortress/core/rbac/AccelMgrImpl.java
new file mode 100644
index 0000000..f9e017c
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/AccelMgrImpl.java
@@ -0,0 +1,282 @@
+/*
+ *   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.
+ *
+ */
+package org.apache.directory.fortress.core.rbac;
+
+
+import java.util.List;
+
+import org.apache.directory.fortress.core.AccelMgr;
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.rbac.dao.AcceleratorDAO;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+
+/**
+ * Implementation class that performs runtime access control operations on data objects of type Fortress entities
+ * This class performs runtime access control operations on objects that are provisioned RBAC entities
+ * that reside in LDAP directory.  These APIs map directly to similar named APIs specified by ANSI and NIST
+ * RBAC system functions.
+ * Many of the java doc function descriptions found below were taken directly from ANSI INCITS 359-2004.
+ * The RBAC Functional specification describes administrative operations for the creation
+ * and maintenance of RBAC element sets and relations; administrative review functions for
+ * performing administrative queries; and system functions for creating and managing
+ * RBAC attributes on user sessions and making access control decisions.
+ * <p/>
+ * <hr>
+ * <h4>RBAC0 - Core</h4>
+ * Many-to-many relationship between Users, Roles and Permissions. Selective role activation into sessions.  API to add, update, delete identity data and perform identity and access control decisions during runtime operations.
+ * <p/>
+ * <img src="../doc-files/RbacCore.png">
+ * <hr>
+ * <h4>RBAC1 - General Hierarchical Roles</h4>
+ * Simplifies role engineering tasks using inheritance of one or more parent roles.
+ * <p/>
+ * <img src="../doc-files/RbacHier.png">
+ * <hr>
+ * <h4>RBAC2 - Static Separation of Duty (SSD) Relations</h4>
+ * Enforce mutual membership exclusions across role assignments.  Facilitate dual control policies by restricting which roles may be assigned to users in combination.  SSD provide added granularity for authorization limits which help enterprises meet strict compliance regulations.
+ * <p/>
+ * <img src="../doc-files/RbacSSD.png">
+ * <hr>
+ * <h4>RBAC3 - Dynamic Separation of Duty (DSD) Relations</h4>
+ * Control allowed role combinations to be activated within an RBAC session.  DSD policies fine tune role policies that facilitate authorization dual control and two man policy restrictions during runtime security checks.
+ * <p/>
+ * <img src="../doc-files/RbacDSD.png">
+ * <hr>
+ * <p/>
+ * This class is NOT thread safe if parent instance variables ({@link #contextId} or {@link #adminSess}) are set.
+ * <p/>
+ *
+ * @author Shawn McKinney
+ */
+public class AccelMgrImpl extends Manageable implements AccelMgr
+{
+    private static final String CLS_NM = AccessMgrImpl.class.getName();
+    private static final AcceleratorDAO aDao = new org.apache.directory.fortress.core.rbac.dao.apache.AcceleratorDAO();
+
+
+    /**
+     * package private constructor ensures outside classes must use factory: {@link org.apache.directory.fortress.core.AccelMgrFactory}
+     */
+    public AccelMgrImpl()
+    {
+    }
+
+
+    /**
+     * Perform user authentication {@link org.apache.directory.fortress.core.rbac.User#password} and role activations.<br />
+     * This method must be called once per user prior to calling other methods within this class.
+     * The successful result is {@link org.apache.directory.fortress.core.rbac.Session} that contains target user's RBAC {@link org.apache.directory.fortress.core.rbac.User#roles} and Admin role {@link org.apache.directory.fortress.core.rbac.User#adminRoles}.<br />
+     * In addition to checking user password validity it will apply configured password policy checks {@link org.apache.directory.fortress.core.rbac.User#pwPolicy}..<br />
+     * Method may also store parms passed in for audit trail {@link org.apache.directory.fortress.core.rbac.FortEntity}.
+     * <h4> This API will...</h4>
+     * <ul>
+     * <li> authenticate user password if trusted == false.
+     * <li> perform <a href="http://www.openldap.org/">OpenLDAP</a> <a href="http://tools.ietf.org/html/draft-behera-ldap-password-policy-10">password policy evaluation</a>, see {@link org.apache.directory.fortress.core.ldap.openldap.OLPWControlImpl}.
+     * <li> fail for any user who is locked by OpenLDAP's policies {@link org.apache.directory.fortress.core.rbac.User#isLocked()}, regardless of trusted flag being set as parm on API.
+     * <li> evaluate temporal {@link org.apache.directory.fortress.core.util.time.Constraint}(s) on {@link org.apache.directory.fortress.core.rbac.User}, {@link org.apache.directory.fortress.core.rbac.UserRole} and {@link UserAdminRole} entities.
+     * <li> process selective role activations into User RBAC Session {@link org.apache.directory.fortress.core.rbac.User#roles}.
+     * <li> check Dynamic Separation of Duties {@link org.apache.directory.fortress.core.rbac.DSDChecker#validate(org.apache.directory.fortress.core.rbac.Session, org.apache.directory.fortress.core.util.time.Constraint, org.apache.directory.fortress.core.util.time.Time)} on {@link org.apache.directory.fortress.core.rbac.User#roles}.
+     * <li> process selective administrative role activations {@link org.apache.directory.fortress.core.rbac.User#adminRoles}.
+     * <li> return a {@link org.apache.directory.fortress.core.rbac.Session} that contains a reference to an object stored on the RBAC server..
+     * <li> throw a checked exception that will be {@link org.apache.directory.fortress.core.SecurityException} or its derivation.
+     * <li> throw a {@link SecurityException} for system failures.
+     * <li> throw a {@link org.apache.directory.fortress.core.PasswordException} for authentication and password policy violations.
+     * <li> throw a {@link org.apache.directory.fortress.core.ValidationException} for data validation errors.
+     * <li> throw a {@link org.apache.directory.fortress.core.FinderException} if User id not found.
+     * </ul>
+     * <h4>
+     * The function is valid if and only if:
+     * </h4>
+     * <ul>
+     * <li> the user is a member of the USERS data set
+     * <li> the password is supplied (unless trusted).
+     * <li> the (optional) active role set is a subset of the roles authorized for that user.
+     * </ul>
+     * <h4>
+     * The following attributes may be set when calling this method
+     * </h4>
+     * <ul>
+     * <li> {@link org.apache.directory.fortress.core.rbac.User#userId} - required
+     * <li> {@link org.apache.directory.fortress.core.rbac.User#password}
+     * <li> {@link org.apache.directory.fortress.core.rbac.User#roles} contains a list of RBAC role names authorized for user and targeted for activation within this session.  Default is all authorized RBAC roles will be activated into this Session.
+     * <li> {@link org.apache.directory.fortress.core.rbac.User#adminRoles} contains a list of Admin role names authorized for user and targeted for activation.  Default is all authorized ARBAC roles will be activated into this Session.
+     * <li> {@link org.apache.directory.fortress.core.rbac.User#props} collection of name value pairs collected on behalf of User during signon.  For example hostname:myservername or ip:192.168.1.99
+     * </ul>
+     * <h4>
+     * Notes:
+     * </h4>
+     * <ul>
+     * <li> roles that violate Dynamic Separation of Duty Relationships will not be activated into session.
+     * <li> role activations will proceed in same order as supplied to User entity setter, see {@link org.apache.directory.fortress.core.rbac.User#setRole(String)}.
+     * </ul>
+     * </p>
+     *
+     * @param user Contains {@link org.apache.directory.fortress.core.rbac.User#userId}, {@link org.apache.directory.fortress.core.rbac.User#password} (optional if {@code isTrusted} is 'true'), optional {@link org.apache.directory.fortress.core.rbac.User#roles}, optional {@link org.apache.directory.fortress.core.rbac.User#adminRoles}
+     * @param isTrusted if true password is not required.
+     * @return Session object will contain authentication result code {@link org.apache.directory.fortress.core.rbac.Session#errorId},
+     * @throws SecurityException in the event of data validation failure, security policy violation or DAO error.
+     */
+    @Override
+    public Session createSession( User user, boolean isTrusted )
+        throws SecurityException
+    {
+        String methodName = "createSession";
+        assertContext( CLS_NM, methodName, user, GlobalErrIds.USER_NULL );
+        return aDao.createSession( user );
+    }
+
+
+    /**
+     * This function requests the RBAC server to delete the session from cache.
+     *
+     * @param session object contains the user's returned RBAC session from the createSession method.
+     * @throws SecurityException in the event runtime error occurs with system.
+     */
+    @Override
+    public void deleteSession( Session session )
+        throws SecurityException
+    {
+        String methodName = "deleteSession";
+        assertContext( CLS_NM, methodName, session, GlobalErrIds.USER_SESS_NULL );
+        aDao.deleteSession( session );
+    }
+
+
+    /**
+     * This function returns the active roles associated with a session. The function is valid if
+     * and only if the session is a valid Fortress session.
+     *
+     * @param session object contains the user's returned RBAC session from the createSession method.
+     * @return List<UserRole> containing all roles active in user's session.  This will NOT contain inherited roles.
+     * @throws SecurityException is thrown if session invalid or system. error.
+     */
+    public List<UserRole> sessionRoles(Session session)
+        throws SecurityException
+    {
+        String methodName = "sessionRoles";
+        assertContext( CLS_NM, methodName, session, GlobalErrIds.USER_SESS_NULL );
+        return aDao.sessionRoles( session );
+    }
+
+
+    /**
+     * Perform user rbac authorization.  This function returns a Boolean value meaning whether the subject of a given session is
+     * allowed or not to perform a given operation on a given object. The function is valid if and
+     * only if the session is a valid Fortress session, the object is a member of the OBJS data set,
+     * and the operation is a member of the OPS data set. The session's subject has the permission
+     * to perform the operation on that object if and only if that permission is assigned to (at least)
+     * one of the session's active roles. This implementation will verify the roles or userId correspond
+     * to the subject's active roles are registered in the object's access control list.
+     *
+     * @param perm  must contain the object, {@link org.apache.directory.fortress.core.rbac.Permission#objName}, and operation, {@link org.apache.directory.fortress.core.rbac.Permission#opName}, of permission User is trying to access.
+     * @param session This object must be instantiated by calling {@link AccessMgrImpl#createSession} method before passing into the method.  No variables need to be set by client after returned from createSession.
+     * @return True if user has access, false otherwise.
+     * @throws SecurityException in the event of data validation failure, security policy violation or DAO error.
+     */
+    @Override
+    public boolean checkAccess( Session session, Permission perm )
+        throws SecurityException
+    {
+        String methodName = "checkAccess";
+        assertContext( CLS_NM, methodName, perm, GlobalErrIds.PERM_NULL );
+        assertContext( CLS_NM, methodName, session, GlobalErrIds.USER_SESS_NULL );
+        VUtil.assertNotNullOrEmpty( perm.getOpName(), GlobalErrIds.PERM_OPERATION_NULL, getFullMethodName( CLS_NM,
+            methodName ) );
+        VUtil.assertNotNullOrEmpty( perm.getObjName(), GlobalErrIds.PERM_OBJECT_NULL, getFullMethodName( CLS_NM,
+            methodName ) );
+        return aDao.checkAccess( session, perm );
+    }
+
+
+    /**
+     * This function returns the permissions of the session, i.e., the permissions assigned
+     * to its authorized roles. The function is valid if and only if the session is a valid Fortress session.
+     *
+     * @param session object contains the user's returned RBAC session from the createSession method.
+     * @return List<Permission> containing permissions (op, obj) active for user's session.
+     * @throws SecurityException in the event runtime error occurs with system.
+     */
+    @Override
+    public List<Permission> sessionPermissions( Session session )
+        throws SecurityException
+    {
+        throw new java.lang.UnsupportedOperationException();
+    }
+
+
+    /**
+     * This function adds a role as an active role of a session whose owner is a given user.
+     * <p>
+     * The function is valid if and only if:
+     * <ul>
+     * <li> the user is a member of the USERS data set
+     * <li> the role is a member of the ROLES data set
+     * <li> the role inclusion does not violate Dynamic Separation of Duty Relationships
+     * <li> the session is a valid Fortress session
+     * <li> the user is authorized to that role
+     * <li> the session is owned by that user.
+     * </ul>
+     * </p>
+     *
+     * @param session object contains the user's returned RBAC session from the createSession method.
+     * @param role object contains the role name, {@link UserRole#name}, to be activated into session.
+     * @throws SecurityException is thrown if user is not allowed to activate or runtime error occurs with system.
+     */
+    @Override
+    public void addActiveRole( Session session, UserRole role )
+        throws SecurityException
+    {
+        String methodName = "addActiveRole";
+        assertContext( CLS_NM, methodName, session, GlobalErrIds.USER_SESS_NULL );
+        assertContext( CLS_NM, methodName, role, GlobalErrIds.ROLE_NULL );
+        VUtil.assertNotNullOrEmpty( role.getUserId(), GlobalErrIds.USER_ID_NULL,
+            getFullMethodName( CLS_NM, methodName ) );
+        VUtil.assertNotNullOrEmpty( role.getName(), GlobalErrIds.ROLE_NM_NULL, getFullMethodName( CLS_NM,
+            methodName ) );
+        aDao.addActiveRole( session, role );
+    }
+
+
+    /**
+     * This function deletes a role from the active role set of a session owned by a given user.
+     * The function is valid if and only if the user is a member of the USERS data set, the
+     * session object contains a valid Fortress session, the session is owned by the user,
+     * and the role is an active role of that session.
+     *
+     * @param session object contains the user's returned RBAC session from the createSession method.
+     * @param role object contains the role name, {@link UserRole#name}, to be deactivated.
+     * @throws SecurityException is thrown if user is not allowed to deactivate or runtime error occurs with system.
+     */
+    @Override
+    public void dropActiveRole( Session session, UserRole role )
+        throws SecurityException
+    {
+        String methodName = "dropActiveRole";
+        assertContext( CLS_NM, methodName, session, GlobalErrIds.USER_SESS_NULL );
+        assertContext( CLS_NM, methodName, role, GlobalErrIds.ROLE_NULL );
+        VUtil.assertNotNullOrEmpty( role.getUserId(), GlobalErrIds.USER_ID_NULL,
+            getFullMethodName( CLS_NM, methodName ) );
+        VUtil.assertNotNullOrEmpty( role.getName(), GlobalErrIds.ROLE_NM_NULL, getFullMethodName( CLS_NM,
+            methodName ) );
+        aDao.dropActiveRole( session, role );
+    }
+}
\ No newline at end of file


Mime
View raw message