17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53125ebfcSsemery * Common Development and Distribution License (the "License").
63125ebfcSsemery * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
2236e852a1SRaja Andra * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <stdlib.h>
277c478bd9Sstevel@tonic-gate #include <syslog.h>
287c478bd9Sstevel@tonic-gate #include <errno.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <assert.h>
337c478bd9Sstevel@tonic-gate #include <stdarg.h>
347c478bd9Sstevel@tonic-gate #include <sys/types.h>
357c478bd9Sstevel@tonic-gate #include <sys/wait.h>
367c478bd9Sstevel@tonic-gate #include <limits.h>
37573374d3Sjjj #include <signal.h>
38573374d3Sjjj #include <pthread.h>
39573374d3Sjjj #include <synch.h>
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h>
427c478bd9Sstevel@tonic-gate #include <rpcsvc/yppasswd.h>
437c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
447c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h>
457c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
467c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
477c478bd9Sstevel@tonic-gate #include <nfs/nfssys.h>
487c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
497c478bd9Sstevel@tonic-gate #include <nsswitch.h>
507c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h>
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
537c478bd9Sstevel@tonic-gate #include <security/pam_modules.h>
547c478bd9Sstevel@tonic-gate #include <security/pam_impl.h>
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate #include <libintl.h>
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate #include <sys/mman.h>
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate #include <passwdutil.h>
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate #include "key_call_uid.h"
6366e150d7SJohn Sonnenschein #include <shadow.h>
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate extern int _nfssys(int, void *);
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate * int msg(pamh, ...)
697c478bd9Sstevel@tonic-gate *
707c478bd9Sstevel@tonic-gate * display message to the user
717c478bd9Sstevel@tonic-gate */
727c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/
73573374d3Sjjj static int
msg(pam_handle_t * pamh,char * fmt,...)747c478bd9Sstevel@tonic-gate msg(pam_handle_t *pamh, char *fmt, ...)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate va_list ap;
777c478bd9Sstevel@tonic-gate char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate va_start(ap, fmt);
807c478bd9Sstevel@tonic-gate (void) vsnprintf(messages[0], sizeof (messages[0]), fmt, ap);
817c478bd9Sstevel@tonic-gate va_end(ap);
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate return (__pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL));
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate /*
887c478bd9Sstevel@tonic-gate * Get the secret key for the given netname, key length, and algorithm
897c478bd9Sstevel@tonic-gate * type and send it to keyserv if the given pw decrypts it. Update the
907c478bd9Sstevel@tonic-gate * following counter args as necessary: get_seckey_cnt, good_pw_cnt, and
917c478bd9Sstevel@tonic-gate * set_seckey_cnt.
927c478bd9Sstevel@tonic-gate *
937c478bd9Sstevel@tonic-gate * Returns 0 on malloc failure, else 1.
947c478bd9Sstevel@tonic-gate */
957c478bd9Sstevel@tonic-gate static int
get_and_set_seckey(pam_handle_t * pamh,const char * netname,keylen_t keylen,algtype_t algtype,const char * pw,uid_t uid,gid_t gid,int * get_seckey_cnt,int * good_pw_cnt,int * set_seckey_cnt,int flags,int debug)967c478bd9Sstevel@tonic-gate get_and_set_seckey(
977c478bd9Sstevel@tonic-gate pam_handle_t *pamh, /* in */
987c478bd9Sstevel@tonic-gate const char *netname, /* in */
997c478bd9Sstevel@tonic-gate keylen_t keylen, /* in */
1007c478bd9Sstevel@tonic-gate algtype_t algtype, /* in */
1017c478bd9Sstevel@tonic-gate const char *pw, /* in */
1027c478bd9Sstevel@tonic-gate uid_t uid, /* in */
1037c478bd9Sstevel@tonic-gate gid_t gid, /* in */
1047c478bd9Sstevel@tonic-gate int *get_seckey_cnt, /* out */
1057c478bd9Sstevel@tonic-gate int *good_pw_cnt, /* out */
1067c478bd9Sstevel@tonic-gate int *set_seckey_cnt, /* out */
1077c478bd9Sstevel@tonic-gate int flags, /* in */
1087c478bd9Sstevel@tonic-gate int debug) /* in */
1097c478bd9Sstevel@tonic-gate {
1107c478bd9Sstevel@tonic-gate char *skey;
1117c478bd9Sstevel@tonic-gate int skeylen;
1127c478bd9Sstevel@tonic-gate char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate skeylen = BITS2NIBBLES(keylen) + 1;
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate if ((skey = malloc(skeylen)) == NULL) {
1177c478bd9Sstevel@tonic-gate return (0);
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate if (getsecretkey_g(netname, keylen, algtype, skey, skeylen, pw)) {
1217c478bd9Sstevel@tonic-gate (*get_seckey_cnt)++;
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate if (skey[0]) {
1247c478bd9Sstevel@tonic-gate /* password does decrypt secret key */
1257c478bd9Sstevel@tonic-gate (*good_pw_cnt)++;
1267c478bd9Sstevel@tonic-gate if (key_setnet_g_uid(netname, skey, keylen, NULL, 0,
1277c478bd9Sstevel@tonic-gate algtype, uid, gid) >= 0) {
1287c478bd9Sstevel@tonic-gate (*set_seckey_cnt)++;
1297c478bd9Sstevel@tonic-gate } else {
1307c478bd9Sstevel@tonic-gate if (debug)
1317c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: "
1327c478bd9Sstevel@tonic-gate "get_and_set_seckey: could not "
1337c478bd9Sstevel@tonic-gate "set secret key for keytype "
1347c478bd9Sstevel@tonic-gate "%d-%d", keylen, algtype);
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate } else {
1377c478bd9Sstevel@tonic-gate if (pamh && !(flags & PAM_SILENT)) {
1387c478bd9Sstevel@tonic-gate (void) snprintf(messages[0],
1397c478bd9Sstevel@tonic-gate sizeof (messages[0]),
1407c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
1417c478bd9Sstevel@tonic-gate "Password does not "
1427c478bd9Sstevel@tonic-gate "decrypt secret key (type = %d-%d) "
1437c478bd9Sstevel@tonic-gate "for '%s'."), keylen, algtype, netname);
1447c478bd9Sstevel@tonic-gate (void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1,
1457c478bd9Sstevel@tonic-gate messages, NULL);
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate } else {
1497c478bd9Sstevel@tonic-gate if (debug)
1507c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: get_and_set_seckey: "
1517c478bd9Sstevel@tonic-gate "could not get secret key for keytype %d-%d",
1527c478bd9Sstevel@tonic-gate keylen, algtype);
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate free(skey);
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate return (1);
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate /*
1617c478bd9Sstevel@tonic-gate * int establish_key(pamh, flags, debug, netname)
1627c478bd9Sstevel@tonic-gate *
163730bc278Ssdussud * This routine establishes the Secure RPC Credentials for the
1647c478bd9Sstevel@tonic-gate * user specified in PAM_USER, using the password in PAM_AUTHTOK.
1657c478bd9Sstevel@tonic-gate *
166730bc278Ssdussud * Establishing RPC credentials is considered a "helper" function for the PAM
167730bc278Ssdussud * stack so we should only return failures or PAM_IGNORE. Returning PAM_SUCCESS
168730bc278Ssdussud * may short circuit the stack and circumvent later critical checks.
169730bc278Ssdussud *
17036e852a1SRaja Andra * we are called from pam_sm_setcred:
171730bc278Ssdussud * 1. if we are root (uid == 0), we do nothing and return
172730bc278Ssdussud * PAM_IGNORE.
173730bc278Ssdussud * 2. else, we try to establish credentials.
1747c478bd9Sstevel@tonic-gate *
175730bc278Ssdussud * We return framework errors as appropriate such as PAM_USER_UNKNOWN,
176730bc278Ssdussud * PAM_BUF_ERR, PAM_PERM_DENIED.
177730bc278Ssdussud *
178730bc278Ssdussud * If we succeed in establishing credentials we return PAM_IGNORE.
179730bc278Ssdussud *
180730bc278Ssdussud * If we fail to establish credentials then we return:
181730bc278Ssdussud * - PAM_SERVICE_ERR (credentials needed) or PAM_SYSTEM_ERR
182730bc278Ssdussud * (credentials not needed) if netname could not be created;
183730bc278Ssdussud * - PAM_AUTH_ERR (credentials needed) or PAM_IGNORE (credentials
184730bc278Ssdussud * not needed) if no credentials were retrieved;
185730bc278Ssdussud * - PAM_AUTH_ERR if the password didn't decrypt the cred;
1867c478bd9Sstevel@tonic-gate * - PAM_SYSTEM_ERR if the cred's could not be stored.
1877c478bd9Sstevel@tonic-gate *
1887c478bd9Sstevel@tonic-gate * This routine returns the user's netname in "netname".
1897c478bd9Sstevel@tonic-gate *
1907c478bd9Sstevel@tonic-gate * All tools--but the PAM stack--currently use getpass() to obtain
1917c478bd9Sstevel@tonic-gate * the user's secure RPC password. We must make sure we don't use more than
1927c478bd9Sstevel@tonic-gate * the first des_block (eight) characters of whatever is handed down to us.
1937c478bd9Sstevel@tonic-gate * Therefore, we use a local variable "short_pass" to hold those 8 char's.
1947c478bd9Sstevel@tonic-gate */
195573374d3Sjjj static int
establish_key(pam_handle_t * pamh,int flags,int debug,char * netname)19636e852a1SRaja Andra establish_key(pam_handle_t *pamh, int flags, int debug, char *netname)
1977c478bd9Sstevel@tonic-gate {
1987c478bd9Sstevel@tonic-gate char *user;
1997c478bd9Sstevel@tonic-gate char *passwd;
2007c478bd9Sstevel@tonic-gate char short_pass[sizeof (des_block)+1], *short_passp;
2017c478bd9Sstevel@tonic-gate int result;
2027c478bd9Sstevel@tonic-gate uid_t uid;
2037c478bd9Sstevel@tonic-gate gid_t gid;
2047c478bd9Sstevel@tonic-gate int err;
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate struct passwd pw; /* Needed to obtain uid */
2077c478bd9Sstevel@tonic-gate char *scratch;
2087c478bd9Sstevel@tonic-gate int scratchlen;
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate mechanism_t **mechs;
2117c478bd9Sstevel@tonic-gate mechanism_t **mpp;
2127c478bd9Sstevel@tonic-gate int get_seckey_cnt = 0;
2137c478bd9Sstevel@tonic-gate int set_seckey_cnt = 0;
2147c478bd9Sstevel@tonic-gate int good_pw_cnt = 0;
2157c478bd9Sstevel@tonic-gate int valid_mech_cnt = 0;
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate (void) pam_get_item(pamh, PAM_USER, (void **)&user);
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate if (user == NULL || *user == '\0') {
2207c478bd9Sstevel@tonic-gate if (debug)
2217c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: user NULL or empty");
2227c478bd9Sstevel@tonic-gate return (PAM_USER_UNKNOWN);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate (void) pam_get_item(pamh, PAM_AUTHTOK, (void **)&passwd);
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate scratchlen = sysconf(_SC_GETPW_R_SIZE_MAX);
2287c478bd9Sstevel@tonic-gate if ((scratch = malloc(scratchlen)) == NULL)
2297c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR);
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate if (getpwnam_r(user, &pw, scratch, scratchlen) == NULL) {
2327c478bd9Sstevel@tonic-gate result = PAM_USER_UNKNOWN;
2337c478bd9Sstevel@tonic-gate goto out;
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate uid = pw.pw_uid;
2377c478bd9Sstevel@tonic-gate gid = pw.pw_gid;
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate /*
2407c478bd9Sstevel@tonic-gate * We don't set credentials when root logs in.
2417c478bd9Sstevel@tonic-gate */
24236e852a1SRaja Andra if (uid == 0) {
2437c478bd9Sstevel@tonic-gate result = PAM_IGNORE;
2447c478bd9Sstevel@tonic-gate goto out;
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate err = user2netname(netname, uid, NULL);
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate if (err != 1) {
2507c478bd9Sstevel@tonic-gate if (debug)
2517c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: user2netname failed");
2527c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR;
2537c478bd9Sstevel@tonic-gate goto out;
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate /* passwd can be NULL (no passwd or su as root) */
2577c478bd9Sstevel@tonic-gate if (passwd) {
2587c478bd9Sstevel@tonic-gate (void) strlcpy(short_pass, passwd, sizeof (short_pass));
2597c478bd9Sstevel@tonic-gate short_passp = short_pass;
2607c478bd9Sstevel@tonic-gate } else
2617c478bd9Sstevel@tonic-gate short_passp = NULL;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate if (mechs = __nis_get_mechanisms(FALSE)) {
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate for (mpp = mechs; *mpp; mpp++) {
2667c478bd9Sstevel@tonic-gate mechanism_t *mp = *mpp;
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate if (AUTH_DES_COMPAT_CHK(mp))
2697c478bd9Sstevel@tonic-gate break; /* fall through to AUTH_DES below */
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate if (!VALID_MECH_ENTRY(mp))
2727c478bd9Sstevel@tonic-gate continue;
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate if (debug)
2757c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: trying "
2767c478bd9Sstevel@tonic-gate "key type = %d-%d", mp->keylen,
2777c478bd9Sstevel@tonic-gate mp->algtype);
2787c478bd9Sstevel@tonic-gate valid_mech_cnt++;
2797c478bd9Sstevel@tonic-gate if (!get_and_set_seckey(pamh, netname, mp->keylen,
280573374d3Sjjj mp->algtype, short_passp, uid, gid,
281573374d3Sjjj &get_seckey_cnt, &good_pw_cnt, &set_seckey_cnt,
28236e852a1SRaja Andra flags, debug)) {
2837c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR;
2847c478bd9Sstevel@tonic-gate goto out;
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate __nis_release_mechanisms(mechs);
2887c478bd9Sstevel@tonic-gate /* fall through to AUTH_DES below */
2897c478bd9Sstevel@tonic-gate } else {
2907c478bd9Sstevel@tonic-gate /*
29136e852a1SRaja Andra * No usable mechs found in security congifuration file thus
2927c478bd9Sstevel@tonic-gate * fallback to AUTH_DES compat.
2937c478bd9Sstevel@tonic-gate */
2947c478bd9Sstevel@tonic-gate if (debug)
2957c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: no valid mechs "
2967c478bd9Sstevel@tonic-gate "found. Trying AUTH_DES.");
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate /*
30036e852a1SRaja Andra * We always perform AUTH_DES for the benefit of services like NFS
30136e852a1SRaja Andra * that may depend on the classic des 192bit key being set.
3027c478bd9Sstevel@tonic-gate */
3037c478bd9Sstevel@tonic-gate if (!get_and_set_seckey(pamh, netname, AUTH_DES_KEYLEN,
3047c478bd9Sstevel@tonic-gate AUTH_DES_ALGTYPE, short_passp, uid, gid, &get_seckey_cnt,
30536e852a1SRaja Andra &good_pw_cnt, &set_seckey_cnt, flags, debug)) {
3067c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR;
3077c478bd9Sstevel@tonic-gate goto out;
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate if (debug) {
3117c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: mech key totals:\n");
3127c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: %d valid mechanism(s)",
3137c478bd9Sstevel@tonic-gate valid_mech_cnt);
3147c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: %d secret key(s) retrieved",
3157c478bd9Sstevel@tonic-gate get_seckey_cnt);
3167c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: %d passwd decrypt successes",
3177c478bd9Sstevel@tonic-gate good_pw_cnt);
3187c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: %d secret key(s) set",
3197c478bd9Sstevel@tonic-gate set_seckey_cnt);
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate if (get_seckey_cnt == 0) { /* No credentials */
32336e852a1SRaja Andra result = PAM_IGNORE;
3247c478bd9Sstevel@tonic-gate goto out;
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate if (good_pw_cnt == 0) { /* wrong password */
3287c478bd9Sstevel@tonic-gate result = PAM_AUTH_ERR;
3297c478bd9Sstevel@tonic-gate goto out;
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate if (set_seckey_cnt == 0) {
3337c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR;
3347c478bd9Sstevel@tonic-gate goto out;
3357c478bd9Sstevel@tonic-gate }
33636e852a1SRaja Andra /* Credentials have been successfully established, return PAM_IGNORE */
3377c478bd9Sstevel@tonic-gate result = PAM_IGNORE;
3387c478bd9Sstevel@tonic-gate out:
339730bc278Ssdussud /*
340730bc278Ssdussud * If we are authenticating we attempt to establish credentials
341730bc278Ssdussud * where appropriate. Failure to do so is only an error if we
342730bc278Ssdussud * definitely needed them. Thus always return PAM_IGNORE
343730bc278Ssdussud * if we are authenticating and credentials were not needed.
344730bc278Ssdussud */
3457c478bd9Sstevel@tonic-gate free(scratch);
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate (void) memset(short_pass, '\0', sizeof (short_pass));
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate return (result);
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate
35236e852a1SRaja Andra /*ARGSUSED*/
3537c478bd9Sstevel@tonic-gate int
pam_sm_authenticate(pam_handle_t * pamh,int flags,int argc,const char ** argv)3547c478bd9Sstevel@tonic-gate pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
3557c478bd9Sstevel@tonic-gate {
35636e852a1SRaja Andra return (PAM_IGNORE);
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate
359573374d3Sjjj
360573374d3Sjjj typedef struct argres {
361573374d3Sjjj uid_t uid;
362573374d3Sjjj int result;
363573374d3Sjjj } argres_t;
364573374d3Sjjj
365573374d3Sjjj /*
366573374d3Sjjj * Revoke NFS DES credentials.
367573374d3Sjjj * NFS may not be installed so we need to deal with SIGSYS
368573374d3Sjjj * when we call _nfssys(); we thus call _nfssys() in a seperate thread that
369573374d3Sjjj * is created specifically for this call. The thread specific signalmask
370573374d3Sjjj * is set to ignore SIGSYS. After the call to _nfssys(), the thread
371573374d3Sjjj * ceases to exist.
372573374d3Sjjj */
373573374d3Sjjj static void *
revoke_nfs_cred(void * ap)374573374d3Sjjj revoke_nfs_cred(void *ap)
375573374d3Sjjj {
376573374d3Sjjj struct nfs_revauth_args nra;
377573374d3Sjjj sigset_t isigset;
378573374d3Sjjj argres_t *argres = (argres_t *)ap;
379573374d3Sjjj
380573374d3Sjjj nra.authtype = AUTH_DES;
381573374d3Sjjj nra.uid = argres->uid;
382573374d3Sjjj
383573374d3Sjjj (void) sigemptyset(&isigset);
384573374d3Sjjj (void) sigaddset(&isigset, SIGSYS);
385573374d3Sjjj
386573374d3Sjjj if (pthread_sigmask(SIG_BLOCK, &isigset, NULL) == 0) {
387573374d3Sjjj argres->result = _nfssys(NFS_REVAUTH, &nra);
388573374d3Sjjj if (argres->result < 0 && errno == ENOSYS) {
389573374d3Sjjj argres->result = 0;
390573374d3Sjjj }
391573374d3Sjjj } else {
392573374d3Sjjj argres->result = -1;
393573374d3Sjjj }
394573374d3Sjjj return (NULL);
395573374d3Sjjj }
396573374d3Sjjj
397573374d3Sjjj static int
remove_key(pam_handle_t * pamh,int flags,int debug)3987c478bd9Sstevel@tonic-gate remove_key(pam_handle_t *pamh, int flags, int debug)
3997c478bd9Sstevel@tonic-gate {
4007c478bd9Sstevel@tonic-gate int result;
4017c478bd9Sstevel@tonic-gate char *uname;
4027c478bd9Sstevel@tonic-gate attrlist attr_pw[2];
4037c478bd9Sstevel@tonic-gate struct pam_repository *auth_rep = NULL;
4047c478bd9Sstevel@tonic-gate pwu_repository_t *pwu_rep;
4057c478bd9Sstevel@tonic-gate uid_t uid;
4067c478bd9Sstevel@tonic-gate gid_t gid;
407573374d3Sjjj argres_t argres;
408*93050252SRaja Andra pthread_t tid;
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate (void) pam_get_item(pamh, PAM_USER, (void **)&uname);
4117c478bd9Sstevel@tonic-gate if (uname == NULL || *uname == NULL) {
4127c478bd9Sstevel@tonic-gate if (debug)
4137c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG,
4147c478bd9Sstevel@tonic-gate "pam_dhkeys: user NULL or empty in remove_key()");
4157c478bd9Sstevel@tonic-gate return (PAM_USER_UNKNOWN);
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate if (strcmp(uname, "root") == 0) {
4197c478bd9Sstevel@tonic-gate if ((flags & PAM_SILENT) == 0) {
4207c478bd9Sstevel@tonic-gate char msg[3][PAM_MAX_MSG_SIZE];
4217c478bd9Sstevel@tonic-gate (void) snprintf(msg[0], sizeof (msg[0]),
4227c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
4237c478bd9Sstevel@tonic-gate "removing root credentials would"
4247c478bd9Sstevel@tonic-gate " break the rpc services that"));
4257c478bd9Sstevel@tonic-gate (void) snprintf(msg[1], sizeof (msg[1]),
4267c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
4277c478bd9Sstevel@tonic-gate "use secure rpc on this host!"));
4287c478bd9Sstevel@tonic-gate (void) snprintf(msg[2], sizeof (msg[2]),
4297c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
4307c478bd9Sstevel@tonic-gate "root may use keylogout -f to do"
4317c478bd9Sstevel@tonic-gate " this (at your own risk)!"));
4327c478bd9Sstevel@tonic-gate (void) __pam_display_msg(pamh, PAM_ERROR_MSG, 3,
4337c478bd9Sstevel@tonic-gate msg, NULL);
4347c478bd9Sstevel@tonic-gate }
4357c478bd9Sstevel@tonic-gate return (PAM_PERM_DENIED);
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate (void) pam_get_item(pamh, PAM_REPOSITORY, (void **)&auth_rep);
4397c478bd9Sstevel@tonic-gate if (auth_rep != NULL) {
4407c478bd9Sstevel@tonic-gate if ((pwu_rep = calloc(1, sizeof (*pwu_rep))) == NULL)
4417c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR);
4427c478bd9Sstevel@tonic-gate pwu_rep->type = auth_rep->type;
4437c478bd9Sstevel@tonic-gate pwu_rep->scope = auth_rep->scope;
4447c478bd9Sstevel@tonic-gate pwu_rep->scope_len = auth_rep->scope_len;
4457c478bd9Sstevel@tonic-gate } else
4467c478bd9Sstevel@tonic-gate pwu_rep = PWU_DEFAULT_REP;
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate /* Retrieve user's uid/gid from the password repository */
4497c478bd9Sstevel@tonic-gate attr_pw[0].type = ATTR_UID; attr_pw[0].next = &attr_pw[1];
4507c478bd9Sstevel@tonic-gate attr_pw[1].type = ATTR_GID; attr_pw[1].next = NULL;
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate result = __get_authtoken_attr(uname, pwu_rep, attr_pw);
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate if (pwu_rep != PWU_DEFAULT_REP)
4557c478bd9Sstevel@tonic-gate free(pwu_rep);
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate if (result == PWU_NOT_FOUND)
4587c478bd9Sstevel@tonic-gate return (PAM_USER_UNKNOWN);
4597c478bd9Sstevel@tonic-gate if (result == PWU_DENIED)
4607c478bd9Sstevel@tonic-gate return (PAM_PERM_DENIED);
4617c478bd9Sstevel@tonic-gate if (result != PWU_SUCCESS)
4627c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate uid = (uid_t)attr_pw[0].data.val_i;
4657c478bd9Sstevel@tonic-gate gid = (gid_t)attr_pw[1].data.val_i;
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate (void) key_removesecret_g_uid(uid, gid);
4687c478bd9Sstevel@tonic-gate
469573374d3Sjjj argres.uid = uid;
470573374d3Sjjj argres.result = -1;
4717c478bd9Sstevel@tonic-gate
472573374d3Sjjj if (pthread_create(&tid, NULL, revoke_nfs_cred, (void *)&argres) == 0)
473573374d3Sjjj (void) pthread_join(tid, NULL);
474573374d3Sjjj
475573374d3Sjjj if (argres.result < 0) {
4767c478bd9Sstevel@tonic-gate if ((flags & PAM_SILENT) == 0) {
4777c478bd9Sstevel@tonic-gate (void) msg(pamh, dgettext(TEXT_DOMAIN,
4787c478bd9Sstevel@tonic-gate "Warning: NFS credentials not destroyed"));
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate return (PAM_AUTH_ERR);
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate return (PAM_IGNORE);
4847c478bd9Sstevel@tonic-gate }
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate int
pam_sm_setcred(pam_handle_t * pamh,int flags,int argc,const char ** argv)4877c478bd9Sstevel@tonic-gate pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
4887c478bd9Sstevel@tonic-gate {
4897c478bd9Sstevel@tonic-gate int i;
4907c478bd9Sstevel@tonic-gate int debug = 0;
4917c478bd9Sstevel@tonic-gate int result;
4927c478bd9Sstevel@tonic-gate char netname[MAXNETNAMELEN + 1];
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) {
4957c478bd9Sstevel@tonic-gate if (strcmp(argv[i], "debug") == 0)
4967c478bd9Sstevel@tonic-gate debug = 1;
4977c478bd9Sstevel@tonic-gate else if (strcmp(argv[i], "nowarn") == 0)
4987c478bd9Sstevel@tonic-gate flags |= PAM_SILENT;
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate /* Check for invalid flags */
5027c478bd9Sstevel@tonic-gate if (flags && (flags & PAM_ESTABLISH_CRED) == 0 &&
5037c478bd9Sstevel@tonic-gate (flags & PAM_REINITIALIZE_CRED) == 0 &&
5047c478bd9Sstevel@tonic-gate (flags & PAM_REFRESH_CRED) == 0 &&
5057c478bd9Sstevel@tonic-gate (flags & PAM_DELETE_CRED) == 0 &&
5067c478bd9Sstevel@tonic-gate (flags & PAM_SILENT) == 0) {
5077c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "pam_dhkeys: pam_setcred: illegal flags %d",
5087c478bd9Sstevel@tonic-gate flags);
5097c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate if ((flags & PAM_REINITIALIZE_CRED) || (flags & PAM_REFRESH_CRED)) {
5147c478bd9Sstevel@tonic-gate /* doesn't apply to UNIX */
5157c478bd9Sstevel@tonic-gate if (debug)
5167c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: cred reinit/refresh "
5177c478bd9Sstevel@tonic-gate "ignored\n");
5187c478bd9Sstevel@tonic-gate return (PAM_IGNORE);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate if (flags & PAM_DELETE_CRED) {
5227c478bd9Sstevel@tonic-gate if (debug)
5237c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: removing creds\n");
5247c478bd9Sstevel@tonic-gate result = remove_key(pamh, flags, debug);
5257c478bd9Sstevel@tonic-gate } else {
52636e852a1SRaja Andra result = establish_key(pamh, flags, debug, netname);
5277c478bd9Sstevel@tonic-gate /* Some diagnostics */
5287c478bd9Sstevel@tonic-gate if ((flags & PAM_SILENT) == 0) {
5297c478bd9Sstevel@tonic-gate if (result == PAM_AUTH_ERR)
5307c478bd9Sstevel@tonic-gate (void) msg(pamh, dgettext(TEXT_DOMAIN,
5317c478bd9Sstevel@tonic-gate "Password does not decrypt any secret "
5327c478bd9Sstevel@tonic-gate "keys for %s."), netname);
5337c478bd9Sstevel@tonic-gate else if (result == PAM_SYSTEM_ERR && netname[0])
5347c478bd9Sstevel@tonic-gate (void) msg(pamh, dgettext(TEXT_DOMAIN,
5357c478bd9Sstevel@tonic-gate "Could not set secret key(s) for %s. "
5367c478bd9Sstevel@tonic-gate "The key server may be down."), netname);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate /* Not having credentials set is not an error... */
5407c478bd9Sstevel@tonic-gate result = PAM_IGNORE;
5417c478bd9Sstevel@tonic-gate }
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate return (result);
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5477c478bd9Sstevel@tonic-gate void
rpc_cleanup(pam_handle_t * pamh,void * data,int pam_status)5487c478bd9Sstevel@tonic-gate rpc_cleanup(pam_handle_t *pamh, void *data, int pam_status)
5497c478bd9Sstevel@tonic-gate {
5507c478bd9Sstevel@tonic-gate if (data) {
5517c478bd9Sstevel@tonic-gate (void) memset(data, 0, strlen(data));
5527c478bd9Sstevel@tonic-gate free(data);
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate
55636e852a1SRaja Andra /*ARGSUSED*/
5577c478bd9Sstevel@tonic-gate int
pam_sm_chauthtok(pam_handle_t * pamh,int flags,int argc,const char ** argv)5587c478bd9Sstevel@tonic-gate pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
5597c478bd9Sstevel@tonic-gate {
5607c478bd9Sstevel@tonic-gate return (PAM_IGNORE);
5617c478bd9Sstevel@tonic-gate }
562