keytab_file.c revision 102644
155682Smarkm/* 2102644Snectar * Copyright (c) 1997 - 2002 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "krb5_locl.h" 3555682Smarkm 36102644SnectarRCSID("$Id: keytab_file.c,v 1.11 2002/05/28 12:57:27 joda Exp $"); 3755682Smarkm 3855682Smarkm#define KRB5_KT_VNO_1 1 3955682Smarkm#define KRB5_KT_VNO_2 2 4055682Smarkm#define KRB5_KT_VNO KRB5_KT_VNO_2 4155682Smarkm 4255682Smarkm/* file operations -------------------------------------------- */ 4355682Smarkm 4455682Smarkmstruct fkt_data { 4555682Smarkm char *filename; 4655682Smarkm}; 4755682Smarkm 4855682Smarkmstatic krb5_error_code 4978527Sassarkrb5_kt_ret_data(krb5_context context, 5078527Sassar krb5_storage *sp, 5155682Smarkm krb5_data *data) 5255682Smarkm{ 5355682Smarkm int ret; 5455682Smarkm int16_t size; 5555682Smarkm ret = krb5_ret_int16(sp, &size); 5655682Smarkm if(ret) 5755682Smarkm return ret; 5855682Smarkm data->length = size; 5955682Smarkm data->data = malloc(size); 6078527Sassar if (data->data == NULL) { 6178527Sassar krb5_set_error_string (context, "malloc: out of memory"); 6255682Smarkm return ENOMEM; 6378527Sassar } 64102644Snectar ret = krb5_storage_read(sp, data->data, size); 6555682Smarkm if(ret != size) 6655682Smarkm return (ret < 0)? errno : KRB5_KT_END; 6755682Smarkm return 0; 6855682Smarkm} 6955682Smarkm 7055682Smarkmstatic krb5_error_code 7178527Sassarkrb5_kt_ret_string(krb5_context context, 7278527Sassar krb5_storage *sp, 7355682Smarkm general_string *data) 7455682Smarkm{ 7555682Smarkm int ret; 7655682Smarkm int16_t size; 7755682Smarkm ret = krb5_ret_int16(sp, &size); 7855682Smarkm if(ret) 7955682Smarkm return ret; 8055682Smarkm *data = malloc(size + 1); 8178527Sassar if (*data == NULL) { 8278527Sassar krb5_set_error_string (context, "malloc: out of memory"); 8355682Smarkm return ENOMEM; 8478527Sassar } 85102644Snectar ret = krb5_storage_read(sp, *data, size); 8655682Smarkm (*data)[size] = '\0'; 8755682Smarkm if(ret != size) 8855682Smarkm return (ret < 0)? errno : KRB5_KT_END; 8955682Smarkm return 0; 9055682Smarkm} 9155682Smarkm 9255682Smarkmstatic krb5_error_code 9378527Sassarkrb5_kt_store_data(krb5_context context, 9478527Sassar krb5_storage *sp, 9555682Smarkm krb5_data data) 9655682Smarkm{ 9755682Smarkm int ret; 9855682Smarkm ret = krb5_store_int16(sp, data.length); 9955682Smarkm if(ret < 0) 10055682Smarkm return ret; 101102644Snectar ret = krb5_storage_write(sp, data.data, data.length); 10255682Smarkm if(ret != data.length){ 10355682Smarkm if(ret < 0) 10455682Smarkm return errno; 10555682Smarkm return KRB5_KT_END; 10655682Smarkm } 10755682Smarkm return 0; 10855682Smarkm} 10955682Smarkm 11055682Smarkmstatic krb5_error_code 11155682Smarkmkrb5_kt_store_string(krb5_storage *sp, 11255682Smarkm general_string data) 11355682Smarkm{ 11455682Smarkm int ret; 11555682Smarkm size_t len = strlen(data); 11655682Smarkm ret = krb5_store_int16(sp, len); 11755682Smarkm if(ret < 0) 11855682Smarkm return ret; 119102644Snectar ret = krb5_storage_write(sp, data, len); 12055682Smarkm if(ret != len){ 12155682Smarkm if(ret < 0) 12255682Smarkm return errno; 12355682Smarkm return KRB5_KT_END; 12455682Smarkm } 12555682Smarkm return 0; 12655682Smarkm} 12755682Smarkm 12855682Smarkmstatic krb5_error_code 12978527Sassarkrb5_kt_ret_keyblock(krb5_context context, krb5_storage *sp, krb5_keyblock *p) 13055682Smarkm{ 13155682Smarkm int ret; 13255682Smarkm int16_t tmp; 13355682Smarkm 13455682Smarkm ret = krb5_ret_int16(sp, &tmp); /* keytype + etype */ 13555682Smarkm if(ret) return ret; 13655682Smarkm p->keytype = tmp; 13778527Sassar ret = krb5_kt_ret_data(context, sp, &p->keyvalue); 13855682Smarkm return ret; 13955682Smarkm} 14055682Smarkm 14155682Smarkmstatic krb5_error_code 14278527Sassarkrb5_kt_store_keyblock(krb5_context context, 14378527Sassar krb5_storage *sp, 14455682Smarkm krb5_keyblock *p) 14555682Smarkm{ 14655682Smarkm int ret; 14755682Smarkm 14855682Smarkm ret = krb5_store_int16(sp, p->keytype); /* keytype + etype */ 14955682Smarkm if(ret) return ret; 15078527Sassar ret = krb5_kt_store_data(context, sp, p->keyvalue); 15155682Smarkm return ret; 15255682Smarkm} 15355682Smarkm 15455682Smarkm 15555682Smarkmstatic krb5_error_code 15678527Sassarkrb5_kt_ret_principal(krb5_context context, 15778527Sassar krb5_storage *sp, 15855682Smarkm krb5_principal *princ) 15955682Smarkm{ 16055682Smarkm int i; 16155682Smarkm int ret; 16255682Smarkm krb5_principal p; 16355682Smarkm int16_t tmp; 16455682Smarkm 16555682Smarkm ALLOC(p, 1); 16678527Sassar if(p == NULL) { 16778527Sassar krb5_set_error_string (context, "malloc: out of memory"); 16855682Smarkm return ENOMEM; 16978527Sassar } 17055682Smarkm 17155682Smarkm ret = krb5_ret_int16(sp, &tmp); 17255682Smarkm if(ret) 17355682Smarkm return ret; 174102644Snectar if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 17555682Smarkm tmp--; 17655682Smarkm p->name.name_string.len = tmp; 17778527Sassar ret = krb5_kt_ret_string(context, sp, &p->realm); 17878527Sassar if(ret) 17978527Sassar return ret; 18055682Smarkm p->name.name_string.val = calloc(p->name.name_string.len, 18155682Smarkm sizeof(*p->name.name_string.val)); 18278527Sassar if(p->name.name_string.val == NULL) { 18378527Sassar krb5_set_error_string (context, "malloc: out of memory"); 18455682Smarkm return ENOMEM; 18578527Sassar } 18655682Smarkm for(i = 0; i < p->name.name_string.len; i++){ 18778527Sassar ret = krb5_kt_ret_string(context, sp, p->name.name_string.val + i); 18878527Sassar if(ret) 18978527Sassar return ret; 19055682Smarkm } 19155682Smarkm if (krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) 19255682Smarkm p->name.name_type = KRB5_NT_UNKNOWN; 19355682Smarkm else { 19455682Smarkm int32_t tmp32; 19555682Smarkm ret = krb5_ret_int32(sp, &tmp32); 19655682Smarkm p->name.name_type = tmp32; 19755682Smarkm if (ret) 19855682Smarkm return ret; 19955682Smarkm } 20055682Smarkm *princ = p; 20155682Smarkm return 0; 20255682Smarkm} 20355682Smarkm 20455682Smarkmstatic krb5_error_code 20578527Sassarkrb5_kt_store_principal(krb5_context context, 20678527Sassar krb5_storage *sp, 20755682Smarkm krb5_principal p) 20855682Smarkm{ 20955682Smarkm int i; 21055682Smarkm int ret; 21155682Smarkm 21255682Smarkm if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 21355682Smarkm ret = krb5_store_int16(sp, p->name.name_string.len + 1); 21455682Smarkm else 21555682Smarkm ret = krb5_store_int16(sp, p->name.name_string.len); 21655682Smarkm if(ret) return ret; 21755682Smarkm ret = krb5_kt_store_string(sp, p->realm); 21855682Smarkm if(ret) return ret; 21955682Smarkm for(i = 0; i < p->name.name_string.len; i++){ 22055682Smarkm ret = krb5_kt_store_string(sp, p->name.name_string.val[i]); 22178527Sassar if(ret) 22278527Sassar return ret; 22355682Smarkm } 22455682Smarkm if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { 22555682Smarkm ret = krb5_store_int32(sp, p->name.name_type); 22655682Smarkm if(ret) 22755682Smarkm return ret; 22855682Smarkm } 22955682Smarkm 23055682Smarkm return 0; 23155682Smarkm} 23255682Smarkm 23355682Smarkmstatic krb5_error_code 23455682Smarkmfkt_resolve(krb5_context context, const char *name, krb5_keytab id) 23555682Smarkm{ 23655682Smarkm struct fkt_data *d; 23778527Sassar 23855682Smarkm d = malloc(sizeof(*d)); 23978527Sassar if(d == NULL) { 24078527Sassar krb5_set_error_string (context, "malloc: out of memory"); 24155682Smarkm return ENOMEM; 24278527Sassar } 24355682Smarkm d->filename = strdup(name); 24455682Smarkm if(d->filename == NULL) { 24555682Smarkm free(d); 24678527Sassar krb5_set_error_string (context, "malloc: out of memory"); 24755682Smarkm return ENOMEM; 24855682Smarkm } 24955682Smarkm id->data = d; 25055682Smarkm return 0; 25155682Smarkm} 25255682Smarkm 25355682Smarkmstatic krb5_error_code 25455682Smarkmfkt_close(krb5_context context, krb5_keytab id) 25555682Smarkm{ 25655682Smarkm struct fkt_data *d = id->data; 25755682Smarkm free(d->filename); 25855682Smarkm free(d); 25955682Smarkm return 0; 26055682Smarkm} 26155682Smarkm 26255682Smarkmstatic krb5_error_code 26355682Smarkmfkt_get_name(krb5_context context, 26455682Smarkm krb5_keytab id, 26555682Smarkm char *name, 26655682Smarkm size_t namesize) 26755682Smarkm{ 26855682Smarkm /* This function is XXX */ 26955682Smarkm struct fkt_data *d = id->data; 27055682Smarkm strlcpy(name, d->filename, namesize); 27155682Smarkm return 0; 27255682Smarkm} 27355682Smarkm 27455682Smarkmstatic void 27555682Smarkmstorage_set_flags(krb5_context context, krb5_storage *sp, int vno) 27655682Smarkm{ 27755682Smarkm int flags = 0; 27855682Smarkm switch(vno) { 27955682Smarkm case KRB5_KT_VNO_1: 28055682Smarkm flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS; 28155682Smarkm flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE; 28255682Smarkm flags |= KRB5_STORAGE_HOST_BYTEORDER; 28355682Smarkm break; 28455682Smarkm case KRB5_KT_VNO_2: 28555682Smarkm break; 28655682Smarkm default: 287102644Snectar krb5_warnx(context, 288102644Snectar "storage_set_flags called with bad vno (%d)", vno); 28955682Smarkm } 29055682Smarkm krb5_storage_set_flags(sp, flags); 29155682Smarkm} 29255682Smarkm 29355682Smarkmstatic krb5_error_code 29455682Smarkmfkt_start_seq_get_int(krb5_context context, 29555682Smarkm krb5_keytab id, 29655682Smarkm int flags, 29755682Smarkm krb5_kt_cursor *c) 29855682Smarkm{ 29955682Smarkm int8_t pvno, tag; 30055682Smarkm krb5_error_code ret; 30155682Smarkm struct fkt_data *d = id->data; 30255682Smarkm 30355682Smarkm c->fd = open (d->filename, flags); 30478527Sassar if (c->fd < 0) { 30578527Sassar ret = errno; 30678527Sassar krb5_set_error_string(context, "open(%s): %s", d->filename, 30778527Sassar strerror(ret)); 30878527Sassar return ret; 30978527Sassar } 31055682Smarkm c->sp = krb5_storage_from_fd(c->fd); 311102644Snectar krb5_storage_set_eof_code(c->sp, KRB5_KT_END); 31255682Smarkm ret = krb5_ret_int8(c->sp, &pvno); 31355682Smarkm if(ret) { 31455682Smarkm krb5_storage_free(c->sp); 31555682Smarkm close(c->fd); 31655682Smarkm return ret; 31755682Smarkm } 31855682Smarkm if(pvno != 5) { 31955682Smarkm krb5_storage_free(c->sp); 32055682Smarkm close(c->fd); 32178527Sassar krb5_clear_error_string (context); 32255682Smarkm return KRB5_KEYTAB_BADVNO; 32355682Smarkm } 32455682Smarkm ret = krb5_ret_int8(c->sp, &tag); 32555682Smarkm if (ret) { 32655682Smarkm krb5_storage_free(c->sp); 32755682Smarkm close(c->fd); 32855682Smarkm return ret; 32955682Smarkm } 33055682Smarkm id->version = tag; 33155682Smarkm storage_set_flags(context, c->sp, id->version); 33255682Smarkm return 0; 33355682Smarkm} 33455682Smarkm 33555682Smarkmstatic krb5_error_code 33655682Smarkmfkt_start_seq_get(krb5_context context, 33755682Smarkm krb5_keytab id, 33855682Smarkm krb5_kt_cursor *c) 33955682Smarkm{ 34055682Smarkm return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY, c); 34155682Smarkm} 34255682Smarkm 34355682Smarkmstatic krb5_error_code 34455682Smarkmfkt_next_entry_int(krb5_context context, 34555682Smarkm krb5_keytab id, 34655682Smarkm krb5_keytab_entry *entry, 34755682Smarkm krb5_kt_cursor *cursor, 34855682Smarkm off_t *start, 34955682Smarkm off_t *end) 35055682Smarkm{ 35155682Smarkm int32_t len; 35255682Smarkm int ret; 35355682Smarkm int8_t tmp8; 35455682Smarkm int32_t tmp32; 355102644Snectar off_t pos, curpos; 35655682Smarkm 357102644Snectar pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); 35855682Smarkmloop: 35955682Smarkm ret = krb5_ret_int32(cursor->sp, &len); 36055682Smarkm if (ret) 36155682Smarkm return ret; 36255682Smarkm if(len < 0) { 363102644Snectar pos = krb5_storage_seek(cursor->sp, -len, SEEK_CUR); 36455682Smarkm goto loop; 36555682Smarkm } 36678527Sassar ret = krb5_kt_ret_principal (context, cursor->sp, &entry->principal); 36755682Smarkm if (ret) 36855682Smarkm goto out; 36955682Smarkm ret = krb5_ret_int32(cursor->sp, &tmp32); 37055682Smarkm entry->timestamp = tmp32; 37155682Smarkm if (ret) 37255682Smarkm goto out; 37355682Smarkm ret = krb5_ret_int8(cursor->sp, &tmp8); 37455682Smarkm if (ret) 37555682Smarkm goto out; 37655682Smarkm entry->vno = tmp8; 37778527Sassar ret = krb5_kt_ret_keyblock (context, cursor->sp, &entry->keyblock); 37855682Smarkm if (ret) 37955682Smarkm goto out; 380102644Snectar /* there might be a 32 bit kvno here 381102644Snectar * if it's zero, assume that the 8bit one was right, 382102644Snectar * otherwise trust the new value */ 383102644Snectar curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); 384102644Snectar if(len + 4 + pos - curpos == 4) { 385102644Snectar ret = krb5_ret_int32(cursor->sp, &tmp32); 386102644Snectar if (ret == 0 && tmp32 != 0) { 387102644Snectar entry->vno = tmp32; 388102644Snectar } 389102644Snectar } 39055682Smarkm if(start) *start = pos; 39155682Smarkm if(end) *end = *start + 4 + len; 39255682Smarkm out: 393102644Snectar krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET); 39455682Smarkm return ret; 39555682Smarkm} 39655682Smarkm 39755682Smarkmstatic krb5_error_code 39855682Smarkmfkt_next_entry(krb5_context context, 39955682Smarkm krb5_keytab id, 40055682Smarkm krb5_keytab_entry *entry, 40155682Smarkm krb5_kt_cursor *cursor) 40255682Smarkm{ 40355682Smarkm return fkt_next_entry_int(context, id, entry, cursor, NULL, NULL); 40455682Smarkm} 40555682Smarkm 40655682Smarkmstatic krb5_error_code 40755682Smarkmfkt_end_seq_get(krb5_context context, 40855682Smarkm krb5_keytab id, 40955682Smarkm krb5_kt_cursor *cursor) 41055682Smarkm{ 41155682Smarkm krb5_storage_free(cursor->sp); 41255682Smarkm close(cursor->fd); 41355682Smarkm return 0; 41455682Smarkm} 41555682Smarkm 41655682Smarkmstatic krb5_error_code 417102644Snectarfkt_setup_keytab(krb5_context context, 418102644Snectar krb5_keytab id, 419102644Snectar krb5_storage *sp) 420102644Snectar{ 421102644Snectar krb5_error_code ret; 422102644Snectar ret = krb5_store_int8(sp, 5); 423102644Snectar if(ret) 424102644Snectar return ret; 425102644Snectar if(id->version == 0) 426102644Snectar id->version = KRB5_KT_VNO; 427102644Snectar return krb5_store_int8 (sp, id->version); 428102644Snectar} 429102644Snectar 430102644Snectarstatic krb5_error_code 43155682Smarkmfkt_add_entry(krb5_context context, 43255682Smarkm krb5_keytab id, 43355682Smarkm krb5_keytab_entry *entry) 43455682Smarkm{ 43555682Smarkm int ret; 43655682Smarkm int fd; 43755682Smarkm krb5_storage *sp; 43855682Smarkm struct fkt_data *d = id->data; 43955682Smarkm krb5_data keytab; 44055682Smarkm int32_t len; 44155682Smarkm 44255682Smarkm fd = open (d->filename, O_RDWR | O_BINARY); 44355682Smarkm if (fd < 0) { 44455682Smarkm fd = open (d->filename, O_RDWR | O_CREAT | O_BINARY, 0600); 44578527Sassar if (fd < 0) { 44678527Sassar ret = errno; 44778527Sassar krb5_set_error_string(context, "open(%s): %s", d->filename, 44878527Sassar strerror(ret)); 44978527Sassar return ret; 45078527Sassar } 45155682Smarkm sp = krb5_storage_from_fd(fd); 452102644Snectar krb5_storage_set_eof_code(sp, KRB5_KT_END); 453102644Snectar ret = fkt_setup_keytab(context, id, sp); 45455682Smarkm if(ret) { 45555682Smarkm krb5_storage_free(sp); 45655682Smarkm close(fd); 45755682Smarkm return ret; 45855682Smarkm } 45955682Smarkm storage_set_flags(context, sp, id->version); 46055682Smarkm } else { 46155682Smarkm int8_t pvno, tag; 46255682Smarkm sp = krb5_storage_from_fd(fd); 463102644Snectar krb5_storage_set_eof_code(sp, KRB5_KT_END); 46455682Smarkm ret = krb5_ret_int8(sp, &pvno); 46555682Smarkm if(ret) { 466102644Snectar /* we probably have a zero byte file, so try to set it up 467102644Snectar properly */ 468102644Snectar ret = fkt_setup_keytab(context, id, sp); 469102644Snectar if(ret) { 470102644Snectar krb5_set_error_string(context, "%s: keytab is corrupted: %s", 471102644Snectar d->filename, strerror(ret)); 472102644Snectar krb5_storage_free(sp); 473102644Snectar close(fd); 474102644Snectar return ret; 475102644Snectar } 476102644Snectar storage_set_flags(context, sp, id->version); 477102644Snectar } else { 478102644Snectar if(pvno != 5) { 479102644Snectar krb5_storage_free(sp); 480102644Snectar close(fd); 481102644Snectar krb5_clear_error_string (context); 482102644Snectar ret = KRB5_KEYTAB_BADVNO; 483102644Snectar krb5_set_error_string(context, "%s: %s", 484102644Snectar d->filename, strerror(ret)); 485102644Snectar return ret; 486102644Snectar } 487102644Snectar ret = krb5_ret_int8 (sp, &tag); 488102644Snectar if (ret) { 489102644Snectar krb5_set_error_string(context, "%s: reading tag: %s", 490102644Snectar d->filename, strerror(ret)); 491102644Snectar krb5_storage_free(sp); 492102644Snectar close(fd); 493102644Snectar return ret; 494102644Snectar } 495102644Snectar id->version = tag; 496102644Snectar storage_set_flags(context, sp, id->version); 49755682Smarkm } 49855682Smarkm } 49955682Smarkm 50055682Smarkm { 50155682Smarkm krb5_storage *emem; 50255682Smarkm emem = krb5_storage_emem(); 50355682Smarkm if(emem == NULL) { 50455682Smarkm ret = ENOMEM; 50578527Sassar krb5_set_error_string (context, "malloc: out of memory"); 50655682Smarkm goto out; 50755682Smarkm } 50878527Sassar ret = krb5_kt_store_principal(context, emem, entry->principal); 50955682Smarkm if(ret) { 51055682Smarkm krb5_storage_free(emem); 51155682Smarkm goto out; 51255682Smarkm } 51355682Smarkm ret = krb5_store_int32 (emem, entry->timestamp); 51455682Smarkm if(ret) { 51555682Smarkm krb5_storage_free(emem); 51655682Smarkm goto out; 51755682Smarkm } 518102644Snectar ret = krb5_store_int8 (emem, entry->vno % 256); 51955682Smarkm if(ret) { 52055682Smarkm krb5_storage_free(emem); 52155682Smarkm goto out; 52255682Smarkm } 52378527Sassar ret = krb5_kt_store_keyblock (context, emem, &entry->keyblock); 52455682Smarkm if(ret) { 52555682Smarkm krb5_storage_free(emem); 52655682Smarkm goto out; 52755682Smarkm } 528102644Snectar ret = krb5_store_int32 (emem, entry->vno); 529102644Snectar if (ret) { 530102644Snectar krb5_storage_free(emem); 531102644Snectar goto out; 532102644Snectar } 533102644Snectar 53455682Smarkm ret = krb5_storage_to_data(emem, &keytab); 53555682Smarkm krb5_storage_free(emem); 53655682Smarkm if(ret) 53755682Smarkm goto out; 53855682Smarkm } 53955682Smarkm 54055682Smarkm while(1) { 54155682Smarkm ret = krb5_ret_int32(sp, &len); 542102644Snectar if(ret == KRB5_KT_END) { 54355682Smarkm len = keytab.length; 54455682Smarkm break; 54555682Smarkm } 54655682Smarkm if(len < 0) { 54755682Smarkm len = -len; 54855682Smarkm if(len >= keytab.length) { 549102644Snectar krb5_storage_seek(sp, -4, SEEK_CUR); 55055682Smarkm break; 55155682Smarkm } 55255682Smarkm } 553102644Snectar krb5_storage_seek(sp, len, SEEK_CUR); 55455682Smarkm } 55555682Smarkm ret = krb5_store_int32(sp, len); 556102644Snectar if(krb5_storage_write(sp, keytab.data, keytab.length) < 0) 55755682Smarkm ret = errno; 55855682Smarkm memset(keytab.data, 0, keytab.length); 55955682Smarkm krb5_data_free(&keytab); 560102644Snectar out: 56155682Smarkm krb5_storage_free(sp); 56255682Smarkm close(fd); 56355682Smarkm return ret; 56455682Smarkm} 56555682Smarkm 56655682Smarkmstatic krb5_error_code 56755682Smarkmfkt_remove_entry(krb5_context context, 56855682Smarkm krb5_keytab id, 56955682Smarkm krb5_keytab_entry *entry) 57055682Smarkm{ 57155682Smarkm krb5_keytab_entry e; 57255682Smarkm krb5_kt_cursor cursor; 57355682Smarkm off_t pos_start, pos_end; 57455682Smarkm int found = 0; 57555682Smarkm 57655682Smarkm fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY, &cursor); 57755682Smarkm while(fkt_next_entry_int(context, id, &e, &cursor, 57855682Smarkm &pos_start, &pos_end) == 0) { 57955682Smarkm if(krb5_kt_compare(context, &e, entry->principal, 58055682Smarkm entry->vno, entry->keyblock.keytype)) { 58155682Smarkm int32_t len; 58255682Smarkm unsigned char buf[128]; 58355682Smarkm found = 1; 584102644Snectar krb5_storage_seek(cursor.sp, pos_start, SEEK_SET); 58555682Smarkm len = pos_end - pos_start - 4; 58655682Smarkm krb5_store_int32(cursor.sp, -len); 58755682Smarkm memset(buf, 0, sizeof(buf)); 58855682Smarkm while(len > 0) { 589102644Snectar krb5_storage_write(cursor.sp, buf, min(len, sizeof(buf))); 59055682Smarkm len -= min(len, sizeof(buf)); 59155682Smarkm } 59255682Smarkm } 59355682Smarkm } 59455682Smarkm krb5_kt_end_seq_get(context, id, &cursor); 59578527Sassar if (!found) { 59678527Sassar krb5_clear_error_string (context); 59755682Smarkm return KRB5_KT_NOTFOUND; 59878527Sassar } 59955682Smarkm return 0; 60055682Smarkm} 60155682Smarkm 60255682Smarkmconst krb5_kt_ops krb5_fkt_ops = { 60355682Smarkm "FILE", 60455682Smarkm fkt_resolve, 60555682Smarkm fkt_get_name, 60655682Smarkm fkt_close, 60755682Smarkm NULL, /* get */ 60855682Smarkm fkt_start_seq_get, 60955682Smarkm fkt_next_entry, 61055682Smarkm fkt_end_seq_get, 61155682Smarkm fkt_add_entry, 61255682Smarkm fkt_remove_entry 61355682Smarkm}; 614