Esempio n. 1
0
krb5_boolean KRB5_CALLCONV
krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
{
    struct stat sbuf;
    struct passwd *pwd;
    char pbuf[MAXPATHLEN];
    krb5_boolean isok = FALSE;
    FILE *fp;
    char kuser[MAX_USERNAME];
    char *princname;
    char linebuf[BUFSIZ];
    char *newline;
    int gobble;

    /* no account => no access */
    char pwbuf[BUFSIZ];
    struct passwd pwx;
    if (k5_getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0)
	return(FALSE);
    (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
    pbuf[sizeof(pbuf) - 1] = '\0';
    (void) strncat(pbuf, "/.k5login", sizeof(pbuf) - 1 - strlen(pbuf));

    if (access(pbuf, F_OK)) {	 /* not accessible */
	/*
	 * if he's trying to log in as himself, and there is no .k5login file,
	 * let him.  To find out, call
	 * krb5_aname_to_localname to convert the principal to a name
	 * which we can string compare. 
	 */
	if (!(krb5_aname_to_localname(context, principal,
				      sizeof(kuser), kuser))
	    && (strcmp(kuser, luser) == 0)) {
	    return(TRUE);
	}
    }
    if (krb5_unparse_name(context, principal, &princname))
	return(FALSE);			/* no hope of matching */

    /* open ~/.k5login */
    if ((fp = fopen(pbuf, "r")) == NULL) {
	free(princname);
	return(FALSE);
    }
    set_cloexec_file(fp);
    /*
     * For security reasons, the .k5login file must be owned either by
     * the user himself, or by root.  Otherwise, don't grant access.
     */
    if (fstat(fileno(fp), &sbuf)) {
	fclose(fp);
	free(princname);
	return(FALSE);
    }
    if (sbuf.st_uid != pwd->pw_uid && !FILE_OWNER_OK(sbuf.st_uid)) {
	fclose(fp);
	free(princname);
	return(FALSE);
    }

    /* check each line */
    while (!isok && (fgets(linebuf, BUFSIZ, fp) != NULL)) {
	/* null-terminate the input string */
	linebuf[BUFSIZ-1] = '\0';
	newline = NULL;
	/* nuke the newline if it exists */
	if ((newline = strchr(linebuf, '\n')))
	    *newline = '\0';
	if (!strcmp(linebuf, princname)) {
	    isok = TRUE;
	    continue;
	}
	/* clean up the rest of the line if necessary */
	if (!newline)
	    while (((gobble = getc(fp)) != EOF) && gobble != '\n');
    }
    free(princname);
    fclose(fp);
    return(isok);
}
Esempio n. 2
0
/*
 * Determine whether principal is authorized to log in as luser according to
 * the user's k5login file.  Return ACCEPT if the k5login file authorizes the
 * principal, PASS if the k5login file does not exist, or REJECT if the k5login
 * file exists but does not authorize the principal.  If k5login files are
 * configured to be non-authoritative, pass instead of rejecting.
 */
static enum result
k5login_ok(krb5_context context, krb5_principal principal, const char *luser)
{
    int authoritative = TRUE, gobble;
    enum result result = REJECT;
    char *filename = NULL, *princname = NULL;
    char *newline, linebuf[BUFSIZ], pwbuf[BUFSIZ];
    struct stat sbuf;
    struct passwd pwx, *pwd;
    FILE *fp = NULL;

    if (profile_get_boolean(context->profile, KRB5_CONF_LIBDEFAULTS,
                            KRB5_CONF_K5LOGIN_AUTHORITATIVE, NULL, TRUE,
                            &authoritative) != 0)
        goto cleanup;

    /* Get the local user's homedir and uid. */
    if (k5_getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0)
        goto cleanup;

    if (get_k5login_filename(context, luser, pwd->pw_dir, &filename) != 0)
        goto cleanup;

    if (access(filename, F_OK) != 0) {
        result = PASS;
        goto cleanup;
    }

    if (krb5_unparse_name(context, principal, &princname) != 0)
        goto cleanup;

    fp = fopen(filename, "r");
    if (fp == NULL)
        goto cleanup;
    set_cloexec_file(fp);

    /* For security reasons, the .k5login file must be owned either by
     * the user or by root. */
    if (fstat(fileno(fp), &sbuf))
        goto cleanup;
    if (sbuf.st_uid != pwd->pw_uid && !FILE_OWNER_OK(sbuf.st_uid))
        goto cleanup;

    /* Check each line. */
    while (result != ACCEPT && (fgets(linebuf, sizeof(linebuf), fp) != NULL)) {
        newline = strrchr(linebuf, '\n');
        if (newline != NULL)
            *newline = '\0';
        if (strcmp(linebuf, princname) == 0)
            result = ACCEPT;
        /* Clean up the rest of the line if necessary. */
        if (newline == NULL)
            while (((gobble = getc(fp)) != EOF) && gobble != '\n');
    }

cleanup:
    free(princname);
    free(filename);
    if (fp != NULL)
        fclose(fp);
    /* If k5login files are non-authoritative, never reject. */
    return (!authoritative && result == REJECT) ? PASS : result;
}