xref: /onnv-gate/usr/src/lib/libsldap/common/ns_sasl.c (revision 12823:2541b129e1fc)
12830Sdjl /*
22830Sdjl  * CDDL HEADER START
32830Sdjl  *
42830Sdjl  * The contents of this file are subject to the terms of the
52830Sdjl  * Common Development and Distribution License (the "License").
62830Sdjl  * You may not use this file except in compliance with the License.
72830Sdjl  *
82830Sdjl  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92830Sdjl  * or http://www.opensolaris.org/os/licensing.
102830Sdjl  * See the License for the specific language governing permissions
112830Sdjl  * and limitations under the License.
122830Sdjl  *
132830Sdjl  * When distributing Covered Code, include this CDDL HEADER in each
142830Sdjl  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152830Sdjl  * If applicable, add the following below this CDDL HEADER, with the
162830Sdjl  * fields enclosed by brackets "[]" replaced with your own identifying
172830Sdjl  * information: Portions Copyright [yyyy] [name of copyright owner]
182830Sdjl  *
192830Sdjl  * CDDL HEADER END
202830Sdjl  */
21*12823SJulian.Pullen@Sun.COM 
222830Sdjl /*
23*12823SJulian.Pullen@Sun.COM  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
242830Sdjl  */
252830Sdjl 
262830Sdjl #include <stdio.h>
272830Sdjl #include <stdlib.h>
282830Sdjl #include <strings.h>
292830Sdjl #include <sys/types.h>
302830Sdjl #include <sys/stat.h>
312830Sdjl #include <unistd.h>
322830Sdjl #include <thread.h>
332830Sdjl #include <synch.h>
342830Sdjl #include <sasl/sasl.h>
352830Sdjl #include <sys/socket.h>
362830Sdjl #include <netdb.h>
372830Sdjl #include <netinet/in.h>
382830Sdjl #include <arpa/inet.h>
392830Sdjl #include <syslog.h>
402830Sdjl #include <ctype.h>
412830Sdjl #include <libscf.h>
422830Sdjl #include <libintl.h>
432830Sdjl #include <locale.h>
442830Sdjl #include "ns_sldap.h"
452830Sdjl #include "ns_internal.h"
462830Sdjl 
472830Sdjl static int self_gssapi_only = 0;
482830Sdjl static mutex_t self_gssapi_only_lock = DEFAULTMUTEX;
492830Sdjl 
502830Sdjl #define	DNS_FMRI	"svc:/network/dns/client:default"
512830Sdjl #define	MSGSIZE		256
522830Sdjl 
532830Sdjl #define	NSSWITCH_CONF	"/etc/nsswitch.conf"
542830Sdjl 
552830Sdjl /*
562830Sdjl  * Error Handling
572830Sdjl  */
582830Sdjl #define	CLIENT_FPRINTF if (mode_verbose && !mode_quiet) (void) fprintf
592830Sdjl 
602830Sdjl /*
612830Sdjl  * nscd calls this function to set self_gssapi_only flag so libsldap performs
622830Sdjl  * sasl/GSSAPI bind only. Also see comments of __ns_ldap_self_gssapi_config.
632830Sdjl  *
642830Sdjl  * Input: flag 0 use any kind of connection
652830Sdjl  *             1 use self/gssapi connection only
662830Sdjl  */
672830Sdjl void
__ns_ldap_self_gssapi_only_set(int flag)682830Sdjl __ns_ldap_self_gssapi_only_set(int flag) {
692830Sdjl 	(void) mutex_lock(&self_gssapi_only_lock);
702830Sdjl 	self_gssapi_only = flag;
712830Sdjl 	(void) mutex_unlock(&self_gssapi_only_lock);
722830Sdjl }
73*12823SJulian.Pullen@Sun.COM 
742830Sdjl /*
752830Sdjl  * Get the flag value of self_gssapi_only
762830Sdjl  */
772830Sdjl int
__s_api_self_gssapi_only_get(void)782830Sdjl __s_api_self_gssapi_only_get(void) {
792830Sdjl 	int flag;
802830Sdjl 	(void) mutex_lock(&self_gssapi_only_lock);
812830Sdjl 	flag = self_gssapi_only;
822830Sdjl 	(void) mutex_unlock(&self_gssapi_only_lock);
832830Sdjl 	return (flag);
842830Sdjl }
85*12823SJulian.Pullen@Sun.COM 
862830Sdjl /*
872830Sdjl  * nscd calls this function to detect the current native ldap configuration.
882830Sdjl  * The output are
892830Sdjl  * NS_LDAP_SELF_GSSAPI_CONFIG_NONE: No credential level self and
902830Sdjl  *                                  no authentication method sasl/GSSAPI is
912830Sdjl  *                                  configured.
922830Sdjl  * NS_LDAP_SELF_GSSAPI_CONFIG_ONLY: Only credential level self and
932830Sdjl  *                                  authentication method sasl/GSSAPI are
942830Sdjl  *                                  configured.
952830Sdjl  * NS_LDAP_SELF_GSSAPI_CONFIG_MIXED: More than one credential level are
962830Sdjl  *                                   configured, including self.
972830Sdjl  *                                   More than one authentication method
982830Sdjl  *                                   are configured, including sasl/GSSAPI.
992830Sdjl  *
1002830Sdjl  * __s_api_crosscheck makes sure self and sasl/GSSAPI pair up if they do
1012830Sdjl  * get configured.
1022830Sdjl  *
1032830Sdjl  * When nscd detects it's MIXED case, it calls __ns_ldap_self_gssapi_only_set
1042830Sdjl  * to force libsldap to do sasl/GSSAPI bind only for per-user lookup.
1052830Sdjl  *
1062830Sdjl  * Return: NS_LDAP_SUCCESS
1072830Sdjl  *         OTHERWISE - FAILURE
1082830Sdjl  *
1092830Sdjl  * Output: config. See comments above.
1102830Sdjl  *
1112830Sdjl  */
1122830Sdjl int
__ns_ldap_self_gssapi_config(ns_ldap_self_gssapi_config_t * config)1132830Sdjl __ns_ldap_self_gssapi_config(ns_ldap_self_gssapi_config_t *config) {
1142830Sdjl 	int	self = 0, other_level = 0, gssapi = 0, other_method = 0;
1152830Sdjl 	ns_auth_t	**aMethod = NULL, **aNext = NULL;
1162830Sdjl 	int		**cLevel = NULL, **cNext = NULL, rc;
1172830Sdjl 	ns_ldap_error_t	*errp = NULL;
1183015Schinlong 	FILE		*fp;
1192830Sdjl 
1202830Sdjl 	if (config == NULL)
1212830Sdjl 		return (NS_LDAP_INVALID_PARAM);
1222830Sdjl 	else
1232830Sdjl 		*config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
1242830Sdjl 
1253015Schinlong 	/*
1263015Schinlong 	 * If config files don't exist, return NS_LDAP_CONFIG.
1273015Schinlong 	 * It's the same return code __ns_ldap_getParam
1283015Schinlong 	 * returns in the same situation.
1293015Schinlong 	 */
1303015Schinlong 	if ((fp = fopen(NSCONFIGFILE, "rF")) == NULL)
1313015Schinlong 		return (NS_LDAP_CONFIG);
1323015Schinlong 	else
1333015Schinlong 		(void) fclose(fp);
1343015Schinlong 	if ((fp = fopen(NSCREDFILE, "rF")) == NULL)
1353015Schinlong 		return (NS_LDAP_CONFIG);
1363015Schinlong 	else
1373015Schinlong 		(void) fclose(fp);
1383015Schinlong 
1392830Sdjl 	/* Get the credential level list */
1402830Sdjl 	if ((rc = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
1412830Sdjl 		(void ***)&cLevel, &errp)) != NS_LDAP_SUCCESS) {
1422830Sdjl 		if (errp)
1432830Sdjl 			(void) __ns_ldap_freeError(&errp);
1442830Sdjl 		if (cLevel)
1452830Sdjl 			(void) __ns_ldap_freeParam((void ***)&cLevel);
1462830Sdjl 		return (rc);
1472830Sdjl 	}
1482830Sdjl 	if (errp)
1492830Sdjl 		(void) __ns_ldap_freeError(&errp);
1502830Sdjl 	/* Get the authentication method list */
1512830Sdjl 	if ((rc = __ns_ldap_getParam(NS_LDAP_AUTH_P,
1522830Sdjl 		(void ***)&aMethod, &errp)) != NS_LDAP_SUCCESS) {
1532830Sdjl 		if (errp)
1542830Sdjl 			(void) __ns_ldap_freeError(&errp);
1552830Sdjl 		if (cLevel)
1562830Sdjl 			(void) __ns_ldap_freeParam((void ***)&cLevel);
1572830Sdjl 		if (aMethod)
1582830Sdjl 			(void) __ns_ldap_freeParam((void ***)&aMethod);
1592830Sdjl 		return (rc);
1602830Sdjl 	}
1612830Sdjl 	if (errp)
1622830Sdjl 		(void) __ns_ldap_freeError(&errp);
1632830Sdjl 
1642830Sdjl 	if (cLevel == NULL || aMethod == NULL) {
1652830Sdjl 		if (cLevel)
1662830Sdjl 			(void) __ns_ldap_freeParam((void ***)&cLevel);
1672830Sdjl 		if (aMethod)
1682830Sdjl 			(void) __ns_ldap_freeParam((void ***)&aMethod);
1692830Sdjl 		return (NS_LDAP_SUCCESS);
1702830Sdjl 	}
1712830Sdjl 
1722830Sdjl 	for (cNext = cLevel; *cNext != NULL; cNext++) {
1732830Sdjl 		if (**cNext == NS_LDAP_CRED_SELF)
1742830Sdjl 			self++;
1752830Sdjl 		else
1762830Sdjl 			other_level++;
1772830Sdjl 	}
1782830Sdjl 	for (aNext = aMethod; *aNext != NULL; aNext++) {
1792830Sdjl 		if ((*aNext)->saslmech == NS_LDAP_SASL_GSSAPI)
1802830Sdjl 			gssapi++;
1812830Sdjl 		else
1822830Sdjl 			other_method++;
1832830Sdjl 	}
1842830Sdjl 
1852830Sdjl 	if (self > 0 && gssapi > 0) {
1862830Sdjl 		if (other_level == 0 && other_method == 0)
1872830Sdjl 			*config = NS_LDAP_SELF_GSSAPI_CONFIG_ONLY;
1882830Sdjl 		else
1892830Sdjl 			*config = NS_LDAP_SELF_GSSAPI_CONFIG_MIXED;
1902830Sdjl 	}
1912830Sdjl 
1922830Sdjl 	if (cLevel)
1932830Sdjl 		(void) __ns_ldap_freeParam((void ***)&cLevel);
1942830Sdjl 	if (aMethod)
1952830Sdjl 		(void) __ns_ldap_freeParam((void ***)&aMethod);
1962830Sdjl 	return (NS_LDAP_SUCCESS);
1972830Sdjl }
1982830Sdjl 
1992830Sdjl int
__s_api_sasl_bind_callback(LDAP * ld,unsigned flags,void * defaults,void * in)2002830Sdjl __s_api_sasl_bind_callback(
2012830Sdjl 	/* LINTED E_FUNC_ARG_UNUSED */
2022830Sdjl 	LDAP		*ld,
2032830Sdjl 	/* LINTED E_FUNC_ARG_UNUSED */
2042830Sdjl 	unsigned	flags,
2052830Sdjl 	void		*defaults,
2062830Sdjl 	void		*in)
2072830Sdjl {
2082830Sdjl 	char		*ret = NULL;
2092830Sdjl 	sasl_interact_t *interact = in;
2102830Sdjl 	ns_sasl_cb_param_t	*cred = (ns_sasl_cb_param_t *)defaults;
2112830Sdjl 
2122830Sdjl 
2132830Sdjl 	while (interact->id != SASL_CB_LIST_END) {
2142830Sdjl 
2152830Sdjl 		switch (interact->id) {
2162830Sdjl 
2172830Sdjl 		case SASL_CB_GETREALM:
2182830Sdjl 			ret =   cred->realm;
2192830Sdjl 			break;
2202830Sdjl 		case SASL_CB_AUTHNAME:
2212830Sdjl 			ret = cred->authid;
2222830Sdjl 			break;
2232830Sdjl 		case SASL_CB_PASS:
2242830Sdjl 			ret = cred->passwd;
2252830Sdjl 			break;
2262830Sdjl 		case SASL_CB_USER:
2272830Sdjl 			ret = cred->authzid;
2282830Sdjl 			break;
2292830Sdjl 		case SASL_CB_NOECHOPROMPT:
2302830Sdjl 		case SASL_CB_ECHOPROMPT:
2312830Sdjl 		default:
2322830Sdjl 			break;
2332830Sdjl 		}
2342830Sdjl 
2352830Sdjl 		if (ret) {
23612022SMichen.Chang@Sun.COM 			/*
23712022SMichen.Chang@Sun.COM 			 * No need to do strdup(ret), the data is always
23812022SMichen.Chang@Sun.COM 			 * available in 'defaults' and libldap won't
23912022SMichen.Chang@Sun.COM 			 * free it either. strdup(ret) causes memory
24012022SMichen.Chang@Sun.COM 			 * leak.
24112022SMichen.Chang@Sun.COM 			 */
24212022SMichen.Chang@Sun.COM 			interact->result = ret;
2432830Sdjl 			interact->len = strlen(ret);
2442830Sdjl 		} else {
2452830Sdjl 			interact->result = NULL;
2462830Sdjl 			interact->len = 0;
2472830Sdjl 		}
2482830Sdjl 		interact++;
2492830Sdjl 	}
2502830Sdjl 
2512830Sdjl 	return (LDAP_SUCCESS);
2522830Sdjl }
2532830Sdjl 
2542830Sdjl /*
2552830Sdjl  * Find "dbase: service1 [...] services2" in fname and return
2562830Sdjl  * " service1 [...] services2"
2572830Sdjl  * e.g.
2582830Sdjl  * Find "hosts: files dns" and return " files dns"
2592830Sdjl  */
2602830Sdjl static char *
__ns_nsw_getconfig(const char * dbase,const char * fname,int * errp)2612830Sdjl __ns_nsw_getconfig(const char *dbase, const char *fname, int *errp)
2622830Sdjl {
2632830Sdjl 	FILE *fp = NULL;
2642830Sdjl 	char *linep, *retp = NULL;
2652830Sdjl 	char lineq[BUFSIZ], db_colon[BUFSIZ];
2662830Sdjl 
2672830Sdjl 	if ((fp = fopen(fname, "rF")) == NULL) {
2682830Sdjl 		*errp = NS_LDAP_CONFIG;
2692830Sdjl 		return (NULL);
2702830Sdjl 	}
2712830Sdjl 	*errp = NS_LDAP_SUCCESS;
2722830Sdjl 
2732830Sdjl 	while (linep = fgets(lineq, BUFSIZ, fp)) {
2742830Sdjl 		char			*tokenp, *comment;
2752830Sdjl 
2762830Sdjl 		/*
2772830Sdjl 		 * Ignore portion of line following the comment character '#'.
2782830Sdjl 		 */
2792830Sdjl 		if ((comment = strchr(linep, '#')) != NULL) {
2802830Sdjl 			*comment = '\0';
2812830Sdjl 		}
2822830Sdjl 		if ((*linep == '\0') || isspace(*linep)) {
2832830Sdjl 			continue;
2842830Sdjl 		}
2852830Sdjl 		(void) snprintf(db_colon, BUFSIZ, "%s:", dbase);
2862830Sdjl 		if ((tokenp = strstr(linep, db_colon)) == NULL) {
2872830Sdjl 			continue; /* ignore this line */
2882830Sdjl 		} else {
2892830Sdjl 			/* skip "dbase:" */
2902830Sdjl 			retp = strdup(tokenp + strlen(db_colon));
2912830Sdjl 			if (retp == NULL)
2922830Sdjl 				*errp = NS_LDAP_MEMORY;
2932830Sdjl 		}
2942830Sdjl 	}
2952830Sdjl 
2962830Sdjl 	(void) fclose(fp);
2972830Sdjl 	return (retp);
2982830Sdjl }
2992830Sdjl /*
3002830Sdjl  *  Test the configurations of the "hosts" and "ipnodes"
3012830Sdjl  *  dns has to be present and appear before ldap
3022830Sdjl  *  e.g.
3032830Sdjl  *  "dns" , "dns files" "dns ldap files", "files dns" are allowed.
3042830Sdjl  *
3052830Sdjl  *  Kerberos requires dns or it'd fail.
3062830Sdjl  */
3072830Sdjl static int
test_dns_nsswitch(int foreground,const char * fname,ns_ldap_error_t ** errpp)3082830Sdjl test_dns_nsswitch(int foreground,
3092830Sdjl 		const char *fname,
3102830Sdjl 		ns_ldap_error_t **errpp) {
3112830Sdjl 	int	ldap, dns, i, pserr, rc = NS_LDAP_SUCCESS;
3122830Sdjl 	char	*db[3] = {"hosts", "ipnodes", NULL};
3132830Sdjl 	char	buf[MSGSIZE], *conf = NULL, *token = NULL, *last = NULL;
3142830Sdjl 
3152830Sdjl 	for (i = 0; db[i] != NULL; i++) {
3162830Sdjl 		conf = __ns_nsw_getconfig(db[i], fname, &pserr);
3172830Sdjl 
3182830Sdjl 		if (conf == NULL) {
3192830Sdjl 			(void) snprintf(buf, MSGSIZE,
3202830Sdjl 				gettext("Parsing %s to find \"%s:\" "
3212830Sdjl 					"failed. err: %d"),
3222830Sdjl 					fname, db[i], pserr);
3232830Sdjl 			if (foreground) {
3242830Sdjl 				(void) fprintf(stderr, "%s\n", buf);
3252830Sdjl 			} else {
3262830Sdjl 				MKERROR(LOG_ERR, *errpp, NS_LDAP_CONFIG,
3272830Sdjl 					strdup(buf), NS_LDAP_MEMORY);
3282830Sdjl 			}
3292830Sdjl 			return (pserr);
3302830Sdjl 		}
3312830Sdjl 		ldap = dns = 0;
3322830Sdjl 		token = strtok_r(conf, " ", &last);
3332830Sdjl 		while (token != NULL) {
3342830Sdjl 			if (strncmp(token, "dns", 3) == 0) {
3352830Sdjl 				if (ldap) {
3362830Sdjl 					(void) snprintf(buf, MSGSIZE,
3372830Sdjl 						gettext("%s: ldap can't appear "
3382830Sdjl 						"before dns"), db[i]);
3392830Sdjl 					if (foreground) {
3402830Sdjl 						(void) fprintf(stderr,
3412830Sdjl 								"start: %s\n",
3422830Sdjl 								buf);
3432830Sdjl 					} else {
3442830Sdjl 						MKERROR(LOG_ERR, *errpp,
3452830Sdjl 							NS_LDAP_CONFIG,
3462830Sdjl 							strdup(buf),
3472830Sdjl 							NS_LDAP_MEMORY);
3482830Sdjl 					}
3492830Sdjl 					free(conf);
3502830Sdjl 					return (NS_LDAP_CONFIG);
3512830Sdjl 				} else {
3522830Sdjl 					dns++;
3532830Sdjl 				}
3542830Sdjl 			} else if (strncmp(token, "ldap", 4) == 0) {
3552830Sdjl 				ldap++;
3562830Sdjl 			}
3572830Sdjl 			/* next token */
3582830Sdjl 			token = strtok_r(NULL, " ", &last);
3592830Sdjl 		}
3602830Sdjl 		if (conf) {
3612830Sdjl 			free(conf);
3622830Sdjl 			conf = NULL;
3632830Sdjl 		}
3642830Sdjl 		if (!dns) {
3652830Sdjl 			(void) snprintf(buf, MSGSIZE,
3662830Sdjl 				gettext("%s: dns is not defined in "
3672830Sdjl 				"%s"), db[i], fname);
3682830Sdjl 			if (foreground) {
3692830Sdjl 				(void) fprintf(stderr, "start: %s\n", buf);
3702830Sdjl 			} else {
3712830Sdjl 				MKERROR(LOG_ERR, *errpp, NS_LDAP_CONFIG,
3722830Sdjl 					strdup(buf), NS_LDAP_MEMORY);
3732830Sdjl 			}
3742830Sdjl 			rc = NS_LDAP_CONFIG;
3752830Sdjl 			break;
3762830Sdjl 		}
3772830Sdjl 	}
3782830Sdjl 	return (rc);
3792830Sdjl }
3802830Sdjl 
3812830Sdjl static boolean_t
is_service(const char * fmri,const char * state)3822830Sdjl is_service(const char *fmri, const char *state) {
3832830Sdjl 	char		*st;
3842830Sdjl 	boolean_t	result = B_FALSE;
3852830Sdjl 
3862830Sdjl 	if ((st = smf_get_state(fmri)) != NULL) {
3872830Sdjl 		if (strcmp(st, state) == 0)
3882830Sdjl 			result = B_TRUE;
3892830Sdjl 		free(st);
3902830Sdjl 	}
3912830Sdjl 	return (result);
3922830Sdjl }
3932830Sdjl 
3942830Sdjl 
3952830Sdjl /*
3962830Sdjl  * This function checks dns prerequisites for sasl/GSSAPI bind.
3972830Sdjl  * It's called only if config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY ||
3982830Sdjl  *   config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED.
3992830Sdjl  */
4002830Sdjl 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)4012830Sdjl __ns_ldap_check_dns_preq(int foreground,
4022830Sdjl 		int mode_verbose,
4032830Sdjl 		int mode_quiet,
4042830Sdjl 		const char *fname,
4052830Sdjl 		ns_ldap_self_gssapi_config_t config,
4062830Sdjl 		ns_ldap_error_t **errpp) {
4072830Sdjl 
4082830Sdjl 	char	buf[MSGSIZE];
4092830Sdjl 	int	retcode = NS_LDAP_SUCCESS;
4102830Sdjl 	int	loglevel;
4112830Sdjl 
4122830Sdjl 	if (errpp)
4132830Sdjl 		*errpp = NULL;
4142830Sdjl 	else
4152830Sdjl 		return (NS_LDAP_INVALID_PARAM);
4162830Sdjl 
4172830Sdjl 	if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
4182830Sdjl 		/* Shouldn't happen. Check this value just in case  */
4192830Sdjl 		return (NS_LDAP_SUCCESS);
4202830Sdjl 
4212830Sdjl 	if ((retcode = test_dns_nsswitch(foreground, fname, errpp)) !=
4222830Sdjl 							NS_LDAP_SUCCESS)
4232830Sdjl 		return (retcode);
4242830Sdjl 
4252830Sdjl 	if (is_service(DNS_FMRI, SCF_STATE_STRING_ONLINE)) {
4262830Sdjl 		if (foreground) {
4272830Sdjl 			CLIENT_FPRINTF(stdout, "start: %s\n",
4282830Sdjl 					gettext("DNS client is enabled"));
4292830Sdjl 		} else {
4304048Schinlong 			syslog(LOG_INFO, "libsldap: %s",
4312830Sdjl 					gettext("DNS client is enabled"));
4322830Sdjl 		}
4332830Sdjl 		return (NS_LDAP_SUCCESS);
4342830Sdjl 	} else {
4352830Sdjl 		if (config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY) {
4362830Sdjl 			(void) snprintf(buf, MSGSIZE,
4372830Sdjl 				gettext("%s: DNS client is not enabled. "
4382830Sdjl 					"Run \"svcadm enable %s\". %s."),
4392830Sdjl 					"Error", DNS_FMRI, "Abort");
4402830Sdjl 			loglevel = LOG_ERR;
4412830Sdjl 			retcode = NS_LDAP_CONFIG;
4422830Sdjl 		} else if (config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED) {
4432830Sdjl 			(void) snprintf(buf, MSGSIZE,
4442830Sdjl 				gettext("%s: DNS client is not enabled. "
4452830Sdjl 					"Run \"svcadm enable %s\". %s."
4462830Sdjl 					"Fall back to other cred level/bind. "),
4472830Sdjl 					"Warning", DNS_FMRI, "Continue");
4482830Sdjl 			loglevel = LOG_INFO;
4492830Sdjl 			retcode = NS_LDAP_SUCCESS;
4502830Sdjl 		}
4512830Sdjl 
4522830Sdjl 		if (foreground) {
4532830Sdjl 			(void) fprintf(stderr, "start: %s\n", buf);
4542830Sdjl 		} else {
4552830Sdjl 			MKERROR(loglevel, *errpp, retcode, strdup(buf),
4562830Sdjl 				NS_LDAP_MEMORY);
4572830Sdjl 		}
4582830Sdjl 		return (retcode);
4592830Sdjl 	}
4602830Sdjl }
4612830Sdjl 
4622830Sdjl /*
4632830Sdjl  * Check if sasl/GSSAPI works
4642830Sdjl  */
4652830Sdjl 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)4662830Sdjl __ns_ldap_check_gssapi_preq(int foreground,
4672830Sdjl 		int mode_verbose,
4682830Sdjl 		int mode_quiet,
4692830Sdjl 		ns_ldap_self_gssapi_config_t config,
4702830Sdjl 		ns_ldap_error_t **errpp) {
4712830Sdjl 
4722830Sdjl 	int	rc;
4732830Sdjl 	char	*attr[2] = {"dn", NULL}, buf[MSGSIZE];
4742830Sdjl 	ns_cred_t	cred;
4752830Sdjl 	ns_ldap_result_t *result = NULL;
4762830Sdjl 	int	loglevel;
4772830Sdjl 
4782830Sdjl 	if (errpp)
4792830Sdjl 		*errpp = NULL;
4802830Sdjl 	else
4812830Sdjl 		return (NS_LDAP_INVALID_PARAM);
4822830Sdjl 
4832830Sdjl 	if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
4842830Sdjl 		/* Don't need to check */
4852830Sdjl 		return (NS_LDAP_SUCCESS);
4862830Sdjl 
4872830Sdjl 	(void) memset(&cred, 0, sizeof (ns_cred_t));
4882830Sdjl 
4892830Sdjl 	cred.auth.type = NS_LDAP_AUTH_SASL;
4902830Sdjl 	cred.auth.tlstype = NS_LDAP_TLS_NONE;
4912830Sdjl 	cred.auth.saslmech = NS_LDAP_SASL_GSSAPI;
4922830Sdjl 
4932830Sdjl 	rc = __ns_ldap_list(NULL, (const char *)"objectclass=*",
4942830Sdjl 		NULL, (const char **)attr, &cred,
4952830Sdjl 		NS_LDAP_SCOPE_BASE, &result, errpp, NULL, NULL);
4962830Sdjl 	if (result)
4972830Sdjl 		(void) __ns_ldap_freeResult(&result);
4982830Sdjl 
4992830Sdjl 	if (rc == NS_LDAP_SUCCESS) {
5002830Sdjl 		if (foreground) {
5012830Sdjl 			CLIENT_FPRINTF(stdout, "start: %s\n",
5022830Sdjl 					gettext("sasl/GSSAPI bind works"));
5032830Sdjl 		} else {
5044048Schinlong 			syslog(LOG_INFO, "libsldap: %s",
5052830Sdjl 					gettext("sasl/GSSAPI bind works"));
5062830Sdjl 		}
5072830Sdjl 		return (NS_LDAP_SUCCESS);
5082830Sdjl 	} else {
5092830Sdjl 		if (config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY) {
5102830Sdjl 			(void) snprintf(buf, MSGSIZE,
5112830Sdjl 				gettext("%s: sasl/GSSAPI bind is not "
5122830Sdjl 					"working. %s."),
5132830Sdjl 					"Error", "Abort");
5142830Sdjl 			loglevel = LOG_ERR;
5152830Sdjl 		} else if (config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED) {
5162830Sdjl 			(void) snprintf(buf, MSGSIZE,
5172830Sdjl 				gettext("%s: sasl/GSSAPI bind is not "
5182830Sdjl 					"working. Fall back to other cred "
5192830Sdjl 					"level/bind. %s."),
5202830Sdjl 					"Warning", "Continue");
5212830Sdjl 			loglevel = LOG_INFO;
5222830Sdjl 			/* reset return code */
5232830Sdjl 			rc = NS_LDAP_SUCCESS;
5242830Sdjl 		}
5252830Sdjl 
5262830Sdjl 		if (foreground) {
5272830Sdjl 			(void) fprintf(stderr, "start: %s\n", buf);
5282830Sdjl 		} else {
5292830Sdjl 			MKERROR(loglevel, *errpp, rc, strdup(buf),
5302830Sdjl 				NS_LDAP_MEMORY);
5312830Sdjl 		}
5322830Sdjl 		return (rc);
5332830Sdjl 	}
5342830Sdjl }
5352830Sdjl /*
5362830Sdjl  * This is called by ldap_cachemgr to check dns and gssapi prequisites.
5372830Sdjl  */
5382830Sdjl 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)5392830Sdjl __ns_ldap_check_all_preq(int foreground,
5402830Sdjl 		int mode_verbose,
5412830Sdjl 		int mode_quiet,
5422830Sdjl 		ns_ldap_self_gssapi_config_t config,
5432830Sdjl 		ns_ldap_error_t **errpp) {
5442830Sdjl 
5452830Sdjl 	int	rc;
5462830Sdjl 
5472830Sdjl 	if (errpp)
5482830Sdjl 		*errpp = NULL;
5492830Sdjl 	else
5502830Sdjl 		return (NS_LDAP_INVALID_PARAM);
5512830Sdjl 
5522830Sdjl 	if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
5532830Sdjl 		/* Don't need to check */
5542830Sdjl 		return (NS_LDAP_SUCCESS);
5552830Sdjl 
5562830Sdjl 	if ((rc = __ns_ldap_check_dns_preq(foreground,
5572830Sdjl 			mode_verbose, mode_quiet, NSSWITCH_CONF,
5582830Sdjl 			config, errpp)) != NS_LDAP_SUCCESS)
5592830Sdjl 		return (rc);
5602830Sdjl 	if ((rc = __ns_ldap_check_gssapi_preq(foreground,
5612830Sdjl 			mode_verbose, mode_quiet, config, errpp)) !=
5622830Sdjl 			NS_LDAP_SUCCESS)
5632830Sdjl 		return (rc);
5642830Sdjl 
5652830Sdjl 	return (NS_LDAP_SUCCESS);
5662830Sdjl }
567