Example #1
0
File: sly.c Project: OPSF/uClinux
int
_pam_krb5_sly_maybe_refresh(pam_handle_t *pamh, int flags,
			    int argc, PAM_KRB5_MAYBE_CONST char **argv)
{
	PAM_KRB5_MAYBE_CONST char *user;
	krb5_context ctx;
	struct _pam_krb5_options *options;
	struct _pam_krb5_user_info *userinfo;
	struct _pam_krb5_stash *stash;
	struct stat st;
	int i, retval, stored;
	uid_t uid;
	gid_t gid;
	const char *v5ccname, *v5filename, *v4tktfile;
#ifdef TKT_ROOT
	char v4tktfilebuf[PATH_MAX];
#endif

	/* Inexpensive checks. */
	switch (_pam_krb5_sly_looks_unsafe()) {
	case 0:
		/* nothing: everything's okay */
		break;
	case 1:
		warn("won't refresh credentials while running under sudo");
		return PAM_SERVICE_ERR;
		break;
	case 2:
		warn("won't refresh credentials while running setuid");
		return PAM_SERVICE_ERR;
		break;
	case 3:
		warn("won't refresh credentials while running setgid");
		return PAM_SERVICE_ERR;
		break;
	default:
		warn("not safe to refresh credentials");
		return PAM_SERVICE_ERR;
		break;
	}

	/* Initialize Kerberos. */
	if (_pam_krb5_init_ctx(&ctx, argc, argv) != 0) {
		warn("error initializing Kerberos");
		return PAM_SERVICE_ERR;
	}

	/* Get the user's name. */
	i = pam_get_user(pamh, &user, NULL);
	if ((i != PAM_SUCCESS) || (user == NULL)) {
		warn("could not identify user name");
		krb5_free_context(ctx);
		return i;
	}

	/* Read our options. */
	options = _pam_krb5_options_init(pamh, argc, argv, ctx);
	if (options == NULL) {
		warn("error parsing options (shouldn't happen)");
		krb5_free_context(ctx);
		return PAM_SERVICE_ERR;
	}
	if (options->debug) {
		debug("called to update credentials for '%s'", user);
	}

	/* Get information about the user and the user's principal name. */
	userinfo = _pam_krb5_user_info_init(ctx, user, options);
	if (userinfo == NULL) {
		if (options->ignore_unknown_principals) {
			retval = PAM_IGNORE;
		} else {
			warn("error getting information about '%s' "
			     "(shouldn't happen)", user);
			retval = PAM_USER_UNKNOWN;
		}
		_pam_krb5_options_free(pamh, ctx, options);
		krb5_free_context(ctx);
		return retval;
	}

	if ((options->user_check) &&
	    (options->minimum_uid != (uid_t)-1) &&
	    (userinfo->uid < options->minimum_uid)) {
		if (options->debug) {
			debug("ignoring '%s' -- uid below minimum", user);
		}
		_pam_krb5_user_info_free(ctx, userinfo);
		_pam_krb5_options_free(pamh, ctx, options);
		krb5_free_context(ctx);
		return PAM_IGNORE;
	}

	/* Get the stash for this user. */
	stash = _pam_krb5_stash_get(pamh, user, userinfo, options);
	if (stash == NULL) {
		warn("error retrieving stash for '%s' (shouldn't happen)",
		     user);
		_pam_krb5_user_info_free(ctx, userinfo);
		_pam_krb5_options_free(pamh, ctx, options);
		krb5_free_context(ctx);
		return PAM_SERVICE_ERR;
	}

	retval = PAM_SERVICE_ERR;

	/* Save credentials in the right places. */
	v5ccname = krb5_cc_default_name(ctx);
	v5filename = NULL;
	if (v5ccname == NULL) {
		/* This should never happen, but all we can do is tell libpam
		 * to ignore us.  We have nothing to do. */
		if (options->debug) {
			debug("ignoring '%s' -- no default ccache name", user);
		}
		retval = PAM_IGNORE;
	} else {
		if (strncmp(v5ccname, "FILE:", 5) == 0) {
			v5filename = v5ccname + 5;
			if (options->debug) {
				debug("ccache is a file named '%s'",
				      v5filename);
			}
		} else {
			if (options->debug) {
				debug("ccache '%s' is not a file", v5ccname);
			}
		}
	}

	stored = 0;
	uid = options->user_check ? userinfo->uid : getuid();
	gid = options->user_check ? userinfo->gid : getgid();

	if (v5_creds_check_initialized(ctx, &stash->v5creds) == 0) {
		if (v5filename != NULL) {
			/* Check the permissions on the ccache file. */
			if ((access(v5filename, R_OK | W_OK) == 0) &&
			    (lstat(v5filename, &st) == 0)) {
				if (S_ISREG(st.st_mode) &&
				    ((st.st_mode & S_IRWXG) == 0) &&
				    ((st.st_mode & S_IRWXO) == 0) &&
				    (st.st_uid == uid) &&
				    (st.st_gid == gid)) {
					if (options->debug) {
						debug("updating ccache '%s' "
						      "for '%s'",
						      v5ccname, user);
					}
					retval = sly_v5(ctx, v5ccname,
							userinfo, stash);
					stored = (retval == PAM_SUCCESS);
				} else {
					if (options->debug) {
						debug("not updating '%s'",
						      v5ccname);
					}
					retval = PAM_SUCCESS;
				}
			} else {
				if (errno == ENOENT) {
					/* We have nothing to do. */
					retval = PAM_SUCCESS;
				}
			}
		} else {
			if (v5ccname != NULL) {
				/* Go ahead and update the current not-a-file
				 * ccache. */
				if (options->debug) {
					debug("updating ccache '%s' for '%s'",
					      v5ccname, user);
				}
				retval = sly_v5(ctx, v5ccname, userinfo, stash);
				stored = (retval == PAM_SUCCESS);
			}
		}
	} else {
		if (options->debug) {
			debug("no credentials available to store in '%s'",
			      v5ccname);
		}
		retval = PAM_SUCCESS;
	}

	v4tktfile = getenv("KRBTKFILE");
#ifdef TKT_ROOT
	if ((v4tktfile == NULL) && (options->user_check)) {
		snprintf(v4tktfilebuf, sizeof(v4tktfilebuf), "%s%ld",
			 TKT_ROOT, (long) uid);
		v4tktfile = v4tktfilebuf;
	}
#endif
	if ((stash->v4present) && (v4tktfile != NULL)) {
		if (access(v4tktfile, R_OK | W_OK) == 0) {
			if (lstat(v4tktfile, &st) == 0) {
				if (S_ISREG(st.st_mode) &&
				    ((st.st_mode & S_IRWXG) == 0) &&
				    ((st.st_mode & S_IRWXO) == 0) &&
				    (st.st_uid == uid) &&
				    (st.st_gid == gid)) {
					if (options->debug) {
						debug("updating ticket file "
						      "'%s' for '%s'",
						      v4tktfile, user);
					}
					sly_v4(ctx, v4tktfile, userinfo, stash);
					stored = 1;
				} else {
					if (options->debug) {
						debug("not updating '%s'",
						      v4tktfile);
					}
				}
			} else {
				if (errno == ENOENT) {
					/* We have nothing to do. */
					if (options->debug) {
						debug("no preexisting ticket "
						      "file found");
					}
					retval = PAM_SUCCESS;
				}
			}
		} else {
			/* Touch nothing. */
			if (options->debug) {
				debug("unable to access preexisting ticket "
				      "file");
			}
			retval = PAM_SUCCESS;
		}
	}

	if (stored && !options->ignore_afs) {
		tokens_obtain(ctx, stash, options, userinfo, 0);
	}

	if (options->debug) {
		debug("_pam_krb5_sly_refresh returning %d (%s)", retval,
		      pam_strerror(pamh, retval));
	}

	_pam_krb5_user_info_free(ctx, userinfo);
	_pam_krb5_options_free(pamh, ctx, options);
	krb5_free_context(ctx);

	return retval;
}
Example #2
0
int
v4_get_creds(krb5_context ctx,
	     pam_handle_t *pamh,
	     struct _pam_krb5_stash *stash,
	     struct _pam_krb5_user_info *userinfo,
	     struct _pam_krb5_options *options,
	     char *password,
	     int *result)
{
	int i;
#if defined(HAVE_KRB5_524_CONVERT_CREDS) || \
    defined(HAVE_KRB524_CONVERT_CREDS_KDC)
	krb5_creds *v4_compat_creds, *in_creds;

	v4_compat_creds = NULL;

	if (options->v4_use_524) {
		if (options->debug) {
			debug("obtaining v4-compatible key");
		}
		/* We need a DES-CBC-CRC v5 credential to convert to a proper v4
		 * credential. */
		i = v5_get_creds_etype(ctx, userinfo, options, &stash->v5creds,
				       ENCTYPE_DES_CBC_CRC, &v4_compat_creds);
		if (i == 0) {
			if (options->debug) {
				debug("obtained des-cbc-crc v5 creds");
			}
			in_creds = v4_compat_creds;
		} else {
			if (options->debug) {
				debug("failed to obtain des-cbc-crc v5 creds: "
				      "%d (%s)", i, v5_error_message(i));
			}
			in_creds = NULL;
			if (v5_creds_check_initialized(ctx,
						       &stash->v5creds) == 0) {
				krb5_copy_creds(ctx, &stash->v5creds,
						&in_creds);
			}
		}
#ifdef HAVE_KRB5_524_CONVERT_CREDS
		if (options->debug) {
			debug("converting v5 creds to v4 creds (etype = %d)",
			      in_creds ? v5_creds_get_etype(in_creds) : 0);
		}
		if ((in_creds != NULL) &&
		    (v5_creds_check_initialized(ctx, in_creds) == 0)) {
			i = krb5_524_convert_creds(ctx, in_creds,
						   &stash->v4creds);
			if (i == 0) {
				if (options->debug) {
					debug("conversion succeeded");
				}
				stash->v4present = 1;
				if (result) {
					*result = i;
				}
				krb5_free_creds(ctx, in_creds);
				return PAM_SUCCESS;
			} else {
				if (options->debug) {
					debug("conversion failed: %d (%s)",
					      i, v5_error_message(i));
				}
			}
		}
#else
#ifdef HAVE_KRB524_CONVERT_CREDS_KDC
		if (options->debug) {
			debug("converting v5 creds to v4 creds (etype = %d)",
			      in_creds ? v5_creds_get_etype(in_creds) : 0);
		}
		if ((in_creds != NULL) &&
		    (v5_creds_check_initialized(ctx, in_creds) == 0)) {
			i = krb524_convert_creds_kdc(ctx, in_creds,
						     &stash->v4creds);
			if (i == 0) {
				if (options->debug) {
					debug("conversion succeeded");
				}
				stash->v4present = 1;
				if (result) {
					*result = i;
				}
				krb5_free_creds(ctx, in_creds);
				return PAM_SUCCESS;
			} else {
				if (options->debug) {
					debug("conversion failed: %d (%s)",
					      i, v5_error_message(i));
				}
			}
		}
#endif
#endif
		if ((in_creds != NULL) &&
		    (v5_creds_check_initialized(ctx, in_creds) == 0)) {
			krb5_free_creds(ctx, in_creds);
		}
	}
#endif
	if ((password != NULL) && (options->v4_use_as_req)) {
		if (options->debug) {
			debug("attempting to obtain initial v4 creds");
		}
		i = _pam_krb5_v4_init(ctx, stash, userinfo, options,
				      KRB5_TGS_NAME, NULL, password, result);
		if (i == PAM_SUCCESS) {
			if (options->debug) {
				debug("initial v4 creds obtained");
			}
			stash->v4present = 1;
			return PAM_SUCCESS;
		}
		if (options->debug) {
			debug("could not obtain initial v4 creds: %d (%s)",
			      i, v5_error_message(i));
		}
	}
	return PAM_AUTH_ERR;
}