1 /* 2 * Copyright (c) 1997-1999 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: store.c,v 1.32 1999/12/02 17:05:12 joda Exp $"); 37 38 void 39 krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags) 40 { 41 sp->flags |= flags; 42 } 43 44 void 45 krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags) 46 { 47 sp->flags &= ~flags; 48 } 49 50 krb5_boolean 51 krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags) 52 { 53 return (sp->flags & flags) == flags; 54 } 55 56 ssize_t 57 _krb5_put_int(void *buffer, unsigned long value, size_t size) 58 { 59 unsigned char *p = buffer; 60 int i; 61 for (i = size - 1; i >= 0; i--) { 62 p[i] = value & 0xff; 63 value >>= 8; 64 } 65 return size; 66 } 67 68 ssize_t 69 _krb5_get_int(void *buffer, unsigned long *value, size_t size) 70 { 71 unsigned char *p = buffer; 72 unsigned long v = 0; 73 int i; 74 for (i = 0; i < size; i++) 75 v = (v << 8) + p[i]; 76 *value = v; 77 return size; 78 } 79 80 krb5_error_code 81 krb5_storage_free(krb5_storage *sp) 82 { 83 if(sp->free) 84 (*sp->free)(sp); 85 free(sp->data); 86 free(sp); 87 return 0; 88 } 89 90 krb5_error_code 91 krb5_storage_to_data(krb5_storage *sp, krb5_data *data) 92 { 93 off_t pos; 94 size_t size; 95 krb5_error_code ret; 96 97 pos = sp->seek(sp, 0, SEEK_CUR); 98 size = (size_t)sp->seek(sp, 0, SEEK_END); 99 ret = krb5_data_alloc (data, size); 100 if (ret) { 101 sp->seek(sp, pos, SEEK_SET); 102 return ret; 103 } 104 if (size) { 105 sp->seek(sp, 0, SEEK_SET); 106 sp->fetch(sp, data->data, data->length); 107 sp->seek(sp, pos, SEEK_SET); 108 } 109 return 0; 110 } 111 112 static krb5_error_code 113 krb5_store_int(krb5_storage *sp, 114 int32_t value, 115 size_t len) 116 { 117 int ret; 118 unsigned char v[4]; 119 120 _krb5_put_int(v, value, len); 121 ret = sp->store(sp, v, len); 122 if (ret != len) 123 return (ret<0)?errno:KRB5_CC_END; 124 return 0; 125 } 126 127 krb5_error_code 128 krb5_store_int32(krb5_storage *sp, 129 int32_t value) 130 { 131 if(krb5_storage_is_flags(sp, KRB5_STORAGE_HOST_BYTEORDER)) 132 value = htonl(value); 133 return krb5_store_int(sp, value, 4); 134 } 135 136 static krb5_error_code 137 krb5_ret_int(krb5_storage *sp, 138 int32_t *value, 139 size_t len) 140 { 141 int ret; 142 unsigned char v[4]; 143 unsigned long w; 144 ret = sp->fetch(sp, v, len); 145 if(ret != len) 146 return (ret<0)?errno:KRB5_CC_END; 147 _krb5_get_int(v, &w, len); 148 *value = w; 149 return 0; 150 } 151 152 krb5_error_code 153 krb5_ret_int32(krb5_storage *sp, 154 int32_t *value) 155 { 156 krb5_error_code ret = krb5_ret_int(sp, value, 4); 157 if(ret) 158 return ret; 159 if(krb5_storage_is_flags(sp, KRB5_STORAGE_HOST_BYTEORDER)) 160 *value = ntohl(*value); 161 return 0; 162 } 163 164 krb5_error_code 165 krb5_store_int16(krb5_storage *sp, 166 int16_t value) 167 { 168 if(krb5_storage_is_flags(sp, KRB5_STORAGE_HOST_BYTEORDER)) 169 value = htons(value); 170 return krb5_store_int(sp, value, 2); 171 } 172 173 krb5_error_code 174 krb5_ret_int16(krb5_storage *sp, 175 int16_t *value) 176 { 177 int32_t v; 178 int ret; 179 ret = krb5_ret_int(sp, &v, 2); 180 if(ret) 181 return ret; 182 *value = v; 183 if(krb5_storage_is_flags(sp, KRB5_STORAGE_HOST_BYTEORDER)) 184 *value = ntohs(*value); 185 return 0; 186 } 187 188 krb5_error_code 189 krb5_store_int8(krb5_storage *sp, 190 int8_t value) 191 { 192 int ret; 193 194 ret = sp->store(sp, &value, sizeof(value)); 195 if (ret != sizeof(value)) 196 return (ret<0)?errno:KRB5_CC_END; 197 return 0; 198 } 199 200 krb5_error_code 201 krb5_ret_int8(krb5_storage *sp, 202 int8_t *value) 203 { 204 int ret; 205 206 ret = sp->fetch(sp, value, sizeof(*value)); 207 if (ret != sizeof(*value)) 208 return (ret<0)?errno:KRB5_CC_END; 209 return 0; 210 } 211 212 krb5_error_code 213 krb5_store_data(krb5_storage *sp, 214 krb5_data data) 215 { 216 int ret; 217 ret = krb5_store_int32(sp, data.length); 218 if(ret < 0) 219 return ret; 220 ret = sp->store(sp, data.data, data.length); 221 if(ret != data.length){ 222 if(ret < 0) 223 return errno; 224 return KRB5_CC_END; 225 } 226 return 0; 227 } 228 229 krb5_error_code 230 krb5_ret_data(krb5_storage *sp, 231 krb5_data *data) 232 { 233 int ret; 234 int32_t size; 235 236 ret = krb5_ret_int32(sp, &size); 237 if(ret) 238 return ret; 239 ret = krb5_data_alloc (data, size); 240 if (ret) 241 return ret; 242 if (size) { 243 ret = sp->fetch(sp, data->data, size); 244 if(ret != size) 245 return (ret < 0)? errno : KRB5_CC_END; 246 } 247 return 0; 248 } 249 250 krb5_error_code 251 krb5_store_string(krb5_storage *sp, const char *s) 252 { 253 krb5_data data; 254 data.length = strlen(s); 255 data.data = (void*)s; 256 return krb5_store_data(sp, data); 257 } 258 259 krb5_error_code 260 krb5_ret_string(krb5_storage *sp, 261 char **string) 262 { 263 int ret; 264 krb5_data data; 265 ret = krb5_ret_data(sp, &data); 266 if(ret) 267 return ret; 268 *string = realloc(data.data, data.length + 1); 269 if(*string == NULL){ 270 free(data.data); 271 return ENOMEM; 272 } 273 (*string)[data.length] = 0; 274 return 0; 275 } 276 277 krb5_error_code 278 krb5_store_stringz(krb5_storage *sp, 279 char *s) 280 { 281 size_t len = strlen(s) + 1; 282 ssize_t ret; 283 284 ret = sp->store(sp, s, len); 285 if(ret != len) { 286 if(ret < 0) 287 return ret; 288 else 289 return KRB5_CC_END; 290 } 291 return 0; 292 } 293 294 krb5_error_code 295 krb5_ret_stringz(krb5_storage *sp, 296 char **string) 297 { 298 char c; 299 char *s = NULL; 300 size_t len = 0; 301 ssize_t ret; 302 303 while((ret = sp->fetch(sp, &c, 1)) == 1){ 304 char *tmp; 305 306 len++; 307 tmp = realloc (s, len); 308 if (tmp == NULL) { 309 free (s); 310 return ENOMEM; 311 } 312 s = tmp; 313 s[len - 1] = c; 314 if(c == 0) 315 break; 316 } 317 if(ret != 1){ 318 free(s); 319 if(ret == 0) 320 return KRB5_CC_END; 321 return ret; 322 } 323 *string = s; 324 return 0; 325 } 326 327 328 krb5_error_code 329 krb5_store_principal(krb5_storage *sp, 330 krb5_principal p) 331 { 332 int i; 333 int ret; 334 335 if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { 336 ret = krb5_store_int32(sp, p->name.name_type); 337 if(ret) return ret; 338 } 339 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 340 ret = krb5_store_int32(sp, p->name.name_string.len + 1); 341 else 342 ret = krb5_store_int32(sp, p->name.name_string.len); 343 344 if(ret) return ret; 345 ret = krb5_store_string(sp, p->realm); 346 if(ret) return ret; 347 for(i = 0; i < p->name.name_string.len; i++){ 348 ret = krb5_store_string(sp, p->name.name_string.val[i]); 349 if(ret) return ret; 350 } 351 return 0; 352 } 353 354 krb5_error_code 355 krb5_ret_principal(krb5_storage *sp, 356 krb5_principal *princ) 357 { 358 int i; 359 int ret; 360 krb5_principal p; 361 int32_t type; 362 int32_t ncomp; 363 364 p = calloc(1, sizeof(*p)); 365 if(p == NULL) 366 return ENOMEM; 367 368 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) 369 type = KRB5_NT_UNKNOWN; 370 else if((ret = krb5_ret_int32(sp, &type))){ 371 free(p); 372 return ret; 373 } 374 if((ret = krb5_ret_int32(sp, &ncomp))){ 375 free(p); 376 return ret; 377 } 378 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 379 ncomp--; 380 p->name.name_type = type; 381 p->name.name_string.len = ncomp; 382 ret = krb5_ret_string(sp, &p->realm); 383 if(ret) return ret; 384 p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val)); 385 if(p->name.name_string.val == NULL){ 386 free(p->realm); 387 return ENOMEM; 388 } 389 for(i = 0; i < ncomp; i++){ 390 ret = krb5_ret_string(sp, &p->name.name_string.val[i]); 391 if(ret) return ret; /* XXX */ 392 } 393 *princ = p; 394 return 0; 395 } 396 397 krb5_error_code 398 krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p) 399 { 400 int ret; 401 ret = krb5_store_int16(sp, p.keytype); 402 if(ret) return ret; 403 404 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ 405 /* this should really be enctype, but it is the same as 406 keytype nowadays */ 407 ret = krb5_store_int16(sp, p.keytype); 408 if(ret) return ret; 409 } 410 411 ret = krb5_store_data(sp, p.keyvalue); 412 return ret; 413 } 414 415 krb5_error_code 416 krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p) 417 { 418 int ret; 419 int16_t tmp; 420 421 ret = krb5_ret_int16(sp, &tmp); 422 if(ret) return ret; 423 p->keytype = tmp; 424 425 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ 426 ret = krb5_ret_int16(sp, &tmp); 427 if(ret) return ret; 428 } 429 430 ret = krb5_ret_data(sp, &p->keyvalue); 431 return ret; 432 } 433 434 krb5_error_code 435 krb5_store_times(krb5_storage *sp, krb5_times times) 436 { 437 int ret; 438 ret = krb5_store_int32(sp, times.authtime); 439 if(ret) return ret; 440 ret = krb5_store_int32(sp, times.starttime); 441 if(ret) return ret; 442 ret = krb5_store_int32(sp, times.endtime); 443 if(ret) return ret; 444 ret = krb5_store_int32(sp, times.renew_till); 445 return ret; 446 } 447 448 krb5_error_code 449 krb5_ret_times(krb5_storage *sp, krb5_times *times) 450 { 451 int ret; 452 int32_t tmp; 453 ret = krb5_ret_int32(sp, &tmp); 454 times->authtime = tmp; 455 if(ret) return ret; 456 ret = krb5_ret_int32(sp, &tmp); 457 times->starttime = tmp; 458 if(ret) return ret; 459 ret = krb5_ret_int32(sp, &tmp); 460 times->endtime = tmp; 461 if(ret) return ret; 462 ret = krb5_ret_int32(sp, &tmp); 463 times->renew_till = tmp; 464 return ret; 465 } 466 467 krb5_error_code 468 krb5_store_address(krb5_storage *sp, krb5_address p) 469 { 470 int ret; 471 ret = krb5_store_int16(sp, p.addr_type); 472 if(ret) return ret; 473 ret = krb5_store_data(sp, p.address); 474 return ret; 475 } 476 477 krb5_error_code 478 krb5_ret_address(krb5_storage *sp, krb5_address *adr) 479 { 480 int16_t t; 481 int ret; 482 ret = krb5_ret_int16(sp, &t); 483 if(ret) return ret; 484 adr->addr_type = t; 485 ret = krb5_ret_data(sp, &adr->address); 486 return ret; 487 } 488 489 krb5_error_code 490 krb5_store_addrs(krb5_storage *sp, krb5_addresses p) 491 { 492 int i; 493 int ret; 494 ret = krb5_store_int32(sp, p.len); 495 if(ret) return ret; 496 for(i = 0; i<p.len; i++){ 497 ret = krb5_store_address(sp, p.val[i]); 498 if(ret) break; 499 } 500 return ret; 501 } 502 503 krb5_error_code 504 krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr) 505 { 506 int i; 507 int ret; 508 int32_t tmp; 509 510 ret = krb5_ret_int32(sp, &tmp); 511 if(ret) return ret; 512 adr->len = tmp; 513 ALLOC(adr->val, adr->len); 514 for(i = 0; i < adr->len; i++){ 515 ret = krb5_ret_address(sp, &adr->val[i]); 516 if(ret) break; 517 } 518 return ret; 519 } 520 521 krb5_error_code 522 krb5_store_authdata(krb5_storage *sp, krb5_authdata auth) 523 { 524 krb5_error_code ret; 525 int i; 526 ret = krb5_store_int32(sp, auth.len); 527 if(ret) return ret; 528 for(i = 0; i < auth.len; i++){ 529 ret = krb5_store_int16(sp, auth.val[i].ad_type); 530 if(ret) break; 531 ret = krb5_store_data(sp, auth.val[i].ad_data); 532 if(ret) break; 533 } 534 return 0; 535 } 536 537 krb5_error_code 538 krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth) 539 { 540 krb5_error_code ret; 541 int32_t tmp; 542 int16_t tmp2; 543 int i; 544 ret = krb5_ret_int32(sp, &tmp); 545 if(ret) return ret; 546 ALLOC_SEQ(auth, tmp); 547 for(i = 0; i < tmp; i++){ 548 ret = krb5_ret_int16(sp, &tmp2); 549 if(ret) break; 550 auth->val[i].ad_type = tmp2; 551 ret = krb5_ret_data(sp, &auth->val[i].ad_data); 552 if(ret) break; 553 } 554 return ret; 555 } 556 557 krb5_error_code 558 krb5_store_creds(krb5_storage *sp, krb5_creds *creds) 559 { 560 krb5_store_principal(sp, creds->client); 561 krb5_store_principal(sp, creds->server); 562 krb5_store_keyblock(sp, creds->session); 563 krb5_store_times(sp, creds->times); 564 krb5_store_int8(sp, 0); /* this is probably the 565 enc-tkt-in-skey bit from KDCOptions */ 566 krb5_store_int32(sp, creds->flags.i); 567 krb5_store_addrs(sp, creds->addresses); 568 krb5_store_authdata(sp, creds->authdata); 569 krb5_store_data(sp, creds->ticket); 570 krb5_store_data(sp, creds->second_ticket); 571 return 0; 572 } 573 574 krb5_error_code 575 krb5_ret_creds(krb5_storage *sp, krb5_creds *creds) 576 { 577 krb5_error_code ret; 578 int8_t dummy8; 579 int32_t dummy32; 580 581 memset(creds, 0, sizeof(*creds)); 582 ret = krb5_ret_principal (sp, &creds->client); 583 if(ret) goto cleanup; 584 ret = krb5_ret_principal (sp, &creds->server); 585 if(ret) goto cleanup; 586 ret = krb5_ret_keyblock (sp, &creds->session); 587 if(ret) goto cleanup; 588 ret = krb5_ret_times (sp, &creds->times); 589 if(ret) goto cleanup; 590 ret = krb5_ret_int8 (sp, &dummy8); 591 if(ret) goto cleanup; 592 ret = krb5_ret_int32 (sp, &dummy32); 593 if(ret) goto cleanup; 594 creds->flags.i = dummy32; 595 ret = krb5_ret_addrs (sp, &creds->addresses); 596 if(ret) goto cleanup; 597 ret = krb5_ret_authdata (sp, &creds->authdata); 598 if(ret) goto cleanup; 599 ret = krb5_ret_data (sp, &creds->ticket); 600 if(ret) goto cleanup; 601 ret = krb5_ret_data (sp, &creds->second_ticket); 602 cleanup: 603 if(ret) 604 #if 0 605 krb5_free_creds_contents(context, creds) /* XXX */ 606 #endif 607 ; 608 return ret; 609 } 610