2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <strings.h>
2N/A#include <sys/types.h>
2N/A#include <sys/stat.h>
2N/A#include <unistd.h>
2N/A#include <thread.h>
2N/A#include <synch.h>
2N/A#include <sasl/sasl.h>
2N/A#include <sys/socket.h>
2N/A#include <netdb.h>
2N/A#include <netinet/in.h>
2N/A#include <arpa/inet.h>
2N/A#include <syslog.h>
2N/A#include <ctype.h>
2N/A#include <libscf.h>
2N/A#include <libintl.h>
2N/A#include <locale.h>
2N/A#include "ns_sldap.h"
2N/A#include "ns_internal.h"
2N/A
2N/Astatic int self_gssapi_only = 0;
2N/Astatic mutex_t self_gssapi_only_lock = DEFAULTMUTEX;
2N/A
2N/A#define DNS_FMRI "svc:/network/dns/client:default"
2N/A#define MSGSIZE 256
2N/A
2N/A#define NSSWITCH_CONF "/etc/nsswitch.conf"
2N/A
2N/A/*
2N/A * Error Handling
2N/A */
2N/A#define CLIENT_FPRINTF if (mode_verbose && !mode_quiet) (void) fprintf
2N/A
2N/A
2N/A/*
2N/A * One time initialization
2N/A */
2N/Aint sasl_gssapi_inited = 0;
2N/Astatic mutex_t sasl_gssapi_lock = DEFAULTMUTEX;
2N/A
2N/A
2N/A/*
2N/A * This function is called before calling the LDAP SASL bind to control
2N/A * the SASL crypto options. This is to stop crypto calling naming services
2N/A * and causing a recursive hang in nscd.
2N/A *
2N/A * These are workarounds as crypto modules should be allowed to call naming
2N/A * services.
2N/A *
2N/A * This routine defines the following environment variables:
2N/A *
2N/A * Defining SOFTTOKEN_DIR=/dev/null stops the crypto module pkcs11_softtoken
2N/A * calling naming services.
2N/A *
2N/A * Defining KMSTOKEN_DIR=/dev/null stops the crypto module pkcs11_kms calling
2N/A * naming services.
2N/A *
2N/A * Defining PKCS11_TPM_DIR=/dev/null stops the crypto module pkcs11_tpm calling
2N/A * naming services. Crypto module pkcs11_tpm also calls library libtspi.so.1.
2N/A *
2N/A * Defining TSS_USER_PS_FILE=/dev/null stops the library libtspi.so.1 from
2N/A * calling naming services.
2N/A */
2N/Aint
2N/A__s_api_sasl_gssapi_init(void)
2N/A{
2N/A int rc = NS_LDAP_SUCCESS;
2N/A
2N/A (void) mutex_lock(&sasl_gssapi_lock);
2N/A if (!sasl_gssapi_inited) {
2N/A if (setenv("SOFTTOKEN_DIR", "/dev/null", 1) != 0) {
2N/A syslog(LOG_ERR, "libsldap: %s",
2N/A gettext("Can't setenv SOFTTOKEN_DIR to /dev/null "
2N/A "for self credential mode"));
2N/A rc = NS_LDAP_INTERNAL;
2N/A goto exit;
2N/A }
2N/A if (setenv("KMSTOKEN_DIR", "/dev/null", 1) != 0) {
2N/A syslog(LOG_ERR, "libsldap: %s",
2N/A gettext("Can't setenv KMSTOKEN_DIR to /dev/null "
2N/A "for self credential mode"));
2N/A rc = NS_LDAP_INTERNAL;
2N/A goto exit;
2N/A }
2N/A if (setenv("PKCS11_TPM_DIR", "/dev/null", 1) != 0) {
2N/A syslog(LOG_ERR, "libsldap: %s",
2N/A gettext("Can't setenv "
2N/A "PKCS11_TPM_TOKEN_DIR to /dev/null "
2N/A "for self credential mode"));
2N/A rc = NS_LDAP_INTERNAL;
2N/A goto exit;
2N/A }
2N/A if (setenv("TSS_USER_PS_FILE", "/dev/null", 1) != 0) {
2N/A syslog(LOG_ERR, "libsldap: %s",
2N/A gettext("Can't setenv TSS_USER_PS_FILE to "
2N/A "/dev/null for self credential mode"));
2N/A rc = NS_LDAP_INTERNAL;
2N/A goto exit;
2N/A }
2N/A syslog(LOG_WARNING, "libsldap: %s",
2N/A gettext("setenv SOFTTOKEN_DIR, KMSTOKEN_DIR, "
2N/A "PKCS11_TPM_TOKEN_DIR and TSS_USER_PS_FILE to "
2N/A "/dev/null for self credential mode"));
2N/A sasl_gssapi_inited = 1;
2N/A }
2N/Aexit:
2N/A (void) mutex_unlock(&sasl_gssapi_lock);
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/A/*
2N/A * nscd calls this function to set self_gssapi_only flag so libsldap performs
2N/A * sasl/GSSAPI bind only. Also see comments of __ns_ldap_self_gssapi_config.
2N/A *
2N/A * Input: flag 0 use any kind of connection
2N/A * 1 use self/gssapi connection only
2N/A */
2N/Avoid
2N/A__ns_ldap_self_gssapi_only_set(int flag)
2N/A{
2N/A (void) mutex_lock(&self_gssapi_only_lock);
2N/A self_gssapi_only = flag;
2N/A (void) mutex_unlock(&self_gssapi_only_lock);
2N/A}
2N/A
2N/A/*
2N/A * Get the flag value of self_gssapi_only
2N/A */
2N/Aint
2N/A__s_api_self_gssapi_only_get(void)
2N/A{
2N/A int flag;
2N/A (void) mutex_lock(&self_gssapi_only_lock);
2N/A flag = self_gssapi_only;
2N/A (void) mutex_unlock(&self_gssapi_only_lock);
2N/A return (flag);
2N/A}
2N/A
2N/A/*
2N/A * nscd calls this function to detect the current native ldap configuration.
2N/A * The output are
2N/A * NS_LDAP_SELF_GSSAPI_CONFIG_NONE: No credential level self and
2N/A * no authentication method sasl/GSSAPI is
2N/A * configured.
2N/A * NS_LDAP_SELF_GSSAPI_CONFIG_ONLY: Only credential level self and
2N/A * authentication method sasl/GSSAPI are
2N/A * configured.
2N/A * NS_LDAP_SELF_GSSAPI_CONFIG_MIXED: More than one credential level are
2N/A * configured, including self.
2N/A * More than one authentication method
2N/A * are configured, including sasl/GSSAPI.
2N/A *
2N/A * __s_api_crosscheck makes sure self and sasl/GSSAPI pair up if they do
2N/A * get configured.
2N/A *
2N/A * When nscd detects it's MIXED case, it calls __ns_ldap_self_gssapi_only_set
2N/A * to force libsldap to do sasl/GSSAPI bind only for per-user lookup.
2N/A *
2N/A * Return: NS_LDAP_SUCCESS
2N/A * OTHERWISE - FAILURE
2N/A *
2N/A * Output: config. See comments above.
2N/A *
2N/A */
2N/Aint
2N/A__ns_ldap_self_gssapi_config(ns_ldap_self_gssapi_config_t *config)
2N/A{
2N/A int self = 0, other_level = 0, gssapi = 0, other_method = 0;
2N/A ns_auth_t **aMethod = NULL, **aNext = NULL;
2N/A int **cLevel = NULL, **cNext = NULL, rc;
2N/A ns_ldap_error_t *errp = NULL;
2N/A FILE *fp;
2N/A
2N/A if (config == NULL)
2N/A return (NS_LDAP_INVALID_PARAM);
2N/A else
2N/A *config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
2N/A
2N/A /*
2N/A * If config files don't exist, return NS_LDAP_CONFIG.
2N/A * It's the same return code __ns_ldap_getParam
2N/A * returns in the same situation.
2N/A */
2N/A if ((fp = fopen(NSCONFIGFILE, "rF")) == NULL)
2N/A return (NS_LDAP_CONFIG);
2N/A else
2N/A (void) fclose(fp);
2N/A if ((fp = fopen(NSCREDFILE, "rF")) == NULL)
2N/A return (NS_LDAP_CONFIG);
2N/A else
2N/A (void) fclose(fp);
2N/A
2N/A /* Get the credential level list */
2N/A if ((rc = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
2N/A (void ***)&cLevel, &errp)) != NS_LDAP_SUCCESS) {
2N/A if (errp)
2N/A (void) __ns_ldap_freeError(&errp);
2N/A if (cLevel)
2N/A (void) __ns_ldap_freeParam((void ***)&cLevel);
2N/A return (rc);
2N/A }
2N/A if (errp)
2N/A (void) __ns_ldap_freeError(&errp);
2N/A /* Get the authentication method list */
2N/A if ((rc = __ns_ldap_getParam(NS_LDAP_AUTH_P,
2N/A (void ***)&aMethod, &errp)) != NS_LDAP_SUCCESS) {
2N/A if (errp)
2N/A (void) __ns_ldap_freeError(&errp);
2N/A if (cLevel)
2N/A (void) __ns_ldap_freeParam((void ***)&cLevel);
2N/A if (aMethod)
2N/A (void) __ns_ldap_freeParam((void ***)&aMethod);
2N/A return (rc);
2N/A }
2N/A if (errp)
2N/A (void) __ns_ldap_freeError(&errp);
2N/A
2N/A if (cLevel == NULL || aMethod == NULL) {
2N/A if (cLevel)
2N/A (void) __ns_ldap_freeParam((void ***)&cLevel);
2N/A if (aMethod)
2N/A (void) __ns_ldap_freeParam((void ***)&aMethod);
2N/A return (NS_LDAP_SUCCESS);
2N/A }
2N/A
2N/A for (cNext = cLevel; *cNext != NULL; cNext++) {
2N/A if (**cNext == NS_LDAP_CRED_SELF)
2N/A self++;
2N/A else
2N/A other_level++;
2N/A }
2N/A for (aNext = aMethod; *aNext != NULL; aNext++) {
2N/A if ((*aNext)->saslmech == NS_LDAP_SASL_GSSAPI)
2N/A gssapi++;
2N/A else
2N/A other_method++;
2N/A }
2N/A
2N/A if (self > 0 && gssapi > 0) {
2N/A if (other_level == 0 && other_method == 0)
2N/A *config = NS_LDAP_SELF_GSSAPI_CONFIG_ONLY;
2N/A else
2N/A *config = NS_LDAP_SELF_GSSAPI_CONFIG_MIXED;
2N/A }
2N/A
2N/A if (cLevel)
2N/A (void) __ns_ldap_freeParam((void ***)&cLevel);
2N/A if (aMethod)
2N/A (void) __ns_ldap_freeParam((void ***)&aMethod);
2N/A return (NS_LDAP_SUCCESS);
2N/A}
2N/A
2N/Aint
2N/A__s_api_sasl_bind_callback(
2N/A /* LINTED E_FUNC_ARG_UNUSED */
2N/A LDAP *ld,
2N/A /* LINTED E_FUNC_ARG_UNUSED */
2N/A unsigned flags,
2N/A void *defaults,
2N/A void *in)
2N/A{
2N/A char *ret = NULL;
2N/A sasl_interact_t *interact = in;
2N/A ns_sasl_cb_param_t *cred = (ns_sasl_cb_param_t *)defaults;
2N/A
2N/A
2N/A while (interact->id != SASL_CB_LIST_END) {
2N/A
2N/A switch (interact->id) {
2N/A
2N/A case SASL_CB_GETREALM:
2N/A ret = cred->realm;
2N/A break;
2N/A case SASL_CB_AUTHNAME:
2N/A ret = cred->authid;
2N/A break;
2N/A case SASL_CB_PASS:
2N/A ret = cred->passwd;
2N/A break;
2N/A case SASL_CB_USER:
2N/A ret = cred->authzid;
2N/A break;
2N/A case SASL_CB_NOECHOPROMPT:
2N/A case SASL_CB_ECHOPROMPT:
2N/A default:
2N/A break;
2N/A }
2N/A
2N/A if (ret) {
2N/A /*
2N/A * No need to do strdup(ret), the data is always
2N/A * available in 'defaults' and libldap won't
2N/A * free it either. strdup(ret) causes memory
2N/A * leak.
2N/A */
2N/A interact->result = ret;
2N/A interact->len = strlen(ret);
2N/A } else {
2N/A interact->result = NULL;
2N/A interact->len = 0;
2N/A }
2N/A interact++;
2N/A }
2N/A
2N/A return (LDAP_SUCCESS);
2N/A}
2N/A
2N/A/*
2N/A * Find "dbase: service1 [...] services2" in fname and return
2N/A * " service1 [...] services2"
2N/A * e.g.
2N/A * Find "hosts: files dns" and return " files dns"
2N/A */
2N/Astatic char *
2N/A__ns_nsw_getconfig(const char *dbase, const char *fname, int *errp)
2N/A{
2N/A FILE *fp = NULL;
2N/A char *linep, *retp = NULL;
2N/A char lineq[BUFSIZ], db_colon[BUFSIZ];
2N/A
2N/A if ((fp = fopen(fname, "rF")) == NULL) {
2N/A *errp = NS_LDAP_CONFIG;
2N/A return (NULL);
2N/A }
2N/A *errp = NS_LDAP_SUCCESS;
2N/A
2N/A while (linep = fgets(lineq, BUFSIZ, fp)) {
2N/A char *tokenp, *comment;
2N/A
2N/A /*
2N/A * Ignore portion of line following the comment character '#'.
2N/A */
2N/A if ((comment = strchr(linep, '#')) != NULL) {
2N/A *comment = '\0';
2N/A }
2N/A if ((*linep == '\0') || isspace(*linep)) {
2N/A continue;
2N/A }
2N/A (void) snprintf(db_colon, BUFSIZ, "%s:", dbase);
2N/A if ((tokenp = strstr(linep, db_colon)) == NULL) {
2N/A continue; /* ignore this line */
2N/A } else {
2N/A /* skip "dbase:" */
2N/A retp = strdup(tokenp + strlen(db_colon));
2N/A if (retp == NULL)
2N/A *errp = NS_LDAP_MEMORY;
2N/A }
2N/A }
2N/A
2N/A (void) fclose(fp);
2N/A return (retp);
2N/A}
2N/A/*
2N/A * Test the configurations of the "hosts" and "ipnodes"
2N/A * dns has to be present and appear before ldap
2N/A * e.g.
2N/A * "dns" , "dns files" "dns ldap files", "files dns" are allowed.
2N/A *
2N/A * Kerberos requires dns or it'd fail.
2N/A */
2N/Astatic int
2N/Atest_dns_nsswitch(int foreground,
2N/A const char *fname,
2N/A ns_ldap_error_t **errpp)
2N/A{
2N/A int ldap, dns, i, pserr, rc = NS_LDAP_SUCCESS;
2N/A char *db[3] = {"hosts", "ipnodes", NULL};
2N/A char buf[MSGSIZE], *conf = NULL, *token = NULL, *last = NULL;
2N/A
2N/A for (i = 0; db[i] != NULL; i++) {
2N/A conf = __ns_nsw_getconfig(db[i], fname, &pserr);
2N/A
2N/A if (conf == NULL) {
2N/A (void) snprintf(buf, MSGSIZE,
2N/A gettext("Parsing %s to find \"%s:\" "
2N/A "failed. err: %d"), fname, db[i], pserr);
2N/A if (foreground) {
2N/A (void) fprintf(stderr, "%s\n", buf);
2N/A } else {
2N/A MKERROR(LOG_ERR, *errpp, NS_LDAP_CONFIG,
2N/A strdup(buf), NS_LDAP_MEMORY);
2N/A }
2N/A return (pserr);
2N/A }
2N/A ldap = dns = 0;
2N/A token = strtok_r(conf, " ", &last);
2N/A while (token != NULL) {
2N/A if (strncmp(token, "dns", 3) == 0) {
2N/A if (ldap) {
2N/A (void) snprintf(buf, MSGSIZE,
2N/A gettext("%s: ldap can't appear "
2N/A "before dns"), db[i]);
2N/A if (foreground) {
2N/A (void) fprintf(stderr,
2N/A "start: %s\n", buf);
2N/A } else {
2N/A MKERROR(LOG_ERR, *errpp,
2N/A NS_LDAP_CONFIG, strdup(buf),
2N/A NS_LDAP_MEMORY);
2N/A }
2N/A free(conf);
2N/A return (NS_LDAP_CONFIG);
2N/A } else {
2N/A dns++;
2N/A }
2N/A } else if (strncmp(token, "ldap", 4) == 0) {
2N/A ldap++;
2N/A }
2N/A /* next token */
2N/A token = strtok_r(NULL, " ", &last);
2N/A }
2N/A if (conf) {
2N/A free(conf);
2N/A conf = NULL;
2N/A }
2N/A if (!dns) {
2N/A (void) snprintf(buf, MSGSIZE,
2N/A gettext("%s: dns is not defined in %s"),
2N/A db[i], fname);
2N/A if (foreground) {
2N/A (void) fprintf(stderr, "start: %s\n", buf);
2N/A } else {
2N/A MKERROR(LOG_ERR, *errpp, NS_LDAP_CONFIG,
2N/A strdup(buf), NS_LDAP_MEMORY);
2N/A }
2N/A rc = NS_LDAP_CONFIG;
2N/A break;
2N/A }
2N/A }
2N/A return (rc);
2N/A}
2N/A
2N/Astatic boolean_t
2N/Ais_service(const char *fmri, const char *state)
2N/A{
2N/A char *st;
2N/A boolean_t result = B_FALSE;
2N/A
2N/A if ((st = smf_get_state(fmri)) != NULL) {
2N/A if (strcmp(st, state) == 0)
2N/A result = B_TRUE;
2N/A free(st);
2N/A }
2N/A return (result);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * This function checks dns prerequisites for sasl/GSSAPI bind.
2N/A * It's called only if config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY ||
2N/A * config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED.
2N/A */
2N/Aint
2N/A__ns_ldap_check_dns_preq(int foreground,
2N/A int mode_verbose,
2N/A int mode_quiet,
2N/A const char *fname,
2N/A ns_ldap_self_gssapi_config_t config,
2N/A ns_ldap_error_t **errpp)
2N/A{
2N/A char buf[MSGSIZE];
2N/A int retcode = NS_LDAP_SUCCESS;
2N/A int loglevel;
2N/A
2N/A if (errpp)
2N/A *errpp = NULL;
2N/A else
2N/A return (NS_LDAP_INVALID_PARAM);
2N/A
2N/A if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
2N/A /* Shouldn't happen. Check this value just in case */
2N/A return (NS_LDAP_SUCCESS);
2N/A
2N/A if ((retcode = test_dns_nsswitch(foreground, fname, errpp))
2N/A != NS_LDAP_SUCCESS)
2N/A return (retcode);
2N/A
2N/A if (is_service(DNS_FMRI, SCF_STATE_STRING_ONLINE)) {
2N/A if (foreground) {
2N/A CLIENT_FPRINTF(stdout, "start: %s\n",
2N/A gettext("DNS client is enabled"));
2N/A } else {
2N/A syslog(LOG_INFO, "libsldap: %s",
2N/A gettext("DNS client is enabled"));
2N/A }
2N/A return (NS_LDAP_SUCCESS);
2N/A } else {
2N/A if (config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY) {
2N/A (void) snprintf(buf, MSGSIZE,
2N/A gettext("%s: DNS client is not enabled. "
2N/A "Run \"svcadm enable %s\". %s."),
2N/A "Error", DNS_FMRI, "Abort");
2N/A loglevel = LOG_ERR;
2N/A retcode = NS_LDAP_CONFIG;
2N/A } else if (config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED) {
2N/A (void) snprintf(buf, MSGSIZE,
2N/A gettext("%s: DNS client is not enabled. "
2N/A "Run \"svcadm enable %s\". %s."
2N/A "Fall back to other cred level/bind. "),
2N/A "Warning", DNS_FMRI, "Continue");
2N/A loglevel = LOG_INFO;
2N/A retcode = NS_LDAP_SUCCESS;
2N/A }
2N/A
2N/A if (foreground) {
2N/A (void) fprintf(stderr, "start: %s\n", buf);
2N/A } else {
2N/A MKERROR(loglevel, *errpp, retcode, strdup(buf),
2N/A NS_LDAP_MEMORY);
2N/A }
2N/A return (retcode);
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Check if sasl/GSSAPI works
2N/A */
2N/Aint
2N/A__ns_ldap_check_gssapi_preq(int foreground,
2N/A int mode_verbose,
2N/A int mode_quiet,
2N/A ns_ldap_self_gssapi_config_t config,
2N/A ns_ldap_error_t **errpp)
2N/A{
2N/A int rc;
2N/A char *attr[2] = {"dn", NULL}, buf[MSGSIZE];
2N/A ns_cred_t cred;
2N/A ns_ldap_result_t *result = NULL;
2N/A int loglevel;
2N/A
2N/A if (errpp)
2N/A *errpp = NULL;
2N/A else
2N/A return (NS_LDAP_INVALID_PARAM);
2N/A
2N/A if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
2N/A /* Don't need to check */
2N/A return (NS_LDAP_SUCCESS);
2N/A
2N/A (void) memset(&cred, 0, sizeof (ns_cred_t));
2N/A
2N/A cred.auth.type = NS_LDAP_AUTH_SASL;
2N/A cred.auth.tlstype = NS_LDAP_TLS_NONE;
2N/A cred.auth.saslmech = NS_LDAP_SASL_GSSAPI;
2N/A
2N/A rc = __ns_ldap_list(NULL, (const char *)"objectclass=*",
2N/A NULL, (const char **)attr, &cred,
2N/A NS_LDAP_SCOPE_BASE, &result, errpp, NULL, NULL);
2N/A if (result)
2N/A (void) __ns_ldap_freeResult(&result);
2N/A
2N/A if (rc == NS_LDAP_SUCCESS) {
2N/A if (foreground) {
2N/A CLIENT_FPRINTF(stdout, "start: %s\n",
2N/A gettext("sasl/GSSAPI bind works"));
2N/A } else {
2N/A syslog(LOG_INFO, "libsldap: %s",
2N/A gettext("sasl/GSSAPI bind works"));
2N/A }
2N/A return (NS_LDAP_SUCCESS);
2N/A } else {
2N/A if (config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY) {
2N/A (void) snprintf(buf, MSGSIZE,
2N/A gettext("%s: sasl/GSSAPI bind is not "
2N/A "working. %s."), "Error", "Abort");
2N/A loglevel = LOG_ERR;
2N/A } else if (config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED) {
2N/A (void) snprintf(buf, MSGSIZE,
2N/A gettext("%s: sasl/GSSAPI bind is not "
2N/A "working. Fall back to other cred "
2N/A "level/bind. %s."),
2N/A "Warning", "Continue");
2N/A loglevel = LOG_INFO;
2N/A /* reset return code */
2N/A rc = NS_LDAP_SUCCESS;
2N/A }
2N/A
2N/A if (foreground) {
2N/A (void) fprintf(stderr, "start: %s\n", buf);
2N/A } else {
2N/A MKERROR(loglevel, *errpp, rc, strdup(buf),
2N/A NS_LDAP_MEMORY);
2N/A }
2N/A return (rc);
2N/A }
2N/A}
2N/A/*
2N/A * This is called by ldap_cachemgr to check dns and gssapi prequisites.
2N/A */
2N/Aint
2N/A__ns_ldap_check_all_preq(int foreground,
2N/A int mode_verbose,
2N/A int mode_quiet,
2N/A ns_ldap_self_gssapi_config_t config,
2N/A ns_ldap_error_t **errpp)
2N/A{
2N/A int rc;
2N/A
2N/A if (errpp)
2N/A *errpp = NULL;
2N/A else
2N/A return (NS_LDAP_INVALID_PARAM);
2N/A
2N/A if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
2N/A /* Don't need to check */
2N/A return (NS_LDAP_SUCCESS);
2N/A
2N/A if ((rc = __ns_ldap_check_dns_preq(foreground, mode_verbose,
2N/A mode_quiet, NSSWITCH_CONF, config, errpp)) != NS_LDAP_SUCCESS)
2N/A return (rc);
2N/A if ((rc = __ns_ldap_check_gssapi_preq(foreground, mode_verbose,
2N/A mode_quiet, config, errpp)) != NS_LDAP_SUCCESS)
2N/A return (rc);
2N/A
2N/A return (NS_LDAP_SUCCESS);
2N/A}