static krb5_error_code fkt_start_seq_get_int(krb5_context context, krb5_keytab id, int flags, int exclusive, krb5_kt_cursor *c) { int8_t pvno, tag; krb5_error_code ret; struct fkt_data *d = id->data; c->fd = open (d->filename, flags); if (c->fd < 0) { ret = errno; krb5_set_error_message(context, ret, N_("keytab %s open failed: %s", ""), d->filename, strerror(ret)); return ret; } rk_cloexec(c->fd); ret = _krb5_xlock(context, c->fd, exclusive, d->filename); if (ret) { close(c->fd); return ret; } c->sp = krb5_storage_from_fd(c->fd); if (c->sp == NULL) { _krb5_xunlock(context, c->fd); close(c->fd); return krb5_enomem(context); } krb5_storage_set_eof_code(c->sp, KRB5_KT_END); ret = krb5_ret_int8(c->sp, &pvno); if(ret) { krb5_storage_free(c->sp); _krb5_xunlock(context, c->fd); close(c->fd); krb5_clear_error_message(context); return ret; } if(pvno != 5) { krb5_storage_free(c->sp); _krb5_xunlock(context, c->fd); close(c->fd); krb5_clear_error_message (context); return KRB5_KEYTAB_BADVNO; } ret = krb5_ret_int8(c->sp, &tag); if (ret) { krb5_storage_free(c->sp); _krb5_xunlock(context, c->fd); close(c->fd); krb5_clear_error_message(context); return ret; } id->version = tag; storage_set_flags(context, c->sp, id->version); return 0; }
static krb5_error_code KRB5_CALLCONV fkt_end_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursor) { krb5_storage_free(cursor->sp); _krb5_xunlock(context, cursor->fd); close(cursor->fd); return 0; }
krb5_error_code _krb5_erase_file(krb5_context context, const char *filename) { int fd; struct stat sb1, sb2; int ret; ret = lstat (filename, &sb1); if (ret < 0) return errno; fd = open(filename, O_RDWR | O_BINARY); if(fd < 0) { if(errno == ENOENT) return 0; else return errno; } rk_cloexec(fd); ret = _krb5_xlock(context, fd, 1, filename); if (ret) { close(fd); return ret; } if (unlink(filename) < 0) { _krb5_xunlock(context, fd); close (fd); return errno; } ret = fstat (fd, &sb2); if (ret < 0) { _krb5_xunlock(context, fd); close (fd); return errno; } /* check if someone was playing with symlinks */ if (sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) { _krb5_xunlock(context, fd); close (fd); return EPERM; } /* there are still hard links to this file */ if (sb2.st_nlink != 0) { _krb5_xunlock(context, fd); close (fd); return 0; } ret = scrub_file (fd); if (ret) { _krb5_xunlock(context, fd); close(fd); return ret; } ret = _krb5_xunlock(context, fd); close (fd); return ret; }
static krb5_error_code fcc_unlock(krb5_context context, int fd) { return _krb5_xunlock(context, fd); }
static krb5_error_code KRB5_CALLCONV fkt_add_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) { int ret; int fd; krb5_storage *sp; struct fkt_data *d = id->data; krb5_data keytab; int32_t len; fd = open (d->filename, O_RDWR | O_BINARY | O_CLOEXEC); if (fd < 0) { fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, 0600); if (fd < 0) { ret = errno; krb5_set_error_message(context, ret, N_("open(%s): %s", ""), d->filename, strerror(ret)); return ret; } rk_cloexec(fd); ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); return ret; } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = fkt_setup_keytab(context, id, sp); if(ret) { goto out; } storage_set_flags(context, sp, id->version); } else { int8_t pvno, tag; rk_cloexec(fd); ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); return ret; } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = krb5_ret_int8(sp, &pvno); if(ret) { /* we probably have a zero byte file, so try to set it up properly */ ret = fkt_setup_keytab(context, id, sp); if(ret) { krb5_set_error_message(context, ret, N_("%s: keytab is corrupted: %s", ""), d->filename, strerror(ret)); goto out; } storage_set_flags(context, sp, id->version); } else { if(pvno != 5) { ret = KRB5_KEYTAB_BADVNO; krb5_set_error_message(context, ret, N_("Bad version in keytab %s", ""), d->filename); goto out; } ret = krb5_ret_int8 (sp, &tag); if (ret) { krb5_set_error_message(context, ret, N_("failed reading tag from " "keytab %s", ""), d->filename); goto out; } id->version = tag; storage_set_flags(context, sp, id->version); } } { krb5_storage *emem; emem = krb5_storage_emem(); if(emem == NULL) { ret = krb5_enomem(context); goto out; } ret = krb5_kt_store_principal(context, emem, entry->principal); if(ret) { krb5_set_error_message(context, ret, N_("Failed storing principal " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_store_int32 (emem, entry->timestamp); if(ret) { krb5_set_error_message(context, ret, N_("Failed storing timpstamp " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_store_int8 (emem, entry->vno % 256); if(ret) { krb5_set_error_message(context, ret, N_("Failed storing kvno " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_kt_store_keyblock (context, d, emem, &entry->keyblock); if(ret) { krb5_storage_free(emem); goto out; } if ((d->flags & KRB5_KT_FL_JAVA) == 0) { ret = krb5_store_int32 (emem, entry->vno); if (ret) { krb5_set_error_message(context, ret, N_("Failed storing extended kvno " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_store_uint32 (emem, entry->flags); if (ret) { krb5_set_error_message(context, ret, N_("Failed storing extended kvno " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } } ret = krb5_storage_to_data(emem, &keytab); krb5_storage_free(emem); if(ret) { krb5_set_error_message(context, ret, N_("Failed converting keytab entry " "to memory block for keytab %s", ""), d->filename); goto out; } } while(1) { ret = krb5_ret_int32(sp, &len); if(ret == KRB5_KT_END) { len = keytab.length; break; } if(len < 0) { len = -len; if(len >= (int)keytab.length) { krb5_storage_seek(sp, -4, SEEK_CUR); break; } } krb5_storage_seek(sp, len, SEEK_CUR); } ret = krb5_store_int32(sp, len); if(krb5_storage_write(sp, keytab.data, keytab.length) < 0) { ret = errno; krb5_set_error_message(context, ret, N_("Failed writing keytab block " "in keytab %s: %s", ""), d->filename, strerror(ret)); } memset(keytab.data, 0, keytab.length); krb5_data_free(&keytab); out: krb5_storage_free(sp); _krb5_xunlock(context, fd); close(fd); return ret; }
static krb5_error_code fkt_add_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) { int ret; int fd; krb5_storage *sp; struct fkt_data *d = id->data; krb5_data keytab; int32_t len; fd = open (d->filename, O_RDWR | O_BINARY); if (fd < 0) { fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600); if (fd < 0) { ret = errno; krb5_set_error_string(context, "open(%s): %s", d->filename, strerror(ret)); return ret; } ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); return ret; } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = fkt_setup_keytab(context, id, sp); if(ret) { goto out; } storage_set_flags(context, sp, id->version); } else { int8_t pvno, tag; ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); return ret; } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = krb5_ret_int8(sp, &pvno); if(ret) { /* we probably have a zero byte file, so try to set it up properly */ ret = fkt_setup_keytab(context, id, sp); if(ret) { krb5_set_error_string(context, "%s: keytab is corrupted: %s", d->filename, strerror(ret)); goto out; } storage_set_flags(context, sp, id->version); } else { if(pvno != 5) { ret = KRB5_KEYTAB_BADVNO; krb5_set_error_string(context, "%s: %s", d->filename, strerror(ret)); goto out; } ret = krb5_ret_int8 (sp, &tag); if (ret) { krb5_set_error_string(context, "%s: reading tag: %s", d->filename, strerror(ret)); goto out; } id->version = tag; storage_set_flags(context, sp, id->version); } } { krb5_storage *emem; emem = krb5_storage_emem(); if(emem == NULL) { ret = ENOMEM; krb5_set_error_string (context, "malloc: out of memory"); goto out; } ret = krb5_kt_store_principal(context, emem, entry->principal); if(ret) { krb5_storage_free(emem); goto out; } ret = krb5_store_int32 (emem, entry->timestamp); if(ret) { krb5_storage_free(emem); goto out; } ret = krb5_store_int8 (emem, entry->vno % 256); if(ret) { krb5_storage_free(emem); goto out; } ret = krb5_kt_store_keyblock (context, emem, &entry->keyblock); if(ret) { krb5_storage_free(emem); goto out; } if ((d->flags & KRB5_KT_FL_JAVA) == 0) { ret = krb5_store_int32 (emem, entry->vno); if (ret) { krb5_storage_free(emem); goto out; } } ret = krb5_storage_to_data(emem, &keytab); krb5_storage_free(emem); if(ret) goto out; } while(1) { ret = krb5_ret_int32(sp, &len); if(ret == KRB5_KT_END) { len = keytab.length; break; } if(len < 0) { len = -len; if(len >= keytab.length) { krb5_storage_seek(sp, -4, SEEK_CUR); break; } } krb5_storage_seek(sp, len, SEEK_CUR); } ret = krb5_store_int32(sp, len); if(krb5_storage_write(sp, keytab.data, keytab.length) < 0) ret = errno; memset(keytab.data, 0, keytab.length); krb5_data_free(&keytab); out: krb5_storage_free(sp); _krb5_xunlock(context, fd); close(fd); return ret; }