Exemplo n.º 1
0
krb5_error_code
osa_adb_release_lock(osa_adb_db_t db)
{
    int ret, fd;

    if (!db->lock->lockcnt)            /* lock already unlocked */
        return OSA_ADB_NOTLOCKED;

    if (--db->lock->lockcnt == 0) {
        if (db->lock->lockmode == KRB5_DB_LOCKMODE_PERMANENT) {
            /* now we need to create the file since it does not exist */
            fd = THREEPARAMOPEN(db->lock->filename,O_RDWR | O_CREAT | O_EXCL,
                                0600);
            if (fd < 0)
                return OSA_ADB_NOLOCKFILE;
            set_cloexec_fd(fd);
            if ((db->lock->lockfile = fdopen(fd, "w+")) == NULL)
                return OSA_ADB_NOLOCKFILE;
        } else if ((ret = krb5_lock_file(db->lock->context,
                                         fileno(db->lock->lockfile),
                                         KRB5_LOCKMODE_UNLOCK)))
            return ret;

        db->lock->lockmode = 0;
    }
    return OSA_ADB_OK;
}
Exemplo n.º 2
0
krb5_error_code
osa_adb_create_db(char *filename, char *lockfilename, int magic)
{
    int lf;
    DB *db;
    BTREEINFO btinfo;

    memset(&btinfo, 0, sizeof(btinfo));
    btinfo.flags = 0;
    btinfo.cachesize = 0;
    btinfo.psize = 4096;
    btinfo.lorder = 0;
    btinfo.minkeypage = 0;
    btinfo.compare = NULL;
    btinfo.prefix = NULL;
    db = dbopen(filename, O_RDWR | O_CREAT | O_EXCL, 0600, DB_BTREE, &btinfo);
    if (db == NULL)
        return errno;
    if (db->close(db) < 0)
        return errno;

    /* only create the lock file if we successfully created the db */
    lf = THREEPARAMOPEN(lockfilename, O_RDWR | O_CREAT | O_EXCL, 0600);
    if (lf == -1)
        return errno;
    (void) close(lf);

    return OSA_ADB_OK;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
static void
update_last_prop_file(char *hostname, char *file_name)
{
    char *file_last_prop;
    int fd;
    static char last_prop[] = ".last_prop";

    if (asprintf(&file_last_prop, "%s.%s%s", file_name, hostname,
                 last_prop) < 0) {
        com_err(progname, ENOMEM,
                _("while allocating filename for update_last_prop_file"));
        return;
    }
    fd = THREEPARAMOPEN(file_last_prop, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    if (fd < 0) {
        com_err(progname, errno, _("while creating 'last_prop' file, '%s'"),
                file_last_prop);
        free(file_last_prop);
        return;
    }
    write(fd, "", 1);
    free(file_last_prop);
    close(fd);
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
/* Destroy the cache file and release the handle. */
static krb5_error_code KRB5_CALLCONV
fcc_destroy(krb5_context context, krb5_ccache id)
{
    krb5_error_code ret = 0;
    fcc_data *data = id->data;
    int st, fd;
    struct stat buf;
    unsigned long i, size;
    unsigned int wlen;
    char zeros[BUFSIZ];

    k5_cc_mutex_lock(context, &data->lock);

    if (OPENCLOSE(id)) {
        invalidate_cache(data);
        fd = THREEPARAMOPEN(data->filename, O_RDWR | O_BINARY, 0);
        if (fd < 0) {
            ret = interpret_errno(context, errno);
            goto cleanup;
        }
        set_cloexec_fd(fd);
        data->fd = fd;
    } else {
        fcc_lseek(data, 0, SEEK_SET);
    }

#ifdef MSDOS_FILESYSTEM
    /*
     * "Disgusting bit of UNIX trivia" - that's how the writers of NFS describe
     * the ability of UNIX to still write to a file which has been unlinked.
     * Naturally, the PC can't do this.  As a result, we have to delete the
     * file after we wipe it clean, but that throws off all the error handling
     * code.  So we have do the work ourselves.
     */
    st = fstat(data->fd, &buf);
    if (st == -1) {
        ret = interpret_errno(context, errno);
        size = 0;               /* Nothing to wipe clean */
    } else {
        size = (unsigned long)buf.st_size;
    }

    memset(zeros, 0, BUFSIZ);
    while (size > 0) {
        wlen = (int)((size > BUFSIZ) ? BUFSIZ : size); /* How much to write */
        i = write(data->fd, zeros, wlen);
        if (i < 0) {
            ret = interpret_errno(context, errno);
            /* Don't jump to cleanup--we still want to delete the file. */
            break;
        }
        size -= i;
    }

    if (OPENCLOSE(id)) {
        (void)close(((fcc_data *)id->data)->fd);
        data->fd = -1;
    }

    st = unlink(data->filename);
    if (st < 0) {
        ret = interpret_errno(context, errno);
        goto cleanup;
    }

#else /* MSDOS_FILESYSTEM */

    st = unlink(data->filename);
    if (st < 0) {
        ret = interpret_errno(context, errno);
        if (OPENCLOSE(id)) {
            (void)close(data->fd);
            data->fd = -1;
        }
        goto cleanup;
    }

    st = fstat(data->fd, &buf);
    if (st < 0) {
        ret = interpret_errno(context, errno);
        if (OPENCLOSE(id)) {
            (void)close(data->fd);
            data->fd = -1;
        }
        goto cleanup;
    }

    /* XXX This may not be legal XXX */
    size = (unsigned long)buf.st_size;
    memset(zeros, 0, BUFSIZ);
    for (i = 0; i < size / BUFSIZ; i++) {
        if (write(data->fd, zeros, BUFSIZ) < 0) {
            ret = interpret_errno(context, errno);
            if (OPENCLOSE(id)) {
                (void)close(data->fd);
                data->fd = -1;
            }
            goto cleanup;
        }
    }

    wlen = size % BUFSIZ;
    if (write(data->fd, zeros, wlen) < 0) {
        ret = interpret_errno(context, errno);
        if (OPENCLOSE(id)) {
            (void)close(data->fd);
            data->fd = -1;
        }
        goto cleanup;
    }

    st = close(data->fd);
    data->fd = -1;

    if (st)
        ret = interpret_errno(context, errno);

#endif /* MSDOS_FILESYSTEM */

cleanup:
    k5_cc_mutex_unlock(context, &data->lock);
    dereference(context, data);
    free(id);

    krb5_change_cache();
    return ret;
}
Exemplo n.º 7
0
/* Open and lock the cache file.  If mode is FCC_OPEN_AND_ERASE, initialize it
 * with a header.  Call with the mutex locked. */
static krb5_error_code
open_cache_file(krb5_context context, krb5_ccache id, int mode)
{
    krb5_os_context os_ctx = &context->os_context;
    krb5_error_code ret;
    fcc_data *data = id->data;
    char fcc_fvno[2];
    uint16_t fcc_flen, fcc_tag, fcc_taglen;
    uint32_t time_offset, usec_offset;
    int f, open_flag, lock_flag, cnt;
    char buf[1024];

    k5_cc_mutex_assert_locked(context, &data->lock);
    invalidate_cache(data);

    if (data->fd != NO_FILE) {
        /* Don't know what state it's in; shut down and start anew. */
        (void)krb5_unlock_file(context, data->fd);
        (void)close(data->fd);
        data->fd = NO_FILE;
    }

    switch (mode) {
    case FCC_OPEN_AND_ERASE:
        unlink(data->filename);
        open_flag = O_CREAT | O_EXCL | O_TRUNC | O_RDWR;
        break;
    case FCC_OPEN_RDWR:
        open_flag = O_RDWR;
        break;
    case FCC_OPEN_RDONLY:
    default:
        open_flag = O_RDONLY;
        break;
    }

    f = THREEPARAMOPEN(data->filename, open_flag | O_BINARY, 0600);
    if (f == NO_FILE) {
        if (errno == ENOENT) {
            ret = KRB5_FCC_NOFILE;
            k5_setmsg(context, ret, _("Credentials cache file '%s' not found"),
                      data->filename);
            return ret;
        } else {
            return interpret_errno(context, errno);
        }
    }
    set_cloexec_fd(f);

    data->mode = mode;

    if (data->mode == FCC_OPEN_RDONLY)
        lock_flag = KRB5_LOCKMODE_SHARED;
    else
        lock_flag = KRB5_LOCKMODE_EXCLUSIVE;
    ret = krb5_lock_file(context, f, lock_flag);
    if (ret) {
        (void)close(f);
        return ret;
    }

    if (mode == FCC_OPEN_AND_ERASE) {
        /* write the version number */
        store_16_be(context->fcc_default_format, fcc_fvno);
        data->version = context->fcc_default_format;
        cnt = write(f, fcc_fvno, 2);
        if (cnt != 2) {
            ret = (cnt == -1) ? interpret_errno(context, errno) : KRB5_CC_IO;
            goto done;
        }
        data->fd = f;

        if (data->version == FVNO_4) {
            /* V4 of the credentials cache format allows for header tags */
            fcc_flen = 0;

            if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID)
                fcc_flen += 2 + 2 + 4 + 4;

            /* Write header length. */
            ret = store16(context, id, fcc_flen);
            if (ret)
                goto done;

            if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) {
                /* Write time offset tag. */
                fcc_tag = FCC_TAG_DELTATIME;
                fcc_taglen = 2 * 4;

                ret = store16(context, id, fcc_tag);
                if (ret)
                    goto done;
                ret = store16(context, id, fcc_taglen);
                if (ret)
                    goto done;
                ret = store32(context, id, os_ctx->time_offset);
                if (ret)
                    goto done;
                ret = store32(context, id, os_ctx->usec_offset);
                if (ret)
                    goto done;
            }
        }
        invalidate_cache(data);
        goto done;
    }

    /* Verify a valid version number is there. */
    invalidate_cache(data);
    if (read(f, fcc_fvno, 2) != 2) {
        ret = KRB5_CC_FORMAT;
        goto done;
    }
    data->version = load_16_be(fcc_fvno);
    if (data->version != FVNO_4 && data->version != FVNO_3 &&
        data->version != FVNO_2 && data->version != FVNO_1) {
        ret = KRB5_CCACHE_BADVNO;
        goto done;
    }

    data->fd = f;

    if (data->version == FVNO_4) {
        if (read16(context, id, &fcc_flen) || fcc_flen > sizeof(buf)) {
            ret = KRB5_CC_FORMAT;
            goto done;
        }

        while (fcc_flen) {
            if (fcc_flen < 2 * 2 || read16(context, id, &fcc_tag) ||
                read16(context, id, &fcc_taglen) ||
                fcc_taglen > fcc_flen - 2 * 2) {
                ret = KRB5_CC_FORMAT;
                goto done;
            }

            switch (fcc_tag) {
            case FCC_TAG_DELTATIME:
                if (fcc_taglen != 2 * 4) {
                    ret = KRB5_CC_FORMAT;
                    goto done;
                }
                if (!(context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) ||
                    (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID)) {
                    if (read_bytes(context, id, buf, fcc_taglen)) {
                        ret = KRB5_CC_FORMAT;
                        goto done;
                    }
                    break;
                }
                if (read32(context, id, NULL, &time_offset) ||
                    read32(context, id, NULL, &usec_offset)) {
                    ret = KRB5_CC_FORMAT;
                    goto done;
                }
                os_ctx->time_offset = time_offset;
                os_ctx->usec_offset = usec_offset;
                os_ctx->os_flags =
                    ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) |
                     KRB5_OS_TOFFSET_VALID);
                break;
            default:
                if (fcc_taglen && read_bytes(context, id, buf, fcc_taglen)) {
                    ret = KRB5_CC_FORMAT;
                    goto done;
                }
                break;
            }
            fcc_flen -= (2 * 2 + fcc_taglen);
        }
    }

done:
    if (ret) {
        data->fd = -1;
        (void)krb5_unlock_file(context, f);
        (void)close(f);
    }
    return ret;
}