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,
127573374d3Sjjj 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: "
132573374d3Sjjj "get_and_set_seckey: could not "
133573374d3Sjjj "set secret key for keytype "
134573374d3Sjjj "%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,
141573374d3Sjjj "Password does not "
142573374d3Sjjj "decrypt secret key (type = %d-%d) "
143573374d3Sjjj "for '%s'."), keylen, algtype, netname);
1447c478bd9Sstevel@tonic-gate (void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1,
145573374d3Sjjj 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: "
151573374d3Sjjj "could not get secret key for keytype %d-%d",
152573374d3Sjjj 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:
17136e852a1SRaja Andra * 1. if we are root (uid == 0), we do nothing and return
17236e852a1SRaja Andra * PAM_IGNORE.
17336e852a1SRaja Andra * 2. else, we try to establish credentials.
1747c478bd9Sstevel@tonic-gate *
17536e852a1SRaja Andra * We return framework errors as appropriate such as PAM_USER_UNKNOWN,
17636e852a1SRaja Andra * PAM_BUF_ERR, PAM_PERM_DENIED.
177730bc278Ssdussud *
17836e852a1SRaja Andra * If we succeed in establishing credentials we return PAM_IGNORE.
1797c478bd9Sstevel@tonic-gate *
18036e852a1SRaja Andra * If we fail to establish credentials then we return:
18136e852a1SRaja Andra * - PAM_SERVICE_ERR (credentials needed) or PAM_SYSTEM_ERR
18236e852a1SRaja Andra * (credentials not needed) if netname could not be created;
18336e852a1SRaja Andra * - PAM_AUTH_ERR (credentials needed) or PAM_IGNORE (credentials
18436e852a1SRaja Andra * not needed) if no credentials were retrieved;
18536e852a1SRaja Andra * - PAM_AUTH_ERR if the password didn't decrypt the cred;
18636e852a1SRaja Andra * - 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
24736e852a1SRaja Andra 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");
252504dd8f6SToomas Soome 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;
260*d6469564SToomas Soome } else {
2617c478bd9Sstevel@tonic-gate short_passp = NULL;
262*d6469564SToomas Soome }
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate if (mechs = __nis_get_mechanisms(FALSE)) {
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate for (mpp = mechs; *mpp; mpp++) {
2677c478bd9Sstevel@tonic-gate mechanism_t *mp = *mpp;
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate if (AUTH_DES_COMPAT_CHK(mp))
2707c478bd9Sstevel@tonic-gate break; /* fall through to AUTH_DES below */
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate if (!VALID_MECH_ENTRY(mp))
2737c478bd9Sstevel@tonic-gate continue;
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate if (debug)
2767c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: trying "
277573374d3Sjjj "key type = %d-%d", mp->keylen,
278573374d3Sjjj mp->algtype);
2797c478bd9Sstevel@tonic-gate valid_mech_cnt++;
2807c478bd9Sstevel@tonic-gate if (!get_and_set_seckey(pamh, netname, mp->keylen,
281573374d3Sjjj mp->algtype, short_passp, uid, gid,
282573374d3Sjjj &get_seckey_cnt, &good_pw_cnt, &set_seckey_cnt,
28336e852a1SRaja Andra flags, debug)) {
2847c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR;
2857c478bd9Sstevel@tonic-gate goto out;
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate __nis_release_mechanisms(mechs);
2897c478bd9Sstevel@tonic-gate /* fall through to AUTH_DES below */
2907c478bd9Sstevel@tonic-gate } else {
2917c478bd9Sstevel@tonic-gate /*
29236e852a1SRaja Andra * No usable mechs found in security congifuration file thus
2937c478bd9Sstevel@tonic-gate * fallback to AUTH_DES compat.
2947c478bd9Sstevel@tonic-gate */
2957c478bd9Sstevel@tonic-gate if (debug)
2967c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: no valid mechs "
297573374d3Sjjj "found. Trying AUTH_DES.");
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate /*
30136e852a1SRaja Andra * We always perform AUTH_DES for the benefit of services like NFS
30236e852a1SRaja Andra * that may depend on the classic des 192bit key being set.
3037c478bd9Sstevel@tonic-gate */
3047c478bd9Sstevel@tonic-gate if (!get_and_set_seckey(pamh, netname, AUTH_DES_KEYLEN,
3057c478bd9Sstevel@tonic-gate AUTH_DES_ALGTYPE, short_passp, uid, gid, &get_seckey_cnt,
30636e852a1SRaja Andra &good_pw_cnt, &set_seckey_cnt, flags, debug)) {
3077c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR;
3087c478bd9Sstevel@tonic-gate goto out;
3097c478bd9Sstevel@tonic-gate }
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate if (debug) {
3127c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: mech key totals:\n");
3137c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: %d valid mechanism(s)",
314573374d3Sjjj valid_mech_cnt);
3157c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: %d secret key(s) retrieved",
316573374d3Sjjj get_seckey_cnt);
3177c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: %d passwd decrypt successes",
318573374d3Sjjj good_pw_cnt);
3197c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: %d secret key(s) set",
320573374d3Sjjj set_seckey_cnt);
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate if (get_seckey_cnt == 0) { /* No credentials */
32436e852a1SRaja Andra result = PAM_IGNORE;
3257c478bd9Sstevel@tonic-gate goto out;
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate if (good_pw_cnt == 0) { /* wrong password */
329730bc278Ssdussud result = PAM_AUTH_ERR;
3307c478bd9Sstevel@tonic-gate goto out;
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate if (set_seckey_cnt == 0) {
334730bc278Ssdussud result = PAM_SYSTEM_ERR;
3357c478bd9Sstevel@tonic-gate goto out;
3367c478bd9Sstevel@tonic-gate }
33736e852a1SRaja Andra /* Credentials have been successfully established, return PAM_IGNORE */
3387c478bd9Sstevel@tonic-gate result = PAM_IGNORE;
3397c478bd9Sstevel@tonic-gate out:
340730bc278Ssdussud /*
341730bc278Ssdussud * If we are authenticating we attempt to establish credentials
342730bc278Ssdussud * where appropriate. Failure to do so is only an error if we
343730bc278Ssdussud * definitely needed them. Thus always return PAM_IGNORE
344730bc278Ssdussud * if we are authenticating and credentials were not needed.
345730bc278Ssdussud */
3467c478bd9Sstevel@tonic-gate free(scratch);
3477c478bd9Sstevel@tonic-gate
3487c478bd9Sstevel@tonic-gate (void) memset(short_pass, '\0', sizeof (short_pass));
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate return (result);
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate
35336e852a1SRaja Andra /*ARGSUSED*/
3547c478bd9Sstevel@tonic-gate int
pam_sm_authenticate(pam_handle_t * pamh,int flags,int argc,const char ** argv)3557c478bd9Sstevel@tonic-gate pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
3567c478bd9Sstevel@tonic-gate {
35736e852a1SRaja Andra return (PAM_IGNORE);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate
360573374d3Sjjj
361573374d3Sjjj typedef struct argres {
362573374d3Sjjj uid_t uid;
363573374d3Sjjj int result;
364573374d3Sjjj } argres_t;
365573374d3Sjjj
366573374d3Sjjj /*
367573374d3Sjjj * Revoke NFS DES credentials.
368573374d3Sjjj * NFS may not be installed so we need to deal with SIGSYS
369573374d3Sjjj * when we call _nfssys(); we thus call _nfssys() in a seperate thread that
370573374d3Sjjj * is created specifically for this call. The thread specific signalmask
371573374d3Sjjj * is set to ignore SIGSYS. After the call to _nfssys(), the thread
372573374d3Sjjj * ceases to exist.
373573374d3Sjjj */
374573374d3Sjjj static void *
revoke_nfs_cred(void * ap)375573374d3Sjjj revoke_nfs_cred(void *ap)
376573374d3Sjjj {
377573374d3Sjjj struct nfs_revauth_args nra;
378573374d3Sjjj sigset_t isigset;
379573374d3Sjjj argres_t *argres = (argres_t *)ap;
380573374d3Sjjj
381573374d3Sjjj nra.authtype = AUTH_DES;
382573374d3Sjjj nra.uid = argres->uid;
383573374d3Sjjj
384573374d3Sjjj (void) sigemptyset(&isigset);
385573374d3Sjjj (void) sigaddset(&isigset, SIGSYS);
386573374d3Sjjj
387573374d3Sjjj if (pthread_sigmask(SIG_BLOCK, &isigset, NULL) == 0) {
388573374d3Sjjj argres->result = _nfssys(NFS_REVAUTH, &nra);
389573374d3Sjjj if (argres->result < 0 && errno == ENOSYS) {
390573374d3Sjjj argres->result = 0;
391573374d3Sjjj }
392573374d3Sjjj } else {
393573374d3Sjjj argres->result = -1;
394573374d3Sjjj }
395573374d3Sjjj return (NULL);
396573374d3Sjjj }
397573374d3Sjjj
398573374d3Sjjj static int
remove_key(pam_handle_t * pamh,int flags,int debug)3997c478bd9Sstevel@tonic-gate remove_key(pam_handle_t *pamh, int flags, int debug)
4007c478bd9Sstevel@tonic-gate {
4017c478bd9Sstevel@tonic-gate int result;
4027c478bd9Sstevel@tonic-gate char *uname;
4037c478bd9Sstevel@tonic-gate attrlist attr_pw[2];
4047c478bd9Sstevel@tonic-gate struct pam_repository *auth_rep = NULL;
4057c478bd9Sstevel@tonic-gate pwu_repository_t *pwu_rep;
4067c478bd9Sstevel@tonic-gate uid_t uid;
4077c478bd9Sstevel@tonic-gate gid_t gid;
408573374d3Sjjj argres_t argres;
40993050252SRaja Andra pthread_t tid;
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate (void) pam_get_item(pamh, PAM_USER, (void **)&uname);
412*d6469564SToomas Soome if (uname == NULL || *uname == '\0') {
4137c478bd9Sstevel@tonic-gate if (debug)
4147c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG,
4157c478bd9Sstevel@tonic-gate "pam_dhkeys: user NULL or empty in remove_key()");
4167c478bd9Sstevel@tonic-gate return (PAM_USER_UNKNOWN);
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate if (strcmp(uname, "root") == 0) {
4207c478bd9Sstevel@tonic-gate if ((flags & PAM_SILENT) == 0) {
4217c478bd9Sstevel@tonic-gate char msg[3][PAM_MAX_MSG_SIZE];
4227c478bd9Sstevel@tonic-gate (void) snprintf(msg[0], sizeof (msg[0]),
4237c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
424573374d3Sjjj "removing root credentials would"
425573374d3Sjjj " break the rpc services that"));
4267c478bd9Sstevel@tonic-gate (void) snprintf(msg[1], sizeof (msg[1]),
4277c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
428573374d3Sjjj "use secure rpc on this host!"));
4297c478bd9Sstevel@tonic-gate (void) snprintf(msg[2], sizeof (msg[2]),
4307c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
431573374d3Sjjj "root may use keylogout -f to do"
432573374d3Sjjj " this (at your own risk)!"));
4337c478bd9Sstevel@tonic-gate (void) __pam_display_msg(pamh, PAM_ERROR_MSG, 3,
4347c478bd9Sstevel@tonic-gate msg, NULL);
4357c478bd9Sstevel@tonic-gate }
4367c478bd9Sstevel@tonic-gate return (PAM_PERM_DENIED);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate (void) pam_get_item(pamh, PAM_REPOSITORY, (void **)&auth_rep);
4407c478bd9Sstevel@tonic-gate if (auth_rep != NULL) {
4417c478bd9Sstevel@tonic-gate if ((pwu_rep = calloc(1, sizeof (*pwu_rep))) == NULL)
4427c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR);
4437c478bd9Sstevel@tonic-gate pwu_rep->type = auth_rep->type;
4447c478bd9Sstevel@tonic-gate pwu_rep->scope = auth_rep->scope;
4457c478bd9Sstevel@tonic-gate pwu_rep->scope_len = auth_rep->scope_len;
446*d6469564SToomas Soome } else {
4477c478bd9Sstevel@tonic-gate pwu_rep = PWU_DEFAULT_REP;
448*d6469564SToomas Soome }
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate /* Retrieve user's uid/gid from the password repository */
4517c478bd9Sstevel@tonic-gate attr_pw[0].type = ATTR_UID; attr_pw[0].next = &attr_pw[1];
4527c478bd9Sstevel@tonic-gate attr_pw[1].type = ATTR_GID; attr_pw[1].next = NULL;
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate result = __get_authtoken_attr(uname, pwu_rep, attr_pw);
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate if (pwu_rep != PWU_DEFAULT_REP)
4577c478bd9Sstevel@tonic-gate free(pwu_rep);
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate if (result == PWU_NOT_FOUND)
4607c478bd9Sstevel@tonic-gate return (PAM_USER_UNKNOWN);
4617c478bd9Sstevel@tonic-gate if (result == PWU_DENIED)
4627c478bd9Sstevel@tonic-gate return (PAM_PERM_DENIED);
4637c478bd9Sstevel@tonic-gate if (result != PWU_SUCCESS)
4647c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate uid = (uid_t)attr_pw[0].data.val_i;
4677c478bd9Sstevel@tonic-gate gid = (gid_t)attr_pw[1].data.val_i;
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate (void) key_removesecret_g_uid(uid, gid);
4707c478bd9Sstevel@tonic-gate
471573374d3Sjjj argres.uid = uid;
472573374d3Sjjj argres.result = -1;
473573374d3Sjjj
474573374d3Sjjj if (pthread_create(&tid, NULL, revoke_nfs_cred, (void *)&argres) == 0)
475573374d3Sjjj (void) pthread_join(tid, NULL);
4767c478bd9Sstevel@tonic-gate
477573374d3Sjjj if (argres.result < 0) {
4787c478bd9Sstevel@tonic-gate if ((flags & PAM_SILENT) == 0) {
4797c478bd9Sstevel@tonic-gate (void) msg(pamh, dgettext(TEXT_DOMAIN,
480573374d3Sjjj "Warning: NFS credentials not destroyed"));
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate return (PAM_AUTH_ERR);
4837c478bd9Sstevel@tonic-gate }
4847c478bd9Sstevel@tonic-gate
4857c478bd9Sstevel@tonic-gate return (PAM_IGNORE);
4867c478bd9Sstevel@tonic-gate }
4877c478bd9Sstevel@tonic-gate
4887c478bd9Sstevel@tonic-gate int
pam_sm_setcred(pam_handle_t * pamh,int flags,int argc,const char ** argv)4897c478bd9Sstevel@tonic-gate pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
4907c478bd9Sstevel@tonic-gate {
4917c478bd9Sstevel@tonic-gate int i;
4927c478bd9Sstevel@tonic-gate int debug = 0;
4937c478bd9Sstevel@tonic-gate int result;
4947c478bd9Sstevel@tonic-gate char netname[MAXNETNAMELEN + 1];
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) {
4977c478bd9Sstevel@tonic-gate if (strcmp(argv[i], "debug") == 0)
4987c478bd9Sstevel@tonic-gate debug = 1;
4997c478bd9Sstevel@tonic-gate else if (strcmp(argv[i], "nowarn") == 0)
5007c478bd9Sstevel@tonic-gate flags |= PAM_SILENT;
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gate /* Check for invalid flags */
5047c478bd9Sstevel@tonic-gate if (flags && (flags & PAM_ESTABLISH_CRED) == 0 &&
505573374d3Sjjj (flags & PAM_REINITIALIZE_CRED) == 0 &&
506573374d3Sjjj (flags & PAM_REFRESH_CRED) == 0 &&
507573374d3Sjjj (flags & PAM_DELETE_CRED) == 0 &&
508573374d3Sjjj (flags & PAM_SILENT) == 0) {
5097c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "pam_dhkeys: pam_setcred: illegal flags %d",
510573374d3Sjjj flags);
5117c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
5127c478bd9Sstevel@tonic-gate }
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate if ((flags & PAM_REINITIALIZE_CRED) || (flags & PAM_REFRESH_CRED)) {
5167c478bd9Sstevel@tonic-gate /* doesn't apply to UNIX */
5177c478bd9Sstevel@tonic-gate if (debug)
5187c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: cred reinit/refresh "
5197c478bd9Sstevel@tonic-gate "ignored\n");
5207c478bd9Sstevel@tonic-gate return (PAM_IGNORE);
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate if (flags & PAM_DELETE_CRED) {
5247c478bd9Sstevel@tonic-gate if (debug)
5257c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_dhkeys: removing creds\n");
5267c478bd9Sstevel@tonic-gate result = remove_key(pamh, flags, debug);
5277c478bd9Sstevel@tonic-gate } else {
52836e852a1SRaja Andra result = establish_key(pamh, flags, debug, netname);
5297c478bd9Sstevel@tonic-gate /* Some diagnostics */
5307c478bd9Sstevel@tonic-gate if ((flags & PAM_SILENT) == 0) {
5317c478bd9Sstevel@tonic-gate if (result == PAM_AUTH_ERR)
5327c478bd9Sstevel@tonic-gate (void) msg(pamh, dgettext(TEXT_DOMAIN,
5337c478bd9Sstevel@tonic-gate "Password does not decrypt any secret "
5347c478bd9Sstevel@tonic-gate "keys for %s."), netname);
5357c478bd9Sstevel@tonic-gate else if (result == PAM_SYSTEM_ERR && netname[0])
5367c478bd9Sstevel@tonic-gate (void) msg(pamh, dgettext(TEXT_DOMAIN,
5377c478bd9Sstevel@tonic-gate "Could not set secret key(s) for %s. "
5387c478bd9Sstevel@tonic-gate "The key server may be down."), netname);
5397c478bd9Sstevel@tonic-gate }
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate /* Not having credentials set is not an error... */
5427c478bd9Sstevel@tonic-gate result = PAM_IGNORE;
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate
5457c478bd9Sstevel@tonic-gate return (result);
5467c478bd9Sstevel@tonic-gate }
5477c478bd9Sstevel@tonic-gate
5487c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5497c478bd9Sstevel@tonic-gate void
rpc_cleanup(pam_handle_t * pamh,void * data,int pam_status)5507c478bd9Sstevel@tonic-gate rpc_cleanup(pam_handle_t *pamh, void *data, int pam_status)
5517c478bd9Sstevel@tonic-gate {
5527c478bd9Sstevel@tonic-gate if (data) {
5537c478bd9Sstevel@tonic-gate (void) memset(data, 0, strlen(data));
5547c478bd9Sstevel@tonic-gate free(data);
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate
55836e852a1SRaja Andra /*ARGSUSED*/
5597c478bd9Sstevel@tonic-gate int
pam_sm_chauthtok(pam_handle_t * pamh,int flags,int argc,const char ** argv)5607c478bd9Sstevel@tonic-gate pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
5617c478bd9Sstevel@tonic-gate {
56236e852a1SRaja Andra return (PAM_IGNORE);
5637c478bd9Sstevel@tonic-gate }
564