1b528cefcSMark Murray /* 2*ae771770SStanislav Sedov * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "krb5_locl.h" 35b528cefcSMark Murray 36*ae771770SStanislav Sedov #ifndef HEIMDAL_SMALLER 37b528cefcSMark Murray 38b528cefcSMark Murray /* afs keyfile operations --------------------------------------- */ 39b528cefcSMark Murray 40b528cefcSMark Murray /* 41b528cefcSMark Murray * Minimum tools to handle the AFS KeyFile. 42b528cefcSMark Murray * 43b528cefcSMark Murray * Format of the KeyFile is: 44b528cefcSMark Murray * <int32_t numkeys> {[<int32_t kvno> <char[8] deskey>] * numkeys} 45b528cefcSMark Murray * 46b528cefcSMark Murray * It just adds to the end of the keyfile, deleting isn't implemented. 47b528cefcSMark Murray * Use your favorite text/hex editor to delete keys. 48b528cefcSMark Murray * 49b528cefcSMark Murray */ 50b528cefcSMark Murray 51b528cefcSMark Murray #define AFS_SERVERTHISCELL "/usr/afs/etc/ThisCell" 52b528cefcSMark Murray #define AFS_SERVERMAGICKRBCONF "/usr/afs/etc/krb.conf" 53b528cefcSMark Murray 54b528cefcSMark Murray struct akf_data { 55*ae771770SStanislav Sedov uint32_t num_entries; 56b528cefcSMark Murray char *filename; 57b528cefcSMark Murray char *cell; 58b528cefcSMark Murray char *realm; 59b528cefcSMark Murray }; 60b528cefcSMark Murray 61b528cefcSMark Murray /* 62b528cefcSMark Murray * set `d->cell' and `d->realm' 63b528cefcSMark Murray */ 64b528cefcSMark Murray 65b528cefcSMark Murray static int 66c19800e8SDoug Rabson get_cell_and_realm (krb5_context context, struct akf_data *d) 67b528cefcSMark Murray { 68b528cefcSMark Murray FILE *f; 69b528cefcSMark Murray char buf[BUFSIZ], *cp; 70adb0ddaeSAssar Westerlund int ret; 71b528cefcSMark Murray 72b528cefcSMark Murray f = fopen (AFS_SERVERTHISCELL, "r"); 73adb0ddaeSAssar Westerlund if (f == NULL) { 74adb0ddaeSAssar Westerlund ret = errno; 75*ae771770SStanislav Sedov krb5_set_error_message (context, ret, 76*ae771770SStanislav Sedov N_("Open ThisCell %s: %s", ""), 77*ae771770SStanislav Sedov AFS_SERVERTHISCELL, 78adb0ddaeSAssar Westerlund strerror(ret)); 79adb0ddaeSAssar Westerlund return ret; 80adb0ddaeSAssar Westerlund } 81b528cefcSMark Murray if (fgets (buf, sizeof(buf), f) == NULL) { 82b528cefcSMark Murray fclose (f); 83*ae771770SStanislav Sedov krb5_set_error_message (context, EINVAL, 84*ae771770SStanislav Sedov N_("No cell in ThisCell file %s", ""), 85*ae771770SStanislav Sedov AFS_SERVERTHISCELL); 86b528cefcSMark Murray return EINVAL; 87b528cefcSMark Murray } 885bda878eSJacques Vidrine buf[strcspn(buf, "\n")] = '\0'; 89b528cefcSMark Murray fclose(f); 90b528cefcSMark Murray 91b528cefcSMark Murray d->cell = strdup (buf); 92adb0ddaeSAssar Westerlund if (d->cell == NULL) { 93*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, 94*ae771770SStanislav Sedov N_("malloc: out of memory", "")); 95adb0ddaeSAssar Westerlund return ENOMEM; 96adb0ddaeSAssar Westerlund } 97b528cefcSMark Murray 98b528cefcSMark Murray f = fopen (AFS_SERVERMAGICKRBCONF, "r"); 99b528cefcSMark Murray if (f != NULL) { 100b528cefcSMark Murray if (fgets (buf, sizeof(buf), f) == NULL) { 101c19800e8SDoug Rabson free (d->cell); 102c19800e8SDoug Rabson d->cell = NULL; 103b528cefcSMark Murray fclose (f); 104*ae771770SStanislav Sedov krb5_set_error_message (context, EINVAL, 105*ae771770SStanislav Sedov N_("No realm in ThisCell file %s", ""), 106adb0ddaeSAssar Westerlund AFS_SERVERMAGICKRBCONF); 107b528cefcSMark Murray return EINVAL; 108b528cefcSMark Murray } 1095bda878eSJacques Vidrine buf[strcspn(buf, "\n")] = '\0'; 110b528cefcSMark Murray fclose(f); 111b528cefcSMark Murray } 112b528cefcSMark Murray /* uppercase */ 113b528cefcSMark Murray for (cp = buf; *cp != '\0'; cp++) 114c19800e8SDoug Rabson *cp = toupper((unsigned char)*cp); 115b528cefcSMark Murray 116b528cefcSMark Murray d->realm = strdup (buf); 117b528cefcSMark Murray if (d->realm == NULL) { 118b528cefcSMark Murray free (d->cell); 119c19800e8SDoug Rabson d->cell = NULL; 120*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, 121*ae771770SStanislav Sedov N_("malloc: out of memory", "")); 122adb0ddaeSAssar Westerlund return ENOMEM; 123b528cefcSMark Murray } 124b528cefcSMark Murray return 0; 125b528cefcSMark Murray } 126b528cefcSMark Murray 127b528cefcSMark Murray /* 128b528cefcSMark Murray * init and get filename 129b528cefcSMark Murray */ 130b528cefcSMark Murray 131*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV 132b528cefcSMark Murray akf_resolve(krb5_context context, const char *name, krb5_keytab id) 133b528cefcSMark Murray { 134b528cefcSMark Murray int ret; 135b528cefcSMark Murray struct akf_data *d = malloc(sizeof (struct akf_data)); 136b528cefcSMark Murray 137adb0ddaeSAssar Westerlund if (d == NULL) { 138*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, 139*ae771770SStanislav Sedov N_("malloc: out of memory", "")); 140adb0ddaeSAssar Westerlund return ENOMEM; 141adb0ddaeSAssar Westerlund } 142b528cefcSMark Murray 143b528cefcSMark Murray d->num_entries = 0; 144adb0ddaeSAssar Westerlund ret = get_cell_and_realm (context, d); 145b528cefcSMark Murray if (ret) { 146b528cefcSMark Murray free (d); 147b528cefcSMark Murray return ret; 148b528cefcSMark Murray } 149b528cefcSMark Murray d->filename = strdup (name); 150b528cefcSMark Murray if (d->filename == NULL) { 151b528cefcSMark Murray free (d->cell); 152b528cefcSMark Murray free (d->realm); 153b528cefcSMark Murray free (d); 154*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, 155*ae771770SStanislav Sedov N_("malloc: out of memory", "")); 156b528cefcSMark Murray return ENOMEM; 157b528cefcSMark Murray } 158b528cefcSMark Murray id->data = d; 159b528cefcSMark Murray 160b528cefcSMark Murray return 0; 161b528cefcSMark Murray } 162b528cefcSMark Murray 163b528cefcSMark Murray /* 164b528cefcSMark Murray * cleanup 165b528cefcSMark Murray */ 166b528cefcSMark Murray 167*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV 168b528cefcSMark Murray akf_close(krb5_context context, krb5_keytab id) 169b528cefcSMark Murray { 170b528cefcSMark Murray struct akf_data *d = id->data; 171b528cefcSMark Murray 172b528cefcSMark Murray free (d->filename); 173b528cefcSMark Murray free (d->cell); 174b528cefcSMark Murray free (d); 175b528cefcSMark Murray return 0; 176b528cefcSMark Murray } 177b528cefcSMark Murray 178b528cefcSMark Murray /* 179b528cefcSMark Murray * Return filename 180b528cefcSMark Murray */ 181b528cefcSMark Murray 182*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV 183b528cefcSMark Murray akf_get_name(krb5_context context, 184b528cefcSMark Murray krb5_keytab id, 185b528cefcSMark Murray char *name, 186b528cefcSMark Murray size_t name_sz) 187b528cefcSMark Murray { 188b528cefcSMark Murray struct akf_data *d = id->data; 189b528cefcSMark Murray 190b528cefcSMark Murray strlcpy (name, d->filename, name_sz); 191b528cefcSMark Murray return 0; 192b528cefcSMark Murray } 193b528cefcSMark Murray 194b528cefcSMark Murray /* 195b528cefcSMark Murray * Init 196b528cefcSMark Murray */ 197b528cefcSMark Murray 198*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV 199b528cefcSMark Murray akf_start_seq_get(krb5_context context, 200b528cefcSMark Murray krb5_keytab id, 201b528cefcSMark Murray krb5_kt_cursor *c) 202b528cefcSMark Murray { 203b528cefcSMark Murray int32_t ret; 204b528cefcSMark Murray struct akf_data *d = id->data; 205b528cefcSMark Murray 206*ae771770SStanislav Sedov c->fd = open (d->filename, O_RDONLY | O_BINARY | O_CLOEXEC, 0600); 207adb0ddaeSAssar Westerlund if (c->fd < 0) { 208adb0ddaeSAssar Westerlund ret = errno; 209*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 210*ae771770SStanislav Sedov N_("keytab afs keyfile open %s failed: %s", ""), 211*ae771770SStanislav Sedov d->filename, strerror(ret)); 212adb0ddaeSAssar Westerlund return ret; 213adb0ddaeSAssar Westerlund } 214b528cefcSMark Murray 215*ae771770SStanislav Sedov c->data = NULL; 216b528cefcSMark Murray c->sp = krb5_storage_from_fd(c->fd); 217*ae771770SStanislav Sedov if (c->sp == NULL) { 218*ae771770SStanislav Sedov close(c->fd); 219*ae771770SStanislav Sedov krb5_clear_error_message (context); 220*ae771770SStanislav Sedov return KRB5_KT_NOTFOUND; 221*ae771770SStanislav Sedov } 222*ae771770SStanislav Sedov krb5_storage_set_eof_code(c->sp, KRB5_KT_END); 223*ae771770SStanislav Sedov 224*ae771770SStanislav Sedov ret = krb5_ret_uint32(c->sp, &d->num_entries); 225*ae771770SStanislav Sedov if(ret || d->num_entries > INT_MAX / 8) { 226b528cefcSMark Murray krb5_storage_free(c->sp); 227b528cefcSMark Murray close(c->fd); 228*ae771770SStanislav Sedov krb5_clear_error_message (context); 2298373020dSJacques Vidrine if(ret == KRB5_KT_END) 230adb0ddaeSAssar Westerlund return KRB5_KT_NOTFOUND; 231b528cefcSMark Murray return ret; 232b528cefcSMark Murray } 233b528cefcSMark Murray 234b528cefcSMark Murray return 0; 235b528cefcSMark Murray } 236b528cefcSMark Murray 237*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV 238b528cefcSMark Murray akf_next_entry(krb5_context context, 239b528cefcSMark Murray krb5_keytab id, 240b528cefcSMark Murray krb5_keytab_entry *entry, 241b528cefcSMark Murray krb5_kt_cursor *cursor) 242b528cefcSMark Murray { 243b528cefcSMark Murray struct akf_data *d = id->data; 244b528cefcSMark Murray int32_t kvno; 245b528cefcSMark Murray off_t pos; 246b528cefcSMark Murray int ret; 247b528cefcSMark Murray 2488373020dSJacques Vidrine pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); 249b528cefcSMark Murray 250b528cefcSMark Murray if ((pos - 4) / (4 + 8) >= d->num_entries) 251b528cefcSMark Murray return KRB5_KT_END; 252b528cefcSMark Murray 253b528cefcSMark Murray ret = krb5_make_principal (context, &entry->principal, 254b528cefcSMark Murray d->realm, "afs", d->cell, NULL); 255b528cefcSMark Murray if (ret) 256b528cefcSMark Murray goto out; 257b528cefcSMark Murray 258b528cefcSMark Murray ret = krb5_ret_int32(cursor->sp, &kvno); 259b528cefcSMark Murray if (ret) { 260b528cefcSMark Murray krb5_free_principal (context, entry->principal); 261b528cefcSMark Murray goto out; 262b528cefcSMark Murray } 263b528cefcSMark Murray 2645e9cd1aeSAssar Westerlund entry->vno = kvno; 265b528cefcSMark Murray 266*ae771770SStanislav Sedov if (cursor->data) 267b528cefcSMark Murray entry->keyblock.keytype = ETYPE_DES_CBC_MD5; 268*ae771770SStanislav Sedov else 269*ae771770SStanislav Sedov entry->keyblock.keytype = ETYPE_DES_CBC_CRC; 270b528cefcSMark Murray entry->keyblock.keyvalue.length = 8; 271b528cefcSMark Murray entry->keyblock.keyvalue.data = malloc (8); 272b528cefcSMark Murray if (entry->keyblock.keyvalue.data == NULL) { 273b528cefcSMark Murray krb5_free_principal (context, entry->principal); 274*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, 275*ae771770SStanislav Sedov N_("malloc: out of memory", "")); 276b528cefcSMark Murray ret = ENOMEM; 277b528cefcSMark Murray goto out; 278b528cefcSMark Murray } 279b528cefcSMark Murray 2808373020dSJacques Vidrine ret = krb5_storage_read(cursor->sp, entry->keyblock.keyvalue.data, 8); 281b528cefcSMark Murray if(ret != 8) 282b528cefcSMark Murray ret = (ret < 0) ? errno : KRB5_KT_END; 2835e9cd1aeSAssar Westerlund else 2845e9cd1aeSAssar Westerlund ret = 0; 285b528cefcSMark Murray 286b528cefcSMark Murray entry->timestamp = time(NULL); 287*ae771770SStanislav Sedov entry->flags = 0; 288*ae771770SStanislav Sedov entry->aliases = NULL; 289b528cefcSMark Murray 290b528cefcSMark Murray out: 291*ae771770SStanislav Sedov if (cursor->data) { 2928373020dSJacques Vidrine krb5_storage_seek(cursor->sp, pos + 4 + 8, SEEK_SET); 293*ae771770SStanislav Sedov cursor->data = NULL; 294*ae771770SStanislav Sedov } else 295*ae771770SStanislav Sedov cursor->data = cursor; 296b528cefcSMark Murray return ret; 297b528cefcSMark Murray } 298b528cefcSMark Murray 299*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV 300b528cefcSMark Murray akf_end_seq_get(krb5_context context, 301b528cefcSMark Murray krb5_keytab id, 302b528cefcSMark Murray krb5_kt_cursor *cursor) 303b528cefcSMark Murray { 304b528cefcSMark Murray krb5_storage_free(cursor->sp); 305b528cefcSMark Murray close(cursor->fd); 306*ae771770SStanislav Sedov cursor->data = NULL; 307b528cefcSMark Murray return 0; 308b528cefcSMark Murray } 309b528cefcSMark Murray 310*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV 311b528cefcSMark Murray akf_add_entry(krb5_context context, 312b528cefcSMark Murray krb5_keytab id, 313b528cefcSMark Murray krb5_keytab_entry *entry) 314b528cefcSMark Murray { 315b528cefcSMark Murray struct akf_data *d = id->data; 316b528cefcSMark Murray int fd, created = 0; 3175e9cd1aeSAssar Westerlund krb5_error_code ret; 3184137ff4cSJacques Vidrine int32_t len; 3194137ff4cSJacques Vidrine krb5_storage *sp; 3204137ff4cSJacques Vidrine 3214137ff4cSJacques Vidrine 322c19800e8SDoug Rabson if (entry->keyblock.keyvalue.length != 8) 3234137ff4cSJacques Vidrine return 0; 324c19800e8SDoug Rabson switch(entry->keyblock.keytype) { 325c19800e8SDoug Rabson case ETYPE_DES_CBC_CRC: 326c19800e8SDoug Rabson case ETYPE_DES_CBC_MD4: 327c19800e8SDoug Rabson case ETYPE_DES_CBC_MD5: 328c19800e8SDoug Rabson break; 329c19800e8SDoug Rabson default: 330c19800e8SDoug Rabson return 0; 331c19800e8SDoug Rabson } 332b528cefcSMark Murray 333*ae771770SStanislav Sedov fd = open (d->filename, O_RDWR | O_BINARY | O_CLOEXEC); 334b528cefcSMark Murray if (fd < 0) { 335b528cefcSMark Murray fd = open (d->filename, 336*ae771770SStanislav Sedov O_RDWR | O_BINARY | O_CREAT | O_EXCL | O_CLOEXEC, 0600); 337adb0ddaeSAssar Westerlund if (fd < 0) { 338adb0ddaeSAssar Westerlund ret = errno; 339*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 340*ae771770SStanislav Sedov N_("open keyfile(%s): %s", ""), 341*ae771770SStanislav Sedov d->filename, 342adb0ddaeSAssar Westerlund strerror(ret)); 343adb0ddaeSAssar Westerlund return ret; 344adb0ddaeSAssar Westerlund } 345b528cefcSMark Murray created = 1; 346b528cefcSMark Murray } 347b528cefcSMark Murray 3485e9cd1aeSAssar Westerlund sp = krb5_storage_from_fd(fd); 3495e9cd1aeSAssar Westerlund if(sp == NULL) { 3505e9cd1aeSAssar Westerlund close(fd); 351*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, 352*ae771770SStanislav Sedov N_("malloc: out of memory", "")); 3535e9cd1aeSAssar Westerlund return ENOMEM; 3545e9cd1aeSAssar Westerlund } 3555e9cd1aeSAssar Westerlund if (created) 3565e9cd1aeSAssar Westerlund len = 0; 3575e9cd1aeSAssar Westerlund else { 3588373020dSJacques Vidrine if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) { 359adb0ddaeSAssar Westerlund ret = errno; 3605e9cd1aeSAssar Westerlund krb5_storage_free(sp); 3615e9cd1aeSAssar Westerlund close(fd); 362*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 363*ae771770SStanislav Sedov N_("seeking in keyfile: %s", ""), 364*ae771770SStanislav Sedov strerror(ret)); 365adb0ddaeSAssar Westerlund return ret; 366b528cefcSMark Murray } 367b528cefcSMark Murray 3685e9cd1aeSAssar Westerlund ret = krb5_ret_int32(sp, &len); 3695e9cd1aeSAssar Westerlund if(ret) { 3705e9cd1aeSAssar Westerlund krb5_storage_free(sp); 3715e9cd1aeSAssar Westerlund close(fd); 3725e9cd1aeSAssar Westerlund return ret; 3735e9cd1aeSAssar Westerlund } 3745e9cd1aeSAssar Westerlund } 375c19800e8SDoug Rabson 376c19800e8SDoug Rabson /* 377c19800e8SDoug Rabson * Make sure we don't add the entry twice, assumes the DES 378c19800e8SDoug Rabson * encryption types are all the same key. 379c19800e8SDoug Rabson */ 380c19800e8SDoug Rabson if (len > 0) { 381c19800e8SDoug Rabson int32_t kvno; 382c19800e8SDoug Rabson int i; 383c19800e8SDoug Rabson 384c19800e8SDoug Rabson for (i = 0; i < len; i++) { 385c19800e8SDoug Rabson ret = krb5_ret_int32(sp, &kvno); 386c19800e8SDoug Rabson if (ret) { 387*ae771770SStanislav Sedov krb5_set_error_message (context, ret, 388*ae771770SStanislav Sedov N_("Failed getting kvno from keyfile", "")); 389c19800e8SDoug Rabson goto out; 390c19800e8SDoug Rabson } 391c19800e8SDoug Rabson if(krb5_storage_seek(sp, 8, SEEK_CUR) < 0) { 392*ae771770SStanislav Sedov ret = errno; 393*ae771770SStanislav Sedov krb5_set_error_message (context, ret, 394*ae771770SStanislav Sedov N_("Failed seeing in keyfile: %s", ""), 395*ae771770SStanislav Sedov strerror(ret)); 396c19800e8SDoug Rabson goto out; 397c19800e8SDoug Rabson } 398c19800e8SDoug Rabson if (kvno == entry->vno) { 399c19800e8SDoug Rabson ret = 0; 400c19800e8SDoug Rabson goto out; 401c19800e8SDoug Rabson } 402c19800e8SDoug Rabson } 403c19800e8SDoug Rabson } 404c19800e8SDoug Rabson 4055e9cd1aeSAssar Westerlund len++; 4065e9cd1aeSAssar Westerlund 4078373020dSJacques Vidrine if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) { 408adb0ddaeSAssar Westerlund ret = errno; 409*ae771770SStanislav Sedov krb5_set_error_message (context, ret, 410*ae771770SStanislav Sedov N_("Failed seeing in keyfile: %s", ""), 411*ae771770SStanislav Sedov strerror(ret)); 412c19800e8SDoug Rabson goto out; 4135e9cd1aeSAssar Westerlund } 414b528cefcSMark Murray 4155e9cd1aeSAssar Westerlund ret = krb5_store_int32(sp, len); 4165e9cd1aeSAssar Westerlund if(ret) { 417*ae771770SStanislav Sedov ret = errno; 418*ae771770SStanislav Sedov krb5_set_error_message (context, ret, 419*ae771770SStanislav Sedov N_("keytab keyfile failed new length", "")); 4205e9cd1aeSAssar Westerlund return ret; 4215e9cd1aeSAssar Westerlund } 4225e9cd1aeSAssar Westerlund 4238373020dSJacques Vidrine if(krb5_storage_seek(sp, (len - 1) * (8 + 4), SEEK_CUR) < 0) { 424adb0ddaeSAssar Westerlund ret = errno; 425*ae771770SStanislav Sedov krb5_set_error_message (context, ret, 426*ae771770SStanislav Sedov N_("seek to end: %s", ""), strerror(ret)); 427c19800e8SDoug Rabson goto out; 4285e9cd1aeSAssar Westerlund } 429b528cefcSMark Murray 4305e9cd1aeSAssar Westerlund ret = krb5_store_int32(sp, entry->vno); 4315e9cd1aeSAssar Westerlund if(ret) { 432*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 433*ae771770SStanislav Sedov N_("keytab keyfile failed store kvno", "")); 434c19800e8SDoug Rabson goto out; 4355e9cd1aeSAssar Westerlund } 4368373020dSJacques Vidrine ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, 4375e9cd1aeSAssar Westerlund entry->keyblock.keyvalue.length); 4385e9cd1aeSAssar Westerlund if(ret != entry->keyblock.keyvalue.length) { 4395e9cd1aeSAssar Westerlund if (ret < 0) 440c19800e8SDoug Rabson ret = errno; 441c19800e8SDoug Rabson else 442c19800e8SDoug Rabson ret = ENOTTY; 443*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 444*ae771770SStanislav Sedov N_("keytab keyfile failed to add key", "")); 445c19800e8SDoug Rabson goto out; 4465e9cd1aeSAssar Westerlund } 447c19800e8SDoug Rabson ret = 0; 448c19800e8SDoug Rabson out: 4495e9cd1aeSAssar Westerlund krb5_storage_free(sp); 450b528cefcSMark Murray close (fd); 451c19800e8SDoug Rabson return ret; 452b528cefcSMark Murray } 453b528cefcSMark Murray 454b528cefcSMark Murray const krb5_kt_ops krb5_akf_ops = { 455b528cefcSMark Murray "AFSKEYFILE", 456b528cefcSMark Murray akf_resolve, 457b528cefcSMark Murray akf_get_name, 458b528cefcSMark Murray akf_close, 459*ae771770SStanislav Sedov NULL, /* destroy */ 460b528cefcSMark Murray NULL, /* get */ 461b528cefcSMark Murray akf_start_seq_get, 462b528cefcSMark Murray akf_next_entry, 463b528cefcSMark Murray akf_end_seq_get, 464b528cefcSMark Murray akf_add_entry, 465b528cefcSMark Murray NULL /* remove */ 466b528cefcSMark Murray }; 467*ae771770SStanislav Sedov 468*ae771770SStanislav Sedov #endif /* HEIMDAL_SMALLER */ 469