/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- krb5_kt_ret_data
- krb5_kt_ret_string
- krb5_kt_store_data
- krb5_kt_store_string
- krb5_kt_ret_keyblock
- krb5_kt_store_keyblock
- krb5_kt_ret_principal
- krb5_kt_store_principal
- fkt_resolve
- fkt_resolve_java14
- fkt_close
- fkt_get_name
- storage_set_flags
- fkt_start_seq_get_int
- fkt_start_seq_get
- fkt_next_entry_int
- fkt_next_entry
- fkt_end_seq_get
- fkt_setup_keytab
- fkt_add_entry
- 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 };