Exemplo n.º 1
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.º 2
0
krb5_error_code KRB5_CALLCONV
krb5_rc_dfl_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep)
{
    krb5_error_code ret;
    struct dfl_data *t;
    krb5_int32 now;

    ret = krb5_timeofday(context, &now);
    if (ret)
        return ret;

    ret = k5_mutex_lock(&id->lock);
    if (ret)
        return ret;

    switch(rc_store(context, id, rep, now, FALSE)) {
    case CMP_MALLOC:
        k5_mutex_unlock(&id->lock);
        return KRB5_RC_MALLOC;
    case CMP_REPLAY:
        k5_mutex_unlock(&id->lock);
        return KRB5KRB_AP_ERR_REPEAT;
    case 0: break;
    default: /* wtf? */ ;
    }
    t = (struct dfl_data *)id->data;
#ifndef NOIOSTUFF
    ret = krb5_rc_io_store(context, t, rep);
    if (ret) {
        k5_mutex_unlock(&id->lock);
        return ret;
    }
#endif
    /* Shall we automatically expunge? */
    if (t->nummisses > t->numhits + EXCESSREPS)
    {
        ret = krb5_rc_dfl_expunge_locked(context, id);
        k5_mutex_unlock(&id->lock);
        return ret;
    }
#ifndef NOIOSTUFF
    else
    {
        if (krb5_rc_io_sync(context, &t->d)) {
            k5_mutex_unlock(&id->lock);
            return KRB5_RC_IO;
        }
    }
#endif
    k5_mutex_unlock(&id->lock);
    return 0;
}
Exemplo n.º 3
0
static krb5_error_code KRB5_CALLCONV
krb5_rc_dfl_init_locked(krb5_context context, krb5_rcache id, krb5_deltat lifespan)
{
    struct dfl_data *t = (struct dfl_data *)id->data;
    krb5_error_code retval;

    t->lifespan = lifespan ? lifespan : context->clockskew;
    /* default to clockskew from the context */
#ifndef NOIOSTUFF
    if ((retval = krb5_rc_io_creat(context, &t->d, &t->name))) {
        return retval;
    }
    if ((krb5_rc_io_write(context, &t->d,
                          (krb5_pointer) &t->lifespan, sizeof(t->lifespan))
         || krb5_rc_io_sync(context, &t->d))) {
        return KRB5_RC_IO;
    }
#endif
    return 0;
}
Exemplo n.º 4
0
static krb5_error_code
krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
{
    struct dfl_data *t = (struct dfl_data *)id->data;
#ifdef NOIOSTUFF
    unsigned int i;
    struct authlist **q;
    struct authlist **qt;
    struct authlist *r;
    struct authlist *rt;
    krb5_int32 now;

    if (krb5_timestamp(context, &now))
        now = 0;

    for (q = &t->a; *q; q = qt) {
        qt = &(*q)->na;
        if (alive(now, &(*q)->rep, t->lifespan) == CMP_EXPIRED) {
            free((*q)->rep.client);
            free((*q)->rep.server);
            if ((*q)->rep.msghash)
                free((*q)->rep.msghash);
            free(*q);
            *q = *qt; /* why doesn't this feel right? */
        }
    }
    for (i = 0; i < t->hsize; i++)
        t->h[i] = (struct authlist *) 0;
    for (r = t->a; r; r = r->na) {
        i = hash(&r->rep, t->hsize);
        rt = t->h[i];
        t->h[i] = r;
        r->nh = rt;
    }
    return 0;
#else
    struct authlist *q;
    char *name;
    krb5_error_code retval = 0;
    krb5_rcache tmp;
    krb5_deltat lifespan = t->lifespan;  /* save original lifespan */

    if (! t->recovering) {
        name = t->name;
        t->name = 0;            /* Clear name so it isn't freed */
        (void) krb5_rc_dfl_close_no_free(context, id);
        retval = krb5_rc_dfl_resolve(context, id, name);
        free(name);
        if (retval)
            return retval;
        retval = krb5_rc_dfl_recover_locked(context, id);
        if (retval)
            return retval;
        t = (struct dfl_data *)id->data; /* point to recovered cache */
    }

    retval = krb5_rc_resolve_type(context, &tmp, "dfl");
    if (retval)
        return retval;
    retval = krb5_rc_resolve(context, tmp, 0);
    if (retval)
        goto cleanup;
    retval = krb5_rc_initialize(context, tmp, lifespan);
    if (retval)
        goto cleanup;
    for (q = t->a; q; q = q->na) {
        if (krb5_rc_io_store(context, (struct dfl_data *)tmp->data, &q->rep)) {
            retval = KRB5_RC_IO;
            goto cleanup;
        }
    }
    /* NOTE: We set retval in case we have an error */
    retval = KRB5_RC_IO;
    if (krb5_rc_io_sync(context, &((struct dfl_data *)tmp->data)->d))
        goto cleanup;
    if (krb5_rc_io_sync(context, &t->d))
        goto cleanup;
    if (krb5_rc_io_move(context, &t->d, &((struct dfl_data *)tmp->data)->d))
        goto cleanup;
    retval = 0;
cleanup:
    (void) krb5_rc_dfl_close(context, tmp);
    return retval;
#endif
}