Example #1
0
/*
 * Function: krb5_changepw
 *
 * Purpose: Initialize and call lower level routines to change a password
 *
 * Arguments:
 *
 *	princ_str	principal name to use, optional
 *	old_password 	old password
 *	new_password  	new password
 *
 * Returns:
 *                      exit status of PAM_SUCCESS for success
 *			1 principal unknown
 *			2 old password wrong
 *			3 cannot initialize admin server session
 *			4 new passwd mismatch or error trying to change pw
 *                      5 password not typed
 *                      6 misc error
 *                      7 incorrect usage
 *
 * Requires:
 *	Passwords cannot be more than 255 characters long.
 *
 * Modifies:
 *
 * Changes the principal's password.
 *
 */
static int
krb5_changepw(
	pam_handle_t *pamh,
	char *princ_str,
	char *old_password,
	char *new_password,
	int debug)
{
	kadm5_ret_t		code;
	krb5_principal 		princ = 0;
	char 			msg_ret[1024], admin_realm[1024];
	char			kprinc[2*MAXHOSTNAMELEN];
	char			*cpw_service;
	kadm5_principal_ent_rec principal_entry;
	kadm5_policy_ent_rec	policy_entry;
	void 			*server_handle;
	krb5_context		context;
	kadm5_config_params	params;

	(void) memset((char *)&params, 0, sizeof (params));
	(void) memset(&principal_entry, 0, sizeof (principal_entry));
	(void) memset(&policy_entry, 0, sizeof (policy_entry));

	if (code = krb5_init_context(&context)) {
		return (6);
	}

	if ((code = get_kmd_kuser(context, (const char *)princ_str, kprinc,
		2*MAXHOSTNAMELEN)) != 0) {
		return (code);
	}

	/* Need to get a krb5_principal struct */

	code = krb5_parse_name(context, kprinc, &princ);

	if (code != 0) {
		return (MISC_EXIT_STATUS);
	}

	if (strlen(old_password) == 0) {
		krb5_free_principal(context, princ);
		return (5);
	}

	(void) snprintf(admin_realm, sizeof (admin_realm), "%s",
		krb5_princ_realm(context, princ)->data);
	params.mask |= KADM5_CONFIG_REALM;
	params.realm = admin_realm;


	if (kadm5_get_cpw_host_srv_name(context, admin_realm, &cpw_service)) {
		syslog(LOG_ERR,
			dgettext(TEXT_DOMAIN,
				"PAM-KRB5 (password):unable to get host based "
				"service name for realm %s\n"),
			admin_realm);
		return (3);
	}

	code = kadm5_init_with_password(kprinc, old_password, cpw_service,
					&params, KADM5_STRUCT_VERSION,
					KADM5_API_VERSION_2, &server_handle);
	free(cpw_service);
	if (code != 0) {
		if (debug)
			syslog(LOG_DEBUG,
			    "PAM-KRB5 (password): changepw: "
			    "init_with_pw failed:  (%s)", error_message(code));
		krb5_free_principal(context, princ);
		return ((code == KADM5_BAD_PASSWORD) ? 2 : 3);
	}

	code = kadm5_chpass_principal_util(server_handle, princ,
					new_password,
					NULL /* don't need pw back */,
					msg_ret,
					sizeof (msg_ret));

	if (code) {
		char msgs[2][PAM_MAX_MSG_SIZE];

		(void) snprintf(msgs[0], PAM_MAX_MSG_SIZE, "%s",
			dgettext(TEXT_DOMAIN,
				"Kerberos password not changed: "));
		(void) snprintf(msgs[1], PAM_MAX_MSG_SIZE, "%s", msg_ret);

		display_msgs(pamh, PAM_ERROR_MSG, 2, msgs);
	}

	krb5_free_principal(context, princ);

	(void) kadm5_destroy(server_handle);

	if (debug)
		syslog(LOG_DEBUG,
		    "PAM-KRB5 (password): changepw: end %d", code);

	if (code == KRB5_LIBOS_CANTREADPWD)
		return (5);
	else if (code)
		return (4);
	else
		return (PAM_SUCCESS);
}
Example #2
0
static int
fetch_princ_entry(
	krb5_module_data_t *kmd,
	char *princ_str,
	kadm5_principal_ent_rec *prent,	/* out */
	int debug)

{
	kadm5_ret_t		code;
	krb5_principal 		princ = 0;
	char 			admin_realm[1024];
	char			kprinc[2*MAXHOSTNAMELEN];
	char			*cpw_service, *password;
	void 			*server_handle;
	krb5_context		context;
	kadm5_config_params	params;

	password = kmd->password;
	context = kmd->kcontext;

	if ((code = get_kmd_kuser(context, (const char *)princ_str,
	    kprinc, 2*MAXHOSTNAMELEN)) != 0) {
		return (code);
	}

	code = krb5_parse_name(context, kprinc, &princ);
	if (code != 0) {
		return (PAM_SYSTEM_ERR);
	}

	if (strlen(password) == 0) {
		krb5_free_principal(context, princ);
		if (debug)
			__pam_log(LOG_AUTH | LOG_DEBUG,
			    "PAM-KRB5 (acct): fetch_princ_entry: pwlen=0");
		return (PAM_AUTH_ERR);
	}

	(void) strlcpy(admin_realm,
		    krb5_princ_realm(context, princ)->data,
		    sizeof (admin_realm));

	(void) memset((char *)&params, 0, sizeof (params));
	params.mask |= KADM5_CONFIG_REALM;
	params.realm = admin_realm;

	if (kadm5_get_cpw_host_srv_name(context, admin_realm, &cpw_service)) {
		__pam_log(LOG_AUTH | LOG_ERR,
			"PAM-KRB5 (acct):  unable to get host based "
			"service name for realm '%s'",
			admin_realm);
		krb5_free_principal(context, princ);
		return (PAM_SYSTEM_ERR);
	}

	code = kadm5_init_with_password(kprinc, password, cpw_service,
					&params, KADM5_STRUCT_VERSION,
					KADM5_API_VERSION_2, NULL,
					&server_handle);
	if (code != 0) {
		if (debug)
			__pam_log(LOG_AUTH | LOG_DEBUG,
			    "PAM-KRB5 (acct): fetch_princ_entry: "
			    "init_with_pw failed: code = %d", code);
		krb5_free_principal(context, princ);
		return ((code == KADM5_BAD_PASSWORD) ?
			PAM_AUTH_ERR : PAM_SYSTEM_ERR);
	}

	if (_kadm5_get_kpasswd_protocol(server_handle) != KRB5_CHGPWD_RPCSEC) {
		if (debug)
			__pam_log(LOG_AUTH | LOG_DEBUG,
			    "PAM-KRB5 (acct): fetch_princ_entry: "
			    "non-RPCSEC_GSS chpw server, can't get "
			    "princ entry");
		(void) kadm5_destroy(server_handle);
		krb5_free_principal(context, princ);
		return (PAM_SYSTEM_ERR);
	}

	code = kadm5_get_principal(server_handle, princ, prent,
				KADM5_PRINCIPAL_NORMAL_MASK);

	if (code != 0) {
		(void) kadm5_destroy(server_handle);
		krb5_free_principal(context, princ);
		return ((code == KADM5_UNK_PRINC) ?
			PAM_USER_UNKNOWN : PAM_SYSTEM_ERR);
	}

	(void) kadm5_destroy(server_handle);
	krb5_free_principal(context, princ);

	return (PAM_SUCCESS);
}
Example #3
0
int
krb5_verifypw(
	pam_handle_t *pamh,
	char 	*princ_str,
	char	*old_password,
	boolean_t disp_flag,
	int debug)
{
	kadm5_ret_t		code;
	krb5_principal 		princ = 0;
	char 			admin_realm[1024];
	char			kprinc[2*MAXHOSTNAMELEN];
	char			*cpw_service;
	kadm5_principal_ent_rec principal_entry;
	kadm5_policy_ent_rec	 policy_entry;
	void 			*server_handle;
	krb5_context		context;
	kadm5_config_params	params;
#define	MSG_ROWS		5
	char			msgs[MSG_ROWS][PAM_MAX_MSG_SIZE];

	(void) memset((char *)&params, 0, sizeof (params));
	(void) memset(&principal_entry, 0, sizeof (principal_entry));
	(void) memset(&policy_entry, 0, sizeof (policy_entry));

	if (code = krb5_init_context(&context)) {
		return (6);
	}

	if ((code = get_kmd_kuser(context, (const char *)princ_str, kprinc,
		2*MAXHOSTNAMELEN)) != 0) {
		return (code);
	}

	/* Need to get a krb5_principal struct */

	code = krb5_parse_name(context, kprinc, &princ);

	if (code != 0) {
		return (MISC_EXIT_STATUS);
	}

	if (strlen(old_password) == 0) {
		krb5_free_principal(context, princ);
		return (5);
	}

	(void) strlcpy(admin_realm,
		    krb5_princ_realm(context, princ)->data,
		    sizeof (admin_realm));

	params.mask |= KADM5_CONFIG_REALM;
	params.realm = admin_realm;


	if (kadm5_get_cpw_host_srv_name(context, admin_realm, &cpw_service)) {
		syslog(LOG_ERR,
		    dgettext(TEXT_DOMAIN,
			"PAM-KRB5 (password): unable to get host based "
			"service name for realm %s\n"),
			admin_realm);
		return (3);
	}

	code = kadm5_init_with_password(kprinc, old_password, cpw_service,
					&params, KADM5_STRUCT_VERSION,
					KADM5_API_VERSION_2, &server_handle);
	if (code != 0) {
		if (debug)
			syslog(LOG_DEBUG,
			    "PAM-KRB5: krb5_verifypw: init_with_pw"
			    " failed: (%s)", error_message(code));
		krb5_free_principal(context, princ);
		return ((code == KADM5_BAD_PASSWORD) ? 2 : 3);
	}

	if (disp_flag &&
	    _kadm5_get_kpasswd_protocol(server_handle) == KRB5_CHGPWD_RPCSEC) {
		/*
		 * Note: copy of this exists in login
		 * (kverify.c/get_verified_in_tkt).
		 */

		code = kadm5_get_principal(server_handle, princ,
						&principal_entry,
						KADM5_PRINCIPAL_NORMAL_MASK);
		if (code != 0) {
			krb5_free_principal(context, princ);
			(void) kadm5_destroy(server_handle);
			return ((code == KADM5_UNK_PRINC) ? 1 :
				MISC_EXIT_STATUS);
		}

		if ((principal_entry.aux_attributes & KADM5_POLICY) != 0) {
			code = kadm5_get_policy(server_handle,
						principal_entry.policy,
						&policy_entry);
			if (code != 0) {
				/*
				 * doesn't matter which error comes back,
				 * there's no nice recovery or need to
				 * differentiate to the user
				 */
				(void) kadm5_free_principal_ent(server_handle,
							&principal_entry);
				krb5_free_principal(context, princ);
				(void) kadm5_destroy(server_handle);
				return (MISC_EXIT_STATUS);
			}

			(void) snprintf(msgs[0], PAM_MAX_MSG_SIZE,
				dgettext(TEXT_DOMAIN, "POLICY_EXPLANATION:"));
			(void) snprintf(msgs[1], PAM_MAX_MSG_SIZE,
				dgettext(TEXT_DOMAIN,
					"Principal string is %s"), princ_str);
			(void) snprintf(msgs[2], PAM_MAX_MSG_SIZE,
				dgettext(TEXT_DOMAIN, "Policy Name is  %s"),
				principal_entry.policy);
			(void) snprintf(msgs[3], PAM_MAX_MSG_SIZE,
				dgettext(TEXT_DOMAIN,
					"Minimum password length is %d"),
					policy_entry.pw_min_length);
			(void) snprintf(msgs[4], PAM_MAX_MSG_SIZE,
				dgettext(TEXT_DOMAIN,
					"Minimum password classes is %d"),
					policy_entry.pw_min_classes);
			display_msgs(pamh, PAM_TEXT_INFO, MSG_ROWS, msgs);

			if (code = kadm5_free_principal_ent(server_handle,
							    &principal_entry)) {
				(void) kadm5_free_policy_ent(server_handle,
							&policy_entry);
				krb5_free_principal(context, princ);
				(void) kadm5_destroy(server_handle);
				return (MISC_EXIT_STATUS);
			}
			if (code = kadm5_free_policy_ent(server_handle,
							&policy_entry)) {
				krb5_free_principal(context, princ);

				(void) kadm5_destroy(server_handle);
				return (MISC_EXIT_STATUS);
			}
		} else {
			/*
			 * kpasswd *COULD* output something here to encourage
			 * the choice of good passwords, in the absence of
			 * an enforced policy.
			 */
			if (code = kadm5_free_principal_ent(server_handle,
							    &principal_entry)) {
				krb5_free_principal(context, princ);
				(void) kadm5_destroy(server_handle);
				return (MISC_EXIT_STATUS);
			}
		}
	}
	krb5_free_principal(context, princ);

	(void) kadm5_destroy(server_handle);

	return (0);
}