Home | History | Annotate | Download | only in sample
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <security/pam_appl.h>
     30 #include <security/pam_modules.h>
     31 #include <string.h>
     32 #include <stdio.h>
     33 #include <stdlib.h>
     34 #include <sys/types.h>
     35 #include <pwd.h>
     36 #include <syslog.h>
     37 #include <libintl.h>
     38 
     39 #include "sample_utils.h"
     40 
     41 /*
     42  *
     43  * Sample module for pam_sm_authenticate.
     44  *
     45  * options -
     46  *
     47  *	debug
     48  *	use_first_pass
     49  *	try_first_pass
     50  *	first_pass_good  (first password is always good when used with use/try)
     51  *	first_pass_bad   (first password is always bad when used with use/try)
     52  *	pass=foobar	 (set good password to "foobar". default good password
     53  *			 is test)
     54  *	always_fail	 always return PAM_AUTH_ERR
     55  *	always_succeed   always return PAM_SUCCESS
     56  *	always_ignore
     57  *
     58  *
     59  */
     60 
     61 /*
     62  * pam_sm_authenticate		- Authenticate user
     63  */
     64 /*ARGSUSED*/
     65 int
     66 pam_sm_authenticate(
     67 	pam_handle_t		*pamh,
     68 	int 			flags,
     69 	int			argc,
     70 	const char		**argv)
     71 {
     72 	char			*user;
     73 	struct pam_conv 	*pam_convp;
     74 	int			err, result = PAM_AUTH_ERR;
     75 	struct pam_response 	*ret_resp = (struct pam_response *)0;
     76 	char 			messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
     77 	int			debug = 0;
     78 	int			try_first_pass = 0;
     79 	int			use_first_pass = 0;
     80 	int			first_pass_good = 0;
     81 	int			first_pass_bad = 0;
     82 	int			i, num_msg;
     83 	char			*firstpass, *password;
     84 	char			the_password[64];
     85 
     86 	if (debug)
     87 		syslog(LOG_DEBUG, "Sample Authentication\n");
     88 
     89 	(void) strcpy(the_password, "test");
     90 
     91 	for (i = 0; i < argc; i++) {
     92 		if (strcmp(argv[i], "debug") == 0)
     93 			debug = 1;
     94 		else if (strcmp(argv[i], "try_first_pass") == 0)
     95 			try_first_pass = 1;
     96 		else if (strcmp(argv[i], "first_pass_good") == 0)
     97 			first_pass_good = 1;
     98 		else if (strcmp(argv[i], "first_pass_bad") == 0)
     99 			first_pass_bad = 1;
    100 		else if (strcmp(argv[i], "use_first_pass") == 0)
    101 			use_first_pass = 1;
    102 		else if (strcmp(argv[i], "always_fail") == 0)
    103 			return (PAM_AUTH_ERR);
    104 		else if (strcmp(argv[i], "always_succeed") == 0)
    105 			return (PAM_SUCCESS);
    106 		else if (strcmp(argv[i], "always_ignore") == 0)
    107 			return (PAM_IGNORE);
    108 		else if (sscanf(argv[i], "pass=%64s", the_password) == 1) {
    109 			/*EMPTY*/;
    110 		}
    111 		else
    112 			syslog(LOG_DEBUG, "illegal scheme option %s", argv[i]);
    113 	}
    114 
    115 	err = pam_get_user(pamh, &user, NULL);
    116 	if (err != PAM_SUCCESS)
    117 		return (err);
    118 
    119 	err = pam_get_item(pamh, PAM_CONV, (void**) &pam_convp);
    120 	if (err != PAM_SUCCESS)
    121 		return (err);
    122 
    123 	(void) pam_get_item(pamh, PAM_AUTHTOK, (void **) &firstpass);
    124 
    125 	if (firstpass && (use_first_pass || try_first_pass)) {
    126 
    127 		if ((first_pass_good ||
    128 			strncmp(firstpass, the_password,
    129 				strlen(the_password)) == 0) &&
    130 				!first_pass_bad) {
    131 					result = PAM_SUCCESS;
    132 					goto out;
    133 		}
    134 		if (use_first_pass) goto out;
    135 	}
    136 
    137 	/*
    138 	 * Get the password from the user
    139 	 */
    140 	if (firstpass) {
    141 		(void) snprintf(messages[0], sizeof (messages[0]),
    142 			dgettext(TEXT_DOMAIN, "TEST Password: "));
    143 	} else {
    144 		(void) snprintf(messages[0], sizeof (messages[0]),
    145 			dgettext(TEXT_DOMAIN, "Password: "));
    146 	}
    147 	num_msg = 1;
    148 	err = __get_authtok(pam_convp->conv,
    149 				num_msg, messages, NULL, &ret_resp);
    150 
    151 	if (err != PAM_SUCCESS) {
    152 		result = err;
    153 		goto out;
    154 	}
    155 
    156 	password = ret_resp->resp;
    157 
    158 	if (password == NULL) {
    159 		result = PAM_AUTH_ERR;
    160 		goto out;
    161 	}
    162 
    163 	/* one last ditch attempt to "login" to TEST */
    164 
    165 	if (strncmp(password, the_password, strlen(the_password)) == 0) {
    166 		result = PAM_SUCCESS;
    167 		if (firstpass == NULL) {
    168 			/* this is the first password, stash it away */
    169 			(void) pam_set_item(pamh, PAM_AUTHTOK, password);
    170 		}
    171 	}
    172 
    173 out:
    174 	if (num_msg > 0) {
    175 		if (ret_resp != 0) {
    176 			if (ret_resp->resp != 0) {
    177 				/* avoid leaving password cleartext around */
    178 				(void) memset(ret_resp->resp, 0,
    179 					strlen(ret_resp->resp));
    180 			}
    181 			__free_resp(num_msg, ret_resp);
    182 			ret_resp = 0;
    183 		}
    184 	}
    185 
    186 	return (result);
    187 }
    188