Ejemplo n.º 1
0
static krb5_error_code KRB5_LIB_CALL
kuserok_sys_k5login_plug_f(void *plug_ctx, krb5_context context,
			   const char *rule, unsigned int flags,
			   const char *k5login_dir, const char *luser,
			   krb5_const_principal principal, krb5_boolean *result)
{
    char filename[MAXPATHLEN];
    size_t len;
    const char *profile_dir = NULL;
    krb5_error_code ret;

    *result = FALSE;

    if (strcmp(rule, "SYSTEM-K5LOGIN") != 0 &&
	strncmp(rule, "SYSTEM-K5LOGIN:"******"SYSTEM-K5LOGIN:"******"%s/%s", profile_dir, luser);
    if (len < sizeof(filename)) {
	ret = check_one_file(context, filename, NULL, TRUE, principal, result);

	if (ret == 0 &&
	    ((flags & KUSEROK_K5LOGIN_IS_AUTHORITATIVE) || *result == TRUE))
	    return 0;
    }

    *result = FALSE;
    return KRB5_PLUGIN_NO_HANDLE;
}
Ejemplo n.º 2
0
static krb5_error_code
check_directory(krb5_context context,
		const char *dirname,
		struct passwd *pwd,
		krb5_principal principal,
		krb5_boolean *result)
{
    DIR *d;
    struct dirent *dent;
    char filename[MAXPATHLEN];
    krb5_error_code ret = 0;
    struct stat st;

    *result = FALSE;

    if(lstat(dirname, &st) < 0)
	return errno;

    if (!S_ISDIR(st.st_mode))
	return ENOTDIR;

    if (st.st_uid != pwd->pw_uid && st.st_uid != 0)
	return EACCES;
    if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0)
	return EACCES;

    if((d = opendir(dirname)) == NULL)
	return errno;

    {
	int fd;
	struct stat st2;

	fd = dirfd(d);
	if(fstat(fd, &st2) < 0) {
	    closedir(d);
	    return errno;
	}
	if(st.st_dev != st2.st_dev || st.st_ino != st2.st_ino) {
	    closedir(d);
	    return EACCES;
	}
    }

    while((dent = readdir(d)) != NULL) {
	if(strcmp(dent->d_name, ".") == 0 ||
	   strcmp(dent->d_name, "..") == 0 ||
	   dent->d_name[0] == '#' ||			  /* emacs autosave */
	   dent->d_name[strlen(dent->d_name) - 1] == '~') /* emacs backup */
	    continue;
	snprintf(filename, sizeof(filename), "%s/%s", dirname, dent->d_name);
	ret = check_one_file(context, filename, pwd, principal, result);
	if(ret == 0 && *result == TRUE)
	    break;
	ret = 0; /* don't propagate errors upstream */
    }
    closedir(d);
    return ret;
}
Ejemplo n.º 3
0
krb5_boolean KRB5_LIB_FUNCTION
krb5_kuserok (krb5_context context,
	      krb5_principal principal,
	      const char *luser)
{
    char *buf;
    size_t buflen;
    struct passwd *pwd;
    krb5_error_code ret;
    krb5_boolean result = FALSE;

    krb5_boolean found_file = FALSE;

#ifdef POSIX_GETPWNAM_R
    char pwbuf[2048];
    struct passwd pw;

    if(getpwnam_r(luser, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0)
	return FALSE;
#else
    pwd = getpwnam (luser);
#endif
    if (pwd == NULL)
	return FALSE;

#define KLOGIN "/.k5login"
    buflen = strlen(pwd->pw_dir) + sizeof(KLOGIN) + 2; /* 2 for .d */
    buf = malloc(buflen);
    if(buf == NULL)
	return FALSE;
    /* check user's ~/.k5login */
    strlcpy(buf, pwd->pw_dir, buflen);
    strlcat(buf, KLOGIN, buflen);
    ret = check_one_file(context, buf, pwd, principal, &result);

    if(ret == 0 && result == TRUE) {
	free(buf);
	return TRUE;
    }

    if(ret != ENOENT) 
	found_file = TRUE;

    strlcat(buf, ".d", buflen);
    ret = check_directory(context, buf, pwd, principal, &result);
    free(buf);
    if(ret == 0 && result == TRUE)
	return TRUE;

    if(ret != ENOENT && ret != ENOTDIR) 
	found_file = TRUE;

    /* finally if no files exist, allow all principals matching
       <localuser>@<LOCALREALM> */
    if(found_file == FALSE)
	return match_local_principals(context, principal, luser);

    return FALSE;
}
Ejemplo n.º 4
0
static krb5_error_code KRB5_LIB_CALL
kuserok_user_k5login_plug_f(void *plug_ctx, krb5_context context,
			    const char *rule, unsigned int flags,
			    const char *k5login_dir, const char *luser,
			    krb5_const_principal principal,
			    krb5_boolean *result)
{
#ifdef _WIN32
    return KRB5_PLUGIN_NO_HANDLE;
#else
    char *path;
    char *path_exp;
    const char *profile_dir = NULL;
    krb5_error_code ret;
    krb5_boolean found_file = FALSE;
    struct passwd pw, *pwd = NULL;
    char pwbuf[2048];

    if (strcmp(rule, "USER-K5LOGIN") != 0)
	return KRB5_PLUGIN_NO_HANDLE;

    profile_dir = k5login_dir;
    if (profile_dir == NULL) {
	/* Don't deadlock with gssd or anything of the sort */
	if (!_krb5_homedir_access(context))
	    return KRB5_PLUGIN_NO_HANDLE;

	if (getpwnam_r(luser, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0) {
	    krb5_set_error_message(context, errno, "User unknown (getpwnam_r())");
	    return KRB5_PLUGIN_NO_HANDLE;
	}
	if (pwd == NULL) {
	    krb5_set_error_message(context, errno, "User unknown (getpwnam())");
	    return KRB5_PLUGIN_NO_HANDLE;
	}
	profile_dir = pwd->pw_dir;
    }

#define KLOGIN "/.k5login"

    if (asprintf(&path, "%s/.k5login.d", profile_dir) == -1)
	return krb5_enomem(context);

    ret = _krb5_expand_path_tokensv(context, path, 1, &path_exp,
				    "luser", luser, NULL);
    free(path);
    if (ret)
	return ret;
    path = path_exp;

    /* check user's ~/.k5login */
    path[strlen(path) - strlen(".d")] = '\0';
    ret = check_one_file(context, path, luser, FALSE, principal, result);

    /*
     * A match in ~/.k5login is sufficient.  A non-match, falls through to the
     * .k5login.d code below.
     */
    if (ret == 0 && *result == TRUE) {
	free(path);
	return 0;
    }
    if (ret != ENOENT)
	found_file = TRUE;

    /*
     * A match in ~/.k5login.d/somefile is sufficient.  A non-match, falls
     * through to the code below that handles negative results.
     *
     * XXX: put back the .d; clever|hackish? you decide
     */
    path[strlen(path)] = '.';
    ret = check_directory(context, path, luser, FALSE, principal, result);
    free(path);
    if (ret == 0 && *result == TRUE)
	return 0;
    if (ret != ENOENT && ret != ENOTDIR)
	found_file = TRUE;

    /*
     * When either ~/.k5login or ~/.k5login.d/ exists, but neither matches
     * and we're authoritative, we're done.  Otherwise, give other plugins
     * a chance.
     */
    *result = FALSE;
    if (found_file && (flags & KUSEROK_K5LOGIN_IS_AUTHORITATIVE))
	return 0;
    return KRB5_PLUGIN_NO_HANDLE;
#endif
}
Ejemplo n.º 5
0
static krb5_error_code
check_directory(krb5_context context,
		const char *dirname,
		const char *owner,
	        krb5_boolean is_system_location,
		krb5_const_principal principal,
		krb5_boolean *result)
{
    DIR *d;
    struct dirent *dent;
    char filename[MAXPATHLEN];
    size_t len;
    krb5_error_code ret = 0;
    struct stat st;

    *result = FALSE;

    if (lstat(dirname, &st) < 0)
	return errno;

    if (!S_ISDIR(st.st_mode)) {
	krb5_set_error_message(context, ENOTDIR, "k5login.d not a directory");
	return ENOTDIR;
    }

    if ((d = opendir(dirname)) == NULL) {
	krb5_set_error_message(context, ENOTDIR, "Could not open k5login.d");
	return errno;
    }

    ret = check_owner_dir(context, dirname, is_system_location, d, &st, owner);
    if (ret)
	goto out;

    while ((dent = readdir(d)) != NULL) {
	/*
	 * XXX: Should we also skip files whose names start with "."?
	 * Vim ".filename.swp" files are also good candidates to skip.
	 * Once we ignore "#*" and "*~", it is not clear what other
	 * heuristics to apply.
	 */
	if (strcmp(dent->d_name, ".") == 0 ||
	   strcmp(dent->d_name, "..") == 0 ||
	   dent->d_name[0] == '#' ||			  /* emacs autosave */
	   dent->d_name[strlen(dent->d_name) - 1] == '~') /* emacs backup */
	    continue;
	len = snprintf(filename, sizeof(filename), "%s/%s", dirname, dent->d_name);
	/* Skip too-long filenames that got truncated by snprintf() */
	if (len < sizeof(filename)) {
	    ret = check_one_file(context, filename, owner, is_system_location,
				 principal, result);
	    if (ret == 0 && *result == TRUE)
		break;
	}
	ret = 0; /* don't propagate errors upstream */
    }

out:
    closedir(d);
    return ret;
}