root/usr/src/lib/libsldap/common/ns_internal.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
 * Copyright 2020 Joyent, Inc.
 */


#ifndef _NS_INTERNAL_H
#define _NS_INTERNAL_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <thread.h>
#include <lber.h>
#include <ldap.h>
#include "ns_sldap.h"
#include "ns_cache_door.h"

/*
 * INTERNALLY USED CONSTANTS
 */

#define MAXERROR                2000
#define TRUE                    1
#define FALSE                   0
#define NSLDAPDIRECTORY         "/var/ldap"
#define NSCONFIGFILE            "/var/ldap/ldap_client_file"
#define NSCONFIGREFRESH         "/var/ldap/ldap_client_file.refresh"
#define NSCREDFILE              "/var/ldap/ldap_client_cred"
#define NSCREDREFRESH           "/var/ldap/ldap_client_cred.refresh"
#define ROTORSIZE               256
#define MASK                    0377
#define LDAPMAXHARDLOOKUPTIME   256
#define DONOTEDIT               \
        "Do not edit this file manually; your changes will be lost." \
        "Please use ldapclient(8) instead."
#define MAXPORTNUMBER           65535
#define MAXPORTNUMBER_STR       "65535"
#define CREDFILE                0
#define CONFIGFILE              1
#define UIDNUMFILTER            "(&(objectclass=posixAccount)(uidnumber=%s))"
#define UIDNUMFILTER_SSD        "(&(%%s)(uidnumber=%s))"
#define UIDFILTER               "(&(objectclass=posixAccount)(uid=%s))"
#define UIDFILTER_SSD           "(&(%%s)(uid=%s))"
#define UIDDNFILTER             "(objectclass=posixAccount)"

#define HOSTFILTER              "(&(objectclass=ipHost)(cn=%s))"
#define HOSTFILTER_SSD          "(&(%%s)(cn=%s))"

#define SIMPLEPAGECTRLFLAG      1
#define VLVCTRLFLAG             2

#define LISTPAGESIZE            1000
#define ENUMPAGESIZE            100

#define DEFMAX                  8
#define TOKENSEPARATOR          '='
#define QUOTETOK                '"'
#define SPACETOK                ' '
#define COMMATOK                ','
#define COLONTOK                ':'
#define QUESTTOK                '?'
#define SEMITOK                 ';'
#define TABTOK                  '\t'
#define OPARATOK                '('
#define CPARATOK                ')'
#define BSLTOK                  '\\'
#define DOORLINESEP             "\07"
#define DOORLINESEP_CHR         0x7
#define COMMASEP                ", "
#define SPACESEP                " "
#define SEMISEP                 ";"
#define COLONSEP                ":"
#define COLSPSEP                ": "
#define EQUALSEP                "="
#define EQUSPSEP                "= "
#define LAST_VALUE              (int)NS_LDAP_HOST_CERTPATH_P
#define BUFSIZE                 BUFSIZ
#define DEFAULTCONFIGNAME       "__default_config"
#define EXP_DEFAULT_TTL         "43200" /* 12 hours TTL */
#define CRYPTMARK               "{NS1}"
#define DOORBUFFERSIZE          8192

#define LDIF_FMT_STR            "%s: %s"
#define FILE_FMT_STR            "%s= %s"
#define DOOR_FMT_STR            "%s=%s"

#define SESSION_CACHE_INC       8
#define CONID_OFFSET            1024
#define NS_DEFAULT_BIND_TIMEOUT         30 /* timeout value in seconds */
#define NS_DEFAULT_SEARCH_TIMEOUT       30 /* timeout value in seconds */

/* max rdn length in conversion routines used by __ns_ldap_addTypedEntry() */
#define RDNSIZE                 512

/*
 * special service used by ldap_cachemgr to indicate a shadow update
 * is to be done with the credential of the administrator identity
 */
#define NS_ADMIN_SHADOW_UPDATE  "shadow__admin_update"

/* Phase 1 profile information */
#define _PROFILE1_OBJECTCLASS   "SolarisNamingProfile"
#define _PROFILE_CONTAINER      "profile"
#define _PROFILE_FILTER         "(&(|(objectclass=%s)(objectclass=%s))(cn=%s))"

/* Phase 2 profile information */
#define _PROFILE2_OBJECTCLASS           "DUAConfigProfile"

/* Common to all profiles */
#define _P_CN                   "cn"

/* Native LDAP Phase 1 Specific Profile Attributes */
#define _P1_SERVERS                     "SolarisLDAPServers"
#define _P1_SEARCHBASEDN                "SolarisSearchBaseDN"
#define _P1_CACHETTL                    "SolarisCacheTTL"
#define _P1_BINDDN                      "SolarisBindDN"
#define _P1_BINDPASSWORD                "SolarisBindPassword"
#define _P1_AUTHMETHOD                  "SolarisAuthMethod"
#define _P1_TRANSPORTSECURITY           "SolarisTransportSecurity"
#define _P1_CERTIFICATEPATH             "SolarisCertificatePath"
#define _P1_CERTIFICATEPASSWORD         "SolarisCertificatePassword"
#define _P1_DATASEARCHDN                "SolarisDataSearchDN"
#define _P1_SEARCHSCOPE                 "SolarisSearchScope"
#define _P1_SEARCHTIMELIMIT             "SolarisSearchTimeLimit"
#define _P1_PREFERREDSERVER             "SolarisPreferredServer"
#define _P1_PREFERREDSERVERONLY         "SolarisPreferredServerOnly"
#define _P1_SEARCHREFERRAL              "SolarisSearchReferral"
#define _P1_BINDTIMELIMIT               "SolarisBindTimeLimit"

/* Native LDAP Phase 2 Specific Profile Attributes */
#define _P2_PREFERREDSERVER             "preferredServerList"
#define _P2_DEFAULTSERVER               "defaultServerList"
#define _P2_SEARCHBASEDN                "defaultSearchBase"
#define _P2_SEARCHSCOPE                 "defaultSearchScope"
#define _P2_AUTHMETHOD                  "authenticationMethod"
#define _P2_CREDENTIALLEVEL             "credentialLevel"
#define _P2_SERVICESEARCHDESC           "serviceSearchDescriptor"
#define _P2_SEARCHTIMELIMIT             "searchTimeLimit"
#define _P2_BINDTIMELIMIT               "bindTimeLimit"
#define _P2_FOLLOWREFERRALS             "followReferrals"
#define _P2_PROFILETTL                  "profileTTL"
#define _P2_ATTRIBUTEMAP                "attributeMap"
#define _P2_OBJECTCLASSMAP              "objectClassMap"
#define _P2_SERVICECREDLEVEL            "serviceCredentialLevel"
#define _P2_SERVICEAUTHMETHOD           "serviceAuthenticationMethod"

/* Control & SASL information from RootDSE door call */
#define _SASLMECHANISM                  "supportedSASLmechanisms"
#define _SASLMECHANISM_LEN              23
#define _SUPPORTEDCONTROL               "supportedControl"
#define _SUPPORTEDCONTROL_LEN           16

#define NS_HASH_MAX     257
#define NS_HASH_SCHEMA_MAPPING_EXISTED  "=MAPPING EXISTED="
#define NS_HASH_RC_SUCCESS              1
#define NS_HASH_RC_NO_MEMORY            -1
#define NS_HASH_RC_CONFIG_ERROR         -2
#define NS_HASH_RC_EXISTED              -3
#define NS_HASH_RC_SYNTAX_ERROR         -4

/* Password management related error message from iDS ldap server */
#define NS_PWDERR_MAXTRIES              \
        "Exceed password retry limit."
#define NS_PWDERR_EXPIRED               \
        "password expired!"
#define NS_PWDERR_ACCT_INACTIVATED      \
        "Account inactivated. Contact system administrator."
#define NS_PWDERR_CHANGE_NOT_ALLOW      \
        "user is not allowed to change password"
#define NS_PWDERR_INVALID_SYNTAX        \
        "invalid password syntax"
#define NS_PWDERR_TRIVIAL_PASSWD        \
        "Password failed triviality check"
#define NS_PWDERR_IN_HISTORY    \
        "password in history"
#define NS_PWDERR_WITHIN_MIN_AGE        \
        "within password minimum age"

/*
 * INTERNALLY USED MACROS
 */

void    __s_api_debug_pause(int priority, int st, const char *mesg);

#define NULL_OR_STR(str)        (!(str) || *(str) == '\0' ? "<NULL>" : (str))

/*
 * MKERROR: builds the error structure and fills in the status and
 * the message.  The message must be a freeable (non-static) string.
 * If it fails to allocate memory for the error structure,
 * it will return the retErr.
 */
#define MKERROR(priority, err, st, mesg, retErr) \
        if (((err) = calloc(1, sizeof (struct ns_ldap_error))) == NULL) \
                return (retErr); \
        (err)->message = mesg; \
        (err)->status = (st); \
        __s_api_debug_pause(priority, st, (err)->message);

/*
 * MKERROR_PWD_MGMT is almost the same as MKERROR
 * except that it takes two more inputs to fill in the
 * password management information part of the
 * ns_ldap_error structure pointed to by err,
 * and it does not log a syslog message.
 */
#define MKERROR_PWD_MGMT(err, st, mesg, pwd_status, sec_until_exp, retErr) \
        if (((err) = calloc(1, sizeof (struct ns_ldap_error))) == NULL) \
                return (retErr); \
        (err)->message = mesg; \
        (err)->status = (st); \
        (err)->pwd_mgmt.status = (pwd_status); \
        (err)->pwd_mgmt.sec_until_expired = (sec_until_exp);

#ifdef DEBUG
#define NSLDAPTRACE(variable, setequal, message) \
        if (variable > 0 || ((setequal != 0) && (variable == setequal))) { \
                char buf[BUFSIZ]; \
                (void) snprintf(buf, BUFSIZ, message); \
                (void) write(__ldap_debug_file, buf); \
        }
#endif

/*
 * INTERNAL DATA STRUCTURES
 */

/*
 * configuration entry type
 */

typedef enum {
        SERVERCONFIG    = 1,
        CLIENTCONFIG    = 2,
        CREDCONFIG      = 3
} ns_conftype_t;

/*
 * datatype of a config entry
 */

typedef enum {
        NS_UNKNOWN      = 0,
        CHARPTR         = 1,            /* Single character pointer */
        ARRAYCP         = 2,            /* comma sep array of char pointers */
        ARRAYAUTH       = 3,            /* Array of auths */
        TIMET           = 4,            /* time relative value (TTL) */
        INT             = 5,            /* single integer */
        SSDLIST         = 6,            /* service search descriptor */
        ATTRMAP         = 7,            /* attribute mapping */
        OBJMAP          = 8,            /* objectclass mapping */
        SERVLIST        = 9,            /* serverlist (SP sep array) */
        ARRAYCRED       = 10,           /* Array of credentialLevels */
        SAMLIST         = 11,           /* serviceAuthenticationMethod */
        SCLLIST         = 12            /* serviceCredentialLevel */
} ns_datatype_t;

typedef enum {
        NS_SUCCESS,
        NS_NOTFOUND,
        NS_PARSE_ERR
} ns_parse_status;

typedef enum {
        NS_DOOR_FMT     = 1,
        NS_LDIF_FMT     = 2,
        NS_FILE_FMT     = 3
} ns_strfmt_t;

/*
 * This enum reduces the number of version string compares
 * against NS_LDAP_VERSION_1 and NS_LDAP_VERSION_2
 */

typedef enum {
        NS_LDAP_V1      = 1000,
        NS_LDAP_V2      = 2000
} ns_version_t;

/*
 * enum<->string mapping construct
 */

typedef struct ns_enum_map {
        int     value;
        char    *name;
} ns_enum_map;

#define ENUM2INT(x)             ((int)(x))

#define INT2PARAMINDEXENUM(x)   ((ParamIndexType)(x))
#define INT2SEARCHREFENUM(x)    ((SearchRef_t)(x))
#define INT2SCOPEENUM(x)        ((ScopeType_t)(x))
#define INT2AUTHENUM(x)         ((AuthType_t)(x))
#define INT2SECENUM(x)          ((TlsType_t)(x))
#define INT2PREFONLYENUM(x)     ((PrefOnly_t)(x))
#define INT2CREDLEVELENUM(x)    ((CredLevel_t)(x))
#define INT2SHADOWUPDATENUM(x)  ((enableShadowUpdate_t)(x))

#define INT2LDAPRETURN(x)       ((ns_ldap_return_code)(x))
#define INT2CONFIGRETURN(x)     ((ns_ldap_config_return_code)(x))
#define INT2PARTIALRETURN(x)    ((ns_ldap_partial_return_code)(x))

/*
 * This structure maps service name to rdn components
 * for use in __ns_getDNs. It also defines the SSD-to-use
 * service for use in __s_api_get_SSDtoUse_service.
 * The idea of an SSD-to-use service is to reduce the configuration
 * complexity. For a service, which does not have its own entries in
 * the LDAP directory, SSD for it is useless, and should not be set.
 * But since this service must share the container with at least
 * one other service which does have it own entries, the SSD for
 * this other service will be shared by this service.
 * This other service is called the SSD-to-use service.
 *
 */

typedef struct ns_service_map {
        char    *service;
        char    *rdn;
        char    *SSDtoUse_service;
} ns_service_map;

/*
 * This structure contains a single mapping from:
 * service:orig -> list of mapped
 */

typedef enum {
        NS_ATTR_MAP,
        NS_OBJ_MAP
} ns_maptype_t;

typedef struct ns_mapping {
        ns_maptype_t    type;
        char            *service;
        char            *orig;
        char            **map;
} ns_mapping_t;

/*
 * The following is the list of internal libsldap configuration data
 * structures.  The configuration is populated normally once per
 * application.  The assumption is that in applications can be
 * relatively short lived (IE ls via nsswitch) so it is important to
 * keep configuration to a minimum, but keep lookups fast.
 *
 * Assumptions:
 * 1 configuration entry per domain, and almost always 1 domain
 * per app.  Hooks exist for multiple domains per app.
 *
 * Configurations are read in from client file cache or from LDAP.
 * Attribute/objectclass mappings are hashed to improve lookup
 * speed.
 */

/*
 * Hash entry types
 */
typedef enum    _ns_hashtype_t {
        NS_HASH_AMAP    = 1,            /* attr map */
        NS_HASH_RAMAP   = 2,            /* reverse attr map */
        NS_HASH_OMAP    = 3,            /* oc map */
        NS_HASH_ROMAP   = 4,            /* reverse oc map */
        NS_HASH_VOID    = 5
} ns_hashtype_t;

typedef struct ns_hash {
        ns_hashtype_t   h_type;
        ns_mapping_t    *h_map;
        struct ns_hash  *h_next;
        struct ns_hash  *h_llnext;
} ns_hash_t;

/*
 * This structure defines the format of an internal configuration
 * parameter for ns_ldap client.
 */

typedef struct ns_param {
        ns_datatype_t   ns_ptype;
        int             ns_acnt;
        union {
                char    **ppc;
                int     *pi;
                char    *pc;
                int     i;
                time_t  tm;
        } ns_pu;
} ns_param_t;

#define ns_ppc  ns_pu.ppc
#define ns_pi   ns_pu.pi
#define ns_pc   ns_pu.pc
#define ns_i    ns_pu.i
#define ns_tm   ns_pu.tm

/*
 * This structure defines an instance of a configuration structure.
 * paramList contains the current ns_ldap parameter configuration
 * and hashTbl contain the current attribute/objectclass mappings.
 * Parameters are indexed by using the value assigned to the parameter
 * in ParamIndexType.
 */

typedef struct ns_config {
        char                    *domainName;
        ns_version_t            version;
        ns_param_t              paramList[NS_LDAP_MAX_PIT_P];
        ns_hash_t               *hashTbl[NS_HASH_MAX];
        ns_hash_t               *llHead;
        ns_ldap_entry_t         *RootDSE;
        boolean_t               delete;
        mutex_t                 config_mutex;
        int                     nUse;
        ldap_get_chg_cookie_t   config_cookie;
} ns_config_t;

/*
 * This structure defines the mapping of the NSCONFIGFILE file
 * statements into their corresponding SolarisNamingProfile,
 * Posix Mapping LDAP attributes, and to their corresponding
 * ParamIndexType enum mapping.  THe ParamIndexType enum
 * definitions can be found in ns_ldap.h.  This structure also
 * defines the default values that are used when a value either
 * does not exist or is undefined.
 */

typedef struct ns_default_config {
        const char      *name;          /* config file parameter name */
        ParamIndexType  index;          /* config file enum index */
        ns_conftype_t   config_type;    /* CLIENT/SERVER/CREDCONFIG */
        ns_datatype_t   data_type;      /* ppc,pi,pc,int etc... */
        int             single_valued;  /* TRUE OR FALSE */
        ns_version_t    version;        /* Version # for attribute */
        const char      *profile_name;  /* profile schema attribute name */
        ns_param_t      defval;         /* config file parameter default */
        int             (*ns_verify)(ParamIndexType i,
                                struct ns_default_config *def,
                                ns_param_t *param,
                                char *errbuf);
        ns_enum_map     *allowed;       /* allowed values */
} ns_default_config;


/*
 * This typedef enumerates all the supported authentication
 * mechanisms currently supported in this library
 */

typedef enum EnumAuthType {
        NS_LDAP_EA_NONE                         = 0,
        NS_LDAP_EA_SIMPLE                       = 1,
        NS_LDAP_EA_SASL_NONE                    = 2,
        NS_LDAP_EA_SASL_CRAM_MD5                = 3,
        NS_LDAP_EA_SASL_DIGEST_MD5              = 4,
        NS_LDAP_EA_SASL_DIGEST_MD5_INT          = 5,
        NS_LDAP_EA_SASL_DIGEST_MD5_CONF         = 6,
        NS_LDAP_EA_SASL_EXTERNAL                = 7,
        NS_LDAP_EA_SASL_GSSAPI                  = 8,
        NS_LDAP_EA_SASL_SPNEGO                  = 9,    /* unsupported */
        NS_LDAP_EA_TLS_NONE                     = 10,
        NS_LDAP_EA_TLS_SIMPLE                   = 11,
        NS_LDAP_EA_TLS_SASL_NONE                = 12,
        NS_LDAP_EA_TLS_SASL_CRAM_MD5            = 13,
        NS_LDAP_EA_TLS_SASL_DIGEST_MD5          = 14,
        NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT      = 15,
        NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF     = 16,
        NS_LDAP_EA_TLS_SASL_EXTERNAL            = 17,
        NS_LDAP_EA_TLS_SASL_GSSAPI              = 18,   /* unsupported */
        NS_LDAP_EA_TLS_SASL_SPNEGO              = 19    /* unsupported */
} EnumAuthType_t;


/*
 * this enum lists the various states of the search state machine
 */

typedef enum {
        INIT                    = 1,
        EXIT                    = 2,
        NEXT_SEARCH_DESCRIPTOR  = 3,
        GET_SESSION             = 4,
        NEXT_SESSION            = 5,
        RESTART_SESSION         = 6,
        NEXT_SEARCH             = 7,
        NEXT_VLV                = 8,
        NEXT_PAGE               = 9,
        ONE_SEARCH              = 10,
        DO_SEARCH               = 11,
        NEXT_RESULT             = 12,
        MULTI_RESULT            = 13,
        PROCESS_RESULT          = 14,
        END_PROCESS_RESULT      = 15,
        END_RESULT              = 16,
        NEXT_REFERRAL           = 17,
        GET_REFERRAL_SESSION    = 18,
        ERROR                   = 19,
        LDAP_ERROR              = 20,
        GET_ACCT_MGMT_INFO      = 21,
        CLEAR_RESULTS           = 22,
        REINIT                  = 23
} ns_state_t;

/*
 * this enum lists the various states of the write state machine
 */
typedef enum {
        W_INIT                  = 1,
        W_EXIT                  = 2,
        GET_CONNECTION          = 3,
        SELECT_OPERATION_SYNC   = 4,
        SELECT_OPERATION_ASYNC  = 5,
        DO_ADD_SYNC             = 6,
        DO_DELETE_SYNC          = 7,
        DO_MODIFY_SYNC          = 8,
        DO_ADD_ASYNC            = 9,
        DO_DELETE_ASYNC         = 10,
        DO_MODIFY_ASYNC         = 11,
        GET_RESULT_SYNC         = 12,
        GET_RESULT_ASYNC        = 13,
        PARSE_RESULT            = 14,
        GET_REFERRAL_CONNECTION = 15,
        W_LDAP_ERROR            = 16,
        W_ERROR                 = 17
} ns_write_state_t;


typedef int ConnectionID;

/*
 * Server side sort type. Orginally the server side sort
 * was set to "cn uid". This did not work with AD and
 * hence single sort attribute was odopted. We dont
 * know which server side sort will work with the
 * Directory and hence we discover which method works.
 */
typedef enum {
        SSS_UNKNOWN             = 0,
        SSS_SINGLE_ATTR         = 1,
        SSS_CN_UID_ATTRS        = 2
} ns_srvsidesort_t;

/*
 * This structure is used by ns_connect to create and manage
 * one or more ldap connections within the library.
 */
typedef struct connection {
        ConnectionID            connectionId;
        boolean_t               usedBit;        /* true if only used by */
                                                /* one thread and not shared */
                                                /* by other threads */
        pid_t                   pid;            /* process id */
        char                    *serverAddr;
        ns_cred_t               *auth;
        LDAP                    *ld;
        thread_t                threadID;       /* thread ID using it */
        struct ns_ldap_cookie   *cookieInfo;
        char                    **controls;             /* from server_info */
        char                    **saslMechanisms;       /* from server_info */
} Connection;

#define ONE_STEP                        1

/*
 * This structure is for referrals processing.
 * The data are from referral URLs returned by
 * LDAP servers
 */
typedef struct ns_referral_info {
        struct ns_referral_info *next;
        char                    *refHost;
        int                     refScope;
        char                    *refDN;
        char                    *refFilter;
} ns_referral_info_t;

struct ns_ldap_cookie;

/*
 * Batch used by __ns_ldap_list_batch_xxx API
 */
struct ns_ldap_list_batch {
        uint32_t                nactive;
        struct ns_ldap_cookie   *next_cookie;
        struct ns_ldap_cookie   *cookie_list;
};

struct ns_conn_user;
typedef struct ns_conn_user ns_conn_user_t;

/*
 * This structure used internally in searches
 */

typedef struct ns_ldap_cookie {
        /* INPUTS */
                /* server list position */

                /* service search descriptor list & position */
        ns_ldap_search_desc_t  **sdlist;
        ns_ldap_search_desc_t  **sdpos;

                /* search filter callback */
        int                     use_filtercb;
        int     (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
                        char **realfilter, const void *userdata);

                /* user callback */
        int                     use_usercb;
        int     (*callback)(const ns_ldap_entry_t *entry,
                        const void *userdata);
        const void              *userdata;

        int                     followRef;
        int                     use_paging;
        char                    *service;
        char                    *i_filter;
        const char * const      *i_attr;
        const char              *i_sortattr;
        const ns_cred_t         *i_auth;
        int                     i_flags;

        /* OUTPUTS */
        ns_ldap_result_t        *result;
        ns_ldap_entry_t         *nextEntry;
                /* Error data */
        int                     err_rc;
        ns_ldap_error_t         *errorp;

        /* PRIVATE */
        ns_state_t              state;
        ns_state_t              new_state;
        ns_state_t              next_state;

        Connection              *conn;
#define conn_auth_type  conn->auth->auth.type
        ConnectionID            connectionId;

        /* paging VLV/SIMPLEPAGE data */
        int                     listType;
        unsigned long           index;
        LDAPControl             **p_serverctrls;
        ns_srvsidesort_t        sortTypeTry;
        int                     entryCount;

        int                     scope;
        char                    *basedn;
        char                    *filter;
        char                    **attribute;

        /* RESULT PROCESSING */
        int                     msgId;
        LDAPMessage             *resultMsg;

        char                    **dns;
        char                    *currentdn;
        int                     flag;
        struct berval           *ctrlCookie;

        /* REFERRALS PROCESSING */
        /* referralinfo list & position */
        ns_referral_info_t      *reflist;
        ns_referral_info_t      *refpos;
        /* search timeout value */
        struct timeval          search_timeout;
        /* response control to hold account management information */
        LDAPControl             **resultctrl;
        /* Flag to indicate password less account management is required */
        int                     nopasswd_acct_mgmt;
        int                     err_from_result;
        ns_conn_user_t          *conn_user;

        /* BATCH PROCESSING */
        ns_ldap_list_batch_t    *batch;
        boolean_t               no_wait;
        boolean_t               reinit_on_retriable_err;
        int                     retries;
        ns_ldap_result_t        **caller_result;
        ns_ldap_error_t         **caller_errorp;
        int                     *caller_rc;
        struct ns_ldap_cookie   *next_cookie_in_batch;
} ns_ldap_cookie_t;

/*
 * This structure is part of the return value information for
 * __s_api_requestServer.  The routine that requests a new server
 * from the cache manager
 */
typedef struct ns_server_info {
        char    *server;
        char    *serverFQDN;
        char    **controls;
        char    **saslMechanisms;
} ns_server_info_t;

/*
 * sasl callback function parameters
 */
typedef struct ns_sasl_cb_param {
        char    *mech;
        char    *authid;
        char    *authzid;
        char    *passwd;
        char    *realm;
} ns_sasl_cb_param_t;

/* Multiple threads per connection variable */
extern int MTperConn;

/*
 * INTERNAL GLOBAL DEFINITIONS AND FUNCTION DECLARATIONS
 */

#ifdef DEBUG
extern int      __ldap_debug_file;
extern int      __ldap_debug_api;
extern int      __ldap_debug_ldap;
extern int      __ldap_debug_servers;
#endif

/* internal connection APIs */
void DropConnection(ConnectionID, int);
int __s_api_getServers(char *** servers, ns_ldap_error_t ** error);

int __s_get_enum_value(ns_config_t *ptr, char *value, ParamIndexType i);
char *__s_get_auth_name(ns_config_t *ptr, AuthType_t type);
char *__s_get_security_name(ns_config_t *ptr, TlsType_t type);
char *__s_get_scope_name(ns_config_t *ptr, ScopeType_t type);
char *__s_get_pref_name(PrefOnly_t type);
char *__s_get_searchref_name(ns_config_t *ptr, SearchRef_t type);
char *__s_get_shadowupdate_name(enableShadowUpdate_t type);
char *__s_get_hostcertpath(void);
void __s_api_free_sessionPool();
int __s_api_requestServer(const char *request, const char *server,
        ns_server_info_t *ret, ns_ldap_error_t **error,  const char *addrType);


/* ************ internal sldap-api functions *********** */
void    __ns_ldap_freeEntry(ns_ldap_entry_t *ep);
void    __ns_ldap_freeASearchDesc(ns_ldap_search_desc_t *);
void    __s_api_split_key_value(char *buffer, char **name, char **value);
int     __s_api_printResult(ns_ldap_result_t *);
int     __s_api_getSearchScope(int *, ns_ldap_error_t **);
int     __s_api_getDNs(char ***, const char *,
        ns_ldap_error_t **);
int     __s_api_get_search_DNs_v1(char ***, const char *,
        ns_ldap_error_t **);
int     __s_api_getConnection(const char *, const int,
        const ns_cred_t *, int *,
        Connection **, ns_ldap_error_t **, int, int, ns_conn_user_t *);
char    **__s_api_cp2dArray(char **);
void    __s_api_free2dArray(char **);

int     __s_api_isCtrlSupported(Connection *, char *);
ns_config_t *__ns_ldap_make_config(ns_ldap_result_t *result);
ns_auth_t  *__s_api_AuthEnumtoStruct(const EnumAuthType_t i);
boolean_t __s_api_peruser_proc(void);
boolean_t __s_api_nscd_proc(void);
char    *dvalue(char *);
char    *evalue(char *);
ns_ldap_error_t *__s_api_make_error(int, char *);
ns_ldap_error_t *__s_api_copy_error(ns_ldap_error_t *);

/* ************ specific 'Standalone' functions ********** */
ns_ldap_return_code __s_api_ip2hostname(char *ipaddr, char **hostname);
struct hostent *__s_api_hostname2ip(const char *name,
                                    struct hostent *result,
                                    char *buffer,
                                    int buflen,
                                    int *h_errnop);
void    __s_api_setInitMode();
void    __s_api_unsetInitMode();
int     __s_api_isStandalone(void);
int __s_api_isInitializing();
ns_ldap_return_code __s_api_findRootDSE(const char *request,
                                        const char *server,
                                        const char *addrType,
                                        ns_server_info_t *ret,
                                        ns_ldap_error_t **error);
ns_config_t *__s_api_create_config_door_str(char *config,
                                ns_ldap_error_t **errorp);

extern void     get_environment();

/* internal Param APIs */
int             __ns_ldap_setParamValue(ns_config_t *ptr,
                        const ParamIndexType type,
                        const void *data, ns_ldap_error_t **error);
int             __s_api_get_type(const char *value, ParamIndexType *type);
int             __s_api_get_versiontype(ns_config_t *ptr, char *value,
                                        ParamIndexType *type);
int             __s_api_get_profiletype(char *value, ParamIndexType *type);
void            __s_api_init_config(ns_config_t *ptr);
void            __s_api_init_config_global(ns_config_t *ptr);
ns_parse_status __s_api_crosscheck(ns_config_t *domainptr, char *errstr,
                                        int check_dn);
ns_config_t     *__s_api_create_config(void);
ns_config_t     *__s_api_get_default_config(void);
ns_config_t     *__s_api_get_default_config_global(void);
ns_config_t     *__s_api_loadrefresh_config();
ns_config_t     *__s_api_loadrefresh_config_global();
void            __s_api_destroy_config(ns_config_t *ptr);
int             __s_api_get_configtype(ParamIndexType type);
const char      *__s_api_get_configname(ParamIndexType type);
char            *__s_api_strValue(ns_config_t *ptr, ParamIndexType i,
                        ns_strfmt_t fmt);
void            __s_api_release_config(ns_config_t *cfg);

/* internal attribute/objectclass mapping api's */
int              __s_api_add_map2hash(ns_config_t *config,
                                ns_hashtype_t type, ns_mapping_t *map);
void            __s_api_destroy_hash(ns_config_t *config);
int             __s_api_parse_map(char *cp, char **sid,
                                char **origA, char ***mapA);
char            **__ns_ldap_mapAttributeList(const char *service,
                                const char * const *origAttrList);
char            *__ns_ldap_mapAttribute(const char *service,
                                const char *origAttr);

/* internal configuration APIs */
void            __ns_ldap_setServer(int set);
ns_ldap_error_t *__ns_ldap_LoadConfiguration();
ns_ldap_error_t *__ns_ldap_LoadDoorInfo(LineBuf *configinfo, char *domainname,
                                ns_config_t *new, int cred_only);
ns_ldap_error_t *__ns_ldap_DumpConfiguration(char *filename);
ns_ldap_error_t *__ns_ldap_DumpLdif(char *filename);
int             __ns_ldap_cache_ping();
ns_ldap_error_t *__ns_ldap_print_config(int);
void            __ns_ldap_default_config();
int             __ns_ldap_download(const char *, char *, char *,
                                ns_ldap_error_t **);
int __ns_ldap_check_dns_preq(int foreground, int mode_verbose, int mode_quiet,
    const char *fname, ns_ldap_self_gssapi_config_t config,
    ns_ldap_error_t **errpp);

int __ns_ldap_check_gssapi_preq(int foreground, int mode_verbose,
    int mode_quiet, ns_ldap_self_gssapi_config_t config,
    ns_ldap_error_t **errpp);

int __ns_ldap_check_all_preq(int foreground, int mode_verbose, int mode_quiet,
    ns_ldap_self_gssapi_config_t config, ns_ldap_error_t **errpp);

/* internal un-exposed APIs */
ns_cred_t       *__ns_ldap_dupAuth(const ns_cred_t *authp);
boolean_t       __s_api_is_auth_matched(const ns_cred_t *auth1,
                    const ns_cred_t *auth2);
int             __s_api_get_SSD_from_SSDtoUse_service(const char *service,
                        ns_ldap_search_desc_t ***SSDlist,
                        ns_ldap_error_t **errorp);
int             __s_api_prepend_automountmapname(const char *service,
                        ns_ldap_search_desc_t ***SSDlist,
                        ns_ldap_error_t ** errorp);
int             __s_api_prepend_automountmapname_to_dn(const char *service,
                        char **basedn,
                        ns_ldap_error_t ** errorp);
int             __s_api_convert_automountmapname(const char *service,
                        char **dn, ns_ldap_error_t ** errorp);
int             __s_api_replace_mapped_attr_in_dn(
                        const char *orig_attr, const char *mapped_attr,
                        const char *dn, char **new_dn);
int             __s_api_append_default_basedn(
                        const char *dn,
                        char **new_dn,
                        int *allocated,
                        ns_ldap_error_t ** errorp);
int             __s_api_removeServer(const char *server);
void            __s_api_removeBadServers(char **server);
void            __s_api_free_server_info(ns_server_info_t *sinfo);
void            __s_api_freeConnection(Connection *con);

/* internal referrals APIs */
int             __s_api_toFollowReferrals(const int flags,
                        int *toFollow,
                        ns_ldap_error_t **errorp);
int             __s_api_addRefInfo(ns_referral_info_t **head,
                        char *url, char *baseDN, int *scope,
                        char *filter, LDAP *ld);
void            __s_api_deleteRefInfo(ns_referral_info_t *head);

/* callback routine for SSD filters */
int             __s_api_merge_SSD_filter(const ns_ldap_search_desc_t *desc,
                        char **realfilter,
                        const void *userdata);

/* network address verification api */
int             __s_api_isipv4(char *addr);
int             __s_api_isipv6(char *addr);
int             __s_api_ishost(char *addr);

/* password management routine */
ns_ldap_passwd_status_t
                __s_api_set_passwd_status(int errnum, char *errmsg);
int             __s_api_contain_passwd_control_oid(char **oids);

/* password less account management routine */
int             __s_api_contain_account_usable_control_oid(char **oids);

/* RFC 2307 section 5.6. Get a canonical name from entry */
char            *__s_api_get_canonical_name(ns_ldap_entry_t *entry,
                        ns_ldap_attr_t *attrptr, int case_ignore);

/* self/sasl/gssapi functions */
int             __s_api_sasl_bind_callback(
                        LDAP            *ld,
                        unsigned        flags,
                        void            *defaults,
                        void            *in);

int             __s_api_self_gssapi_only_get(void);

int             __print2buf(LineBuf *line, const char *toprint, char *sep);

#ifdef __cplusplus
}
#endif

#endif /* _NS_INTERNAL_H */