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; }
static krb5_error_code krb5_rc_io_store(krb5_context context, struct dfl_data *t, krb5_donot_replay *rep) { unsigned int clientlen, serverlen, len; char *buf, *ptr; krb5_error_code ret; clientlen = strlen(rep->client) + 1; serverlen = strlen(rep->server) + 1; len = sizeof(clientlen) + clientlen + sizeof(serverlen) + serverlen + sizeof(rep->cusec) + sizeof(rep->ctime); buf = malloc(len); if (buf == 0) return KRB5_RC_MALLOC; ptr = buf; memcpy(ptr, &clientlen, sizeof(clientlen)); ptr += sizeof(clientlen); memcpy(ptr, rep->client, clientlen); ptr += clientlen; memcpy(ptr, &serverlen, sizeof(serverlen)); ptr += sizeof(serverlen); memcpy(ptr, rep->server, serverlen); ptr += serverlen; memcpy(ptr, &rep->cusec, sizeof(rep->cusec)); ptr += sizeof(rep->cusec); memcpy(ptr, &rep->ctime, sizeof(rep->ctime)); ptr += sizeof(rep->ctime); ret = krb5_rc_io_write(context, &t->d, buf, len); free(buf); return ret; }
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; }
static krb5_error_code krb5_rc_io_store(krb5_context context, struct dfl_data *t, krb5_donot_replay *rep) { size_t clientlen, serverlen; unsigned int len; krb5_error_code ret; struct k5buf buf, extbuf; char *extstr; clientlen = strlen(rep->client); serverlen = strlen(rep->server); if (rep->msghash) { /* * Write a hash extension record, to be followed by a record * in regular format (without the message hash) for the * benefit of old implementations. */ /* Format the extension value so we know its length. */ k5_buf_init_dynamic(&extbuf); k5_buf_add_fmt(&extbuf, "HASH:%s %lu:%s %lu:%s", rep->msghash, (unsigned long)clientlen, rep->client, (unsigned long)serverlen, rep->server); if (k5_buf_status(&extbuf) != 0) return KRB5_RC_MALLOC; extstr = extbuf.data; /* * Put the extension value into the server field of a * regular-format record, with an empty client field. */ k5_buf_init_dynamic(&buf); len = 1; k5_buf_add_len(&buf, (char *)&len, sizeof(len)); k5_buf_add_len(&buf, "", 1); len = strlen(extstr) + 1; k5_buf_add_len(&buf, (char *)&len, sizeof(len)); k5_buf_add_len(&buf, extstr, len); k5_buf_add_len(&buf, (char *)&rep->cusec, sizeof(rep->cusec)); k5_buf_add_len(&buf, (char *)&rep->ctime, sizeof(rep->ctime)); free(extstr); } else /* No extension record needed. */ k5_buf_init_dynamic(&buf); len = clientlen + 1; k5_buf_add_len(&buf, (char *)&len, sizeof(len)); k5_buf_add_len(&buf, rep->client, len); len = serverlen + 1; k5_buf_add_len(&buf, (char *)&len, sizeof(len)); k5_buf_add_len(&buf, rep->server, len); k5_buf_add_len(&buf, (char *)&rep->cusec, sizeof(rep->cusec)); k5_buf_add_len(&buf, (char *)&rep->ctime, sizeof(rep->ctime)); if (k5_buf_status(&buf) != 0) return KRB5_RC_MALLOC; ret = krb5_rc_io_write(context, &t->d, buf.data, buf.len); k5_buf_free(&buf); return ret; }