/*******************************************************************************

 * $Novell: GraceLogin.java,v 1.7 2002/07/29 21:17:42 $

 * Copyright (c) 2001 Novell, Inc. All Rights Reserved.

 *

 * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND

 * TREATIES. USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE

 * AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS

 * THIS WORK. PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO

 * DEVELOPER A ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE

 * CODE IN ITS PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS

 * TO MARKET, DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF

 * DEVELOPER'S PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR

 * DEVELOPER'S CUSTOMERS WITH RESPECT TO THIS CODE.

 *

 * $name:         GraceLogin.java

 * $description:  If a password has expired and grace logins are enabled, the

 *                bind operation succeeds but uses one grace login. An

 *                application may want to detect this situation and display

 *                a warning message to the user to change his or her password.

 *

 *                In eDirectory 8.5 an interim solution was provided to detect

 *                expired passwords. When a password is expired, a message is

 *                returned in the bind response of the form:

 *                    "NDS error -223"

 *

 *                It is expected that a control will be added in a future

 *                release to allow detection of expired passwords.

 *

 *                If desired, the application can read the user object to obtain

 *                the total and remaining grace logins.

 ******************************************************************************/

import com.novell.ldap.*;

import java.util.Enumeration;

import java.util.Iterator;

import java.io.UnsupportedEncodingException;



public class GraceLogin

{

    public static void main( String[] args )

    {

        if (args.length != 3) {

            System.err.println(

                "Usage:   java GraceLogin <host Name> <login dn> <password>");

            System.err.println(

                "Example: java GraceLogin Acme.com \"cn=Admin,o=Acme\" secret");

            System.exit(1);

        }



        int rc;

        int ldapVersion   = LDAPConnection.LDAP_V3;

        int ldapPort      = LDAPConnection.DEFAULT_PORT;

        String msg;

        String ldapHost   = args[0];;

        String loginDN    = args[1];

        String password   = args[2];

        LDAPConnection conn = new LDAPConnection();



        LDAPResponseQueue queue = null;

        try {

            // Encode the password to UTF-8

            byte[] pw = null;

            try {

                pw = password.getBytes("UTF8");

            } catch( UnsupportedEncodingException ex) {

                System.out.println("Error encoding password: " + ex.toString());

                System.exit(1);

            }

            // connect to the server

            conn.connect( ldapHost, ldapPort );

            // bind to the server. Asynchronous bind is used to

            // get the response and the message from the response

            queue = conn.bind( ldapVersion,

                             loginDN,

                             pw,

                             (LDAPResponseQueue)null );

            // get the bind response

            LDAPResponse rsp = (LDAPResponse)queue.getResponse();

            // get the return code and the message from the response

            rc = rsp.getResultCode();

            msg = rsp.getErrorMessage();



            // is bind successful ?

            if ( rc == LDAPException.SUCCESS )

                System.out.println("Bind is successful.");

            else {

                System.out.println("Bind failed.");

                throw new LDAPException( msg, rc, (String)null );

            }



            // is grace login used? get the message ID from the message

            // and then compare the message ID with "-223"

            if ( msg != null && msg.length() != 0) {

                // message ID starts with '-'

                String messageID = msg.substring(msg.indexOf((int)'-'));

                int lastIndex = messageID.length()-1;



                // strip off the trailing non numeric character(s)

                while ( true ) {

                    int charAscii = (int)messageID.charAt(lastIndex);

                    if ( charAscii >= 48 && charAscii <= 57 )

                        break;

                    int len = lastIndex;

                    lastIndex = lastIndex - 1;

                    messageID = messageID.substring(0, len);

                }



                if ( messageID.compareTo( "-223" ) == 0 ) {

                    System.out.println(

                        "Password is expired for loginDN: " + loginDN);

                    System.out.println("Grace login used:");

                    getGraceLoginInfo(conn, loginDN);

                }

            }



            // do some LDAP operations here then exit

            conn.disconnect();

        }

        catch( LDAPException e ) {

            System.out.println( "Error: " + e.toString() );

            System.exit(1);

        }

        System.exit(0);

    }



    // getGraceLoginInfo() uses read() to get grace login info. The read()

    // returns the entry specified by dn. The entry only contains the

    // attributes specified by returnAttrs

    public static void getGraceLoginInfo( LDAPConnection conn, String dn )

        throws LDAPException

    {

        String attributeName;

        String returnAttrs[] = { "loginGraceRemaining", "loginGraceLimit" };

        Enumeration allValues;

        LDAPAttribute attribute;

        LDAPAttributeSet attributeSet;



        try {

            // read login object and return grace login attrs

            LDAPEntry graceLogin = conn.read( dn, returnAttrs );



            // printout the grace login attrs and values

            attributeSet = graceLogin.getAttributeSet();

            Iterator allAttributes = attributeSet.iterator();



            while(allAttributes.hasNext()) {

                attribute = (LDAPAttribute)allAttributes.next();

                attributeName = attribute.getName();

                allValues = attribute.getStringValues();

                String attrValue = (String) allValues.nextElement();

                System.out.println("  " + attributeName + ": "+ attrValue);

            }

        }

        catch( LDAPException e ) {

            System.err.println( "getGraceLoginInfo() Failed.");

            System.err.println( "Error: " + e.toString() );

            System.exit(1);

        }

    }

}

