Author: erodriguez
Date: Wed Dec 29 03:13:03 2004
New Revision: 123624

URL: http://svn.apache.org/viewcvs?view=rev&rev=123624
Log:
Infrastructure for using changepw protocol with embedded Eve store.
Added:
   
incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/EmbeddedEveStore.java
   
incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/PasswordStoreEntry.java
   
incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/PasswordStoreEntryModifier.java

Added: 
incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/EmbeddedEveStore.java
Url: 
http://svn.apache.org/viewcvs/incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/EmbeddedEveStore.java?view=auto&rev=123624
==============================================================================
--- (empty file)
+++ 
incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/EmbeddedEveStore.java
   Wed Dec 29 03:13:03 2004
@@ -0,0 +1,339 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.kerberos.changepw.store;
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchResult;
+import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.kerberos.KerberosPrincipal;
+
+import org.apache.ldap.common.ldif.LdifIterator;
+import org.apache.ldap.common.ldif.LdifParser;
+import org.apache.ldap.common.ldif.LdifParserImpl;
+import org.apache.ldap.common.message.LockableAttributesImpl;
+import org.apache.ldap.common.name.LdapName;
+import org.apache.ldap.common.util.NestableRuntimeException;
+
+
+/**
+ * ChangePassword backing store implementation using an embedded Eve DIT
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class EmbeddedEveStore implements PasswordStore
+{
+
+    // ------------------------------------------------------------------------
+    // Krb5 Schema Attributes
+    // ------------------------------------------------------------------------
+
+    /**
+     * The key of the property specifying where Kerberos users are stored.  If 
this
+     * property is not set the store defaults to performing a subtree search
+     * from the DN in the [EMAIL PROTECTED] Context#PROVIDER_URL}. If it is 
present a more
+     * efficient search is conducted on the more specific DN.
+     */
+    public static final String KDC_ENTRY_BASEDN_KEY = "kdc.entry.basedn";
+    public static final String KDC_ENTRY_LDIF_FILE = "kdc.entry.ldif.file";
+
+    /** the krb5kdc schema key for a krb5KDCEntry */
+    private static final String KEY_ATTR = "krb5Key";
+    /** the krb5kdc schema key encryption type for a krb5KDCEntry */
+    private static final String TYPE_ATTR = "krb5EncryptionType";
+    /** the krb5kdc schema principal name for a krb5KDCEntry */
+    private static final String PRINCIPAL_ATTR = "krb5PrincipalName";
+    /** the krb5kdc schema key version identifier for a krb5KDCEntry */
+    private static final String VERSION_ATTR = "krb5KeyVersionNumber";
+
+    /** JNDI environment properties and more */
+    private final Hashtable env;
+    /** a handle on the top initial context: get new context from this */
+    private InitialDirContext ctx;
+    /** the search base relative to provider URL to use for reading entries */
+    private Name searchBaseDn;
+
+
+    /**
+     * Creates the embedded Eve principal store.
+     *
+     * @param env the environment properties used to initialize the Eve
+     * Kerberos environment
+     */
+    public EmbeddedEveStore( Hashtable env )
+    {
+        this.env = ( Hashtable ) env.clone();
+        this.env.put( Context.INITIAL_CONTEXT_FACTORY, 
"org.apache.eve.jndi.EveContextFactory" );
+    }
+
+
+    /**
+     * Fires up the Eve backing store using the environment properties 
supplied to the
+     * constructor.  The JNDI default context factor and some other parameters
+     * are automatically set though.  This method then checks to see if the
+     * suffix is installed and setup according to the needed DIT structure.
+     *
+     * Create some additional indices for the Kerberos schema, namely on
+     * krb5PrincipalName.  Also objectClass should be indexed as well.  If 
these
+     * indices are not specified we should add them here.
+     */
+    public void init()
+    {
+        LdapName ctxRoot;
+
+        try
+        {
+            ctx = new InitialDirContext( env );
+        }
+        catch ( NamingException e )
+        {
+            // @todo for now until we can find a better means of error handling
+            e.printStackTrace();
+            String msg = "Failed to create initial context for Eve provider";
+            NestableRuntimeException fault;
+            fault = new NestableRuntimeException( msg, e );
+            throw fault;
+        }
+
+        // get the seach base if it has been set ------------------------------
+        if ( env.containsKey( KDC_ENTRY_BASEDN_KEY ) )
+        {
+            try
+            {
+                ctxRoot = new LdapName( ctx.getNameInNamespace() );
+                searchBaseDn = new LdapName( ( String ) env.get( 
KDC_ENTRY_BASEDN_KEY ) );
+
+                if ( searchBaseDn.startsWith( ctxRoot ) )
+                {
+                    for ( int ii = 0; ii < ctxRoot.size(); ii++ )
+                    {
+                        searchBaseDn.remove( 0 );
+                    }
+                }
+                else
+                {
+                    String msg = "Failed to create initial context for Eve 
provider";
+                    IllegalArgumentException fault;
+                    fault = new IllegalArgumentException( msg );
+                    throw fault;
+                }
+            }
+            catch ( NamingException e )
+            {
+                // @todo for now until we can find a better means of error 
handling
+                e.printStackTrace();
+                String msg = "Failed to find search base for Eve store";
+                NestableRuntimeException fault;
+                fault = new NestableRuntimeException( msg, e );
+                throw fault;
+            }
+        }
+
+        // An LDIF must be loaded if this is the first time we're starting
+        // otherwise we're done and ready to serve lookup requests
+        if ( ! env.containsKey( KDC_ENTRY_LDIF_FILE ) )
+        {
+            return;
+        }
+
+        try
+        {
+            File file = new File( ( ( String ) env.get( KDC_ENTRY_LDIF_FILE ) 
).trim() );
+
+            if ( ! file.exists() )
+            {
+                System.err.println( "LDIF file '" + file.getAbsolutePath() + 
"' does not exit!" );
+
+                System.exit( 4 );
+            }
+
+            FileInputStream in = new FileInputStream( file );
+            LdifIterator iterator = new LdifIterator( in );
+            LdifParser ldifParser = new LdifParserImpl();
+
+            while ( iterator.hasNext() )
+            {
+                String ldif = ( String ) iterator.next();
+                Attributes attributes = new LockableAttributesImpl();
+                ldifParser.parse( attributes, ldif );
+                String dn = ( String ) attributes.remove( "dn" ).get();
+
+                if ( attributes.get( "objectClass" ).contains( "krb5KDCEntry" 
) )
+                {
+                    String pw = ( String ) attributes.get( "userpassword" 
).get();
+                    String krbPrincipal = ( String ) attributes.get( 
PRINCIPAL_ATTR ).get();
+                    KerberosPrincipal principal = new KerberosPrincipal( 
krbPrincipal );
+                    KerberosKey key = new KerberosKey( principal, 
pw.toCharArray(), "DES" ) ;
+                    byte[] encodedKey = key.getEncoded();
+                    attributes.put( KEY_ATTR, encodedKey );
+                    attributes.put( VERSION_ATTR, Integer.toString( 
key.getVersionNumber() ) );
+                    attributes.put( TYPE_ATTR, Integer.toString( 
key.getKeyType() ) );
+                }
+
+                try
+                {
+                    if ( ctx.lookup( dn ) == null )
+                    {
+                        System.out.println( "Entry " + dn + " from LDIF 
exists." );
+                        continue;
+                    }
+                }
+                catch( Exception e )
+                {
+                    System.out.println( "Entry " + dn
+                            + " from LDIF does not exist.  Creating it ..." );
+
+                }
+
+                ctx.createSubcontext( getRelativeName( ctx, dn ), attributes );
+            }
+        }
+        catch( Exception e )
+        {
+            // @todo for now until we can find a better means of error handling
+            e.printStackTrace();
+            String msg = "Failed to import initial LDIF into Eve store";
+            NestableRuntimeException fault;
+            fault = new NestableRuntimeException( msg, e );
+            throw fault;
+        }
+
+
+        try
+        {
+            String ldifFile = ( String ) env.get( KDC_ENTRY_LDIF_FILE );
+            FileInputStream in = new FileInputStream( ldifFile );
+            LdifIterator iterator = new LdifIterator( in );
+            LdifParser ldifParser = new LdifParserImpl();
+
+            while ( iterator.hasNext() )
+            {
+                String ldif = ( String ) iterator.next();
+                Attributes attributes = new LockableAttributesImpl();
+                ldifParser.parse( attributes, ldif );
+                String dn = ( String ) attributes.remove( "dn" ).get();
+
+                Context stored = ( Context ) ctx.lookup( getRelativeName( ctx, 
dn ) );
+
+                if ( stored == null )
+                {
+                    throw new IllegalStateException( "LDIF entries not being 
pushed to disk" );
+                }
+            }
+        }
+        catch( Exception e )
+        {
+            // @todo for now until we can find a better means of error handling
+            e.printStackTrace();
+            String msg = "Failed to import initial LDIF into Eve store";
+            NestableRuntimeException fault;
+            fault = new NestableRuntimeException( msg, e );
+            throw fault;
+        }
+    }
+
+
+    public Name getRelativeName( Context base, String dn ) throws 
NamingException
+    {
+        LdapName rdn = new LdapName( dn );
+        LdapName baseDn = new LdapName( base.getNameInNamespace() );
+
+        if ( rdn.startsWith( baseDn ) )
+        {
+            for ( int ii = 0; ii < baseDn.size(); ii++ )
+            {
+                rdn.remove( 0 );
+            }
+        }
+        else
+        {
+            throw new NamingException( dn + " is not a subordinate of context:"
+                + baseDn.toString() );
+        }
+
+        return rdn;
+    }
+
+
+    public String changePassword( KerberosPrincipal principal, byte[] key )
+    {
+        if ( principal == null )
+        {
+            return null;
+        }
+
+        Attributes attributes = new LockableAttributesImpl();
+        attributes.put( PRINCIPAL_ATTR, principal.getName() );
+        try
+        {
+            Attributes attrs = null;
+            NamingEnumeration list = ctx.search( searchBaseDn, attributes );
+            if ( list.hasMore() )
+            {
+                SearchResult result = ( SearchResult ) list.next();
+                attrs = result.getAttributes();
+            }
+            list.close();
+
+            if ( attrs == null )
+            {
+                return null;
+            }
+
+            return getEntry( attrs );
+        }
+        catch ( NamingException e )
+        {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+
+    /**
+     * Marshals an a String from an Attributes object.
+     *
+     * @param attrs the attributes of the Kerberos principal
+     * @return the entry for the principal
+     * @throws NamingException if there are any access problems
+     */
+    private String getEntry( Attributes attrs ) throws NamingException
+    {
+        PasswordStoreEntryModifier modifier = new PasswordStoreEntryModifier();
+        String principal = (String) attrs.get( PRINCIPAL_ATTR ).get();
+        String encryptionType = (String) attrs.get( TYPE_ATTR ).get();
+        String keyVersionNumber = (String) attrs.get( VERSION_ATTR ).get();
+        byte[] keyBytes = (byte[]) attrs.get( KEY_ATTR ).get();
+
+        modifier.setPrincipal( new KerberosPrincipal( principal ) );
+        modifier.setEncryptionType( Integer.parseInt( encryptionType ) );
+        modifier.setKeyVersionNumber( Integer.parseInt( keyVersionNumber ) );
+        modifier.setKey( keyBytes );
+        return modifier.getEntry().getCommonName();
+    }
+}
+

Added: 
incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/PasswordStoreEntry.java
Url: 
http://svn.apache.org/viewcvs/incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/PasswordStoreEntry.java?view=auto&rev=123624
==============================================================================
--- (empty file)
+++ 
incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/PasswordStoreEntry.java
 Wed Dec 29 03:13:03 2004
@@ -0,0 +1,90 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.kerberos.changepw.store;
+
+import org.apache.kerberos.crypto.encryption.*;
+import org.apache.kerberos.messages.value.*;
+
+import javax.security.auth.kerberos.*;
+
+public class PasswordStoreEntry {
+       
+       // 'Principal'
+       private String            _commonName;
+       private KerberosPrincipal _principal;
+       
+       // 'KDCEntry'
+       private KerberosTime  _validStart;
+       private KerberosTime  _validEnd;
+       private KerberosTime  _passwordEnd;
+       private int           _maxLife;
+       private int           _maxRenew;
+       private int           _kdcFlags;
+       private EncryptionKey _key;
+       
+       private String _realmName;
+       
+       PasswordStoreEntry(String commonName, KerberosPrincipal principal,
+                       int keyVersionNumber, KerberosTime validStart, 
KerberosTime validEnd,
+                       KerberosTime passwordEnd, int maxLife, int maxRenew, 
int kdcFlags,
+                       int keyType, byte[] key, String realmName) {
+               
+               _commonName       = commonName;
+               _principal        = principal;
+               _validStart       = validStart;
+               _validEnd         = validEnd;
+               _passwordEnd      = passwordEnd;
+               _maxLife          = maxLife;
+               _maxRenew         = maxRenew;
+               _kdcFlags         = kdcFlags;
+               _realmName        = realmName;
+               
+               _key = new 
EncryptionKey(EncryptionType.getTypeByOrdinal(keyType), key, keyVersionNumber);
+       }
+       
+       public String getCommonName() {
+               return _commonName;
+       }
+       public EncryptionKey getEncryptionKey() {
+               return _key;
+       }
+       public int getKDCFlags() {
+               return _kdcFlags;
+       }
+       public int getMaxLife() {
+               return _maxLife;
+       }
+       public int getMaxRenew() {
+               return _maxRenew;
+       }
+       public KerberosTime getPasswordEnd() {
+               return _passwordEnd;
+       }
+       public KerberosPrincipal getPrincipal() {
+               return _principal;
+       }
+       public String getRealmName() {
+               return _realmName;
+       }
+       public KerberosTime getValidEnd() {
+               return _validEnd;
+       }
+       public KerberosTime getValidStart() {
+               return _validStart;
+       }
+}
+

Added: 
incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/PasswordStoreEntryModifier.java
Url: 
http://svn.apache.org/viewcvs/incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/PasswordStoreEntryModifier.java?view=auto&rev=123624
==============================================================================
--- (empty file)
+++ 
incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store/PasswordStoreEntryModifier.java
 Wed Dec 29 03:13:03 2004
@@ -0,0 +1,86 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.kerberos.changepw.store;
+
+import org.apache.kerberos.messages.value.*;
+
+import javax.security.auth.kerberos.*;
+
+public class PasswordStoreEntryModifier {
+       
+       // 'Principal'
+       private String            _commonName;
+       private KerberosPrincipal _principal;
+       
+       // 'KDCEntry'
+       private int _keyVersionNumber; // must
+       // may
+       private KerberosTime _validStart;
+       private KerberosTime _validEnd;
+       private KerberosTime _passwordEnd;
+       private int          _maxLife;
+       private int          _maxRenew;
+       private int          _kdcFlags;
+       private int          _encryptionType;
+       private byte[]       _key;
+       
+       private String _realmName;
+       
+       public PasswordStoreEntry getEntry() {
+               return new PasswordStoreEntry(_commonName, _principal, 
_keyVersionNumber,
+                               _validStart, _validEnd, _passwordEnd, _maxLife, 
_maxRenew,
+                               _kdcFlags, _encryptionType, _key, _realmName);
+       }
+
+       public void setCommonName(String commonName) {
+               _commonName = commonName;
+       }
+       public void setEncryptionType(int encryptionType) {
+               _encryptionType = encryptionType;
+       }
+       public void setKDCFlags(int kdcFlags) {
+               _kdcFlags = kdcFlags;
+       }
+       public void setKey(byte[] key) {
+               _key = key;
+       }
+       public void setKeyVersionNumber(int keyVersionNumber) {
+               _keyVersionNumber = keyVersionNumber;
+       }
+       public void setMaxLife(int maxLife) {
+               _maxLife = maxLife;
+       }
+       public void setMaxRenew(int maxRenew) {
+               _maxRenew = maxRenew;
+       }
+       public void setPasswordEnd(KerberosTime passwordEnd) {
+               _passwordEnd = passwordEnd;
+       }
+       public void setPrincipal(KerberosPrincipal principal) {
+               _principal = principal;
+       }
+       public void setRealmName(String realmName) {
+               _realmName = realmName;
+       }
+       public void setValidEnd(KerberosTime validEnd) {
+               _validEnd = validEnd;
+       }
+       public void setValidStart(KerberosTime validStart) {
+               _validStart = validStart;
+       }
+}
+

Reply via email to