1*cb5caa98Sdjl /* 2*cb5caa98Sdjl * CDDL HEADER START 3*cb5caa98Sdjl * 4*cb5caa98Sdjl * The contents of this file are subject to the terms of the 5*cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6*cb5caa98Sdjl * You may not use this file except in compliance with the License. 7*cb5caa98Sdjl * 8*cb5caa98Sdjl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*cb5caa98Sdjl * or http://www.opensolaris.org/os/licensing. 10*cb5caa98Sdjl * See the License for the specific language governing permissions 11*cb5caa98Sdjl * and limitations under the License. 12*cb5caa98Sdjl * 13*cb5caa98Sdjl * When distributing Covered Code, include this CDDL HEADER in each 14*cb5caa98Sdjl * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*cb5caa98Sdjl * If applicable, add the following below this CDDL HEADER, with the 16*cb5caa98Sdjl * fields enclosed by brackets "[]" replaced with your own identifying 17*cb5caa98Sdjl * information: Portions Copyright [yyyy] [name of copyright owner] 18*cb5caa98Sdjl * 19*cb5caa98Sdjl * CDDL HEADER END 20*cb5caa98Sdjl */ 21*cb5caa98Sdjl /* 22*cb5caa98Sdjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*cb5caa98Sdjl * Use is subject to license terms. 24*cb5caa98Sdjl */ 25*cb5caa98Sdjl 26*cb5caa98Sdjl #pragma ident "%Z%%M% %I% %E% SMI" 27*cb5caa98Sdjl 28*cb5caa98Sdjl #include <stdio.h> 29*cb5caa98Sdjl #include <stdlib.h> 30*cb5caa98Sdjl #include <strings.h> 31*cb5caa98Sdjl #include <sys/types.h> 32*cb5caa98Sdjl #include <sys/stat.h> 33*cb5caa98Sdjl #include <unistd.h> 34*cb5caa98Sdjl #include <thread.h> 35*cb5caa98Sdjl #include <synch.h> 36*cb5caa98Sdjl #include <sasl/sasl.h> 37*cb5caa98Sdjl #include <sys/socket.h> 38*cb5caa98Sdjl #include <netdb.h> 39*cb5caa98Sdjl #include <netinet/in.h> 40*cb5caa98Sdjl #include <arpa/inet.h> 41*cb5caa98Sdjl #include <syslog.h> 42*cb5caa98Sdjl #include <ctype.h> 43*cb5caa98Sdjl #include <libscf.h> 44*cb5caa98Sdjl #include <libintl.h> 45*cb5caa98Sdjl #include <locale.h> 46*cb5caa98Sdjl #include "ns_sldap.h" 47*cb5caa98Sdjl #include "ns_internal.h" 48*cb5caa98Sdjl 49*cb5caa98Sdjl static int self_gssapi_only = 0; 50*cb5caa98Sdjl static mutex_t self_gssapi_only_lock = DEFAULTMUTEX; 51*cb5caa98Sdjl 52*cb5caa98Sdjl #define DNS_FMRI "svc:/network/dns/client:default" 53*cb5caa98Sdjl #define MSGSIZE 256 54*cb5caa98Sdjl 55*cb5caa98Sdjl #define NSSWITCH_CONF "/etc/nsswitch.conf" 56*cb5caa98Sdjl 57*cb5caa98Sdjl /* 58*cb5caa98Sdjl * Error Handling 59*cb5caa98Sdjl */ 60*cb5caa98Sdjl #define CLIENT_FPRINTF if (mode_verbose && !mode_quiet) (void) fprintf 61*cb5caa98Sdjl 62*cb5caa98Sdjl /* 63*cb5caa98Sdjl * One time initializtion 64*cb5caa98Sdjl */ 65*cb5caa98Sdjl int sasl_gssapi_inited = 0; 66*cb5caa98Sdjl static mutex_t sasl_gssapi_lock = DEFAULTMUTEX; 67*cb5caa98Sdjl int 68*cb5caa98Sdjl __s_api_sasl_gssapi_init(void) { 69*cb5caa98Sdjl int rc = NS_LDAP_SUCCESS; 70*cb5caa98Sdjl (void) mutex_lock(&sasl_gssapi_lock); 71*cb5caa98Sdjl if (!sasl_gssapi_inited) { 72*cb5caa98Sdjl if (getuid() == 0) { 73*cb5caa98Sdjl if (system( 74*cb5caa98Sdjl "/usr/sbin/cryptoadm disable metaslot") 75*cb5caa98Sdjl == 0) { 76*cb5caa98Sdjl syslog(LOG_WARNING, 77*cb5caa98Sdjl "libsldap: Metaslot disabled " 78*cb5caa98Sdjl "for self credential mode"); 79*cb5caa98Sdjl sasl_gssapi_inited = 1; 80*cb5caa98Sdjl } else { 81*cb5caa98Sdjl syslog(LOG_ERR, 82*cb5caa98Sdjl "libsldap: Can't disable " 83*cb5caa98Sdjl "Metaslot for self credential " 84*cb5caa98Sdjl "mode"); 85*cb5caa98Sdjl rc = NS_LDAP_INTERNAL; 86*cb5caa98Sdjl } 87*cb5caa98Sdjl } 88*cb5caa98Sdjl } 89*cb5caa98Sdjl (void) mutex_unlock(&sasl_gssapi_lock); 90*cb5caa98Sdjl 91*cb5caa98Sdjl return (rc); 92*cb5caa98Sdjl } 93*cb5caa98Sdjl 94*cb5caa98Sdjl /* 95*cb5caa98Sdjl * nscd calls this function to set self_gssapi_only flag so libsldap performs 96*cb5caa98Sdjl * sasl/GSSAPI bind only. Also see comments of __ns_ldap_self_gssapi_config. 97*cb5caa98Sdjl * 98*cb5caa98Sdjl * Input: flag 0 use any kind of connection 99*cb5caa98Sdjl * 1 use self/gssapi connection only 100*cb5caa98Sdjl */ 101*cb5caa98Sdjl void 102*cb5caa98Sdjl __ns_ldap_self_gssapi_only_set(int flag) { 103*cb5caa98Sdjl (void) mutex_lock(&self_gssapi_only_lock); 104*cb5caa98Sdjl self_gssapi_only = flag; 105*cb5caa98Sdjl (void) mutex_unlock(&self_gssapi_only_lock); 106*cb5caa98Sdjl } 107*cb5caa98Sdjl /* 108*cb5caa98Sdjl * Get the flag value of self_gssapi_only 109*cb5caa98Sdjl */ 110*cb5caa98Sdjl int 111*cb5caa98Sdjl __s_api_self_gssapi_only_get(void) { 112*cb5caa98Sdjl int flag; 113*cb5caa98Sdjl (void) mutex_lock(&self_gssapi_only_lock); 114*cb5caa98Sdjl flag = self_gssapi_only; 115*cb5caa98Sdjl (void) mutex_unlock(&self_gssapi_only_lock); 116*cb5caa98Sdjl return (flag); 117*cb5caa98Sdjl } 118*cb5caa98Sdjl /* 119*cb5caa98Sdjl * nscd calls this function to detect the current native ldap configuration. 120*cb5caa98Sdjl * The output are 121*cb5caa98Sdjl * NS_LDAP_SELF_GSSAPI_CONFIG_NONE: No credential level self and 122*cb5caa98Sdjl * no authentication method sasl/GSSAPI is 123*cb5caa98Sdjl * configured. 124*cb5caa98Sdjl * NS_LDAP_SELF_GSSAPI_CONFIG_ONLY: Only credential level self and 125*cb5caa98Sdjl * authentication method sasl/GSSAPI are 126*cb5caa98Sdjl * configured. 127*cb5caa98Sdjl * NS_LDAP_SELF_GSSAPI_CONFIG_MIXED: More than one credential level are 128*cb5caa98Sdjl * configured, including self. 129*cb5caa98Sdjl * More than one authentication method 130*cb5caa98Sdjl * are configured, including sasl/GSSAPI. 131*cb5caa98Sdjl * 132*cb5caa98Sdjl * __s_api_crosscheck makes sure self and sasl/GSSAPI pair up if they do 133*cb5caa98Sdjl * get configured. 134*cb5caa98Sdjl * 135*cb5caa98Sdjl * When nscd detects it's MIXED case, it calls __ns_ldap_self_gssapi_only_set 136*cb5caa98Sdjl * to force libsldap to do sasl/GSSAPI bind only for per-user lookup. 137*cb5caa98Sdjl * 138*cb5caa98Sdjl * Return: NS_LDAP_SUCCESS 139*cb5caa98Sdjl * OTHERWISE - FAILURE 140*cb5caa98Sdjl * 141*cb5caa98Sdjl * Output: config. See comments above. 142*cb5caa98Sdjl * 143*cb5caa98Sdjl */ 144*cb5caa98Sdjl int 145*cb5caa98Sdjl __ns_ldap_self_gssapi_config(ns_ldap_self_gssapi_config_t *config) { 146*cb5caa98Sdjl int self = 0, other_level = 0, gssapi = 0, other_method = 0; 147*cb5caa98Sdjl ns_auth_t **aMethod = NULL, **aNext = NULL; 148*cb5caa98Sdjl int **cLevel = NULL, **cNext = NULL, rc; 149*cb5caa98Sdjl ns_ldap_error_t *errp = NULL; 150*cb5caa98Sdjl 151*cb5caa98Sdjl if (config == NULL) 152*cb5caa98Sdjl return (NS_LDAP_INVALID_PARAM); 153*cb5caa98Sdjl else 154*cb5caa98Sdjl *config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE; 155*cb5caa98Sdjl 156*cb5caa98Sdjl /* Get the credential level list */ 157*cb5caa98Sdjl if ((rc = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P, 158*cb5caa98Sdjl (void ***)&cLevel, &errp)) != NS_LDAP_SUCCESS) { 159*cb5caa98Sdjl if (errp) 160*cb5caa98Sdjl (void) __ns_ldap_freeError(&errp); 161*cb5caa98Sdjl if (cLevel) 162*cb5caa98Sdjl (void) __ns_ldap_freeParam((void ***)&cLevel); 163*cb5caa98Sdjl return (rc); 164*cb5caa98Sdjl } 165*cb5caa98Sdjl if (errp) 166*cb5caa98Sdjl (void) __ns_ldap_freeError(&errp); 167*cb5caa98Sdjl /* Get the authentication method list */ 168*cb5caa98Sdjl if ((rc = __ns_ldap_getParam(NS_LDAP_AUTH_P, 169*cb5caa98Sdjl (void ***)&aMethod, &errp)) != NS_LDAP_SUCCESS) { 170*cb5caa98Sdjl if (errp) 171*cb5caa98Sdjl (void) __ns_ldap_freeError(&errp); 172*cb5caa98Sdjl if (cLevel) 173*cb5caa98Sdjl (void) __ns_ldap_freeParam((void ***)&cLevel); 174*cb5caa98Sdjl if (aMethod) 175*cb5caa98Sdjl (void) __ns_ldap_freeParam((void ***)&aMethod); 176*cb5caa98Sdjl return (rc); 177*cb5caa98Sdjl } 178*cb5caa98Sdjl if (errp) 179*cb5caa98Sdjl (void) __ns_ldap_freeError(&errp); 180*cb5caa98Sdjl 181*cb5caa98Sdjl if (cLevel == NULL || aMethod == NULL) { 182*cb5caa98Sdjl if (cLevel) 183*cb5caa98Sdjl (void) __ns_ldap_freeParam((void ***)&cLevel); 184*cb5caa98Sdjl if (aMethod) 185*cb5caa98Sdjl (void) __ns_ldap_freeParam((void ***)&aMethod); 186*cb5caa98Sdjl return (NS_LDAP_SUCCESS); 187*cb5caa98Sdjl } 188*cb5caa98Sdjl 189*cb5caa98Sdjl for (cNext = cLevel; *cNext != NULL; cNext++) { 190*cb5caa98Sdjl if (**cNext == NS_LDAP_CRED_SELF) 191*cb5caa98Sdjl self++; 192*cb5caa98Sdjl else 193*cb5caa98Sdjl other_level++; 194*cb5caa98Sdjl } 195*cb5caa98Sdjl for (aNext = aMethod; *aNext != NULL; aNext++) { 196*cb5caa98Sdjl if ((*aNext)->saslmech == NS_LDAP_SASL_GSSAPI) 197*cb5caa98Sdjl gssapi++; 198*cb5caa98Sdjl else 199*cb5caa98Sdjl other_method++; 200*cb5caa98Sdjl } 201*cb5caa98Sdjl 202*cb5caa98Sdjl if (self > 0 && gssapi > 0) { 203*cb5caa98Sdjl if (other_level == 0 && other_method == 0) 204*cb5caa98Sdjl *config = NS_LDAP_SELF_GSSAPI_CONFIG_ONLY; 205*cb5caa98Sdjl else 206*cb5caa98Sdjl *config = NS_LDAP_SELF_GSSAPI_CONFIG_MIXED; 207*cb5caa98Sdjl } 208*cb5caa98Sdjl 209*cb5caa98Sdjl if (cLevel) 210*cb5caa98Sdjl (void) __ns_ldap_freeParam((void ***)&cLevel); 211*cb5caa98Sdjl if (aMethod) 212*cb5caa98Sdjl (void) __ns_ldap_freeParam((void ***)&aMethod); 213*cb5caa98Sdjl return (NS_LDAP_SUCCESS); 214*cb5caa98Sdjl } 215*cb5caa98Sdjl 216*cb5caa98Sdjl int 217*cb5caa98Sdjl __s_api_sasl_bind_callback( 218*cb5caa98Sdjl /* LINTED E_FUNC_ARG_UNUSED */ 219*cb5caa98Sdjl LDAP *ld, 220*cb5caa98Sdjl /* LINTED E_FUNC_ARG_UNUSED */ 221*cb5caa98Sdjl unsigned flags, 222*cb5caa98Sdjl void *defaults, 223*cb5caa98Sdjl void *in) 224*cb5caa98Sdjl { 225*cb5caa98Sdjl char *ret = NULL; 226*cb5caa98Sdjl sasl_interact_t *interact = in; 227*cb5caa98Sdjl ns_sasl_cb_param_t *cred = (ns_sasl_cb_param_t *)defaults; 228*cb5caa98Sdjl 229*cb5caa98Sdjl 230*cb5caa98Sdjl while (interact->id != SASL_CB_LIST_END) { 231*cb5caa98Sdjl 232*cb5caa98Sdjl switch (interact->id) { 233*cb5caa98Sdjl 234*cb5caa98Sdjl case SASL_CB_GETREALM: 235*cb5caa98Sdjl ret = cred->realm; 236*cb5caa98Sdjl break; 237*cb5caa98Sdjl case SASL_CB_AUTHNAME: 238*cb5caa98Sdjl ret = cred->authid; 239*cb5caa98Sdjl break; 240*cb5caa98Sdjl case SASL_CB_PASS: 241*cb5caa98Sdjl ret = cred->passwd; 242*cb5caa98Sdjl break; 243*cb5caa98Sdjl case SASL_CB_USER: 244*cb5caa98Sdjl ret = cred->authzid; 245*cb5caa98Sdjl break; 246*cb5caa98Sdjl case SASL_CB_NOECHOPROMPT: 247*cb5caa98Sdjl case SASL_CB_ECHOPROMPT: 248*cb5caa98Sdjl default: 249*cb5caa98Sdjl break; 250*cb5caa98Sdjl } 251*cb5caa98Sdjl 252*cb5caa98Sdjl if (ret) { 253*cb5caa98Sdjl interact->result = strdup(ret); 254*cb5caa98Sdjl if (interact->result == NULL) 255*cb5caa98Sdjl return (LDAP_NO_MEMORY); 256*cb5caa98Sdjl 257*cb5caa98Sdjl interact->len = strlen(ret); 258*cb5caa98Sdjl } else { 259*cb5caa98Sdjl interact->result = NULL; 260*cb5caa98Sdjl interact->len = 0; 261*cb5caa98Sdjl } 262*cb5caa98Sdjl interact++; 263*cb5caa98Sdjl } 264*cb5caa98Sdjl 265*cb5caa98Sdjl return (LDAP_SUCCESS); 266*cb5caa98Sdjl } 267*cb5caa98Sdjl 268*cb5caa98Sdjl /* 269*cb5caa98Sdjl * Find "dbase: service1 [...] services2" in fname and return 270*cb5caa98Sdjl * " service1 [...] services2" 271*cb5caa98Sdjl * e.g. 272*cb5caa98Sdjl * Find "hosts: files dns" and return " files dns" 273*cb5caa98Sdjl */ 274*cb5caa98Sdjl static char * 275*cb5caa98Sdjl __ns_nsw_getconfig(const char *dbase, const char *fname, int *errp) 276*cb5caa98Sdjl { 277*cb5caa98Sdjl FILE *fp = NULL; 278*cb5caa98Sdjl char *linep, *retp = NULL; 279*cb5caa98Sdjl char lineq[BUFSIZ], db_colon[BUFSIZ]; 280*cb5caa98Sdjl 281*cb5caa98Sdjl if ((fp = fopen(fname, "rF")) == NULL) { 282*cb5caa98Sdjl *errp = NS_LDAP_CONFIG; 283*cb5caa98Sdjl return (NULL); 284*cb5caa98Sdjl } 285*cb5caa98Sdjl *errp = NS_LDAP_SUCCESS; 286*cb5caa98Sdjl 287*cb5caa98Sdjl while (linep = fgets(lineq, BUFSIZ, fp)) { 288*cb5caa98Sdjl char *tokenp, *comment; 289*cb5caa98Sdjl 290*cb5caa98Sdjl /* 291*cb5caa98Sdjl * Ignore portion of line following the comment character '#'. 292*cb5caa98Sdjl */ 293*cb5caa98Sdjl if ((comment = strchr(linep, '#')) != NULL) { 294*cb5caa98Sdjl *comment = '\0'; 295*cb5caa98Sdjl } 296*cb5caa98Sdjl if ((*linep == '\0') || isspace(*linep)) { 297*cb5caa98Sdjl continue; 298*cb5caa98Sdjl } 299*cb5caa98Sdjl (void) snprintf(db_colon, BUFSIZ, "%s:", dbase); 300*cb5caa98Sdjl if ((tokenp = strstr(linep, db_colon)) == NULL) { 301*cb5caa98Sdjl continue; /* ignore this line */ 302*cb5caa98Sdjl } else { 303*cb5caa98Sdjl /* skip "dbase:" */ 304*cb5caa98Sdjl retp = strdup(tokenp + strlen(db_colon)); 305*cb5caa98Sdjl if (retp == NULL) 306*cb5caa98Sdjl *errp = NS_LDAP_MEMORY; 307*cb5caa98Sdjl } 308*cb5caa98Sdjl } 309*cb5caa98Sdjl 310*cb5caa98Sdjl (void) fclose(fp); 311*cb5caa98Sdjl return (retp); 312*cb5caa98Sdjl } 313*cb5caa98Sdjl /* 314*cb5caa98Sdjl * Test the configurations of the "hosts" and "ipnodes" 315*cb5caa98Sdjl * dns has to be present and appear before ldap 316*cb5caa98Sdjl * e.g. 317*cb5caa98Sdjl * "dns" , "dns files" "dns ldap files", "files dns" are allowed. 318*cb5caa98Sdjl * 319*cb5caa98Sdjl * Kerberos requires dns or it'd fail. 320*cb5caa98Sdjl */ 321*cb5caa98Sdjl static int 322*cb5caa98Sdjl test_dns_nsswitch(int foreground, 323*cb5caa98Sdjl const char *fname, 324*cb5caa98Sdjl ns_ldap_error_t **errpp) { 325*cb5caa98Sdjl int ldap, dns, i, pserr, rc = NS_LDAP_SUCCESS; 326*cb5caa98Sdjl char *db[3] = {"hosts", "ipnodes", NULL}; 327*cb5caa98Sdjl char buf[MSGSIZE], *conf = NULL, *token = NULL, *last = NULL; 328*cb5caa98Sdjl 329*cb5caa98Sdjl for (i = 0; db[i] != NULL; i++) { 330*cb5caa98Sdjl conf = __ns_nsw_getconfig(db[i], fname, &pserr); 331*cb5caa98Sdjl 332*cb5caa98Sdjl if (conf == NULL) { 333*cb5caa98Sdjl (void) snprintf(buf, MSGSIZE, 334*cb5caa98Sdjl gettext("Parsing %s to find \"%s:\" " 335*cb5caa98Sdjl "failed. err: %d"), 336*cb5caa98Sdjl fname, db[i], pserr); 337*cb5caa98Sdjl if (foreground) { 338*cb5caa98Sdjl (void) fprintf(stderr, "%s\n", buf); 339*cb5caa98Sdjl } else { 340*cb5caa98Sdjl MKERROR(LOG_ERR, *errpp, NS_LDAP_CONFIG, 341*cb5caa98Sdjl strdup(buf), NS_LDAP_MEMORY); 342*cb5caa98Sdjl } 343*cb5caa98Sdjl return (pserr); 344*cb5caa98Sdjl } 345*cb5caa98Sdjl ldap = dns = 0; 346*cb5caa98Sdjl token = strtok_r(conf, " ", &last); 347*cb5caa98Sdjl while (token != NULL) { 348*cb5caa98Sdjl if (strncmp(token, "dns", 3) == 0) { 349*cb5caa98Sdjl if (ldap) { 350*cb5caa98Sdjl (void) snprintf(buf, MSGSIZE, 351*cb5caa98Sdjl gettext("%s: ldap can't appear " 352*cb5caa98Sdjl "before dns"), db[i]); 353*cb5caa98Sdjl if (foreground) { 354*cb5caa98Sdjl (void) fprintf(stderr, 355*cb5caa98Sdjl "start: %s\n", 356*cb5caa98Sdjl buf); 357*cb5caa98Sdjl } else { 358*cb5caa98Sdjl MKERROR(LOG_ERR, *errpp, 359*cb5caa98Sdjl NS_LDAP_CONFIG, 360*cb5caa98Sdjl strdup(buf), 361*cb5caa98Sdjl NS_LDAP_MEMORY); 362*cb5caa98Sdjl } 363*cb5caa98Sdjl free(conf); 364*cb5caa98Sdjl return (NS_LDAP_CONFIG); 365*cb5caa98Sdjl } else { 366*cb5caa98Sdjl dns++; 367*cb5caa98Sdjl } 368*cb5caa98Sdjl } else if (strncmp(token, "ldap", 4) == 0) { 369*cb5caa98Sdjl ldap++; 370*cb5caa98Sdjl } 371*cb5caa98Sdjl /* next token */ 372*cb5caa98Sdjl token = strtok_r(NULL, " ", &last); 373*cb5caa98Sdjl } 374*cb5caa98Sdjl if (conf) { 375*cb5caa98Sdjl free(conf); 376*cb5caa98Sdjl conf = NULL; 377*cb5caa98Sdjl } 378*cb5caa98Sdjl if (!dns) { 379*cb5caa98Sdjl (void) snprintf(buf, MSGSIZE, 380*cb5caa98Sdjl gettext("%s: dns is not defined in " 381*cb5caa98Sdjl "%s"), db[i], fname); 382*cb5caa98Sdjl if (foreground) { 383*cb5caa98Sdjl (void) fprintf(stderr, "start: %s\n", buf); 384*cb5caa98Sdjl } else { 385*cb5caa98Sdjl MKERROR(LOG_ERR, *errpp, NS_LDAP_CONFIG, 386*cb5caa98Sdjl strdup(buf), NS_LDAP_MEMORY); 387*cb5caa98Sdjl } 388*cb5caa98Sdjl rc = NS_LDAP_CONFIG; 389*cb5caa98Sdjl break; 390*cb5caa98Sdjl } 391*cb5caa98Sdjl } 392*cb5caa98Sdjl return (rc); 393*cb5caa98Sdjl } 394*cb5caa98Sdjl 395*cb5caa98Sdjl static boolean_t 396*cb5caa98Sdjl is_service(const char *fmri, const char *state) { 397*cb5caa98Sdjl char *st; 398*cb5caa98Sdjl boolean_t result = B_FALSE; 399*cb5caa98Sdjl 400*cb5caa98Sdjl if ((st = smf_get_state(fmri)) != NULL) { 401*cb5caa98Sdjl if (strcmp(st, state) == 0) 402*cb5caa98Sdjl result = B_TRUE; 403*cb5caa98Sdjl free(st); 404*cb5caa98Sdjl } 405*cb5caa98Sdjl return (result); 406*cb5caa98Sdjl } 407*cb5caa98Sdjl 408*cb5caa98Sdjl 409*cb5caa98Sdjl /* 410*cb5caa98Sdjl * This function checks dns prerequisites for sasl/GSSAPI bind. 411*cb5caa98Sdjl * It's called only if config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY || 412*cb5caa98Sdjl * config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED. 413*cb5caa98Sdjl */ 414*cb5caa98Sdjl int 415*cb5caa98Sdjl __ns_ldap_check_dns_preq(int foreground, 416*cb5caa98Sdjl int mode_verbose, 417*cb5caa98Sdjl int mode_quiet, 418*cb5caa98Sdjl const char *fname, 419*cb5caa98Sdjl ns_ldap_self_gssapi_config_t config, 420*cb5caa98Sdjl ns_ldap_error_t **errpp) { 421*cb5caa98Sdjl 422*cb5caa98Sdjl char buf[MSGSIZE]; 423*cb5caa98Sdjl int retcode = NS_LDAP_SUCCESS; 424*cb5caa98Sdjl int loglevel; 425*cb5caa98Sdjl 426*cb5caa98Sdjl if (errpp) 427*cb5caa98Sdjl *errpp = NULL; 428*cb5caa98Sdjl else 429*cb5caa98Sdjl return (NS_LDAP_INVALID_PARAM); 430*cb5caa98Sdjl 431*cb5caa98Sdjl if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE) 432*cb5caa98Sdjl /* Shouldn't happen. Check this value just in case */ 433*cb5caa98Sdjl return (NS_LDAP_SUCCESS); 434*cb5caa98Sdjl 435*cb5caa98Sdjl if ((retcode = test_dns_nsswitch(foreground, fname, errpp)) != 436*cb5caa98Sdjl NS_LDAP_SUCCESS) 437*cb5caa98Sdjl return (retcode); 438*cb5caa98Sdjl 439*cb5caa98Sdjl if (is_service(DNS_FMRI, SCF_STATE_STRING_ONLINE)) { 440*cb5caa98Sdjl if (foreground) { 441*cb5caa98Sdjl CLIENT_FPRINTF(stdout, "start: %s\n", 442*cb5caa98Sdjl gettext("DNS client is enabled")); 443*cb5caa98Sdjl } else { 444*cb5caa98Sdjl syslog(LOG_INFO, "%s", 445*cb5caa98Sdjl gettext("DNS client is enabled")); 446*cb5caa98Sdjl } 447*cb5caa98Sdjl return (NS_LDAP_SUCCESS); 448*cb5caa98Sdjl } else { 449*cb5caa98Sdjl if (config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY) { 450*cb5caa98Sdjl (void) snprintf(buf, MSGSIZE, 451*cb5caa98Sdjl gettext("%s: DNS client is not enabled. " 452*cb5caa98Sdjl "Run \"svcadm enable %s\". %s."), 453*cb5caa98Sdjl "Error", DNS_FMRI, "Abort"); 454*cb5caa98Sdjl loglevel = LOG_ERR; 455*cb5caa98Sdjl retcode = NS_LDAP_CONFIG; 456*cb5caa98Sdjl } else if (config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED) { 457*cb5caa98Sdjl (void) snprintf(buf, MSGSIZE, 458*cb5caa98Sdjl gettext("%s: DNS client is not enabled. " 459*cb5caa98Sdjl "Run \"svcadm enable %s\". %s." 460*cb5caa98Sdjl "Fall back to other cred level/bind. "), 461*cb5caa98Sdjl "Warning", DNS_FMRI, "Continue"); 462*cb5caa98Sdjl loglevel = LOG_INFO; 463*cb5caa98Sdjl retcode = NS_LDAP_SUCCESS; 464*cb5caa98Sdjl } 465*cb5caa98Sdjl 466*cb5caa98Sdjl if (foreground) { 467*cb5caa98Sdjl (void) fprintf(stderr, "start: %s\n", buf); 468*cb5caa98Sdjl } else { 469*cb5caa98Sdjl MKERROR(loglevel, *errpp, retcode, strdup(buf), 470*cb5caa98Sdjl NS_LDAP_MEMORY); 471*cb5caa98Sdjl } 472*cb5caa98Sdjl return (retcode); 473*cb5caa98Sdjl } 474*cb5caa98Sdjl } 475*cb5caa98Sdjl 476*cb5caa98Sdjl /* 477*cb5caa98Sdjl * Check if sasl/GSSAPI works 478*cb5caa98Sdjl */ 479*cb5caa98Sdjl int 480*cb5caa98Sdjl __ns_ldap_check_gssapi_preq(int foreground, 481*cb5caa98Sdjl int mode_verbose, 482*cb5caa98Sdjl int mode_quiet, 483*cb5caa98Sdjl ns_ldap_self_gssapi_config_t config, 484*cb5caa98Sdjl ns_ldap_error_t **errpp) { 485*cb5caa98Sdjl 486*cb5caa98Sdjl int rc; 487*cb5caa98Sdjl char *attr[2] = {"dn", NULL}, buf[MSGSIZE]; 488*cb5caa98Sdjl ns_cred_t cred; 489*cb5caa98Sdjl ns_ldap_result_t *result = NULL; 490*cb5caa98Sdjl int loglevel; 491*cb5caa98Sdjl 492*cb5caa98Sdjl if (errpp) 493*cb5caa98Sdjl *errpp = NULL; 494*cb5caa98Sdjl else 495*cb5caa98Sdjl return (NS_LDAP_INVALID_PARAM); 496*cb5caa98Sdjl 497*cb5caa98Sdjl if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE) 498*cb5caa98Sdjl /* Don't need to check */ 499*cb5caa98Sdjl return (NS_LDAP_SUCCESS); 500*cb5caa98Sdjl 501*cb5caa98Sdjl (void) memset(&cred, 0, sizeof (ns_cred_t)); 502*cb5caa98Sdjl 503*cb5caa98Sdjl cred.auth.type = NS_LDAP_AUTH_SASL; 504*cb5caa98Sdjl cred.auth.tlstype = NS_LDAP_TLS_NONE; 505*cb5caa98Sdjl cred.auth.saslmech = NS_LDAP_SASL_GSSAPI; 506*cb5caa98Sdjl 507*cb5caa98Sdjl rc = __ns_ldap_list(NULL, (const char *)"objectclass=*", 508*cb5caa98Sdjl NULL, (const char **)attr, &cred, 509*cb5caa98Sdjl NS_LDAP_SCOPE_BASE, &result, errpp, NULL, NULL); 510*cb5caa98Sdjl if (result) 511*cb5caa98Sdjl (void) __ns_ldap_freeResult(&result); 512*cb5caa98Sdjl 513*cb5caa98Sdjl if (rc == NS_LDAP_SUCCESS) { 514*cb5caa98Sdjl if (foreground) { 515*cb5caa98Sdjl CLIENT_FPRINTF(stdout, "start: %s\n", 516*cb5caa98Sdjl gettext("sasl/GSSAPI bind works")); 517*cb5caa98Sdjl } else { 518*cb5caa98Sdjl syslog(LOG_INFO, "%s", 519*cb5caa98Sdjl gettext("sasl/GSSAPI bind works")); 520*cb5caa98Sdjl } 521*cb5caa98Sdjl return (NS_LDAP_SUCCESS); 522*cb5caa98Sdjl } else { 523*cb5caa98Sdjl if (config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY) { 524*cb5caa98Sdjl (void) snprintf(buf, MSGSIZE, 525*cb5caa98Sdjl gettext("%s: sasl/GSSAPI bind is not " 526*cb5caa98Sdjl "working. %s."), 527*cb5caa98Sdjl "Error", "Abort"); 528*cb5caa98Sdjl loglevel = LOG_ERR; 529*cb5caa98Sdjl } else if (config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED) { 530*cb5caa98Sdjl (void) snprintf(buf, MSGSIZE, 531*cb5caa98Sdjl gettext("%s: sasl/GSSAPI bind is not " 532*cb5caa98Sdjl "working. Fall back to other cred " 533*cb5caa98Sdjl "level/bind. %s."), 534*cb5caa98Sdjl "Warning", "Continue"); 535*cb5caa98Sdjl loglevel = LOG_INFO; 536*cb5caa98Sdjl /* reset return code */ 537*cb5caa98Sdjl rc = NS_LDAP_SUCCESS; 538*cb5caa98Sdjl } 539*cb5caa98Sdjl 540*cb5caa98Sdjl if (foreground) { 541*cb5caa98Sdjl (void) fprintf(stderr, "start: %s\n", buf); 542*cb5caa98Sdjl } else { 543*cb5caa98Sdjl MKERROR(loglevel, *errpp, rc, strdup(buf), 544*cb5caa98Sdjl NS_LDAP_MEMORY); 545*cb5caa98Sdjl } 546*cb5caa98Sdjl return (rc); 547*cb5caa98Sdjl } 548*cb5caa98Sdjl } 549*cb5caa98Sdjl /* 550*cb5caa98Sdjl * This is called by ldap_cachemgr to check dns and gssapi prequisites. 551*cb5caa98Sdjl */ 552*cb5caa98Sdjl int 553*cb5caa98Sdjl __ns_ldap_check_all_preq(int foreground, 554*cb5caa98Sdjl int mode_verbose, 555*cb5caa98Sdjl int mode_quiet, 556*cb5caa98Sdjl ns_ldap_self_gssapi_config_t config, 557*cb5caa98Sdjl ns_ldap_error_t **errpp) { 558*cb5caa98Sdjl 559*cb5caa98Sdjl int rc; 560*cb5caa98Sdjl 561*cb5caa98Sdjl if (errpp) 562*cb5caa98Sdjl *errpp = NULL; 563*cb5caa98Sdjl else 564*cb5caa98Sdjl return (NS_LDAP_INVALID_PARAM); 565*cb5caa98Sdjl 566*cb5caa98Sdjl if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE) 567*cb5caa98Sdjl /* Don't need to check */ 568*cb5caa98Sdjl return (NS_LDAP_SUCCESS); 569*cb5caa98Sdjl 570*cb5caa98Sdjl if ((rc = __ns_ldap_check_dns_preq(foreground, 571*cb5caa98Sdjl mode_verbose, mode_quiet, NSSWITCH_CONF, 572*cb5caa98Sdjl config, errpp)) != NS_LDAP_SUCCESS) 573*cb5caa98Sdjl return (rc); 574*cb5caa98Sdjl if ((rc = __ns_ldap_check_gssapi_preq(foreground, 575*cb5caa98Sdjl mode_verbose, mode_quiet, config, errpp)) != 576*cb5caa98Sdjl NS_LDAP_SUCCESS) 577*cb5caa98Sdjl return (rc); 578*cb5caa98Sdjl 579*cb5caa98Sdjl return (NS_LDAP_SUCCESS); 580*cb5caa98Sdjl } 581