#========================================================================
# Authenticate a user using a secure TLS connection
#========================================================================
#
# Change Log:
#   09 Aug 05  T L Wolfe
#      - Original code completed
#
#========================================================================
# Copyright (C) 2005, California Institute of Technology, JPL.
#                     U.S. Government Sponsorship acknowledged.
#========================================================================

import ldap, sys

#------------------------------------------------------------------------
# Function: authenticate user
#
#     return -1 if an error occured
#     return  0 if the password does not match or
#                  the user's dn does not exist
#     return  1 if user was authenticated
#
#  param  description
#  -----  ----------------------------------------
#  svr    LDAP server name or IP address
#  dn     user's DN
#  pwd    user's password
#  dbg    debug flag
#------------------------------------------------------------------------

def AuthenticateUser (svr="",dn="",pwd="",dbg=0):

    if (svr == "") or (dn == "") or (pwd == ""):
        return -1,"Bad parameter"

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    if dbg:
        print "\nSetting options..."    
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    try:
        ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
        ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,'/..../cacert.pem')
    except ldap.LDAPError, e:
        return -1,e
    

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    if dbg:
        print "\nCreating LDAP object..."    
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    try:

       l = ldap.initialize("ldap://" + svr)  # NO TRACE
 
#      l = ldap.initialize("ldap://" + svr,
#                          trace_level=3,
#                          trace_file=sys.stderr)

       l.protocol_version = ldap.VERSION3

       l.set_option(ldap.OPT_X_TLS,ldap.OPT_X_TLS_DEMAND)

    except ldap.LDAPError, e:    
        return -1,e

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    if dbg:
        print "\nStarting TLS connection..."    
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    try:
        l.start_tls_s()
    except ldap.LDAPError, e:    
        return -1,e
    
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    if dbg:
        print "\nBinding to server as user..."    
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    try: 
        l.simple_bind_s(dn,pwd)
    except ldap.NO_SUCH_OBJECT, e:
        l.unbind_s()
        return 0,e
    except ldap.INVALID_CREDENTIALS, e:
        l.unbind_s()
        return 0,e
    except ldap.LDAPError, e:
        l.unbind_s()
        return -1,e

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    if dbg:
        print "\nUn-binding from server..."    
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    l.unbind_s()
    return 1,""

#-----------------------------------------------------------------------
# test AuthenticateUser function
#-----------------------------------------------------------------------

#server   = "ldap.jpl.nasa.gov"
server   = "eis-dir-200.jpl.nasa.gov"
username = "yyyyyyyyyy"
userdn   = "uid=" + username + ",ou=personnel,dc=dir,dc=jpl,dc=nasa,dc=gov"
password = "xxxxxxxxxx" 
debug    = 1

if debug:
    print "\n"
    print "--- Runtime Environment -------------------------------------"
    print "server   = " + server
    print "username = " + username
    print "usedn    = " + userdn
    print "password = " + password
    print "-------------------------------------------------------------"
    print "\n"

status,errmsg = AuthenticateUser(server,userdn,password,debug)

if status < 0:
    print "\nERROR"
    print errmsg
elif status == 0:
    print "\nUSER NOT AUTHENTICATED"
else:
    print "\nUSER AUTHENTICATED"