root/source4/heimdal/lib/krb5/keytab_file.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. krb5_kt_ret_data
  2. krb5_kt_ret_string
  3. krb5_kt_store_data
  4. krb5_kt_store_string
  5. krb5_kt_ret_keyblock
  6. krb5_kt_store_keyblock
  7. krb5_kt_ret_principal
  8. krb5_kt_store_principal
  9. fkt_resolve
  10. fkt_resolve_java14
  11. fkt_close
  12. fkt_get_name
  13. storage_set_flags
  14. fkt_start_seq_get_int
  15. fkt_start_seq_get
  16. fkt_next_entry_int
  17. fkt_next_entry
  18. fkt_end_seq_get
  19. fkt_setup_keytab
  20. fkt_add_entry
  21. fkt_remove_entry

   1 /*
   2  * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #include "krb5_locl.h"
  35 
  36 RCSID("$Id$");
  37 
  38 #define KRB5_KT_VNO_1 1
  39 #define KRB5_KT_VNO_2 2
  40 #define KRB5_KT_VNO   KRB5_KT_VNO_2
  41 
  42 #define KRB5_KT_FL_JAVA 1
  43 
  44 
  45 /* file operations -------------------------------------------- */
  46 
  47 struct fkt_data {
  48     char *filename;
  49     int flags;
  50 };
  51 
  52 static krb5_error_code
  53 krb5_kt_ret_data(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
  54                  krb5_storage *sp,
  55                  krb5_data *data)
  56 {
  57     int ret;
  58     int16_t size;
  59     ret = krb5_ret_int16(sp, &size);
  60     if(ret)
  61         return ret;
  62     data->length = size;
  63     data->data = malloc(size);
  64     if (data->data == NULL) {
  65         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
  66         return ENOMEM;
  67     }
  68     ret = krb5_storage_read(sp, data->data, size);
  69     if(ret != size)
  70         return (ret < 0)? errno : KRB5_KT_END;
  71     return 0;
  72 }
  73 
  74 static krb5_error_code
  75 krb5_kt_ret_string(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
  76                    krb5_storage *sp,
  77                    heim_general_string *data)
  78 {
  79     int ret;
  80     int16_t size;
  81     ret = krb5_ret_int16(sp, &size);
  82     if(ret)
  83         return ret;
  84     *data = malloc(size + 1);
  85     if (*data == NULL) {
  86         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
  87         return ENOMEM;
  88     }
  89     ret = krb5_storage_read(sp, *data, size);
  90     (*data)[size] = '\0';
  91     if(ret != size)
  92         return (ret < 0)? errno : KRB5_KT_END;
  93     return 0;
  94 }
  95 
  96 static krb5_error_code
  97 krb5_kt_store_data(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
  98                    krb5_storage *sp,
  99                    krb5_data data)
 100 {
 101     int ret;
 102     ret = krb5_store_int16(sp, data.length);
 103     if(ret < 0)
 104         return ret;
 105     ret = krb5_storage_write(sp, data.data, data.length);
 106     if(ret != data.length){
 107         if(ret < 0)
 108             return errno;
 109         return KRB5_KT_END;
 110     }
 111     return 0;
 112 }
 113 
 114 static krb5_error_code
 115 krb5_kt_store_string(krb5_storage *sp,
     /* [<][>][^][v][top][bottom][index][help] */
 116                      heim_general_string data)
 117 {
 118     int ret;
 119     size_t len = strlen(data);
 120     ret = krb5_store_int16(sp, len);
 121     if(ret < 0)
 122         return ret;
 123     ret = krb5_storage_write(sp, data, len);
 124     if(ret != len){
 125         if(ret < 0)
 126             return errno;
 127         return KRB5_KT_END;
 128     }
 129     return 0;
 130 }
 131 
 132 static krb5_error_code
 133 krb5_kt_ret_keyblock(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 134                      struct fkt_data *fkt,
 135                      krb5_storage *sp,
 136                      krb5_keyblock *p)
 137 {
 138     int ret;
 139     int16_t tmp;
 140 
 141     ret = krb5_ret_int16(sp, &tmp); /* keytype + etype */
 142     if(ret)  {
 143         krb5_set_error_message(context, ret,
 144                                N_("Cant read keyblock from file %s", ""),
 145                                fkt->filename);
 146         return ret;
 147     }
 148     p->keytype = tmp;
 149     ret = krb5_kt_ret_data(context, sp, &p->keyvalue);
 150     if (ret)
 151         krb5_set_error_message(context, ret,
 152                                N_("Cant read keyblock from file %s", ""),
 153                                fkt->filename);
 154     return ret;
 155 }
 156 
 157 static krb5_error_code
 158 krb5_kt_store_keyblock(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 159                        struct fkt_data *fkt,
 160                        krb5_storage *sp,
 161                        krb5_keyblock *p)
 162 {
 163     int ret;
 164 
 165     ret = krb5_store_int16(sp, p->keytype); /* keytype + etype */
 166     if(ret) {
 167         krb5_set_error_message(context, ret,
 168                                N_("Cant store keyblock to file %s", ""),
 169                                fkt->filename);
 170         return ret;
 171     }
 172     ret = krb5_kt_store_data(context, sp, p->keyvalue);
 173     if (ret)
 174         krb5_set_error_message(context, ret,
 175                                N_("Cant store keyblock to file %s", ""),
 176                                fkt->filename);
 177     return ret;
 178 }
 179 
 180 
 181 static krb5_error_code
 182 krb5_kt_ret_principal(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 183                       struct fkt_data *fkt,
 184                       krb5_storage *sp,
 185                       krb5_principal *princ)
 186 {
 187     int i;
 188     int ret;
 189     krb5_principal p;
 190     int16_t len;
 191 
 192     ALLOC(p, 1);
 193     if(p == NULL) {
 194         krb5_set_error_message(context, ENOMEM,
 195                                N_("malloc: out of memory", ""));
 196         return ENOMEM;
 197     }
 198 
 199     ret = krb5_ret_int16(sp, &len);
 200     if(ret) {
 201         krb5_set_error_message(context, ret,
 202                                N_("Failed decoding length of "
 203                                   "keytab principal in keytab file %s", ""),
 204                                fkt->filename);
 205         goto out;
 206     }
 207     if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
 208         len--;
 209     if (len < 0) {
 210         ret = KRB5_KT_END;
 211         krb5_set_error_message(context, ret,
 212                                N_("Keytab principal contains "
 213                                   "invalid length in keytab %s", ""),
 214                                fkt->filename);
 215         goto out;
 216     }
 217     ret = krb5_kt_ret_string(context, sp, &p->realm);
 218     if(ret) {
 219         krb5_set_error_message(context, ret,
 220                                N_("Can't read realm from keytab: %s", ""),
 221                                fkt->filename);
 222         goto out;
 223     }
 224     p->name.name_string.val = calloc(len, sizeof(*p->name.name_string.val));
 225     if(p->name.name_string.val == NULL) {
 226         ret = ENOMEM;
 227         krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
 228         goto out;
 229     }
 230     p->name.name_string.len = len;
 231     for(i = 0; i < p->name.name_string.len; i++){
 232         ret = krb5_kt_ret_string(context, sp, p->name.name_string.val + i);
 233         if(ret) {
 234             krb5_set_error_message(context, ret,
 235                                    N_("Can't read principal from "
 236                                       "keytab: %s", ""),
 237                                    fkt->filename);
 238             goto out;
 239         }
 240     }
 241     if (krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
 242         p->name.name_type = KRB5_NT_UNKNOWN;
 243     else {
 244         int32_t tmp32;
 245         ret = krb5_ret_int32(sp, &tmp32);
 246         p->name.name_type = tmp32;
 247         if (ret) {
 248             krb5_set_error_message(context, ret,
 249                                    N_("Can't read name-type from "
 250                                       "keytab: %s", ""),
 251                                    fkt->filename);
 252             goto out;
 253         }
 254     }
 255     *princ = p;
 256     return 0;
 257 out:
 258     krb5_free_principal(context, p);
 259     return ret;
 260 }
 261 
 262 static krb5_error_code
 263 krb5_kt_store_principal(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 264                         krb5_storage *sp,
 265                         krb5_principal p)
 266 {
 267     int i;
 268     int ret;
 269 
 270     if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
 271         ret = krb5_store_int16(sp, p->name.name_string.len + 1);
 272     else
 273         ret = krb5_store_int16(sp, p->name.name_string.len);
 274     if(ret) return ret;
 275     ret = krb5_kt_store_string(sp, p->realm);
 276     if(ret) return ret;
 277     for(i = 0; i < p->name.name_string.len; i++){
 278         ret = krb5_kt_store_string(sp, p->name.name_string.val[i]);
 279         if(ret)
 280             return ret;
 281     }
 282     if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
 283         ret = krb5_store_int32(sp, p->name.name_type);
 284         if(ret)
 285             return ret;
 286     }
 287 
 288     return 0;
 289 }
 290 
 291 static krb5_error_code
 292 fkt_resolve(krb5_context context, const char *name, krb5_keytab id)
     /* [<][>][^][v][top][bottom][index][help] */
 293 {
 294     struct fkt_data *d;
 295 
 296     d = malloc(sizeof(*d));
 297     if(d == NULL) {
 298         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 299         return ENOMEM;
 300     }
 301     d->filename = strdup(name);
 302     if(d->filename == NULL) {
 303         free(d);
 304         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 305         return ENOMEM;
 306     }
 307     d->flags = 0;
 308     id->data = d;
 309     return 0;
 310 }
 311 
 312 static krb5_error_code
 313 fkt_resolve_java14(krb5_context context, const char *name, krb5_keytab id)
     /* [<][>][^][v][top][bottom][index][help] */
 314 {
 315     krb5_error_code ret;
 316 
 317     ret = fkt_resolve(context, name, id);
 318     if (ret == 0) {
 319         struct fkt_data *d = id->data;
 320         d->flags |= KRB5_KT_FL_JAVA;
 321     }
 322     return ret;
 323 }
 324 
 325 static krb5_error_code
 326 fkt_close(krb5_context context, krb5_keytab id)
     /* [<][>][^][v][top][bottom][index][help] */
 327 {
 328     struct fkt_data *d = id->data;
 329     free(d->filename);
 330     free(d);
 331     return 0;
 332 }
 333 
 334 static krb5_error_code
 335 fkt_get_name(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 336              krb5_keytab id,
 337              char *name,
 338              size_t namesize)
 339 {
 340     /* This function is XXX */
 341     struct fkt_data *d = id->data;
 342     strlcpy(name, d->filename, namesize);
 343     return 0;
 344 }
 345 
 346 static void
 347 storage_set_flags(krb5_context context, krb5_storage *sp, int vno)
     /* [<][>][^][v][top][bottom][index][help] */
 348 {
 349     int flags = 0;
 350     switch(vno) {
 351     case KRB5_KT_VNO_1:
 352         flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS;
 353         flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE;
 354         flags |= KRB5_STORAGE_HOST_BYTEORDER;
 355         break;
 356     case KRB5_KT_VNO_2:
 357         break;
 358     default:
 359         krb5_warnx(context,
 360                    "storage_set_flags called with bad vno (%d)", vno);
 361     }
 362     krb5_storage_set_flags(sp, flags);
 363 }
 364 
 365 static krb5_error_code
 366 fkt_start_seq_get_int(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 367                       krb5_keytab id,
 368                       int flags,
 369                       int exclusive,
 370                       krb5_kt_cursor *c)
 371 {
 372     int8_t pvno, tag;
 373     krb5_error_code ret;
 374     struct fkt_data *d = id->data;
 375 
 376     c->fd = open (d->filename, flags);
 377     if (c->fd < 0) {
 378         ret = errno;
 379         krb5_set_error_message(context, ret,
 380                                N_("keytab %s open failed: %s", ""),
 381                                d->filename, strerror(ret));
 382         return ret;
 383     }
 384     rk_cloexec(c->fd);
 385     ret = _krb5_xlock(context, c->fd, exclusive, d->filename);
 386     if (ret) {
 387         close(c->fd);
 388         return ret;
 389     }
 390     c->sp = krb5_storage_from_fd(c->fd);
 391     if (c->sp == NULL) {
 392         _krb5_xunlock(context, c->fd);
 393         close(c->fd);
 394         krb5_set_error_message(context, ENOMEM,
 395                                N_("malloc: out of memory", ""));
 396         return ENOMEM;
 397     }
 398     krb5_storage_set_eof_code(c->sp, KRB5_KT_END);
 399     ret = krb5_ret_int8(c->sp, &pvno);
 400     if(ret) {
 401         krb5_storage_free(c->sp);
 402         _krb5_xunlock(context, c->fd);
 403         close(c->fd);
 404         krb5_clear_error_message(context);
 405         return ret;
 406     }
 407     if(pvno != 5) {
 408         krb5_storage_free(c->sp);
 409         _krb5_xunlock(context, c->fd);
 410         close(c->fd);
 411         krb5_clear_error_message (context);
 412         return KRB5_KEYTAB_BADVNO;
 413     }
 414     ret = krb5_ret_int8(c->sp, &tag);
 415     if (ret) {
 416         krb5_storage_free(c->sp);
 417         _krb5_xunlock(context, c->fd);
 418         close(c->fd);
 419         krb5_clear_error_message(context);
 420         return ret;
 421     }
 422     id->version = tag;
 423     storage_set_flags(context, c->sp, id->version);
 424     return 0;
 425 }
 426 
 427 static krb5_error_code
 428 fkt_start_seq_get(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 429                   krb5_keytab id,
 430                   krb5_kt_cursor *c)
 431 {
 432     return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY | O_CLOEXEC, 0, c);
 433 }
 434 
 435 static krb5_error_code
 436 fkt_next_entry_int(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 437                    krb5_keytab id,
 438                    krb5_keytab_entry *entry,
 439                    krb5_kt_cursor *cursor,
 440                    off_t *start,
 441                    off_t *end)
 442 {
 443     struct fkt_data *d = id->data;
 444     int32_t len;
 445     int ret;
 446     int8_t tmp8;
 447     int32_t tmp32;
 448     off_t pos, curpos;
 449 
 450     pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
 451 loop:
 452     ret = krb5_ret_int32(cursor->sp, &len);
 453     if (ret)
 454         return ret;
 455     if(len < 0) {
 456         pos = krb5_storage_seek(cursor->sp, -len, SEEK_CUR);
 457         goto loop;
 458     }
 459     ret = krb5_kt_ret_principal (context, d, cursor->sp, &entry->principal);
 460     if (ret)
 461         goto out;
 462     ret = krb5_ret_int32(cursor->sp, &tmp32);
 463     entry->timestamp = tmp32;
 464     if (ret)
 465         goto out;
 466     ret = krb5_ret_int8(cursor->sp, &tmp8);
 467     if (ret)
 468         goto out;
 469     entry->vno = tmp8;
 470     ret = krb5_kt_ret_keyblock (context, d, cursor->sp, &entry->keyblock);
 471     if (ret)
 472         goto out;
 473     /* there might be a 32 bit kvno here
 474      * if it's zero, assume that the 8bit one was right,
 475      * otherwise trust the new value */
 476     curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
 477     if(len + 4 + pos - curpos >= 4) {
 478         ret = krb5_ret_int32(cursor->sp, &tmp32);
 479         if (ret == 0 && tmp32 != 0) {
 480             entry->vno = tmp32;
 481         }
 482     }
 483     if(start) *start = pos;
 484     if(end) *end = pos + 4 + len;
 485  out:
 486     krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET);
 487     return ret;
 488 }
 489 
 490 static krb5_error_code
 491 fkt_next_entry(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 492                krb5_keytab id,
 493                krb5_keytab_entry *entry,
 494                krb5_kt_cursor *cursor)
 495 {
 496     return fkt_next_entry_int(context, id, entry, cursor, NULL, NULL);
 497 }
 498 
 499 static krb5_error_code
 500 fkt_end_seq_get(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 501                 krb5_keytab id,
 502                 krb5_kt_cursor *cursor)
 503 {
 504     krb5_storage_free(cursor->sp);
 505     _krb5_xunlock(context, cursor->fd);
 506     close(cursor->fd);
 507     return 0;
 508 }
 509 
 510 static krb5_error_code
 511 fkt_setup_keytab(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 512                  krb5_keytab id,
 513                  krb5_storage *sp)
 514 {
 515     krb5_error_code ret;
 516     ret = krb5_store_int8(sp, 5);
 517     if(ret)
 518         return ret;
 519     if(id->version == 0)
 520         id->version = KRB5_KT_VNO;
 521     return krb5_store_int8 (sp, id->version);
 522 }
 523                 
 524 static krb5_error_code
 525 fkt_add_entry(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 526               krb5_keytab id,
 527               krb5_keytab_entry *entry)
 528 {
 529     int ret;
 530     int fd;
 531     krb5_storage *sp;
 532     struct fkt_data *d = id->data;
 533     krb5_data keytab;
 534     int32_t len;
 535 
 536     fd = open (d->filename, O_RDWR | O_BINARY | O_CLOEXEC);
 537     if (fd < 0) {
 538         fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, 0600);
 539         if (fd < 0) {
 540             ret = errno;
 541             krb5_set_error_message(context, ret,
 542                                    N_("open(%s): %s", ""), d->filename,
 543                                    strerror(ret));
 544             return ret;
 545         }
 546         rk_cloexec(fd);
 547 
 548         ret = _krb5_xlock(context, fd, 1, d->filename);
 549         if (ret) {
 550             close(fd);
 551             return ret;
 552         }
 553         sp = krb5_storage_from_fd(fd);
 554         krb5_storage_set_eof_code(sp, KRB5_KT_END);
 555         ret = fkt_setup_keytab(context, id, sp);
 556         if(ret) {
 557             goto out;
 558         }
 559         storage_set_flags(context, sp, id->version);
 560     } else {
 561         int8_t pvno, tag;
 562 
 563         rk_cloexec(fd);
 564 
 565         ret = _krb5_xlock(context, fd, 1, d->filename);
 566         if (ret) {
 567             close(fd);
 568             return ret;
 569         }
 570         sp = krb5_storage_from_fd(fd);
 571         krb5_storage_set_eof_code(sp, KRB5_KT_END);
 572         ret = krb5_ret_int8(sp, &pvno);
 573         if(ret) {
 574             /* we probably have a zero byte file, so try to set it up
 575                properly */
 576             ret = fkt_setup_keytab(context, id, sp);
 577             if(ret) {
 578                 krb5_set_error_message(context, ret,
 579                                        N_("%s: keytab is corrupted: %s", ""),
 580                                        d->filename, strerror(ret));
 581                 goto out;
 582             }
 583             storage_set_flags(context, sp, id->version);
 584         } else {
 585             if(pvno != 5) {
 586                 ret = KRB5_KEYTAB_BADVNO;
 587                 krb5_set_error_message(context, ret,
 588                                        N_("Bad version in keytab %s", ""),
 589                                        d->filename);
 590                 goto out;
 591             }
 592             ret = krb5_ret_int8 (sp, &tag);
 593             if (ret) {
 594                 krb5_set_error_message(context, ret,
 595                                        N_("failed reading tag from "
 596                                           "keytab %s", ""),
 597                                        d->filename);
 598                 goto out;
 599             }
 600             id->version = tag;
 601             storage_set_flags(context, sp, id->version);
 602         }
 603     }
 604 
 605     {
 606         krb5_storage *emem;
 607         emem = krb5_storage_emem();
 608         if(emem == NULL) {
 609             ret = ENOMEM;
 610             krb5_set_error_message(context, ret,
 611                                    N_("malloc: out of memory", ""));
 612             goto out;
 613         }
 614         ret = krb5_kt_store_principal(context, emem, entry->principal);
 615         if(ret) {
 616             krb5_set_error_message(context, ret,
 617                                    N_("Failed storing principal "
 618                                       "in keytab %s", ""),
 619                                    d->filename);
 620             krb5_storage_free(emem);
 621             goto out;
 622         }
 623         ret = krb5_store_int32 (emem, entry->timestamp);
 624         if(ret) {
 625             krb5_set_error_message(context, ret,
 626                                    N_("Failed storing timpstamp "
 627                                       "in keytab %s", ""),
 628                                    d->filename);
 629             krb5_storage_free(emem);
 630             goto out;
 631         }
 632         ret = krb5_store_int8 (emem, entry->vno % 256);
 633         if(ret) {
 634             krb5_set_error_message(context, ret,
 635                                    N_("Failed storing kvno "
 636                                       "in keytab %s", ""),
 637                                    d->filename);
 638             krb5_storage_free(emem);
 639             goto out;
 640         }
 641         ret = krb5_kt_store_keyblock (context, d, emem, &entry->keyblock);
 642         if(ret) {
 643             krb5_storage_free(emem);
 644             goto out;
 645         }
 646         if ((d->flags & KRB5_KT_FL_JAVA) == 0) {
 647             ret = krb5_store_int32 (emem, entry->vno);
 648             if (ret) {
 649                 krb5_set_error_message(context, ret,
 650                                        N_("Failed storing extended kvno "
 651                                           "in keytab %s", ""),
 652                                        d->filename);
 653                 krb5_storage_free(emem);
 654                 goto out;
 655             }
 656         }
 657 
 658         ret = krb5_storage_to_data(emem, &keytab);
 659         krb5_storage_free(emem);
 660         if(ret) {
 661             krb5_set_error_message(context, ret,
 662                                    N_("Failed converting keytab entry "
 663                                       "to memory block for keytab %s", ""),
 664                                    d->filename);
 665             goto out;
 666         }
 667     }
 668 
 669     while(1) {
 670         ret = krb5_ret_int32(sp, &len);
 671         if(ret == KRB5_KT_END) {
 672             len = keytab.length;
 673             break;
 674         }
 675         if(len < 0) {
 676             len = -len;
 677             if(len >= keytab.length) {
 678                 krb5_storage_seek(sp, -4, SEEK_CUR);
 679                 break;
 680             }
 681         }
 682         krb5_storage_seek(sp, len, SEEK_CUR);
 683     }
 684     ret = krb5_store_int32(sp, len);
 685     if(krb5_storage_write(sp, keytab.data, keytab.length) < 0) {
 686         ret = errno;
 687         krb5_set_error_message(context, ret,
 688                                N_("Failed writing keytab block "
 689                                   "in keytab %s: %s", ""),
 690                                d->filename, strerror(ret));
 691     }
 692     memset(keytab.data, 0, keytab.length);
 693     krb5_data_free(&keytab);
 694   out:
 695     krb5_storage_free(sp);
 696     _krb5_xunlock(context, fd);
 697     close(fd);
 698     return ret;
 699 }
 700 
 701 static krb5_error_code
 702 fkt_remove_entry(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 703                  krb5_keytab id,
 704                  krb5_keytab_entry *entry)
 705 {
 706     krb5_keytab_entry e;
 707     krb5_kt_cursor cursor;
 708     off_t pos_start, pos_end;
 709     int found = 0;
 710     krb5_error_code ret;
 711 
 712     ret = fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY | O_CLOEXEC, 1, &cursor);
 713     if(ret != 0)
 714         goto out; /* return other error here? */
 715     while(fkt_next_entry_int(context, id, &e, &cursor,
 716                              &pos_start, &pos_end) == 0) {
 717         if(krb5_kt_compare(context, &e, entry->principal,
 718                            entry->vno, entry->keyblock.keytype)) {
 719             int32_t len;
 720             unsigned char buf[128];
 721             found = 1;
 722             krb5_storage_seek(cursor.sp, pos_start, SEEK_SET);
 723             len = pos_end - pos_start - 4;
 724             krb5_store_int32(cursor.sp, -len);
 725             memset(buf, 0, sizeof(buf));
 726             while(len > 0) {
 727                 krb5_storage_write(cursor.sp, buf, min(len, sizeof(buf)));
 728                 len -= min(len, sizeof(buf));
 729             }
 730         }
 731         krb5_kt_free_entry(context, &e);
 732     }
 733     krb5_kt_end_seq_get(context, id, &cursor);
 734   out:
 735     if (!found) {
 736         krb5_clear_error_message (context);
 737         return KRB5_KT_NOTFOUND;
 738     }
 739     return 0;
 740 }
 741 
 742 const krb5_kt_ops krb5_fkt_ops = {
 743     "FILE",
 744     fkt_resolve,
 745     fkt_get_name,
 746     fkt_close,
 747     NULL, /* get */
 748     fkt_start_seq_get,
 749     fkt_next_entry,
 750     fkt_end_seq_get,
 751     fkt_add_entry,
 752     fkt_remove_entry
 753 };
 754 
 755 const krb5_kt_ops krb5_wrfkt_ops = {
 756     "WRFILE",
 757     fkt_resolve,
 758     fkt_get_name,
 759     fkt_close,
 760     NULL, /* get */
 761     fkt_start_seq_get,
 762     fkt_next_entry,
 763     fkt_end_seq_get,
 764     fkt_add_entry,
 765     fkt_remove_entry
 766 };
 767 
 768 const krb5_kt_ops krb5_javakt_ops = {
 769     "JAVA14",
 770     fkt_resolve_java14,
 771     fkt_get_name,
 772     fkt_close,
 773     NULL, /* get */
 774     fkt_start_seq_get,
 775     fkt_next_entry,
 776     fkt_end_seq_get,
 777     fkt_add_entry,
 778     fkt_remove_entry
 779 };

/* [<][>][^][v][top][bottom][index][help] */