/*
 * 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 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */


#ifndef	_NS_SLDAP_H
#define	_NS_SLDAP_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <sys/types.h>
#include <lber.h>
#include <ldap.h>

/*
 * Version
 */
#define	NS_LDAP_VERSION		NS_LDAP_VERSION_2
#define	NS_LDAP_VERSION_1	"1.0"
#define	NS_LDAP_VERSION_2	"2.0"

/*
 * Flags
 */
#define	NS_LDAP_HARD		  0x001
#define	NS_LDAP_ALL_RES		  0x002

/* Search Referral Option */
typedef enum SearchRef {
	NS_LDAP_FOLLOWREF	= 0x004,
	NS_LDAP_NOREF		= 0x008
} SearchRef_t;

typedef enum ScopeType {
	NS_LDAP_SCOPE_BASE	= 0x010,
	NS_LDAP_SCOPE_ONELEVEL	= 0x020,
	NS_LDAP_SCOPE_SUBTREE	= 0x040
} ScopeType_t;

/*
 * BE VERY CAREFUL. DO NOT USE FLAG NS_LDAP_KEEP_CONN UNLESS YOU MUST
 * IN libsldap.so.1 THERE IS NO CONNECTION GARBAGE COLLECTION AND IF
 * THIS FLAG GETS USED THERE MIGHT BE A CONNECTION LEAK. CURRENTLY THIS
 * IS ONLY SUPPORTED FOR LIST AND INTENDED FOR APPLICATIONS LIKE AUTOMOUNTER
 */

#define	NS_LDAP_KEEP_CONN	  0x080
#define	NS_LDAP_NEW_CONN	  0x400
#define	NS_LDAP_NOMAP		  0x800

#define	NS_LDAP_PAGE_CTRL	  0x1000
#define	NS_LDAP_NO_PAGE_CTRL	  0x0000

/*
 * NS_LDAP_NOT_CVT_DN is needed when attribute mapping is used
 * to retrieve the DN in LDAP and DN is not to be converted when
 * being passed back to the application. See __ns_ldap_uid2dn()
 * and __ns_ldap_host2dn() for such usage.
 */
#define	NS_LDAP_NOT_CVT_DN	0x2000

/*
 * Authentication Information
 */
typedef enum CredLevel {
	NS_LDAP_CRED_ANON	= 0,
	NS_LDAP_CRED_PROXY	= 1,
	NS_LDAP_CRED_SELF	= 2
} CredLevel_t;

typedef enum AuthType {
	NS_LDAP_AUTH_NONE	= 0,
	NS_LDAP_AUTH_SIMPLE	= 1,
	NS_LDAP_AUTH_SASL	= 2,
	NS_LDAP_AUTH_TLS	= 3,	/* implied SASL usage */
	NS_LDAP_AUTH_ATLS	= 4	/* implied SASL usage */
} AuthType_t;

typedef enum TlsType {
	NS_LDAP_TLS_NONE	= 0,
	NS_LDAP_TLS_SIMPLE	= 1,
	NS_LDAP_TLS_SASL	= 2
} TlsType_t;

typedef enum SaslMech {
	NS_LDAP_SASL_NONE	= 0,	/* No SASL mechanism */
	NS_LDAP_SASL_CRAM_MD5	= 1,
	NS_LDAP_SASL_DIGEST_MD5	= 2,
	NS_LDAP_SASL_EXTERNAL	= 3,	/* currently not supported */
	NS_LDAP_SASL_GSSAPI	= 4,
	NS_LDAP_SASL_SPNEGO	= 5	/* currently not supported */
} SaslMech_t;

typedef enum SaslOpt {
	NS_LDAP_SASLOPT_NONE	= 0,
	NS_LDAP_SASLOPT_INT	= 1,
	NS_LDAP_SASLOPT_PRIV	= 2
} SaslOpt_t;

typedef enum PrefOnly {
	NS_LDAP_PREF_FALSE	= 0,
	NS_LDAP_PREF_TRUE	= 1
} PrefOnly_t;

typedef struct UnixCred {
	char	*userID;	/* Unix ID number */
	char	*passwd;	/* password */
} UnixCred_t;

typedef struct CertCred {
	char	*path;		/* certificate path */
	char	*passwd;	/* password */
	char	*nickname;	/* nickname */
} CertCred_t;

typedef struct ns_auth {
	AuthType_t	type;
	TlsType_t	tlstype;
	SaslMech_t	saslmech;
	SaslOpt_t	saslopt;
} ns_auth_t;

typedef struct ns_cred {
	ns_auth_t	auth;
	char		*hostcertpath;
	union {
		UnixCred_t	unix_cred;
		CertCred_t	cert_cred;
	} cred;
} ns_cred_t;


typedef struct LineBuf {
	char *str;
	int len;
	int alloc;
} LineBuf;

/*
 * Configuration Information
 */

typedef enum {
	NS_LDAP_FILE_VERSION_P		= 0,
	NS_LDAP_BINDDN_P		= 1,
	NS_LDAP_BINDPASSWD_P		= 2,
	NS_LDAP_SERVERS_P		= 3,
	NS_LDAP_SEARCH_BASEDN_P		= 4,
	NS_LDAP_AUTH_P			= 5,
/*
 * NS_LDAP_TRANSPORT_SEC_P is only left in for backward compatibility
 * with version 1 clients and their configuration files.  The only
 * supported value is NS_LDAP_SEC_NONE.  No application should be
 * using this parameter type (either through getParam or setParam.
 */
	NS_LDAP_TRANSPORT_SEC_P		= 6,
	NS_LDAP_SEARCH_REF_P		= 7,
	NS_LDAP_DOMAIN_P		= 8,
	NS_LDAP_EXP_P			= 9,
	NS_LDAP_CERT_PATH_P		= 10,
	NS_LDAP_CERT_PASS_P		= 11,
	NS_LDAP_SEARCH_DN_P		= 12,
	NS_LDAP_SEARCH_SCOPE_P		= 13,
	NS_LDAP_SEARCH_TIME_P		= 14,
	NS_LDAP_SERVER_PREF_P		= 15,
	NS_LDAP_PREF_ONLY_P		= 16,
	NS_LDAP_CACHETTL_P		= 17,
	NS_LDAP_PROFILE_P		= 18,
	NS_LDAP_CREDENTIAL_LEVEL_P	= 19,
	NS_LDAP_SERVICE_SEARCH_DESC_P	= 20,
	NS_LDAP_BIND_TIME_P		= 21,
	NS_LDAP_ATTRIBUTEMAP_P		= 22,
	NS_LDAP_OBJECTCLASSMAP_P	= 23,
	NS_LDAP_CERT_NICKNAME_P		= 24,
	NS_LDAP_SERVICE_AUTH_METHOD_P	= 25,
	NS_LDAP_SERVICE_CRED_LEVEL_P	= 26,
	NS_LDAP_HOST_CERTPATH_P		= 27,
/*
 * The following entry (max ParamIndexType) is an internal
 * placeholder.  It must be the last (and highest value)
 * entry in this eNum.  Please update accordingly.
 */
	NS_LDAP_MAX_PIT_P		= 28

} ParamIndexType;

/*
 * NONE - No self / SASL/GSSAPI configured
 * ONLY - Only self / SASL/GSSAPI configured
 * MIXED - self / SASL/GSSAPI is mixed with other types of configuration
 */
typedef enum {
	NS_LDAP_SELF_GSSAPI_CONFIG_NONE = 0,
	NS_LDAP_SELF_GSSAPI_CONFIG_ONLY = 1,
	NS_LDAP_SELF_GSSAPI_CONFIG_MIXED = 2
} ns_ldap_self_gssapi_config_t;

/*
 * __ns_ldap_*() return codes
 */
typedef enum {
	NS_LDAP_SUCCESS		= 0, /* success, no info in errorp */
	NS_LDAP_OP_FAILED	= 1, /* failed operation, no info in errorp */
	NS_LDAP_NOTFOUND	= 2, /* entry not found, no info in errorp */
	NS_LDAP_MEMORY		= 3, /* memory failure, no info in errorp */
	NS_LDAP_CONFIG		= 4, /* config problem, detail in errorp */
	NS_LDAP_PARTIAL		= 5, /* partial result, detail in errorp */
	NS_LDAP_INTERNAL	= 7, /* LDAP error, detail in errorp */
	NS_LDAP_INVALID_PARAM	= 8, /* LDAP error, no info in errorp */
	NS_LDAP_SUCCESS_WITH_INFO
				= 9  /* success, with info in errorp */
} ns_ldap_return_code;

/*
 * Detailed error code for NS_LDAP_CONFIG
 */
typedef enum {
	NS_CONFIG_SYNTAX	= 0,	/* syntax error */
	NS_CONFIG_NODEFAULT	= 1,	/* no default value */
	NS_CONFIG_NOTLOADED	= 2,	/* configuration not loaded */
	NS_CONFIG_NOTALLOW	= 3,	/* operation requested not allowed */
	NS_CONFIG_FILE		= 4,	/* configuration file problem */
	NS_CONFIG_CACHEMGR	= 5	/* error with door to ldap_cachemgr */
} ns_ldap_config_return_code;

/*
 * Detailed error code for NS_LDAP_PARTIAL
 */
typedef enum {
	NS_PARTIAL_TIMEOUT	= 0,	/* partial results due to timeout */
	NS_PARTIAL_OTHER	= 1	/* error encountered */
} ns_ldap_partial_return_code;

/*
 * For use by __ns_ldap_addTypedEntry() for publickey serivicetype
 */
typedef enum {
	NS_HOSTCRED_FALSE = 0,
	NS_HOSTCRED_TRUE  = 1
} hostcred_t;

/*
 * Detailed password status
 */
typedef enum {
	NS_PASSWD_GOOD			= 0,	/* password is good */
	NS_PASSWD_ABOUT_TO_EXPIRE	= 1,	/* password is good but */
						/* about to expire */
	NS_PASSWD_CHANGE_NEEDED		= 2,	/* good but need to be */
						/* changed immediately */
	NS_PASSWD_EXPIRED		= 3,	/* password expired */
	NS_PASSWD_RETRY_EXCEEDED	= 4,	/* exceed retry limit; */
						/* account is locked */
	NS_PASSWD_CHANGE_NOT_ALLOWED	= 5,	/* can only be changed */
						/* by the administrator */
	NS_PASSWD_INVALID_SYNTAX	= 6,	/* can not be changed: */
						/* new password has */
						/* invalid syntax -- */
						/* same value as attr */
						/* cn, sn, uid, etc. */
	NS_PASSWD_TOO_SHORT		= 7,	/* can not be changed: */
						/* new password has */
						/* less chars than */
						/* required */
	NS_PASSWD_IN_HISTORY		= 8,	/* can not be changed: */
						/* reuse old password  */
	NS_PASSWD_WITHIN_MIN_AGE	= 9 	/* can not be changed: */
						/* within minimum age  */
} ns_ldap_passwd_status_t;

/*
 * Password management information structure
 *
 * This structure is different from AcctUsableResponse_t structure in
 * that this structure holds result of users account mgmt information when
 * an ldap bind is done with user name and user password.
 */
typedef struct ns_ldap_passwd_mgmt {
	ns_ldap_passwd_status_t
		status;			/* password status */
	int	sec_until_expired;	/* seconds until expired, */
					/* valid if status is */
					/* NS_PASSWD_ABOUT_TO_EXPIRE */
} ns_ldap_passwd_mgmt_t;

/*
 * LDAP V3 control flag for account management - Used for account management
 * when no password is provided
 */
#define	NS_LDAP_ACCOUNT_USABLE_CONTROL	"1.3.6.1.4.1.42.2.27.9.5.8"

/*
 * Structure for holding the response returned by server for
 * NS_LDAP_ACCOUNT_USABLE_CONTROL control when account is not available.
 */
typedef struct AcctUsableMoreInfo {
	int inactive;
	int reset;
	int expired;
	int rem_grace;
	int sec_b4_unlock;
} AcctUsableMoreInfo_t;

/*
 * Structure used to hold the response from the server for
 * NS_LDAP_ACCOUNT_USABLE_CONTROL control. The ASN1 notation is as below:
 *
 * ACCOUNT_USABLE_RESPONSE::= CHOICE {
 * is_available		[0] INTEGER, seconds before expiration
 * is_not_available	[1] More_info
 * }
 *
 * More_info::= SEQUENCE {
 * inactive		[0] BOOLEAN DEFAULT FALSE,
 * reset		[1] BOOLEAN DEFAULT FALSE,
 * expired		[2] BOOLEAN DEFAULT FALSE,
 * remaining_grace	[3] INTEGER OPTIONAL,
 * seconds_before_unlock[4] INTEGER OPTIONAL
 * }
 *
 * This structure is different from ns_ldap_passwd_mgmt_t structure in
 * that this structure holds result of users account mgmt information when
 * pam_ldap doesn't have the users password and proxy agent is used for
 * obtaining the account management information.
 */
typedef struct AcctUsableResponse {
	int choice;
	union {
		int seconds_before_expiry;
		AcctUsableMoreInfo_t more_info;
	} AcctUsableResp;
} AcctUsableResponse_t;

/*
 * Simplified LDAP Naming API result structure
 */
typedef struct ns_ldap_error {
	int	status;				/* LDAP error code */
	char	*message;			/* LDAP error message */
	ns_ldap_passwd_mgmt_t	pwd_mgmt;	/* LDAP password */
						/* management info */
} ns_ldap_error_t;

typedef struct	 ns_ldap_attr {
	char	*attrname;			/* attribute name */
	uint_t	value_count;
	char	**attrvalue;			/* attribute values */
} ns_ldap_attr_t;

typedef struct ns_ldap_entry {
	uint_t		attr_count;		/* number of attributes */
	ns_ldap_attr_t	**attr_pair;		/* attributes pairs */
	struct ns_ldap_entry *next;		/* next entry */
} ns_ldap_entry_t;

typedef struct ns_ldap_result {
	uint_t	entries_count;		/* number of entries */
	ns_ldap_entry_t	*entry;		/* data */
} ns_ldap_result_t;

/*
 * structures for the conversion routines used by typedAddEntry()
 */

typedef struct _ns_netgroups {
	char  *name;
	char  **triplet;
	char  **netgroup;
} _ns_netgroups_t;

typedef struct _ns_netmasks {
	char *netnumber;
	char *netmask;
} _ns_netmasks_t;

typedef struct _ns_bootp {
	char *name;
	char **param;
} _ns_bootp_t;

typedef struct _ns_ethers {
	char *name;
	char *ether;
} _ns_ethers_t;

typedef struct _ns_pubkey {
	char *name;
	hostcred_t hostcred;
	char *pubkey;
	char *privkey;
} _ns_pubkey_t;

typedef struct _ns_alias {
	char *alias;
	char **member;
} _ns_alias_t;

typedef struct _ns_automount {
	char *mapname;
	char *key;
	char *value;
} _ns_automount_t;

/*
 * return values for the callback function in __ns_ldap_list()
 */
#define	NS_LDAP_CB_NEXT	0	/* get the next entry */
#define	NS_LDAP_CB_DONE	1	/* done */

/*
 * Input values for the type specified in __ns_ldap_addTypedEntry()
 * and __ns_ldap_delTypedEntry()
 */

#define	NS_LDAP_TYPE_PASSWD	"passwd"
#define	NS_LDAP_TYPE_GROUP	"group"
#define	NS_LDAP_TYPE_HOSTS	"hosts"
#define	NS_LDAP_TYPE_IPNODES	"ipnodes"
#define	NS_LDAP_TYPE_PROFILE	"prof_attr"
#define	NS_LDAP_TYPE_RPC	"rpc"
#define	NS_LDAP_TYPE_PROTOCOLS	"protocols"
#define	NS_LDAP_TYPE_NETWORKS	"networks"
#define	NS_LDAP_TYPE_NETGROUP	"netgroup"
#define	NS_LDAP_TYPE_ALIASES	"aliases"
#define	NS_LDAP_TYPE_SERVICES	"services"
#define	NS_LDAP_TYPE_ETHERS	"ethers"
#define	NS_LDAP_TYPE_SHADOW	"shadow"
#define	NS_LDAP_TYPE_NETMASKS	"netmasks"
#define	NS_LDAP_TYPE_AUTHATTR	"auth_attr"
#define	NS_LDAP_TYPE_EXECATTR	"exec_attr"
#define	NS_LDAP_TYPE_USERATTR	"user_attr"
#define	NS_LDAP_TYPE_PROJECT	"project"
#define	NS_LDAP_TYPE_PUBLICKEY	"publickey"
#define	NS_LDAP_TYPE_AUUSER	"audit_user"
#define	NS_LDAP_TYPE_BOOTPARAMS "bootparams"
#define	NS_LDAP_TYPE_AUTOMOUNT  "auto_"
#define	NS_LDAP_TYPE_TNRHDB	"tnrhdb"
#define	NS_LDAP_TYPE_TNRHTP	"tnrhtp"

/*
 * service descriptor/attribute mapping structure
 */

typedef struct ns_ldap_search_desc {
	char		*basedn;	/* search base dn */
	ScopeType_t	scope;		/* search scope */
	char		*filter;	/* search filter */
} ns_ldap_search_desc_t;

typedef struct ns_ldap_attribute_map {
	char		*origAttr;	/* original attribute */
	char		**mappedAttr;	/* mapped attribute(s) */
} ns_ldap_attribute_map_t;

typedef struct ns_ldap_objectclass_map {
	char		*origOC;	/* original objectclass */
	char		*mappedOC;	/* mapped objectclass */
} ns_ldap_objectclass_map_t;

/*
 * Simplified LDAP Naming APIs
 */
int __ns_ldap_list(
	const char *service,
	const char *filter,
	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
			char **realfilter, const void *userdata),
	const char * const *attribute,
	const ns_cred_t *cred,
	const int flags,
	ns_ldap_result_t ** result,
	ns_ldap_error_t ** errorp,
	int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
	const void *userdata);

int  __ns_ldap_addAttr(
	const char *service,
	const char *dn,
	const ns_ldap_attr_t * const *attr,
	const ns_cred_t *cred,
	const int flags,
	ns_ldap_error_t **errorp);

int __ns_ldap_delAttr(
	const char *service,
	const char *dn,
	const ns_ldap_attr_t * const *attr,
	const ns_cred_t *cred,
	const int flags,
	ns_ldap_error_t **errorp);

int  __ns_ldap_repAttr(
	const char *service,
	const char *dn,
	const ns_ldap_attr_t * const *attr,
	const ns_cred_t *cred,
	const int flags,
	ns_ldap_error_t **errorp);

int  __ns_ldap_addEntry(
	const char *service,
	const char *dn,
	const ns_ldap_entry_t *entry,
	const ns_cred_t *cred,
	const int flags,
	ns_ldap_error_t **errorp);

int  __ns_ldap_addTypedEntry(
	const char *servicetype,
	const char *basedn,
	const void *data,
	const int  create,
	const ns_cred_t *cred,
	const int flags,
	ns_ldap_error_t **errorp);

int __ns_ldap_delEntry(
	const char *service,
	const char *dn,
	const ns_cred_t *cred,
	const int flags,
	ns_ldap_error_t **errorp);

int __ns_ldap_firstEntry(
	const char *service,
	const char *filter,
	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
			char **realfilter, const void *userdata),
	const char * const *attribute,
	const ns_cred_t *cred,
	const int flags,
	void **cookie,
	ns_ldap_result_t ** result,
	ns_ldap_error_t **errorp,
	const void *userdata);

int  __ns_ldap_nextEntry(
	void *cookie,
	ns_ldap_result_t ** result,
	ns_ldap_error_t **errorp);

int  __ns_ldap_endEntry(
	void **cookie,
	ns_ldap_error_t **errorp);

int __ns_ldap_freeResult(
	ns_ldap_result_t **result);

int __ns_ldap_freeError(
	ns_ldap_error_t **errorp);

int  __ns_ldap_uid2dn(
	const char *uid,
	char **userDN,
	const ns_cred_t *cred,
	ns_ldap_error_t ** errorp);

int  __ns_ldap_host2dn(
	const char *host,
	const char *domain,
	char **hostDN,
	const ns_cred_t *cred,
	ns_ldap_error_t ** errorp);

int  __ns_ldap_dn2domain(
	const char *dn,
	char **domain,
	const ns_cred_t *cred,
	ns_ldap_error_t ** errorp);

int __ns_ldap_auth(
	const ns_cred_t *cred,
	const int flag,
	ns_ldap_error_t **errorp,
	LDAPControl **serverctrls,
	LDAPControl **clientctrls);

int __ns_ldap_freeCred(
	ns_cred_t **credp);

int __ns_ldap_err2str(
	int err,
	char **strmsg);

int __ns_ldap_setParam(
	const ParamIndexType type,
	const void *data,
	ns_ldap_error_t **errorp);

int __ns_ldap_getParam(
	const ParamIndexType type,
	void ***data,
	ns_ldap_error_t **errorp);

int __ns_ldap_freeParam(
	void ***data);

char **__ns_ldap_getAttr(
	const ns_ldap_entry_t *entry,
	const char *attrname);

ns_ldap_attr_t	*__ns_ldap_getAttrStruct(
	const ns_ldap_entry_t *entry,
	const char *attrname);

int __ns_ldap_getServiceAuthMethods(
	const char *service,
	ns_auth_t ***auth,
	ns_ldap_error_t **errorp);

int __ns_ldap_getSearchDescriptors(
	const char *service,
	ns_ldap_search_desc_t ***desc,
	ns_ldap_error_t **errorp);

int __ns_ldap_freeSearchDescriptors(
	ns_ldap_search_desc_t ***desc);

int __ns_ldap_getAttributeMaps(
	const char *service,
	ns_ldap_attribute_map_t ***maps,
	ns_ldap_error_t **errorp);

int __ns_ldap_freeAttributeMaps(
	ns_ldap_attribute_map_t ***maps);

char **__ns_ldap_getMappedAttributes(
	const char *service,
	const char *origAttribute);

char **__ns_ldap_getOrigAttribute(
	const char *service,
	const char *mappedAttribute);

int __ns_ldap_getObjectClassMaps(
	const char *service,
	ns_ldap_objectclass_map_t ***maps,
	ns_ldap_error_t **errorp);

int __ns_ldap_freeObjectClassMaps(
	ns_ldap_objectclass_map_t ***maps);

char **__ns_ldap_getMappedObjectClass(
	const char *service,
	const char *origObjectClass);

char **__ns_ldap_getOrigObjectClass(
	const char *service,
	const char *mappedObjectClass);

int __ns_ldap_getParamType(
	const char *value,
	ParamIndexType *type);

int __ns_ldap_getAcctMgmt(
	const char *user,
	AcctUsableResponse_t *acctResp);
void
__ns_ldap_self_gssapi_only_set(
	int flag);
int
__ns_ldap_self_gssapi_config(
	ns_ldap_self_gssapi_config_t *config);
#ifdef __cplusplus
}
#endif

#endif /* _NS_SLDAP_H */