idnits 2.17.1 draft-ietf-kitten-gss-loop-00.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- ** The document is more than 15 pages and seems to lack a Table of Contents. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The document seems to lack an IANA Considerations section. (See Section 2.2 of https://www.ietf.org/id-info/checklist for how to handle the case when there are no actions for IANA.) Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (May 8, 2014) is 3642 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. Checking references for intended status: Informational ---------------------------------------------------------------------------- No issues found here. Summary: 2 errors (**), 0 flaws (~~), 1 warning (==), 2 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Network Working Group B. Kaduk 3 Internet-Draft MIT 4 Intended status: Informational May 8, 2014 5 Expires: November 9, 2014 7 Structure of the GSS Negotiation Loop 8 draft-ietf-kitten-gss-loop-00 10 Abstract 12 This document specifies the generic structure of the negotiation loop 13 to establish a GSS security context between initiator and acceptor. 14 The control flow of the loop is indicated for both parties, including 15 error conditions, and indications are given for where application- 16 specific behavior must be specified. 18 Status of This Memo 20 This Internet-Draft is submitted in full conformance with the 21 provisions of BCP 78 and BCP 79. 23 Internet-Drafts are working documents of the Internet Engineering 24 Task Force (IETF). Note that other groups may also distribute 25 working documents as Internet-Drafts. The list of current Internet- 26 Drafts is at http://datatracker.ietf.org/drafts/current/. 28 Internet-Drafts are draft documents valid for a maximum of six months 29 and may be updated, replaced, or obsoleted by other documents at any 30 time. It is inappropriate to use Internet-Drafts as reference 31 material or to cite them other than as "work in progress." 33 This Internet-Draft will expire on November 9, 2014. 35 Copyright Notice 37 Copyright (c) 2014 IETF Trust and the persons identified as the 38 document authors. All rights reserved. 40 This document is subject to BCP 78 and the IETF Trust's Legal 41 Provisions Relating to IETF Documents 42 (http://trustee.ietf.org/license-info) in effect on the date of 43 publication of this document. Please review these documents 44 carefully, as they describe your rights and restrictions with respect 45 to this document. Code Components extracted from this document must 46 include Simplified BSD License text as described in Section 4.e of 47 the Trust Legal Provisions and are provided without warranty as 48 described in the Simplified BSD License. 50 1. Introduction 52 The Generic Security Service Application Program Intervace version 2 53 [RFC2743] provides a generic interface for security services, in the 54 form of an abstraction layer over the underlying security mechanisms 55 that an application may use. A GSS initiator and acceptor exchange 56 messages, called tokens, until a security context is established. 57 Such a security context allows for mutual authentication of the two 58 parties, the passing of confidential or integrity-protected messages 59 between the initiator and acceptor, the generation of identical 60 pseudo-random bit strings by both participants [RFC4401], and more. 61 The number of tokens which must be exchanged between initiator and 62 acceptor in order to establish the security context is dependent on 63 the underlying mechanism as well as the desired properties of the 64 security context, and is in general not known to the application. 65 Accordingly, the application's control flow must include a loop 66 within which GSS security context tokens are exchanged, which 67 terminates upon successful establishment of a security context (or an 68 error condition). 70 The GSS-API C bindings [RFC2744] provide some example code for such a 71 negotiation loop, but this code does not specify the application's 72 behavior on unexpected or error conditions. As such, individual 73 application protocol specifications have had to specify the structure 74 of their GSS negotiation loops, including error handling, on a per- 75 protocol basis. [RFC4462], [RFC3645], [RFC5801], [RFC4752], 76 [RFC2203] This represents a substantial duplication of effort, and 77 the various specifications go into different levels of detail and 78 describe different possible error conditions. It is therefore 79 preferable to have the structure of the GSS negotiation loop, 80 including error conditions and token passing, described in a single 81 specification, which can then be referred to from other documents in 82 lieu of repeating the structure of the loop each time. This document 83 will perform that role. 85 The necessary requirements for correctly performing a GSS negotiation 86 loop are essentially all included in [RFC2743], but they are 87 scattered in many different places. This document brings all the 88 requirements together into one place for the convenience of 89 implementors, even though the normative requirements remain in 90 [RFC2743]. In a few places, this document notes additional behavior 91 which is useful for applications but is not mandated by [RFC2743]. 93 2. Loop Structure 95 The loop is begun by the appropriately named initiator, which calls 96 GSS_Init_sec_context() with an empty (zero-length) input_token and a 97 fixed set of input flags containing the desired attributes for the 98 security context. The initiator should not change any of the input 99 parameters to GSS_Init_sec_context() between calls to it during the 100 loop, with the exception of the input_token parameter, which will 101 contain a message from the acceptor after the initial call, and the 102 input_context_handle, which must be the result returned in the 103 output_context_handle of the previous call to GSS_Init_sec_context() 104 (GSS_C_NO_CONTEXT for the first call). (In the C bindings, there is 105 only a single read/modify context_handle argument, so the same 106 variable should be passed for each call in the loop.) RFC 2743 only 107 requires that the claimant_cred_handle argument remain constant over 108 all calls in the loop, but the other non-excepted arguments should 109 also remain fixed for reliable operation. 111 The following subsections will describe the various steps of the 112 loop, without special consideration to whether a call to 113 GSS_Init_sec_context() or GSS_Accept_sec_context() is the first such 114 call in the loop. For the first call to each routine in the loop, 115 the major status code from the previous call to 116 GSS_Init_sec_context() or GSS_Accept_sec_context() should be taken as 117 GSS_S_CONTINUE_NEEDED. 119 2.1. Anonymous Initiators 121 If the initiator is requesting anonymity by setting the anon_req_flag 122 input to GSS_Init_sec_context(), then on non-error returns from 123 GSS_Init_sec_context() (that is, when the major status is 124 GSS_S_COMPLETE or GSS_S_CONTINUE_NEEDED), the initiator must verify 125 that the output value of anon_state from GSS_Init_sec_context() is 126 true before sending the security context token to the acceptor. 127 Failing to perform this check could cause the initiator to lose 128 anonymity. 130 2.2. GSS_Init_sec_context 132 The initiator calls GSS_Init_sec_context(), using the 133 input_context_handle for the current proto-security-context and its 134 fixed set of input parameters, and the input_token received from the 135 acceptor (if not the first iteration of the loop). The presence of a 136 nonempty output_token and the value of the major status code are the 137 indicators for how to proceed: 139 If the major status code is GSS_S_COMPLETE and the output_token is 140 empty, then the context negotiation is fully complete and ready 141 for use by the initiator with no further actions. 143 If the major status code is GSS_S_COMPLETE and the output_token is 144 nonempty, then the initiator's portion of the security context 145 negotiation is complete but the acceptor's is not. The initiator 146 must send the output_token to the acceptor so that the acceptor 147 can establish its half of the security context. 149 If the major status code is GSS_S_CONTINUE_NEEDED and the 150 output_token is nonempty, the context negotiation is incomplete. 151 The initiator must send the output_token to the acceptor and await 152 another input_token from the acceptor. 154 If the major status code is GSS_S_CONTINUE_NEEDED and the 155 output_token is empty, the mechanism has produced an output which 156 is not compliant with [RFC2743]. However, there are some known 157 implementations of certain mechanisms which do produce empty 158 context negotiation tokens. For maximum interoperability, 159 applications should be prepared to accept such tokens, and should 160 transmit them to the acceptor if they are generated. 162 If the major status code is any other value, the context 163 negotiation has failed. If the output_token is nonempty, it is an 164 error token, and the initiator should send it to the acceptor. If 165 the output_token is empty, then the initiator should indicate the 166 failure to the acceptor if an appropriate channel to do so is 167 available. 169 2.3. Sending from Initiator to Acceptor 171 The establishment of a GSS security context between initiator and 172 acceptor requires some communication channel by which to exchange the 173 context negotiation tokens. The nature of this channel is not 174 specified by the GSS specification -- it could be a synchronous TCP 175 channel, a UDP-based RPC protocol, or any other sort of channel. In 176 many cases, the channel will be multiplexed with non-GSS application 177 data; the application protocol must provide some means by which the 178 GSS context tokens can be identified and passed through to the 179 mechanism accordingly. It is in such cases where the application 180 protocol has a means to indicate error conditions that the initiator 181 could indicate a failure to the acceptor, as mentioned in some of the 182 above cases conditional on "an appropriate channel to do so". 184 However, even the presence of a communication channel does not 185 necessarily indicate that it is appropriate for the initiator to 186 indicate such errors. For example, if the acceptor is a stateless or 187 near-stateless UDP server, there is probably no need for the 188 initiator to explicitly indicate its failure to the acceptor. 189 Conditions such as this can be treated in individual application 190 protocol specifications. 192 If a regular security context output_token is produced by the call to 193 GSS_Init_sec_context(), the initiator must transmit this token to the 194 acceptor over the application's communication channel. If the call 195 to GSS_Init_sec_context() returns an error token as output_token, it 196 is recommended that the intiator transmit this token to the acceptor 197 over the application's communication channel. 199 2.4. Acceptor Sanity Checking 201 The acceptor's half of the negotiation loop is triggered by the 202 receipt of a context token from the initiator. Before calling 203 GSS_Accept_sec_context(), the acceptor may find it useful to perform 204 some sanity checks on the state of the negotiation loop. 206 If the acceptor receives a context token but was not expecting such a 207 token (for example, if the acceptor's previous call to 208 GSS_Accept_sec_context() returned GSS_S_COMPLETE), this is probably 209 an error condition indicating that the initiator's state is invalid. 210 See Section 3.2 for some exceptional cases. It is likely appropriate 211 for the acceptor to report this error condition to the acceptor via 212 the application's communication channel. 214 If the acceptor is expecting a context token (e.g., if the previous 215 call to GSS_Accept_sec_context() returned GSS_S_CONTINUE_NEEDED), but 216 does not receive such a token within a reasonable amount of time 217 after transmitting the previous output_token to the initiator, the 218 acceptor should assume that the initiator's state is invalid and fail 219 the GSS negotiation. Again, it is likely appropriate for the 220 acceptor to report this error condition to the initiator via the 221 application's communication channel. 223 2.5. GSS_Accept_sec_context 225 The GSS acceptor responds to the actions of an initiator; as such, 226 there should always be a nonempty input_token to calls to 227 GSS_Accept_sec_context(). The input_context_handle parameter will 228 always be given as the output_context_handle from the previous call 229 to GSS_Accept_sec_context() in a given negotiation loop (or 230 GSS_C_NO_CONTEXT on the first call), but the acceptor_cred_handle and 231 chan_bindings arguments should remain fixed over the course of a 232 given GSS negotiation loop. [RFC2743] only requires that the 233 acceptor_cred_handle remain fixed throughout the loop, but the 234 chan_bindings argument should also remain fixed for reliable 235 operation. 237 The GSS acceptor calls GSS_Accept_sec_context(), using the 238 input_context_handle for the current proto-security-context and the 239 input_token received from the initiator. The presence of a nonempty 240 output_token and the value of the major status code are the 241 indicators for how to proceed: 243 If the major status code is GSS_S_COMPLETE and the output_token is 244 empty, then the context negotiation is fully complete and ready 245 for use by the acceptor with no further actions. 247 If the major status code is GSS_S_COMPLETE and the output_token is 248 nonempty, then the acceptor's portion of the security context 249 negotiation is complete but the initiator's is not. The acceptor 250 must send the output_token to the initiator so that the initiator 251 can establish its half of the security context. 253 If the major status code is GSS_S_CONTINUE_NEEDED and the 254 output_token is nonempty, the context negotiation is incomplete. 255 The acceptor must send the output_token to the initiator and await 256 another input_token from the initiator. 258 If the major status code is GSS_S_CONTINUE_NEEDED and the 259 output_token is empty, the mechanism has produced an output which 260 is not compliant with [RFC2743]. However, there are some known 261 implementations of certain mechanisms which do produce empty 262 context negotiation tokens. For maximum interoperability, 263 applications should be prepared to accept such tokens, and should 264 transmit them to the initiator if they are generated. 266 If the major status code is any other value, the context 267 negotiation has failed. If the output_token is nonempty, it is an 268 error token, and the acceptor should send it to the initiator. If 269 the output_token is empty, then the acceptor should indicate the 270 failure to the initiator if an appropriate channel to do so is 271 available. 273 2.6. Sending from Acceptor to Initiator 275 The mechanism for sending the context token from acceptor to 276 initiator will depend on the nature of the communication channel 277 between the two parties. For a synchronous bidirectional channel, it 278 can be just another piece of data sent over the link, but for a 279 stateless UDP RPC acceptor, the token will probably end up being sent 280 as an RPC output parameter. Application protocol specifications will 281 need to specify the nature of this behavior. 283 If the application protocol has the initiator driving the 284 application's control flow (with the acceptor just responding to 285 actions from the initiator), it is particularly helpful for the 286 acceptor to indicate a failure to the initiator, as mentioned in some 287 of the above cases conditional on "an appropriate channel to do so". 289 If a regular security context output_token is produced by the call to 290 GSS_Accept_sec_context(), the acceptor must transmit this token to 291 the initiator over the application's communication channel. If the 292 call to GSS_Accept_sec_context() returns an error token as 293 output_token, it is recommended that the acceptor transmit this token 294 to the initiator over the application's communication channel. 296 2.7. Initiator input validation 298 The initiator's half of the negotiation loop is triggered (after the 299 first call) by receipt of a context token from the acceptor. Before 300 calling GSS_Init_sec_context(), the initiator may find it useful to 301 perform some sanity checks on the state of the negotiation loop. 303 If the initiator receives a context token but was not expecting such 304 a token (for example, if the initiator's previous call to 305 GSS_Init_sec_context() returned GSS_S_COMPLETE), this is probably an 306 error condition indicating that the acceptor's state is invalid. See 307 Section 3.2 for some exceptional cases. It may be appropriate for 308 the initiator to report this error condition to the acceptor via the 309 application's communication channel. 311 If the initiator is expecting a context token (that is, the previous 312 call to GSS_Init_sec_context() returned GSS_S_CONTINUE_NEEDED), but 313 does not receive such a token within a reasonable amount of time 314 after transmitting the previous output_token to the acceptor, the 315 initiator should assume that the acceptor's state is invalid and fail 316 the GSS negotiation. Again, it may be appropriate for the initiator 317 to report this error condition to the acceptor via the application's 318 communication channel. 320 2.8. Continue the Loop 322 If the loop is in neither a success or failure condition, then the 323 loop must continue. Control flow returns to Section 2.2. 325 3. After Security Context Negotiation 327 Once a party has completed its half of the security context and 328 fulfilled its obligations to the other party, the context is 329 complete, but it is not necessarily ready and appropriate for use. 330 (In some cases the context may be ready for use earlier than this, 331 see Section 3.1.) In particular, the security context flags may not 332 be appropriate for the given application's use. 334 The initiator specifies as part of its fixed set of inputs to 335 GSS_Init_sec_context() values for the following booleans: 336 deleg_req_flag, mutual_req_flag, replay_det_req_flag, 337 sequence_req_flag, conf_req_flag, and integ_req_flag. Upon 338 completion of security context negotiation, the initiator must verify 339 that the values of the deleg_state, mutual_state, replay_det_state, 340 sequence_state, conf_avail, and integ_avail flags from the last call 341 to GSS_Init_sec_context() corresponding to the requested flags. If a 342 flag was requested but is not available, and that feature is 343 necessary for the appplication protocol, the initiator must destroy 344 the security context and not use the security context for application 345 traffic. 347 Application protocol specifications citing this document should 348 indicate which context flags are required for their application 349 protocol. 351 The acceptor receives as output the following booleans: deleg_state, 352 mutual_state, replay_det_state, sequence_state, anon_state, 353 trans_state, conf_avail, and integ_avail. The acceptor must verify 354 that any flags necessary for the application protocol are set. If a 355 necessary flag is not set, the acceptor must destroy the security 356 context and not use the security context for application traffic. 358 3.1. Using Partially Complete Security Contexts 360 For mechanism/flag combinations that require multiple token 361 exchanges, an application protocol may find it desirable to begin 362 sending application data protected with GSS per-message operations 363 while continuing to exchange security context tokens to complete the 364 security context negotiation. For example, an application may wish 365 to reduce the number of round trips before application data is 366 transmitted. The prot_ready_state output value from 367 GSS_Init_sec_context() and GSS_Accept_sec_context() indicates when 368 per-message operations are avaialble. Applications using per-message 369 operations on a partially complete security context must ensure that 370 there is some mechanism in place to prevent replays of those 371 messages. 373 Applications requiring confidentiality and/or integrity protection 374 from such messages must check the value of the conf_avail and/or 375 integ_avail output flags from GSS_Init_sec_context()/ 376 GSS_Accept_sec_context() as well as the conf_state output of 377 GSS_Wrap() (if GSS_Wrap() is used). 379 3.2. Additional Context Tokens 381 Under some (rare) conditions, a context token will be received by a 382 party to a security context negotiation after that party has 383 completed the negotiation (i.e., after GSS_Init_sec_context() or 384 GSS_Accept_sec_context() has returned GSS_S_COMPLETE). Such tokens 385 must be passed to GSS_Process_context_token() for processing. 387 The most common cause of such tokens is security context deletion 388 tokens, emitted when the remote party called GSS_Delete_sec_context() 389 with a non-null output_context_token parameter. With the GSS-API 390 version 2, it is not recommended to use security context deletion 391 tokens. 393 Extra security context tokens can also be emitted if the selected 394 mechanism specifies some functionality (such as per-message 395 confidentiality protection) as optional-to-implement, and the 396 acceptor's implementation does not implement the optional 397 functionality, but the functionality was requested by the initiator. 398 In this case, the acceptor's GSS implementation is required to emit 399 at least one context token (even when one would not otherwise be 400 needed to complete the context negotiation), and this can result in 401 an "extra" token. 403 In the rare case when an application receives an extra context token, 404 GSS_Inquire_context() should be used after processing the extra token 405 to re-verify that the context does support the features necessary for 406 the application protocol. This will also indicate whether the token 407 was a deletion token, in which case the major status will be 408 GSS_S_NO_CONTEXT. 410 4. Sample Code 412 This section gives sample code for the GSS negotiation loop, both for 413 a regular application and for an application where the initiator 414 wishes to remain anonymous. Since the code for the two cases is very 415 similar, the anonymous-specific additions are wrapped in a 416 conditional check; that check and the conditional code may be ignored 417 if anonymous processing is not needed. 419 Since the communication channel between the initiator and acceptor is 420 a matter for individual application protocols, it is inherently 421 unspecified at the GSS-API level, which can lead to examples that are 422 less satisfying than may be desired. For example, the sample code in 423 [RFC2744] uses an unspecified send_token_to_peer() routine. Fully 424 correct and general code to frame and transmit tokens requires a 425 substantial amount of error checking and would detract from the core 426 purpose of this document, so we only present the function signature 427 for one example of what such functions might be, and leave some 428 comments in the otherwise-empty function bodies. 430 This sample code is written in C, using the GSS-API C bindings 431 [RFC2744]. It uses the macro GSS_ERROR() to help unpack the various 432 sorts of information which can be stored in the major status field; 433 supplementary information does not necessarily indicate an error. 435 Applications written in other languages will need to exercise care 436 that checks against the major status value are written correctly. 438 This sample code should be compilable as a standalone program, linked 439 against a GSS-API library. In addition to supplying implementations 440 for the token transmission/receipt routines, in order for the program 441 to successfully run when linked against most GSS-API libraries, the 442 initiator will need to specify an explicit target name for the 443 acceptor (which must match the credentials available to the 444 acceptor). A skeleton for how this may be done is provided, using a 445 dummy name. 447 This sample code assumes v2 of the GSS-API. Applications wishing to 448 remain compatible with v1 of the GSS-API may need to perform 449 additional checks in some locations. 451 4.1. GSS Application Sample Code 453 #include 454 #include 455 #include 456 #include 457 #include 458 #include 459 #include 461 /* 462 * This helper is used only on buffers that we allocate ourselves (e.g., 463 * from receive_token()). Buffers allocated by GSS routines must use 464 * gss_release_buffer(). 465 */ 466 static void 467 release_buffer(gss_buffer_t buf) 468 { 469 free(buf->value); 470 buf->value = NULL; 471 buf->length = 0; 472 } 474 /* 475 * Helper to send a token on the specified fd. 476 * 477 * If errors are encountered, this routine must not directly cause 478 * termination of the process (i.e., by errx()), because compliant GSS 479 * applications must release resources allocated by the GSS library 480 * before exiting. (These resources may be non-local to the current 481 * process.) 482 */ 484 static int 485 send_token(int fd, gss_buffer_t token) 486 { 487 /* 488 * Supply token framing and transmission code here. 489 * 490 * It is advisable for the application protocol to specify the 491 * length of the token being transmitted, unless the underlying 492 * transit does so implicitly. 493 * 494 * In addition to checking for error returns from whichever 495 * syscall(s) are used to send data, applications should have 496 * a loop to handle EINTR returns. 497 */ 498 return 1; 499 } 501 /* 502 * Helper to receive a token on the specified fd. 503 * 504 * If errors are encountered, this routine must not directly cause 505 * termination of the process (i.e., by errx()), because compliant GSS 506 * applications must release resources allocated by the GSS library 507 * before exiting. (These resources may be non-local to the current 508 * process.) 509 */ 510 static int 511 receive_token(int fd, gss_buffer_t token) 512 { 513 /* 514 * Supply token framing and transmission code here. 515 * 516 * In addition to checking for error returns from whichever 517 * syscall(s) are used to receive data, applications should have 518 * a loop to handle EINTR returns. 519 * 520 * This routine is assumed to allocate memory for the local copy 521 * of the received token, which must be freed with release_buffer(). 522 */ 523 return 1; 524 } 526 static void 527 do_initiator(int readfd, int writefd, int anon) 528 { 529 int initiator_established = 0, ret; 530 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 531 OM_uint32 major, minor, req_flags, ret_flags; 532 gss_buffer_desc input_token, output_token, name_buf; 533 gss_name_t target_name = GSS_C_NO_NAME; 535 memset(&input_token, 0, sizeof(input_token)); 536 memset(&output_token, 0, sizeof(output_token)); 537 memset(&name_buf, 0, sizeof(name_buf)); 539 /* Applications should set target_name to a real value. */ 540 name_buf.value = "@"; 541 name_buf.length = strlen(name_buf.value); 542 major = gss_import_name(&minor, &name_buf, 543 GSS_C_NT_HOSTBASED_SERVICE, &target_name); 545 /* Mutual authentication will require a token from acceptor to 546 * initiator, and thus a second call to gss_init_sec_context(). */ 547 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG; 548 if (anon) 549 req_flags |= GSS_C_ANON_FLAG; 551 while (!initiator_established) { 552 /* The initiator_cred_handle, mech_type, time_req, 553 * input_chan_bindings, actual_mech_type, and time_rec 554 * parameters are not needed in many cases. We pass 555 * GSS_C_NO_CREDENTIAL, GSS_C_NO_OID, 0, NULL, NULL, and NULL 556 * for them, respectively. */ 557 major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ctx, 558 target_name, GSS_C_NO_OID, 559 req_flags, 0, NULL, &input_token, 560 NULL, &output_token, &ret_flags, 561 NULL); 562 /* This was allocated by receive_token() and is no longer 563 * needed. Free it now to avoid leaks if the loop continues. */ 564 release_buffer(&input_token); 565 if (anon) { 566 /* Initiators which wish to remain anonymous must check 567 * whether their request has been honored before sending 568 * each token. */ 569 if (!(ret_flags & GSS_C_ANON_FLAG)) { 570 warnx("Anonymous requested but not available\n"); 571 goto cleanup; 572 } 573 } 574 /* Always send a token if we are expecting another input token 575 * (GSS_S_CONTINUE_NEEDED is set) or if it is nonempty. */ 576 if ((major & GSS_S_CONTINUE_NEEDED) || 577 output_token.length > 0) { 578 ret = send_token(writefd, &output_token); 579 if (ret != 0) 580 goto cleanup; 581 } 582 /* Check for errors after sending the token so that we will send 583 * error tokens. */ 584 if (GSS_ERROR(major)) { 585 warnx("gss_init_sec_context() error major 0x%x\n", major); 586 goto cleanup; 587 } 588 /* Free the output token's storage; we don't need it anymore. 589 * gss_release_buffer() is safe to call on the output buffer 590 * from gss_int_sec_context(), even if there is no storage 591 * associated with that buffer. */ 592 (void)gss_release_buffer(&minor, &output_token); 594 if (major & GSS_S_CONTINUE_NEEDED) { 595 ret = receive_token(readfd, &input_token); 596 if (ret != 0) 597 goto cleanup; 598 } else if (major == GSS_S_COMPLETE) { 599 initiator_established = 1; 600 } else { 601 /* This situation is forbidden by RFC 2743. Bail out. */ 602 warnx("major not complete or continue but not error\n"); 603 goto cleanup; 604 } 605 } /* while(!initiator_established) */ 606 if ((ret_flags & req_flags) != req_flags) { 607 warnx("Negotiated context does not support requested flags\n"); 608 goto cleanup; 609 } 610 printf("Initiator's context negotiation successful\n"); 611 cleanup: 612 /* We are required to release storage for nonzero-length output 613 * tokens. gss_release_buffer() zeros the length, so we are 614 * will not attempt to release the same buffer twice. */ 615 if (output_token.length > 0) 616 (void)gss_release_buffer(&minor, &output_token); 617 /* Do not request a context deletion token; pass NULL. */ 618 (void)gss_delete_sec_context(&minor, &ctx, NULL); 619 (void)gss_release_name(&minor, &target_name); 620 } 622 static void 623 do_acceptor(int readfd, int writefd) 624 { 625 int acceptor_established = 0, ret; 626 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 627 OM_uint32 major, minor, ret_flags; 628 gss_buffer_desc input_token, output_token; 629 gss_name_t client_name; 631 memset(&input_token, 0, sizeof(input_token)); 632 memset(&output_token, 0, sizeof(output_token)); 634 major = GSS_S_CONTINUE_NEEDED; 636 while(!acceptor_established) { 637 if (major & GSS_S_CONTINUE_NEEDED) { 638 ret = receive_token(readfd, &input_token); 639 if (ret != 0) 640 goto cleanup; 641 } else if (major == GSS_S_COMPLETE) { 642 acceptor_established = 1; 643 break; 644 } else { 645 /* This situation is forbidden by RFC 2743. Bail out. */ 646 warnx("major not complete or continue but not error\n"); 647 goto cleanup; 648 } 649 /* We can use the default behavior or do not need the returned 650 * information for the parameters acceptor_cred_handle, 651 * input_chan_bindings, mech_type, time_rec, and 652 * delegated_cred_handle and pass the values 653 * GSS_C_NO_CREDENTIAL, NULL, NULL, NULL, and NULL, 654 * respectively. In some cases the src_name will not be 655 * needed, but most likely it will be needed for some 656 * authorization or logging functionality. */ 657 major = gss_accept_sec_context(&minor, &ctx, 658 GSS_C_NO_CREDENTIAL, 659 &input_token, NULL, 660 &client_name, NULL, 661 &output_token, &ret_flags, NULL, 662 NULL); 663 /* This was allocated by receive_token() and is no longer 664 * needed. Free it now to avoid leaks if the loop continues. */ 665 release_buffer(&input_token); 666 /* Always send a token if we are expecting another input token 667 * (GSS_S_CONTINUE_NEEDED is set) or if it is nonempty. */ 668 if ((major & GSS_S_CONTINUE_NEEDED) || 669 output_token.length > 0) { 670 ret = send_token(writefd, &output_token); 671 if (ret != 0) 672 goto cleanup; 673 } 674 /* Check for errors after sending the token so that we will send 675 * error tokens. */ 677 if (GSS_ERROR(major)) { 678 warnx("gss_accept_sec_context() error major 0x%x\n", major); 679 goto cleanup; 680 } 681 /* Free the output token's storage; we don't need it anymore. 682 * gss_release_buffer() is safe to call on the output buffer 683 * from gss_accept_sec_context(), even if there is no storage 684 * associated with that buffer. */ 685 (void)gss_release_buffer(&minor, &output_token); 686 } /* while(!acceptor_established) */ 687 if (!(ret_flags & GSS_C_INTEG_FLAG)) { 688 warnx("Negotiated context does not support integrity\n"); 689 goto cleanup; 690 } 691 printf("Acceptor's context negotiation successful\n"); 692 cleanup: 693 release_buffer(&input_token); 694 /* We are required to release storage for nonzero-length output 695 * tokens. gss_release_buffer() zeros the length, so we are 696 * will not attempt to release the same buffer twice. */ 697 if (output_token.length > 0) 698 (void)gss_release_buffer(&minor, &output_token); 699 /* Do not request a context deletion token, pass NULL. */ 700 (void)gss_delete_sec_context(&minor, &ctx, NULL); 701 (void)gss_release_name(&minor, &client_name); 702 } 704 int 705 main(void) 706 { 707 pid_t pid; 708 int fd1 = -1, fd2 = -1; 710 /* Create fds for reading/writing here. */ 711 pid = fork(); 712 if (pid == 0) 713 do_initiator(fd1, fd2, 0); 714 else if (pid > 0) 715 do_acceptor(fd2, fd1); 716 else 717 err(1, "fork() failed\n"); 718 exit(0); 719 } 720 5. Security Considerations 722 This document provides a (reasonably) concise description and example 723 for correct construction of the GSS-API security context negotiation 724 loop. Since everything relating to the construction and use of a GSS 725 security context is security-related, there are security-relevant 726 considerations throughout the document. It is useful to call out a 727 few things in this section, though. 729 The GSS-API uses a request-and-check model for features. An 730 application using the GSS-API requests that certain features 731 (confidentiality protection for messages, or anonymity), but such a 732 request does not require the GSS implementation to provide that 733 feature. The application must check the returned flags to verify 734 whether a requested feature is present; if the feature was non- 735 optional for the application, the application must generate an error. 736 Phrased differently, the GSS-API will not generate an error if it is 737 unable to satisfy the features requested by the application. 739 6. References 741 6.1. Normative References 743 [RFC2743] Linn, J., "Generic Security Service Application Program 744 Interface Version 2, Update 1", RFC 2743, January 2000. 746 [RFC2744] Wray, J., "Generic Security Service API Version 2 : 747 C-bindings", RFC 2744, January 2000. 749 6.2. Informational References 751 [RFC4462] Hutzelman, J., Salowey, J., Galbraith, J., and V. Welch, 752 "Generic Security Service Application Program Interface 753 (GSS-API) Authentication and Key Exchange for the Secure 754 Shell (SSH) Protocol", RFC 4462, May 2006. 756 [RFC4401] Williams, N., "A Pseudo-Random Function (PRF) API 757 Extension for the Generic Security Service Application 758 Program Interface (GSS-API)", RFC 4401, February 2006. 760 [RFC3645] Kwan, S., Garg, P., Gilroy, J., Esibov, L., Westhead, J., 761 and R. Hall, "Generic Security Service Algorithm for 762 Secret Key Transaction Authentication for DNS (GSS-TSIG)", 763 RFC 3645, October 2003. 765 [RFC5801] Josefsson, S. and N. Williams, "Using Generic Security 766 Service Application Program Interface (GSS-API) Mechanisms 767 in Simple Authentication and Security Layer (SASL): The 768 GS2 Mechanism Family", RFC 5801, July 2010. 770 [RFC4752] Melnikov, A., "The Kerberos V5 ("GSSAPI") Simple 771 Authentication and Security Layer (SASL) Mechanism", RFC 772 4752, November 2006. 774 [RFC2203] Eisler, M., Chiu, A., and L. Ling, "RPCSEC_GSS Protocol 775 Specification", RFC 2203, September 1997. 777 Appendix A. Acknowledgements 779 Thanks to Nico Williams and Jeff Hutzleman for prompting me to write 780 this document. 782 Author's Address 784 Benjamin Kaduk 785 MIT Kerberos Consortium 787 Email: kaduk@mit.edu