1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 /* 8 * lib/krb5/krb/ser_actx.c 9 * 10 * Copyright 1995 by the Massachusetts Institute of Technology. 11 * All Rights Reserved. 12 * 13 * Export of this software from the United States of America may 14 * require a specific license from the United States Government. 15 * It is the responsibility of any person or organization contemplating 16 * export to obtain such a license before exporting. 17 * 18 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 19 * distribute this software and its documentation for any purpose and 20 * without fee is hereby granted, provided that the above copyright 21 * notice appear in all copies and that both that copyright notice and 22 * this permission notice appear in supporting documentation, and that 23 * the name of M.I.T. not be used in advertising or publicity pertaining 24 * to distribution of the software without specific, written prior 25 * permission. Furthermore if you modify this software you must label 26 * your software as modified software and not distribute it in such a 27 * fashion that it might be confused with the original M.I.T. software. 28 * M.I.T. makes no representations about the suitability of 29 * this software for any purpose. It is provided "as is" without express 30 * or implied warranty. 31 * 32 */ 33 34 /* 35 * ser_actx.c - Serialize krb5_auth_context structure. 36 */ 37 #include <k5-int.h> 38 #include <auth_con.h> 39 40 #define TOKEN_RADDR 950916 41 #define TOKEN_RPORT 950917 42 #define TOKEN_LADDR 950918 43 #define TOKEN_LPORT 950919 44 #define TOKEN_KEYBLOCK 950920 45 #define TOKEN_LSKBLOCK 950921 46 #define TOKEN_RSKBLOCK 950922 47 48 /* 49 * Routines to deal with externalizing the krb5_auth_context: 50 * krb5_auth_context_size(); 51 * krb5_auth_context_externalize(); 52 * krb5_auth_context_internalize(); 53 */ 54 static krb5_error_code krb5_auth_context_size 55 (krb5_context, krb5_pointer, size_t *); 56 static krb5_error_code krb5_auth_context_externalize 57 (krb5_context, krb5_pointer, krb5_octet **, size_t *); 58 static krb5_error_code krb5_auth_context_internalize 59 (krb5_context,krb5_pointer *, krb5_octet **, size_t *); 60 61 /* 62 * Other metadata serialization initializers. 63 */ 64 krb5_error_code krb5_ser_authdata_init (krb5_context); 65 krb5_error_code krb5_ser_address_init (krb5_context); 66 krb5_error_code krb5_ser_authenticator_init (krb5_context); 67 krb5_error_code krb5_ser_checksum_init (krb5_context); 68 krb5_error_code krb5_ser_keyblock_init (krb5_context); 69 krb5_error_code krb5_ser_principal_init (krb5_context); 70 71 /* Local data */ 72 static const krb5_ser_entry krb5_auth_context_ser_entry = { 73 KV5M_AUTH_CONTEXT, /* Type */ 74 krb5_auth_context_size, /* Sizer routine */ 75 krb5_auth_context_externalize, /* Externalize routine */ 76 krb5_auth_context_internalize /* Internalize routine */ 77 }; 78 79 /* 80 * krb5_auth_context_size() - Determine the size required to externalize 81 * the krb5_auth_context. 82 */ 83 static krb5_error_code 84 krb5_auth_context_size( 85 krb5_context kcontext, 86 krb5_pointer arg, 87 size_t *sizep) 88 { 89 krb5_error_code kret; 90 krb5_auth_context auth_context; 91 size_t required; 92 93 /* 94 * krb5_auth_context requires at minimum: 95 * krb5_int32 for KV5M_AUTH_CONTEXT 96 * krb5_int32 for auth_context_flags 97 * krb5_int32 for remote_seq_number 98 * krb5_int32 for local_seq_number 99 * krb5_int32 for req_cksumtype 100 * krb5_int32 for safe_cksumtype 101 * krb5_int32 for size of i_vector 102 * krb5_int32 for KV5M_AUTH_CONTEXT 103 */ 104 kret = EINVAL; 105 auth_context = (krb5_auth_context) arg; 106 if (auth_context) { 107 kret = 0; 108 109 /* Calculate size required by i_vector - ptooey */ 110 if (auth_context->i_vector && auth_context->keyblock) { 111 kret = krb5_c_block_size(kcontext, auth_context->keyblock->enctype, 112 &required); 113 } else { 114 required = 0; 115 } 116 117 required += sizeof(krb5_int32)*8; 118 119 /* Calculate size required by remote_addr, if appropriate */ 120 if (!kret && auth_context->remote_addr) { 121 kret = krb5_size_opaque(kcontext, 122 KV5M_ADDRESS, 123 (krb5_pointer) auth_context->remote_addr, 124 &required); 125 if (!kret) 126 required += sizeof(krb5_int32); 127 } 128 129 /* Calculate size required by remote_port, if appropriate */ 130 if (!kret && auth_context->remote_port) { 131 kret = krb5_size_opaque(kcontext, 132 KV5M_ADDRESS, 133 (krb5_pointer) auth_context->remote_port, 134 &required); 135 if (!kret) 136 required += sizeof(krb5_int32); 137 } 138 139 /* Calculate size required by local_addr, if appropriate */ 140 if (!kret && auth_context->local_addr) { 141 kret = krb5_size_opaque(kcontext, 142 KV5M_ADDRESS, 143 (krb5_pointer) auth_context->local_addr, 144 &required); 145 if (!kret) 146 required += sizeof(krb5_int32); 147 } 148 149 /* Calculate size required by local_port, if appropriate */ 150 if (!kret && auth_context->local_port) { 151 kret = krb5_size_opaque(kcontext, 152 KV5M_ADDRESS, 153 (krb5_pointer) auth_context->local_port, 154 &required); 155 if (!kret) 156 required += sizeof(krb5_int32); 157 } 158 159 /* Calculate size required by keyblock, if appropriate */ 160 if (!kret && auth_context->keyblock) { 161 kret = krb5_size_opaque(kcontext, 162 KV5M_KEYBLOCK, 163 (krb5_pointer) auth_context->keyblock, 164 &required); 165 if (!kret) 166 required += sizeof(krb5_int32); 167 } 168 169 /* Calculate size required by send_subkey, if appropriate */ 170 if (!kret && auth_context->send_subkey) { 171 kret = krb5_size_opaque(kcontext, 172 KV5M_KEYBLOCK, 173 (krb5_pointer) auth_context->send_subkey, 174 &required); 175 if (!kret) 176 required += sizeof(krb5_int32); 177 } 178 179 /* Calculate size required by recv_subkey, if appropriate */ 180 if (!kret && auth_context->recv_subkey) { 181 kret = krb5_size_opaque(kcontext, 182 KV5M_KEYBLOCK, 183 (krb5_pointer) auth_context->recv_subkey, 184 &required); 185 if (!kret) 186 required += sizeof(krb5_int32); 187 } 188 189 /* Calculate size required by authentp, if appropriate */ 190 if (!kret && auth_context->authentp) 191 kret = krb5_size_opaque(kcontext, 192 KV5M_AUTHENTICATOR, 193 (krb5_pointer) auth_context->authentp, 194 &required); 195 196 } 197 if (!kret) 198 *sizep += required; 199 return(kret); 200 } 201 202 /* 203 * krb5_auth_context_externalize() - Externalize the krb5_auth_context. 204 */ 205 static krb5_error_code 206 krb5_auth_context_externalize( 207 krb5_context kcontext, 208 krb5_pointer arg, 209 krb5_octet **buffer, 210 size_t *lenremain) 211 { 212 krb5_error_code kret; 213 krb5_auth_context auth_context; 214 size_t required; 215 krb5_octet *bp; 216 size_t remain; 217 size_t obuf; 218 219 required = 0; 220 bp = *buffer; 221 remain = *lenremain; 222 kret = EINVAL; 223 auth_context = (krb5_auth_context) arg; 224 if (auth_context) { 225 kret = ENOMEM; 226 if (!krb5_auth_context_size(kcontext, arg, &required) && 227 (required <= remain)) { 228 229 /* Write fixed portion */ 230 (void) krb5_ser_pack_int32(KV5M_AUTH_CONTEXT, &bp, &remain); 231 (void) krb5_ser_pack_int32(auth_context->auth_context_flags, 232 &bp, &remain); 233 (void) krb5_ser_pack_int32(auth_context->remote_seq_number, 234 &bp, &remain); 235 (void) krb5_ser_pack_int32(auth_context->local_seq_number, 236 &bp, &remain); 237 (void) krb5_ser_pack_int32((krb5_int32) auth_context->req_cksumtype, 238 &bp, &remain); 239 (void) krb5_ser_pack_int32((krb5_int32) auth_context->safe_cksumtype, 240 &bp, &remain); 241 242 kret = 0; 243 244 /* Now figure out the number of bytes for i_vector and write it */ 245 if (auth_context->i_vector) { 246 kret = krb5_c_block_size(kcontext, 247 auth_context->keyblock->enctype, 248 &obuf); 249 } else { 250 obuf = 0; 251 } 252 253 if (!kret) 254 (void) krb5_ser_pack_int32(obuf, &bp, &remain); 255 256 /* Now copy i_vector */ 257 if (!kret && auth_context->i_vector) 258 (void) krb5_ser_pack_bytes(auth_context->i_vector, 259 (size_t) obuf, 260 &bp, &remain); 261 262 /* Now handle remote_addr, if appropriate */ 263 if (!kret && auth_context->remote_addr) { 264 (void) krb5_ser_pack_int32(TOKEN_RADDR, &bp, &remain); 265 kret = krb5_externalize_opaque(kcontext, 266 KV5M_ADDRESS, 267 (krb5_pointer) 268 auth_context->remote_addr, 269 &bp, 270 &remain); 271 } 272 273 /* Now handle remote_port, if appropriate */ 274 if (!kret && auth_context->remote_port) { 275 (void) krb5_ser_pack_int32(TOKEN_RPORT, &bp, &remain); 276 kret = krb5_externalize_opaque(kcontext, 277 KV5M_ADDRESS, 278 (krb5_pointer) 279 auth_context->remote_addr, 280 &bp, 281 &remain); 282 } 283 284 /* Now handle local_addr, if appropriate */ 285 if (!kret && auth_context->local_addr) { 286 (void) krb5_ser_pack_int32(TOKEN_LADDR, &bp, &remain); 287 kret = krb5_externalize_opaque(kcontext, 288 KV5M_ADDRESS, 289 (krb5_pointer) 290 auth_context->local_addr, 291 &bp, 292 &remain); 293 } 294 295 /* Now handle local_port, if appropriate */ 296 if (!kret && auth_context->local_port) { 297 (void) krb5_ser_pack_int32(TOKEN_LPORT, &bp, &remain); 298 kret = krb5_externalize_opaque(kcontext, 299 KV5M_ADDRESS, 300 (krb5_pointer) 301 auth_context->local_addr, 302 &bp, 303 &remain); 304 } 305 306 /* Now handle keyblock, if appropriate */ 307 if (!kret && auth_context->keyblock) { 308 (void) krb5_ser_pack_int32(TOKEN_KEYBLOCK, &bp, &remain); 309 kret = krb5_externalize_opaque(kcontext, 310 KV5M_KEYBLOCK, 311 (krb5_pointer) 312 auth_context->keyblock, 313 &bp, 314 &remain); 315 } 316 317 /* Now handle subkey, if appropriate */ 318 if (!kret && auth_context->send_subkey) { 319 (void) krb5_ser_pack_int32(TOKEN_LSKBLOCK, &bp, &remain); 320 kret = krb5_externalize_opaque(kcontext, 321 KV5M_KEYBLOCK, 322 (krb5_pointer) 323 auth_context->send_subkey, 324 &bp, 325 &remain); 326 } 327 328 /* Now handle subkey, if appropriate */ 329 if (!kret && auth_context->recv_subkey) { 330 (void) krb5_ser_pack_int32(TOKEN_RSKBLOCK, &bp, &remain); 331 kret = krb5_externalize_opaque(kcontext, 332 KV5M_KEYBLOCK, 333 (krb5_pointer) 334 auth_context->recv_subkey, 335 &bp, 336 &remain); 337 } 338 339 /* Now handle authentp, if appropriate */ 340 if (!kret && auth_context->authentp) 341 kret = krb5_externalize_opaque(kcontext, 342 KV5M_AUTHENTICATOR, 343 (krb5_pointer) 344 auth_context->authentp, 345 &bp, 346 &remain); 347 348 /* 349 * If we were successful, write trailer then update the pointer and 350 * remaining length; 351 */ 352 if (!kret) { 353 /* Write our trailer */ 354 (void) krb5_ser_pack_int32(KV5M_AUTH_CONTEXT, &bp, &remain); 355 *buffer = bp; 356 *lenremain = remain; 357 } 358 } 359 } 360 return(kret); 361 } 362 363 /* 364 * krb5_auth_context_internalize() - Internalize the krb5_auth_context. 365 */ 366 static krb5_error_code 367 krb5_auth_context_internalize( 368 krb5_context kcontext, 369 krb5_pointer *argp, 370 krb5_octet **buffer, 371 size_t *lenremain) 372 { 373 krb5_error_code kret; 374 krb5_auth_context auth_context; 375 krb5_int32 ibuf; 376 krb5_octet *bp; 377 size_t remain; 378 krb5_int32 ivlen; 379 krb5_int32 tag; 380 381 bp = *buffer; 382 remain = *lenremain; 383 kret = EINVAL; 384 /* Read our magic number */ 385 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) 386 ibuf = 0; 387 if (ibuf == KV5M_AUTH_CONTEXT) { 388 kret = ENOMEM; 389 390 /* Get memory for the auth_context */ 391 if ((remain >= (5*sizeof(krb5_int32))) && 392 (auth_context = (krb5_auth_context) 393 MALLOC(sizeof(struct _krb5_auth_context)))) { 394 (void) memset(auth_context, 0, sizeof(struct _krb5_auth_context)); 395 396 /* Get auth_context_flags */ 397 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 398 auth_context->auth_context_flags = ibuf; 399 400 /* Get remote_seq_number */ 401 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 402 auth_context->remote_seq_number = ibuf; 403 404 /* Get local_seq_number */ 405 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 406 auth_context->local_seq_number = ibuf; 407 408 /* Get req_cksumtype */ 409 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 410 auth_context->req_cksumtype = (krb5_cksumtype) ibuf; 411 412 /* Get safe_cksumtype */ 413 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 414 auth_context->safe_cksumtype = (krb5_cksumtype) ibuf; 415 416 /* Get length of i_vector */ 417 (void) krb5_ser_unpack_int32(&ivlen, &bp, &remain); 418 419 if (ivlen) { 420 if ((auth_context->i_vector = 421 (krb5_pointer) MALLOC((size_t)ivlen))) 422 kret = krb5_ser_unpack_bytes(auth_context->i_vector, 423 (size_t) ivlen, 424 &bp, 425 &remain); 426 else 427 kret = ENOMEM; 428 } 429 else 430 kret = 0; 431 432 /* Peek at next token */ 433 tag = 0; 434 if (!kret) 435 kret = krb5_ser_unpack_int32(&tag, &bp, &remain); 436 437 /* This is the remote_addr */ 438 if (!kret && (tag == TOKEN_RADDR)) { 439 if (!(kret = krb5_internalize_opaque(kcontext, 440 KV5M_ADDRESS, 441 (krb5_pointer *) 442 &auth_context-> 443 remote_addr, 444 &bp, 445 &remain))) 446 kret = krb5_ser_unpack_int32(&tag, &bp, &remain); 447 } 448 449 /* This is the remote_port */ 450 if (!kret && (tag == TOKEN_RPORT)) { 451 if (!(kret = krb5_internalize_opaque(kcontext, 452 KV5M_ADDRESS, 453 (krb5_pointer *) 454 &auth_context-> 455 remote_port, 456 &bp, 457 &remain))) 458 kret = krb5_ser_unpack_int32(&tag, &bp, &remain); 459 } 460 461 /* This is the local_addr */ 462 if (!kret && (tag == TOKEN_LADDR)) { 463 if (!(kret = krb5_internalize_opaque(kcontext, 464 KV5M_ADDRESS, 465 (krb5_pointer *) 466 &auth_context-> 467 local_addr, 468 &bp, 469 &remain))) 470 kret = krb5_ser_unpack_int32(&tag, &bp, &remain); 471 } 472 473 /* This is the local_port */ 474 if (!kret && (tag == TOKEN_LPORT)) { 475 if (!(kret = krb5_internalize_opaque(kcontext, 476 KV5M_ADDRESS, 477 (krb5_pointer *) 478 &auth_context-> 479 local_port, 480 &bp, 481 &remain))) 482 kret = krb5_ser_unpack_int32(&tag, &bp, &remain); 483 } 484 485 /* This is the keyblock */ 486 if (!kret && (tag == TOKEN_KEYBLOCK)) { 487 if (!(kret = krb5_internalize_opaque(kcontext, 488 KV5M_KEYBLOCK, 489 (krb5_pointer *) 490 &auth_context->keyblock, 491 &bp, 492 &remain))) 493 kret = krb5_ser_unpack_int32(&tag, &bp, &remain); 494 } 495 496 /* This is the send_subkey */ 497 if (!kret && (tag == TOKEN_LSKBLOCK)) { 498 if (!(kret = krb5_internalize_opaque(kcontext, 499 KV5M_KEYBLOCK, 500 (krb5_pointer *) 501 &auth_context-> 502 send_subkey, 503 &bp, 504 &remain))) 505 kret = krb5_ser_unpack_int32(&tag, &bp, &remain); 506 } 507 508 /* This is the recv_subkey */ 509 if (!kret) { 510 if (tag == TOKEN_RSKBLOCK) { 511 kret = krb5_internalize_opaque(kcontext, 512 KV5M_KEYBLOCK, 513 (krb5_pointer *) 514 &auth_context-> 515 recv_subkey, 516 &bp, 517 &remain); 518 } 519 else { 520 /* 521 * We read the next tag, but it's not of any use here, so 522 * we effectively 'unget' it here. 523 */ 524 bp -= sizeof(krb5_int32); 525 remain += sizeof(krb5_int32); 526 } 527 } 528 529 /* Now find the authentp */ 530 if (!kret) { 531 if ((kret = krb5_internalize_opaque(kcontext, 532 KV5M_AUTHENTICATOR, 533 (krb5_pointer *) 534 &auth_context->authentp, 535 &bp, 536 &remain))) { 537 if (kret == EINVAL) 538 kret = 0; 539 } 540 } 541 542 /* Finally, find the trailer */ 543 if (!kret) { 544 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); 545 if (!kret && (ibuf != KV5M_AUTH_CONTEXT)) 546 kret = EINVAL; 547 } 548 if (!kret) { 549 *buffer = bp; 550 *lenremain = remain; 551 auth_context->magic = KV5M_AUTH_CONTEXT; 552 *argp = (krb5_pointer) auth_context; 553 } 554 /* We don't import the auth_context into the kernel */ 555 #ifndef _KERNEL 556 else 557 krb5_auth_con_free(kcontext, auth_context); 558 #endif 559 } 560 } 561 return(kret); 562 } 563 564 /* 565 * Register the auth_context serializer. 566 */ 567 krb5_error_code KRB5_CALLCONV 568 krb5_ser_auth_context_init(krb5_context kcontext) 569 { 570 krb5_error_code kret; 571 kret = krb5_register_serializer(kcontext, &krb5_auth_context_ser_entry); 572 if (!kret) 573 kret = krb5_ser_authdata_init(kcontext); 574 if (!kret) 575 kret = krb5_ser_address_init(kcontext); 576 if (!kret) 577 kret = krb5_ser_authenticator_init(kcontext); 578 if (!kret) 579 kret = krb5_ser_checksum_init(kcontext); 580 if (!kret) 581 kret = krb5_ser_keyblock_init(kcontext); 582 if (!kret) 583 kret = krb5_ser_principal_init(kcontext); 584 return(kret); 585 } 586