directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From erodrig...@apache.org
Subject svn commit: r123624 - incubator/directory/changepw/trunk/core/src/java/org/apache/kerberos/changepw/store
Date Wed, 29 Dec 2004 11:13:05 GMT
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:directory-dev@incubator.apache.org">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 {@link 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;
+	}
+}
+

Mime
View raw message