/** 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 <string.h>
#include "libadminutil/admutil.h"
#include "libadminutil/distadm.h"
#include "libadmsslutil/psetcssl.h"
#include "libadmsslutil/srvutilssl.h"


PR_IMPLEMENT(AttrNameList)
getServerDNListSSL(AdmldapInfo info)
{
  char        *domainDN = NULL, *isie = NULL, *sie = NULL;
  char        *ptr = NULL, *adminName = NULL;
  char        *host = NULL;
  char        *siepwd = NULL;
  PsetHndl    domainPset;
  int         errorCode;
  AttrNameList  nl;

  isie = admldapGetISIEDN(info);
  if (!isie) goto err;
  /*
   * ISIE sample:
   * isie: cn=<NAME> Administration Server, cn=Server Group, cn=myhost.example.com, ou=example.com, o=NetscapeRoot
   */

  ptr=strchr(isie, ',');
  if (!ptr) goto err;

  *ptr = '\0'; /* to cut out "<NAME> Administration Server" later */

  sie = admldapGetSIEDN(info);

  ptr++;

  while (*ptr == ' ' &&  *ptr != '\0') ptr++;

  if (*ptr == '\0') goto err;

  domainDN = PL_strdup(ptr);
  if (!domainDN) goto err;

  adminName = strchr(isie, '=');
  if (!adminName) goto err;
  adminName++;

  /* Use domainDN to create a pset */
  host = admldapGetHost(info);
  siepwd = admldapGetSIEPWD(info);
  domainPset = psetRealCreateSSL(info, host,
                                 admldapGetPort(info),
                                 admldapGetSecurity(info),
                                 domainDN,
                                 sie,
                                 siepwd,
                                 NULL,
                                 &errorCode);

  PR_Free(host);
  host = NULL;
  if (siepwd) {
    memset(siepwd, '\0', strlen(siepwd));
    PR_Free(siepwd);
    siepwd = NULL;
  }
  if (!domainPset) goto err;

  nl = retrieveSIEs(domainPset, domainDN, adminName);

  psetDelete(domainPset);
  if (domainDN) PR_Free(domainDN);
  if (sie) PR_Free(sie);
  if (isie) PR_Free(isie);
  return nl;

err:
  if (isie) PR_Free(isie);
  if (sie) PR_Free(sie);
  if (domainDN) PR_Free(domainDN);
  return NULL;
}
  
PR_IMPLEMENT(AttributeList)
getInstalledServerDNListSSL(AdmldapInfo info)
{
  char          *domainDN, *isie = NULL;
  char          *host = NULL;
  char          *siedn = NULL;
  char          *siepwd = NULL;
  PsetHndl      domainPset;
  int           errorCode;
  AttributeList resultList;

  isie = admldapGetISIEDN(info);
  if (!isie) goto err;

  domainDN=strchr(isie, ',');
  if (!domainDN) goto err;

  domainDN++;

  while (*domainDN == ' ' &&  *domainDN != '\0') domainDN++;

  if (*domainDN == '\0') goto err;

  /* Use domainDN to create a pset */
  host = admldapGetHost(info);
  siedn = admldapGetSIEDN(info);
  siepwd = admldapGetSIEPWD(info);
  domainPset = psetRealCreateSSL(info, host,
                                 admldapGetPort(info),
                                 admldapGetSecurity(info),
                                 domainDN,
                                 siedn,
                                 siepwd,
                                 NULL,
                                 &errorCode);
  PR_Free(host);
  host = NULL;
  PR_Free(siedn);
  siedn = NULL;
  if (siepwd) {
    memset(siepwd, '\0', strlen(siepwd));
    PR_Free(siepwd);
    siepwd = NULL;
  }
  if (!domainPset) goto err;
  resultList = retrieveISIEs(domainPset, domainDN);
  psetDelete(domainPset);

  PR_Free(isie);
  return resultList;
err:
  if (isie) PR_Free(isie);
  return NULL;

}

#define IS_A_DELIMITER(x) ((x == ',') || (x == ' ') || (x == '+') || (x == '\0'))

PR_IMPLEMENT(char *)
findSIEDNByIDSSL(AdmldapInfo info, const char *serverID)
{
  char *retval = NULL;
  char *siedn = NULL;
  char *userdn = NULL;
  char *passwd = NULL;
  int rval = 0;

  siedn = admldapGetSIEDN(info);
  ADM_GetUserDNString(&rval, &userdn);
  ADM_GetCurrentPassword(&rval, &passwd);

  /* HACK HACK HACK */
  /* getServerDNListSSL uses the siedn as the binddn - so we temporarily
     replace the siedn with the userdn - fortunately it doesn't use the
     siedn as the SIE DN */
  admldapSetSIEDN(info, userdn);
  admSetCachedSIEPWD(passwd);

  AttrNameList nl = getServerDNListSSL(info);

  /* HACK HACK HACK - reset after getServerDNListSSL */
  admldapSetSIEDN(info, siedn);
  PL_strfree(siedn);

  if (nl) {
    size_t len = strlen(serverID);
    AttrNameList nlptr = nl;
    while ((retval = *nlptr++)) {
      /* nl is a list of DNs like this:
	 cn=slapd-foo, ...
	 cn=slapd-bar,...
	 cn=admin-serv-localhost,
	 ...
	 serverID is the value of the cn - we have to look for the trailing
	 delimiter to distinguish between slapd-foo slapd-foo2
      */
      if ((len <= strlen(retval+3)) &&
	  !PL_strncasecmp(retval+3, serverID, len) &&
	  (IS_A_DELIMITER(retval[3+len]))) {
	retval = PL_strdup(retval);
	break;
      }
    }
    deleteAttrNameList(nl);
  }

  return retval;
}
