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