/** BEGIN COPYRIGHT BLOCK
 * Copyright (C) 2001 Sun Microsystems, Inc.  Used by permission.
 * Copyright (C) 2005 Red Hat, Inc.
 * All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation version
 * 2.1 of the License.
 *                                                                                  
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *                                                                                  
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * END COPYRIGHT BLOCK **/
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <ldap.h>
#include "libadminutil/distadm.h"
#include "libadmsslutil/admsslutil.h"
#include "libadminutil/admutil-int.h"

#ifdef XP_WIN32
#define strcasecmp stricmp
#define strncasecmp _strnicmp
#endif


static AdmldapInfo
admldapCGIbuild(AdmldapInfo ldapInfo, int* error_code)
{
  char           *localAdmin = 0;
  char           *username = 0;
  char           *binddn = 0;
  char           *bindpw = 0;
  char           *host = 0;
  LDAP           *ld;
  int            rv, err;
  int            ldapError;

  if (!ldapInfo) {
    *error_code = ADMUTIL_ENV_ERR;
    return NULL;
  }

  /* Get UserDN and User Password  */
  rv = ADM_GetUserDNString(&err, &binddn);
  if (rv < 0 || !binddn || !*binddn) {
    rv = ADM_GetCurrentUsername(&err, &username);
    if (rv < 0 || !username || !*username) {
      *error_code = ADMUTIL_ENV_ERR;
      destroyAdmldap(ldapInfo);
      return NULL;
    }
    else {
      /* No DN, maybe it is local super */
      localAdmin = admGetLocalAdmin(NULL, &rv);
      if (localAdmin) {
        if (strcmp(username, localAdmin)) {
          *error_code = ADMUTIL_ENV_ERR;
          destroyAdmldap(ldapInfo);
          PL_strfree(localAdmin);
          return NULL;
        }
        else {
          binddn = admldapGetSIEDN(ldapInfo);
          bindpw = admldapGetSIEPWD(ldapInfo);
        }
        PL_strfree(localAdmin);
        localAdmin = NULL;
      }
      else {
        *error_code = ADMUTIL_ENV_ERR;
        destroyAdmldap(ldapInfo);
        return NULL;
      }
    }
  }
  else {
    rv = ADM_GetCurrentPassword(&err, &bindpw);
  }

  /* Set up LDAP */
  
  *error_code = ADMUTIL_OP_OK;

  host = admldapGetHost(ldapInfo);
  if (admldapGetSecurity(ldapInfo))
    ld = admutil_ldap_init(ldapInfo, NULL, host, admldapGetPort(ldapInfo), 1, 0, NULL);
  else
    ld = admutil_ldap_init(ldapInfo, NULL, host, admldapGetPort(ldapInfo), 1, 0, NULL);
  PL_strfree(host);
  host = NULL;

  if (!ld) {
    *error_code = ADMUTIL_LDAP_ERR;
    destroyAdmldap(ldapInfo);
    PL_strfree(binddn);
    if (bindpw) {
      memset(bindpw, 0, strlen(bindpw));
      PL_strfree(bindpw);
    }
    return NULL;
  }

  ldapError = admutil_ldap_bind(ld, binddn, bindpw, LDAP_SASL_SIMPLE, NULL, NULL, NULL, NULL);
  PL_strfree(binddn);
  if (bindpw) {
    memset(bindpw, 0, strlen(bindpw));
    PL_strfree(bindpw);
    bindpw = NULL;
  }

  /* authenticate to LDAP server*/
  if (ldapError  != LDAP_SUCCESS) {
#ifdef LDAP_DEBUG
    fprintf(stderr, "ldap_simple_bind_s: [%s] error %d:%s\n", binddn, ldapError, ldap_err2string(ldapError));
#endif
    switch (ldapError) {
    case LDAP_INAPPROPRIATE_AUTH:
    case LDAP_INVALID_CREDENTIALS:
    case LDAP_INSUFFICIENT_ACCESS:
      /* authenticate failed: Should not continue */
      ldap_unbind_ext(ld, NULL, NULL);
      *error_code = ADMUTIL_LDAP_ERR;
      destroyAdmldap(ldapInfo);
      return NULL;
    case LDAP_NO_SUCH_OBJECT:
    case LDAP_ALIAS_PROBLEM:
    case LDAP_INVALID_DN_SYNTAX:
      /* Not a good user DN */
      ldap_unbind_ext(ld, NULL, NULL);
      *error_code = ADMUTIL_LDAP_ERR;
      destroyAdmldap(ldapInfo);
      return NULL;
      break;
    default:
      ldap_unbind_ext(ld, NULL, NULL);
      *error_code = ADMUTIL_LDAP_ERR;
      destroyAdmldap(ldapInfo);
      return NULL;
    }
  }

  admldapSetLDAPHndl(ldapInfo, ld);
  return ldapInfo;
}

PR_IMPLEMENT(int)
admldapSetAdmGrpUserDirectoryCGI(AdmldapInfo ldapInfo,
								 char* directoryURL,
                                 char* bindDN, 
                                 char* bindPassword,
                                 char* directoryInfoRef, 
                                 int* error_code)
{
  int            errorCode, status;

  if ((ldapInfo = admldapCGIbuild(ldapInfo, &errorCode)) == NULL) {
    *error_code = UG_OP_FAIL;
    return 0;
  }
  
  status = admldapSetAdmGrpUserDirectory(ldapInfo,
                                         directoryURL,
                                         bindDN,
                                         bindPassword,
                                         directoryInfoRef,
                                         error_code);

  return status;
}

PR_IMPLEMENT(int)
admldapSetDomainUserDirectoryCGI(AdmldapInfo ldapInfo,
								 char* directoryURL,
                                 char* bindDN, 
                                 char* bindPassword,
                                 char* directoryInfoRef, 
                                 int* error_code)
{
  int            errorCode, status;

  if ((ldapInfo = admldapCGIbuild(ldapInfo, &errorCode)) == NULL) {
    *error_code = UG_OP_FAIL;
    return 0;
  }
  
  status = admldapSetDomainUserDirectory(ldapInfo,
                                         directoryURL,
                                         bindDN,
                                         bindPassword,
                                         directoryInfoRef,
                                         error_code);

  return status;
}

/*
  emacs settings
  Local Variables:
  c-basic-offset: 2
  End:
*/
