/*
* 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
* 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
*/
/*
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <thread.h>
#include <synch.h>
#include <netdb.h>
#include <syslog.h>
#include <ctype.h>
#include <libscf.h>
#include <libintl.h>
#include <locale.h>
#include "ns_sldap.h"
#include "ns_internal.h"
static int self_gssapi_only = 0;
/*
* Error Handling
*/
/*
* One time initialization
*/
int sasl_gssapi_inited = 0;
/*
* This function is called before calling the LDAP SASL bind to control
* the SASL crypto options. This is to stop crypto calling naming services
* and causing a recursive hang in nscd.
*
* These are workarounds as crypto modules should be allowed to call naming
* services.
*
* This routine defines the following environment variables:
*
* calling naming services.
*
* naming services.
*
* naming services. Crypto module pkcs11_tpm also calls library libtspi.so.1.
*
* calling naming services.
*/
int
__s_api_sasl_gssapi_init(void)
{
(void) mutex_lock(&sasl_gssapi_lock);
if (!sasl_gssapi_inited) {
"for self credential mode"));
goto exit;
}
"for self credential mode"));
goto exit;
}
gettext("Can't setenv "
"for self credential mode"));
goto exit;
}
gettext("Can't setenv TSS_USER_PS_FILE to "
goto exit;
}
gettext("setenv SOFTTOKEN_DIR, KMSTOKEN_DIR, "
"PKCS11_TPM_TOKEN_DIR and TSS_USER_PS_FILE to "
sasl_gssapi_inited = 1;
}
exit:
(void) mutex_unlock(&sasl_gssapi_lock);
return (rc);
}
/*
* nscd calls this function to set self_gssapi_only flag so libsldap performs
*
* Input: flag 0 use any kind of connection
*/
void
{
(void) mutex_lock(&self_gssapi_only_lock);
(void) mutex_unlock(&self_gssapi_only_lock);
}
/*
* Get the flag value of self_gssapi_only
*/
int
{
int flag;
(void) mutex_lock(&self_gssapi_only_lock);
(void) mutex_unlock(&self_gssapi_only_lock);
return (flag);
}
/*
* nscd calls this function to detect the current native ldap configuration.
* The output are
* NS_LDAP_SELF_GSSAPI_CONFIG_NONE: No credential level self and
* configured.
* NS_LDAP_SELF_GSSAPI_CONFIG_ONLY: Only credential level self and
* configured.
* NS_LDAP_SELF_GSSAPI_CONFIG_MIXED: More than one credential level are
* configured, including self.
* More than one authentication method
*
* get configured.
*
* When nscd detects it's MIXED case, it calls __ns_ldap_self_gssapi_only_set
*
* Return: NS_LDAP_SUCCESS
* OTHERWISE - FAILURE
*
* Output: config. See comments above.
*
*/
int
{
return (NS_LDAP_INVALID_PARAM);
else
/*
* If config files don't exist, return NS_LDAP_CONFIG.
* It's the same return code __ns_ldap_getParam
* returns in the same situation.
*/
return (NS_LDAP_CONFIG);
else
return (NS_LDAP_CONFIG);
else
/* Get the credential level list */
if (errp)
(void) __ns_ldap_freeError(&errp);
if (cLevel)
(void) __ns_ldap_freeParam((void ***)&cLevel);
return (rc);
}
if (errp)
(void) __ns_ldap_freeError(&errp);
/* Get the authentication method list */
if (errp)
(void) __ns_ldap_freeError(&errp);
if (cLevel)
(void) __ns_ldap_freeParam((void ***)&cLevel);
if (aMethod)
(void) __ns_ldap_freeParam((void ***)&aMethod);
return (rc);
}
if (errp)
(void) __ns_ldap_freeError(&errp);
if (cLevel)
(void) __ns_ldap_freeParam((void ***)&cLevel);
if (aMethod)
(void) __ns_ldap_freeParam((void ***)&aMethod);
return (NS_LDAP_SUCCESS);
}
if (**cNext == NS_LDAP_CRED_SELF)
self++;
else
other_level++;
}
gssapi++;
else
other_method++;
}
if (other_level == 0 && other_method == 0)
else
}
if (cLevel)
(void) __ns_ldap_freeParam((void ***)&cLevel);
if (aMethod)
(void) __ns_ldap_freeParam((void ***)&aMethod);
return (NS_LDAP_SUCCESS);
}
int
/* LINTED E_FUNC_ARG_UNUSED */
/* LINTED E_FUNC_ARG_UNUSED */
unsigned flags,
void *defaults,
void *in)
{
case SASL_CB_GETREALM:
break;
case SASL_CB_AUTHNAME:
break;
case SASL_CB_PASS:
break;
case SASL_CB_USER:
break;
case SASL_CB_NOECHOPROMPT:
case SASL_CB_ECHOPROMPT:
default:
break;
}
if (ret) {
/*
* No need to do strdup(ret), the data is always
* available in 'defaults' and libldap won't
* free it either. strdup(ret) causes memory
* leak.
*/
} else {
}
interact++;
}
return (LDAP_SUCCESS);
}
/*
* Find "dbase: service1 [...] services2" in fname and return
* " service1 [...] services2"
* e.g.
* Find "hosts: files dns" and return " files dns"
*/
static char *
{
*errp = NS_LDAP_CONFIG;
return (NULL);
}
*errp = NS_LDAP_SUCCESS;
/*
* Ignore portion of line following the comment character '#'.
*/
*comment = '\0';
}
continue;
}
continue; /* ignore this line */
} else {
/* skip "dbase:" */
*errp = NS_LDAP_MEMORY;
}
}
return (retp);
}
/*
* Test the configurations of the "hosts" and "ipnodes"
* dns has to be present and appear before ldap
* e.g.
* "dns" , "dns files" "dns ldap files", "files dns" are allowed.
*
* Kerberos requires dns or it'd fail.
*/
static int
const char *fname,
{
gettext("Parsing %s to find \"%s:\" "
if (foreground) {
} else {
}
return (pserr);
}
if (ldap) {
gettext("%s: ldap can't appear "
"before dns"), db[i]);
if (foreground) {
"start: %s\n", buf);
} else {
}
return (NS_LDAP_CONFIG);
} else {
dns++;
}
ldap++;
}
/* next token */
}
if (conf) {
}
if (!dns) {
gettext("%s: dns is not defined in %s"),
if (foreground) {
} else {
}
rc = NS_LDAP_CONFIG;
break;
}
}
return (rc);
}
static boolean_t
{
char *st;
}
return (result);
}
/*
* It's called only if config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY ||
* config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED.
*/
int
int mode_verbose,
int mode_quiet,
const char *fname,
{
int loglevel;
if (errpp)
else
return (NS_LDAP_INVALID_PARAM);
/* Shouldn't happen. Check this value just in case */
return (NS_LDAP_SUCCESS);
!= NS_LDAP_SUCCESS)
return (retcode);
if (foreground) {
gettext("DNS client is enabled"));
} else {
gettext("DNS client is enabled"));
}
return (NS_LDAP_SUCCESS);
} else {
if (config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY) {
gettext("%s: DNS client is not enabled. "
"Run \"svcadm enable %s\". %s."),
} else if (config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED) {
gettext("%s: DNS client is not enabled. "
"Run \"svcadm enable %s\". %s."
}
if (foreground) {
} else {
}
return (retcode);
}
}
/*
*/
int
int mode_verbose,
int mode_quiet,
{
int rc;
int loglevel;
if (errpp)
else
return (NS_LDAP_INVALID_PARAM);
/* Don't need to check */
return (NS_LDAP_SUCCESS);
if (result)
(void) __ns_ldap_freeResult(&result);
if (rc == NS_LDAP_SUCCESS) {
if (foreground) {
} else {
}
return (NS_LDAP_SUCCESS);
} else {
if (config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY) {
"working. %s."), "Error", "Abort");
} else if (config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED) {
"working. Fall back to other cred "
"Warning", "Continue");
/* reset return code */
}
if (foreground) {
} else {
}
return (rc);
}
}
/*
* This is called by ldap_cachemgr to check dns and gssapi prequisites.
*/
int
int mode_verbose,
int mode_quiet,
{
int rc;
if (errpp)
else
return (NS_LDAP_INVALID_PARAM);
/* Don't need to check */
return (NS_LDAP_SUCCESS);
return (rc);
return (rc);
return (NS_LDAP_SUCCESS);
}