示例#1
0
文件: rc_io.c 项目: Akasurde/krb5
krb5_error_code
krb5_rc_io_creat(krb5_context context, krb5_rc_iostuff *d, char **fn)
{
    krb5_int16 rc_vno = htons(KRB5_RC_VNO);
    krb5_error_code retval = 0;
    int flags, do_not_unlink = 0;
    char *dir;
    size_t dirlen;

    GETDIR;
    if (fn && *fn) {
        if (asprintf(&d->fn, "%s%s%s", dir, PATH_SEPARATOR, *fn) < 0)
            return KRB5_RC_IO_MALLOC;
        d->fd = -1;
        do {
            if (unlink(d->fn) == -1 && errno != ENOENT)
                break;
            flags = O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY;
            d->fd = THREEPARAMOPEN(d->fn, flags, 0600);
        } while (d->fd == -1 && errno == EEXIST);
    } else {
        retval = krb5_rc_io_mkstemp(context, d, dir);
        if (retval)
            goto cleanup;
        if (d->fd != -1 && fn) {
            *fn = strdup(d->fn + dirlen);
            if (*fn == NULL) {
                free(d->fn);
                return KRB5_RC_IO_MALLOC;
            }
        }
    }
    if (d->fd == -1) {
        retval = rc_map_errno(context, errno, d->fn, "create");
        if (retval == KRB5_RC_IO_PERM)
            do_not_unlink = 1;
        goto cleanup;
    }
    set_cloexec_fd(d->fd);
    retval = krb5_rc_io_write(context, d, (krb5_pointer)&rc_vno,
                              sizeof(rc_vno));
    if (retval)
        goto cleanup;

    retval = krb5_rc_io_sync(context, d);

cleanup:
    if (retval) {
        if (d->fn) {
            if (!do_not_unlink)
                (void) unlink(d->fn);
            free(d->fn);
            d->fn = NULL;
        }
        if (d->fd != -1) {
            (void) close(d->fd);
        }
    }
    return retval;
}
示例#2
0
文件: rc_io.c 项目: arkadiyg/krb5
static krb5_error_code
krb5_rc_io_open_internal(krb5_context context, krb5_rc_iostuff *d, char *fn,
                         char* full_pathname)
{
    krb5_int16 rc_vno;
    krb5_error_code retval = 0;
    int do_not_unlink = 1;
#ifndef NO_USERID
    struct stat sb1, sb2;
#endif
    char *dir;

    dir = getdir();
    if (full_pathname) {
        if (!(d->fn = strdup(full_pathname)))
            return KRB5_RC_IO_MALLOC;
    } else {
        if (asprintf(&d->fn, "%s%s%s", dir, PATH_SEPARATOR, fn) < 0)
            return KRB5_RC_IO_MALLOC;
    }

#ifdef NO_USERID
    d->fd = THREEPARAMOPEN(d->fn, O_RDWR | O_BINARY, 0600);
    if (d->fd == -1) {
        retval = rc_map_errno(context, errno, d->fn, "open");
        goto cleanup;
    }
#else
    d->fd = -1;
    retval = lstat(d->fn, &sb1);
    if (retval != 0) {
        retval = rc_map_errno(context, errno, d->fn, "lstat");
        goto cleanup;
    }
    d->fd = THREEPARAMOPEN(d->fn, O_RDWR | O_BINARY, 0600);
    if (d->fd < 0) {
        retval = rc_map_errno(context, errno, d->fn, "open");
        goto cleanup;
    }
    retval = fstat(d->fd, &sb2);
    if (retval < 0) {
        retval = rc_map_errno(context, errno, d->fn, "fstat");
        goto cleanup;
    }
    /* check if someone was playing with symlinks */
    if ((sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino)
        || (sb1.st_mode & S_IFMT) != S_IFREG)
    {
        retval = KRB5_RC_IO_PERM;
        k5_setmsg(context, retval, "rcache not a file %s", d->fn);
        goto cleanup;
    }
    /* check that non other can read/write/execute the file */
    if (sb1.st_mode & 077) {
        k5_setmsg(context, retval,
                  _("Insecure file mode for replay cache file %s"), d->fn);
        return KRB5_RC_IO_UNKNOWN;
    }
    /* owned by me */
    if (sb1.st_uid != geteuid()) {
        retval = KRB5_RC_IO_PERM;
        k5_setmsg(context, retval, _("rcache not owned by %d"),
                  (int)geteuid());
        goto cleanup;
    }
#endif
    set_cloexec_fd(d->fd);

    do_not_unlink = 0;
    retval = krb5_rc_io_read(context, d, (krb5_pointer) &rc_vno,
                             sizeof(rc_vno));
    if (retval)
        goto cleanup;

    if (ntohs(rc_vno) != KRB5_RC_VNO)
        retval = KRB5_RCACHE_BADVNO;

cleanup:
    if (retval) {
        if (!do_not_unlink)
            (void) unlink(d->fn);
        free(d->fn);
        d->fn = NULL;
        if (d->fd >= 0)
            (void) close(d->fd);
    }
    return retval;
}